Local Payment Methods
Client-Side Implementation
Browser support
Learn more about browser support for v3 of our JavaScript SDK.
Basic configuration
Determine which merchant account to use
This will determine which PayPal credentials are used for the transaction, and must match the merchant account specified with any other calls in the transaction lifecycle (e.g. Transaction.sale). Many merchants use a separate merchant account for local payments. Other merchants use separate merchant accounts for transactions in different currencies. It is not possible to switch merchant accounts between the start and finish of a local payment transaction, so it is important to determine the correct one from the start.
- Javascript
function merchantAccountId() {
return("EUR_local");
}
Load the component
If you're using <script>
tags to load files, be sure to at least include:
- HTML
<script src="https://js.braintreegateway.com/web/3.103.0/js/client.min.js"></script>
<script src="https://js.braintreegateway.com/web/3.103.0/js/local-payment.min.js"></script>
Initialize the component
Every integration requires a client
. Once you've created one, you can pass it to the local payment component to accept your payments.
- Callback
- Promise
var localPaymentInstance;
// Create a client.
braintree.client.create({
authorization: CLIENT_AUTHORIZATION
}, function (clientErr, clientInstance) {
// Stop if there was a problem creating the client.
// This could happen if there is a network error or if the authorization
// is invalid.
if (clientErr) {
console.error('Error creating client:', clientErr);
return;
}
// Create a local payment component.
braintree.localPayment.create({
client: clientInstance,
merchantAccountId: merchantAccountId()
}, function (localPaymentErr, paymentInstance) {
// Stop if there was a problem creating local payment component.
// This could happen if there was a network error or if it's incorrectly
// configured.
if (localPaymentErr) {
console.error('Error creating local payment:', localPaymentErr);
return;
}
localPaymentInstance = paymentInstance;
});
});
Render Local Payment Method buttons
You will need to render and style a button for each payment method you intend to support.
- HTML
<button id="ideal-button">
<img src="img/ideal.png" class="payment-button" />
</button>
<button id="sofort-button">
<img src="img/sofort.png" class="payment-button" />
</button>
Use the local payment component to attach a listener to your buttons to begin the payment flow.
- Javascript
var idealButton = document.getElementById('ideal-button');
var sofortButton = document.getElementById('sofort-button');
The following is a list of valid paymentType
, countryCode
, and currencyCode
values for each Local Payment Method:
Local Payment Method | Payment type | Country codes | Currency codes |
---|---|---|---|
Bancontact | bancontact |
BE |
EUR |
BLIK | blik |
PL |
PLN |
EPS | eps |
AT |
`EUR |
grabpay | grabpay |
SG |
SGD |
iDEAL | ideal |
NL |
EUR |
Klarna Pay Now / SOFORT | sofort |
AT , BE , DE , IT , NL , ES , GB |
EUR (outside GB ), GBP (GB only) |
MyBank | mybank |
IT |
EUR |
Pay Upon Invoice | pay_upon_invoice |
DE |
EUR |
P24 | p24 |
PL |
EUR , PLN |
The paymentTypeCountryCode
parameter is only required for payment methods with multiple potential country codes. If a paymentTypeCountryCode
is not provided, then the countryCode
value will be used as the paymentTypeCountryCode
.
The following is a list of required parameters for each Local Payment Method, as well as any applicable transaction limits:
Local Payment Method | Required parameters | Customer transaction limits |
---|---|---|
Bancontact | givenName , surname , currencyCode |
Min: 1.00 EUR |
BLIK | givenName , surname , currencyCode , email |
Min: 1.00 PLN |
EPS | givenName , surname , currencyCode |
Min: 1.00 EUR |
grabpay | givenName , surname , currencyCode |
Min: 1.00 SGD |
iDEAL | givenName , surname , currencyCode |
N/A |
Klarna Pay Now / SOFORT | givenName , surname , currencyCode , countryCode , paymentTypeCountryCode |
Min: 1.00 EUR (outside the United Kingdom), 1.00 GBP (United Kingdom only) |
MyBank | givenName , surname , currencyCode |
N/A |
Pay Upon Invoice | givenName , surname , currencyCode , address , email , billingAddress , birthDate , phone , phoneCountryCode |
Min: 5.00 EUR |
P24 | givenName , surname , currencyCode , email |
Min: 1.00 PLN |
The following is a list of business identification numbers (bic
) you can optionally include to identify the specific bank when processing iDEAL
as a payment payment method:
Bank | BIC |
---|---|
Rabobank | RABONL2U |
ABN AMRO | ABNANL2A |
Van Lanschot Bankiers | FVLBNL22 |
Triodos Bank | TRIONL2U |
ING Bank | INGBNL2A |
SNS Bank | SNSBNL2A |
ASN | ASNBNL21 |
RegioBank | RBRBNL21 |
Knab | KNABNL2H |
Bunq | BUNQNL2A |
Yoursafe | BITSNL2A |
N26 Bank | NTSBDEB1 |
Invoke local payment flow
You must implement the startPayment
method for preprocessing and result handling.
- Callback
- Promise
function createLocalPaymentClickListener(type) {
return function (event) {
event.preventDefault();
localPaymentInstance.startPayment({
paymentType: type,
amount: '10.67',
fallback: { // see Fallback section for details on these params
url: 'https://your-domain.com/page-to-complete-checkout',
buttonText: 'Complete Payment'
},
currencyCode: 'EUR',
givenName: 'Joe',
surname: 'Doe',
address: {
countryCode: 'NL'
},
onPaymentStart: function (data, start) {
// NOTE: It is critical here to store data.paymentId on your server
// so it can be mapped to a webhook sent by Braintree once the
// buyer completes their payment. See Start the payment
// section for details.
// Call start to initiate the popup
start();
}
}, function (startPaymentError, payload) {
if (startPaymentError) {
if (startPaymentError.code === 'LOCAL_PAYMENT_POPUP_CLOSED') {
console.error('Customer closed Local Payment popup.');
} else {
console.error('Error!', startPaymentError);
}
} else {
// Send the nonce to your server to create a transaction
console.log(payload.nonce);
}
});
};
}
idealButton.addEventListener('click', createLocalPaymentClickListener('ideal'));
sofortButton.addEventListener('click', createLocalPaymentClickListener('sofort'));
Start the payment
Before starting the payment flow for the buyer, you must store the paymentId
provided in the data
object in the onPaymentStart
method. This identifier is critical for handling a case where the buyer completes the payment flow with their bank and exits that flow without returning to your checkout page. Braintree recommends that you store the paymentId
and map it to a shopping cart identifier or some other form of identifier. This information will be necessary when Braintree sends you a webhook of a completed payment.
See the Local Payment Method webhooks reference for details on the exact content of the Local Payment Method completed notification.
Fallback
If a customer is using a mobile device and has a mobile app to process their payment, the window will automatically redirect to the mobile app. The app will then open up a new window that is unable to communicate with the original page that started the flow. Because of this, you must configure a fallback URL and button text, which will be used to create a button in the window created by the mobile app to redirect back to your website.
- Callback
localPaymentInstance.startPayment({
fallback: {
url: 'https://your-domain.com/page-to-complete-checkout', // the page to go to on completion of the flow
buttonText: 'Complete Payment' // the text to put into the button to trigger the redirect
},
// etc
The URL you configure will automatically have query parameters added to it that will be used to complete the payment. On the page you configure, set up the localPaymentInstance
and call tokenize:
- Callback
- Promise
braintree.client.create({
authorization: CLIENT_AUTHORIZATION
}, function (clientErr, clientInstance) {
braintree.localPayment.create({
client: clientInstance
}, function (localPaymentErr, localPaymentInstance) {
if (localPaymentInstance.hasTokenizationParams()) {
localPaymentInstance.tokenize(function (tokenizeError, payload) {
if (tokenizeError) {
// handle tokenization error
}
// send payload.nonce to your server
});
} else {
// if this page should only be reached when
// recovering from a mobile app switch,
// display an error for not having the
// correct params in the query string
}
});
});
Shipping addresses
If you need a shipping address to ship physical goods, set shippingAddressRequired
to true
. This setting will prompt your customer to provide shipping details. If you have already collected these details from your customer, you can pass the shipping details within the startPayment
method to avoid having your customer provide them again.
- Callback
- Promise
function createLocalPaymentClickListener(type) {
return function (event) {
event.preventDefault();
localPaymentInstance.startPayment({
paymentType: type,
amount: '10.67',
fallback: { // see Fallback section for details on these params
url: 'https://your-domain.com/page-to-complete-checkout',
buttonText: 'Complete Payment'
},
currencyCode: 'EUR',
shippingAddressRequired: true,
email: 'joe@getbraintree.com',
phone: '5101231234',
givenName: 'Joe',
surname: 'Doe',
address: {
streetAddress: 'Oosterdoksstraat 110',
extendedAddress: 'Apt. B',
locality: 'DK Amsterdam',
postalCode: '1011',
region: 'NH',
countryCode: 'NL'
},
onPaymentStart: function (data, start) {
// NOTE: It is critical here to store data.paymentId on your server
// so it can be mapped to a webhook sent by Braintree once the
// buyer completes their payment. See Start the payment
// section for details.
// Call start to initiate the popup
start();
}
}, function (startPaymentError, payload) {
if (startPaymentError) {
if (startPaymentError.code === 'LOCAL_PAYMENT_POPUP_CLOSED') {
console.error('Customer closed Local Payment popup.');
} else {
console.error('Error!', startPaymentError);
}
} else {
// Send the nonce to your server to create a transaction
console.log(payload.nonce);
}
});
};
}
idealButton.addEventListener('click', createLocalPaymentClickListener('ideal'));
sofortButton.addEventListener('click', createLocalPaymentClickListener('sofort'));
If you are not shipping physical goods, set shippingAddressRequired
to false
. This setting will prompt your customer to provide just the basic information like givenName
, surname
, phone
, and email
. If you have already collected these details from your customer, you can pass them within the startPayment
method to avoid having your customer provide them again.
- Callback
- Promise
function createLocalPaymentClickListener(type) {
return function (event) {
event.preventDefault();
localPaymentInstance.startPayment({
paymentType: type,
amount: '10.67',
fallback: { // see Fallback section for details on these params
url: 'https://your-domain.com/page-to-complete-checkout',
buttonText: 'Complete Payment'
},
currencyCode: 'EUR',
shippingAddressRequired: false,
email: 'joe@getbraintree.com',
phone: '5101231234',
givenName: 'Joe',
surname: 'Doe',
address: {
countryCode: 'NL'
},
onPaymentStart: function (data, start) {
// NOTE: It is critical here to store data.paymentId on your server
// so it can be mapped to a webhook sent by Braintree once the
// buyer completes their payment. See Start the payment
// section for details.
// Call start to initiate the popup
start();
}
}, function (startPaymentError, payload) {
if (startPaymentError) {
if (startPaymentError.code === 'LOCAL_PAYMENT_POPUP_CLOSED') {
console.error('Customer closed Local Payment popup.');
} else {
console.error('Error!', startPaymentError);
}
} else {
// Send the nonce to your server to create a transaction
console.log(payload.nonce);
}
});
};
}
idealButton.addEventListener('click', createLocalPaymentClickListener('ideal'));
sofortButton.addEventListener('click', createLocalPaymentClickListener('sofort'));
Next Page: Server-side →