ACH ダイレクトデビットによる支払いを受け付ける
カスタムの決済フォームを構築するか、Stripe Checkout を使用して、ACH ダイレクトデビットによる決済を受け付けます。
Web サイトでの ACH ダイレクトデビットによる決済の受け付けは、以下のように構成されます。
- 決済を追跡するためのオブジェクトを作成する
- Stripe Financial Connections によって有効化される即時確認を使用して、支払い方法の情報を収集する
- 決済を処理するために Stripe に送信する
- 顧客の銀行口座を確認する
注
ACH ダイレクトデビットは通知遅延型の支払い方法であるため、決済後すぐには売上が利用可能になりません。通常、決済金額がお客様のアカウントに入金されるまでに 4 営業日かかります。
Stripe では、Payment Intent (支払いインテント) と呼ばれる決済オブジェクトを使用して、決済が完了するまでの状態のすべてを追跡および処理します。
顧客を作成または取得する推奨サーバー側
ユーザーがビジネスでアカウントを作成する際に、Customer オブジェクトを作成するか、このユーザーに関連付けられた既存の Customer を取得します。この Customer オブジェクトの ID を、顧客を表す社内の内部表記と関連付けることで、保存されている支払い方法の詳細を後で取得して使用することができます。Financial Connections のリピートユーザーの最適化を有効にするには、Customer にメールアドレスを含めます。
PaymentIntent を作成するサーバー側
PaymentIntent (支払いインテント) は、顧客から支払いを回収する意図を表すオブジェクトで、決済プロセスのライフサイクルの各段階を追跡します。
サーバーで PaymentIntent を作成し、回収する金額と通貨 usd を指定します。Payment Intents API を使用した実装がすでにある場合は、PaymentIntent の支払い方法タイプのリストに us_ を追加します。Customer の id を指定します。
将来その支払い方法を再利用する場合には、値を off_ に設定して setup_future_usage パラメーターを指定します。
デフォルトでは、銀行口座の支払い情報の収集では、手動の口座番号入力と少額入金の確認のフォールバックオプションを使用し、Financial Connections で顧客のアカウントを即時確認します。Financial Connections を設定し、ACH の実装を最適化するために追加の口座データにアクセスする方法については、Financial Connections に関するドキュメントをご覧ください。たとえば、Financial Connections を使用して、ACH 決済の開始前にアカウントの残高を確認できます。
注
顧客がアカウントを認証した後で、追加データにアクセスを拡張するには、権限を拡張してアカウントを再度関連付ける必要があります。
client secret を取得する
PaymentIntent には、client secret が含まれています。これは、支払いプロセスを安全に完了するためにクライアント側で使用されます。client secret をクライアント側に渡す際は、いくつかの方法を使用できます。
支払い方法の詳細を収集するクライアント側
顧客が ACH Direct Debitでの支払いをクリックしたときに、Stripe.js を使用してその支払いを Stripe に送信することをお勧めします。Stripe.js は、決済フローを構築するための Stripe の基本的な JavaScript ライブラリです。これにより、実装に関する複雑な処理が自動的に行われ、将来、他の決済手段にも対応できるように実装を簡単に拡張できます。
Stripe.js スクリプトを決済ページに含めるには、このスクリプトを HTML ファイルの head に追加します。
<head> <title>Checkout</title> <script src="https://js.stripe.com/clover/stripe.js"></script> </head>
決済ページで以下の JavaScript を使用して、Stripe.js のインスタンスを作成します。
// Set your publishable key. Remember to change this to your live publishable key in production! // See your keys here: https://dashboard.stripe.com/apikeys const stripe = Stripe();'pk_test_TYooMQauvdEDq54NiTphI7jx'
PaymentIntent オブジェクト全体をクライアントに送信する代わりに、前のステップからの client secret を使用します。これは、Stripe API リクエストを認証する API キーとは異なります。
client secret は支払いを完了できるため、慎重に取り扱う必要があります。記録したり、URL に埋め込んだり、当該の顧客以外に漏洩することがないようにしてください。
stripe.collectBankAccountForPayment を使用して、Financial Connections で銀行口座の詳細を収集し、PaymentMethod を作成して PaymentIntent に関連付けます。ACH ダイレクトデビットの PaymentMethod を作成するには、billing_ パラメーターに口座名義人を含める必要があります。
// Use the form that already exists on the web page. const paymentMethodForm = document.getElementById('payment-method-form'); const confirmationForm = document.getElementById('confirmation-form'); paymentMethodForm.addEventListener('submit', (ev) => { ev.preventDefault(); const accountHolderNameField = document.getElementById('account-holder-name-field'); const emailField = document.getElementById('email-field'); // Calling this method will open the instant verification dialog. stripe.collectBankAccountForPayment({ clientSecret: clientSecret, params: { payment_method_type: 'us_bank_account', payment_method_data: { billing_details: { name: accountHolderNameField.value, email: emailField.value, }, }, }, expand: ['payment_method'], }) .then(({paymentIntent, error}) => { if (error) { console.error(error.message); // PaymentMethod collection failed for some reason. } else if (paymentIntent.status === 'requires_payment_method') { // Customer canceled the hosted verification modal. Present them with other // payment method type options. } else if (paymentIntent.status === 'requires_confirmation') { // We collected an account - possibly instantly verified, but possibly // manually-entered. Display payment method details and mandate text // to the customer and confirm the intent once they accept // the mandate. confirmationForm.show(); } }); });
Financial Connections 認証フローでは、銀行口座の詳細の収集と確認を自動的に処理します。顧客が認証フローを完了すると、PaymentMethod が自動的に PaymentIntent に関連付けられ、Financial Connections アカウントが作成されます。
よくある間違い
手動入力と少額入金によって顧客が関連付けた銀行口座では、残高、所有権、取引などの追加の銀行口座データにアクセスできません。
すべてのデバイスで最適なユーザー体験を提供できるように、ビューポートの meta タグを使用して、ページのビューポートの minimum-scale を 1 に設定します。
<meta name="viewport" content="width=device-width, minimum-scale=1" />
オプションFinancial Connections 銀行口座のデータにアクセスするサーバー側
PaymentIntent の作成時に、追加のデータ権限をリクエストする場合にのみ、Financial Connections データにアクセスできます。
顧客がStripe Financial Connections 認証フローを完了すると、返される us_ PaymentMethod には、Financial Connections アカウントを指す financial_connections_account ID が含まれます。この ID を使用して口座データにアクセスします。
よくある間違い
顧客が手動入力および少額入金によって関連付けた銀行口座には、Payment Method の financial_ ID がありません。
Financial Connections アカウント ID を特定するには、PaymentIntent を取得して payment_ 属性を拡張します。
{ "id": "{{PAYMENT_INTENT_ID}}", "object": "payment_intent", // ... "payment_method": { "id": "{{PAYMENT_METHOD_ID}}", // ... "type": "us_bank_account" "us_bank_account": { "account_holder_type": "individual", "account_type": "checking", "bank_name": "TEST BANK", "financial_connections_account": "{{FINANCIAL_CONNECTIONS_ACCOUNT_ID}}", "fingerprint": "q9qchffggRjlX2tb", "last4": "6789", "routing_number": "110000000" } } // ... }
balances 権限の取得を選択した場合、この段階で残高を確認して、支払いの確定前に十分な資金があることを確認することをお勧めします。
追加の口座データを使用して、Financial Connections で ACH の実装を最適化する方法をご紹介します。
同意書承認を収集し、決済を送信するクライアント側
支払いを開始する前に、顧客に同意書の規約を表示して、顧客から承認を得る必要があります。
Nacha の運営規則に準拠するため、決済を開始する前に、同意書の規約を表示して顧客から承認を得る必要があります。同意書の詳細については、こちらの記事をご覧ください。
顧客が同意書の規約を承認する場合、PaymentIntent を確定する必要があります。顧客がフォームを送信したら、stripe.confirmUsBankAccountPayment を使用して支払いを完了します。
confirmationForm.addEventListener('submit', (ev) => { ev.preventDefault(); stripe.confirmUsBankAccountPayment(clientSecret) .then(({paymentIntent, error}) => { if (error) { console.error(error.message); // The payment failed for some reason. } else if (paymentIntent.status === "requires_payment_method") { // Confirmation failed. Attempt again with a different payment method. } else if (paymentIntent.status === "processing") { // Confirmation succeeded! The account will be debited. // Display a message to customer. } else if (paymentIntent.next_action?.type === "verify_with_microdeposits") { // The account needs to be verified through microdeposits. // Display a message to consumer with next steps (consumer waits for // microdeposits, then enters a statement descriptor code on a page sent to them through email). } }); });
注
stripe.confirmUsBankAccountPayment の完了には数秒かかる場合があります。この間、フォームが再送信されないように無効化し、待機中のインジケーター (スピナーなど) を表示します。エラーが発生した場合は、それを顧客に表示し、フォームを再度有効化し、待機中のインジケーターを非表示にします。
成功した場合、Stripe から以下のいずれかのステータスで PaymentIntent オブジェクトが返されます。
| ステータス | 説明 | 次のステップ |
|---|---|---|
requires_ | 銀行口座の確認を完了するには、追加のアクションが必要です。 | ステップ 6: 少額入金で銀行口座を確認する |
processing | 銀行口座が即座に確認されたか、確認が必要ありません。 | ステップ 7: PaymentIntent の成功を確認する |
PaymentIntent の確定に成功した後、同意書の確認メールと収集した銀行口座情報を顧客に送信する必要があります。Stripe はデフォルトでこれらの処理を行いますが、ご希望に応じてカスタム通知の送信を選択することもできます。
少額入金で銀行口座を確認するクライアント側
すべての顧客が銀行口座を即時に確認できるわけではありません。このステップは、顧客が前のステップで即時確認フローからオプトアウトした場合にのみ適用されます。
このような場合、Stripe は descriptor_ による少額入金を送金し、銀行口座の確認でさらに問題が発生した場合には、amount による少額入金に戻る場合があります。これらの入金が顧客のオンライン明細書に表示されるには 1 ~ 2 営業日かかります。
- 明細書表記コード。SM で始まる一意の 6 桁の
descriptor_を指定して、0.01 USD の 1 件の少額入金を顧客の銀行口座に送金します。顧客は、この文字列を使用して、銀行口座を確認します。code - 金額。Stripe は、
ACCTVERIFYという明細書表記を使用し、一意でない 2 件の少額入金を顧客の銀行口座に送金します。顧客は、この入金額を使用して銀行口座を確認します。
前のステップの stripe.confirmUsBankAccountPayment メソッドの呼び出しの結果として、requires_ 状態の PaymentIntent が返されます。この PaymentIntent には、確認を完了するための有益な情報を含む next_ フィールドが含まれています。
next_action: { type: "verify_with_microdeposits", verify_with_microdeposits: { arrival_date: 1647586800, hosted_verification_url: "https://payments.stripe.com/…", microdeposit_type: "descriptor_code" } }
請求書メールを指定した場合、Stripe はこのメールで入金の到着予定日を顧客に通知します。このメールには、Stripe がオンラインで提供する確認ページへのリンクが含まれ、顧客はそのページで入金額を確認して銀行口座の確認を完了することができます。
警告
確認の失敗は、明細書表記ベースの少額入金の場合は 10 回、金額ベースの少額入金の場合は 3 回までです。この上限を超えると、Stripe は銀行口座を確認できなくなります。また、少額入金の確認は 10 日経過するとタイムアウトになります。この期間内に少額入金を確認できなかった場合、PaymentIntent は新しい支払い方法の詳細を要求する状態に戻ります。少額入金とは何か、どのように使用されるのかを顧客に明確に伝えることで、確認に関する問題を回避できます。
オプション: カスタムのメール通知を送信する
必要に応じて、顧客にカスタムのメール通知を送信することができます。カスタムメールを設定した後は、顧客が確認メールに応答する方法を指定する必要があります。以下の方法のうち、いずれか _1 つ_を指定してください。
Stripe 上のオンライン確認ページを使用します。これを行うには、next_action オブジェクトの
verify_URL を使用し、顧客に確認プロセスを完了するよう指示します。with_ microdeposits[hosted_ verification_ url] Stripe がオンラインで提供する確認ページを使用しない場合、ご自身のサイトにフォームを作成します。顧客はこのフォームを使用して少額入金の金額を伝え、Stripe.js を使用して、銀行口座を確認します。
- 確認のために、少なくとも 6 桁のストリングの
descriptor codeパラメーターを処理するフォームを設定します。 - また、Stripe は、フォームで
amountsパラメーターを処理するように設定することもお勧めします。顧客が利用する一部の銀行で必要になる場合があるためです。
組み込みは、
descriptor_「または」code amountsでのみ渡されます。組み込みでどちらが使用されているかを判断するには、next_オブジェクトのaction verify_の値を確認します。with_ microdeposits[microdeposit_ type] - 確認のために、少なくとも 6 桁のストリングの
stripe.verifyMicrodepositsForPayment(clientSecret, { // Provide either a descriptor_code OR amounts, not both descriptor_code: 'SMT86W', amounts: [32, 45], });
銀行口座の確認に成功すると、Stripe は PaymentIntent オブジェクトを processing の status で返し、payment_intent.processing Webhook イベントを送信します。
確認が失敗する原因はいくつか存在します。失敗は直接的なエラー応答で同期的に発生することも、payment_intent.payment_failed Webhook イベントを通じて非同期で発生することもあります (以下の例を参照してください)。
| エラーコード | 同期または非同期 | メッセージ | ステータスの変化 |
|---|---|---|---|
payment_ | 同期、または Webhook イベントを通じて非同期で発生 | 少額入金に失敗しました。指定した銀行口座、金融機関、支店の番号を確認してください | status は requires_ で、last_ が設定されます。 |
payment_ | 同期 | 指定された金額が銀行口座に送金された金額と一致しません。確認試行の残り回数は {attempts_remaining} 回です。 | 変化なし |
payment_ | 同期、または Webhook イベントを通じて非同期で発生 | 許容された確認の試行回数を超えました | status は requires_ で、last_ が設定されます。 |
payment_ | Webhook イベントを通じて非同期で発生 | 少額入金がタイムアウトになりました。顧客は要求された 10 日の期間内に銀行口座を確認しませんでした。 | status は requires_ で、last_ が設定されます。 |
PaymentIntent の成功を確認するサーバー側
ACH ダイレクトデビットは、通知遅延型の支払い方法です。このため、顧客の口座から引き落としを開始してから、決済の成功または失敗の通知を受けるまでに最大で 4 営業日かかります。
PaymentIntent を作成すると、その初期ステータスは processing となります。決済が成功すると、PaymentIntent のステータスは processing から succeeded に更新されます。
Webhook を使用して決済が成功したことを確認し、顧客に決済完了を通知することをお勧めします。Stripe ダッシュボードでイベントを表示することもできます。
組み込みをテストする
Financial Connections を使用して即時確認を行うシナリオをテストする方法をご紹介します。
サンドボックスで取引メールを送信する
銀行口座の詳細を収集し、同意書を受け付けたら、サンドボックスで同意書の確認メールと少額入金の確認メールを送信します。
ドメインが {domain} でユーザー名が {username} の場合、{username}+test_email@{domain} というメール形式を使用してテスト取引メールを送信してください。
たとえば、ドメインが example.com でユーザー名が info の場合、ACH Direct Debit 決済のテストには info+test_email@example.com という形式を使用します。この形式により、メールが正しくルーティングされます。+test_email サフィックスを含めない場合、メールは送信されません。
よくある間違い
テスト中にこれらのメールをトリガーするには、Stripe の本番環境利用の申請を行う必要があります。
テスト用口座番号
Stripe では、手動入力の銀行口座の組み込みが本番環境に移行する準備が整ったかどうかを確認するため、テスト用の口座番号と対応するトークンをいくつか用意しています。
| 口座番号 | トークン | 金融番号 | 動作 |
|---|---|---|---|
000123456789 | pm_ | 110000000 | 支払いは成功します。 |
000111111113 | pm_ | 110000000 | 口座が解約済みであるため、支払いは失敗します。 |
000000004954 | pm_ | 110000000 | この支払いは、不正利用のリスクが高いため、Radar によってブロックされています。 |
000111111116 | pm_ | 110000000 | 口座が見つからないため、支払いは失敗します。 |
000222222227 | pm_ | 110000000 | 残高不足のため、支払いは失敗します。 |
000333333335 | pm_ | 110000000 | 引き落としがオーソリされていないため、支払いは失敗します。 |
000444444440 | pm_ | 110000000 | 通貨が無効であるため、支払いは失敗します。 |
000666666661 | pm_ | 110000000 | 支払いで少額入金の送金が失敗します。 |
000555555559 | pm_ | 110000000 | 支払いによって不審請求の申請が開始されています。 |
000000000009 | pm_ | 110000000 | 支払いは無期限に処理中のままになります。これは PaymentIntent のキャンセルをテストするのに便利です。 |
000777777771 | pm_ | 110000000 | 支払い額がアカウントの週次支払い額の上限を超えているため、支払いが失敗しました。 |
テスト取引を完了する前に、自動的に支払いに成功または失敗するテスト用のすべての口座を確認する必要があります。確認するには、下記の少額入金のテスト用の金額または明細書表記コードを使用します。
少額入金の金額と明細書表記コードをテストする
さまざまなシナリオを再現するために、これらの少額入金の金額「または」明細書表記コードの値 0.01 を使用します。
| 少額入金の金額 | 明細書表記コードの値 0.01 | シナリオ |
|---|---|---|
32 および 45 | SM11AA | アカウントの確認をシミュレーションします。 |
10 および 11 | SM33CC | 許容された確認回数の超過をシミュレーションします。 |
40 および 41 | SM44DD | 少額入金のタイムアウトをシミュレーションします。 |
売上処理の動作をテストする
テスト取引は即座に売上として処理され、利用可能なテスト残高に追加されます。この動作は、利用可能な残高で取引が売上として処理されるまでに数日かかることがある、本番環境とは異なります。
オプション即時の確認のみサーバー側
デフォルトでは、アメリカの銀行口座による支払いを使用すると、顧客は銀行口座の即時確認、または少額入金を使用できます。必要に応じて、PaymentIntent を作成するときに、verification_method パラメーターを使用して、銀行口座の即時確認のみを要求するように設定することもできます。
これにより、少額入金の確認を処理する必要はなくなりますが、即時確認に失敗した場合は、PaymentIntent のステータスは、顧客の銀行口座の即時確認に失敗したことを示す requires_ となります。
オプション少額入金のみによる確認サーバー側
デフォルトでは、アメリカの銀行口座による支払いを使用すると、顧客は銀行口座の即時確認、または少額入金を使用できます。必要に応じて、PaymentIntent を作成するときに、verification_method パラメーターを使用して、少額入金による確認のみを要求するように設定することもできます。
注意
カスタムの決済フォームを使用している場合、自社の UI を構築して銀行口座の詳細を収集する必要があります。Stripe の少額入金に関するメールを無効にしている場合は、少額入金のコードまたは金額を確認するために顧客用の自社の UI を構築する必要があります。
自社のフォームで顧客の銀行口座を収集し、その詳細を使用して stripe.confirmUsBankAccountPayment を呼び出し、PaymentIntent を完了する必要があります。
var form = document.getElementById('payment-form'); var accountholderName = document.getElementById('accountholder-name'); var email = document.getElementById('email'); var accountNumber = document.getElementById('account-number'); var routingNumber = document.getElementById('routing-number'); var accountHolderType= document.getElementById('account-holder-type'); var submitButton = document.getElementById('submit-button'); var clientSecret = submitButton.dataset.secret; form.addEventListener('submit', function(event) { event.preventDefault(); stripe.confirmUsBankAccountPayment(clientSecret, { payment_method: { billing_details: { name: accountholderName.value, email: email.value, }, us_bank_account: { account_number: accountNumber.value, routing_number: routingNumber.value, account_holder_type: accountHolderType.value, // 'individual' or 'company' }, }, }) .then(({paymentIntent, error}) => { if (error) { // Inform the customer that there was an error. console.log(error.message); } else { // Handle next step based on the intent's status. console.log("PaymentIntent ID: " + paymentIntent.id); console.log("PaymentIntent status: " + paymentIntent.status); } }); });
オプション不審請求の申請を解決するサーバー側
一般的に、顧客は銀行を通じて、個人口座では引き落とし後 60 日以内、事業用口座では 2 営業日以内に ACH Direct Debit 決済に対する不審請求の申し立てを行うことができます。まれなケースとして、この申し立て期限を過ぎてからでも、引き落としに対して不審請求の申し立てを行える場合があります。
顧客が決済に対して不審請求を申請すると、Stripe は charge.dispute.closed Webhook イベントを送信し、PaymentMethod のオーソリは取り消されます。
まれに、PaymentIntent が succeeded に変わった後に、Stripe が銀行から ACH の失敗を受け取ることがあります。この場合、Stripe は以下の reason で不審請求の申請を作成します。
insufficient_funds incorrect_account_ details bank_can't_ process
この場合、Stripe は失敗の手数料を請求します。
この PaymentMethod を再利用する今後の決済では、次のエラーが返されます。
{ "error": { "message": "This PaymentIntent requires a mandate, but no existing mandate was found. Collect mandate acceptance from the customer and try again, providing acceptance data in the mandate_data parameter.", "payment_intent": { ... } "type": "invalid_request_error" } }
このエラーには、requires_ の状態の PaymentIntent が含まれています。決済を続けるには、以下を行う必要があります。
- 今後の決済で不審請求が申請されないように、顧客の不審請求の申請を解決します。
- 顧客からの承認をもう一度確認します。
支払いの承認を確認するには、Stripe.js を使用してオンラインで顧客から同意書の承認を収集するか、Stripe API を使用してオフラインで確認します。
注意
顧客が同じ銀行口座からの複数の支払いに対して不審請求を申請する場合、Stripe は該当の銀行口座をブロックします。解決策については、Stripe サポートにお問い合わせください。
オプション支払いの参照情報
支払い参照番号は銀行で生成され、これを使用して銀行口座の所有者は銀行で資金を確認できます。支払いが成功すると、ダッシュボードと Charge オブジェクト内に支払い参照番号が表示されます。
| 支払いの状態 | 支払いの参照値 |
|---|---|
| 保留中 | 利用不可 |
| 失敗 | 利用不可 |
| 成功 | 利用可能 (091000015001234 など) |
また、charge. Webhook を受け取ったら、payment_ の内容を確認して、payment_reference を見つけます。
次のイベントの例は、成功した ACH 支払いと支払い参照番号を示しています。
{ "id": "{{EVENT_ID}}", "object": "event", // omitted some fields in the example "type": "charge.succeeded", "data": { "object": { "id": "{{PAYMENT_ID}}", "object": "charge", //... "paid": true, "payment_intent": "{{PAYMENT_INTENT_ID}}", "payment_method": "{{PAYMENT_METHOD_ID}}", "payment_method_details": { "type": "us_bank_account", "us_bank_account": { "account_holder_type": "individual", "account_type": "checking", "bank_name": "TEST BANK", "fingerprint": "Ih3foEnRvLXShyfB", "last4": "1000", "payment_reference": "091000015001234", "routing_number": "110000000" } } // ... } } }
destination_ の内容を表示して、返金された ACH 支払いに関連付けられた refund reference を見つけます。
次のイベントの例は、返金参照番号が指定された、成功した ACH 返金のレンダリングを示しています。 返金 の詳細をご覧ください。
{ "id": "{{EVENT_ID}}", "object": "event", "type": "charge.refund.updated", "data": { "object": { "id": "{{REFUND_ID}}", "object": "refund", //... "payment_intent": "{{PAYMENT_INTENT_ID}}", "destination_details": { "type": "us_bank_transfer", "us_bank_transfer": { "reference": "091000015001111", "reference_status": "available" } } // ... } } }
オプション顧客の振替日を設定するサーバー側
予定期日を指定して、Stripe が顧客の銀行口座から引き落としを行う日付を制御できます。予定期日は、現在の日付から 3~15 日以内の日付に指定しなければなりません。
目標期日は、売上が顧客の口座を離れる日を期日指定します。設定日の 3 営業日前までの目標期日を設定された PaymentIntent をキャンセルできます。
次のいずれかの条件を満たす予定期日は、翌営業日まで引き落としが延期されます。
- 週末、祝日、またはその他の非営業日に当たる予定期日。
- 3 営業日以内に到来する予定期日。
このパラメーターは、ベストエフォート方式で機能します。顧客の銀行は、祝日の関係やその他の理由により、異なる日付に引き落としを処理する場合があります。