Save Apple Pay with the JavaScript SDK

DOCSCURRENT

Last updated: Dec 13th, 12:45am

Save Apple Pay payment methods so merchants can make recurring payments without the payer being present.

How it works

When a payer on your website agrees to save the Apple Pay payment method, PayPal creates a customer record after the first successful transaction, encrypts the payment method information, and stores it in the vault. The saved payment information can only be accessed by the merchant. The merchant can use this saved payment method to make recurring payments on behalf of the payer.

  1. The payer chooses to save their payment method.
  2. For a first-time payer, PayPal generates a customer ID. Store this in your system for future use.

Know before you code

  • To accept one-time or recurring payments using Apple Pay, you need a business account that is approved by PayPal.
  • You'll need an existing Apple Pay integration.
  • Complete the steps in Get started to get the following sandbox account information from the Developer Dashboard:
    • Sandbox client ID and secret of a REST app.
    • Access token to use the PayPal REST API server.
  • This integration uses the following:

1. Enable Apple Pay

Before your app can save Apple Pay as a payment method, verify that your sandbox business account supports Apple Pay. See the Apple Pay integration guide for more information.

This screenshot shows the Apple Pay sandbox settings in the mobile and digital payments section of the PayPal Developer Dashboard. This only applies to direct merchant integrations:

A,screenshot,showing,the,Apple,Pay,sandbox,settings,in,the,mobile,and,digital,payments,section,of,the,PayPal,Developer,Dashboard

2. Create an Apple Pay Payment Session

An Apple Pay Payment Session is a payment sheet that PayPal shows to the payer to start a payment.

Request an Apple Pay Payment Session by passing the following request object:

    1// Note: the `applepayConfig` object in this request is the response from `paypal.Applepay().config()`.
    2const paymentRequest = {
    3 countryCode: applepayConfig.countryCode,
    4 merchantCapabilities: applepayConfig.merchantCapabilities,
    5 supportedNetworks: applepayConfig.supportedNetworks,
    6 currencyCode: "USD",
    7 requiredShippingContactFields: ["name", "phone", "email", "postalAddress"],
    8 requiredBillingContactFields: ["postalAddress"],
    9 lineItems: [
    10 {
    11 label: "Recurring",
    12 amount: "100.00",
    13 paymentTiming: "recurring",
    14 recurringPaymentStartDate: "2023-06-08T18:09:07.501Z"
    15 }
    16 ],
    17 total: {
    18 label: "Demo",
    19 type: "final",
    20 amount: "100.00"
    21 }
    22};
    23const session = new ApplePaySession(4, paymentRequest);

    3. Create order and Save Apple Pay

    Server-side

    Set up your server to call the Create Order v2 API endpoint. The Apple Pay button pressed on the client side determines the payment_source sent in the following sample.

    This SDK uses the Orders v2 REST API to save the Apple Pay payment method in the background. Add the attributes needed to save an Apple Pay payment method by using the request from Save Apple Pay for the first time below.


    Platform considerations

    When your platform saves a payment method, it can be owned by either:

    1. Your platform.
    2. A merchant on your platform.

    If you are a platform, pass the the build notation (BN) code of the partner in the PayPal-Partner-Attribution-Id header for server-side calls to the Orders API. PayPal uses this information for reporting and tracking purposes.

    For a merchant on your platform, pass the PayPal-Auth-Assertion header as part of calls to the Orders API. This ensures that the owner of the saved payment method is the merchant, not your platform.


    Save Apple Pay for the first time

    Save the Apple Pay payment method the first time a payer opts in. This request is for payers who meet both of these conditions:

    • Payer hasn't previously stored Apple Pay as a payment method for recurring purchases.
    • Payer consents to store the Apple Pay payment method for future use.

    Request

      1curl -v -X POST https://api-m.sandbox.paypal.com/v2/checkout/orders -H "Content-Type: application/json" -H "Authorization: Bearer ACCESS-TOKEN" -H "PayPal-Partner-Attribution-Id: BN-CODE" -d '{
      2 "intent": "CAPTURE",
      3 "purchase_units": [{
      4 "reference_id": "d9f80740-38f0-11e8-b467-0ed5f89f718b",
      5 "amount": {
      6 "currency_code": "USD",
      7 "value": "100.00"
      8 }
      9 }],
      10 "payment_source": {
      11 "apple_pay": {
      12 "stored_credential": {
      13 "payment_initiator": "CUSTOMER",
      14 "payment_type": "RECURRING"
      15 },
      16 "attributes": {
      17 "vault": {
      18 "store_in_vault": "ON_SUCCESS"
      19 }
      20 }
      21 }
      22 }
      23 }

      Response

      Pass the order.id to the JavaScript SDK. The SDK updates the order with the Apple Pay payment method that the payer selects. PayPal handles any PCI Compliance checks.

      The request needs to pass payment_source.attributes.vault.store_in_vault to save the Apple Pay payment method. Details about a saved payment method are available only after an order is authorized or captured.

        1{
        2 "id": "5O190127TN364715T",
        3 "status": "CREATED",
        4 "intent": "CAPTURE",
        5 "payment_source": {
        6 "apple_pay": {
        7 "name": "Firstname Lastname",
        8 "email_address": "payer@example.com",
        9 "phone_number": {
        10 "national_number": "15555555555"
        11 },
        12 "card": {
        13 "name": "Firstname Lastname",
        14 "last_digits": "4949",
        15 "brand": "VISA",
        16 "type": "CREDIT",
        17 "billing_address": {
        18 "address_line_1": "123 Main St.",
        19 "admin_area_2": "Anytown",
        20 "admin_area_1": "CA",
        21 "postal_code": "12345",
        22 "country_code": "US"
        23 }
        24 }
        25 },
        26 "purchase_units": [{
        27 "reference_id": "d9f80740-38f0-11e8-b467-0ed5f89f718b",
        28 "amount": {
        29 "currency_code": "USD",
        30 "value": "100.00"
        31 }
        32 }],
        33 "create_time": "2021-10-28T21:18:49Z",
        34 "links": [{
        35 "href": "https://api-m.sandbox.paypal.com/v2/checkout/orders/5O190127TN364715T",
        36 "rel": "self",
        37 "method": "GET"
        38 },
        39 {
        40 "href": "https://www.sandbox.paypal.com/checkoutnow?token=5O190127TN364715T",
        41 "rel": "approve",
        42 "method": "GET"
        43 },
        44 {
        45 "href": "https://api-m.sandbox.paypal.com/v2/checkout/orders/5O190127TN364715T",
        46 "rel": "update",
        47 "method": "PATCH"
        48 },
        49 {
        50 "href": "https://api-m.sandbox.paypal.com/v2/checkout/orders/5O190127TN364715T/capture",
        51 "rel": "capture",
        52 "method": "POST"
        53 }
        54 ]
        55 }

        Save Apple Pay for returning payer

        This request is for payers who:

        • Have an Apple Pay payment method already saved to the vault.
        • Want to save another Apple Pay payment method to the vault.

        Pass the previously-stored PayPal-generated customer.id as part of this request. Link additional payment_sources to this customer using their customer.id.


        Request

          1curl -v -X POST https://api-m.sandbox.paypal.com/v2/checkout/orders -H "Content-Type: application/json" -H "Authorization: Bearer ACCESS-TOKEN" -d '{
          2 "intent": "CAPTURE",
          3 "purchase_units": [{
          4 "reference_id": "d9f80740-38f0-11e8-b467-0ed5f89f718b",
          5 "amount": {
          6 "currency_code": "USD",
          7 "value": "100.00"
          8 }
          9 }],
          10 "payment_source": {
          11 "apple_pay": {
          12 "stored_credential": {
          13 "payment_initiator": "CUSTOMER",
          14 "payment_type": "RECURRING"
          15 },
          16 "attributes": {
          17 "customer": {
          18 "id": "PayPal-generated customer id"
          19 },
          20 "vault": {
          21 "store_in_vault": "ON_SUCCESS"
          22 },
          23 }
          24 }
          25 }
          26 }

          Response

          Pass the order.id to the JavaScript SDK. The SDK updates the order with the Apple Pay payment method that the payer selects. PayPal handles any PCI Compliance checks.

          The request needs to pass payment_source.attributes.vault.store_in_vault to save the Apple Pay payment method. Details about a saved payment method are available only after an order is authorized or captured.

            1{
            2 "id": "5O190127TN364715T",
            3 "status": "CREATED",
            4 "intent": "CAPTURE",
            5 "purchase_units": [{
            6 "reference_id": "d9f80740-38f0-11e8-b467-0ed5f89f718b",
            7 "amount": {
            8 "currency_code": "USD",
            9 "value": "100.00"
            10 }
            11 }],
            12 "create_time": "2021-10-28T21:18:49Z",
            13 "links": [{
            14 "href": "https://api-m.sandbox.paypal.com/v2/checkout/orders/5O190127TN364715T",
            15 "rel": "self",
            16 "method": "GET"
            17 },
            18 {
            19 "href": "https://www.sandbox.paypal.com/checkoutnow?token=5O190127TN364715T",
            20 "rel": "approve",
            21 "method": "GET"
            22 },
            23 {
            24 "href": "https://api-m.sandbox.paypal.com/v2/checkout/orders/5O190127TN364715T",
            25 "rel": "update",
            26 "method": "PATCH"
            27 },
            28 {
            29 "href": "https://api-m.sandbox.paypal.com/v2/checkout/orders/5O190127TN364715T/capture",
            30 "rel": "capture",
            31 "method": "POST"
            32 }
            33 ]
            34 }

            4. Authorize or capture order and save Apple Pay

            Set up your server to call the Authorize or Capture Order APIs:

            After the payer approves, the onApprove function is called in the JavaScript SDK. Depending on the intent passed as part of your Create Order call, the server calls the following APIs:

            • Capture Order v2 API endpoint if the intent passed was CAPTURE.
            • Authorize Order v2 API endpoint if the intent passed was AUTHORIZE.
            • Platform integrations need to pass the PayPal-Partner-Attribution-Id header for reporting and tracking purposes.


            Request

            Authorize order request

              1curl -v -X POST https://api-m.sandbox.paypal.com/v2/checkout/orders/5O190127TN364715T/authorize -H "Content-Type: application/json" -H "Authorization: Bearer ACCESS-TOKEN" -H "PayPal-Partner-Attribution-Id: BN-CODE" -d '{}'

              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 -d '{}'

                Response

                  1{
                  2 "id": "5O190127TN364715T",
                  3 "intent": "CAPTURE",
                  4 "status": "COMPLETED",
                  5 "payment_source": {
                  6 "apple_pay": {
                  7 "name": "Firstname Lastname",
                  8 "email_address": "payer@example.com",
                  9 "phone_number": {
                  10 "national_number": "15555555555"
                  11 },
                  12 "card": {
                  13 "name": "Firstname Lastname",
                  14 "last_digits": "4949",
                  15 "brand": "VISA",
                  16 "type": "CREDIT",
                  17 "billing_address": {
                  18 "address_line_1": "123 Main St.",
                  19 "admin_area_2": "Anytown",
                  20 "admin_area_1": "CA",
                  21 "postal_code": "12345",
                  22 "country_code": "US"
                  23 },
                  24 },
                  25 "attributes": {
                  26 "vault": {
                  27 "id": "nkq2y9g",
                  28 "customer": {
                  29 "id": "695922590"
                  30 },
                  31 "status": "VAULTED",
                  32 "links": [{
                  33 "href": "https://api-m.sandbox.paypal.com/v3/vault/payment-tokens/nkq2y9g",
                  34 "rel": "self",
                  35 "method": "GET"
                  36 },
                  37 {
                  38 "href": "https://api-m.sandbox.paypal.com/v3/vault/payment-tokens/nkq2y9g",
                  39 "rel": "delete",
                  40 "method": "DELETE"
                  41 },
                  42 {
                  43 "href": "https://api-m.sandbox.paypal.com/v2/checkout/orders/5O190127TN364715T",
                  44 "rel": "up",
                  45 "method": "GET"
                  46 }
                  47 ]
                  48 }
                  49 }
                  50 }
                  51 },
                  52 "purchase_units": [{
                  53 "reference_id": "d9f80740-38f0-11e8-b467-0ed5f89f718b",
                  54 "payments": {
                  55 "captures": [{
                  56 "id": "3C679366HH908993F",
                  57 "status": "COMPLETED",
                  58 "amount": {
                  59 "currency_code": "USD",
                  60 "value": "100.00"
                  61 },
                  62 "seller_protection": {
                  63 "status": "NOT_ELIGIBLE"
                  64 },
                  65 "final_capture": true,
                  66 "seller_receivable_breakdown": {
                  67 "gross_amount": {
                  68 "currency_code": "USD",
                  69 "value": "100.00"
                  70 },
                  71 "paypal_fee": {
                  72 "currency_code": "USD",
                  73 "value": "3.00"
                  74 },
                  75 "net_amount": {
                  76 "currency_code": "USD",
                  77 "value": "97.00"
                  78 }
                  79 },
                  80 "create_time": "2022-01-01T21:20:49Z",
                  81 "update_time": "2022-01-01T21:20:49Z",
                  82 "processor_response": {
                  83 "avs_code": "Y",
                  84 "cvv_code": "M",
                  85 "response_code": "0000"
                  86 },
                  87 "links": [{
                  88 "href": "https://api-m.sandbox.paypal.com/v2/payments/captures/3C679366HH908993F",
                  89 "rel": "self",
                  90 "method": "GET"
                  91 },
                  92 {
                  93 "href": "https://api-m.sandbox.paypal.com/v2/payments/captures/3C679366HH908993F/refund",
                  94 "rel": "refund",
                  95 "method": "POST"
                  96 }
                  97 ]
                  98 }]
                  99 }
                  100 }],
                  101 "links": [{
                  102 "href": "https://api-m.sandbox.paypal.com/v2/checkout/orders/5O190127TN364715T",
                  103 "rel": "self",
                  104 "method": "GET"
                  105 }]
                  106}

                  The response to the authorize or capture request shows that the Orders v2 API calls the Payment Method Tokens v3 API to save the payment method.

                  This response passes the relevant information with the vault.id when the vault.status is VAULTED. Use this vault.id for future payments.

                  Check Orders API response

                  Check Orders API response

                  When a payer chooses to save Apple Pay for recurring purchases and 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. "APPROVED" means the payment is approved to be saved.

                  Payment methods are saved with a vault.id if the response returned is "VAULTED". An example of an "APPROVED" status is in the following sample:

                    1"attributes": {
                    2 "vault": {
                    3 "status": "APPROVED",
                    4 "links": [
                    5 {
                    6 "href": "https://api-m.sandbox.paypal.com/v2/checkout/orders/5O190127TN364715T",
                    7 "rel": "up",
                    8 "method": "GET"
                    9 }
                    10 ]
                    11 }
                    12 }

                    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 "admin_area_2":"Anytown",
                      34 "admin_area_1":"CA",
                      35 "postal_code":"12345",
                      36 "country_code":"US"
                      37 }
                      38 }
                      39 },
                      40 "customer":{
                      41 "id":"695922590"
                      42 }
                      43 },
                      44 "links":[
                      45 {
                      46 "href":"https://api-m.sandbox.paypal.com/v1/notifications/webhooks-events/WH-1KN88282901968003-82E75604WM969463F",
                      47 "rel":"self",
                      48 "method":"GET"
                      49 },
                      50 {
                      51 "href":"https://api-m.sandbox.paypal.com/v1/notifications/webhooks-events/WH-1KN88282901968003-82E75604WM969463F/resend",
                      52 "rel":"resend",
                      53 "method":"POST"
                      54 }
                      55 ]
                      56 }

                      In the previous example, the resource.id field is the vault ID. The resource.customer.id is the PayPal-generated customer ID.

                      See also

                      5. Delete saved payment method token

                      To delete a saved payment method token, call the Delete Payment Token endpoint of the Payment Method Tokens v3 API:

                        1curl -v -X DELETE https://api-m.sandbox.paypal.com//v3/vault/payment-tokens/ nkq2y9g -H "Content-Type: application/json" -H "Authorization: Bearer ACCESS-TOKEN" -d '{}'

                        6. Pay with a saved payment method

                        Set up your checkout page to show a returning customer their saved Apple Pay payment method. Make a call to the Capture Payment for Order endpoint of the Orders v2 API and pass the apple_pay.vault_id.

                        To use a saved payment method:

                        1. Use the List All Payment Tokens endpoint of the Payment Method Tokens v3 API to retrieve all the payment methods saved for the customer.
                        2. Use the vault_id associated with the payment method the customer selected in the input of the Capture Payment for Order endpoint of the Orders v2 API.
                        3. Log in to the sandbox with your merchant account and verify the transaction.

                        Merchant-initiated transactions

                        For merchants or partners who want to process a recurring payment for a customer with an Apple Pay payment method already saved:

                          1curl -v -X POST https://api-m.sandbox.paypal.com/v2/checkout/orders -H "Content-Type: application/json" -H "Authorization: Bearer ACCESS-TOKEN" -d '{
                          2 "intent": "CAPTURE",
                          3 "purchase_units": [{
                          4 "reference_id": "d9f80740-38f0-11e8-b467-0ed5f89f718b",
                          5 "amount": {
                          6 "currency_code": "USD",
                          7 "value": "100.00"
                          8 }
                          9 }],
                          10 "payment_source": {
                          11 "apple_pay": {
                          12 "stored_credential": {
                          13 "payment_initiator": "MERCHANT",
                          14 "payment_type": "RECURRING",
                          15 "usage": "SUBSEQUENT",
                          16 },
                          17 "vault_id": "nkq2y9g"
                          18 }
                          19 }
                          20 }

                          7. Test your integration

                          Test your Apple Pay integration in the PayPal sandbox and production environments to ensure that your app works correctly.

                          Use your personal sandbox login information during checkout to complete a payment using Apple Pay. Then, log into the sandbox site sandbox.paypal.com to see that the money has moved into your account.

                          1. Open your test page with the Safari web browser on an iOS device or computer.
                          2. Get a test card from your Apple sandbox account.
                          3. Add the test card to your Apple Wallet on your iOS device or by using the Safari browser on the web.
                          4. Tap the Apple Pay button to open a pop-up with the Apple Pay payment sheet.
                          5. Make a payment using the Apple Pay payment sheet.
                          6. If you have an additional confirmation page on your merchant website, continue to confirm the payment.
                          7. Log in to your merchant account and continue to your confirmation page to confirm that the money you used for payment showed up in the account.


                          Test cards for Apple Pay

                          Refer to Apple's sandbox testing page to learn more about using test cards for Apple Pay.

                          8. Next steps

                          9. Go live

                          1. Go to paypal.com and sign in with your business account.
                          2. Go to Account Settings > Payment Method > Enable Apple Pay.
                          3. In the Apple Pay payment methods section, select Get Started.
                          4. After you submit the details on the Profile collection, your status will change to "Your eligibility to save customer Apple Pay payment methods is under review". It might be approved instantly as well.
                          5. Based on information provided in the profile collection of the Business Account, you might see a status like Denied, Success, or Need more information. Once the information is vetted, you get a Success status.

                          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