Skip to content
Create account
or
Sign in
The Stripe Docs logo
/
Ask AI
Create account
Sign in
Get started
Payments
Revenue
Platforms and marketplaces
Money management
Developer tools
Overview
About Stripe payments
Upgrade your integration
Payments analytics
Online payments
OverviewFind your use caseManaged Payments
Use Payment Links
Build a checkout page
Build an advanced integration
Build an in-app integration
Payment Methods
Add payment methods
    Overview
    Payment method integration options
    Manage default payment methods in the Dashboard
    Payment method types
    Cards
    Pay with Stripe balance
    Crypto
    Bank debits
      ACH Direct Debit
      Bacs Direct Debit
      Pre-authorised debit in Canada
      Australia BECS Direct Debit
      New Zeland BECS Direct Debit
      SEPA Direct Debit
        Accept a payment
        Save bank details
    Bank redirects
    Bank transfers
    Credit transfers (Sources)
    Buy now, pay later
    Real-time payments
    Vouchers
    Wallets
    Enable local payment methods by country
    Custom payment methods
Manage payment methods
Faster checkout with Link
Payment interfaces
Payment Links
Checkout
Web Elements
In-app Elements
Payment scenarios
Custom payment flows
Flexible acquiring
Orchestration
In-person payments
Terminal
Other Stripe products
Financial Connections
Crypto
Climate
HomePaymentsAdd payment methodsBank debitsSEPA Direct Debit

Save SEPA Direct Debit details for future payments

Learn how to save payment method details for future SEPA Direct Debit payments.

Copy page

Note

When processing SEPA Direct Debit payments using the Stripe Creditor ID, we recommend you use the pre-built checkout page to save SEPA Direct Debit details for future use.

You can use the Setup Intents API to collect payment method details in advance, and determine the final amount or payment date later. Use it to:

  • Save payment methods to a wallet to streamline future purchases
  • Collect surcharges after fulfilling a service
  • Start a free trial for a subscription

Set up Stripe
Server-side

First, you need a Stripe account. Register now.

Use our official libraries for access to the Stripe API from your application:

Command Line
Ruby
# Available as a gem sudo gem install stripe
Gemfile
Ruby
# If you use bundler, you can add this line to your Gemfile gem 'stripe'

Create or retrieve a Customer
Server-side

To reuse a SEPA Direct Debit account for future payments, it must be attached to a Customer.

You should create a Customer object when your customer creates an account with your business. Associating the ID of the Customer object with your own internal representation of a customer will enable you to retrieve and use the stored payment method details later. If your customer hasn’t created an account, you can still create a Customer object now and associate it with your internal representation of the customer’s account later.

Create a new Customer or retrieve an existing Customer to associate with these payment details. Include the following code on your server to create a new Customer.

Command Line
cURL
curl -X POST https://api.stripe.com/v1/customers \ -u "
sk_test_BQokikJOvBiI2HlWgH4olfQ2
:"

Create a SetupIntent
Server-side

A SetupIntent is an object that represents your intent and tracks the steps to set up your customer’s payment method for future payments. For SEPA Direct Debit, this includes collecting a mandate from the customer and checking the validity of the IBAN.

Create a SetupIntent on your server with payment_method_types set to sepa_debit and specify the Customer’s id.:

Command Line
curl
curl https://api.stripe.com/v1/setup_intents \ -u
sk_test_BQokikJOvBiI2HlWgH4olfQ2
:
\ -d "payment_method_types[]"="sepa_debit" \ -d "customer"="{{CUSTOMER_ID}}"

Collect payment method details and mandate acknowledgment
Client-side

You’re ready to collect payment information on the client with Stripe Elements. Elements is a set of pre-built UI components for collecting payment details.

A Stripe Element contains an iframe that securely sends the payment information to Stripe over an HTTPS connection. The checkout page address must also start with https:// rather than http:// for your integration to work.

You can test your integration without using HTTPS. Enable it when you’re ready to accept live payments.

Set up Stripe Elements

Stripe Elements is automatically available as a feature of Stripe.js. Include the Stripe.js script on your payment page by adding it to the head of your HTML file. Always load Stripe.js directly from js.stripe.com to remain PCI compliant. Do not include the script in a bundle or host a copy of it yourself.

payment_setup.html
<head> <title>Submit Payment</title> <script src="https://js.stripe.com/v3/"></script> </head>

Create an instance of Elements with the following JavaScript on your payment page:

const stripe = Stripe(
'pk_test_TYooMQauvdEDq54NiTphI7jx'
); const elements = stripe.elements();

Add and configure an IBAN Element

Elements needs a place to live in your payment form. Create empty DOM nodes (containers) with unique IDs in your payment form. Additionally, your customer must read and accept the SEPA Direct Debit mandate.

Display the following standard authorization text for your customer to implicitly sign the mandate.

Replace Rocket Rides with your company name.

Authorization text template

By providing your payment information and confirming this payment, you authorise (A) and Stripe, our payment service provider, to send instructions to your bank to debit your account and (B) your bank to debit your account in accordance with those instructions. As part of your rights, you are entitled to a refund from your bank under the terms and conditions of your agreement with your bank. A refund must be claimed within 8 weeks starting from the date on which your account was debited. Your rights are explained in a statement that you can obtain from your bank. You agree to receive notifications for future debits up to 2 days before they occur.

Copy

​​Setting up a payment method creates the accepted mandate. As the customer has implicitly signed the mandate when accepting these terms, you must communicate these terms in your form or through email.

payment_setup.html
<form action="/form" method="post" id="setup-form"> <div class="form-row inline"> <div class="col"> <label for="accountholder-name"> Name </label> <input id="accountholder-name" name="accountholder-name" placeholder="Jenny Rosen" required /> </div> <div class="col"> <label for="email"> Email Address </label> <input id="email" name="email" type="email" placeholder="jenny.rosen@example.com" required /> </div> </div> <div class="form-row"> <!-- Using a label with a for attribute that matches the ID of the Element container enables the Element to automatically gain focus when the customer clicks on the label. --> <label for="iban-element"> IBAN </label> <div id="iban-element"> <!-- A Stripe Element will be inserted here. --> </div> </div> <!-- Add the client_secret from the SetupIntent as a data attribute --> <button id="submit-button" data-secret="{CLIENT_SECRET}"> Set up SEPA Direct Debit </button> <!-- Display mandate acceptance text. --> <div id="mandate-acceptance"> By providing your payment information and confirming this payment, you authorise (A) Rocket Rides and Stripe, our payment service provider and/or PPRO, its local service provider, to send instructions to your bank to debit your account and (B) your bank to debit your account in accordance with those instructions. As part of your rights, you are entitled to a refund from your bank under the terms and conditions of your agreement with your bank. A refund must be claimed within 8 weeks starting from the date on which your account was debited. Your rights are explained in a statement that you can obtain from your bank. You agree to receive notifications for future debits up to 2 days before they occur. </div> <!-- Used to display form errors. --> <div id="error-message" role="alert"></div> </form>

When the form loads, you can create an instance of the IBAN Element and mount it to the Element container:

// Custom styling can be passed to options when creating an Element. const style = { base: { color: '#32325d', fontSize: '16px', '::placeholder': { color: '#aab7c4' }, ':-webkit-autofill': { color: '#32325d', }, }, invalid: { color: '#fa755a', iconColor: '#fa755a', ':-webkit-autofill': { color: '#fa755a', }, }, }; const options = { style, supportedCountries: ['SEPA'], // Elements can use a placeholder as an example IBAN that reflects // the IBAN format of your customer's country. If you know your // customer's country, we recommend passing it to the Element as the // placeholderCountry. placeholderCountry: 'DE', }; // Create an instance of the IBAN Element const iban = elements.create('iban', options); // Add an instance of the IBAN Element into the `iban-element` <div> iban.mount('#iban-element');

Submit the payment method details to Stripe
Client-side

Rather than sending the entire SetupIntent object to the client, use its client secret from step 3. 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 setup. Do not log it, embed it in URLs, or expose it to anyone but the customer.

Use stripe.confirmSepaDebitSetup to complete the setup when the user submits the form. Creating a SEPA Direct Debit PaymentMethod requires that you include the customer’s name and email address in the billing_details property of the payment_method parameter. Additionally, IBANs with the country codes AD, PF, TF, GI, GB, GG, VA, IM, JE, MC, NC, BL, PM, SM, CH, and WF require the country and line1 properties of the billing_details.address property. Listen to the change event of the IBAN element to get the IBAN’s country code.

A successful setup will return a succeeded value for the SetupIntent’s status property. If the setup is not successful, inspect the returned error to determine the cause.

Because customer was set, the PaymentMethod will be attached to the provided Customer object after a successful setup. This allows you to use the stored PaymentMethod to collect future payments without prompting the customer for payment method details.

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', (event) => { event.preventDefault(); stripe.confirmSepaDebitSetup( clientSecret, { payment_method: { sepa_debit: iban, billing_details: { name: accountholderName.value, email: email.value, }, }, } ); });

Test the integration

You can test your form using the IBANs below with your confirmSepaDebitSetup request. The payment method details are successfully collected for each IBAN but exhibit different behaviour when charged.

Test IBANs
Account NumberDescription
AT611904300234573201The PaymentIntent status transitions from processing to succeeded.
AT321904300235473204The PaymentIntent status transitions from processing to succeeded after at least three minutes.
AT861904300235473202The PaymentIntent status transitions from processing to requires_payment_method.
AT051904300235473205The PaymentIntent status transitions from processing to requires_payment_method after at least three minutes.
AT591904300235473203The PaymentIntent status transitions from processing to succeeded, but a dispute is immediately created.
AT981904300000343434The payment fails with a charge_exceeds_source_limit failure code due to payment amount causing account to exceed its weekly payment volume limit.
AT601904300000121212The payment fails with a charge_exceeds_weekly_limit failure code due to payment amount exceeding account's transaction volume limit.
AT981904300002222227The payment fails with an insufficient_funds failure code.

OptionalValidate the IBAN Element

See also

  • Manually configure SEPA Direct Debit as a payment
  • Connect payments
Was this page helpful?
YesNo
Need help? Contact Support.
Join our early access programme.
Check out our changelog.
Questions? Contact Sales.
LLM? Read llms.txt.
Powered by Markdoc