Create account
Sign in
Home
Payments
Business operations
Financial services
Developer tools
Security
All products
Home
Payments
Business operations
Home
Payments
Business operations
Financial services
Developer tools
Support
Overview
Overview
Bank debits
Bank redirects
Bancontact
Accept a payment
Save bank details during payment
Set up future payments
EPS
FPX
giropay
iDEAL
Przelewy24
Sofort
Bank transfers
Buy now pay later
Vouchers
Wallets
Testing
HomePaymentsBank redirectsBancontact

Bancontact payments

Learn how to accept Bancontact, a common payment method in Belgium.

Bancontact with Sources

We recommend using Payment Intents or Checkout to accept Bancontact payments. If you’re using the Sources API, see Bancontact payments with Sources.

Bancontact is a single use payment method where customers are required to authenticate their payment. Customers pay with Bancontact by redirecting from your website, authorizing the payment, then returning to your website where you get immediate notification on whether the payment succeeded or failed.

Your use of Bancontact must be in accordance with our Bancontact Terms of Service.

Set up Stripe
Server-side

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

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

Create a PaymentIntent
Server-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. First, create a PaymentIntent on your server and specify the amount to collect and the eur currency. If you already have an integration using the Payment Intents API, add bancontact to the list of payment method types for your PaymentIntent.

Terminal
curl https://api.stripe.com/v1/payment_intents \ -u
sk_test_4eC39HqLyjWDarjtT1zdp7dc
: \ -d "amount"=1099 \ -d "currency"="eur" \ -d "payment_method_types[]"="bancontact"

The default language setting of the Bancontact authorization page is English (en). However, you can customize it to match the preferred language of your customer by setting the value of the preferred_language property in the request to fr, nl, or de.

Terminal
curl https://api.stripe.com/v1/payment_intents \ -u
sk_test_4eC39HqLyjWDarjtT1zdp7dc
: \ -d "amount"=1099 \ -d "currency"="eur" \ -d "payment_method_types[]"="bancontact" \ -d "payment_method_options[bancontact][preferred_language]"="fr"

Included in the returned PaymentIntent is a client secret, which is used on the client side to securely complete the payment process instead of passing the entire PaymentIntent object. There are different approaches that you can use to pass the client secret to the client side.

You can retrieve the client secret from an endpoint on your server using the browser’s fetch function on the client side. This approach is generally most suitable when your client side is a single-page application, particularly one built with a modern frontend framework such as React. This example shows how to create the server endpoint that serves the client secret:

main.rb
get '/secret' do intent = # ... Create or retrieve the PaymentIntent {client_secret: intent.client_secret}.to_json end

This example demonstrates how to fetch the client secret with JavaScript on the client side:

var response = fetch('/secret').then(function(response) { return response.json(); }).then(function(responseJson) { var clientSecret = responseJson.client_secret; // Call stripe.confirmBancontactPayment() with the client secret. });

Collect payment method details
Client-side

Create a payment form on your client to collect the required billing details from the customer:

FieldValue
nameThe full name (first and last) of the customer.
checkout.html
<form id="payment-form"> <div class="form-row"> <label for="name"> Name </label> <input id="name" name="name" required> </div> <!-- Used to display form errors. --> <div id="error-message" role="alert"></div> <button id="submit-button">Pay with Bancontact</button> </form>

Submit the payment to Stripe
Client-side

To create a payment on the client side, pass the client secret of the PaymentIntent object that you created in Step 2.

The client secret is different from your API keys that authenticate Stripe API requests. It 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.

When a customer clicks to pay with Bancontact, 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 complexities like the redirect described below, 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/account/apikeys var stripe = Stripe(
'pk_test_TYooMQauvdEDq54NiTphI7jx'
);

Confirm Bancontact payment

Use stripe.confirmBancontactPayment to handle the redirect away from your page and to complete the payment. Add a return_url to this function to indicate where Stripe should redirect the user to after they complete the payment on Bancontact’s website or mobile application. You must also provide the user’s full name in the billing_details hash.

client.js
var stripe = Stripe(
'pk_test_TYooMQauvdEDq54NiTphI7jx'
); // Redirects away from the client stripe.confirmBancontactPayment( '{{PAYMENT_INTENT_CLIENT_SECRET}}', { payment_method: { billing_details: { name: "Jenny Rosen" } }, return_url: 'https://your-website.com/checkout/complete', } ).then(function(result) { if (result.error) { // Inform the customer that there was an error. } });

Handling the redirect

The following URL query parameters are provided when Stripe redirects the customer to the return_url.

ParameterDescription
payment_intentThe unique identifier for the PaymentIntent.
payment_intent_client_secretThe client secret of the PaymentIntent object.

You may also append your own query parameters when providing the return_url. They will persist through the redirect process.

The return_url should correspond to a page on your website that provides the status of the payment. You should verify the status of the PaymentIntent when rendering the return page. You can do so by using the retrievePaymentIntent function from Stripe.js and passing in the payment_intent_client_secret.

var url = new URL(window.location); var clientSecret = url.searchParams.get('payment_intent_client_secret'); stripe.retrievePaymentIntent(clientSecret).then(function(response) { if (response.error) { // Handle error here } else if (response.paymentIntent && response.paymentIntent.status === 'succeeded') { // Handle successful payment here } });

Bank account details

You can find details about the bank account the customer used to complete the payment on the resulting Charge under the payment_method_details property.

{ "charges": { "data": [ { "payment_method_details": { "bancontact": { "bank_code": "VAPE", "bank_name": "VAN DE PUT & CO", "bics": "VAPEBE22", "iban_last4": "7061", "preferred_language": "en", "verified_name": "Jenny Rosen" }, "type": "bancontact" }, "id": "src_16xhynE8WzK49JbAs9M21jaR", "object": "source",

Handle post-payment events

Stripe sends a payment_intent.succeeded event when the payment completes. Use the Dashboard, a custom webhook, or a partner solution to receive these events and run actions, like sending an order confirmation email to your customer, logging the sale in a database, or starting a shipping workflow.

Listen for these events rather than waiting on a callback from the client. On the client, the customer could close the browser window or quit the app before the callback executes. Setting up your integration to listen for asynchronous events also makes it easier to accept more payment methods in the future. Check out our guide to payment methods to see the differences between all supported payment methods.

Manually

Use the Stripe Dashboard to view all your Stripe payments, send email receipts, handle payouts, or retry failed payments.

  • View your test payments in the Dashboard

Custom code

Build a webhook handler to listen for events and build custom asynchronous payment flows. Test and debug your webhook integration locally with the Stripe CLI.

  • Build a custom webhook

Prebuilt apps

Handle common business events, like shipping and inventory management, by integrating a partner application.

  • Browse shipping apps and extensions
  • Browse inventory management apps and extensions
  • See all partner solutions

Handle the Bancontact redirect manually

We recommend relying on Stripe.js to handle Bancontact redirects and payments client-side with confirmBancontactPayment. Using Stripe.js makes it much easier to extend your integration to other payment methods. However, you can also manually redirect your customers on your server by following these steps:

  1. Create and confirm a PaymentIntent of type bancontact. You must provide the payment_method_data.billing_details.name property, which you should collect from your customer. Note that, by specifying payment_method_data, a PaymentMethod is created and immediately used with this PaymentIntent. You must also provide the URL where your customer is redirected to after they complete their payment in the return_url field. You may optionally provide your own query parameters in this URL. These parameters will be included in the final URL upon completing the redirect flow.
# Set your secret key. Remember to switch to your live secret key in production. # See your keys here: https://dashboard.stripe.com/account/apikeys Stripe.api_key =
"sk_test_4eC39HqLyjWDarjtT1zdp7dc"
payment_intent = Stripe::PaymentIntent.create({ confirm: true, amount: 1099, currency: 'eur', payment_method_types: ['bancontact'], payment_method_data: { type: 'bancontact', billing_details: { name: 'Jenny Rosen', }, }, return_url: 'https://your-website.com/checkout/complete', })
  1. Check that the PaymentIntent has a status of requires_action and the type for next_action is redirect_to_url.
{ "status": "requires_action", "next_action": { "type": "redirect_to_url", "redirect_to_url": { "url": "https://hooks.stripe.com/...", "return_url": "https://your-website.com/checkout/complete" } }, "id": "pi_1G1sgdKi6xqXeNtkldRRE6HT", "object": "payment_intent", "amount": 1099,
  1. Redirect the customer to the URL provided in the next_action.redirect_to_url.url property. The code example here is approximate—the redirect method may be different in your web framework.
if payment_intent.status == 'requires_action' && payment_intent.next_action.type == 'redirect_to_url' url = payment_intent.next_action.redirect_to_url.url redirect(url) end

When the customer finishes the payment process, they are sent to the return_url configured in step 1. The payment_intent and payment_intent_client_secret URL query parameters are included and you may pass through your own query parameters, as described above.

We recommend that you rely on webhooks to confirm the status of a payment.

Was this page helpful?
Questions? Contact us.
Developer tutorials on YouTube.
You can unsubscribe at any time. Read our privacy policy.
On this page
Set up Stripe
Create a PaymentIntent
Collect payment method details
Submit the payment to Stripe
Handle post-payment events
Handle the Bancontact redirect manually