この記事では、Stripeを利用した決済フォームを実装する際に、リダイレクトをオフにする方法をElements / Checkoutの2つで紹介します。kintoneなどのビジネスアプリケーションに決済機能を埋め込む時のような、現在いるページからの離脱をできるだけ回避したいケースでの決済機能実装を検討されている方はぜひお試しください。
Stripeの決済フローにはリダイレクトが含まれる
Stripeで決済フォームを実装する場合、Checkout / Elements両方でリダイレクトが発生します。これは決済プロバイダによる認証ページへの遷移等を処理するための挙動です。多くの決済手段をサポートし、Stripeが新しく決済手段を追加した場合の対応コストを低く抑えるためにも、できるだけリダイレクトが発生する前提での決済フロー実装を推奨しています。
リダイレクトの設定や、リダイレクト後の動作をカスタマイズする方法については、Stripe Docsにドキュメントが用意されていますので、こちらをご確認ください。
https://docs.stripe.com/payments/checkout/custom-success-page?payment-ui=embedded-form
しかし一方で別のサービス・プラットフォームやフレームワーク上に決済フローを導入する場合、ユーザーが現在いるページの中で決済フローを完結させなければならないケースも存在します。例えばモーダル上での操作や、URL / Cookieなどで状態が管理されていない画面にいる場合は、一度離脱するとユーザーがその画面に戻って来ることができません。そのため、決済手段の種類が制限される可能性はありますが、リダイレクトさせない決済フローの実装方法を知る必要があります。
Stripe Checkoutを利用した埋め込み決済フォームでリダイレクトを停止する
Stripe Checkoutでは、決済フォームをWebページ上に埋め込むことができます。
この場合決済フォームの操作が完了するとreturn_url
で指定したURLへのリダイレクトが実行されます。
const checkoutSession = await stripe.checkout.sessions.create({
ui_mode: 'embedded',
line_items: [
{
// Provide the exact Price ID (for example, pr_1234) of the product you want to sell
price: '{{PRICE_ID}}',
quantity: 1,
},
],
mode: 'payment',
return_url: `${YOUR_DOMAIN}/return.html?session_id={CHECKOUT_SESSION_ID}`,
});
リダイレクトをオフにする場合、return_url
の代わりにredirect_on_completion='never'
を設定します。これによってリダイレクトが必要な決済手段はフォーム上に表示されなくなりますが、決済処理フローの中でリダイレクトが発生することはなくなります。ただしpayment_method_types
を利用して顧客に表示する決済手段を制御している場合は、リダイレクト必須な決済手段を指定するとエラーになりますのでご注意ください。
const checkoutSession = await stripe.checkout.sessions.create({
ui_mode: 'embedded',
line_items: [{
price: '{{PRICE_ID}}',
quantity: 1
}],
mode: 'payment',
+ redirect_on_completion: 'never',
- return_url: `${YOUR_DOMAIN}/return.html?session_id={CHECKOUT_SESSION_ID}`,
})
決済フォームの操作完了後のアクションを設定する
リダイレクトをオフにした場合、決済フォームの操作が完了した場合の処理をフロントエンドのJavaScriptで実装する必要があります。決済フォームの操作が完了した時に実行される処理は、initEmbeddedCheckout
関数の引数にonComplete
として設定します。
以下のサンプルコードでは、決済フォームの操作が完了すると、フォーム自体を非表示にしています。initEmbeddedCheckout
の戻り値で取得できるelements
を利用して操作を行いますので、let
を使ってonComplete
内でも値を利用できるようにしましょう。
<h1>Stripe Checkout Demo</h1>
<form id="payment-form">
<div id="payment-element"></div>
</form>
<script>
let elements
const stripe = Stripe('${STRIPE_PUB_API_KEY}')
// Stripe Elementsを初期化
stripe.initEmbeddedCheckout({
fetchClientSecret: async () => "${checkoutSession.client_secret}",
onComplete: async () => {
if (!elements) return
elements.destroy()
}
}).then(elm => {
elements = elm
elements.mount('#payment-element')
})
</script>
Stripe Elementsを利用した埋め込み決済フォームでリダイレクトを停止する
もう一つの決済フォーム実装方法が、Stripe Elementsです。Checkoutよりも利用できる機能は限定されますが、Appearance APIを利用してフォームのデザインをカスタマイズできるなどのメリットがあります。
Elementsを利用した決済フォームでも、リダイレクトが発生します。フォームをsubmit
した際に、ユーザーはconfirmPayment
関数に設定したconfirmParams[return_url]
のURLへリダイレクトされます。
const { error } = await stripe.confirmPayment({
elements,
confirmParams: {
// Make sure to change this to your payment completion page
return_url: "http://localhost:4242/complete.html",
},
});
このリダイレクトを使わないようにするには、confirmParams[return_url]
の代わりにredirect=if_required
を設定しましょう。これによってリダイレクトが行われない形で決済処理が実行されます。こちらもリダイレクトが必要な決済手段での処理が実行できなくなりますので、切り替える際はサポート予定の決済手段が動作するかを必ず確認しましょう。
const { error } = await stripe.confirmPayment({
elements,
+ redirect: 'if_required'
- confirmParams: {
- return_url: "http://localhost:4242/complete.html",
- },
});
決済処理が完了した後の実装については、confirmPayments
のレスポンスを利用します。レスポンスに含まれるpaymentIntent
オブジェクトとerror
オブジェクトの2つを利用して、決済処理の成否やその後のユーザーに向けた表示の制御などを実装しましょう。
const { error, paymentIntent } = await stripe.confirmPayment({
elements,
redirect: 'if_required'
});
if (error) {
const errorMessage = document.getElementById('error-message');
errorMessage.textContent = result.error.code + ':' + result.error.message;
} else if (paymentIntent) {
// 成功時の処理
}
まとめ
Stripeを利用してさまざまなサービスやプラットフォームに決済機能を追加することができます。しかし構築するサービス・プラットフォームの制約などによって、リダイレクトを行わない形で実装する必要があるケースも存在します。このようなケースでは、Stripe.jsのパラメータを調整することで、リダイレクトの制御を行いましょう。
ただしクレジットカード以外の決済手段をサポートしている場合、決済手段によっては、決済処理のためにリダイレクトが必須であることもあります。このような決済手段はフォームに表示されないか、決済処理がエラーになることがありますので、実装方法を変更する場合には、決済手段ごとの動作について事前にテストを行いましょう。
Stripeを使うことでさまざまな要件やビジネスケースにあわせた実装を、効率的に行えます。ぜひStripe DocsやQiitaのStripeページを参考に、実装方法についてお調べください。
ドキュメント