Save Apple Pay with the JavaScript SDK
DocsCurrentLast updated: September 19th 2024, @ 11:07:28 am
Save Apple Pay payment methods so merchants can make recurring payments without the payer being present.
Note: Apple Pay can't be used as a payment method for returning buyers, according to Apple guidelines.
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.
- The payer chooses to save their payment method.
- 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.
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:
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:
- Your platform.
- 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 \2 -H "Content-Type: application/json" \3 -H "Authorization: Bearer ACCESS-TOKEN" \4 -H "PayPal-Partner-Attribution-Id: BN-CODE" \5 -d '{6 "intent": "CAPTURE",7 "purchase_units": [{8 "reference_id": "d9f80740-38f0-11e8-b467-0ed5f89f718b",9 "amount": {10 "currency_code": "USD",11 "value": "100.00"12 }13 }],14 "payment_source": {15 "apple_pay": {16 "stored_credential": {17 "payment_initiator": "CUSTOMER",18 "payment_type": "RECURRING"19 },20 "attributes": {21 "vault": {22 "store_in_vault": "ON_SUCCESS"23 }24 }25 }26 }27 }
Note: When
payment_source.apple_pay.attributes.vault.store_in_vault
is set toON_SUCCESS
, that means the Apple Pay payment method is saved when the authorization or capture succeeds.
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 \2 -H "Content-Type: application/json" \3 -H "Authorization: Bearer ACCESS-TOKEN" \4 -d '{5 "intent": "CAPTURE",6 "purchase_units": [{7 "reference_id": "d9f80740-38f0-11e8-b467-0ed5f89f718b",8 "amount": {9 "currency_code": "USD",10 "value": "100.00"11 }12 }],13 "payment_source": {14 "apple_pay": {15 "stored_credential": {16 "payment_initiator": "CUSTOMER",17 "payment_type": "RECURRING"18 },19 "attributes": {20 "customer": {21 "id": "PayPal-generated customer id"22 },23 "vault": {24 "store_in_vault": "ON_SUCCESS"25 },26 }27 }28 }29 }
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 \2 -H "Content-Type: application/json" \3 -H "Authorization: Bearer ACCESS-TOKEN" \4 -H "PayPal-Partner-Attribution-Id: BN-CODE" \5 -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 -H "PayPal-Partner-Attribution-Id: BN-CODE" \5 -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
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 "href": "https://api-m.sandbox.paypal.com/v2/checkout/orders/5O190127TN364715T",6 "rel": "up",7 "method": "GET"8 }]9 }10}
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
- Make Orders API calls from your server with the Orders v2 API.
- Refer to the Capture Payment for Order endpoint 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
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 \2 -H "Content-Type: application/json" \3 -H "Authorization: Bearer ACCESS-TOKEN" \4 -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:
- Use the List All Payment Tokens endpoint of the Payment Method Tokens v3 API to retrieve all the payment methods saved for the customer.
- 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. - Log in to the sandbox with your merchant account and verify the transaction.
Note: The Javascript SDK has no direct support to show saved payments.
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 \2 -H "Content-Type: application/json" \3 -H "Authorization: Bearer ACCESS-TOKEN" \4 -d '{5 "intent": "CAPTURE",6 "purchase_units": [{7 "reference_id": "d9f80740-38f0-11e8-b467-0ed5f89f718b",8 "amount": {9 "currency_code": "USD",10 "value": "100.00"11 }12 }],13 "payment_source": {14 "apple_pay": {15 "stored_credential": {16 "payment_initiator": "MERCHANT",17 "payment_type": "RECURRING",18 "usage": "SUBSEQUENT",19 },20 "vault_id": "nkq2y9g"21 }22 }23 }
7. Test your integration
Test in the PayPal sandbox to ensure that saving payment methods works correctly.
Save payment method
- On your checkout page, enter your card information and select the option to save your card. You can use test card numbers for testing.
- Capture the payment.
- Log in to sandbox with your merchant account and verify the transaction.
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
- Test and go live with this integration. See the Go live section below for more details.
- Complete production onboarding to be eligible to process cards with your live PayPal account.
- Change the credentials and API URLs from
api-m.sandbox.paypal.com
toapi-m.paypal.com
when going live with your integration. - You can create orders without the
payment_source.paypal.attributes.vault
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.
- To manage subsequent or recurring transactions, see Use Saved Payment Token.
9. Go live
- Go to paypal.com and sign in with your business account.
- Go to Account Settings > Payment Method > Enable Apple Pay.
- In the Apple Pay payment methods section, select Get Started.
- 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.
- 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.