Stripe Elementsで、カード決済と銀行振込の両方をサポートする決済処理を実装する

クレジットカードを利用した商品の注文やサービス申し込みは、今やオンラインビジネスに欠かせない要素です。
ですが、より多くの顧客に商品・サービスを提供したいと考えた場合、クレジットカードを利用できない顧客やシーンについても考慮する必要があります。

例えば、電車での移動中や混み合った店内、信頼性の低いwi-fiネットワークを一時的に利用している場合などでは、クレジットカードを取り出したりカード情報を送信したりすることをためらうことがあります。
また、未成年者など自分のクレジットカードを持っていない方の存在もビジネスによっては無視することができません。

この記事では、Stripeを利用してカード決済だけでなく、銀行振込での決済も処理する方法を紹介します。

## 銀行振込での決済処理も、PaymentIntentを利用する

StripeでのカードやGoogle Pay / Apple Payなどの処理は、まずサーバー側でPayment Intentを作成します。

```js
    const paymentIntent = await stripe.paymentIntents.create({
      amount: 100,
      currency: 'jpy',
    });
```

そしてフロントエンドで、Payment Intentのclient secretを利用して決済フォームを表示させます。

```js
    const elements = stripe.elements({
      clientSecret: paymentIntentAPIResponse.client_secret,
    });
    const card = elements.create('payment');
    card.mount('#card-element');
```

最後に、フォームのSubmit操作を受けて決済を完了させます。


```js
      const form = document.getElementById('payment-form');
      form.addEventListener('submit', async (e) => {
        e.preventDefault();
        const {error: stripeError} = await stripe.confirmPayment({
          elements,
          confirmParams: {
            return_url: `${window.location.origin}/return.html`,
          }
        });
      });
```

## 銀行振込にも対応した、決済フォームに変更する方法

銀行振込の場合も、同様にPayment Intentを作成して決済処理を行います。

### Step1: 銀行振込をサポートするために、Customerデータを作成する

銀行振込での決済をサポートするには、振込先口座情報を紐づける顧客データが必要です。

そのため、銀行振込を導入する場合、「**Payment Intent作成前に、Customerデータを作成**する」必要があります。

```diff_javascript
+ const customer = await stripe.customers.create()
 const paymentIntent = await stripe.paymentIntents.create({
+   customer: customer.id,
   amount: 100,
   currency: 'jpy',
 });
```

### Step2: 銀行振込に必要な情報を追加する

続いて、「どの国の銀行振込を利用するか」などの情報をPayment Intentに追加します。

```diff_javascript
 const customer = await stripe.customers.create()
 const paymentIntent = await stripe.paymentIntents.create({
   customer: customer.id,
   amount: 100,
   currency: 'jpy',
+   payment_method_types: ['customer_balance', 'card'],
+   payment_method_data: {
+     type: 'customer_balance',
+   },
+   payment_method_options: {
+     customer_balance: {
+       funding_type: 'bank_transfer',
+       bank_transfer: {
+        type: 'jp_bank_transfer',
+       },
+     },
+   },
 });
```

### フロントエンド側の実装は、Payment Elementならば変更不要

Payment Elementを利用して決済フォームを実装している場合、フロントエンド側のコードは変更する必要がありません。

変更内容を反映したPayment IntentのClient Secretを受け取ると、銀行振込も選択できる表示に自動で切り替わります。

![スクリーンショット 2022-09-02 14.38.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2366300/68916750-a251-9c3c-a5d3-400f29d3ec35.png)

また、`stripe.confirmPayment（）`を実行すると、振込先口座情報が記載されたページに自動でリダイレクトします。

![スクリーンショット 2022-06-23 12.35.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2366300/a7fcadb3-39e7-1236-58ba-c8973016ac3a.png)

## Webhookを利用して、振込状況を確認する

顧客が必要な金額を振り込みしたかどうかについては、Stripe Webhookを利用して確認できます。
`payment_intent.succeeded`イベントは、カードなどの決済でも発火します。
そのため、複数の決済方法をサポートしたいシステムでは、このイベントを受けて発送系などのシステムを動かすアーキテクチャにする必要があります。

```js
      if (event.type === 'payment_intent.succeeded') {
          const paymentIntent = event.data.object;
          /**
           * 入金が完了したことをシステムに伝える。
           * - 入金のお礼メール
           * - 発送系のシステムをよびだす
           * - etc...
           **/
      }
```

## 銀行振込をテストする

銀行振込での決済をテストする簡単な方法は、Stripe Dashboardを利用することです。
対象となる顧客の詳細ページを開き、[支払い方法]の[追加]をクリックします。

![UVqinCKx.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2366300/2959cc2c-b7b4-5879-2662-e9e54d0a7490.png)

すると、[現金残高に資金を追加(テスト環境のみ)]が表示されます。これをクリックすると、顧客の現金残高を追加することができます。

![9uZbbaU5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2366300/b6aea603-2c96-8eca-ec8d-4ccfd318e6a7.png)

残高を追加すると、作成済みのPayment Intentや請求書の金額の決済が自動で行われます。
そのため、`payment_intent.succeeded`のテストが行いたい場合は、請求金額と同じか、それより多い額を入金しましょう。

 
## カード決済と銀行振込両方をサポートした決済フォームを作るポイント

### 会員管理機能がある場合、作成したCustomerデータとの紐付けを行おう

カードやコンビニなどの決済では不要でしたが、銀行振込では顧客ごとにStripeにCustomerオブジェクトを作成する必要があります。
振込先の情報は、Customerごとに変わりますので、会員による注文など、繰り返し銀行振込で決済を行うことが想定される場合は、必ずCustomerのIDを正しくPayment Intent作成時の引数に渡すようにしましょう。
もし同じ顧客に複数のCustomerが設定された場合、顧客が「前回の注文で利用した銀行口座」に誤って振り込みを行ってしまう。などの問題が発生する恐れがありますので、ご注意ください。

## おわりに

Stripeを利用することで、銀行振込での決済についてもStripe上で完結できるようになります。
これまでは通帳記入や各銀行サービスで都度入金を確認し、システムにそれを反映させるオペレーションがありました。
しかしStripeを利用することで、入金の確認や残高の過不足のチェックの自動化だけでなく、銀行振込の取引データについてもStripe上で分析できるようになります。