LoginSignup
0
0

Composable Storefront で Stripe を利用して簡易な決済を実装してみる - 実装編

Last updated at Posted at 2024-01-15

※ これから記載する事項は、私が所属する会社とは一切関係のない事柄です。

今回は「Composable Storefront で Stripe を利用して簡易な決済を実装してみる - 内容編」の続編で実装編としてどのように Composable Storefront に簡易な決済を Stripe で実装したかを紹介します。

実装したフロー

Stripe × Composable (1) (1).jpg

実装したサンプルコード

PWA Kit に実装した内容

今回は PWA Kit の拡張テンプレートを利用しています。拡張のために追加したコードは Github で確認できます。

PWA Kit (Composable Storefront) でポイントとなる実装は下記の点です。

ポイント 1 - React Stripe.js のインストールと利用

下記コマンドでパッケージをインストールします。詳細は「React Stripe.js リファレンス」を参照してください。

npm install --save @stripe/react-stripe-js @stripe/stripe-js

実際に利用している部分はこちらです。

pwa-kit/sample-stripe/overrides/app/pages/checkout/index.jsx
==OMITTED==
const [stripePromise, setStripePromise] = useState(null)
useEffect(() => {
    setStripePromise(
        loadStripe(
            '{Your API key}'
        )
    )
}, [])

==OMITTED==

return (
    <CheckoutProvider>
        <Elements stripe={stripePromise}>
            <Checkout />
        </Elements>
    </CheckoutProvider>
)
==OMITTED==

ポイント 2 - Create Stripe payment method

チェックアウトの確認画面に遷移する際に 呼ばれる onPaymentSubmit 内で stripe.createPaymentMethod を呼んで Stripe の Payment Method を作成しています。

pwa-kit/sample-stripe/overrides/app/pages/checkout/partials/payment.jsx
==OMITTED==
const result = await stripe.createPaymentMethod({
    type: 'card',
    card: elements.getElement(CardElement)
})
if (result.error) {
    showToast({
        title: result.error.message,
        status: 'error'
    })
    return
}
==OMITTED==

ポイント 3 - Add CC payment instrument for basket with Stripe payment method id

上記で作成された Payment Method ID は c_stripePyamentMethodId というプロパティで B2C Commerce の Payment Instrument に追加しています。実際に保存している部分は後に紹介する Hooks 部分です。
API 呼び出し時に Stripe の Payment Intent の情報や保存するか否かの情報が返却されますがその情報は State として stripeObj保存しています。また画面が再度リロードされた際に保存する部分も作成しています。

pwa-kit/sample-stripe/overrides/app/pages/checkout/partials/payment.jsx
==OMITTED==
const paymentMethod = result.paymentMethod
const paymentInstrument = {
    paymentMethodId: 'STRIPE',
    c_stripePyamentMethodId: paymentMethod.id,
    c_willSaved: stripeObj.willSaved,
    paymentCard: {
        maskedNumber: `*********${paymentMethod.card.last4}`,
        cardType: getPaymentInstrumentCardType(paymentMethod.card.brand),
        expirationMonth: parseInt(paymentMethod.card.exp_month),
        expirationYear: parseInt(paymentMethod.card.exp_year)
    }
}
const basketResult = await addPaymentInstrumentToBasket({
    parameters: {basketId: basket?.basketId},
    body: paymentInstrument
})
const instrument = basketResult.paymentInstruments.find(
    (item) => item.paymentMethodId === 'STRIPE'
)
setStripeObj({
    stripeIntentId: basket.c_stripeIntentId,
    stripeClientSecret: basket.c_stripeClientSecret,
    stripePyamentMethodId: instrument.c_stripePyamentMethodId,
    willSaved: instrument.c_willSaved
})
==OMITTED==

setStripeObjReact コンテクストを利用したアプリケーション全体的に統一感があると思いますが、今回はわかりやすさを重視してコンポーネントのプロパティとして渡しています。

ポイント 4 - Confirm Stripe payment intent

作成された 上記で作成された Payment Intent を元に認証を行うために注文を確定されるときに呼び出される submitOrder 関数内で stripe.confirmCardPayment を呼び出しています。

pwa-kit/sample-stripe/overrides/app/pages/checkout/index.jsx
==OMITTED==
const result = await stripe.confirmCardPayment(stripeObj.stripeClientSecret, options)
if (result.error) {
    throw new Error(result.error.message)
}
==OMITTED==

ポイント 5 - CSP の設定

js.stripe.com からの JS の読み込みや iframe の読み込みを許可します。実際に利用している部分はこちらです。

pwa-kit/sample-stripe/overrides/app/ssr.js
==OMITTED==
app.use(
  helmet({
    contentSecurityPolicy: {
      useDefaults: true,
      directives: {
        "img-src": [
          // Default source for product images - replace with your CDN
          "*.commercecloud.salesforce.com",
        ],
        "script-src": [
          // Used by the service worker in /worker/main.js
          "storage.googleapis.com",
          /****** Sample Stripe Added Start ******/
          "js.stripe.com",
          /****** Sample Stripe Added End ******/
        ],
        "connect-src": [
          // Connect to Einstein APIs
          "api.cquotient.com",
        ],
        /****** Sample Stripe Added Start ******/
        "frame-src": ["js.stripe.com"],
        /****** Sample Stripe Added End ******/
      },
    },
  })
);
==OMITTED==

SCAPI Hooks に実装した内容

SCAPI Hooks では addPaymentInstrumentToBasket が呼ばれた際に下記の実装を行なっています。詳細は Github のソースコードをご覧ください。

  • B2C Commerce の顧客と紐づく Stripe の Customer がまだない場合の Customer の作成
  • c_stripePyamentMethodId パラメータを利用した Payment Intent の作成

他にもサンプルとなる Hooks が公開されているので参考にしてみてください。

B2C Commerce の設定

マイグレーションファイルを利用して下記の B2C Commerce の設定を行なっています。

設定 1 - システムオブジェクトへのカスタムフィールドの追加

ソースコード

  • Profile オブジェクトに stripeCustomerId フィールドの追加
  • OrderPaymentInstrument オブジェクトに stripeIntentId , stripeClientSecret , stripePaymentMethodId , willSaved フィールドの追加
  • Basket オブジェクトに stripeIntentId , stripeClientSecret フィールドの追加

設定 2 - 支払い方法とプロセッサー

ソースコード

  • STRIPE という ID を持つ支払い方法を設定しています。

設定 3 - サービス

ソースコード

  • Stripe の REST API を利用するためのサービスを作成しています。

マイグレーションには以前紹介した b2c-tools が便利です。「Salesforce B2C Commerce で利用できる b2c-tools について」をご参照ください。

実際に利用する際の注意

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0