Sign in
An image of the Stripe logo
Create account
Sign in
Home
Payments
Business operations
Financial services
Developer tools
No-code
All products
Home
Payments
Business operations
Home
Payments
Business operations
Financial services
Developer tools
Support
Overview
Overview
How subscriptions work
Recurring pricing models
Get started
Quickstart
Integrate a SaaS business
Embed a pricing table
Design an integration
Build a subscriptions integration
Migrate subscriptions to Stripe
Billing resources
Coupons
Customers
Subscriptions
Subscription invoices
Manage subscriptions
Change subscriptions
Usage-based billing
Use trial periods
Set payment methods
ACH Direct Debit
Bacs Direct Debit in the UK
Bank transfer
BECS Direct Debit in Australia
Pre-authorized debit in Canada
SEPA Direct Debit in the EU
iDEAL with SEPA Direct Debit
Bancontact with SEPA Direct Debit
Sofort with SEPA Direct Debit
Subscriptions with multiple products
Set subscription quantities
Subscription webhooks
Schedule subscriptions
Tax
Sales-led B2B billing
Integrate with Salesforce
Manage recurring revenue
Revenue recognition
Revenue recovery
Subscription metrics
Customer management
Overview
Set up the the no-code customer portal
Set up the customer portal with the API
Configure the customer portal
Testing
Test your integration
Test clocks
Strong Customer Authentication (SCA)
Invoices API updates
Testing
Billing
·
HomePaymentsSubscriptionsSet payment methods

Set up a subscription with pre-authorized debit in Canada

Learn how to create and charge for a subscription with Canadian pre-authorized debits.

Subscriptions support in Checkout is not yet supported. If you’d like to learn about early access when this feature is available, please contact us to join our waitlist.

Create a product and price
Dashboard

Products represent the item or service you’re selling. Prices define how much and how frequently you charge for a product. This includes how much the product costs, what currency you accept, and whether it’s a one-time or recurring charge. If you only have a few products and prices, create and manage them in the Dashboard.

This guide uses a stock photo service as an example and charges customers a 15 CAD monthly subscription. To model this:

  1. Navigate to the Add a product page.
  2. Enter a Name for the product.
  3. Enter 15 for the price.
  4. Select CAD as the currency.
  5. Click Save product.

After you create the product and the price, record the price ID so you can use it in subsequent steps. The pricing page displays the ID and it looks similar to this: price_G0FvDp6vZvdwRZ.

Create the subscription
Server-side

To create a subscription with a free trial period, see Subscription trials.

Create a subscription with the price and customer with status incomplete by providing the payment_behavior parameter with the value of default_incomplete.

Command Line
curl https://api.stripe.com/v1/subscriptions \ -u
sk_test_4eC39HqLyjWDarjtT1zdp7dc
: \ -d "customer"="{{CUSTOMER_ID}}" \ -d "items[0][price]"="price_F52b2UdntfQsfR" \ -d "payment_behavior"="default_incomplete" \ -d "payment_settings[payment_method_types][]"="acss_debit" \ -d "expand[0]"="latest_invoice.payment_intent"

Included in the response is the subscription’s first PaymentIntent, containing the client secret, which is used on the client side to securely complete the payment process instead of passing the entire PaymentIntent object. Return the client_secret to the frontend to complete payment.

Collect payment method details and mandate acknowledgment
Client-side

To use Canadian pre-authorized debits, you must obtain authorization from your customer for one-time and recurring debits using a pre-authorized debit agreement (see PAD Mandates). The Mandate object records this agreement and authorization.

Stripe automatically configures subscription and invoice mandates for you. The customer only needs to acknowledge the mandate terms once, subsequent subscription charges will succeed without further intervention.

Newly acknowledged mandates have a three-day holding period required per Payments Canada network rules. The subscription’s first PaymentIntent has a processing status until the payment succeeds.

When a customer clicks to pay with Canadian pre-authorized debit, we recommend you use Stripe.js to submit the payment to Stripe. Stripe.js 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.

Include the Stripe.js script on your checkout page by adding it to the head of your HTML file.

checkout.html
<head> <title>Checkout</title> <script src="https://js.stripe.com/v3/"></script> </head>

Create an instance of Stripe.js with the following JavaScript on your checkout page.

client.js
// Set your publishable key. Remember to change this to your live publishable key in production! // See your keys here: https://dashboard.stripe.com/apikeys const stripe = Stripe(
'pk_test_TYooMQauvdEDq54NiTphI7jx'
);

Rather than sending the entire PaymentIntent object to the client, use its client secret from the previous step. This is different from your API keys that authenticate Stripe API requests.

The client secret should still be handled carefully because it can complete the charge. Do not log it, embed it in URLs, or expose it to anyone but the customer.

Use stripe.confirmAcssDebitPayment to collect bank account details and verification, confirm the mandate, and complete the payment when the user submits the form. Including the customer’s email address and the account holder’s name in the billing_details property of the payment_method parameter is required to create a PAD payment method.

const form = document.getElementById('payment-form'); const accountholderName = document.getElementById('accountholder-name'); const email = document.getElementById('email'); const submitButton = document.getElementById('submit-button'); const clientSecret = submitButton.dataset.secret; form.addEventListener('submit', async (event) => { event.preventDefault(); const {paymentIntent, error} = await stripe.confirmAcssDebitPayment( clientSecret, { payment_method: { billing_details: { name: accountholderName.value, email: email.value, }, }, } ); if (error) { // Inform the customer that there was an error. console.log(error.message); } else { // Handle next step based on PaymentIntent's status. console.log("PaymentIntent ID: " + paymentIntent.id); console.log("PaymentIntent status: " + paymentIntent.status); } });

Stripe.js then loads an on-page modal UI that handles bank account details collection and verification, presents a hosted mandate agreement and collects authorization.

stripe.confirmAcssDebitPayment may take several seconds to complete. During that time, disable your form from being resubmitted and show a waiting indicator like a spinner. If you receive an error, show it to the customer, re-enable the form, and hide the waiting indicator.

If the customer completes instant verification, the subscription automatically becomes active. Otherwise, consult the following section to handle micro-deposit verification while the subscription remains incomplete.

Verify bank account with micro-deposits
Client-side

Customers have 10 days to successfully verify micro-deposits for a subscription, instead of 23 hours normally given in the subscription lifecycle. However, this expiration can’t be later than the billing cycle date.

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 this case, Stripe automatically sends two micro-deposits to the customer’s bank account. These deposits take one to two business days to appear on the customer’s online statement and have statement descriptors that include ACCTVERIFY.

The result of the stripe.confirmAcssDebitPayment method call in the previous step is a PaymentIntent in the requires_action state. The PaymentIntent contains a next_action field that contains some useful information for completing the verification.

Stripe notifies your customer at the billing 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.

There is a limit of three failed verification attempts. If this limit is exceeded, the bank account can no longer be verified. In addition, there is a timeout for micro-deposit verifications of 10 days. If micro-deposits are not verified in that time, the PaymentIntent reverts to requiring new payment method details. Clear messaging about what these micro-deposits are and how you use them can help your customers avoid verification issues.

Optional: Custom email and verification page

If you choose to send custom email notifications, you have to email your customer instead. To do this, you can use the verify_with_microdeposits[hosted_verification_url] URL in the next_action object to direct your customer to complete the verification process.

If you are sending custom emails and don’t want to use the Stripe hosted verification page, you can create a form on your site for your customers to relay these amounts to you and verify the bank account using Stripe.js.

stripe.verifyMicrodepositsForPayment(clientSecret, { amounts: [32, 45], });

Set the default payment method
Server

You now have an active subscription belonging to a customer with a payment method, but this payment method isn’t automatically used for future payments. To automatically bill this payment method in the future, use a webhook consumer to listen to the invoice.payment_succeeded event for new subscriptions and set the default payment method.

server.rb
# Set your secret key. Remember to switch to your live secret key in production. # See your keys here: https://dashboard.stripe.com/apikeys Stripe.api_key =
'sk_test_4eC39HqLyjWDarjtT1zdp7dc'
if event.type == 'invoice.payment_succeeded' invoice = event.data.object if invoice['billing_reason'] == 'subscription_create' subscription_id = invoice['subscription'] payment_intent_id = invoice['payment_intent'] # Retrieve the payment intent used to pay the subscription payment_intent = Stripe::PaymentIntent.retrieve(payment_intent_id) # Set the default payment method Stripe::Subscription.update( subscription_id, default_payment_method: payment_intent.payment_method ) end end

Manage subscription status
Client-side

Assuming the initial payment succeeds, the state of the subscription is active and requires no further action. When payments fail, the status changes to the Subscription status configured in your automatic collection settings. Notify the customer upon failure and charge them with a different payment method.

Canadian pre-authorized debit payments are never automatically retried, even if you have a retry schedule configured for other payment methods.

Test your integration

It is possible to both skip the mandate delay and receive the micro-deposit verification email by providing an email in the form of {any_prefix}+skip_waiting+test_email@{any_domain}.

Skip mandate delay

After collecting the bank account details and accepting a mandate, Canadian pre-authorized debit payments are held for three days before charging (see PAD Mandates).

To test a payment that will immediately attempt to charge after verification is complete, provide an email in the payment_method[billing_details][email] field in the form of {any_prefix}+skip_waiting@{any_domain} when confirming the payment method details.

Receive micro-deposit verification email

In order to receive the micro-deposit verification email in test mode after collecting the bank account details and accepting a mandate, provide an email in the payment_method[billing_details][email] field in the form of {any_prefix}+test_email@{any_domain} when confirming the payment method details.

Test account numbers

Stripe provides several test account numbers you can use to make sure your integration for manually-entered bank accounts is ready for production. All test accounts that automatically succeed or fail the payment must be verified using the test micro-deposit amounts below before they can be completed.

Institution NumberTransit NumberAccount NumberScenario
00011000000123456789Succeeds the payment immediately after micro-deposits are verified.
00011000900123456789Succeeds the payment with a three-minute delay after micro-deposits are verified.
00011000000222222227Fails the payment immediately after micro-deposits are verified.
00011000900222222227Fails the payment with a three-minute delay after micro-deposits are verified.
00011000000666666661Fails to send verification micro-deposits.

To mimic successful or failed bank account verifications in test mode, use these meaningful amounts for micro-deposits:

Micro-deposit ValuesScenario
32 and 45Successfully verifies the account.
Any other number combinationsFails account verification.

OptionalSetting the billing cycle

OptionalSubscription trials

OptionalSaving payment method details for future use

Was this page helpful?
Questions? Contact us.
Watch our developer tutorials.
Check out our product changelog.
Powered by Markdoc
You can unsubscribe at any time. Read our privacy policy.
On this page
Create a product and price
Create the subscription
Collect payment method details and mandate acknowledgment
Verify bank account with micro-deposits
Set the default payment method
Manage subscription status
Test your integration
Setting the billing cycle
Subscription trials
Saving payment method details for future use
Stripe Shell
Test mode
▗▄ ▄▟█ █▀▀ ▗▟████▙▖ ██████ ███▗▟█ ███ ███▗▟██▙▖ ▗▟█████▙▖ ███▖ ▀▀ ███ ███▀▀▀ ███ ███▀ ███ ███ ███ ▝▜████▙▖ ███ ███ ███ ███ ███ █████████ ▄▄ ▝███ ███ ▄ ███ ███ ███▄ ███ ███ ▄▄ ▝▜████▛▘ ▝▜███▛ ███ ███ ███▝▜██▛▘ ▝▜█████▛▘ ███ ▀▘
Welcome to the Stripe Shell! Stripe Shell is a browser-based shell with the Stripe CLI pre-installed. Login to Stripe docs and press Control + Backtick on your keyboard to start managing your Stripe resources in test mode. - View supported commands: - Find webhook events: - Listen for webhook events: - Call Stripe APIs: stripe [api resource] [operation] (e.g. )
The Stripe Shell is best experienced on desktop.
$