# Save details for future payments with ACH Direct Debit Learn how to save payment method details for future ACH Direct Debit payments. # Checkout > This is a Checkout for when payment-ui is checkout. View the full page at https://docs.stripe.com/payments/ach-direct-debit/set-up-payment?payment-ui=checkout. You can use Checkout in [setup mode](https://docs.stripe.com/api/checkout/sessions/object.md#checkout_session_object-mode) to collect payment method details in advance, with the final amount or payment date determined later. This is useful for: - Saving payment methods to a wallet to streamline future purchases - Collecting surcharges after fulfilling a service - Starting a free trial for a *subscription* (A Subscription represents the product details associated with the plan that your customer subscribes to. Allows you to charge the customer on a recurring basis) > ACH Direct Debit is a [delayed notification](https://docs.stripe.com/payments/payment-methods.md#payment-notification) payment method, which means that funds aren’t immediately available after payment. A payment typically takes 4 business days to arrive in your account. ## Before you begin This guide shows you how to extend the foundational [set up future payments](https://docs.stripe.com/payments/save-and-reuse.md?platform=web&ui=stripe-hosted) Checkout integration to add support for ACH Direct Debit payments. ## Create or retrieve a customer [Recommended] [Server-side] > #### Use the Accounts v2 API to represent customers > > The Accounts v2 API is GA for Connect users, and in public preview for other Stripe users. All Stripe users can enable Accounts v2 [in their Dashboard](https://dashboard.stripe.com/settings/connect/platform-setup). However, when making calls to the Accounts v2 API, preview users need to [specify a preview version](https://docs.stripe.com/api-v2-overview.md#sdk-and-api-versioning). > > For most use cases, we recommend [modeling your customers as customer-configured Account objects](https://docs.stripe.com/connect/use-accounts-as-customers.md) instead of using [Customer](https://docs.stripe.com/api/customers.md) objects. #### Accounts v2 Create a customer-configured [Account](https://docs.stripe.com/api/v2/core/accounts/object.md#v2_account_object-configuration-customer) object when your user creates an account with your business, or retrieve an existing `Account` associated with this user. Associating the ID of the `Account` object with your own internal representation of a customer enables you to retrieve and use the stored payment method details later. Include an email address on the `Account` to enable Financial Connections’ [return user optimization](https://docs.stripe.com/financial-connections/fundamentals.md#return-user-optimization). ```curl curl -X POST https://api.stripe.com/v2/core/accounts \ -H "Authorization: Bearer <>" \ -H "Stripe-Version: 2026-03-25.preview" \ --json '{ "contact_email": "{{CUSTOMER_EMAIL}}" }' ``` #### Customers v1 Create a *Customer* (Customer objects represent customers of your business. They let you reuse payment methods and give you the ability to track multiple payments) object when your user creates an account with your business, or retrieve an existing `Customer` associated with this user. Associating the ID of the `Customer` object with your own internal representation of a customer enables you to retrieve and use the stored payment method details later. Include an email address on the `Customer` to enable Financial Connections’ [return user optimization](https://docs.stripe.com/financial-connections/fundamentals.md#return-user-optimization). ```curl curl https://api.stripe.com/v1/customers \ -u "<>:" \ -d email={{CUSTOMER_EMAIL}} ``` ## Enable ACH Direct Debit as a payment method 创建新的 [Checkout Session](https://docs.stripe.com/api/checkout/sessions.md) 时,您需要: 1. Add `us_bank_account` to the list of `payment_method_types`. 1. Set the `permissions` parameter to include `payment_method`. #### Stripe 托管页面 ```curl curl https://api.stripe.com/v1/checkout/sessions \ -u "<>:" \ -d "customer={{CUSTOMER_ID}}" \ -d mode=setup \ -d "payment_method_options[us_bank_account][financial_connections][permissions][]=payment_method" \ -d "payment_method_types[]=card" \ -d "payment_method_types[]=us_bank_account" \ --data-urlencode "success_url=https://example.com/success" ``` #### 嵌入式表单 ```curl curl https://api.stripe.com/v1/checkout/sessions \ -u "<>:" \ -d "customer={{CUSTOMER_ID}}" \ -d mode=setup \ -d "payment_method_options[us_bank_account][financial_connections][permissions][]=payment_method" \ -d "payment_method_types[]=card" \ -d "payment_method_types[]=us_bank_account" \ --data-urlencode "return_url=https://example.com/return" \ -d ui_mode=embedded_page ``` For more information on Financial Connections fees, see [pricing details](https://stripe.com/financial-connections#pricing). By default, collecting bank account payment information uses [Financial Connections](https://docs.stripe.com/financial-connections.md) to instantly verify your customer’s account, with a fallback option of manual account number entry and microdeposit verification. See the [Financial Connections docs](https://docs.stripe.com/financial-connections/ach-direct-debit-payments.md) to learn how to configure Financial Connections and access additional account data to optimize your ACH integration. For example, you can use Financial Connections to check an account’s balance before initiating the ACH payment. > To expand access to additional data after a customer authenticates their account, they must re-link their account with expanded permissions. During the Checkout session, the customer sees a dialog that gives them the option to use instant verification or provide bank account details for microdeposit verification. If the customer opts for microdeposit verification, Stripe automatically sends two small deposits to the provided bank account. These deposits can take 1-2 business days to appear on the customer’s online bank statement. When the deposits arrive, the customer receives an email with a link to confirm these amounts and verify the bank account with Stripe. After verification completes, the payment begins processing. ## 测试您的集成 了解如何使用 [Financial Connections](https://docs.stripe.com/financial-connections/testing.md#web-how-to-use-test-accounts) 进行即时验证来测试各种场景。 ### 在沙盒中发送交易电子邮件 在您收集了银行账户详情并接受授权后,在*沙盒* (A sandbox is an isolated test environment that allows you to test Stripe functionality in your account without affecting your live integration. Use sandboxes to safely experiment with new features and changes)中发送授权确认和微存款验证电子邮件。 如果您的域名是 **{domain}**,并且您的用户名是 **{username}**,请使用以下邮件格式发送测试交易邮件: **{username}+test\_email@{domain}**。 例如,如果您的域名是 **example.com**,用户名是 **info**,则使用格式 **info+test\_email@example.com** 来测试 ACH 直接借记支付。这种格式确保电子邮件路由正确。如果您不包含 **+test\_email** 后缀,我们将不发送电子邮件。 > 您需要[激活您的 Stripe 账户](https://docs.stripe.com/get-started/account/activate.md)后才能在测试时触发这些邮件。 ### 测试账号 Stripe 提供了几个测试账号和相应的令牌,您可以用它们来确保您的手动输入银行账户的集成已经可以投入生产。 | 账号 | 令牌 | 路径号码 | 行为 | | -------------- | -------------------------------------- | ----------- | ------------------------------------------------------------------------------------------------- | | `000123456789` | `pm_usBankAccount_success` | `110000000` | 付款成功。 | | `000111111113` | `pm_usBankAccount_accountClosed` | `110000000` | 付款因账户已关闭失败。 | | `000000004954` | `pm_usBankAccount_riskLevelHighest` | `110000000` | 由于[高欺诈风险](https://docs.stripe.com/radar/risk-evaluation.md#high-risk),该支付被 Radar 阻止了。 | | `000111111116` | `pm_usBankAccount_noAccount` | `110000000` | 付款因查无账户失败。 | | `000222222227` | `pm_usBankAccount_insufficientFunds` | `110000000` | 付款因资金不足失败。 | | `000333333335` | `pm_usBankAccount_debitNotAuthorized` | `110000000` | 付款因扣款未获授权失败。 | | `000444444440` | `pm_usBankAccount_invalidCurrency` | `110000000` | 付款因货币无效失败。 | | `000666666661` | `pm_usBankAccount_failMicrodeposits` | `110000000` | 付款时未能发送微额存款。 | | `000555555559` | `pm_usBankAccount_dispute` | `110000000` | 这笔付款触发了争议。 | | `000000000009` | `pm_usBankAccount_processing` | `110000000` | 支付会无限期地保持处理中。这对于测试 [PaymentIntent 取消](https://docs.stripe.com/api/payment_intents/cancel.md) 很有用。 | | `000777777771` | `pm_usBankAccount_weeklyLimitExceeded` | `110000000` | 付款因支付金额导致账户超过每周支付限额失败了。 | | `000888888885` | | `110000000` | 付款失败是因为[令牌化账户号](https://docs.stripe.com/financial-connections/tokenized-account-numbers.md)已停用。 | 在测试交易完成之前,您需要验证所有付款能够自动成功或失败的测试账户。为此,请使用下面测试用的微存款金额或描述符代码。 ### 测试微存款金额和描述符代码 要模拟不同的场景,请使用这些微存款金额_或_ 0.01 此描述符代码值。 | 微存款金额 | 0.01 描述代码的值 | 场景 | | ----------- | ----------- | ---------------- | | `32` 和 `45` | SM11AA | 模拟验证账户。 | | `10` 和 `11` | SM33CC | 模拟次数超过允许的验证尝试次数。 | | `40` 和 `41` | SM44DD | 模拟微存款超时。 | ### 测试结算行为 测试交易会即时结算并添加到您的可用测试余额中。该行为与真实模式不同,真实模式的交易可能需要[数天](https://docs.stripe.com/payments/ach-direct-debit/set-up-payment.md#timing)才能结算到您的可用余额中。 ## 使用支付方式 After completing the Checkout Session, you can [collect](https://docs.stripe.com/payments/checkout/save-and-reuse.md?payment-ui=stripe-hosted#retrieve-checkout-session) the [PaymentMethod](https://docs.stripe.com/api/payment_methods.md) ID. You can use these PaymentMethod IDs to initiate future payments without having to prompt the customer for their bank account a second time. When [creating a PaymentIntent](https://docs.stripe.com/api/payment_intents/create.md), provide the `payment_method` and customer IDs to charge your customer using their saved bank account information. ## Optional: Instant only verification By default, ACH Direct Debit payments allow your customers to use instant bank account verification or microdeposits. You can optionally require instant bank account verification only, using the `payment_method_options[us_bank_account][verification_method]` parameter when you create the Checkout session. #### Accounts v2 ```curl curl https://api.stripe.com/v1/checkout/sessions \ -u "<>:" \ -d mode=setup \ -d "customer_account={{CUSTOMERACCOUNT_ID}}" \ -d "payment_method_types[]=card" \ -d "payment_method_types[]=us_bank_account" \ -d "payment_method_options[us_bank_account][verification_method]=instant" \ -d "payment_method_options[us_bank_account][financial_connections][permissions][]=payment_method" \ -d "payment_method_options[us_bank_account][financial_connections][permissions][]=balances" \ --data-urlencode "success_url=https://example.com/success" ``` #### Customers v1 ```curl curl https://api.stripe.com/v1/checkout/sessions \ -u "<>:" \ -d mode=setup \ -d "customer={{CUSTOMER_ID}}" \ -d "payment_method_types[]=card" \ -d "payment_method_types[]=us_bank_account" \ -d "payment_method_options[us_bank_account][verification_method]=instant" \ -d "payment_method_options[us_bank_account][financial_connections][permissions][]=payment_method" \ -d "payment_method_options[us_bank_account][financial_connections][permissions][]=balances" \ --data-urlencode "success_url=https://example.com/success" ``` ## Optional: Access data on a Financial Connections bank account You can only access Financial Connections data if you request additional [data permissions](https://docs.stripe.com/financial-connections/fundamentals.md#data-permissions) when you create your SetupIntent. After your customer successfully completes the [Stripe Financial Connections authentication flow](https://docs.stripe.com/financial-connections/fundamentals.md#authentication-flow), the `us_bank_account` PaymentMethod returned includes a [financial_connections_account](https://docs.stripe.com/api/payment_methods/object.md#payment_method_object-us_bank_account-financial_connections_account) ID that points to a [Financial Connections Account](https://docs.stripe.com/api/financial_connections/accounts.md). Use this ID to access account data. > Bank accounts that your customers link through manual entry and microdeposits don’t have a `financial_connections_account` ID on the Payment Method. To determine the Financial Connections account ID, retrieve the SetupIntent and expand the `payment_method` attribute: ```curl curl -G https://api.stripe.com/v1/setup_intents/{{SETUPINTENT_ID}} \ -u "<>:" \ -d "expand[]=payment_method" ``` ```json { "id": "{{SETUP_INTENT_ID}}", "object": "setup_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" } } // ... } ``` If you have access to balances data, we recommend [checking balances](https://docs.stripe.com/financial-connections/balances.md#initiate-balance-refresh) before initiating payments with the collected Payment Method. Learn more about using additional account data to optimize your ACH integration with [Financial Connections](https://docs.stripe.com/financial-connections/ach-direct-debit-payments.md#optimize). ## Optional: Updating the default payment method After the `SetupIntent` reaches the `succeeded` state, you can update your customer’s `default_payment_method`. #### Ruby ```ruby # Don't put any keys in code. See https://docs.stripe.com/keys-best-practices. # Find your keys at https://dashboard.stripe.com/apikeys. Stripe.api_key = '<>' if event.type == 'setup_intent.succeeded' setup_intent = event.data.object customer_id = setup_intent['customer'] payment_method_id = setup_intent['payment_method'] # Set the default payment method Stripe::Customer.update( customer_id, { invoice_settings: { default_payment_method: payment_method_id } } ) end ``` # Elements > This is a Elements for when payment-ui is elements. View the full page at https://docs.stripe.com/payments/ach-direct-debit/set-up-payment?payment-ui=elements. You can use the [Setup Intents API](https://docs.stripe.com/payments/setup-intents.md) to collect payment method details in advance, with the final amount or payment date determined later. This is useful for: - Saving payment methods to a wallet to streamline future purchases - Collecting surcharges after fulfilling a service - Starting a free trial for a *subscription* (A Subscription represents the product details associated with the plan that your customer subscribes to. Allows you to charge the customer on a recurring basis) > ACH Direct Debit is a [delayed notification](https://docs.stripe.com/payments/payment-methods.md#payment-notification) payment method, which means that funds aren’t immediately available after payment. A payment typically takes 4 business days to arrive in your account. ## Create or retrieve a customer [Recommended] [Server-side] > #### Use the Accounts v2 API to represent customers > > The Accounts v2 API is GA for Connect users, and in public preview for other Stripe users. All Stripe users can enable Accounts v2 [in their Dashboard](https://dashboard.stripe.com/settings/connect/platform-setup). However, when making calls to the Accounts v2 API, preview users need to [specify a preview version](https://docs.stripe.com/api-v2-overview.md#sdk-and-api-versioning). > > For most use cases, we recommend [modeling your customers as customer-configured Account objects](https://docs.stripe.com/connect/use-accounts-as-customers.md) instead of using [Customer](https://docs.stripe.com/api/customers.md) objects. #### Accounts v2 Create a customer-configured [Account](https://docs.stripe.com/api/v2/core/accounts/object.md#v2_account_object-configuration-customer) object when your user creates an account with your business, or retrieve an existing `Account` associated with this user. Associating the ID of the `Account` object with your own internal representation of a customer enables you to retrieve and use the stored payment method details later. Include an email address on the `Account` to enable Financial Connections’ [return user optimization](https://docs.stripe.com/financial-connections/fundamentals.md#return-user-optimization). ```curl curl -X POST https://api.stripe.com/v2/core/accounts \ -H "Authorization: Bearer <>" \ -H "Stripe-Version: 2026-03-25.preview" \ --json '{ "contact_email": "{{CUSTOMER_EMAIL}}" }' ``` #### Customers v1 Create a *Customer* (Customer objects represent customers of your business. They let you reuse payment methods and give you the ability to track multiple payments) object when your user creates an account with your business, or retrieve an existing `Customer` associated with this user. Associating the ID of the `Customer` object with your own internal representation of a customer enables you to retrieve and use the stored payment method details later. Include an email address on the `Customer` to enable Financial Connections’ [return user optimization](https://docs.stripe.com/financial-connections/fundamentals.md#return-user-optimization). ```curl curl https://api.stripe.com/v1/customers \ -u "<>:" \ -d email={{CUSTOMER_EMAIL}} ``` ## 创建 SetupIntent [服务器端] A [SetupIntent](https://docs.stripe.com/api/setup_intents.md) is an object that represents your intent to set up a customer’s payment method for future payments. The `SetupIntent` tracks the steps of this set-up process. Create a SetupIntent on your server with [payment_method_types](https://docs.stripe.com/api/setup_intents/create.md#create_setup_intent-payment_method_types) set to us_bank_account and specify the Customer’s [id](https://docs.stripe.com/api/customers/object.md#customer_object-id). For more information on Financial Connections fees, see [pricing details](https://stripe.com/financial-connections#pricing). By default, collecting bank account payment information uses [Financial Connections](https://docs.stripe.com/financial-connections.md) to instantly verify your customer’s account, with a fallback option of manual account number entry and microdeposit verification. See the [Financial Connections docs](https://docs.stripe.com/financial-connections/ach-direct-debit-payments.md) to learn how to configure Financial Connections and access additional account data to optimize your ACH integration. For example, you can use Financial Connections to check an account’s balance before initiating the ACH payment. > To expand access to additional data after a customer authenticates their account, they must re-link their account with expanded permissions. ```curl curl https://api.stripe.com/v1/setup_intents \ -u "<>:" \ -d customer={{CUSTOMER_ID}} \ -d "payment_method_types[]=us_bank_account" \ -d "payment_method_options[us_bank_account][financial_connections][permissions][]=payment_method" \ -d "payment_method_options[us_bank_account][financial_connections][permissions][]=balances" ``` ### 检索客户端私钥 SetupIntent 中包含的是一个*客户端私钥* (The client secret is a unique key returned from Stripe as part of a PaymentIntent. This key lets the client access important fields from the PaymentIntent (status, amount, currency) while hiding sensitive ones (metadata, customer)),用于在客户端安全地完成支付流程。有不同的方法可以将客户端私钥传递到客户端。 #### 单页应用 使用浏览器的 `fetch` 功能,从您的服务器上的端点获取客户端私钥。如果您的客户端是单页应用,特别是用现代的前端框架(例如 React)搭建的情况,则该方法最为合适。创建服务于客户端私钥的服务器端点: #### Ruby ```ruby get '/secret' do intent = # ... Create or retrieve the SetupIntent {client_secret: intent.client_secret}.to_json end ``` 然后在客户端用 JavaScript 获取客户端私钥: ```javascript (async () => { const response = await fetch('/secret'); const {client_secret: clientSecret} = await response.json(); // Render the form using the clientSecret })(); ``` #### 服务端呈现 从服务器将客户端私钥传递到客户端。如果在将静态内容发送到浏览器之前,您的应用程序会在服务器上生成静态内容,则此种方法最有效。 在您的结账表单中添加 [client_secret](https://docs.stripe.com/api/setup_intents/object.md#setup_intent_object-client_secret)。在您的服务器代码中,从 SetupIntent 检索客户端密钥: #### Ruby ```erb
``` ```ruby get '/checkout' do @intent = # ... Fetch or create the SetupIntent erb :checkout end ``` ## 收集支付方式详情 [客户端] When a customer clicks to pay with ACH Direct Debit, we recommend you use Stripe.js to submit the payment to Stripe. [Stripe.js](https://docs.stripe.com/payments/elements.md) is our foundational JavaScript library for building payment flows. It will automatically handle integration complexities, and enables you to easily extend your integration to other payment methods in the future. 在您的结账页面包含 Stripe.js 脚本,方法是将它添加到您的 HTML 文件的 `head` 部分。 ```html Checkout ``` 用下面的 JavaScript 在您的结账页面创建一个 Stripe.js 实例。 ```javascript // 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('<>'); ``` Rather than sending the entire SetupIntent object to the client, use its *client secret* (The client secret is a unique key returned from Stripe as part of a PaymentIntent. This key lets the client access important fields from the PaymentIntent (status, amount, currency) while hiding sensitive ones (metadata, customer)) from the previous step. This is different from your API keys that authenticate Stripe API requests. Handle the client secret carefully because it can complete the Payment Method setup process. Don’t log it, embed it in URLs, or expose it to anyone but the customer. Use [stripe.collectBankAccountForSetup](https://docs.stripe.com/js/setup_intents/collect_bank_account_for_setup) to collect bank account details with [Financial Connections](https://docs.stripe.com/financial-connections.md), create a *PaymentMethod* (PaymentMethods represent your customer's payment instruments, used with the Payment Intents or Setup Intents APIs), and attach that PaymentMethod to the SetupIntent. Including the account holder’s name in the `billing_details` parameter is required to create an ACH Direct Debit PaymentMethod. ```javascript // 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.collectBankAccountForSetup({ clientSecret: clientSecret, params: { payment_method_type: 'us_bank_account', payment_method_data: { billing_details: { name: accountHolderNameField.value, email: emailField.value, }, }, }, expand: ['payment_method'], }) .then(({setupIntent, error}) => { if (error) { console.error(error.message); // PaymentMethod collection failed for some reason. } else if (setupIntent.status === 'requires_payment_method') { // Customer canceled the hosted verification modal. Present them with other // payment method type options. } else if (setupIntent.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(); } }); }); ``` The [Financial Connections authentication flow](https://docs.stripe.com/financial-connections/fundamentals.md#authentication-flow) automatically handles bank account details collection and verification. When your customer completes the authentication flow, the *PaymentMethod* (PaymentMethods represent your customer's payment instruments, used with the Payment Intents or Setup Intents APIs) automatically attaches to the SetupIntent, and creates a [Financial Connections Account](https://docs.stripe.com/api/financial_connections/accounts.md). > Bank accounts that your customers link through manual entry and microdeposits won’t have access to additional bank account data like balances, ownership, and transactions. To provide the best user experience on all devices, set the viewport `minimum-scale` for your page to 1 using the viewport `meta` tag. ```html ``` ## Optional: Access data on a Financial Connections bank account [服务器端] You can only access Financial Connections data if you request additional [data permissions](https://docs.stripe.com/financial-connections/fundamentals.md#data-permissions) when you create your SetupIntent. After your customer successfully completes the [Stripe Financial Connections authentication flow](https://docs.stripe.com/financial-connections/fundamentals.md#authentication-flow), the `us_bank_account` PaymentMethod returned includes a [financial_connections_account](https://docs.stripe.com/api/payment_methods/object.md#payment_method_object-us_bank_account-financial_connections_account) ID that points to a [Financial Connections Account](https://docs.stripe.com/api/financial_connections/accounts.md). Use this ID to access account data. > Bank accounts that your customers link through manual entry and microdeposits don’t have a `financial_connections_account` ID on the Payment Method. To determine the Financial Connections account ID, retrieve the SetupIntent and expand the `payment_method` attribute: ```curl curl -G https://api.stripe.com/v1/setup_intents/{{SETUPINTENT_ID}} \ -u "<>:" \ -d "expand[]=payment_method" ``` ```json { "id": "{{SETUP_INTENT_ID}}", "object": "setup_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" } } // ... } ``` If you have access to balances data, we recommend [checking balances](https://docs.stripe.com/financial-connections/balances.md#initiate-balance-refresh) before initiating payments with the collected Payment Method. Learn more about using additional account data to optimize your ACH integration with [Financial Connections](https://docs.stripe.com/financial-connections/ach-direct-debit-payments.md#optimize). ## Collect mandate acknowledgement and submit [客户端] Before you can complete the SetupIntent and save the payment method details for the customer, you must obtain authorization for payment by displaying mandate terms for the customer to accept. To be compliant with Nacha rules, you must obtain authorization from your customer before you can initiate payment by displaying mandate terms for them to accept. For more information on mandates, see [Mandates](https://docs.stripe.com/payments/ach-direct-debit.md#mandates). When the customer accepts the mandate terms, you must confirm the SetupIntent. Use [stripe.confirmUsBankAccountSetup](https://docs.stripe.com/js/setup_intents/confirm_us_bank_account_setup) to complete the payment when the customer submits the form. ```javascript confirmationForm.addEventListener('submit', (ev) => { ev.preventDefault(); stripe.confirmUsBankAccountSetup(clientSecret) .then(({setupIntent, error}) => { if (error) { console.error(error.message); // The payment failed for some reason. } else if (setupIntent.status === "requires_payment_method") { // Confirmation failed. Attempt again with a different payment method. } else if (setupIntent.status === "succeeded") { // Confirmation succeeded! The account is now saved. // Display a message to customer. } else if (setupIntent.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.confirmUsBankAccountSetup](https://docs.stripe.com/js/setup_intents/confirm_us_bank_account_setup) might take several seconds to complete. During that time, disable resubmittals of your form and show a waiting indicator (for example, a spinner). If you receive an error, show it to the customer, re-enable the form, and hide the waiting indicator. If successful, Stripe returns a SetupIntent object, with one of the following possible statuses: | 状态 | 描述 | 后续步骤 | | ----------------- | ------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------- | | `succeeded` | The bank account has been instantly verified or verification wasn’t necessary. | 无需操作 | | `requires_action` | Further action needed to complete bank account verification. | Step 6: [Verifying bank accounts with microdeposits](https://docs.stripe.com/payments/ach-direct-debit/accept-a-payment.md#web-verify-with-microdeposits) | After successfully confirming the SetupIntent, an email confirmation of the mandate and collected bank account details must be sent to your customer. Stripe handles these by default, but you can choose to [send custom notifications](https://docs.stripe.com/payments/ach-direct-debit.md#mandate-and-microdeposit-emails) if you prefer. ## Verify bank account with microdeposits [客户端] Not all customers can verify the bank account instantly. This step only applies if your customer has elected to opt out of the instant verification flow in the previous step. In these cases, Stripe sends a `descriptor_code` microdeposit and might fall back to an `amount` microdeposit if any further issues arise with verifying the bank account. These deposits take 1-2 business days to appear on the customer’s online statement. - **Descriptor code**. Stripe sends a single, 0.01 USD microdeposit to the customer’s bank account with a unique, 6-digit `descriptor_code` that starts with SM. Your customer uses this string to verify their bank account. - **Amount**. Stripe sends two, non-unique microdeposits to the customer’s bank account, with a statement descriptor that reads `ACCTVERIFY`. Your customer uses the deposit amounts to verify their bank account. The result of the [stripe.confirmUsBankAccountSetup](https://docs.stripe.com/js/setup_intents/confirm_us_bank_account_setup) method call in the previous step is a SetupIntent in the `requires_action` state. The SetupIntent contains a `next_action` field that contains some useful information for completing the verification. ```javascript next_action: { type: "verify_with_microdeposits", verify_with_microdeposits: { arrival_date: 1647586800, hosted_verification_url: "https://payments.stripe.com/…", microdeposit_type: "descriptor_code" } } ``` If you supplied a [billing email](https://docs.stripe.com/api/payment_methods/object.md#payment_method_object-billing_details-email), Stripe notifies your customer through this email when the deposits are expected to arrive. The email includes a link to a Stripe-hosted verification page where they can confirm the amounts of the deposits and complete verification. > Verification attempts have a limit of ten failures for descriptor-based microdeposits and three for amount-based ones. If you exceed this limit, we can no longer verify the bank account. In addition, microdeposit verifications have a timeout of 10 days. If you can’t verify microdeposits in that time, the SetupIntent reverts to requiring new payment method details. Clear messaging about what these microdeposits are and how you use them can help your customers avoid verification issues. ### Optional: Send custom email notifications Optionally, you can send [custom email notifications](https://docs.stripe.com/payments/ach-direct-debit.md#mandate-and-microdeposit-emails) to your customer. After you set up custom emails, you need to specify how the customer responds to the verification email. To do so, choose *one* of the following: - Use the Stripe-hosted verification page. To do this, use the `verify_with_microdeposits[hosted_verification_url]` URL in the [next_action](https://docs.stripe.com/api/payment_intents/object.md#payment_intent_object-next_action-verify_with_microdeposits-hosted_verification_url) object to direct your customer to complete the verification process. - If you prefer not to use the Stripe-hosted verification page, create a form on your site. Your customers then use this form to relay microdeposit amounts to you and verify the bank account using [Stripe.js](https://docs.stripe.com/js/payment_intents/verify_microdeposits_for_payment). - At minimum, set up the form to handle the `descriptor code` parameter, which is a 6-digit string for verification purposes. - Stripe also recommends that you set your form to handle the `amounts` parameter, as some banks your customers use might require it. Integrations only pass in the `descriptor_code` *or* `amounts`. To determine which one your integration uses, check the value for `verify_with_microdeposits[microdeposit_type]` in the `next_action` object. ```javascript stripe.verifyMicrodepositsForSetup(clientSecret, { // Provide either a descriptor_code OR amounts, not both descriptor_code: `SMT86W`, amounts: [32, 45], }); ``` When the bank account is successfully verified, Stripe returns the SetupIntent object with a `status` of `succeeded`, and sends a [setup_intent.succeeded](https://docs.stripe.com/api/events/types.md#event_types-setup_intent.succeeded) *webhook* (A webhook is a real-time push notification sent to your application as a JSON payload through HTTPS requests) event. Verification can fail for several reasons. The failure might happen synchronously as a direct error response, or asynchronously through a [setup_intent.setup_failed](https://docs.stripe.com/api/events/types.md#event_types-setup_intent.setup_failed) webhook event (shown in the following examples). #### Synchronous Error ```json { "error": { "code": "payment_method_microdeposit_verification_amounts_mismatch", "message": "The amounts provided do not match the amounts that were sent to the bank account. You have {attempts_remaining} verification attempts remaining.", "type": "invalid_request_error" } } ``` #### Webhook Event ```javascript { "object": { "id": "seti_1234", "object": "setup_intent", "customer": "cus_0246", ... "last_setup_error": { "code": "payment_method_microdeposit_verification_attempts_exceeded", "message": "You have exceeded the number of allowed verification attempts.", }, ... "status": "requires_payment_method" } } ``` | Error Code | Synchronous or Asynchronous | 消息 | Status change | | ------------------------------------------------------------ | ------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------- | | `payment_method_microdeposit_failed` | Synchronously, or asynchronously through webhook event | Microdeposits failed. Please check the account, institution and transit numbers provided | `status` is `requires_payment_method`, and `last_setup_error` is set. | | `payment_method_microdeposit_verification_amounts_mismatch` | Synchronously | The amounts provided don’t match the amounts that were sent to the bank account. You have {attempts_remaining} verification attempts remaining. | Unchanged | | `payment_method_microdeposit_verification_attempts_exceeded` | Synchronously, or asynchronously through webhook event | Exceeded number of allowed verification attempts | `status` is `requires_payment_method`, and `last_setup_error` is set. | | `payment_method_microdeposit_verification_timeout` | Asynchronously through webhook event | Microdeposit timeout. Customer hasn’t verified their bank account within the required 10 day period. | `status` is `requires_payment_method`, and `last_setup_error` is set. | ## 测试您的集成 了解如何使用 [Financial Connections](https://docs.stripe.com/financial-connections/testing.md#web-how-to-use-test-accounts) 进行即时验证来测试各种场景。 ### 在沙盒中发送交易电子邮件 在您收集了银行账户详情并接受授权后,在*沙盒* (A sandbox is an isolated test environment that allows you to test Stripe functionality in your account without affecting your live integration. Use sandboxes to safely experiment with new features and changes)中发送授权确认和微存款验证电子邮件。 如果您的域名是 **{domain}**,并且您的用户名是 **{username}**,请使用以下邮件格式发送测试交易邮件: **{username}+test\_email@{domain}**。 例如,如果您的域名是 **example.com**,用户名是 **info**,则使用格式 **info+test\_email@example.com** 来测试 ACH 直接借记支付。这种格式确保电子邮件路由正确。如果您不包含 **+test\_email** 后缀,我们将不发送电子邮件。 > 您需要[激活您的 Stripe 账户](https://docs.stripe.com/get-started/account/activate.md)后才能在测试时触发这些邮件。 ### 测试账号 Stripe 提供了几个测试账号和相应的令牌,您可以用它们来确保您的手动输入银行账户的集成已经可以投入生产。 | 账号 | 令牌 | 路径号码 | 行为 | | -------------- | -------------------------------------- | ----------- | ------------------------------------------------------------------------------------------------- | | `000123456789` | `pm_usBankAccount_success` | `110000000` | 付款成功。 | | `000111111113` | `pm_usBankAccount_accountClosed` | `110000000` | 付款因账户已关闭失败。 | | `000000004954` | `pm_usBankAccount_riskLevelHighest` | `110000000` | 由于[高欺诈风险](https://docs.stripe.com/radar/risk-evaluation.md#high-risk),该支付被 Radar 阻止了。 | | `000111111116` | `pm_usBankAccount_noAccount` | `110000000` | 付款因查无账户失败。 | | `000222222227` | `pm_usBankAccount_insufficientFunds` | `110000000` | 付款因资金不足失败。 | | `000333333335` | `pm_usBankAccount_debitNotAuthorized` | `110000000` | 付款因扣款未获授权失败。 | | `000444444440` | `pm_usBankAccount_invalidCurrency` | `110000000` | 付款因货币无效失败。 | | `000666666661` | `pm_usBankAccount_failMicrodeposits` | `110000000` | 付款时未能发送微额存款。 | | `000555555559` | `pm_usBankAccount_dispute` | `110000000` | 这笔付款触发了争议。 | | `000000000009` | `pm_usBankAccount_processing` | `110000000` | 支付会无限期地保持处理中。这对于测试 [PaymentIntent 取消](https://docs.stripe.com/api/payment_intents/cancel.md) 很有用。 | | `000777777771` | `pm_usBankAccount_weeklyLimitExceeded` | `110000000` | 付款因支付金额导致账户超过每周支付限额失败了。 | | `000888888885` | | `110000000` | 付款失败是因为[令牌化账户号](https://docs.stripe.com/financial-connections/tokenized-account-numbers.md)已停用。 | 在测试交易完成之前,您需要验证所有付款能够自动成功或失败的测试账户。为此,请使用下面测试用的微存款金额或描述符代码。 ### 测试微存款金额和描述符代码 要模拟不同的场景,请使用这些微存款金额_或_ 0.01 此描述符代码值。 | 微存款金额 | 0.01 描述代码的值 | 场景 | | ----------- | ----------- | ---------------- | | `32` 和 `45` | SM11AA | 模拟验证账户。 | | `10` 和 `11` | SM33CC | 模拟次数超过允许的验证尝试次数。 | | `40` 和 `41` | SM44DD | 模拟微存款超时。 | ### 测试结算行为 测试交易会即时结算并添加到您的可用测试余额中。该行为与真实模式不同,真实模式的交易可能需要[数天](https://docs.stripe.com/payments/ach-direct-debit/set-up-payment.md#timing)才能结算到您的可用余额中。 ## Accepting future payments [服务器端] When the SetupIntent succeeds, it will create a new *PaymentMethod* (PaymentMethods represent your customer's payment instruments, used with the Payment Intents or Setup Intents APIs) attached to a [Customer](https://docs.stripe.com/api/customers.md). These can be used to initiate future payments without having to prompt the customer for their bank account a second time. #### curl ```bash curl https://api.stripe.com/v1/payment_intents \ -u <>: \ -d "amount"=1099 \ -d "currency"="usd" \ -d "customer"="{{CUSTOMER_ID}}" \ -d "payment_method"="{{PAYMENT_METHOD_ID}}" \ -d "payment_method_types[]"="us_bank_account" \ -d "confirm"="true" ``` ## Optional: Instant only verification [服务器端] By default, setting up a US bank account payment method allows your customers to use instant bank account verification or microdeposits. You can optionally require instant bank account verification only, using the [verification_method](https://docs.stripe.com/api/setup_intents/object.md#setup_intent_object-payment_method_options-us_bank_account-verification_method) parameter when you create the SetupIntent. ```curl curl https://api.stripe.com/v1/setup_intents \ -u "<>:" \ -d "customer={{CUSTOMER_ID}}" \ -d "payment_method_types[]=us_bank_account" \ -d "payment_method_options[us_bank_account][verification_method]=instant" \ -d "payment_method_options[us_bank_account][financial_connections][permissions][]=payment_method" \ -d "payment_method_options[us_bank_account][financial_connections][permissions][]=balances" ``` This ensures that you don’t need to handle microdeposit verification. However, if instant verification fails, the SetupIntent’s status is `requires_payment_method`, indicating a failure to instantly verify a bank account for your customer. ## Optional: Microdeposit only verification [服务器端] By default, setting up a US bank account payment method lets your customers use instant bank account verification or microdeposits. You can optionally require microdeposit verification using the [verification_method](https://docs.stripe.com/api/setup_intents/object.md#setup_intent_object-payment_method_options-us_bank_account-verification_method) parameter when you create the SetupIntent. > If using a custom payment form, you must build your own UI to collect bank account details. If you disable Stripe microdeposit emails, you must build your own UI for your customer to confirm the microdeposit code or amount. ```curl curl https://api.stripe.com/v1/setup_intents \ -u "<>:" \ -d "customer={{CUSTOMER_ID}}" \ -d "payment_method_types[]=us_bank_account" \ -d "payment_method_options[us_bank_account][verification_method]=microdeposits" ``` You must then collect your customer’s bank account with your own form and call [stripe.confirmUsBankAccountSetup](https://docs.stripe.com/js/setup_intents/confirm_us_bank_account_setup) with those details to complete the SetupIntent. ```javascript 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.confirmUsBankAccountSetup(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({setupIntent, 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("SetupIntent ID: " + setupIntent.id); console.log("SetupIntent status: " + setupIntent.status); } }); }); ``` ## Optional: Updating the default payment method [服务器端] After the `SetupIntent` reaches the `succeeded` state, you can update your customer’s `default_payment_method`. #### Ruby ```ruby # Don't put any keys in code. See https://docs.stripe.com/keys-best-practices. # Find your keys at https://dashboard.stripe.com/apikeys. Stripe.api_key = '<>' if event.type == 'setup_intent.succeeded' setup_intent = event.data.object customer_id = setup_intent['customer'] payment_method_id = setup_intent['payment_method'] # Set the default payment method Stripe::Customer.update( customer_id, { invoice_settings: { default_payment_method: payment_method_id } } ) end ``` # iOS > This is a iOS for when payment-ui is mobile and platform is ios. View the full page at https://docs.stripe.com/payments/ach-direct-debit/set-up-payment?payment-ui=mobile&platform=ios. You can use the [Setup Intents API](https://docs.stripe.com/payments/setup-intents.md) to collect payment method details in advance, with the final amount or payment date determined later. This is useful for: - Saving payment methods to a wallet to streamline future purchases - Collecting surcharges after fulfilling a service - Starting a free trial for a *subscription* (A Subscription represents the product details associated with the plan that your customer subscribes to. Allows you to charge the customer on a recurring basis) > ACH Direct Debit is a [delayed notification](https://docs.stripe.com/payments/payment-methods.md#payment-notification) payment method, which means that funds aren’t immediately available after payment. A payment typically takes 4 business days to arrive in your account. [iOS SDK](https://github.com/stripe/stripe-ios) 是开源的,[有完整的文档](https://stripe.dev/stripe-ios/index.html),并且与支持 iOS 13 或更高版本操作系统的应用程序兼容。 #### Swift Package Manager 要安装 SDK: 1. 在 Xcode 中,选择**文件** > **添加工具包依赖…**并输入 `https://github.com/stripe/stripe-ios-spm` 作为仓库 URL。 1. 从我们的[发布页面](https://github.com/stripe/stripe-ios/releases)选择最新的版本号。 1. 将 **StripePayments** 和 **StripeFinancialConnections** 产品添加到[您的目标应用程序](https://developer.apple.com/documentation/swift_packages/adding_package_dependencies_to_your_app)。 #### CocoaPods 1. 如果您还没有[CocoaPods](https://guides.cocoapods.org/using/getting-started.html),请安装其最新版本。 1. 如果您目前没有 [Podfile](https://guides.cocoapods.org/syntax/podfile.html),请运行以下命令创建一个: ```bash pod init ``` 1. 将这一行代码添加到您的 `Podfile`: ```podfile pod 'Stripe' pod 'StripeFinancialConnections' ``` 1. 运行以下命令: ```bash pod install ``` 1. 今后,一定记得用 `.xcworkspace` 文件来打开您在 Xcode 中的项目,不要使用 `.xcodeproj` 文件。 1. 将来,要更新到 SDK 的最新版本,运行: ```bash pod update Stripe pod update StripeFinancialConnections ``` #### Carthage 1. 如果您还没有[Carthage](https://github.com/Carthage/Carthage#installing-carthage),请安装其最新版本。 1. 将这一行代码添加到您的 `Cartfile`。 ```cartfile github "stripe/stripe-ios" ``` 1. 按照 [Carthage 安装说明](https://github.com/Carthage/Carthage#if-youre-building-for-ios-tvos-or-watchos)进行。确保嵌入[这里](https://github.com/stripe/stripe-ios#releases)所列的所有必要框架。 1. 除以上链接所需的框架外,一定也要包含框架 **StripeFinancialConnections** 1. 将来,要更新到 SDK 的最新版本,运行以下命令即可: ```bash carthage update stripe-ios --platform ios ``` #### 手动框架 1. 前往我们的 [GitHub 发布页面](https://github.com/stripe/stripe-ios/releases/latest),下载并解压缩 **Stripe.xcframework.zip**。 1. 将 **Stripe.xcframework** 拖拽到您的 Xcode 项目中 **General**(常规)设置的 **Embedded Binaries**(嵌入式二进制文件)部分。一定要选择**需要时复制项目**。 1. 重复 **StripeFinancialConnections.xcframework** 的第 2 步 1. 为[这里](https://github.com/stripe/stripe-ios#releases)所列的所有必要框架重复第 2 步。 1. 将来,要更新到 SDK 的最新版本,重复第 1-3 步。 > 有关最新 SDK 发布及过往版本的详细信息,请查看 GitHub 上的[发布](https://github.com/stripe/stripe-ios/releases)页面。要想在新版本发布时接收通知,请[查看仓库的发布情况](https://help.github.com/en/articles/watching-and-unwatching-releases-for-a-repository#watching-releases-for-a-repository)。 在应用程序启动时使用您的 Stripe [公钥](https://dashboard.stripe.com/test/apikeys) 配置 SDK。这样可使您的应用程序向 Stripe API 发出请求。 #### Swift ```swift import UIKitimportStripeFinancialConnections @main class AppDelegate: UIResponder, UIApplicationDelegate { func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {StripeAPI.defaultPublishableKey = "<>" // do any other necessary launch configuration return true } } ``` > 测试时使用您的[测试密钥](https://docs.stripe.com/keys.md#obtain-api-keys),发布应用时使用[真实模式](https://docs.stripe.com/keys.md#test-live-modes)密钥。 ## Create or retrieve a customer [Recommended] [Server-side] > #### Use the Accounts v2 API to represent customers > > The Accounts v2 API is GA for Connect users, and in public preview for other Stripe users. All Stripe users can enable Accounts v2 [in their Dashboard](https://dashboard.stripe.com/settings/connect/platform-setup). However, when making calls to the Accounts v2 API, preview users need to [specify a preview version](https://docs.stripe.com/api-v2-overview.md#sdk-and-api-versioning). > > For most use cases, we recommend [modeling your customers as customer-configured Account objects](https://docs.stripe.com/connect/use-accounts-as-customers.md) instead of using [Customer](https://docs.stripe.com/api/customers.md) objects. #### Accounts v2 Create a customer-configured [Account](https://docs.stripe.com/api/v2/core/accounts/object.md#v2_account_object-configuration-customer) object when your user creates an account with your business, or retrieve an existing `Account` associated with this user. Associating the ID of the `Account` object with your own internal representation of a customer enables you to retrieve and use the stored payment method details later. Include an email address on the `Account` to enable Financial Connections’ [return user optimization](https://docs.stripe.com/financial-connections/fundamentals.md#return-user-optimization). ```curl curl -X POST https://api.stripe.com/v2/core/accounts \ -H "Authorization: Bearer <>" \ -H "Stripe-Version: 2026-03-25.preview" \ --json '{ "contact_email": "{{CUSTOMER_EMAIL}}" }' ``` #### Customers v1 Create a *Customer* (Customer objects represent customers of your business. They let you reuse payment methods and give you the ability to track multiple payments) object when your user creates an account with your business, or retrieve an existing `Customer` associated with this user. Associating the ID of the `Customer` object with your own internal representation of a customer enables you to retrieve and use the stored payment method details later. Include an email address on the `Customer` to enable Financial Connections’ [return user optimization](https://docs.stripe.com/financial-connections/fundamentals.md#return-user-optimization). ```curl curl https://api.stripe.com/v1/customers \ -u "<>:" \ -d email={{CUSTOMER_EMAIL}} ``` ## 创建 SetupIntent [服务器端] [客户端] A [SetupIntent](https://docs.stripe.com/api/setup_intents.md) is an object that represents your intent to set up a customer’s payment method for future payments. The `SetupIntent` tracks the steps of this set-up process. ### 服务器端 Create a SetupIntent on your server with [payment_method_types](https://docs.stripe.com/api/setup_intents/create.md#create_setup_intent-payment_method_types) set to us_bank_account and specify the Customer’s [id](https://docs.stripe.com/api/customers/object.md#customer_object-id). For more information on Financial Connections fees, see [pricing details](https://stripe.com/financial-connections#pricing). By default, collecting bank account payment information uses [Financial Connections](https://docs.stripe.com/financial-connections.md) to instantly verify your customer’s account, with a fallback option of manual account number entry and microdeposit verification. See the [Financial Connections docs](https://docs.stripe.com/financial-connections/ach-direct-debit-payments.md) to learn how to configure Financial Connections and access additional account data to optimize your ACH integration. For example, you can use Financial Connections to check an account’s balance before initiating the ACH payment. > To expand access to additional data after a customer authenticates their account, they must re-link their account with expanded permissions. ```curl curl https://api.stripe.com/v1/setup_intents \ -u "<>:" \ -d customer={{CUSTOMER_ID}} \ -d "payment_method_types[]=us_bank_account" \ -d "payment_method_options[us_bank_account][financial_connections][permissions][]=payment_method" \ -d "payment_method_options[us_bank_account][financial_connections][permissions][]=balances" ``` ### 客户端 Included in the returned SetupIntent is a *client secret* (The client secret is a unique key returned from Stripe as part of a PaymentIntent. This key lets the client access important fields from the PaymentIntent (status, amount, currency) while hiding sensitive ones (metadata, customer)), which the client side uses to securely complete the setup instead of passing the entire SetupIntent object. There are different approaches that you can use to pass the client secret to the client side. #### Swift ```swift import UIKit import StripePayments class CheckoutViewController: UIViewController { var setupIntentClientSecret: String? func startCheckout() { // Request a SetupIntent from your server and store its client secret } }} ``` ## 设置返回页面 [客户端] 客户可能会离开您的应用来验证(例如,去 Safari 或他们的网银应用)。若允许他们在验证后自动返回到您的应用,[配置一个自定义页面内跳转协议 (URL Scheme)](https://developer.apple.com/documentation/xcode/defining-a-custom-url-scheme-for-your-app),并设置您的应用程序代理将 URL 转发到 SDK。Stripe 不支持[通用链接](https://developer.apple.com/documentation/xcode/allowing-apps-and-websites-to-link-to-your-content)。 > Stripe 可能会在提供的返回页面 中附加额外的参数。确保您的代码不会拒绝带有额外参数的返回页面。 #### SceneDelegate #### Swift ```swift // This method handles opening custom URL schemes (for example, "your-app://stripe-redirect") func scene(_ scene: UIScene, openURLContexts URLContexts: Set) { guard let url = URLContexts.first?.url else { return } let stripeHandled = StripeAPI.handleURLCallback(with: url) if (!stripeHandled) { // This was not a Stripe url – handle the URL normally as you would } } ``` #### AppDelegate #### Swift ```swift // This method handles opening custom URL schemes (for example, "your-app://stripe-redirect") func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey: Any] = [:]) -> Bool { let stripeHandled = StripeAPI.handleURLCallback(with: url) if (stripeHandled) { return true } else { // This was not a Stripe url – handle the URL normally as you would } return false } ``` #### SwiftUI #### Swift ```swift @main struct MyApp: App { var body: some Scene { WindowGroup { Text("Hello, world!").onOpenURL { incomingURL in let stripeHandled = StripeAPI.handleURLCallback(with: incomingURL) if (!stripeHandled) { // This was not a Stripe url – handle the URL normally as you would } } } } } ``` ## 收集支付方式详情 [客户端] ACH Direct Debit requires a customer name and (optional) email for the setupIntent to succeed. In your app, collect the required billing details from the customer: - Their full name (first and last) - Their email address Use the class function `collectUSBankAccountParams` in `STPCollectBankAccountParams` to create your parameters required to call `collectBankAccountForSetup`. Create an instance of `BankAccountCollector` to call `collectBankAccountForSetup` to collect bank account details, create a *PaymentMethod* (PaymentMethods represent your customer's payment instruments, used with the Payment Intents or Setup Intents APIs), and attach that PaymentMethod to the SetupIntent. Including the account holder’s name in the `billing_details` parameter is required to create an ACH Direct Debit PaymentMethod. #### Swift ```swift // Build params let collectParams = STPCollectBankAccountParams.collectUSBankAccountParams(with: name, email: email) // Calling this method will display a modal for collecting bank account information let bankAccountCollector = STPBankAccountCollector() bankAccountCollector.collectBankAccountForSetup(clientSecret: clientSecret, returnURL: "https://your-app-domain.com/stripe-redirect", params: collectParams, from: self) { intent, error in guard let intent = intent else { // handle error return } if case .requiresPaymentMethod = intent.status { // Customer canceled the Financial Connections modal. Present them with other // payment method type options. } else if case .requiresConfirmation = intent.status { // 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. } } ``` This loads a modal UI that handles bank account details collection and verification. When it completes, the *PaymentMethod* (PaymentMethods represent your customer's payment instruments, used with the Payment Intents or Setup Intents APIs) automatically attaches to the SetupIntent. ## Optional: Access data on a Financial Connections bank account [服务器端] You can only access Financial Connections data if you request additional [data permissions](https://docs.stripe.com/financial-connections/fundamentals.md#data-permissions) when you create your SetupIntent. After your customer successfully completes the [Stripe Financial Connections authentication flow](https://docs.stripe.com/financial-connections/fundamentals.md#authentication-flow), the `us_bank_account` PaymentMethod returned includes a [financial_connections_account](https://docs.stripe.com/api/payment_methods/object.md#payment_method_object-us_bank_account-financial_connections_account) ID that points to a [Financial Connections Account](https://docs.stripe.com/api/financial_connections/accounts.md). Use this ID to access account data. > Bank accounts that your customers link through manual entry and microdeposits don’t have a `financial_connections_account` ID on the Payment Method. To determine the Financial Connections account ID, retrieve the SetupIntent and expand the `payment_method` attribute: ```curl curl -G https://api.stripe.com/v1/setup_intents/{{SETUPINTENT_ID}} \ -u "<>:" \ -d "expand[]=payment_method" ``` ```json { "id": "{{SETUP_INTENT_ID}}", "object": "setup_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" } } // ... } ``` If you have access to balances data, we recommend [checking balances](https://docs.stripe.com/financial-connections/balances.md#initiate-balance-refresh) before initiating payments with the collected Payment Method. Learn more about using additional account data to optimize your ACH integration with [Financial Connections](https://docs.stripe.com/financial-connections/ach-direct-debit-payments.md#optimize). ## Collect mandate acknowledgement and submit [客户端] Before you can complete the SetupIntent and save the payment method details for the customer, you must obtain authorization for payment by displaying mandate terms for the customer to accept. To be compliant with *Nacha* (Nacha is the governing body that oversees the ACH network) rules, you must obtain authorization from your customer before you can initiate payment by displaying mandate terms for them to accept. For more information on mandates, see [Mandates](https://docs.stripe.com/payments/ach-direct-debit.md#mandates). When the customer accepts the mandate terms, you must confirm the SetupIntent. Use `confirmSetupIntent` to complete the payment when the customer submits the form. #### Swift ```swift let setupIntentParams = STPSetupIntentConfirmParams(clientSecret: clientSecret, paymentMethodType: .USBankAccount) STPPaymentHandler.shared().confirmSetupIntent( setupIntentParams, with: self ) { (status, intent, error) in switch status { case .failed: // Payment failed case .canceled: // Payment was canceled case .succeeded: // Payment succeeded @unknown default: fatalError() } } ``` > `confirmSetupIntent` might take several seconds to complete. During that time, disable resubmittals of your form and show a waiting indicator (for example, a spinner). If you receive an error, show it to the customer, re-enable the form, and hide the waiting indicator. If successful, Stripe returns a SetupIntent object, with one of the following possible statuses: | 状态 | 描述 | 后续步骤 | | ----------------- | ------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------- | | `succeeded` | The bank account has been instantly verified or verification wasn’t necessary. | 无需操作 | | `requires_action` | Further action needed to complete bank account verification. | Step 6: [Verifying bank accounts with microdeposits](https://docs.stripe.com/payments/ach-direct-debit/accept-a-payment.md#ios-verify-with-microdeposits) | After successfully confirming the SetupIntent, an email confirmation of the mandate and collected bank account details must be sent to your customer. Stripe handles these by default, but you can choose to [send custom notifications](https://docs.stripe.com/payments/ach-direct-debit.md#mandate-and-microdeposit-emails) if you prefer. ## Verify bank account with microdeposits [客户端] Not all customers can verify the bank account instantly. This step only applies if your customer has elected to opt out of the instant verification flow in the previous step. In these cases, Stripe sends a `descriptor_code` microdeposit and might fall back to an `amount` microdeposit if any further issues arise with verifying the bank account. These deposits take 1-2 business days to appear on the customer’s online statement. - **Descriptor code**. Stripe sends a single, 0.01 USD microdeposit to the customer’s bank account with a unique, 6-digit `descriptor_code` that starts with SM. Your customer uses this string to verify their bank account. - **Amount**. Stripe sends two, non-unique microdeposits to the customer’s bank account, with a statement descriptor that reads `ACCTVERIFY`. Your customer uses the deposit amounts to verify their bank account. The result of the `confirmSetupIntent` method call in the previous step is a SetupIntent in the `requires_action` state. The SetupIntent contains a [next_action](https://docs.stripe.com/api/setup_intents/object.md#setup_intent_object-next_action-verify_with_microdeposits) field that contains some useful information for completing the verification. If you supplied a [billing email](https://docs.stripe.com/api/payment_methods/object.md#payment_method_object-billing_details-email), Stripe notifies your customer through this email when the deposits are expected to arrive. The email includes a link to a Stripe-hosted verification page where they can confirm the amounts of the deposits and complete verification. > Verification attempts have a limit of ten failures for descriptor-based microdeposits and three for amount-based ones. If you exceed this limit, we can no longer verify the bank account. In addition, microdeposit verifications have a timeout of 10 days. If you can’t verify microdeposits in that time, the PaymentIntent reverts to requiring new payment method details. Clear messaging about what these microdeposits are and how you use them can help your customers avoid verification issues. ### Optional: Send custom email notifications You can also send [custom email notifications](https://docs.stripe.com/payments/ach-direct-debit.md#mandate-and-microdeposit-emails) to your customer. After you set up custom emails, you need to specify how the customer responds to the verification email. To do so, choose *one* of the following: - Use the Stripe-hosted verification page. To do this, use the `verify_with_microdeposits[hosted_verification_url]` URL in the [next_action](https://docs.stripe.com/api/payment_intents/object.md#payment_intent_object-next_action-verify_with_microdeposits-hosted_verification_url) object to direct your customer to complete the verification process. - If you prefer not to use the Stripe-hosted verification page, create a form in your app. Your customers then use this form to relay microdeposit amounts to you and verify the bank account using the iOS SDK. - At minimum, set up the form to handle the `descriptor code` parameter, which is a 6-digit string for verification purposes. - Stripe also recommends that you set your form to handle the `amounts` parameter, as some banks your customers use might require it. Integrations only pass in the `descriptor_code` *or* `amounts`. To determine which one your integration uses, check the value for `verify_with_microdeposits[microdeposit_type]` in the `next_action` object. #### Swift ```swift // Use if you are using a descriptor code, do not use if you are using amounts STPAPIClient.shared.verifySetupIntentWithMicrodeposits(clientSecret: clientSecret, descriptorCode: descriptorCode, completion: { intent, error in }) // Use if you are using amounts, do not use if you are using descriptor code STPAPIClient.shared.verifySetupIntentWithMicrodeposits(clientSecret: clientSecret, firstAmount: firstAmount, secondAmount: secondAmount, completion: { intent, error in }) ``` When the bank account is successfully verified, Stripe returns the SetupIntent object with a `status` of `succeeded`. Verification can fail for several reasons. The failure happens synchronously as a direct error response. ```json { "error": { "code": "payment_method_microdeposit_verification_amounts_mismatch", "message": "The amounts provided do not match the amounts that were sent to the bank account. You have {attempts_remaining} verification attempts remaining.", "type": "invalid_request_error" } } ``` | Error Code | 消息 | Status change | | ------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------- | | `payment_method_microdeposit_failed` | Microdeposits failed. Please check the account, institution and transit numbers provided. | `status` is `requires_payment_method`, and `last_setup_error` is set. | | `payment_method_microdeposit_verification_amounts_mismatch` | The amounts provided don’t match the amounts that were sent to the bank account. You have {attempts_remaining} verification attempts remaining. | Unchanged | | `payment_method_microdeposit_verification_attempts_exceeded` | Exceeded number of allowed verification attempts | `status` is `requires_payment_method`, and `last_setup_error` is set. | ## 测试您的集成 了解如何使用 [Financial Connections](https://docs.stripe.com/financial-connections/testing.md#web-how-to-use-test-accounts) 进行即时验证来测试各种场景。 ### 在沙盒中发送交易电子邮件 在您收集了银行账户详情并接受授权后,在*沙盒* (A sandbox is an isolated test environment that allows you to test Stripe functionality in your account without affecting your live integration. Use sandboxes to safely experiment with new features and changes)中发送授权确认和微存款验证电子邮件。 如果您的域名是 **{domain}**,并且您的用户名是 **{username}**,请使用以下邮件格式发送测试交易邮件: **{username}+test\_email@{domain}**。 例如,如果您的域名是 **example.com**,用户名是 **info**,则使用格式 **info+test\_email@example.com** 来测试 ACH 直接借记支付。这种格式确保电子邮件路由正确。如果您不包含 **+test\_email** 后缀,我们将不发送电子邮件。 > 您需要[激活您的 Stripe 账户](https://docs.stripe.com/get-started/account/activate.md)后才能在测试时触发这些邮件。 ### 测试账号 Stripe 提供了几个测试账号和相应的令牌,您可以用它们来确保您的手动输入银行账户的集成已经可以投入生产。 | 账号 | 令牌 | 路径号码 | 行为 | | -------------- | -------------------------------------- | ----------- | ------------------------------------------------------------------------------------------------- | | `000123456789` | `pm_usBankAccount_success` | `110000000` | 付款成功。 | | `000111111113` | `pm_usBankAccount_accountClosed` | `110000000` | 付款因账户已关闭失败。 | | `000000004954` | `pm_usBankAccount_riskLevelHighest` | `110000000` | 由于[高欺诈风险](https://docs.stripe.com/radar/risk-evaluation.md#high-risk),该支付被 Radar 阻止了。 | | `000111111116` | `pm_usBankAccount_noAccount` | `110000000` | 付款因查无账户失败。 | | `000222222227` | `pm_usBankAccount_insufficientFunds` | `110000000` | 付款因资金不足失败。 | | `000333333335` | `pm_usBankAccount_debitNotAuthorized` | `110000000` | 付款因扣款未获授权失败。 | | `000444444440` | `pm_usBankAccount_invalidCurrency` | `110000000` | 付款因货币无效失败。 | | `000666666661` | `pm_usBankAccount_failMicrodeposits` | `110000000` | 付款时未能发送微额存款。 | | `000555555559` | `pm_usBankAccount_dispute` | `110000000` | 这笔付款触发了争议。 | | `000000000009` | `pm_usBankAccount_processing` | `110000000` | 支付会无限期地保持处理中。这对于测试 [PaymentIntent 取消](https://docs.stripe.com/api/payment_intents/cancel.md) 很有用。 | | `000777777771` | `pm_usBankAccount_weeklyLimitExceeded` | `110000000` | 付款因支付金额导致账户超过每周支付限额失败了。 | | `000888888885` | | `110000000` | 付款失败是因为[令牌化账户号](https://docs.stripe.com/financial-connections/tokenized-account-numbers.md)已停用。 | 在测试交易完成之前,您需要验证所有付款能够自动成功或失败的测试账户。为此,请使用下面测试用的微存款金额或描述符代码。 ### 测试微存款金额和描述符代码 要模拟不同的场景,请使用这些微存款金额_或_ 0.01 此描述符代码值。 | 微存款金额 | 0.01 描述代码的值 | 场景 | | ----------- | ----------- | ---------------- | | `32` 和 `45` | SM11AA | 模拟验证账户。 | | `10` 和 `11` | SM33CC | 模拟次数超过允许的验证尝试次数。 | | `40` 和 `41` | SM44DD | 模拟微存款超时。 | ### 测试结算行为 测试交易会即时结算并添加到您的可用测试余额中。该行为与真实模式不同,真实模式的交易可能需要[数天](https://docs.stripe.com/payments/ach-direct-debit/set-up-payment.md#timing)才能结算到您的可用余额中。 ## Accepting future payments [服务器端] When the SetupIntent succeeds, it will create a new *PaymentMethod* (PaymentMethods represent your customer's payment instruments, used with the Payment Intents or Setup Intents APIs) attached to a [Customer](https://docs.stripe.com/api/customers.md). These can be used to initiate future payments without having to prompt the customer for their bank account a second time. #### curl ```bash curl https://api.stripe.com/v1/payment_intents \ -u <>: \ -d "amount"=1099 \ -d "currency"="usd" \ -d "customer"="{{CUSTOMER_ID}}" \ -d "payment_method"="{{PAYMENT_METHOD_ID}}" \ -d "payment_method_types[]"="us_bank_account" \ -d "confirm"="true" ``` ## Optional: Instant only verification [服务器端] By default, setting up a US bank account payment method allows your customers to use instant bank account verification or microdeposits. You can optionally require instant bank account verification only, using the [verification_method](https://docs.stripe.com/api/setup_intents/object.md#setup_intent_object-payment_method_options-us_bank_account-verification_method) parameter when you create the SetupIntent. ```curl curl https://api.stripe.com/v1/setup_intents \ -u "<>:" \ -d "customer={{CUSTOMER_ID}}" \ -d "payment_method_types[]=us_bank_account" \ -d "payment_method_options[us_bank_account][verification_method]=instant" \ -d "payment_method_options[us_bank_account][financial_connections][permissions][]=payment_method" \ -d "payment_method_options[us_bank_account][financial_connections][permissions][]=balances" ``` This ensures that you don’t need to handle microdeposit verification. However, if instant verification fails, the SetupIntent’s status is `requires_payment_method`, indicating a failure to instantly verify a bank account for your customer. ## Optional: Microdeposit only verification [服务器端] By default, setting up a US bank account payment method lets your customers use instant bank account verification or microdeposits. You can optionally require microdeposit verification using the [verification_method](https://docs.stripe.com/api/setup_intents/object.md#setup_intent_object-payment_method_options-us_bank_account-verification_method) parameter when you create the SetupIntent. > If using a custom payment form, you must build your own UI to collect bank account details. If you disable Stripe microdeposit emails, you must build your own UI for your customer to confirm the microdeposit code or amount. ```curl curl https://api.stripe.com/v1/setup_intents \ -u "<>:" \ -d "customer={{CUSTOMER_ID}}" \ -d "payment_method_types[]=us_bank_account" \ -d "payment_method_options[us_bank_account][verification_method]=microdeposits" ``` You must then collect your customer’s bank account with your own UI and call [STPPaymentHandler.confirmSetupIntent](https://stripe.dev/stripe-ios/stripepayments/documentation/stripepayments/stppaymenthandler/confirmsetupintent\(_:with:completion:\)) with those details to complete the SetupIntent. #### Swift ```swift // Use your own UI to collect your customer's input let accountholderName = // … let email = // … let accountNumber = // … let routingNumber = // … let accountType = // … let accountHolderType = // … let usBankAccountParams = STPPaymentMethodUSBankAccountParams() usBankAccountParams.accountNumber = accountNumber usBankAccountParams.routingNumber = routingNumber usBankAccountParams.accountType = accountType usBankAccountParams.accountHolderType = accountHolderType let billingDetails = STPPaymentMethodBillingDetails() billingDetails.name = accountholderName billingDetails.email = email let paymentMethodParams = STPPaymentMethodParams(usBankAccount: usBankAccountParams, billingDetails: billingDetails, metadata: nil) let setupIntentParams = STPSetupIntentConfirmParams(clientSecret: clientSecret) setupIntentParams.paymentMethodParams = paymentMethodParams setupIntentParams.returnURL = "https://your-app-domain.com/stripe-redirect" STPPaymentHandler.shared().confirmSetupIntent( setupIntentParams, with: self ) { (status, intent, error) in // Handle the result } ``` ## Optional: Updating the default payment method [服务器端] After the `SetupIntent` reaches the `succeeded` state, you can update your customer’s `default_payment_method`. #### Ruby ```ruby # Don't put any keys in code. See https://docs.stripe.com/keys-best-practices. # Find your keys at https://dashboard.stripe.com/apikeys. Stripe.api_key = '<>' if event.type == 'setup_intent.succeeded' setup_intent = event.data.object customer_id = setup_intent['customer'] payment_method_id = setup_intent['payment_method'] # Set the default payment method Stripe::Customer.update( customer_id, { invoice_settings: { default_payment_method: payment_method_id } } ) end ``` # Android > This is a Android for when payment-ui is mobile and platform is android. View the full page at https://docs.stripe.com/payments/ach-direct-debit/set-up-payment?payment-ui=mobile&platform=android. You can use the [Setup Intents API](https://docs.stripe.com/payments/setup-intents.md) to collect payment method details in advance, with the final amount or payment date determined later. This is useful for: - Saving payment methods to a wallet to streamline future purchases - Collecting surcharges after fulfilling a service - Starting a free trial for a *subscription* (A Subscription represents the product details associated with the plan that your customer subscribes to. Allows you to charge the customer on a recurring basis) > ACH Direct Debit is a [delayed notification](https://docs.stripe.com/payments/payment-methods.md#payment-notification) payment method, which means that funds aren’t immediately available after payment. A payment typically takes 4 business days to arrive in your account. [Stripe Android SDK](https://github.com/stripe/stripe-android) 是开源的,且[有完整的文档](https://stripe.dev/stripe-android/)。 安装 SDK 时,将 `stripe-android` 和 `financial-connections` 添加到您的 [app/build.gradle](https://developer.android.com/studio/build/dependencies) 文件的 `dependencies` 块中: #### Kotlin ```kotlin plugins { id("com.android.application") } android { ... } dependencies { // ... // Stripe Android SDK implementation("com.stripe:stripe-android:23.2.0") // Include the financial connections SDK to support US bank account as a payment method implementation("com.stripe:financial-connections:23.2.0") // Financial Connections SDK implementation("com.stripe:financial-connections:23.2.0") } ``` > 有关最新 SDK 发布及过往版本的详细信息,请查看 GitHub 上的[发布](https://github.com/stripe/stripe-android/releases)页面。要想在新版本发布时接收通知,请[查看仓库的发布情况](https://docs.github.com/en/github/managing-subscriptions-and-notifications-on-github/configuring-notifications#configuring-your-watch-settings-for-an-individual-repository)。 用您的 Stripe [公钥](https://dashboard.stripe.com/apikeys)配置 SDK,以便它可以向 Stripe API 发送请求,例如在您的 `Application` 子类中: #### Kotlin ```kotlin import com.stripe.android.PaymentConfiguration class MyApp : Application() { override fun onCreate() { super.onCreate() PaymentConfiguration.init( applicationContext, "<>" ) } } ``` > 测试时使用您的[测试密钥](https://docs.stripe.com/keys.md#obtain-api-keys),发布应用时使用[真实模式](https://docs.stripe.com/keys.md#test-live-modes)密钥。 ## Create or retrieve a customer [Recommended] [Server-side] > #### Use the Accounts v2 API to represent customers > > The Accounts v2 API is GA for Connect users, and in public preview for other Stripe users. All Stripe users can enable Accounts v2 [in their Dashboard](https://dashboard.stripe.com/settings/connect/platform-setup). However, when making calls to the Accounts v2 API, preview users need to [specify a preview version](https://docs.stripe.com/api-v2-overview.md#sdk-and-api-versioning). > > For most use cases, we recommend [modeling your customers as customer-configured Account objects](https://docs.stripe.com/connect/use-accounts-as-customers.md) instead of using [Customer](https://docs.stripe.com/api/customers.md) objects. #### Accounts v2 Create a customer-configured [Account](https://docs.stripe.com/api/v2/core/accounts/object.md#v2_account_object-configuration-customer) object when your user creates an account with your business, or retrieve an existing `Account` associated with this user. Associating the ID of the `Account` object with your own internal representation of a customer enables you to retrieve and use the stored payment method details later. Include an email address on the `Account` to enable Financial Connections’ [return user optimization](https://docs.stripe.com/financial-connections/fundamentals.md#return-user-optimization). ```curl curl -X POST https://api.stripe.com/v2/core/accounts \ -H "Authorization: Bearer <>" \ -H "Stripe-Version: 2026-03-25.preview" \ --json '{ "contact_email": "{{CUSTOMER_EMAIL}}" }' ``` #### Customers v1 Create a *Customer* (Customer objects represent customers of your business. They let you reuse payment methods and give you the ability to track multiple payments) object when your user creates an account with your business, or retrieve an existing `Customer` associated with this user. Associating the ID of the `Customer` object with your own internal representation of a customer enables you to retrieve and use the stored payment method details later. Include an email address on the `Customer` to enable Financial Connections’ [return user optimization](https://docs.stripe.com/financial-connections/fundamentals.md#return-user-optimization). ```curl curl https://api.stripe.com/v1/customers \ -u "<>:" \ -d email={{CUSTOMER_EMAIL}} ``` ## 创建 SetupIntent [服务器端] [客户端] A [SetupIntent](https://docs.stripe.com/api/setup_intents.md) is an object that represents your intent to set up a customer’s payment method for future payments. The `SetupIntent` tracks the steps of this set-up process. ### 服务器端 Create a SetupIntent on your server with [payment_method_types](https://docs.stripe.com/api/setup_intents/create.md#create_setup_intent-payment_method_types) set to us_bank_account and specify the Customer’s [id](https://docs.stripe.com/api/customers/object.md#customer_object-id). For more information on Financial Connections fees, see [pricing details](https://stripe.com/financial-connections#pricing). By default, collecting bank account payment information uses [Financial Connections](https://docs.stripe.com/financial-connections.md) to instantly verify your customer’s account, with a fallback option of manual account number entry and microdeposit verification. See the [Financial Connections docs](https://docs.stripe.com/financial-connections/ach-direct-debit-payments.md) to learn how to configure Financial Connections and access additional account data to optimize your ACH integration. For example, you can use Financial Connections to check an account’s balance before initiating the ACH payment. > To expand access to additional data after a customer authenticates their account, they must re-link their account with expanded permissions. ```curl curl https://api.stripe.com/v1/setup_intents \ -u "<>:" \ -d customer={{CUSTOMER_ID}} \ -d "payment_method_types[]=us_bank_account" \ -d "payment_method_options[us_bank_account][financial_connections][permissions][]=payment_method" \ -d "payment_method_options[us_bank_account][financial_connections][permissions][]=balances" ``` ### 客户端 Included in the returned SetupIntent is a *client secret* (The client secret is a unique key returned from Stripe as part of a PaymentIntent. This key lets the client access important fields from the PaymentIntent (status, amount, currency) while hiding sensitive ones (metadata, customer)), which is used on the client side to securely complete the setup instead of passing the entire SetupIntent object. There are different approaches that you can use to pass the client secret to the client side. #### Kotlin ```kotlin import androidx.appcompat.app.AppCompatActivity class CheckoutActivity : AppCompatActivity() { lateinit var setupIntentClientSecret: String fun startCheckout() { // Request a SetupIntent from your server and store its client secret } } ``` ## 收集支付方式详情 [客户端] ACH Direct Debit requires a customer name and (optional) email for the payment to succeed. In your app, collect the required billing details from the customer: - Their full name (first and last) - Their email address Use `CollectBankAccountConfiguration.USBankAccount` to create the parameters required to call `presentWithSetupIntent`. Initialize a CollectBankAccountLauncher instance inside onCreate of your checkout Activity, passing a method to handle the result. Then proceed to call `presentWithSetupIntent` to collect bank account details, create a *PaymentMethod* (PaymentMethods represent your customer's payment instruments, used with the Payment Intents or Setup Intents APIs), and attach that PaymentMethod to the SetupIntent. #### Kotlin ```kotlin import androidx.appcompat.app.AppCompatActivity class CheckoutActivity : AppCompatActivity() { private lateinit var setupIntentClientSecret: String private lateinit var collectBankAccountLauncher: CollectBankAccountLauncher override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) // Create collector collectBankAccountLauncher = CollectBankAccountLauncher.create( this ) { result: CollectBankAccountResult -> when (result) { is CollectBankAccountResult.Completed -> { val intent = result.response.intent if (intent.status === StripeIntent.Status.RequiresPaymentMethod) { // Customer canceled the Financial Connections modal. Present them with other // payment method type options. } else if (intent.status === StripeIntent.Status.RequiresConfirmation) { // 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. } } is CollectBankAccountResult.Cancelled -> { // handle cancellation } is CollectBankAccountResult.Failed -> { // handle error print("Error: ${result.error}") } } } } fun startCheckout() { // ... // Build params val collectParams: CollectBankAccountConfiguration = CollectBankAccountConfiguration.USBankAccount( name, email ) // Calling this method will trigger the Financial Connections modal to be displayed collectBankAccountLauncher.presentWithSetupIntent( publishableKey, setupIntentClientSecret, collectParams ) } } ``` This loads a modal UI that handles bank account details collection and verification. When it completes, the *PaymentMethod* (PaymentMethods represent your customer's payment instruments, used with the Payment Intents or Setup Intents APIs) automatically attaches to the SetupIntent. ## Optional: Access data on a Financial Connections bank account [服务器端] You can only access Financial Connections data if you request additional [data permissions](https://docs.stripe.com/financial-connections/fundamentals.md#data-permissions) when you create your SetupIntent. After your customer successfully completes the [Stripe Financial Connections authentication flow](https://docs.stripe.com/financial-connections/fundamentals.md#authentication-flow), the `us_bank_account` PaymentMethod returned includes a [financial_connections_account](https://docs.stripe.com/api/payment_methods/object.md#payment_method_object-us_bank_account-financial_connections_account) ID that points to a [Financial Connections Account](https://docs.stripe.com/api/financial_connections/accounts.md). Use this ID to access account data. > Bank accounts that your customers link through manual entry and microdeposits don’t have a `financial_connections_account` ID on the Payment Method. To determine the Financial Connections account ID, retrieve the SetupIntent and expand the `payment_method` attribute: ```curl curl -G https://api.stripe.com/v1/setup_intents/{{SETUPINTENT_ID}} \ -u "<>:" \ -d "expand[]=payment_method" ``` ```json { "id": "{{SETUP_INTENT_ID}}", "object": "setup_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" } } // ... } ``` If you have access to balances data, we recommend [checking balances](https://docs.stripe.com/financial-connections/balances.md#initiate-balance-refresh) before initiating payments with the collected Payment Method. Learn more about using additional account data to optimize your ACH integration with [Financial Connections](https://docs.stripe.com/financial-connections/ach-direct-debit-payments.md#optimize). ## Collect mandate acknowledgement and submit [客户端] Before you can complete the SetupIntent and save the payment method details for the customer, you must obtain authorization for payment by displaying mandate terms for the customer to accept. To be compliant with *Nacha* (Nacha is the governing body that oversees the ACH network) rules, you must obtain authorization from your customer before you can initiate payment by displaying mandate terms for them to accept. For more information on mandates, see [Mandates](https://docs.stripe.com/payments/ach-direct-debit.md#mandates). When the customer accepts the mandate terms, you must confirm the Setup. Use `confirm` to complete the payment when the customer submits the form. #### Kotlin ```kotlin class CheckoutActivity : AppCompatActivity() { // ... private lateinit var setupIntentClientSecret: String private val paymentLauncher: PaymentLauncher by lazy { val paymentConfiguration = PaymentConfiguration.getInstance(applicationContext) PaymentLauncher.Companion.create( this, paymentConfiguration.publishableKey, paymentConfiguration.stripeAccountId, ::onPaymentResult ) } private fun startCheckout() { // ... val confirmParams = ConfirmSetupIntentParams.create( clientSecret = setupIntentClientSecret, paymentMethodType = PaymentMethod.Type.USBankAccount ) paymentLauncher.confirm(confirmParams) } private fun onPaymentResult(paymentResult: PaymentResult) { when (paymentResult) { is PaymentResult.Completed -> { // show success UI } is PaymentResult.Canceled -> { // handle cancel flow } is PaymentResult.Failed -> { // handle failures // (for example, the customer might need to choose a new payment // method) } } } } ``` > `confirm` might take several seconds to complete. During that time, disable resubmittals of your form and show a waiting indicator (for example, a spinner). If you receive an error, show it to the customer, re-enable the form, and hide the waiting indicator. If successful, Stripe returns a SetupIntent object, with one of the following possible statuses: | 状态 | 描述 | 后续步骤 | | ----------------- | ------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `succeeded` | The bank account has been instantly verified or verification wasn’t necessary. | 无需操作 | | `requires_action` | Further action needed to complete bank account verification. | Step 6: [Verifying bank accounts with microdeposits](https://docs.stripe.com/payments/ach-direct-debit/accept-a-payment.md#android-verify-with-microdeposits) | After successfully confirming the Setup, an email confirmation of the mandate and collected bank account details must be sent to your customer. Stripe handles these by default, but you can choose to [send custom notifications](https://docs.stripe.com/payments/ach-direct-debit.md#mandate-and-microdeposit-emails) if you prefer. ## Verify bank account with microdeposits [客户端] Not all customers can verify the bank account instantly. This step only applies if your customer has elected to opt out of the instant verification flow in the previous step. In these cases, Stripe sends a `descriptor_code` microdeposit and might fall back to an `amount` microdeposit if any further issues arise with verifying the bank account. These deposits take 1-2 business days to appear on the customer’s online statement. - **Descriptor code**. Stripe sends a single, 0.01 USD microdeposit to the customer’s bank account with a unique, 6-digit `descriptor_code` that starts with SM. Your customer uses this string to verify their bank account. - **Amount**. Stripe sends two, non-unique microdeposits to the customer’s bank account, with a statement descriptor that reads `ACCTVERIFY`. Your customer uses the deposit amounts to verify their bank account. The result of the `confirmSetupIntent` method call in the previous step is a SetupIntent in the `requires_action` state. The SetupIntent contains a [next_action](https://docs.stripe.com/api/setup_intents/object.md#setup_intent_object-next_action-verify_with_microdeposits) field that contains some useful information for completing the verification. If you supplied a [billing email](https://docs.stripe.com/api/payment_methods/object.md#payment_method_object-billing_details-email), Stripe notifies your customer through this email when the deposits are expected to arrive. The email includes a link to a Stripe-hosted verification page where they can confirm the amounts of the deposits and complete verification. > Verification attempts have a limit of ten failures for descriptor-based microdeposits and three for amount-based ones. If you exceed this limit, we can no longer verify the bank account. In addition, microdeposit verifications have a timeout of 10 days. If you can’t verify microdeposits in that time, the PaymentIntent reverts to requiring new payment method details. Clear messaging about what these microdeposits are and how you use them can help your customers avoid verification issues. ### Optional: Send custom email notifications You can also send [custom email notifications](https://docs.stripe.com/payments/ach-direct-debit.md#mandate-and-microdeposit-emails) to your customer. After you set up custom emails, you need to specify how the customer responds to the verification email. To do so, choose *one* of the following: - Use the Stripe-hosted verification page. To do this, use the `verify_with_microdeposits[hosted_verification_url]` URL in the [next_action](https://docs.stripe.com/api/payment_intents/object.md#payment_intent_object-next_action-verify_with_microdeposits-hosted_verification_url) object to direct your customer to complete the verification process. - If you prefer not to use the Stripe-hosted verification page, create a form in your app. Your customers then use this form to relay microdeposit amounts to you and verify the bank account using the Android SDK. - At minimum, set up the form to handle the `descriptor code` parameter, which is a 6-digit string for verification purposes. - Stripe also recommends that you set your form to handle the `amounts` parameter, as some banks your customers use might require it. Integrations only pass in the `descriptor_code` *or* `amounts`. To determine which one your integration uses, check the value for `verify_with_microdeposits[microdeposit_type]` in the `next_action` object. #### Kotlin ```kotlin // Use if you are using a descriptor code, do not use if you are using amounts fun verifySetupIntentWithMicrodeposits( clientSecret: String, descriptorCode: String, callback: ApiResultCallback ) // Use if you are using amounts, do not use if you are using descriptor code fun verifySetupIntentWithMicrodeposits( clientSecret: String, firstAmount: Int, secondAmount: Int, callback: ApiResultCallback ) ``` When the bank account is successfully verified, Stripe returns the SetupIntent object with a `status` of `succeeded`. Verification can fail for several reasons. The failure happens synchronously as a direct error response. ```json { "error": { "code": "payment_method_microdeposit_verification_amounts_mismatch", "message": "The amounts provided do not match the amounts that were sent to the bank account. You have {attempts_remaining} verification attempts remaining.", "type": "invalid_request_error" } } ``` | Error Code | 消息 | Status change | | ------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------- | | `payment_method_microdeposit_failed` | Microdeposits failed. Please check the account, institution and transit numbers provided. | `status` is `requires_payment_method`, and `last_setup_error` is set. | | `payment_method_microdeposit_verification_amounts_mismatch` | The amounts provided don’t match the amounts that were sent to the bank account. You have {attempts_remaining} verification attempts remaining. | Unchanged | | `payment_method_microdeposit_verification_attempts_exceeded` | Exceeded number of allowed verification attempts | `status` is `requires_payment_method`, and `last_setup_error` is set. | ## 测试您的集成 了解如何使用 [Financial Connections](https://docs.stripe.com/financial-connections/testing.md#web-how-to-use-test-accounts) 进行即时验证来测试各种场景。 ### 在沙盒中发送交易电子邮件 在您收集了银行账户详情并接受授权后,在*沙盒* (A sandbox is an isolated test environment that allows you to test Stripe functionality in your account without affecting your live integration. Use sandboxes to safely experiment with new features and changes)中发送授权确认和微存款验证电子邮件。 如果您的域名是 **{domain}**,并且您的用户名是 **{username}**,请使用以下邮件格式发送测试交易邮件: **{username}+test\_email@{domain}**。 例如,如果您的域名是 **example.com**,用户名是 **info**,则使用格式 **info+test\_email@example.com** 来测试 ACH 直接借记支付。这种格式确保电子邮件路由正确。如果您不包含 **+test\_email** 后缀,我们将不发送电子邮件。 > 您需要[激活您的 Stripe 账户](https://docs.stripe.com/get-started/account/activate.md)后才能在测试时触发这些邮件。 ### 测试账号 Stripe 提供了几个测试账号和相应的令牌,您可以用它们来确保您的手动输入银行账户的集成已经可以投入生产。 | 账号 | 令牌 | 路径号码 | 行为 | | -------------- | -------------------------------------- | ----------- | ------------------------------------------------------------------------------------------------- | | `000123456789` | `pm_usBankAccount_success` | `110000000` | 付款成功。 | | `000111111113` | `pm_usBankAccount_accountClosed` | `110000000` | 付款因账户已关闭失败。 | | `000000004954` | `pm_usBankAccount_riskLevelHighest` | `110000000` | 由于[高欺诈风险](https://docs.stripe.com/radar/risk-evaluation.md#high-risk),该支付被 Radar 阻止了。 | | `000111111116` | `pm_usBankAccount_noAccount` | `110000000` | 付款因查无账户失败。 | | `000222222227` | `pm_usBankAccount_insufficientFunds` | `110000000` | 付款因资金不足失败。 | | `000333333335` | `pm_usBankAccount_debitNotAuthorized` | `110000000` | 付款因扣款未获授权失败。 | | `000444444440` | `pm_usBankAccount_invalidCurrency` | `110000000` | 付款因货币无效失败。 | | `000666666661` | `pm_usBankAccount_failMicrodeposits` | `110000000` | 付款时未能发送微额存款。 | | `000555555559` | `pm_usBankAccount_dispute` | `110000000` | 这笔付款触发了争议。 | | `000000000009` | `pm_usBankAccount_processing` | `110000000` | 支付会无限期地保持处理中。这对于测试 [PaymentIntent 取消](https://docs.stripe.com/api/payment_intents/cancel.md) 很有用。 | | `000777777771` | `pm_usBankAccount_weeklyLimitExceeded` | `110000000` | 付款因支付金额导致账户超过每周支付限额失败了。 | | `000888888885` | | `110000000` | 付款失败是因为[令牌化账户号](https://docs.stripe.com/financial-connections/tokenized-account-numbers.md)已停用。 | 在测试交易完成之前,您需要验证所有付款能够自动成功或失败的测试账户。为此,请使用下面测试用的微存款金额或描述符代码。 ### 测试微存款金额和描述符代码 要模拟不同的场景,请使用这些微存款金额_或_ 0.01 此描述符代码值。 | 微存款金额 | 0.01 描述代码的值 | 场景 | | ----------- | ----------- | ---------------- | | `32` 和 `45` | SM11AA | 模拟验证账户。 | | `10` 和 `11` | SM33CC | 模拟次数超过允许的验证尝试次数。 | | `40` 和 `41` | SM44DD | 模拟微存款超时。 | ### 测试结算行为 测试交易会即时结算并添加到您的可用测试余额中。该行为与真实模式不同,真实模式的交易可能需要[数天](https://docs.stripe.com/payments/ach-direct-debit/set-up-payment.md#timing)才能结算到您的可用余额中。 ## Accepting future payments [服务器端] When the SetupIntent succeeds, it will create a new *PaymentMethod* (PaymentMethods represent your customer's payment instruments, used with the Payment Intents or Setup Intents APIs) attached to a [Customer](https://docs.stripe.com/api/customers.md). These can be used to initiate future payments without having to prompt the customer for their bank account a second time. #### curl ```bash curl https://api.stripe.com/v1/payment_intents \ -u <>: \ -d "amount"=1099 \ -d "currency"="usd" \ -d "customer"="{{CUSTOMER_ID}}" \ -d "payment_method"="{{PAYMENT_METHOD_ID}}" \ -d "payment_method_types[]"="us_bank_account" \ -d "confirm"="true" ``` ## Optional: Instant only verification [服务器端] By default, setting up a US bank account payment method allows your customers to use instant bank account verification or microdeposits. You can optionally require instant bank account verification only, using the [verification_method](https://docs.stripe.com/api/setup_intents/object.md#setup_intent_object-payment_method_options-us_bank_account-verification_method) parameter when you create the SetupIntent. ```curl curl https://api.stripe.com/v1/setup_intents \ -u "<>:" \ -d "customer={{CUSTOMER_ID}}" \ -d "payment_method_types[]=us_bank_account" \ -d "payment_method_options[us_bank_account][verification_method]=instant" \ -d "payment_method_options[us_bank_account][financial_connections][permissions][]=payment_method" \ -d "payment_method_options[us_bank_account][financial_connections][permissions][]=balances" ``` This ensures that you don’t need to handle microdeposit verification. However, if instant verification fails, the SetupIntent’s status is `requires_payment_method`, indicating a failure to instantly verify a bank account for your customer. ## Optional: Microdeposit only verification [服务器端] By default, setting up a US bank account payment method lets your customers use instant bank account verification or microdeposits. You can optionally require microdeposit verification using the [verification_method](https://docs.stripe.com/api/setup_intents/object.md#setup_intent_object-payment_method_options-us_bank_account-verification_method) parameter when you create the SetupIntent. > If using a custom payment form, you must build your own UI to collect bank account details. If you disable Stripe microdeposit emails, you must build your own UI for your customer to confirm the microdeposit code or amount. ```curl curl https://api.stripe.com/v1/setup_intents \ -u "<>:" \ -d "customer={{CUSTOMER_ID}}" \ -d "payment_method_types[]=us_bank_account" \ -d "payment_method_options[us_bank_account][verification_method]=microdeposits" ``` You must then collect your customer’s bank account with your own UI and call [PaymentLauncher.confirm](https://stripe.dev/stripe-android/payments-core/com.stripe.android.payments.paymentlauncher/-payment-launcher/confirm.html) with those details to complete the SetupIntent. #### Kotlin ```kotlin class CheckoutActivity : AppCompatActivity() { private lateinit var setupIntentClientSecret: String private val paymentLauncher: PaymentLauncher = // … private fun confirmSetupIntent() { // Use your own UI to collect your customer's input val accountholderName: String = // … val email: String = // … val accountNumber: String = // … val routingNumber: String = // … val accountType: PaymentMethod.USBankAccount.USBankAccountType = // … val accountHolderType: PaymentMethod.USBankAccount.USBankAccountHolderType = // … val createParams = PaymentMethodCreateParams.create( usBankAccount = PaymentMethodCreateParams.USBankAccount( accountNumber = accountNumber, routingNumber = routingNumber, accountType = accountType, accountHolderType = accountHolderType, ), billingDetails = PaymentMethod.BillingDetails( name = accountholderName, email = email, ), ) val confirmParams = ConfirmSetupIntentParams.create( paymentMethodCreateParams = createParams, clientSecret = setupIntentClientSecret, ) paymentLauncher.confirm(confirmParams) } } ``` ## Optional: Updating the default payment method [服务器端] After the `SetupIntent` reaches the `succeeded` state, you can update your customer’s `default_payment_method`. #### Ruby ```ruby # Don't put any keys in code. See https://docs.stripe.com/keys-best-practices. # Find your keys at https://dashboard.stripe.com/apikeys. Stripe.api_key = '<>' if event.type == 'setup_intent.succeeded' setup_intent = event.data.object customer_id = setup_intent['customer'] payment_method_id = setup_intent['payment_method'] # Set the default payment method Stripe::Customer.update( customer_id, { invoice_settings: { default_payment_method: payment_method_id } } ) end ``` # React Native > This is a React Native for when payment-ui is mobile and platform is react-native. View the full page at https://docs.stripe.com/payments/ach-direct-debit/set-up-payment?payment-ui=mobile&platform=react-native. You can use the [Setup Intents API](https://docs.stripe.com/payments/setup-intents.md) to collect payment method details in advance, with the final amount or payment date determined later. This is useful for: - Saving payment methods to a wallet to streamline future purchases - Collecting surcharges after fulfilling a service - Starting a free trial for a *subscription* (A Subscription represents the product details associated with the plan that your customer subscribes to. Allows you to charge the customer on a recurring basis) > ACH Direct Debit is a [delayed notification](https://docs.stripe.com/payments/payment-methods.md#payment-notification) payment method, which means that funds aren’t immediately available after payment. A payment typically takes 4 business days to arrive in your account. ## 设置 Stripe [服务器端] [客户端] ### 服务器端 该集成要求您的服务器上的端点与 Stripe API 通讯。请用我们的官方库从您的服务器访问 Stripe API: #### Ruby ```bash # Available as a gem sudo gem install stripe ``` ```ruby # If you use bundler, you can add this line to your Gemfile gem 'stripe' ``` ### 客户端 [React Native SDK](https://github.com/stripe/stripe-react-native) 是开源的,有完整的文档。在内部,它利用的是[原生 iOS](https://github.com/stripe/stripe-ios) 和 [Android](https://github.com/stripe/stripe-android) SDK。要安装 Stripe 的 React Native SDK,在您的项目目录中运行以下某个指令(取决于您使用的软件包管理器)。 #### yarn ```bash yarn add @stripe/stripe-react-native ``` #### npm ```bash npm install @stripe/stripe-react-native ``` 然后,安装一些其他必要的依赖项: - 对于 iOS,请转到 **ios** 目录并运行 `pod install` 以确保同时安装了所需的本地依赖项。 - 对于 Android,无需安装其他依赖项。 > 建议按照[官方 TypeScript 指南](https://reactnative.dev/docs/typescript#adding-typescript-to-an-existing-project)添加 TypeScript 支持。 ### Stripe 初始化 要在您的 React Native 应用中初始化 Stripe,使用 `StripeProvider` 组件包裹您的支付界面,或者使用 `initStripe` 初始化方法。只需要 `publishableKey` 中的 API [公钥](https://docs.stripe.com/keys.md#obtain-api-keys)。下例显示的是用 `StripeProvider` 组件初始化 Stripe 的方式。 ```jsx import { useState, useEffect } from 'react'; import { StripeProvider } from '@stripe/stripe-react-native'; function App() { const [publishableKey, setPublishableKey] = useState(''); const fetchPublishableKey = async () => { const key = await fetchKey(); // fetch key from your server here setPublishableKey(key); }; useEffect(() => { fetchPublishableKey(); }, []); return ( {/* Your app code here */} ); } ``` > 测试与开发时使用 API [测试模式](https://docs.stripe.com/keys.md#obtain-api-keys),发布时使用[真实模式](https://docs.stripe.com/keys.md#test-live-modes)密钥。 ## Create or retrieve a customer [Recommended] [Server-side] > #### Use the Accounts v2 API to represent customers > > The Accounts v2 API is GA for Connect users, and in public preview for other Stripe users. All Stripe users can enable Accounts v2 [in their Dashboard](https://dashboard.stripe.com/settings/connect/platform-setup). However, when making calls to the Accounts v2 API, preview users need to [specify a preview version](https://docs.stripe.com/api-v2-overview.md#sdk-and-api-versioning). > > For most use cases, we recommend [modeling your customers as customer-configured Account objects](https://docs.stripe.com/connect/use-accounts-as-customers.md) instead of using [Customer](https://docs.stripe.com/api/customers.md) objects. #### Accounts v2 Create a customer-configured [Account](https://docs.stripe.com/api/v2/core/accounts/object.md#v2_account_object-configuration-customer) object when your user creates an account with your business, or retrieve an existing `Account` associated with this user. Associating the ID of the `Account` object with your own internal representation of a customer enables you to retrieve and use the stored payment method details later. Include an email address on the `Account` to enable Financial Connections’ [return user optimization](https://docs.stripe.com/financial-connections/fundamentals.md#return-user-optimization). ```curl curl -X POST https://api.stripe.com/v2/core/accounts \ -H "Authorization: Bearer <>" \ -H "Stripe-Version: 2026-03-25.preview" \ --json '{ "contact_email": "{{CUSTOMER_EMAIL}}" }' ``` #### Customers v1 Create a *Customer* (Customer objects represent customers of your business. They let you reuse payment methods and give you the ability to track multiple payments) object when your user creates an account with your business, or retrieve an existing `Customer` associated with this user. Associating the ID of the `Customer` object with your own internal representation of a customer enables you to retrieve and use the stored payment method details later. Include an email address on the `Customer` to enable Financial Connections’ [return user optimization](https://docs.stripe.com/financial-connections/fundamentals.md#return-user-optimization). ```curl curl https://api.stripe.com/v1/customers \ -u "<>:" \ -d email={{CUSTOMER_EMAIL}} ``` ## 创建 SetupIntent [服务器端] A [SetupIntent](https://docs.stripe.com/api/setup_intents.md) is an object that represents your intent to set up a customer’s payment method for future payments. The `SetupIntent` tracks the steps of this set-up process. Create a SetupIntent on your server with [payment_method_types](https://docs.stripe.com/api/setup_intents/create.md#create_setup_intent-payment_method_types) set to `us_bank_account` and specify the Customer’s [id](https://docs.stripe.com/api/customers/object.md#customer_object-id). ### 服务器端 Create a SetupIntent on your server with [payment_method_types](https://docs.stripe.com/api/setup_intents/create.md#create_setup_intent-payment_method_types) set to `us_bank_account` and specify the Customer’s [id](https://docs.stripe.com/api/customers/object.md#customer_object-id). For more information on Financial Connections fees, see [pricing details](https://stripe.com/financial-connections#pricing). By default, collecting bank account payment information uses [Financial Connections](https://docs.stripe.com/financial-connections.md) to instantly verify your customer’s account, with a fallback option of manual account number entry and microdeposit verification. See the [Financial Connections docs](https://docs.stripe.com/financial-connections/ach-direct-debit-payments.md) to learn how to configure Financial Connections and access additional account data to optimize your ACH integration. For example, you can use Financial Connections to check an account’s balance before initiating the ACH payment. > To expand access to additional data after a customer authenticates their account, they must re-link their account with expanded permissions. ```curl curl https://api.stripe.com/v1/setup_intents \ -u "<>:" \ -d customer={{CUSTOMER_ID}} \ -d "payment_method_types[]=us_bank_account" \ -d "payment_method_options[us_bank_account][financial_connections][permissions][]=payment_method" \ -d "payment_method_options[us_bank_account][financial_connections][permissions][]=balances" ``` ### 客户端 A SetupIntent includes a *client secret* (The client secret is a unique key returned from Stripe as part of a PaymentIntent. This key lets the client access important fields from the PaymentIntent (status, amount, currency) while hiding sensitive ones (metadata, customer)). You can use the client secret in your React Native app to securely complete the payment process instead of passing back the entire SetupIntent object. In your app, request a SetupIntent from your server and store its client secret. ```javascript function PaymentScreen() { // ... const fetchIntentClientSecret = async () => { const response = await fetch(`${API_URL}/create-intent`, { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ // This is an example request body, the parameters you pass are up to you customer: '', }), }); const {clientSecret} = await response.json(); return clientSecret; }; return ...; } ``` ## 收集支付方式详情 [客户端] Rather than sending the entire SetupIntent object to the client, use its *client secret* (The client secret is a unique key returned from Stripe as part of a PaymentIntent. This key lets the client access important fields from the PaymentIntent (status, amount, currency) while hiding sensitive ones (metadata, customer)) from the previous step. This is different from your API keys that authenticate Stripe API requests. Handle the client secret carefully because it can complete the charge. Don’t log it, embed it in URLs, or expose it to anyone but the customer Use [collectBankAccountForSetup](https://docs.stripe.com/js/setup_intents/collect_bank_account_for_setup) to collect bank account details, create a *PaymentMethod* (PaymentMethods represent your customer's payment instruments, used with the Payment Intents or Setup Intents APIs), and attach that PaymentMethod to the SetupIntent. You must include the account holder’s name in the `billingDetails` parameter to create an ACH Direct Debit PaymentMethod. ```javascript import {collectBankAccountForSetup} from '@stripe/stripe-react-native'; export default function MyPaymentScreen() { const [name, setName] = useState(''); const handleCollectBankAccountPress = async () => { // Fetch the intent client secret from the backend. // See `fetchIntentClientSecret()`'s implementation above. const {clientSecret} = await fetchIntentClientSecret(); const {setupIntent, error} = await collectBankAccountForSetup( clientSecret, { paymentMethodType: 'USBankAccount', paymentMethodData: { billingDetails: { name: "John Doe", }, }, }, ); if (error) { Alert.alert(`Error code: ${error.code}`, error.message); } else if (setupIntent) { Alert.alert('Setup status:', setupIntent.status); if (setupIntent.status === SetupIntents.Status.RequiresConfirmation) { // The next step is to call `confirmSetup` } else if (setupIntent.status === SetupIntents.Status.RequiresAction) { // The next step is to call `verifyMicrodepositsForSetup` } } }; return ( setName(value.nativeEvent.text)} />