※ これから記載する事項は、私が所属する会社とは一切関係のない事柄です。
今回は「Composable Storefront で Stripe を利用して簡易な決済を実装してみる - 内容編」の続編で実装編としてどのように Composable Storefront に簡易な決済を Stripe で実装したかを紹介します。
実装したフロー
実装したサンプルコード
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
実際に利用している部分はこちらです。
==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 を作成しています。
==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 に保存しています。また画面が再度リロードされた際に保存する部分も作成しています。
==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==
setStripeObj
は React コンテクストを利用したアプリケーション全体的に統一感があると思いますが、今回はわかりやすさを重視してコンポーネントのプロパティとして渡しています。
ポイント 4 - Confirm Stripe payment intent
作成された 上記で作成された Payment Intent を元に認証を行うために注文を確定されるときに呼び出される submitOrder
関数内で stripe.confirmCardPayment を呼び出しています。
==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 の読み込みを許可します。実際に利用している部分はこちらです。
==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 について」をご参照ください。
実際に利用する際の注意
-
PWA Kit の
{Your API key}
の値を Stripe の API Key (公開可能キー) に置き換えてください。 -
サービスのユーザ ID の
{Stripe API Key}
を Stripe の API Key (シークレットキー) に置き換える必要があります。 - PWA Kit の config フォルダに default.js を置いていないのでご注意ください。
- 買い物かご削除・更新時の Stripe Payment Intent の削除・更新はしていません。(価格の更新に関しては Calculate Hook を利用して、削除の場合は
dw.ocapi.shop.basket.beforeDELETE
Hook を利用すればいいかと思います。 )