Save cards with the JavaScript SDK
Last updated: Nov 4th, 8:42am
After customers save their credit or debit card, they can select it for faster checkout. Customers won't have to enter payment details for future transactions.
Use the JavaScript SDK to save a payer's card if you aren't PCI Compliant - SAQ A but want to save credit or debit cards during checkout.
Know before you code
- This integration requires a PayPal Developer account.
- You'll need to have an existing advanced credit and debit card payments integration. PayPal must approve your account to process advanced credit and debit card payments.
- Complete the steps in Get started to get the following sandbox account information from the Developer Dashboard:
- The sandbox client ID and secret of your REST app.
- An access token to use the PayPal REST API server.
- This client-side and server-side integration uses the following:
How it works
PayPal encrypts payment method information and stores it in a digital vault for that customer.
- The payer saves their payment method.
- For a first-time payer, PayPal creates a customer ID. Store this within your system for future use.
- When the customer returns to your website and is ready to check out, pass their PayPal-generated customer ID to the JavaScript SDK. The customer ID tells the JavaScript SDK to save or reuse a saved payment method.
- The payer completes a billing agreement.
- The JavaScript SDK populates the checkout page with each saved payment method. Each payment method appears as a one-click button next to other ways to pay.
The checkout process is now shorter because it uses saved payment information.
Use cases
Businesses save payment methods if they want customers to:
- Check out without re-entering a payment method
- Pay after use, for example, ride-sharing and food delivery
Select platform or merchant
If you're a third-party saving payment method on behalf of merchants, select Merchant (see steps 1-7).
If you're a platform for hosting merchants, select Platform (see steps 3-7).
Generate user ID token for payer
Merchant (first-time payer)
A payer wants to save a payment method for the first time.
The PayPal OAuth 2.0 API has a has a response_type parameter. Set the response_type to id_token to retrieve a unique ID token for a payer when a payer saves a new payment method.
Sample server-side user ID token request
1curl -s -X POST https://api-m.sandbox.paypal.com/v1/oauth2/token \2 -u "CLIENT-ID:CLIENT-SECRET" \3 -H "Content-Type: application/x-www-form-urlencoded" \4 -H "PayPal-Auth-Assertion: PAYPAL-AUTH-ASSERTION" \5 -H "PayPal-Partner-Attribution-Id: BN-CODE" \6 -d "grant_type=client_credentials" \7 -d "response_type=id_token" \8 -d "target_customer_id=100161227" // PayPal-generated customer ID
Modify the code
Copy the code sample and modify it as follows:
- Change
CLIENT-ID
to your client ID. - Change
CLIENT-SECRET
to your client secret. - Change
PAYPAL-AUTH-ASSERTION
to your PayPal-Auth-Assertion token. - Change
BN-CODE
to your PayPal Attribution ID to receive revenue attribution. To find your BN code, see Code and Credential Reference.
Merchant (returning payer)
A payer wants to use a saved payment method.
Pass the id_token into the POST body target_customer_id
parameter. The target_customer_id
is a unique customer ID generated when a payment_source
is saved to the vault. The target_customer_id
is available when capturing an order or retrieving saved payment information.
Note: Pass the customer identifier generated by PayPal, not the one you use to identify the customer in your system.
Sample server-side user ID token request with a customer ID
1curl -s -X POST https://api-m.sandbox.paypal.com/v1/oauth2/token \2 -u "CLIENT-ID:CLIENT-SECRET" \3 -H "Content-Type: application/x-www-form-urlencoded" \4 -H "PayPal-Auth-Assertion: PAYPAL-AUTH-ASSERTION" \5 -H "PayPal-Partner-Attribution-Id: BN-CODE" \6 -d "grant_type=client_credentials" \7 -d "response_type=id_token" \8 -d "target_customer_id=100161227" // PayPal-generated customer ID
Modify the code
Copy the code sample and modify it as follows:
- Change
CLIENT-ID
to your client ID. - Change
CLIENT-SECRET
to your client secret. - Change
PAYPAL-AUTH-ASSERTION
to your PayPal-Auth-Assertion token. - Change
BN-CODE
to your PayPal Attribution ID to receive revenue attribution. To find your BN code, see Code and Credential Reference. - Change
CUSTOMER-ID
to the PayPal-generated customer ID.
Pass user ID token to JavaScript SDK
Merchant
Pass the id_token
into the JavaScript SDK through the data-user-id-token
.
1<script src="https://www.paypal.com/sdk/js?client-id=CLIENT-ID&merchant-id=MERCHANT-ID" data-user-id-token="ID-TOKEN"></script>
Modify the code
Copy the code sample and modify it as follows:
- Change
CLIENT-ID
to your client ID. - Change
MERCHANT-ID
to your merchant ID. - Change
ID-TOKEN
to theid_token
returned in the previous step
Add checkbox for payers to save card
Merchant and Platform
Add a checkbox element grouped with your card collection fields to give payers the option to save their card.
1<div>2 <input type="checkbox" id="save" name="save">3 <label for="save">Save your card</label>4</div>
Pass checkbox value
Merchant and Platform
Pass document.querySelector('#save').checked
to your server with the following details in the createOrder()
method:
- Value of the checkbox
- Card name
- Billing address
No verification
1const cardFields = paypal.CardFields({2 createOrder: (data) => {3 // Create the order on your server and return the order ID4 const saveCheckbox = document.getElementById("save");5 return fetch("/api/paypal/order/create/", {6 method: "POST",7 body: JSON.stringify({8 // Include the saveCheckbox.checked value9 // Optionally, include the card name and billing address10 }),11 }).then((res) => {12 return res.json();13 }).then((orderData) => {14 // Return the order ID that was created on your server15 return orderData.id;16 });17 },18 onApprove: function (data) {19 // Authorize or capture the order on your server20 const { orderID } = data;21 return fetch(`/api/paypal/orders/${orderID}/capture/`, {22 method: "POST"23 }).then((res) => {24 return res.json();25 }).then((orderData) => {26 // Retrieve vault details from the response27 const vault = orderData?.paymentSource?.card?.attributes?.vault;28 if (vault) {29 // Save the vault.id and vault.customer.id for future use30 }31 // Handle successful transaction32 });33 },34 onError: function (error) {35 // Handle any error that may occur36 }37});38if (cardFields.isEligible()) {39 cardFields.NameField().render("#card-name-field-container");40 cardFields.NumberField().render("#card-number-field-container");41 cardFields.ExpiryField().render("#card-expiry-field-container");42 cardFields.CVVField().render("#card-cvv-field-container");43} else {44 // Handle the workflow when credit and debit cards are not available45}46const submitButton = document.getElementById("submit-button");47submitButton.addEventListener("click", () => {48 cardFields.submit().then(() => {49 // Handle successful transaction50 }).catch((error) => {51 // Handle any error that may occur52 });53});
3D Secure
To trigger 3D Secure, pass the required contingency with the verification method in the create orders payload. The verification method can be contingencies parameter with SCA_ALWAYS
or SCA_WHEN_REQUIRED
.
SCA_ALWAYS
triggers an authentication for every transaction, while SCA_WHEN_REQUIRED
triggers an authentication only when a regional compliance mandate such as PSD2 is required. 3D Secure is supported only in countries with a PSD2 compliance mandate.
1const cardFields = paypal.CardFields({2 createOrder: (data) => {3 // Create the order on your server and return the order ID4 const saveCheckbox = document.getElementById("save");5 return fetch("/api/paypal/order/create/", {6 method: "POST",7 body: JSON.stringify({8 // Include the saveCheckbox.checked value9 // Optionally, include the card name and billing address10 // Pass in the 3DS contingency as a verification attribute along with the payment source11 ...12 card: {13 attributes: {14 verification: {15 method: "SCA_ALWAYS",//SCA_WHEN_REQUIRED is another option for the verification method16 },17 },18 experience_context: {19 shipping_preference: "NO_SHIPPING",20 return_url: "https://example.com/returnUrl",21 cancel_url: "https://example.com/cancelUrl",22 },23 },24 }),25 }).then((res) => {26 return res.json();27 }).then((orderData) => {28 // Return the order ID that was created on your server29 return orderData.id;30 });31 },32 onApprove: function (data) {33 // Authorize or capture the order on your server34 const { liabilityshift, orderID } = data;35 if(liabilityShift) {36 /* Handle liability shift. More information in the response parameters */37 }38 return fetch(`/api/paypal/orders/${orderID}/capture/`, {39 method: "POST"40 }).then((res) => {41 return res.json();42 }).then((orderData) => {43 // Retrieve vault details from the response44 const vault = orderData?.paymentSource?.card?.attributes?.vault;45 if (vault) {46 // Save the vault.id and vault.customer.id for future use47 }48 // Handle successful transaction49 });50 },51 onError: function (error) {52 // Handle any error that may occur53 },54 onCancel: function () {55 // Manage presentment when customer closes 3DS verification modal56 }57});58if (cardFields.isEligible()) {59 cardFields.NameField().render("#card-name-field-container");60 cardFields.NumberField().render("#card-number-field-container");61 cardFields.ExpiryField().render("#card-expiry-field-container");62 cardFields.CVVField().render("#card-cvv-field-container");63} else {64 // Handle the workflow when credit and debit cards are not available65}66const submitButton = document.getElementById("submit-button");67submitButton.addEventListener("click", () => {68 cardFields.submit().then(() => {69 // Handle successful transaction70 }).catch((error) => {71 // Handle any error that may occur72 });73});
Create order and save card
Merchant and Platform
Server side
Set up your server to call the Create Order API. The button that the payer selects determines the payment_source
sent in the following sample.
This SDK uses the Orders v2 API to save payment methods in the background. Use the following request using the Orders API to add attributes needed to save a card.
First-time payer
Save payment method for first-time payers
This request is for payers who:
- Don't have a payment source saved into the vault.
- Selected the save checkbox. The document.querySelector('#save').checked value is true.
To run 3D Secure on the card, set the payment_source.card.attributes.verification.method
to SCA_ALWAYS
or SCA_WHEN_REQUIRED
.
SCA_ALWAYS
triggers an authentication for every transaction, while SCA_WHEN_REQUIRED
triggers an authentication only when a regional compliance mandate such as PSD2 is required. 3D Secure is supported only in countries with a PSD2 compliance mandate.
1curl -v -X POST https://api-m.sandbox.paypal.com/v2/checkout/orders \2 -H "Content-Type: application/json" \3 -H "Authorization: Bearer ACCESS-TOKEN" \4 -H "PayPal-Auth-Assertion: PAYPAL-AUTH-ASSERTION" \5 -H "PayPal-Partner-Attribution-Id: BN-CODE" \6 -d '{7 "intent": "CAPTURE",8 "purchase_units": [9 {10 "reference_id": "d9f80740-38f0-11e8-b467-0ed5f89f718b",11 "amount": {12 "currency_code": "USD",13 "value": "100.00"14 }15 }16 ],17 "payment_source": {18 "card": {19 "name": "Firstname Lastname",20 "billing_address": {21 "address_line_1": "123 Main St.",22 "address_line_2": "Unit B",23 "admin_area_2": "Anytown",24 "admin_area_1": "CA",25 "postal_code": "12345",26 "country_code": "US"27 },28 "attributes": {29 "vault": {30 "store_in_vault": "ON_SUCCESS"31 },32 "verification": {33 "method:" "SCA_ALWAYS"34 }35 }36 }37 }38 }'
Response
Pass the order id to the JavaScript SDK. The SDK updates the order with the new card details. PayPal handles any PCI compliance issues.
After the SDK is updated, it triggers the onApprove()
method, which receives an object containing the orderID
. You can authorize or capture the order when you have the orderID
.
Note: The request to save the payment method is made when the order is created through payment_source.attributes.vault.store_in_vault
. Vault details are available only after an order is authorized or captured.
1{2 "id": "5O190127TN364715T",3 "status": "CREATED",4 "intent": "CAPTURE",5 "payment_source": {6 "card": {7 "brand": "VISA",8 "last-digits": "1881",9 "billing_address": {10 "address_line_1": "123 Main St.",11 "address_line_2": "Unit B",12 "admin_area_2": "Anytown",13 "admin_area_1": "CA",14 "postal_code": "12345",15 "country_code": "US"16 }17 }18 },19 "purchase_units": [{20 "reference_id": "d9f80740-38f0-11e8-b467-0ed5f89f718b",21 "amount": {22 "currency_code": "USD",23 "value": "100.00"24 }25 }],26 "create_time": "2021-10-28T21:18:49Z",27 "links": [{28 "href": "https://api-m.sandbox.paypal.com/v2/checkout/orders/5O190127TN364715T",29 "rel": "self",30 "method": "GET"31 },32 {33 "href": "https://www.sandbox.paypal.com/checkoutnow?token=5O190127TN364715T",34 "rel": "approve",35 "method": "GET"36 },37 {38 "href": "https://api-m.sandbox.paypal.com/v2/checkout/orders/5O190127TN364715T",39 "rel": "update",40 "method": "PATCH"41 },42 {43 "href": "https://api-m.sandbox.paypal.com/v2/checkout/orders/5O190127TN364715T/capture",44 "rel": "capture",45 "method": "POST"46 }47 ]48 }
Returning payer
Save payment method for returning payers
This request is for payers who:
- Already have a payment method saved in the vault.
- Want to save another payment method to the vault.
- Selected the save checkbox. The
document.getElementById("save")
.checked value is true.
Pass the PayPal-generated customer.id
as part of this request. Link additional payment_sources
to this customer through their customer.id
. The customer.id
is returned in the response from an authorize
or capture
request.
1curl -v -X POST https://api-m.sandbox.paypal.com/v2/checkout/orders \2 -H "Content-Type: application/json" \3 -H "Authorization: Bearer ACCESS-TOKEN" \4 -H "PayPal-Auth-Assertion: PAYPAL-AUTH-ASSERTION" \5 -H "PayPal-Partner-Attribution-Id: BN-CODE" \6 -d '{7 "intent": "CAPTURE",8 "purchase_units": [9 {10 "reference_id": "d9f80740-38f0-11e8-b467-0ed5f89f718b",11 "amount": {12 "currency_code": "USD",13 "value": "100.00"14 }15 }16 ],17 "payment_source": {18 "card": {19 "name": "Firstname Lastname",20 "billing_address": {21 "address_line_1": "123 Main Street",22 "address_line_2": "Unit B",23 "admin_area_2": "Anytown",24 "admin_area_1": "CA",25 "postal_code": "12345",26 "country_code": "US"27 },28 "attributes": {29 "customer" : {30 "id": "100161227" // PayPal-generated customer ID31 },32 "vault": {33 "store_in_vault": "ON_SUCCESS"34 },35 }36 }37 }38 }'
Response
Pass the order id to the JavaScript SDK. The SDK updates the order with the new card details. PayPal handles any PCI compliance issues.
After the SDK is updated, it triggers the onApprove()
method, which receives an object containing the orderID
. You can authorize or capture the order when you have the orderID
.
Note: The request to save the payment method is made when the order is created through payment_source.attributes.vault.store_in_vault
. Vault details are available only after an order is authorized or captured.
1{2 "id": "5O190127TN364715T",3 "status": "CREATED",4 "intent": "CAPTURE",5 "payment_source": {6 "card": {7 "brand": "VISA",8 "last-digits": "1881",9 "billing_address": {10 "address_line_1": "123 Main St.",11 "address_line_2": "Unit B",12 "admin_area_2": "Anytown",13 "admin_area_1": "CA",14 "postal_code": "12345",15 "country_code": "US"16 }17 }18 },19 "purchase_units": [{20 "reference_id": "d9f80740-38f0-11e8-b467-0ed5f89f718b",21 "amount": {22 "currency_code": "USD",23 "value": "100.00"24 }25 }],26 "create_time": "2021-10-28T21:18:49Z",27 "links": [{28 "href": "https://api-m.sandbox.paypal.com/v2/checkout/orders/5O190127TN364715T",29 "rel": "self",30 "method": "GET"31 },32 {33 "href": "https://www.sandbox.paypal.com/checkoutnow?token=5O190127TN364715T",34 "rel": "approve",35 "method": "GET"36 },37 {38 "href": "https://api-m.sandbox.paypal.com/v2/checkout/orders/5O190127TN364715T",39 "rel": "update",40 "method": "PATCH"41 },42 {43 "href": "https://api-m.sandbox.paypal.com/v2/checkout/orders/5O190127TN364715T/capture",44 "rel": "capture",45 "method": "POST"46 }47 ]48 }
Authorize or capture order request
1curl -v -X POST https://api-m.sandbox.paypal.com/v2/checkout/orders/5O190127TN364715T/capture \2 -H "Content-Type: application/json" \3 -H "Authorization: Bearer ACCESS-TOKEN" \4 -H "PayPal-Auth-Assertion: PAYPAL-AUTH-ASSERTION" \5 -H "PayPal-Partner-Attribution-Id: BN-CODE" \6 -d '{}'
Response
1{2 "id": "6XH94174N5355381V",3 "intent": "CAPTURE",4 "status": "COMPLETED",5 "payment_source": {6 "card": {7 "last_digits": "1881",8 "brand": "VISA",9 "type": "UNKNOWN",10 "attributes": {11 "vault": {12 "id": "1j4a89ge",13 "status": "VAULTED",14 "customer": {15 "id": "100161227"16 },17 "links": [18 {19 "href": "https://api-m.sandbox.paypal.com/v3/vault/payment-tokens/1j4a89ge",20 "rel": "self",21 "method": "GET"22 },23 {24 "href": "https://api-m.sandbox.paypal.com/v3/vault/payment-tokens/1j4a89ge",25 "rel": "delete",26 "method": "DELETE"27 },28 {29 "href": "https://api-m.sandbox.paypal.com/v2/checkout/orders/6XH94174N5355381V",30 "rel": "up",31 "method": "GET"32 }33 ]34 }35 }36 }37 },38 "purchase_units": [39 {40 "reference_id": "5a69b6e3-1916-4269-87b9-358516da5102",41 "amount": {42 "currency_code": "USD",43 "value": "101.00"44 },45 "payee": {46 "email_address": "merchant@example.com",47 "merchant_id": "BADP95SC2GDE6"48 },49 "soft_descriptor": "PP*TEST STORE",50 "payments": {51 "captures": [52 {53 "id": "9J594045WV338432T",54 "status": "COMPLETED",55 "amount": {56 "currency_code": "USD",57 "value": "101.00"58 },59 "final_capture": true,60 "disbursement_mode": "INSTANT",61 "seller_protection": {62 "status": "NOT_ELIGIBLE"63 },64 "seller_receivable_breakdown": {65 "gross_amount": {66 "currency_code": "USD",67 "value": "101.00"68 },69 "paypal_fee": {70 "currency_code": "USD",71 "value": "3.11"72 },73 "net_amount": {74 "currency_code": "USD",75 "value": "97.89"76 }77 },78 "links": [79 {80 "href": "https://api-m.sandbox.paypal.com/v2/payments/captures/9J594045WV338432T",81 "rel": "self",82 "method": "GET"83 },84 {85 "href": "https://api-m.sandbox.paypal.com/v2/payments/captures/9J594045WV338432T/refund",86 "rel": "refund",87 "method": "POST"88 },89 {90 "href": "https://api-m.sandbox.paypal.com/v2/checkout/orders/6XH94174N5355381V",91 "rel": "up",92 "method": "GET"93 }94 ],95 "create_time": "2022-09-23T20:17:31Z",96 "update_time": "2022-09-23T20:17:31Z",97 "processor_response": {98 "avs_code": "A",99 "cvv_code": "M",100 "response_code": "0000"101 }102 }103 ]104 }105 }106 ],107 "create_time": "2022-09-23T20:17:31Z",108 "update_time": "2022-09-23T20:17:31Z",109 "links": [110 {111 "href": "https://api-m.sandbox.paypal.com/v2/checkout/orders/6XH94174N5355381V",112 "rel": "self",113 "method": "GET"114 }115 ]116}
In the response from the Authorize or Capture request, the Orders v2 API interacts with the Payment Method Tokens v3 API to save the card.
The payment_source.card.attributes.vault
stores the card information as the vault.id
, which can be used for future payments when the vault.status
is VAULTED
.
Save approved payment source
If the payment has been authorized or captured, the payer doesn't need to be present to save a payment_source
. To keep checkout times as short as possible, the Orders API responds as soon as payment is captured.
If the attributes.vault.status
returned after payment is APPROVED, you won't have a vault.id
yet. An example of the attributes object from this scenario is in the following sample:
1"attributes": {2 "vault": {3 "status": "APPROVED",4 "links": []5 }6 }
The Payment Method Tokens API still saves the payment source even after the Orders API returns its response and sends a webhook after the payment source is saved.
In order to retrieve a vault_id
when an APPROVED status is returned, you'll need to subscribe to the VAULT.PAYMENT-TOKEN.CREATED
webhook.
The Payment Method Tokens API sends a webhook after the payment source is saved. An example of the VAULT.PAYMENT-TOKEN.CREATED
webhook payload is shown in the following sample:
1{2 "id":"WH-1KN88282901968003-82E75604WM969463F",3 "event_version":"1.0",4 "create_time":"2022-08-15T14:13:48.978Z",5 "resource_type":"payment_token",6 "resource_version":"3.0",7 "event_type":"VAULT.PAYMENT-TOKEN.CREATED",8 "summary":"A payment token has been created.",9 "resource":{10 "time_created":"2022-08-15T07:13:48.964PDT",11 "links":[12 {13 "href":"https://api-m.sandbox.paypal.com/v3/vault/payment-tokens/9n6724m",14 "rel":"self",15 "method":"GET",16 "encType":"application/json"17 },18 {19 "href":"https://api-m.sandbox.paypal.com/v3/vault/payment-tokens/9n6724m",20 "rel":"delete",21 "method":"DELETE",22 "encType":"application/json"23 }24 ],25 "id":"nkq2y9g",26 "payment_source":{27 "card":{28 "last_digits":"1111",29 "brand":"VISA",30 "expiry":"2027-02",31 "billing_address":{32 "address_line_1":"123 Main St.",33 "address_line_2":"Unit B",34 "admin_area_2":"Anytown",35 "admin_area_1":"CA",36 "postal_code":"12345",37 "country_code":"US"38 }39 }40 },41 "customer":{42 "id":"695922590"43 }44 },45 "links":[46 {47 "href":"https://api-m.sandbox.paypal.com/v1/notifications/webhooks-events/WH-1KN88282901968003-82E75604WM969463F",48 "rel":"self",49 "method":"GET"50 },51 {52 "href":"https://api-m.sandbox.paypal.com/v1/notifications/webhooks-events/WH-1KN88282901968003-82E75604WM969463F/resend",53 "rel":"resend",54 "method":"POST"55 }56 ]57 }
In this example, the resource.id field
is the vault ID, and resource.customer.id
is the PayPal-generated customer ID.
You can now style your card fields and test a purchase.
Payment processor codes
Payment processors return the following codes when they receive a transaction request. For advanced card payments, the code displays in the authorization object under the response_code
field.
The following sample shows the processor response codes returned in an authorization (avs_code
) and capture call (cvv_code
) response:
1"processor_response": {2 "avs_code": "Y",3 "cvv_code": "S",4 "response_code": "0000"5 }
See the Orders API response_code
object to get the processor response code for the non-PayPal payment processor errors.
Pay with saved payment methods
Merchant and Platform
When a payer returns to your site, you can show the payer's saved payment methods with the Payment Method Tokens API.
Create UI
Create your own UI to show saved payment methods for returning payers.
List all saved payment methods
Make the server-side list all payment tokens API call to retrieve payment methods saved to a payer's PayPal-generated customer ID. Based on this list, you can show all saved payment methods to a payer to select during checkout.
- Sample request
- Sample request
1curl -L -X GET https://api-m.sandbox.paypal.com/v3/vault/payment-tokens?customer_id=100161227 \2 -H "Content-Type: application/json" \3 -H "Accept-Language: en_US" \4 -H "PayPal-Auth-Assertion: PAYPAL-AUTH-ASSERTION" \5 -H "PayPal-Partner-Attribution-Id: BN-CODE" \6 -H "Authorization: Bearer ACCESS-TOKEN"
Show saved card to payer
Display the saved card to the payer and use the Orders API to make another transaction. Use the vault ID the payer selects as an input to the Orders API to capture the payment.
Use supported CSS properties to style the card fields.
- Sample request
- Sample response
1curl -L -X POST https://api-m.sandbox.paypal.com/v2/checkout/orders \2 -H "Accept: application/json" \3 -H "Content-Type: application/json" \4 -H "Accept-Language: en_US" \5 -H "PayPal-Auth-Assertion: PAYPAL-AUTH-ASSERTION" \6 -H "PayPal-Partner-Attribution-Id: BN-CODE" \7 -H "PayPal-Request-Id: PAYPAL-REQUEST-ID" \8 -H "Authorization: Bearer ACCESS-TOKEN" \9 -d '{10 "intent": "CAPTURE",11 "purchase_units": [12 {13 "amount": {14 "currency_code": "USD",15 "value": "50.00"16 }17 }18 ],19 "payment_source": {20 "card": {21 "vault_id":"1j4a89ge"22 }23 }24 }'
Integrate front end
The following sample shows how a full script to save cards might appear in HTML:
1<!DOCTYPE html>2 <head>3 <!-- Add meta tags for mobile and IE -->4 <meta charset="utf-8" />5 </head>6 <body>7 <script src="https://www.paypal.com/sdk/js?components=card-fields&client-id=YOUR-CLIENT-ID¤cy=USD&intent=capture&merchant-id=YOUR-MERCHANT-ID"></script>8 <div align="center"> or </div>9 <!-- Advanced credit and debit card payments form -->10 <div class='card_container'>11 <div id='card-number'></div>12 <div id='expiration-date'></div>13 <div id='cvv'></div>14 <div id='card-holder-name'></div>15 <label>16 <input type='checkbox' id='vault' name='vault' /> Vault17 </label>18 <br><br>19 <button value='submit' id='submit' class='btn'>Pay</button>20 </div>21 <!-- Implementation -->22 <script>23 // Create the card fields component and define callbacks24 const cardFields = paypal.CardFields({25 createOrder: async (data) => {26 const result = await fetch("https://api-m.sandbox.paypal.com/v2/checkout/orders", {27 method: "POST",28 body: JSON.stringify({29 intent: "CAPTURE",30 purchase_units: [{31 amount: {32 currency_code: "USD",33 value: "100.00"34 }35 }],36 payment_source: {37 card: {38 attributes: {39 verification: {40 method: "SCA_ALWAYS"41 },42 vault: {43 store_in_vault: "ON_SUCCESS",44 usage_type: "PLATFORM",45 customer_type: "CONSUMER",46 permit_multiple_payment_tokens: true,47 },48 }49 },50 experience_context: {51 shipping_preference: "NO_SHIPPING",52 return_url: "https://example.com/returnUrl",53 cancel_url: "https://example.com/cancelUrl",54 },55 },56 }),57 headers: {58 "Content-Type": "application/json",59 "Authorization": "Bearer ACCESS_TOKEN",60 "PayPal-Request-Id": "UNIQUE_ALPHANUMERIC_KEY"61 },62 })63 const {64 id65 } = await result.json();66 return id;67 },68 onApprove: async (data) => {69 const {70 orderID71 } = data;72 return fetch('https://api-m.sandbox.paypal.com/v2/checkout/orders/${orderID}/capture/', {73 method: "POST",74 body: JSON.stringify({75 payment_source: {76 attributes: {77 vault: {78 store_in_vault: "ON_SUCCESS",79 usage_type: "PLATFORM",80 customer_type: "CONSUMER",81 permit_multiple_payment_tokens: true,82 },83 },84 experience_context: {85 shipping_preference: "NO_SHIPPING",86 return_url: "https://example.com/returnUrl",87 cancel_url: "https://example.com/cancelUrl",88 },89 },90 }),91 headers: {92 "Content-Type": "application/json",93 "Authorization": "Bearer ACCESS_TOKEN",94 "PayPal-Request-Id": "UNIQUE_ALPHANUMERIC_KEY"95 },96 })97 // Retrieve vault details from the response and98 // save vault.id and customer.id for the buyer's return experience99 return await res.json();100 },101 onError: (error) => console.error('Something went wrong:', error)102 });103 // Render each field after checking for eligibility104 // Check eligibility and display advanced credit and debit card payments105 if (cardFields.isEligible()) {106 cardFields.NameField().render("#card-holder-name");107 cardFields.NumberField().render("#card-number");108 cardFields.ExpiryField().render("#expiration-date");109 cardFields.CVVField().render("#cvv");110 } else {111 // Handle workflow when credit and debit cards are not available112 }113 const submitButton = document.getElementById("submit");114 submitButton.addEventListener("click", () => {115 cardFields116 .submit()117 .then(() => {118 console.log("submit was successful");119 })120 .catch((error) => {121 console.error("submit erred:", error);122 });123 });124 </script>125 </html>
Test cards
Use the following card numbers to test transactions in the sandbox:
Test number | Card type |
---|---|
371449635398431 | American Express |
376680816376961 | American Express |
36259600000004 | Diners Club |
6304000000000000 | Maestro |
5063516945005047 | Maestro |
2223000048400011 | Mastercard |
4005519200000004 | Visa |
4012000033330026 | Visa |
4012000077777777 | Visa |
4012888888881881 | Visa |
4217651111111119 | Visa |
4500600000000061 | Visa |
4772129056533503 | Visa |
4915805038587737 | Visa |
Next steps
-
Test and go live with this integration.
- Change the credentials and API URL from sandbox to your live environment when going live with your integration.
- Use payment method token with checkout for subsequent or recurring transactions.
- You can get a payment token, list all payment tokens, delete a payment token, and more with the Payment Method Tokens API.
See also
- Provide customer authentication with 3D Secure.
- Keep saved cards up-to-date with the real-time account updater.