Accept an ACH Direct Debit payment
Build a custom payment form or use Stripe Checkout to accept payments with ACH Direct Debit.
Accepting ACH Direct Debit payments in your app consists of:
- Creating an object to track a payment
- Collecting payment method information with instant verifications enabled by Stripe Financial Connections
- Submitting the payment to Stripe for processing
- Verifying your customer’s bank account
Note
ACH Direct Debit is a delayed 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 uses the payment object, the Payment Intent, to track and handle all the states of the payment until the payment completes.
The Stripe Android SDK is open source and fully documented.
To install the SDK, add stripe-android
and financial-connections
to the dependencies
block of your app/build.gradle file:
Note
For details on the latest SDK release and past versions, see the Releases page on GitHub. To receive notifications when a new release is published, watch releases for the repository.
Configure the SDK with your Stripe publishable key so that it can make requests to the Stripe API, such as in your Application
subclass:
Note
Create or retrieve a customerRecommendedServer-side
Create a Customer 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.
Create a PaymentIntentServer-sideClient-side
A PaymentIntent is an object that represents your intent to collect payment from a customer and tracks the lifecycle of the payment process through each stage.
Server-side 
First, create a PaymentIntent on your server and specify the amount to collect and the usd
currency. If you already have an integration using the Payment Intents API, add us_
to the list of payment method types for your PaymentIntent. Optionally, specify the id of the Customer.
If you want to reuse the payment method in the future, provide the setup_future_usage parameter with the value of off_
.
By default, collecting bank account payment information uses Financial Connections to instantly verify your customer’s account, with a fallback option of manual account number entry and microdeposit verification. See the Financial Connections docs 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.
Note
To expand access to additional data after a customer authenticates their account, they must re-link their account with expanded permissions.
Client-side 
Included in the returned PaymentIntent is a client secret, which the client side can use to securely complete the payment process instead of passing the entire PaymentIntent object. On the client, request a PaymentIntent from your server and use the client secret for subsequent API calls.
Collect payment method detailsClient-side
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.
to create the parameters required to call presentWithPaymentIntent
.
Initialize a CollectBankAccountLauncher
instance inside onCreate of your checkout Activity, passing a method to handle the result. Then proceed to call presentWithPaymentIntent
to collect bank account details, create a PaymentMethod, and attach that PaymentMethod to the PaymentIntent.
This loads a modal UI that handles bank account details collection and verification. When it completes, the PaymentMethod automatically attaches to the PaymentIntent.
Collect mandate acknowledgement and submit the paymentClient-side
Before you can initiate the payment, you must obtain authorization from your customer by displaying mandate terms for them 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.
When the customer accepts the mandate terms, you must confirm the Payment. Use confirm
to complete the payment when the customer submits the form.
Note
confirm
may 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 PaymentIntent object, with one of the following possible statuses:
Status | Description | Next Steps |
---|---|---|
requires_ | Further action is needed to complete bank account verification. | Step 5: Verifying bank accounts with microdeposits |
processing | The bank account was instantly verified or verification isn’t necessary. | Step 6: Confirm the PaymentIntent succeeded |
After successfully confirming the Payment, 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 if you prefer.
Verify bank account with micro-depositsClient-side
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_
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_
that starts with SM. Your customer uses this string to verify their bank account.code - 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 confirmPayment
method call in the previous step is a PaymentIntent in the requires_
state. The PaymentIntent contains a next_action field that contains some useful information for completing the verification.
If you supplied a billing 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.
Warning
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 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_
URL in the next_action object to direct your customer to complete the verification process.with_ microdeposits[hosted_ verification_ url] 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 may require it.
Integrations only pass in the
descriptor_
orcode amounts
. To determine which one your integration uses, check the value forverify_
in thewith_ microdeposits[microdeposit_ type] next_
object.action - At minimum, set up the form to handle the
When the bank account is successfully verified, Stripe returns the PaymentIntent object with a status
of processing
.
Verification can fail for several reasons. The failure happens synchronously as a direct error response.
{ "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 | Message | Status change |
---|---|---|
payment_ | Microdeposits failed. Please check the account, institution and transit numbers provided. | status is requires_ , and last_ is set. |
payment_ | The amounts provided do not match the amounts that were sent to the bank account. You have {attempts_remaining} verification attempts remaining. | Unchanged |
payment_ | Exceeded number of allowed verification attempts | status is requires_ , and last_ is set. |
Confirm the PaymentIntent succeededServer-side
ACH Direct Debit is a delayed notification payment method. This means that it can take up to four business days to receive notification of the success or failure of a payment after you initiate a debit from your customer’s account.
The PaymentIntent you create initially has a status of processing
. After the payment has succeeded, the PaymentIntent status is updated from processing
to succeeded
.
We recommend using webhooks to confirm the charge has succeeded and to notify the customer that the payment is complete. You can also view events on the Stripe Dashboard.
Test your integration
Learn how to test scenarios with instant verifications using Financial Connections.
Send transaction emails in a sandbox
After you collect the bank account details and accept a mandate, send the mandate confirmation and microdeposit verification emails in a sandbox.
If your domain is {domain} and your username is {username}, use the the following email format to send test transaction emails: {username}+test_email@{domain}.
For example, if your domain is example.com and your username is info, use the format info+test_email@example.com for testing ACH Direct Debit payments. This format ensures that emails route correctly. If you don’t include the +test_email suffix, we won’t send the email.
Common mistake
You need to activate your Stripe account before you can trigger these emails while testing.
Test account numbers
Stripe provides several test account numbers and corresponding tokens you can use to make sure your integration for manually-entered bank accounts is ready for production.
Account number | Token | Routing number | Behavior |
---|---|---|---|
000123456789 | pm_ | 110000000 | The payment succeeds. |
000111111113 | pm_ | 110000000 | The payment fails because the account is closed. |
000000004954 | pm_ | 110000000 | The payment is blocked by Radar due to a high risk of fraud. |
000111111116 | pm_ | 110000000 | The payment fails because no account is found. |
000222222227 | pm_ | 110000000 | The payment fails due to insufficient funds. |
000333333335 | pm_ | 110000000 | The payment fails because debits aren’t authorized. |
000444444440 | pm_ | 110000000 | The payment fails due to invalid currency. |
000666666661 | pm_ | 110000000 | The payment fails to send microdeposits. |
000555555559 | pm_ | 110000000 | The payment triggers a dispute. |
000000000009 | pm_ | 110000000 | The payment stays in processing indefinitely. Useful for testing PaymentIntent cancellation. |
000777777771 | pm_ | 110000000 | The payment fails due to payment amount causing the account to exceed its weekly payment volume limit. |
Before test transactions can complete, you need to verify all test accounts that automatically succeed or fail the payment. To do so, use the test microdeposit amounts or descriptor codes below.
Test microdeposit amounts and descriptor codes
To mimic different scenarios, use these microdeposit amounts or 0.01 descriptor code values.
Microdeposit values | 0.01 descriptor code values | Scenario |
---|---|---|
32 and 45 | SM11AA | Simulates verifying the account. |
10 and 11 | SM33CC | Simulates exceeding the number of allowed verification attempts. |
40 and 41 | SM44DD | Simulates a microdeposit timeout. |
Test settlement behavior
Test transactions settle instantly and are added to your available test balance. This behavior differs from livemode, where transactions can take multiple days to settle in your available balance.