# Save Apple Pay with the JavaScript SDK v5 (/sdk/js/v5/save-with-purchase/apple-pay)

Turn a checkout into a reusable Apple Pay payment method with the JavaScript SDK v5.



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

> **Info:** **Note:** Apple Pay can't be used as a payment method for returning buyers, according to Apple guidelines.

## How it works [#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 [#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](/v5/apple-pay/integrate) integration.
* Complete the steps in [Get started](/api/rest/) to get the following sandbox account information from the Developer Dashboard:
  * Sandbox client ID and secret of [a REST app](https://www.paypal.com/signin?returnUri=https%3A%2F%2Fdeveloper.paypal.com%2Fdeveloper%2Fapplications\&intent=developer).
  * Access token to use the PayPal REST API server.
* This integration uses the following:
  * [PayPal JavaScript SDK](/sdk/js/reference)
  * [Orders REST API](/api/orders/v2)

## 1. Enable Apple Pay [#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](/v5/apple-pay/integrate#1-set-up-your-sandbox-account-to-accept-apple-pay) for more information.

> **Info:** **Note:** When your integration is ready to go live, read the **Go live** section below for details about the additional steps needed for Apple Pay onboarding.

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:

<img src="https://paypalobjects.com/devdoc/sdk_acdc_acceptpayments.png" alt="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 [#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:

```javascript lineNumbers
// Note: the `applepayConfig` object in this request is the response from `paypal.Applepay().config()`.
const paymentRequest = {
  countryCode: applepayConfig.countryCode,
  merchantCapabilities: applepayConfig.merchantCapabilities,
  supportedNetworks: applepayConfig.supportedNetworks,
  currencyCode: "USD",
  requiredShippingContactFields: ["name", "phone", "email", "postalAddress"],
  requiredBillingContactFields: ["postalAddress"],
  lineItems: [
    {
      label: "Recurring",
      amount: "100.00",
      paymentTiming: "recurring",
      recurringPaymentStartDate: "2023-06-08T18:09:07.501Z",
    },
  ],
  total: {
    label: "Demo",
    type: "final",
    amount: "100.00",
  },
};
const session = new ApplePaySession(4, paymentRequest);
```

## 3. Create an order and save Apple Pay [#3-create-an-order-and-save-apple-pay]

### Server side [#server-side]

Set up your server-side integration to create the order and save the Apple Pay payment method.

Set up your server to call the [Create Order v2 API endpoint](/api/orders/v2/orders-create). 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](/api/orders/v2) 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 [#platform-considerations]

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

* Your platform.
* A merchant on your platform.

If you are a platform, pass the build notation (BN) code of the partner in the [`PayPal-Partner-Attribution-Id`](/api/rest/requests/#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`](/api/rest/requests/) 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-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 [#request]

```bash lineNumbers
curl -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 '{
      "intent": "CAPTURE",
      "purchase_units": [{
        "reference_id": "d9f80740-38f0-11e8-b467-0ed5f89f718b",
        "amount": {
         "currency_code": "USD",
          "value": "100.00"
        }
      }],
      "payment_source": {
        "apple_pay": {
          "stored_credential": {
            "payment_initiator": "CUSTOMER",
            "payment_type": "RECURRING"
          },
          "attributes": {
            "vault": {
              "store_in_vault": "ON_SUCCESS"
            }
          }
        }
      }
    }
```

> **Info:** **Note:** When `payment_source.apple_pay.attributes.vault.store_in_vault` is set to `ON_SUCCESS`, that means the Apple Pay payment method is saved when the authorization or capture succeeds.

### Response [#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.

```json lineNumbers
{
    "id": "5O190127TN364715T",
    "status": "CREATED",
    "intent": "CAPTURE",
    "payment_source": {
      "apple_pay": {
        "name": "Firstname Lastname",
       "email_address": "payer@example.com",
        "phone_number": {
           "national_number": "15555555555"
        },
        "card": {
            "name": "Firstname Lastname",
            "last_digits": "4949",
            "brand": "VISA",
            "type": "CREDIT",
            "billing_address": {
                "address_line_1": "123 Main St.",
                "admin_area_2": "Anytown",
                "admin_area_1": "CA",
                "postal_code": "12345",
                "country_code": "US"
            }
        }
    },
    "purchase_units": [{
      "reference_id": "d9f80740-38f0-11e8-b467-0ed5f89f718b",
      "amount": {
        "currency_code": "USD",
        "value": "100.00"
      }
    }],
    "create_time": "2021-10-28T21:18:49Z",
    "links": [{
        "href": "https://api-m.sandbox.paypal.com/v2/checkout/orders/5O190127TN364715T",
        "rel": "self",
        "method": "GET"
      },
      {
        "href": "https://www.sandbox.paypal.com/checkoutnow?token=5O190127TN364715T",
        "rel": "approve",
        "method": "GET"
      },
      {
        "href": "https://api-m.sandbox.paypal.com/v2/checkout/orders/5O190127TN364715T",
        "rel": "update",
        "method": "PATCH"
      },
      {
        "href": "https://api-m.sandbox.paypal.com/v2/checkout/orders/5O190127TN364715T/capture",
        "rel": "capture",
        "method": "POST"
      }
    ]
  }
```

### Save Apple Pay for returning payer [#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 [#request-1]

```bash lineNumbers
curl -v -X POST https://api-m.sandbox.paypal.com/v2/checkout/orders  -H "Content-Type: application/json"  -H "Authorization: Bearer ACCESS-TOKEN"  -d '{
      "intent": "CAPTURE",
      "purchase_units": [{
        "reference_id": "d9f80740-38f0-11e8-b467-0ed5f89f718b",
        "amount": {
          "currency_code": "USD",
          "value": "100.00"
        }
      }],
      "payment_source": {
        "apple_pay": {
          "stored_credential": {
            "payment_initiator": "CUSTOMER",
            "payment_type": "RECURRING"
          },
          "attributes": {
            "customer": {
                "id": "PayPal-generated customer id"
            },
            "vault": {
              "store_in_vault": "ON_SUCCESS"
            },
          }
        }
      }
    }
```

#### Response [#response-1]

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.

```json lineNumbers
{
  "id": "5O190127TN364715T",
  "status": "CREATED",
  "intent": "CAPTURE",
  "purchase_units": [
    {
      "reference_id": "d9f80740-38f0-11e8-b467-0ed5f89f718b",
      "amount": {
        "currency_code": "USD",
        "value": "100.00"
      }
    }
  ],
  "create_time": "2021-10-28T21:18:49Z",
  "links": [
    {
      "href": "https://api-m.sandbox.paypal.com/v2/checkout/orders/5O190127TN364715T",
      "rel": "self",
      "method": "GET"
    },
    {
      "href": "https://www.sandbox.paypal.com/checkoutnow?token=5O190127TN364715T",
      "rel": "approve",
      "method": "GET"
    },
    {
      "href": "https://api-m.sandbox.paypal.com/v2/checkout/orders/5O190127TN364715T",
      "rel": "update",
      "method": "PATCH"
    },
    {
      "href": "https://api-m.sandbox.paypal.com/v2/checkout/orders/5O190127TN364715T/capture",
      "rel": "capture",
      "method": "POST"
    }
  ]
}
```

## 4. Authorize or capture order [#4-authorize-or-capture-order]

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/orders/v2/orders-capture) API endpoint if the intent passed was `CAPTURE`.
* [Authorize Order v2](/api/orders/v2/orders-authorize) 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 [#request-2]

Send the following request based on the intent you passed when you created the order.

#### Authorize order request [#authorize-order-request]

```bash lineNumbers
curl -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 [#capture-order-request]

```bash lineNumbers
curl -v -X POST https://api-m.sandbox.paypal.com/v2/checkout/orders/5O190127TN364715T/capture \
 -H "Content-Type: application/json" \
 -H "Authorization: Bearer ACCESS-TOKEN" \
 -d '{}'
```

#### Response [#response-2]

```json lineNumbers
{
  "id": "5O190127TN364715T",
  "intent": "CAPTURE",
  "status": "COMPLETED",
  "payment_source": {
    "apple_pay": {
      "name": "Firstname Lastname",
      "email_address": "payer@example.com",
      "phone_number": {
        "national_number": "15555555555"
      },
      "card": {
        "name": "Firstname Lastname",
        "last_digits": "4949",
        "brand": "VISA",
        "type": "CREDIT",
        "billing_address": {
          "address_line_1": "123 Main St.",
          "admin_area_2": "Anytown",
          "admin_area_1": "CA",
          "postal_code": "12345",
          "country_code": "US"
        }
      },
      "attributes": {
        "vault": {
          "id": "nkq2y9g",
          "customer": {
            "id": "695922590"
          },
          "status": "VAULTED",
          "links": [
            {
              "href": "https://api-m.sandbox.paypal.com/v3/vault/payment-tokens/nkq2y9g",
              "rel": "self",
              "method": "GET"
            },
            {
              "href": "https://api-m.sandbox.paypal.com/v3/vault/payment-tokens/nkq2y9g",
              "rel": "delete",
              "method": "DELETE"
            },
            {
              "href": "https://api-m.sandbox.paypal.com/v2/checkout/orders/5O190127TN364715T",
              "rel": "up",
              "method": "GET"
            }
          ]
        }
      }
    }
  },
  "purchase_units": [
    {
      "reference_id": "d9f80740-38f0-11e8-b467-0ed5f89f718b",
      "payments": {
        "captures": [
          {
            "id": "3C679366HH908993F",
            "status": "COMPLETED",
            "amount": {
              "currency_code": "USD",
              "value": "100.00"
            },
            "seller_protection": {
              "status": "NOT_ELIGIBLE"
            },
            "final_capture": true,
            "seller_receivable_breakdown": {
              "gross_amount": {
                "currency_code": "USD",
                "value": "100.00"
              },
              "paypal_fee": {
                "currency_code": "USD",
                "value": "3.00"
              },
              "net_amount": {
                "currency_code": "USD",
                "value": "97.00"
              }
            },
            "create_time": "2022-01-01T21:20:49Z",
            "update_time": "2022-01-01T21:20:49Z",
            "processor_response": {
              "avs_code": "Y",
              "cvv_code": "M",
              "response_code": "0000"
            },
            "links": [
              {
                "href": "https://api-m.sandbox.paypal.com/v2/payments/captures/3C679366HH908993F",
                "rel": "self",
                "method": "GET"
              },
              {
                "href": "https://api-m.sandbox.paypal.com/v2/payments/captures/3C679366HH908993F/refund",
                "rel": "refund",
                "method": "POST"
              }
            ]
          }
        ]
      }
    }
  ],
  "links": [
    {
      "href": "https://api-m.sandbox.paypal.com/v2/checkout/orders/5O190127TN364715T",
      "rel": "self",
      "method": "GET"
    }
  ]
}
```

The response to the authorize or capture request shows that the Orders v2 API calls the [Payment Method Tokens v3 API](https://api-m.sandbox.paypal.com/v3/vault/payment-tokens/nkq2y9g) 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:

```json lineNumbers
"attributes": {
        "vault": {
          "status": "APPROVED",
          "links": [
            {
              "href": "https://api-m.sandbox.paypal.com/v2/checkout/orders/5O190127TN364715T",
              "rel": "up",
              "method": "GET"
            }
          ]
        }
      }
```

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](/api/rest/webhooks/event-names/#vault#vault).

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:

```json lineNumbers
{
  "id": "WH-1KN88282901968003-82E75604WM969463F",
  "event_version": "1.0",
  "create_time": "2022-08-15T14:13:48.978Z",
  "resource_type": "payment_token",
  "resource_version": "3.0",
  "event_type": "VAULT.PAYMENT-TOKEN.CREATED",
  "summary": "A payment token has been created.",
  "resource": {
    "time_created": "2022-08-15T07:13:48.964PDT",
    "links": [
      {
        "href": "https://api-m.sandbox.paypal.com/v3/vault/payment-tokens/9n6724m",
        "rel": "self",
        "method": "GET",
        "encType": "application/json"
      },
      {
        "href": "https://api-m.sandbox.paypal.com/v3/vault/payment-tokens/9n6724m",
        "rel": "delete",
        "method": "DELETE",
        "encType": "application/json"
      }
    ],
    "id": "nkq2y9g",
    "payment_source": {
      "card": {
        "last_digits": "1111",
        "brand": "VISA",
        "expiry": "2027-02",
        "billing_address": {
          "address_line_1": "123 Main St.",
          "admin_area_2": "Anytown",
          "admin_area_1": "CA",
          "postal_code": "12345",
          "country_code": "US"
        }
      }
    },
    "customer": {
      "id": "695922590"
    }
  },
  "links": [
    {
      "href": "https://api-m.sandbox.paypal.com/v1/notifications/webhooks-events/WH-1KN88282901968003-82E75604WM969463F",
      "rel": "self",
      "method": "GET"
    },
    {
      "href": "https://api-m.sandbox.paypal.com/v1/notifications/webhooks-events/WH-1KN88282901968003-82E75604WM969463F/resend",
      "rel": "resend",
      "method": "POST"
    }
  ]
}
```

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

### See also [#see-also]

* Make Orders API calls from your server with the [Orders v2 API](/api/orders/v2).
* Refer to the [Capture Payment for Order endpoint](/api/orders/v2/orders-capture) of the Orders v2 API to learn more about the values you can pass as you build your code.

## 5. Delete saved payment method token [#5-delete-saved-payment-method-token]

To delete a saved payment method token, call the [Delete Payment Token endpoint](/api/payment-tokens/v3/payment-tokens-delete) of the Payment Method Tokens v3 API:

```bash lineNumbers
curl -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 [#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](/api/orders/v2/orders-capture) 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](/api/payment-tokens/v3/customer-payment-tokens-get) 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](/api/orders/v2/orders-capture) of the Orders v2 API.
3. Log into the [sandbox](https://www.sandbox.paypal.com/) with your merchant account and verify the transaction.

> **Info:** **Note:** The JavaScript SDK has no direct support to show saved payments.

### Merchant-initiated transactions [#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:

```bash lineNumbers
curl -v -X POST https://api-m.sandbox.paypal.com/v2/checkout/orders  -H "Content-Type: application/json"  -H "Authorization: Bearer ACCESS-TOKEN"  -d '{
      "intent": "CAPTURE",
      "purchase_units": [{
        "reference_id": "d9f80740-38f0-11e8-b467-0ed5f89f718b",
        "amount": {
          "currency_code": "USD",
          "value": "100.00"
        }
      }],
      "payment_source": {
        "apple_pay": {
          "stored_credential": {
            "payment_initiator": "MERCHANT",
            "payment_type": "RECURRING",
            "usage": "SUBSEQUENT",
          },
          "vault_id": "nkq2y9g"
        }
      }
    }
```

## 7. Test your integration [#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](https://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 into 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 [#test-cards-for-apple-pay]

Refer to Apple's [sandbox testing page](https://developer.apple.com/apple-pay/sandbox-testing/) to learn more about using test cards for Apple Pay.

## 8. Next steps [#8-next-steps]

* Test and go live with this integration. See the **Go live** section below for more details.
* Complete [production onboarding](https://www.paypal.com/bizsignup/entry/product/ppcp) to be eligible to process cards with your live PayPal account.
* Change the credentials and API URLs from `api-m.sandbox.paypal.com` to `api-m.paypal.com` when going live with your integration.
* You can [create orders](/api/orders/v2/orders-create) without the `payment_source.paypal.attributes.vault` for subsequent or recurring transactions.
* You can [get a payment token](/api/payment-tokens/v3/payment-tokens-get), [list all payment tokens](/api/payment-tokens/v3/customer-payment-tokens-get), [delete a payment token](/api/payment-tokens/v3/payment-tokens-delete), and more with the [Payment Method Tokens API](/api/payment-tokens/v3).
* To manage subsequent or recurring transactions, see [Use Saved Payment Token](/api/payment-tokens/v3).

## 9. Go live [#9-go-live]

1. Go to paypal.com and log into 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 changes 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**. After the information is vetted, you get a **Success** status.
