Client-side implementation
ACH Direct Debit is available to eligible merchants. It's currently not available in our Drop-in UI.
Implement ACH Direct Debit on your client to collect a customer's bank account information, verify it using one of three verification methods, and exchange it for a payment method nonce you can use to create transactions.
On this page, we cover:
- The basic workflow for each verification method
- How to load and initialize the usBankAccount component on your client
- How to collect customers' bank account information based on the verification method(s) you intend to use
- How to prove you have authorization to charge customers' accounts
- How to exchange the bank account information for a payment method nonce
In addition to completing your client implementation, be sure to follow the Server-side Implementation and Testing and Go Live portions of the guide, as well.
Workflows by verification method
As mentioned in the ACH overview, you must verify a customer's bank account information before you can transact on it. However, your verification workflow changes depending on which verification method you use. Learn more about the 3 available verification methods in our support articles.
All verification methods are triggered server-side and require you to store the bank account as a payment method in your Vault before you can create a transaction. If you attempt to create a one-time transaction with a payment method nonce representing an unverified bank account, the request fails.
If you'd like to allow your customers to choose their preferred method, or if you'd like to present a backup verification method if the first attempt fails, you can implement multiple verification methods.
Network check
- On your client side, prompt the customer to enter the required bank account information and consent to ACH Direct Debit transactions
- Tokenize the bank account information to get a payment method nonce
- On your server side, use the payment method nonce to save the bank account information as a payment method in your Vault and specify the verification method as network_check
- By default, only account/routing number information is verified. If you want to also verify personal/business information, specify customer_verification under verification_add_ons.
- Check the verification status on the payment method response object to determine whether the bank account was verified successfully
- If the verification status is verified, create transactions as needed using the payment method token
If the verification status is PROCESSOR_DECLINED with Processor Response Codes 2046 or 2092, you must deliver the following message to consumers:
Sorry, the bank account was not charged but you may still complete this transaction with an alternative account or payment method. This transaction was declined based, at least in part, on consumer reporting data obtained from Giact Systems, LLC. Giact did not make the decision to decline this transaction and is unable to provide the specific reasons why the transaction was declined. You have the right to obtain a free copy of your consumer report from Giact if you make a request within 60 days and you have the right to dispute the accuracy or completeness of the information with Giact by contacting them:
Giact Systems, LLC
700 Central Expy. S, Suite 300
Allen, TX 75013
1-866-918-2409
Micro-transfers
- On your client side, prompt the customer to enter the required bank account information and consent to ACH Direct Debit transactions
- Tokenize the bank account information to get a payment method nonce
- On your server side, use the payment method nonce to save the bank account information as a payment method in your Vault and specify the verification method as micro_transfers
- This triggers the deposit of two sub-$1 amounts into the customer's bank account, followed immediately by a single debit to reverse the deposits
- In your UI, prompt the customer to enter the micro-deposit amounts they see in their bank account and then attempt confirmation using the API
- Customers should see PAYPAL on their statement
- You have up to 5 attempts to provide the correct amounts
- On your server side, check the verification status on the payment method response object to determine whether the bank account was verified successfully
- Verification status moves from pending to verified when all micro-transfer credits and debits have successfully settled and the customer has confirmed the amounts
- If the verification status is verified, create transactions as needed using the payment method token
Independent check
- On your client side, prompt the customer to enter the required bank account information and consent to ACH Direct Debit transactions
- Tokenize the bank account information to get a payment method nonce
- On your server side, save the banking information as a payment method in your Vault using the payment method nonce and specify the verification method as independent_check
- This automatically sets the payment method's verification status to verified
- Create transactions as needed using the payment method token
Load the component
Use direct links
If you're integrating with <script> tags, you can load the usBankAccount component just like the required client component:
- HTML
<script src="https://js.braintreegateway.com/web/4.0.0-alpha.0/js/client.min.js"></script>
<script src="https://js.braintreegateway.com/web/4.0.0-alpha.0/js/us-bank-account.min.js"></script>Use CommonJS (Browserify or Webpack)
You can require the us-bank-account module just like the client module:
- JavaScript
const client = require('braintree-web/client');
const usBankAccount = require('braintree-web/us-bank-account');
// ...Initialize the component
Every Braintree.js component requires a Client, and the usBankAccount component is no exception. Create a usBankAccountInstance like this:
- Async/Await
async function initializeUsBankAccount() {
try {
const clientInstance = await braintree.client.create({
authorization: 'CLIENT-TOKEN-FROM-SERVER'
});
const usBankAccountInstance = await braintree.usBankAccount.create({
client: clientInstance
});
// Use the usBankAccountInstance here.
// ...
} catch (err) {
// Handle the component creation error.
}
}If the promise resolves without an error, usBankAccountInstance is ready to use in the following steps.
Collect bank account information
After your component is ready, collect the required bank account information from the customer according to the verification method(s) you intend to use. For Network Check, Micro-Transfers, or Independent Check, the following bank account information is required:
- routingNumber
- accountNumber
- accountType (checking or savings)
- ownershipType (personal or business)
- firstName (if personal)
- lastName (if personal)
- businessName (if business)
- billingAddress
Use network check, micro-transfers, or independent check
To create a transaction with this information, you'll need to exchange the bank details for a payment method nonce using the tokenize method. Here's an example to get fields from a form:
- Async/Await
// ...
async function collectBankDetails() {
try {
const usBankAccountInstance = await braintree.usBankAccount.create({
client: clientInstance
});
// ...
const bankDetails = {
accountNumber: document.getElementById('account-number').value,
routingNumber: document.getElementById('routing-number').value,
accountType: document.querySelector('input[name="account-type"]:checked').value,
ownershipType: document.querySelector('input[name="ownership-type"]:checked').value,
billingAddress: {
streetAddress: document.getElementById('billing-street-address').value,
extendedAddress: document.getElementById('billing-extended-address').value,
locality: document.getElementById('billing-locality').value,
region: document.getElementById('billing-region').value,
postalCode: document.getElementById('billing-postal-code').value
}
};
if (bankDetails.ownershipType === 'personal') {
bankDetails.firstName = document.getElementById('first-name').value;
bankDetails.lastName = document.getElementById('last-name').value;
} else {
bankDetails.businessName = document.getElementById('business-name').value;
}
// ...
} catch (err) {
// Handle the error.
}
}After this runs, bankDetails contains the values you need for tokenization.
Show required authorization language
For all ACH transactions, you are required to collect a mandate or "proof of authorization" from the customer to prove that you have their explicit permission to debit their bank account. We facilitate this requirement by storing the mandate text for you and providing it directly to banks if required, as long as you do both of the following:
- Include the exact text shown below as part of your checkout flow, at or near the final Buy button (for example, a Purchase or Complete button)
- Pass the text back to us as mandateText when you tokenize the bank account information
The explicit language you must include for different use-cases is provided below:
Standing authorization for future purchases ("Subsequent Entries"):
By clicking ["Checkout/Submit"], I authorize Braintree, a PayPal service, on behalf of [your business name here] to verify my bank account information using bank information and consumer reports and I authorize [your business name here] to store my account information on file and to initiate ACH/electronic debits for future payments, as follows: Account holder: <insert full name>, Financial Institution: <insert bank name>, [Checking / Savings] Account Number: <insert account number or last 4>, Routing Number: <insert routing number>, Authorization Date: <insert date>.
Any subsequent ACH/electronic debits to my account can be initiated by online confirmation. I understand that this authorization will remain in full force and effect until I notify [your business name here] that I wish to revoke this authorization [insert manner of revocation, e.g. in writing / by phone].
One-time purchase ("Single Entry"):
By clicking ["Checkout/Submit/Agree/Continue"], I authorize Braintree, a PayPal service, on behalf of [your business name here] to verify my bank account information using bank information and consumer reports and I authorize [your business name here] to initiate a one-time ACH/electronic debit to my account as follows: Account holder: <insert full name>, Financial Institution: <insert bank name>, [Checking / Savings] Account Number: <insert account number or last 4>, Routing Number: <insert routing number>, Amount: <insert amount>, Authorization Date: <insert date>.
Tokenize bank account information
Regardless of which verification method you use, after you've collected the required bank account information, the next step is to tokenize it in exchange for a payment method nonce.
The tokenize call is also where you should pass the required mandateText that you displayed to the customer in your UI.
- Async/Await
// ...
async function tokenizeBankAccount() {
try {
const usBankAccountInstance = await braintree.usBankAccount.create({
client: clientInstance
});
// Collect bankDetails.
const tokenizedPayload = await usBankAccountInstance.tokenize({
bankDetails: bankDetails,
mandateText: 'By clicking ["Checkout"], I authorize Braintree, a service of PayPal, on behalf of [your business name here] (i) to verify my bank account information using bank information and consumer reports and (ii) to debit my bank account.'
});
// Submit tokenizedPayload.nonce to your server as you would
// other payment method nonces.
} catch (err) {
// Handle the error.
}
}A successful call returns a tokenizedPayload object containing a nonce you can submit to your server.
- Tokenizing bank account information means exchanging any bank account information for a payment method nonce.
Tokenize only exchanges the bank account information for a payment method nonce through Braintree. You'll need to trigger verification separately on your server.
Collect device data
We recommend including device data with all customer-initiated transactions to decrease the risk of fraud. For more information, see our guide on Device Data Collection.