Stripe Billingで、銀行振込とカード決済の両方をサポートする際に注意すること

Stripe Billingを利用することで、カード決済だけでなく、銀行振込でのサブスクリプションも簡単に提供することができます。
しかし、決済タイミングの違いなどでサービスへの組み込みには注意が必要な点がいくつか存在します。
今回はそれぞれの決済方法での違いと併用する際のポイントを紹介します。

## Webhookで決済方法の違いを吸収する

もっとも大きな違いは、「請求・支払い方法」です。

カード決済の場合、顧客が登録したカードに対して請求を行うため、2回目以降の決済についても提供側・顧客どちらも特別な操作は原則不要です。
しかし銀行振込の場合、毎回顧客が必要金額を指定口座に振り込む必要があります。
そのため、サービスの提供開始タイミングを「決済が完了した後」とする場合には、以下のようなWebhookを用意して、決済が完了しているか否かを処理する必要があります。

```js
      if (event.type === 'customer.subscription.updated') {
          const subscription = event.data.object;
          if (subscription.status === "active") {
            /**
             * サブスクリプションを開始することを、システムに伝える。
             **/
          } else if (subscription.status === "past_due") {
            /**
             * 支払いが完了していないことを、システムに伝える。
             **/
          }
      }
```

## PaymentElementを利用する場合は、SetupIntentを活用する

PaymentElementを利用することで、デザインのカスタマイズ性の高い決済フォームを簡単に手に入れることができます。
ただし、PaymentElementを利用するには、前もってPaymentIntentやSubscriptionを作成しておく必要があります。

```js
        const subscription = await stripe.subscriptions.create({
          customer: 'cus_xxxx',
          items: [{
            price: 'price_xxxx',
          }],
          payment_behavior: 'default_incomplete',
          expand: ['latest_invoice.payment_intent'],
        });
        return {
            customerId,
            subscriptionId: subscription.id,
            clientSecret: subscription.latest_invoice.payment_intent.client_secret,
        }
```

ただし、銀行振り込みではPaymentElementを利用する必要はないことや、カード決済時と引数が異なるなど、作成したSubscriptionをそのまま銀行振込での決済に利用するのは一手間かかります。

### カード・銀行振込両方をサポートする場合、SetupIntentで事前にカード決済情報を入力させよう
お勧めしたい方法は、サブスクリプション作成時にカードを登録するのではなく、その前のステップで決済情報を指定させることです。
PaymentElementはSetupIntentを利用したカード情報の登録にも利用できます。
そこで、SetupIntentを利用して前もってカード情報を登録する動線を作ります。

```js
    const setupIntent = await stripe.setupIntent.create({
      customer: 'cus_xxxx',
    });
    return {
      customerId,
      clientSecret: setupIntent.client_secret,
    }
```

その後、決済方法を指定する画面を用意し、決済方法を選択したタイミングでSubscriptionを作成するように実装します。
TypeScriptの場合、`Stripe.SubscriptionCreateParams`を対象の型に設定すると良いでしょう。


```js
      const subscriptionCreateParams = {
        customer: customerId,
        items: [{
          price: 'price_xxxxx',
        }],
        collection_method: 'charge_automatically'
      };
      if (paymentMethod === 'bank_transfer') {
        subscriptionCreateParams.collection_method = 'send_invoice';
        subscriptionCreateParams.days_until_due = 30;
        subscriptionCreateParams.payment_settings = {
          payment_method_types: ['customer_balance'],
        }
      }
      const subscription = await stripe.subscriptions.create(subscriptionCreateParams);
```

## テストクロックを使って、両決済を事前にシミュレートしよう

![kRxiOz5B.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2366300/53a18d49-1c9a-2ca3-ac8c-f6954fcb202c.png)

Stripeには、サブスクリプションの時間経過をシミュレートするためのテストクロック機能があります。テストクロックを利用することで、「残高が不足した状態で更新日を迎えた時の挙動」や「新しいサブスクリプションの、初回入金が期日より遅れて行われた場合の挙動」など、複雑なケースのテストも簡単に行うことができます。

URL: https://dashboard.stripe.com/test/test-clocks

この機能を利用して、開発時にカード決済・銀行振込どちらの決済も問題なく動作しているかを確認しましょう。

## おわりに

カード決済と銀行振込両方をStripe Billingでサポートする場合に注意したい点や利用できる機能について紹介しました。
この他にも実際に運用されている方に質問してみたい、プレゼンテーションを聞いてみたいなどがありましたら、Stripeユーザーが運営しているコミュニティ「JP_Stripes」にぜひご参加ください。

https://www.facebook.com/groups/jpstripes/