Apple Pay
Accept Apple Pay on the Ginger Payments hosted payment page, or in your own checkout.
With Apple Pay, your customers pay with a card stored in their Apple Wallet, confirmed with Face ID, Touch ID or their device passcode. They don't enter card details. Apple Pay works in Safari and in apps on supported Apple devices.
You can accept Apple Pay in two ways:
| Integration | How it works | Apple registration |
|---|---|---|
| Hosted payment page | Ginger Payments shows the Apple Pay button on the hosted payment page. | Not needed |
| Server-to-server | You show the Apple Pay button in your own checkout and send the payment token to the API. | Needed: you integrate with Apple Pay on the web |
Hosted payment page
On the hosted payment page, you don't need to register with Apple. The page checks whether your customer's device and browser support Apple Pay, and only then shows the Apple Pay button.
Once Apple Pay is active in your project, it appears on the hosted payment page along with your other payment methods. To send your customer straight to Apple Pay, create the order with apple-pay as the payment method:
curl https://api.dev.gingerpayments.com/v1/orders/ \
--user "$API_KEY:" \
--header "Content-Type: application/json" \
--data '{
"currency": "EUR",
"amount": 995,
"merchant_order_id": "EXAMPLE001",
"description": "Example Apple Pay order",
"return_url": "https://www.example.com/order/EXAMPLE001",
"webhook_url": "https://www.example.com/webhook",
"transactions": [
{
"payment_method": "apple-pay"
}
],
"customer": {
"merchant_customer_id": "123456789",
"email_address": "user@example.com",
"first_name": "John",
"last_name": "Smith",
"address_type": "billing",
"address": "100 Main St",
"postal_code": "SW1A 1AA",
"city": "London",
"country": "GB",
"locale": "en",
"phone_numbers": ["+441234567890"],
"ip_address": "198.51.100.1"
}
}'Redirect your customer to the payment_url of the transaction in the response. Then handle the result as for any other payment: wait for the webhook and check the order status.
Server-to-server
With a server-to-server integration, you show the Apple Pay button in your own checkout. Before you start, read Apple's documentation and make sure your integration follows it:
- Apple Pay on the web
- Acceptable use guidelines for Apple Pay on the web
- Apple Pay human interface guidelines
You can process the payment token from Apple in two ways:
| Flow | Who decrypts the Apple Pay token | Who manages the Apple Pay keys |
|---|---|---|
| Encrypted payload | Ginger Payments | Ginger Payments |
| Decrypted payload | You | You |
Encrypted payload
You pass the encrypted payment token from Apple to Ginger Payments. Ginger Payments decrypts it and stores the card in the vault.
Not available in test mode
You can't test the encrypted payload flow in a test project. Test it in a live project with small amounts, in a controlled setting.
| Step | Endpoint | What it does |
|---|---|---|
| 1 | POST /v1/orders/ | Creates the order and the Apple Pay transaction. |
| 2 | POST /v1/apple-pay/sessions/ | Validates your merchant session with Apple. |
| 3 | POST /v1/apple-pay/payment-tokens/persist/ | Decrypts the payment token and returns a vaultToken, cryptogram and ECI indicator. |
| 4 | POST /pay/{order_id}/select-payment-method/apple-pay/{transaction_id}/ | Executes the payment. |
Create the order
Create an order with an apple-pay transaction, as in the hosted payment page example. The response contains the IDs and the setup token you need in the next steps:
{
"id": "6bf8a727-bef2-4420-8d41-af82f6f19f3d",
"project_id": "05ad138f-52fa-40dc-9751-5fde949dcb57",
"status": "new",
"transactions": [
{
"id": "59f5866a-c216-472e-b803-8a4e83c4578a",
"payment_method": "apple-pay",
"payment_method_details": {
"setup_token": "c6d0a22b-df22-41a2-aac1-d647173ff219"
},
"status": "new"
}
]
}The response is shortened. Save the order id, the project_id, the transaction id and the setup_token.
Start the Apple Pay session
When your customer taps the Apple Pay button, Apple triggers the onvalidatemerchant event in the browser. Send the event.validationURL to your server, and request a merchant session from the API:
curl https://api.dev.gingerpayments.com/v1/apple-pay/sessions/ \
--user "$API_KEY:" \
--header "Content-Type: application/json" \
--data '{
"validationUrl": "https://apple-pay-gateway.apple.com/paymentservices/startSession",
"merchantIdentifier": "05ad138f52fa40dc97515fde949dcb57",
"displayName": "Example Shop",
"initiativeContext": "shop.example.com"
}'| Field | Description |
|---|---|
validationUrl | The event.validationURL from Apple Pay. |
merchantIdentifier | Your project ID without hyphens. |
displayName | The name of your shop, as shown to your customer. Use the trade name of your project. |
initiativeContext | The domain of your payment page. |
The response contains the merchant session from Apple:
{
"sessionData": "..."
}Pass the sessionData to session.completeMerchantValidation() in the browser to complete the merchant validation.
Store the payment details
After your customer confirms the payment, Apple triggers the onpaymentauthorized event. It contains the encrypted payment token in event.payment.token.paymentData. Send its contents to the API, together with the setupToken from step 1:
curl https://api.dev.gingerpayments.com/v1/apple-pay/payment-tokens/persist/ \
--user "$API_KEY:" \
--header "Content-Type: application/json" \
--data '{
"setupToken": "c6d0a22b-df22-41a2-aac1-d647173ff219",
"data": "C+YChH...dTlaSmc=",
"signature": "MIAGCSqGSIb3DQ...==",
"header": {
"publicKeyHash": "yFMDm...s=",
"ephemeralPublicKey": "MFkwEwYHKo...SoHnSg==",
"transactionId": "878...4c52"
},
"version": "EC_v1"
}'Apple describes the fields in its payment token format reference.
The response contains what you need to execute the payment:
{
"vaultToken": "d972dc43-6a3d-4dcf-b54e-6e9a0fe325e3",
"onlinePaymentCryptogram": "AgAAAAAABk4DWZ4C28yUQAAAAAA=",
"eciIndicator": "7"
}Execute the payment
Send the vault token, cryptogram and ECI indicator to the payment URL of the transaction:
curl https://api.dev.gingerpayments.com/pay/6bf8a727-bef2-4420-8d41-af82f6f19f3d/select-payment-method/apple-pay/59f5866a-c216-472e-b803-8a4e83c4578a/ \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data '{
"vault_token": "d972dc43-6a3d-4dcf-b54e-6e9a0fe325e3",
"online_payment_cryptogram": "AgAAAAAABk4DWZ4C28yUQAAAAAA=",
"eci_indicator": "7"
}'{
"is_successful": true,
"redirect_url": "https://api.dev.gingerpayments.com/pay/6bf8a727-bef2-4420-8d41-af82f6f19f3d/59f5866a-c216-472e-b803-8a4e83c4578a/completed/",
"reason": "none"
}Redirect your customer to the redirect_url. Then wait for the webhook and check the order status before you deliver.
Decrypted payload
You decrypt the payment token from Apple yourself, with your own Apple Pay keys, and store the card details in the Ginger Payments vault.
You handle card data
The decrypted payload contains the card number. Your systems must be PCI DSS compliant to process it. See Server-to-server.
| Step | Endpoint | What it does |
|---|---|---|
| 1 | POST /v1/orders/ | Creates the order and the Apple Pay transaction. |
| 2 | Apple Pay | Your customer confirms the payment. You decrypt the payload. |
| 3 | POST https://tokens.dev.gingerpayments.com/v1/cards/ | Stores the card details in the vault and returns a vault_token. |
| 4 | POST /pay/{order_id}/select-payment-method/apple-pay/{transaction_id}/ | Executes the payment. |
Create the order
Create an order with an apple-pay transaction, as in the hosted payment page example. Save the order id, the transaction id and the setup_token from payment_method_details.
Get the payment data from Apple
Your customer taps the Apple Pay button and confirms the payment. Apple returns an encrypted payload. Decrypt it with your Apple Pay keys, and take the card number, expiry date, online payment cryptogram and ECI indicator from it.
Store the card details
Store the card in the vault with the setup_token from step 1. The expiry date uses the format MMYYYY:
curl https://tokens.dev.gingerpayments.com/v1/cards/ \
--user "$API_KEY:" \
--header "Content-Type: application/json" \
--data '{
"pan": "4871049999999910",
"expiry": "122028",
"setup_token": "c6d0a22b-df22-41a2-aac1-d647173ff219"
}'{
"brand": "visa",
"brands": ["visa"],
"truncated_pan": "4871********9910",
"vault_token": "d972dc43-6a3d-4dcf-b54e-6e9a0fe325e3"
}The setup token can be used once, within 300 seconds after the order was created.
Execute the payment
Send the vault_token from the vault, and the cryptogram and ECI indicator from the decrypted payload, to the payment URL of the transaction:
curl https://api.dev.gingerpayments.com/pay/6bf8a727-bef2-4420-8d41-af82f6f19f3d/select-payment-method/apple-pay/59f5866a-c216-472e-b803-8a4e83c4578a/ \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data '{
"vault_token": "d972dc43-6a3d-4dcf-b54e-6e9a0fe325e3",
"online_payment_cryptogram": "AgAAAAAABk4DWZ4C28yUQAAAAAA=",
"eci_indicator": "7"
}'The response is the same as in the encrypted payload flow. Redirect your customer to the redirect_url, then check the order status.
Customer details
Send the customer object with every Apple Pay order. Depending on your acquirer, these fields can be required:
| Field | Description |
|---|---|
merchant_customer_id | Your own customer reference. |
email_address | Your customer's email address. |
first_name | 1 to 120 characters. Pattern: ^[\w -,\.À-ÖØ-öø-ÿ]+$ |
last_name | 1 to 120 characters. Pattern: ^[\w -,\.À-ÖØ-öø-ÿ]+$ |
address_type | Always billing. |
address | Billing address, 1 to 120 characters. Pattern: ^[\w -,\.\-À-ÖØ-öø-ÿ]+$ |
postal_code | 1 to 10 characters. Pattern: ^[A-Z0-9]+( [A-Z0-9]*)?$ |
city | 1 to 120 characters. Pattern: ^[\w -,\.\-À-ÖØ-öø-ÿ]+$ |
country | ISO 3166-1 alpha-2 country code, such as GB. |
phone_numbers | List of phone numbers, including the country code. |
Recurring payments
Apple Pay supports recurring payments. See Recurring payments with Apple Pay.