0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Stripe / JP_StripesAdvent Calendar 2024

Day 17

Stripe Elements (PaymentElement / Checkout)でリダイレクトをオフにする方法

Posted at

この記事では、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ページ上に埋め込むことができます。

スクリーンショット 2024-12-12 16.29.46.png

この場合決済フォームの操作が完了すると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 DocsQiitaのStripeページを参考に、実装方法についてお調べください。

ドキュメント

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

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?