PayPal
Vault
Vaulting a PayPal account will allow you to charge the account in the future without requiring your customer to be present during the transaction or re-authenticate with PayPal when they are present during the transaction.
The vaulted payment flow supports the following features:
- Select or add shipping addresses in the PayPal account
- Select or add funding instruments in the PayPal account
- Two factor authentication support (currently only for US, UK, CA, DE, AT, and AU)
Typical use cases for the vaulted payment flow:
- Faster payments for repeat customers
- Subscriptions
- Recurring billing (e.g. automatic top-up or usage based charges)
Invoking the Vault flow
An integration with our Vault would typically be used in conjunction with your standard Checkout flow. The only differences are how the PayPal JS SDK is loaded and the options you provide when tokenizing with the PayPal Checkout component.
Enable the Vault flow by setting the flow
option to 'vault'
and passing vault: true
in the loadPayPalSDK
method and using a createBillingAgreement
function to create the payment resource:
- Callback
- Promise
// Create a PayPal Checkout component
// 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 PayPal Checkout component.
braintree.paypalCheckout.create({
client: clientInstance
}, function (paypalCheckoutErr, paypalCheckoutInstance) {
paypalCheckoutInstance.loadPayPalSDK({
vault: true
}, function () {
paypal.Buttons({
fundingSource: paypal.FUNDING.PAYPAL,
createBillingAgreement: function () {
return paypalCheckoutInstance.createPayment({
flow: 'vault', // Required
// The following are optional params
billingAgreementDescription: 'Your agreement description',
enableShippingAddress: true,
shippingAddressEditable: false,
shippingAddressOverride: {
recipientName: 'Scruff McGruff',
line1: '1234 Main St.',
line2: 'Unit 1',
city: 'Chicago',
countryCode: 'US',
postalCode: '60652',
state: 'IL',
phone: '123.456.7890'
}
});
},
onShippingChange: function (data, actions) {
// Perform some validation or calculation logic on 'data'
if ( /* need to update shipping options or lineItems */ ) {
return paypalCheckoutInstance.updatePayment({
amount: 10.00, // Required
currency: 'USD',
lineItems: [...], // Required
paymentId: data.paymentId, // Required
shippingOptions: [...], // Optional
});
} else if (/* address not supported */) {
return actions.reject();
}
return actions.resolve();
},
onApprove: function (data, actions) {
return paypalCheckoutInstance.tokenizePayment(data, function (err, payload) {
// Submit 'payload.nonce' to your server
});
},
onCancel: function (data) {
console.log('PayPal payment canceled', JSON.stringify(data, 0, 2));
},
onError: function (err) {
console.error('PayPal error', err);
}
}).render('#paypal-button').then(function () {
// The PayPal button will be rendered in an html element with the ID
// 'paypal-button'. This function will be called when the PayPal button
// is set up and ready to be used
});
});
});
});
Use the onShippingChange
function from the PayPal JS SDK setup method to listen for shipping changes that occur within the PayPal pop-up; then, use the updatePayment
function , part of the Braintree JS SDK's paypalCheckoutInstance
, to update the PayPal checkout flow with modified order line items or shipping options. Note that updatePayment
replaces use of actions.order.patch
.
Use the paypalCheckoutInstance
in the onApprove
function of the PayPal JS SDK setup method to tokenize the PayPal account. After the customer completes the consent flow and the PayPal pop-up closes, successful tokenization will return a payment method nonce.
Send the nonce to your server and use a Braintree server SDK to call PaymentMethod.create
, which creates a PayPal payment method in your Vault. Alternatively, use Transaction.sale
to create a transaction.
Collecting device data
Collecting device data from your customers is required when initiating non-recurring transactions from Vault records. Collecting and passing this data with transactions will help reduce decline rates.
To collect device data for PayPal, use the dataCollector
component. If you're using script
tags to load files, make sure to include:
- HTML
<script src="https://js.braintreegateway.com/web/3.111.0/js/data-collector.min.js"></script>
- Callback
- Promise
var myDeviceData;
braintree.client.create({
authorization: 'TOKEN',
}, function (err, clientInstance) {
braintree.dataCollector.create({
client: clientInstance,
}, function (err, dataCollectorInstance) {
if (err) {
// Handle error
return;
}
// At this point, you should access the dataCollectorInstance.deviceData value and provide it
// to your server, e.g. by injecting it into your form as a hidden input
myDeviceData = dataCollectorInstance.deviceData;
});
// Initialize your PayPal Checkout component here
braintree.paypalCheckout.create(/* ... */);
});
To cleanly reset your integration, call teardown()
on the dataCollectorInstance
object.
- JavaScript
dataCollectorInstance.teardown();
Returning customer experience
This allows customers the flexibility to change the payment method that they had previously selected within the PayPal Wallet when storing it within a vault.
Customers can choose to change the payment method by clicking on the PayPal button as seen below and clicking the link Change payment method
.
The PayPal button can be rendered as a Change payment method
button for vaulted customers.
- Be sure to use the Checkout flow instead of the Vault flow
- Use a client token generated with a customer ID that has a vaulted PayPal Billing Agreement when initializing the Braintree client instance
- Set
autoSetDataUserIdToken: true
when initializing the Braintree PayPal Checkout instance - Optionally set additional
dataAttributes
, such as amount, when using the Braintree PayPal Checkout instance to load the PayPal SDK. For details, see the PayPal docs.
- Callback
- Promise
// Create a client.
braintree.client.create({
authorization: CLIENT_TOKEN_ENCODED_WITH_CUSTOMER_ID
}, function (clientErr, clientInstance) {
// Create a PayPal Checkout component.
braintree.paypalCheckout.create({
autoSetDataUserIdToken: true,
client: clientInstance
}, function (paypalCheckoutErr, paypalCheckoutInstance) {
paypalCheckoutInstance.loadPayPalSDK({
// The following are optional params
dataAttributes: {
amount: "100.00"
}
}, function () {
paypal.Buttons({
fundingSource: paypal.FUNDING.PAYPAL,
createOrder: function () {
return paypalCheckoutInstance.createPayment({
//...
});
},
onApprove: function (data, actions) {
return paypalCheckoutInstance.tokenizePayment(data, function (err, payload) {
// Submit 'payload.nonce' to your server
});
},
onCancel: function (data) {
console.log('PayPal payment canceled', JSON.stringify(data, 0, 2));
},
onError: function (err) {
console.error('PayPal error', err);
}
}).render('#paypal-button').then(function () {
// The PayPal button will be rendered in an html element with the ID
// 'paypal-button'. This function will be called when the PayPal button
// is set up and ready to be used
});
});
});
});
Country and language support
The Vault flow is available to merchants in all countries that we support. The language in the UI will automatically adjust based on the customer's country.
Currency presentment
In the Vault flow itself, the transaction currency and amount are not displayed to the customer. It is up to you to display these details in your checkout flow somewhere (e.g. cart page, order review page, etc.). Our Server-Side guide outlines which currencies are supported for PayPal transactions.
Next Page: Server-side →