Save cards for purchase later with the JavaScript SDK

CURRENT

Last updated: Dec 13th, 12:28am

Save payment methods to charge payers after a set amount of time. For example, you can offer a free trial and charge payers after the trial expires. Payers don't need to be present when charged. No checkout required.

Use the SDK to save a payer's card if you aren't PCI Compliant - SAQ A but want to save credit or debit cards.


Availability

See Supported Countries

  • Australia
  • Austria
  • Belgium
  • Bulgaria
  • Canada
  • China
  • Cyprus
  • Czech Republic
  • Denmark
  • Estonia
  • Finland
  • France
  • Germany
  • Hong Kong
  • Hungary
  • Ireland
  • Italy
  • Japan
  • Latvia
  • Liechtenstein
  • Lithuania
  • Luxembourg
  • Malta
  • Netherlands
  • Norway
  • Poland
  • Portugal
  • Romania
  • Singapore
  • Slovakia
  • Slovenia
  • Spain
  • Sweden
  • United Kingdom
  • United States

Know before you code

  • You are responsible for the front-end user experience. The JavaScript SDK provides back-end support.

  • To save payment methods, you must be able to identify payers uniquely. For example, payers create an account and log in to your site.
  • Complete the steps in Get started to get the following sandbox account information from the Developer Dashboard:
    • Your sandbox account login information
    • Your access token

  • This client-side integration uses information passed through the CardFields component to save a card without a transaction.
  • The SDK saves the following card types for purchase later:
    • American Express
    • Discover
    • Mastercard
    • Visa

  • You'll need an existing advanced credit and debit integration. PayPal must approve your business account for advanced credit and debit card payments.

How it works

PayPal encrypts payment method information and stores it in a digital vault for that customer.

  1. The payer saves their payment method.
  2. For a first-time payer, PayPal creates a customer ID. Store this within your system for future use.
  3. 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.
  4. The payer completes a billing agreement.
  5. 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.

1. Set up account to save payments

Set up your sandbox and live business accounts to save payment methods:

  1. Log in to the Developer Dashboard.
  2. Under REST API apps, select your app name.
  3. Under Sandbox App Settings > App Feature Options, check Accept payments.
  4. Expand Advanced options. Confirm that Vault is selected.

2. Add SDK to HTML page

Pass your client ID and merchant ID to the SDK to identify yourself and the merchant you're saving payment methods for. Replace CLIENT-ID with your app's client ID and MERCHANT-ID in the following sample:

    1<script src="https://www.paypal.com/sdk/js?components=card-fields&client-id=CLIENT-ID&merchant-id=MERCHANT-ID"</script>

    Modify the code

    • Change CLIENT_ID to your client ID.
    • Change MERCHANT_ID to your merchant ID.

    3. Create setup token

    You request a setup token from your server. Pass the setup token from your server to the SDK with the createVaultSetupToken callback.

    The createVaultSetupToken callback:

    • Calls the server endpoint you created to generate and retrieve the setup token.
    • Makes a request to your server endpoint.

    Then, your server uses its access token to create and return the setup token to the client.

    Any errors that occur while creating a setup token show up in the onError callback provided to the card fields component.

    Create a setup token for cards that have:

    • No verification
    • 3D Secure verification

    Supported callback


    No verification


    Callback Returns Description
    createVaultSetupToken Setup token (string) The merchant's server must receive this callback. To get a setup token, see Create a setup token for cards from the merchant server. The SDK then saves the payment method and updates the setup token with payment method details.

    3D Secure


    Callback Returns Description
    createVaultSetupToken Setup token (string) The merchant's server must receive this callback. Send either "SCA_ALWAYS" or "SCA_WHEN_REQUIRED" in verification_method with this request's body. To get a setup token, see Create a setup token for cards from the merchant server. The SDK then saves the payment method and updates the setup token with payment method details.

    Front-end sample

    No verification

      1const cardFields = paypal.CardFields({
      2createVaultSetupToken:()=>{
      3// The merchant calls their server API to generate a vaultSetupToken
      4// and return it here as a string
      5const result =awaitfetch("example.com/create/setup/token")
      6return result.token
      7}
      8onApprove:({ vaultSetupToken })=>{
      9// Send the vaultSetupToken to the merchant server to use later.
      10}
      11})


      3D Secure

        1createVaultSetupToken:()=>{
        2// The merchant calls their server API to generate a vaultSetupToken
        3// Send the SCA_ALWAYS or SCA_WHEN_REQUIRED contingency with the request body
        4// and return it here as a string
        5const result =awaitfetch("merchant.com/create/setup/token")
        6return result.token
        7}
        8onApprove:({ vaultSetupToken, liabilityShift })=>{
        9// Handle liabilityShift. Refer to response parameters for further information
        10// Send the vaultSetupToken to the merchant server to use later
        11}
        12})

        Back-end sample

        Make this request from your server.


        Platform

        This setup token is generated with an empty card in the payment_source object. PayPal hosted fields use this token to securely update the setup token with payment details.

          1curl -v -k -X POST https://api-m.sandbox.paypal.com/v3/vault/setup-tokens \
          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 -H "PayPal-Request-Id: REQUEST-ID" \
          7 -d '{
          8 "payment_source": {
          9 "card": {
          10 "name": "Firstname Lastname",
          11 "billing_address": {
          12 "address_line_1": "123 Main St.",
          13 "address_line_2": "Unit B",
          14 "admin_area_2": "San Jose",
          15 "admin_area_1": "CA",
          16 "postal_code": "12345",
          17 "country_code": "US"
          18 },
          19 "experience_context": {
          20 "brand_name": "EXAMPLE INC",
          21 "locale": "en-US",
          22 "return_url": "https://example.com/returnUrl",
          23 "cancel_url": "https://example.com/cancelUrl"
          24 }
          25 }
          26}
          27}'

          Modify the code

          1. Change ACCESS-TOKEN to your sandbox app's access token.
          2. Change PAYPAL-AUTH-ASSERTION to your PayPal-Auth-Assertion token.
          3. Change BN-CODE to your PayPal Attribution ID to receive revenue attribution. To f
          4. Change REQUEST-ID to a set of unique alphanumeric characters such as a time stamp.
          5. In the createVaultSetupToken, call the endpoint on your server to create a setup token with the Payment Method Tokens API. createVaultSetupToken returns the setup token as a string.


          Merchant

          This setup token is generated with an empty payment_source. PayPal hosted fields use this token to securely update the setup token with payment details.

            1curl -v -k -X POST https://api-m.sandbox.paypal.com/v3/vault/setup-tokens \
            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 -H "PayPal-Request-Id: REQUEST-ID" \
            7 -d '{
            8 "payment_source": {
            9 "card": {
            10 "name": "Firstname Lastname",
            11 "billing_address": {
            12 "address_line_1": "123 Main St.",
            13 "address_line_2": "Unit B",
            14 "admin_area_2": "Anytown",
            15 "admin_area_1": "CA",
            16 "postal_code": "12345",
            17 "country_code": "US"
            18 },
            19 "experience_context": {
            20 "brand_name": "EXAMPLE INC",
            21 "locale": "en-US",
            22 "return_url": "https://example.com/returnUrl",
            23 "cancel_url": "https://example.com/cancelUrl"
            24 }
            25 }
            26 }
            27}'

            Modify the code

            1. Change ACCESS-TOKEN to your sandbox app's access token.
            2. Change PAYPAL-AUTH-ASSERTION to your PayPal-Auth-Assertion token.
            3. Change BN-CODE to your PayPal Attribution ID to receive revenue attribution. To find your BN code, see Code and Credential Reference.
            4. Change REQUEST-ID to a set of unique alphanumeric characters such as a time stamp.
            5. In the createVaultSetupToken callback, call an endpoint on your server to create a setup token with the Payment Method Tokens API. createVaultSetupToken returns the setup token as a string.

            4. Initialize card fields to save data

            After the SDK has a setup token, it renders card fields for the payer to submit card details. The SDK then returns the vaultSetupToken to the merchant through the onApprove callback.

            When you complete this step, CardFields are ready to save card details for later use.

            Supported callback

            No verification

            Callback Returns Description
            onApprove { vaultSetupToken: string } The merchant gets the updated vaultSetupToken when the payment method is saved. The merchant must store the vaultSetupToken token in their system.


            3D Secure


            Callback Returns Description
            onApprove { vaultSetupToken: string, liabilityShift: string } This callback provides the updated vaultSetupToken and liabilityShift when the payment method is saved. The merchant stores the vaultSetupToken token in their system.

            Front-end sample

            No verification

              1const cardFields = paypal.CardFields({
              2createVaultSetupToken:()=>{
              3// The merchant calls their server API to generate a vaultSetupToken
              4// and return it here as a string
              5const result =awaitfetch("merchant.com/create/setup/token")
              6return result.token
              7}
              8onApprove:({
              9 vaultSetupToken
              10})=>{
              11// Send the vaultSetupToken to the merchant server
              12// for the server to generate a payment token
              13returnfetch("example.com/create/payment/token",{body:JSON.stringify({ vaultSetupToken })})
              14},
              15})

              3D Secure

                1const cardFields = paypal.CardFields({
                2createVaultSetupToken:()=>{
                3// The merchant calls their server API to generate a vaultSetupToken
                4// and return it here as a string
                5const result =awaitfetch("https://api-m.sandbox.paypal.com/v3/vault/setup-tokens",
                6{
                7method:"POST",
                8body:JSON.stringify(
                9"payment_source":{
                10"card":{
                11"verification_method":"SCA_WHEN_REQUIRED",
                12"usage_type":"MERCHANT",
                13"experience_context":{
                14"return_url":"https://example.com/returnUrl",
                15"cancel_url":"https://example.com/cancelUrl"
                16}
                17}
                18}),
                19}
                20);
                21const{ id, customer }=await result.json();
                22const result =awaitfetch("merchant.com/create/setup/token")
                23return result.token
                24},
                25onApprove:({ vaultSetupToken, liabilityShift })=>{
                26// Send the vaultSetupToken to the merchant server for later use.
                27},
                28onError:(error)=>console.error('Something went wrong:', error)
                29})

                Back-end sample

                Make this request from your server.

                Platform

                  1curl -v -k -X POST https://api-m.sandbox.paypal.com/v3/vault/payment-tokens \
                  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 -H "PayPal-Request-Id: REQUEST-ID"\
                  7 -d '{
                  8 "payment_source": {
                  9 "token": {
                  10 "id": "VAULT-SETUP-TOKEN",
                  11 "type": "SETUP_TOKEN"
                  12 }
                  13 }
                  14 }'

                  Modify the code

                  1. Pass the vaultSetupToken returned by onApprove to your server.
                  2. Change ACCESS-TOKEN to your sandbox app's access token.
                  3. Change PAYPAL-AUTH-ASSERTION to your PayPal-Auth-Assertion token.
                  4. Change BN-CODE to your PayPal Attribution ID to receive revenue attribution. To find your BN code, see Code and Credential Reference.
                  5. Change REQUEST-ID to a set of unique alphanumeric characters such as a time stamp.
                  6. Change VAULT-SETUP-TOKEN to the value passed from the client.
                  7. Save the resulting payment token returned from the API to use in future transactions.

                  Merchant

                    1curl -v -k -X POST https://api-m.sandbox.paypal.com/v3/vault/payment-tokens \
                    2 -H "Content-Type: application/json" \
                    3 -H "Authorization: Bearer ACCESS-TOKEN" \
                    4 -H "PayPal-Request-Id: REQUEST-ID" \
                    5 -H "PayPal-Auth-Assertion: PAYPAL-AUTH-ASSERTION" \
                    6 -H "PayPal-Partner-Attribution-Id: BN-CODE" \
                    7 -H "PayPal-Request-ID: REQUEST-ID" \
                    8 -d '{
                    9 "payment_source": {
                    10 "token": {
                    11 "id": "VAULT-SETUP-TOKEN",
                    12 "type": "SETUP_TOKEN"
                    13 }
                    14 }
                    15 }'

                    Modify the code

                    1. Pass the vaultSetupToken returned by onApprove to your server.
                    2. Change ACCESS-TOKEN to your sandbox app's access token.
                    3. Change PAYPAL-AUTH-ASSERTION to your PayPal-Auth-Assertion token.
                    4. Change BN-CODE to your PayPal Attribution ID to receive revenue attribution. To find your BN code, see Code and Credential Reference.
                    5. Change REQUEST-ID to a set of unique alphanumeric characters such as a time stamp.
                    6. Change VAULT-SETUP-TOKEN to the value passed from the client.
                    7. Save the resulting payment token returned from the API to use in future transactions.

                    Avoid validation errors

                    CardFields can't be configured with both the createOrder callback and the createVaultSetupToken callback. When saving cards, only pass createVaultSetupToken.

                      1// Throws a validation error: can't call both 'createVaultSetupToken' and 'createOrder'
                      2paypal.CardFields({
                      3 createVaultSetupToken: () => {...},
                      4 createOrder: () => {...}
                      5})

                      5. Show error page

                      If an error prevents checkout, alert the payer that an error has occurred using the onError callback.

                        1paypal.CardFields({
                        2 onError(err) {
                        3 console.error("Something went wrong:", err)
                        4 }
                        5 })

                        Supported callback

                        CallbackReturnsDescription
                        onError{ vaultSetupToken: string }The merchant gets the updated vaultSetupToken when the payment method is saved. The merchant must store the vaultSetupToken token in their system.

                        6. Show saved payment methods to returning payers

                        When a payer returns to your site, you can show the payer's saved payment methods with the Payment Method Tokens API.

                        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: List all saved payment methods

                        Platform

                          1curl -L -X GET https://api-m.sandbox.paypal.com/v3/vault/payment-tokens?customer_id=CUSTOMER-ID \
                          2 -H "Content-Type: application/json"\
                          3 -H "Accept-Language: en_US"\
                          4 -H "Authorization: Bearer ACCESS-TOKEN"\
                          5 -H "PayPal-Auth-Assertion: PAYPAL-AUTH-ASSERTION"\
                          6 -H "PayPal-Partner-Attribution-Id: BN-CODE"\
                          7 -H "PayPal-Request-Id: REQUEST-ID"\
                          8 -d '{}'

                          Modify the code

                          • Change CUSTOMER-ID to a PayPal-generated customer ID.
                          • Change ACCESS-TOKEN to your sandbox app's access token.
                          • 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 REQUEST-ID to a set of unique alphanumeric characters such as a time stamp.

                          Merchant

                            1curl -L -X GET https://api-m.sandbox.paypal.com/v3/vault/payment-tokens?customer_id=CUSTOMER-ID \
                            2 -H "Content-Type: application/json"\
                            3 -H "Accept-Language: en_US"\
                            4 -H "Authorization: Bearer ACCESS-TOKEN"\
                            5 -H "PayPal-Auth-Assertion: PAYPAL-AUTH-ASSERTION"\
                            6 -H "PayPal-Partner-Attribution-Id: BN-CODE"\
                            7 -H "PayPal-Request-Id: REQUEST-ID"\
                            8 -d '{}'

                            Modify the code

                            • Change CUSTOMER-ID to a PayPal-generated customer ID.
                            • Change ACCESS-TOKEN to your sandbox app's access token.
                            • 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 REQUEST-ID to a set of unique alphanumeric characters such as a time stamp.

                            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. We recommend showing the card brand and last 4 digits.

                            Visa,ending,in,1234

                            7. Integrate back end

                            The following sample shows a complete back-end integration to save cards for purchase later:

                            Platform

                              1import"dotenv/config";
                              2importexpressfrom"express";
                              3const{PORT=8888}= process.env;
                              4const app =express();
                              5 app.set("view engine","ejs");
                              6 app.use(express.static("public"));
                              7// Create setup token
                              8 app.post("/api/vault/token",async(req, res)=>{
                              9try{
                              10// Use your access token to securely generate a setup token
                              11// with an empty payment_source
                              12const vaultResponse =awaitfetch("https://api-m.sandbox.paypal.com/v3/vault/setup-tokens",{
                              13method:"POST",
                              14body:JSON.stringify({payment_source:{}}),
                              15headers:{
                              16"Authorization":"Bearer ${ACCESS-TOKEN}",
                              17"PayPal-Request-Id":Date.now(),
                              18"PayPal-Auth-Assertion":"PAYPAL-AUTH-ASSERTION",
                              19"PayPal-Partner-Attribution-Id":"BN-CODE"
                              20}
                              21})
                              22// Return the reponse to the client
                              23 res.json(vaultResponse);
                              24}catch(err){
                              25 res.status(500).send(err.message);
                              26}
                              27})
                              28// Create payment token from a setup token
                              29 app.post("/api/vault/:setupToken",async(req, res)=>{
                              30const{ setupToken }= req.params;
                              31try{
                              32const paymentTokenResult =awaitfetch(
                              33"https://api-m.sandbox.paypal.com/v3/vault/payment-tokens",
                              34{
                              35method:"POST",
                              36body:{
                              37payment_source:{
                              38token:{
                              39id: setupToken,
                              40type:"SETUP_TOKEN"
                              41}
                              42}
                              43},
                              44headers:{
                              45"Authorization":"Bearer ${ACCESS-TOKEN}",
                              46"PayPal-Request-Id":Date.now(),
                              47"PayPal-Auth-Assertion":"PAYPAL-AUTH-ASSERTION",
                              48"PayPal-Partner-Attribution-Id":"BN-CODE"
                              49}
                              50})
                              51const paymentMethodToken = paymentTokenResult.id
                              52const customerId = paymentTokenResult.customer.id
                              53awaitsave(paymentMethodToken, customerId)
                              54 res.json(captureData);
                              55}catch(err){
                              56 res.status(500).send(err.message);
                              57}
                              58})
                              59constsave=asyncfunction(paymentMethodToken, customerId){
                              60// Specify where to save the payment method token
                              61}
                              62 app.listen(PORT,()=>{
                              63console.log('Server listening at http://localhost:${PORT}/');
                              64})

                              Merchant

                                1import"dotenv/config";
                                2importexpressfrom"express";
                                3const{PORT=8888}= process.env;
                                4const app =express();
                                5app.set("view engine","ejs");
                                6app.use(express.static("public"));
                                7// Create setup token
                                8app.post("/api/vault/token",async(req, res)=>{
                                9try{
                                10// Use your access token to securely generate a setup token
                                11// with an empty payment_source
                                12const payload ={
                                13payment_source:{
                                14card:{}
                                15}
                                16}
                                17const vaultResponse =awaitfetch("https://api-m.sandbox.paypal.com/v3/vault/setup-tokens",{
                                18method:"POST",
                                19body:JSON.stringify(payload),
                                20headers:{
                                21"Authorization":"Bearer ${ACCESS-TOKEN}",
                                22"PayPal-Request-Id":Date.now(),
                                23"PayPal-Auth-Assertion":"PAYPAL-AUTH-ASSERTION",
                                24"PayPal-Partner-Attribution-Id":"BN-CODE"
                                25}
                                26})
                                27// Return the reponse to the client
                                28 res.json(vaultResponse);
                                29}catch(err){
                                30 res.status(500).send(err.message);
                                31}
                                32})
                                33// Create payment token from a setup token
                                34app.post("/api/vault/:setupToken",async(req, res)=>{
                                35const{ setupToken }= req.params;
                                36try{
                                37const paymentTokenResult =awaitfetch(
                                38"https://api-m.sandbox.paypal.com/v3/vault/payment-tokens",
                                39{
                                40method:"POST",
                                41body:{
                                42payment_source:{
                                43token:{
                                44id: setupToken,
                                45type:"SETUP_TOKEN"
                                46}
                                47}
                                48},
                                49headers:{
                                50Authorization:'Bearer ${ACCESS-TOKEN}',
                                51"PayPal-Request-Id":Date.now(),
                                52"PayPal-Auth-Assertion":"PAYPAL-AUTH-ASSERTION",
                                53"PayPal-Partner-Attribution-Id":"BN-CODE"
                                54}
                                55})
                                56const paymentMethodToken = paymentTokenResult.id
                                57const customerId = paymentTokenResult.customer.id
                                58awaitsave(paymentMethodToken, customerId)
                                59 res.json(captureData);
                                60}catch(err){
                                61 res.status(500).send(err.message);
                                62}
                                63})
                                64constsave=asyncfunction(paymentMethodToken, customerId){
                                65// Specify where to save the payment method token
                                66}
                                67app.listen(PORT,()=>{
                                68console.log('Server listening at http://localhost:${PORT}/');
                                69})

                                8. Integrate front end

                                The following sample shows how a full script to save cards might appear in HTML:

                                  1<!DOCTYPE html>
                                  2<html>
                                  3<head>
                                  4 <!-- Add meta tags for mobile and IE -->
                                  5 <meta charset="utf-8" />
                                  6</head>
                                  7<body>
                                  8 <!-- Include the PayPal JavaScript SDK -->
                                  9 <script src="https://www.paypal.com/sdk/js?components=card-fields&client-id=YOUR-CLIENT-ID&currency=USD&intent=capture&merchant-id=YOUR-MERCHANT-ID"></script>
                                  10 <div align="center"> or </div>
                                  11 <!-- Advanced credit and debit card payments form -->
                                  12 <div class='card_container'>
                                  13 <div id='card-number'></div>
                                  14 <div id='expiration-date'></div>
                                  15 <div id='cvv'></div>
                                  16 <div id='card-holder-name'></div>
                                  17 <label>
                                  18 <input type='checkbox' id='vault' name='vault' /> Vault
                                  19 </label>
                                  20 <br><br>
                                  21 <button value='submit' id='submit' class='btn'>Pay</button>
                                  22 </div>
                                  23 <!-- Implementation -->
                                  24 <script>
                                  25 const cardFields = paypal.CardFields({
                                  26 createVaultSetupToken: async () => {
                                  27 // The merchant calls their server API to generate a setup token
                                  28 // and return it here as a string
                                  29 const result = await fetch("https://example.com/api/vault/token", {
                                  30 method: "POST"
                                  31 });
                                  32 const { id } = await result.json();
                                  33 return id;
                                  34 },
                                  35 onApprove: async (data) => {
                                  36 return fetch(`https://example.com/api/vault/${data.vaultSetupToken}`, {
                                  37 method: "POST"
                                  38 });
                                  39 },
                                  40 onError: (error) => console.error('Something went wrong:', error)
                                  41 })
                                  42 // Check eligibility and display advanced credit and debit card payments
                                  43 if (cardFields.isEligible()) {
                                  44 cardFields.NameField().render("#card-holder-name");
                                  45 cardFields.NumberField().render("#card-number");
                                  46 cardFields.ExpiryField().render("#expiration-date");
                                  47 cardFields.CVVField().render("#cvv");
                                  48 } else {
                                  49 // Handle the workflow when credit and debit cards are not available
                                  50 }
                                  51 const submitButton = document.getElementById("submit"); submitButton.addEventListener("click", () => {
                                  52 cardFields
                                  53 .submit()
                                  54 .then(() => {
                                  55 console.log("submit was successful");
                                  56 })
                                  57 .catch((error) => {
                                  58 console.error("submit erred:", error);
                                  59 });
                                  60 });
                                  61 </script>
                                  62</body>
                                  63</html>

                                  9. Test saving cards

                                  Use the following card numbers to test transactions in the sandbox:

                                  See test card numbers and types
                                  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

                                  Test your integration to see if it saves credit and debit cards as expected. Any errors that occur appear in the onError callback provided to the CardFields component.

                                  1. Render the card fields.
                                  2. Create a save button in your UI.
                                  3. When the save button is selected:
                                    1. Create a setup token.
                                    2. Update the setup token with card details.
                                  4. On your server, use a server-side call to swap your setup token for a payment token from the Payment Method Tokens API.
                                    1. For a first-time payer, save the PayPal-generated customer.id.
                                    2. For a returning payer, use the PayPal-generated customer.id to swap the setup-token for a payment-token.
                                  5. Save the payment-token for future use.
                                  6. Show saved payment methods:
                                    1. Make a server-side call to the list all payment tokens endpoint. Include the PayPal-generated customer.id.
                                    2. Style the card fields.



                                  Optional: Show saved payment methods

                                  We recommend creating a page on your site where payers can see their saved payment methods as in the following example:

                                  A,website,showing,a,payment,methods,page.,The,page,shows,the,payer,saved,a,PayPal,Wallet,and,a,credit,card.,The,card,option,is,highlighted.

                                  Next step

                                  Go live with your integration.

                                  If you accept cookies, we’ll use them to improve and customize your experience and enable our partners to show you personalized PayPal ads when you visit other sites. Manage cookies and learn more