Returning buyer integration (SDK)
Last updated: Sept 23rd, 9:45pm
Enhance your existing PayPal billing agreement SDK integration for returning buyers.
On this page
- On this page
- Know before you code
- 1. Generate ID token
- 2. Add the SDK and buttons
- 3. Render the button
- 4. Set up a transaction or create an order
- 5. Buyer approval
Know before you code
Make sure you complete or have the following before you begin:
- Complete the steps in Get started to get the following sandbox account information from the Developer Dashboard:
- Get API Credentials (Client ID and Secret)
- Exchange your API credentials for an access token
- Make sure you have the ability to identify the buyers who come to your website.
- Make sure you are enabled to create and process payments using billing agreements.
1. Generate ID token
Generate an ID token for your buyer.
Pass the billing agreement ID to PayPal to generate an ID token. The ID token is a unique ID for each billing agreement ID that's created.
Sample client token request
1curl -v POST https://api-m.sandbox.paypal.com/v1/identity/generate-token \2 -H 'Accept: application/json' \3 -H 'Accept-Language: en_US' \4 -H 'Authorization: Bearer <ACCESS-TOKEN>' \5 -H 'Content-Type: application/json' \6 -d '{7 "billing_agreement_id": "B-XXXXXXXXXXXX"8 }'
Modify the code
- Copy the sample request code.
- Change the access token to your sandbox access token.
- Replace B-XXXXXXXXXXXX with the billing agreement ID created for that particular buyer.
Sample client token response
1{2 "client_token": "eyJicmFpbnRyZWUiOnsiYXV0aG9yaXphdGlvbkZpbmdlcnByaW50IjoiYTI1ZjhmYTUwYjc2NmY1YTg2ZjUwOGY1NDgxNWIxNGIyYjNkYjk1MzQ0ZjMyNjAwOWI5NmQ3YjFlOTAzZGNiNHxtZXJjaGFudF9pZD1yd3dua3FnMnhnNTZobTJuJnB1YmxpY19rZXk9NjNrdm4zN3Z0MjlxYjRkZiZjcmVhdGVkX2F0PTIwMjEtMDgtMjVUMDg6MzQ6MzAuMzg2WiZjdXN0b21lcl9pZD1jdXN0b21lcl81NzgwNDI1MjkiLCJ2ZXJzaW9uIjoiMy1wYXlwYWwifSwicGF5cGFsIjp7ImlkVG9rZW4iOiJleUpyYVdRaU9pSmxOREEyTmpBNFlqVTBZVGswTkRneFlqazFZemMxTkRJME9HTmpNVEl6WmlJc0luUjVjQ0k2SWtwWFZDSXNJbUZzWnlJNklsSlRNalUySW4wLmV5SnBjM01pT2lKb2RIUndjem92TDJGd2FTNXpZVzVrWW05NExuQmhlWEJoYkM1amIyMGlMQ0p5YjJ4bElqb2lUVVZTUTBoQlRsUWlMQ0psZUhSbGNtNWhiRjlwWkNJNld5SlFZWGxRWVd3Nk9FZEhPVXRWVWtRMVFVTlpNaUpkTENKelpYTnphVzl1WDJsdVpHVjRJam9pVTJwNGFYZ3hTMDloVW1SNGNtbFhNWGgwV0RWamRWZHhUalZwSWl3aVkyeHBaVzUwWDJsa0lqb2lRV1F3YlZFeGNFSm1kbkEwYlc5Q01qQlNaMFJrTlZadVZtVktWR2h6YVdSbFMwNVNWemQ0TmtJM1oxY3hNMlk0U0docFUyNXlOSEJIYVVSek4wOVhjakJIU1VwYVgwOVFRVW90VTJNeVNVZ2lMQ0poWTNJaU9sc2lZMnhwWlc1MElsMHNJbUYxWkNJNklrRmtNRzFSTVhCQ1puWndORzF2UWpJd1VtZEVaRFZXYmxabFNsUm9jMmxrWlV0T1VsYzNlRFpDTjJkWE1UTm1PRWhvYVZOdWNqUndSMmxFY3pkUFYzSXdSMGxLV2w5UFVFRktMVk5qTWtsSUlpd2lZWFYwYUY5MGFXMWxJam94TmpJNU9EZ3dORGN3TENKdmNIUnBiMjV6SWpwN0ltTjFjM1J2YldWeVgybGtJam9pWTNWemRHOXRaWEpmTlRjNE1EUXlOVEk1SW4wc0ltRjZJam9pWjJOd0xuTnNZeUlzSW5OamIzQmxjeUk2V3lKQ2NtRnBiblJ5WldVNlZtRjFiSFFpTENKUVlYbHdZV3c2YjI1bFgzUnBiV1ZmY0dGNWJXVnVkQ0pkTENKbGVIQWlPakUyTWprNE9ERXpOekFzSW1saGRDSTZNVFl5T1RnNE1EUTNNQ3dpYW5ScElqb2lWVEpCUVVwM1dYYzVSV2t5YWkwME1qUmZOakl6ZGtsTVpEVlZNMWRLVFcxcFVucHVUMXB0UmsxNGVEaHBZak4xY3pkWFVEa3hXVVpTZW1KUFFqRk9hVUpMYkhrdFRHMXJOemRzWDJaNGJXRmhOV0ZsUnpoU2NHeHlUMVYwWW0xclUwWjBMVWhVYmtKT1IzWnVUWFJQUTBkNFVHSkpXRFJVY0hkbGJFaHhWbEVpZlEuSXlrTktCZ2c5RWtGaFJ5TC0yT3hnTUswb0p6Y09XazYwaEpORS03Qm5vdkI3RURTS18tNkM1RmtDZUpqamk1YjB5TjM1S3RaeHNnWFZlT2VVSkozd240THI0UTZ1LWIxRV9kOFpjb04tZDRZa2FXd0tKVnhYWFR5NVI1NGJLRXdWWjBLZXI0WGdXM3NFWnhGNnFiaktrbmQtNnJWVjNkTFZDU1ZtUEk1a29TMFRQTXp1OGI4QjBTX2JfUldCbXhSRUNJV0lEVGZGdGxqZnA0SWp0czhJeDFBa1dxMXRsR21qcUtDdmpMTTBnakszeExndjBfUlNzRkcxX3BxNEhzUWRKc1JmeDg2TUw5R3h1ZlZFSk1NV0FoZDhfbDlGSmUtQ3N0TU4weVR5RUZaeEljWUIwSk53d1lWbWowSGtKdGR2bHJPdDhuX3N6RmdBNVByYm1YZW93IiwiYWNjZXNzVG9rZW4iOiJBMjFBQUpDY2NvNmhMRzBIQi1SeHh4Zy1Tb3F2Qjg4RUFPQjVJZGFjX05VQlZac0VrVGhOZ0dUSzc2RDlrRHZhZVE3bzNRbFY3OWJYS0M5VUVMTDk0eVhwV19KUXgyQ3BBIn19",3 "id_token": "eyJraWQiOiJlNDA2NjA4YjU0YTk0NDgxYjk1Yzc1NDI0OGNjMTIzZiIsInR5cCI6IkpXVCIsImFsZyI6IlJTMjU2In0.eyJpc3MiOiJodHRwczovL2FwaS5zYW5kYm94LnBheXBhbC5jb20iLCJyb2xlIjoiTUVSQ0hBTlQiLCJleHRlcm5hbF9pZCI6WyJQYXlQYWw6OEdHOUtVUkQ1QUNZMiJdLCJzZXNzaW9uX2luZGV4IjoiU2p4aXgxS09hUmR4cmlXMXh0WDVjdVdxTjVpIiwiY2xpZW50X2lkIjoiQWQwbVExcEJmdnA0bW9CMjBSZ0RkNVZuVmVKVGhzaWRlS05SVzd4NkI3Z1cxM2Y4SGhpU25yNHBHaURzN09XcjBHSUpaX09QQUotU2MySUgiLCJhY3IiOlsiY2xpZW50Il0sImF1ZCI6IkFkMG1RMXBCZnZwNG1vQjIwUmdEZDVWblZlSlRoc2lkZUtOUlc3eDZCN2dXMTNmOEhoaVNucjRwR2lEczdPV3IwR0lKWl9PUEFKLVNjMklIIiwiYXV0aF90aW1lIjoxNjI5ODgwNDcwLCJvcHRpb25zIjp7ImN1c3RvbWVyX2lkIjoiY3VzdG9tZXJfNTc4MDQyNTI5In0sImF6IjoiZ2NwLnNsYyIsInNjb3BlcyI6WyJCcmFpbnRyZWU6VmF1bHQiLCJQYXlwYWw6b25lX3RpbWVfcGF5bWVudCJdLCJleHAiOjE2Mjk4ODEzNzAsImlhdCI6MTYyOTg4MDQ3MCwianRpIjoiVTJBQUp3WXc5RWkyai00MjRfNjIzdklMZDVVM1dKTW1pUnpuT1ptRk14eDhpYjN1czdXUDkxWUZSemJPQjFOaUJLbHktTG1rNzdsX2Z4bWFhNWFlRzhScGxyT1V0Ym1rU0Z0LUhUbkJOR3ZuTXRPQ0d4UGJJWDRUcHdlbEhxVlEifQ.IykNKBgg9EkFhRyL-2OxgMK0oJzcOWk60hJNE-7BnovB7EDSK_-6C5FkCeJjji5b0yN35KtZxsgXVeOeUJJ3wn4Lr4Q6u-b1E_d8ZcoN-d4YkaWwKJVxXXTy5R54bKEwVZ0Ker4XgW3sEZxF6qbjKknd-6rVV3dLVCSVmPI5koS0TPMzu8b8B0S_b_RWBmxRECIWIDTfFtljfp4Ijts8Ix1AkWq1tlGmjqKCvjLM0gjK3xLgv0_RSsFG1_pq4HsQdJsRfx86ML9GxufVEJMMWAhd8_l9FJe-CstMN0yTyEFZxIcYB0JNwwYVmj0HkJtdvlrOt8n_szFgA5PrbmXeow",4 "expires_in": 36005}
2. Add the SDK and buttons
Add the JavaScript SDK and payment buttons to your page.
Copy the sample JavaScript SDK code and paste it into the code of your checkout page or any other page where you want to render the buttons.
1<!DOCTYPE html>2<html>3 <head>4 <meta name="viewport" content="width=device-width, initial-scale=1"> <!-- Ensures optimal rendering on mobile devices. -->5 <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <!-- Optimal Internet Explorer compatibility -->6 </head>7 <body>8 <script src="https://www.paypal.com/sdk/js?client-id=YOUR_CLIENT_ID¤cy=CURRENCY&intent=capture&commit=false" data-user-id-token=YOUR_ID_TOKEN> // Replace YOUR_CLIENT_ID with your sandbox client ID9 </script>10 <div id="paypal-button-container"></div>11 </body>12</html>
Modify the code
Update the script tag to pass the required parameters for your integration:
- In the SDK code, replace
YOUR_CLIENT_IDwith your client ID. - In the SDK code, replace
YOUR_ID_TOKENwith your ID token.
To customize the intent, currency, commit, vault, and locale values, see the JavaScript SDK reference.
3. Render the button
Tell the SDK how to render button and what action to take.
Sample code
1paypal.Buttons({2// More code to be added here3}).render('#paypal-button-container');
4. Set up a transaction or create an order
Note: Make sure you're on version 62 or higher of the NVP/SOAP APIs to integrate Pay Later offers.
Tell the SDK how to setup a transaction or create an order.
After your buyer logs in to PayPal and authorizes the transaction successfully, the script calls the onApprove() function that you defined. This function finalizes the transaction. Otherwise, it calls onError().
When your buyer selects the PayPal button, the script calls a createOrder() function that you can define. In this function, return a promise for a token, payment ID, or order ID, from the PayPal API that you're calling.
Return the token value from an NVP/SOAP SetExpressCheckout response to the client. Then, return that token in the createOrder function:
1paypal.Buttons({2 createOrder: function() {3 var SETEC_URL = 'https://mystore.com/api/set-express-checkout';45 return fetch(SETEC_URL, {6 method: 'post',7 headers: {8 'content-type': 'application/json'9 }10 }).then(function(res) {11 return res.json();12 }).then(function(data) {13 return data.token;14 });15 }16}).render('#paypal-button-container');
- Make sure the amount is greater than zero.
- The SetExpressCheckout call should not contain any references to billing agreement parameter such as
L_BILLINGTYPEn. - Add
NOSHIPPING=1if no shipping address is required to be passed during a transaction, or addNOSHIPPING=0andADDROVERRIDE=1if the shipping address must be passed along with the shipping address (using the shipping address fields in SetExpressCheckout). - Because the JavaScript SDK does not use the
RETURNURLandCANCELURLvalues in the NVP/SOAP API, pass https://www.paypal.com/checkoutnow/error as a placeholder value for these keys. - To handle transaction success or failure, use onApprove, onCancel, and onError by using
actions.redirect(‘/desired-page'). - For a returning buyer, you don't need to get the buyer approval because you already have consent from them for future purchases.
5. Buyer approval
Tell the SDK what to do on getting buyer approval.
After the buyer logs in to PayPal and authorizes the transaction, the script calls the onApprove() function that you defined. This function finalizes the transaction.
Call your server with the data.orderID and data.payerID values in a DoExpressCheckoutPayment NVP/SOAP API call.
1paypal.Buttons({2 onApprove: function(data) {3 var DOEC_URL = 'https://mystore.com/api/do-express-checkout';45 return fetch(DOEC_URL, {6 method: 'post',7 headers: {8 'content-type': 'application/json'9 },10 body: JSON.stringify({11 token: data.orderID,12 payerID: data.payerID13 })14 });15 }16}).render('#paypal-button-container');
Invoke a DoExpressCheckoutPayment call on your server with the token and payerID. This, in turn, calls the DoReferenceTransaction functionality API that's called during a direct API integration.
Note: Because you don't need to get the buyer approval, the script calls the onApprove() function that you defined after the createOrder() function. This function finalizes the transaction.