Apple Pay
Apple Pay is a mobile payment solution available on iOS devices. It uses several proprietary technologies to create an end-to-end, in-app and in-store, mobile payment experience. Because Apple Pay represents a significantly different workflow than other traditional payment methods, it’s important to first understand how it works before integrating with Spreedly.
Supported gateways
You can use Spreedly’s Apple Pay support with any gateway or endpoint that supports Network Tokenization. Today, that includes:
- Adyen
- Authorize.net
- Braintree
- Checkout.com
- CommerceHub
- CyberSource
- CyberSource REST
- Datatrans (Planet)
- Heartland Payment Systems
- Moneris
- Orbital
- Payeezy
- Payeezy (formerly GGE4)
- Stripe
- Stripe Payment Intents
- Spreedly Test gateway
- Vantiv eCommerce
- Vantiv Express
- WorldPay
If you’d like to use Apple Pay against a gateway not listed here that supports network tokenization, drop us a line.
How Apple Pay works
At the time of sale, Apple Pay encrypts a payment token that contains an alias PAN (card number), cryptogram, and basic transaction information and hands it to the merchant iOS app. From there it is up to the merchant app to send the payment token to a supporting processor. In traditional workflows, without Spreedly, the token is sent to one of the few gateways that natively support Apple Pay. This full lifecycle is outlined here:
With Spreedly
Spreedly’s Apple Pay support allows you to use Apple Pay against any gateway or endpoint that supports network tokenization (what Apple Pay is built on) without having your provisioning certificate locked into a single gateway.
The overall transaction flow is very similar to the traditional Apple Pay process. The only difference is that Spreedly becomes the Apple Pay certificate issuer and is responsible for decrypting the payment token on behalf of your chosen gateway or receiver. You can visualize the difference as follows:
The first step to using Apple Pay with Spreedly is to have Spreedly generate your Apple Pay certificate.
Generate certificate
To generate an Apple Pay certificate:
- Generate a certificate signing request using the certificates API
- Send the CSR to Apple, which will sign the certificate
- Update the certificate record at Spreedly with the signed certificate PEM
- Use the signed certificate in your iOS app
CSR
Invoke the generate certificate call using your environment credentials. Be sure to specify the ec-prime256v1 encryption algorithm and fill in the cn (common name) and email_address fields with relevant values.
curl https://core.spreedly.com/v1/certificates/generate.xml \ -u 'C7cRfNJGODKh4Iu5Ox3PToKjniY:4UIuWybmdythfNGPqAqyQnYha6s451ri0fYAo4p3drZUi7q2Jf4b7HKg8etDtoKJ' \ -H 'Content-Type: application/xml' \ -d '<certificate> <algorithm>ec-prime256v1</algorithm> <cn>MyApp ApplePay Production Certificate</cn> <email_address>[email protected]</email_address> </certificate>'
The certificate response will contain a csr field, which contains the PEM-formatted certificate signing request. Copy and paste that into a csr.pem file (or programmatically save it to disk). You will need to upload this to Apple in order for the certificate to be signed and usable in your iOS app.
<certificate> <token>82zijevOgorZWPq6FsP23iPSG3p</token> <algorithm>ec-prime256v1</algorithm> <cn>MyApp ApplePay Production Certificate</cn> <o nil="true"/> <ou nil="true"/> <c nil="true"/> <st nil="true"/> <l nil="true"/> <email_address>[email protected]</email_address> <public_key>-----BEGIN PUBLIC KEY----- MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAESaY3NYZANBCUGYvipMN5QbbdsGRH WLcrvfQ+QucP+XPOYjHRQRPe6McXjDwsxYvsGRWTGJ2BSuIu5gm/e5bOUw== -----END PUBLIC KEY----- </public_key> <public_key_hash>EZnY9rTkdJ00Vh8jwugcS0gwOdme7TF6Wk12XKuHz5I=</public_key_hash> <csr>-----BEGIN CERTIFICATE REQUEST----- MIIBSDCB7wIBADCBjDEuMCwGA1UEAwwlTXlBcHAgQXBwbGVQYXkgUHJvZHVjdGlv biBDZXJ0aWZpY2F0ZTEJMAcGA1UECgwAMQkwBwYDVQQLDAAxCTAHBgNVBAYTADEJ MAcGA1UECAwAMQkwBwYDVQQHDAAxIzAhBgkqhkiG9w0BCQEWFHNlY3VyaXR5QHlv dXJvcmcuY29tMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAESaY3NYZANBCUGYvi pMN5QbbdsGRHWLcrvfQ+QucP+XPOYjHRQRPe6McXjDwsxYvsGRWTGJ2BSuIu5gm/ e5bOU6AAMAoGCCqGSM49BAMCA0gAMEUCIQDoS6EhkPEUBey9n5JS7OVQEpfag/KE iPQFwHx452SAYQIgCfUdM0HB6x6JFiDB/mxypPtFeukc1JjU6A14c6lT6FY= -----END CERTIFICATE REQUEST----- </csr> <pem nil="true"/> <created_at type="dateTime">2019-03-20T19:52:34Z</created_at> <updated_at type="dateTime">2019-03-20T19:52:34Z</updated_at> </certificate>
Sign certificate
Log into the Apple iOS Developer Center and go the “Certificates, Identifiers & Profiles” section. In the create a new certificate view, select “Apple Pay Payment Processing Certificate”:
Next, select the Merchant ID for your certificate by navigating to the Merchant IDs page). If you have not created a Merchant ID yet you can create one here to link your certificate.
On the next page, under “Apple Pay Payment Processing Certificate”, click the button to “Create Certificate”. On the “Create A New Certificate” page, select the csr.pem file that contains the CSR value returned from the Spreedly certificate API call.
Press the “Generate” button and wait for the certificate to be signed. When the certificate has been signed, download it and include it in your iOS project.
Once this certificate has been signed and included in your iOS app, you must also update the certificate record at Spreedly to include the signed certificate.
Update signed certificate
Send the PEM-formatted signed certificate back to Spreedly by updating the certificate record.
curl https://core.spreedly.com/v1/certificates/NOTIlPqjM4Q9rmrHmrpxSWB96ph.xml \
-u 'C7cRfNJGODKh4Iu5Ox3PToKjniY:4UIuWybmdythfNGPqAqyQnYha6s451ri0fYAo4p3drZUi7q2Jf4b7HKg8etDtoKJ' \
-X PUT \
-H 'Content-Type: application/xml' \
-d '<certificate>
<pem><![CDATA[-----BEGIN CERTIFICATE-----
MIIEiTCCBC6gAwIBAgIIFRZ9ouKAzqwwCgYIKoZIzj0EAwIwgYAxNDAyBgNVBAMM
K0FwcGxlIFdvcmxkd2lkZSBEZXZlbG9wZXIgUmVsYXRpb25zIENBIC0gRzIxJjAk
BgNVBAsMHUFwcGxlIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MRMwEQYDVQQKDApB
cHBsZSBJbmMuMQswCQYDVQQGEwJVUzAeFw0xNTAyMTkyMDMzMzBaFw0xNzAzMjAy
MDMzMzBaMIG5MTowOAYKCZImiZPyLGQBAQwqbWVyY2hhbnQuY29tLnNlYXRnZWVr
LlNwcmVlZGx5QXBwbGVQYXlUZXN0MUAwPgYDVQQDDDdNZXJjaGFudCBJRDogbWVy
Y2hhbnQuY29tLnNlYXRnZWVrLlNwcmVlZGx5QXBwbGVQYXlUZXN0MRMwEQYDVQQL
DAo5QjNRWTlXQlo1MRcwFQYDVQQKDA5TZWF0R2VlaywgSW5jLjELMAkGA1UEBhMC
VVMwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAQhoBD6FaOXUJq3e4EoI7rWemTz
hLaPlAdF87WzmbhWKVNJ9LAEhrBjAtj6is765Ow2dnYta0QPF9EJoubwKOjKo4IC
VTCCAlEwRwYIKwYBBQUHAQEEOzA5MDcGCCsGAQUFBzABhitodHRwOi8vb2NzcC5h
cHBsZS5jb20vb2NzcDA0LWFwcGxld3dkcmNhMjAxMB0GA1UdDgQWBBQMV4lSAdev
m6sv1MVm5yR0gWij+jAMBgNVHRMBAf8EAjAAMB8GA1UdIwQYMBaAFIS2hMw6hmJy
FlmU6BqjvUjfOt8LMIIBHQYDVR0gBIIBFDCCARAwggEMBgkqhkiG92NkBQEwgf4w
gcMGCCsGAQUFBwICMIG2DIGzUmVsaWFuY2Ugb24gdGhpcyBjZXJ0aWZpY2F0ZSBi
eSBhbnkgcGFydHkgYXNzdW1lcyBhY2NlcHRhbmNlIG9mIHRoZSB0aGVuIGFwcGxp
Y2FibGUgc3RhbmRhcmQgdGVybXMgYW5kIGNvbmRpdGlvbnMgb2YgdXNlLCBjZXJ0
aWZpY2F0ZSBwb2xpY3kgYW5kIGNlcnRpZmljYXRpb24gcHJhY3RpY2Ugc3RhdGVt
ZW50cy4wNgYIKwYBBQUHAgEWKmh0dHA6Ly93d3cuYXBwbGUuY29tL2NlcnRpZmlj
YXRlYXV0aG9yaXR5LzA2BgNVHR8ELzAtMCugKaAnhiVodHRwOi8vY3JsLmFwcGxl
LmNvbS9hcHBsZXd3ZHJjYTIuY3JsMA4GA1UdDwEB/wQEAwIDKDBPBgkqhkiG92Nk
BiAEQgxAODlDQjI1MDkxOTI0RDY3RjlFMEM2QUVDMzA0MENBMkFGNzA4MEYzRTBG
Q0NFMTZBOTY5RDkyMUE0QkM5RTA1RjAKBggqhkjOPQQDAgNJADBGAiEAvKYdzDtD
Q87guVNkybbcEY1Y/nXO9Ry+4fVDwXYMET0CIQDEiK1+xSSziPZ/PPQHF8MCWsD0
LDW0aLigLHbDgQcrXA==
-----END CERTIFICATE-----
]]></pem>
</certificate>'
<certificate>
<token>BHD5mnpizTjP9NhlQqUuIMs8qFF</token>
<algorithm>ec-prime256v1</algorithm>
<cn>MyApp ApplePay Production Certificate</cn>
<o nil="true"/>
<ou nil="true"/>
<c nil="true"/>
<st nil="true"/>
<l nil="true"/>
<email_address>[email protected]</email_address>
<public_key>-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIaAQ+hWjl1Cat3uBKCO61npk84S2
j5QHRfO1s5m4VilTSfSwBIawYwLY+orO+uTsNnZ2LWtEDxfRCaLm8Cjoyg==
-----END PUBLIC KEY-----
</public_key>
<public_key_hash>/4UKqrtx7AmlRvLatYt9LDt64IYo+G9eaqqS6LFOAdI=</public_key_hash>
<csr>-----BEGIN CERTIFICATE REQUEST-----
MIIBSTCB7wIBADCBjDEuMCwGA1UEAwwlTXlBcHAgQXBwbGVQYXkgUHJvZHVjdGlv
biBDZXJ0aWZpY2F0ZTEJMAcGA1UECgwAMQkwBwYDVQQLDAAxCTAHBgNVBAYTADEJ
MAcGA1UECAwAMQkwBwYDVQQHDAAxIzAhBgkqhkiG9w0BCQEWFHNlY3VyaXR5QHlv
dXJvcmcuY29tMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE0fpMDOVsNWh56lzY
LLT8AUv77xfxIDEH0EvVcoDIGjO1wHwrUhp/p8kSVXYEt5i+jzE7UHEUNwrD5YtC
7i64hKAAMAoGCCqGSM49BAMCA0kAMEYCIQD0qoJM4EKR9DT6AIHNMm7I0Hwzu3rp
u7CIFgdchCsNeQIhANCstbvSt7ZwQY4abRS9GiTlFn3vGGjwGdeeXb0RmxGg
-----END CERTIFICATE REQUEST-----
</csr>
<pem>-----BEGIN CERTIFICATE-----
MIIEiTCCBC6gAwIBAgIIFRZ9ouKAzqwwCgYIKoZIzj0EAwIwgYAxNDAyBgNVBAMM
K0FwcGxlIFdvcmxkd2lkZSBEZXZlbG9wZXIgUmVsYXRpb25zIENBIC0gRzIxJjAk
BgNVBAsMHUFwcGxlIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MRMwEQYDVQQKDApB
cHBsZSBJbmMuMQswCQYDVQQGEwJVUzAeFw0xNTAyMTkyMDMzMzBaFw0xNzAzMjAy
MDMzMzBaMIG5MTowOAYKCZImiZPyLGQBAQwqbWVyY2hhbnQuY29tLnNlYXRnZWVr
LlNwcmVlZGx5QXBwbGVQYXlUZXN0MUAwPgYDVQQDDDdNZXJjaGFudCBJRDogbWVy
Y2hhbnQuY29tLnNlYXRnZWVrLlNwcmVlZGx5QXBwbGVQYXlUZXN0MRMwEQYDVQQL
DAo5QjNRWTlXQlo1MRcwFQYDVQQKDA5TZWF0R2VlaywgSW5jLjELMAkGA1UEBhMC
VVMwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAQhoBD6FaOXUJq3e4EoI7rWemTz
hLaPlAdF87WzmbhWKVNJ9LAEhrBjAtj6is765Ow2dnYta0QPF9EJoubwKOjKo4IC
VTCCAlEwRwYIKwYBBQUHAQEEOzA5MDcGCCsGAQUFBzABhitodHRwOi8vb2NzcC5h
cHBsZS5jb20vb2NzcDA0LWFwcGxld3dkcmNhMjAxMB0GA1UdDgQWBBQMV4lSAdev
m6sv1MVm5yR0gWij+jAMBgNVHRMBAf8EAjAAMB8GA1UdIwQYMBaAFIS2hMw6hmJy
FlmU6BqjvUjfOt8LMIIBHQYDVR0gBIIBFDCCARAwggEMBgkqhkiG92NkBQEwgf4w
gcMGCCsGAQUFBwICMIG2DIGzUmVsaWFuY2Ugb24gdGhpcyBjZXJ0aWZpY2F0ZSBi
eSBhbnkgcGFydHkgYXNzdW1lcyBhY2NlcHRhbmNlIG9mIHRoZSB0aGVuIGFwcGxp
Y2FibGUgc3RhbmRhcmQgdGVybXMgYW5kIGNvbmRpdGlvbnMgb2YgdXNlLCBjZXJ0
aWZpY2F0ZSBwb2xpY3kgYW5kIGNlcnRpZmljYXRpb24gcHJhY3RpY2Ugc3RhdGVt
ZW50cy4wNgYIKwYBBQUHAgEWKmh0dHA6Ly93d3cuYXBwbGUuY29tL2NlcnRpZmlj
YXRlYXV0aG9yaXR5LzA2BgNVHR8ELzAtMCugKaAnhiVodHRwOi8vY3JsLmFwcGxl
LmNvbS9hcHBsZXd3ZHJjYTIuY3JsMA4GA1UdDwEB/wQEAwIDKDBPBgkqhkiG92Nk
BiAEQgxAODlDQjI1MDkxOTI0RDY3RjlFMEM2QUVDMzA0MENBMkFGNzA4MEYzRTBG
Q0NFMTZBOTY5RDkyMUE0QkM5RTA1RjAKBggqhkjOPQQDAgNJADBGAiEAvKYdzDtD
Q87guVNkybbcEY1Y/nXO9Ry+4fVDwXYMET0CIQDEiK1+xSSziPZ/PPQHF8MCWsD0
LDW0aLigLHbDgQcrXA==
-----END CERTIFICATE-----
</pem>
<created_at type="dateTime">2017-06-27T18:16:35Z</created_at>
<updated_at type="dateTime">2017-07-27T17:51:48Z</updated_at>
</certificate>
With the signed certificate in place, any Apple Pay payment tokens generated by your app can be sent to Spreedly. Spreedly will use the corresponding private key to decrypt the token and transact against the embedded alias PAN and cryptogram.
Making a purchase
When an Apple Pay transaction is initiated in your iOS device, you will get a PKPaymentToken which contains a JSON-formatted paymentData string. This paymentData is what Spreedly needs to process the transaction and looks something like this:
{
"version":"EC_v1",
"data":"QlzLxRFnNP9/GTaMhBwgmZ2ywntbr9iOcBY4TjPZyNrnCwsJd2cq61bDQjo3agVU0LuEot2VIHHocVrp5jdy0FkxdFhGd+j7hPvutFYGwZPcuuBgROb0beA1wfGDi09I+OWL+8x5+8QPl+y8EAGJdWHXr4CuL7hEj4CjtUhfj5GYLMceUcvwgGaWY7WzqnEO9UwUowlDP9C3cD21cW8osn/IKROTInGcZB0mzM5bVHM73NSFiFepNL6rQtomp034C+p9mikB4nc+vR49oVop0Pf+uO7YVq7cIWrrpgMG7ussnc3u4bmr3JhCNtKZzRQ2MqTxKv/CfDq099JQIvTj8hbqswv1t+yQ5ZhJ3m4bcPwrcyIVej5J241R7dNPu9xVjM6LSOX9KeGZQGud",
"signature":"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",
"header":{
"ephemeralPublicKey":"MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEQwjaSlnZ3EXpwKfWAd2e1VnbS6vmioMyF6bNcq/Qd65NLQsjrPatzHWbJzG7v5vJtAyrf6WhoNx3C1VchQxYuw==",
"transactionId":"e220cc1504ec15835a375e9e8659e27dcbc1abe1f959a179d8308dd8211c9371",
"publicKeyHash":"/4UKqrtx7AmlRvLatYt9LDt64IYo+G9eaqqS6LFOAdI="
}
}
Transacting with an Apple Pay payment method is very similar to using a credit card. Depending on your gateway’s support, you can initiate an authorize or purchase, passing in the Apple Pay payment data string (you can also add an Apple Pay payment method as a separate call from the actual transaction
curl https://core.spreedly.com/v1/gateways/LlkjmEk0xNkcWrNixXa1fvNoTP4/purchase.xml \ -u 'C7cRfNJGODKh4Iu5Ox3PToKjniY:4UIuWybmdythfNGPqAqyQnYha6s451ri0fYAo4p3drZUi7q2Jf4b7HKg8etDtoKJ' \ -H 'Content-Type: application/xml' \ -d '<transaction> <apple_pay> <payment_data><![CDATA[{"version":"EC_v1","data":"QlzLxRFnNP9/GTaMhBwgmZ2ywntbr9iOcBY4TjPZyNrnCwsJd2cq61bDQjo3agVU0LuEot2VIHHocVrp5jdy0FkxdFhGd+j7hPvutFYGwZPcuuBgROb0beA1wfGDi09I+OWL+8x5+8QPl+y8EAGJdWHXr4CuL7hEj4CjtUhfj5GYLMceUcvwgGaWY7WzqnEO9UwUowlDP9C3cD21cW8osn/IKROTInGcZB0mzM5bVHM73NSFiFepNL6rQtomp034C+p9mikB4nc+vR49oVop0Pf+uO7YVq7cIWrrpgMG7ussnc3u4bmr3JhCNtKZzRQ2MqTxKv/CfDq099JQIvTj8hbqswv1t+yQ5ZhJ3m4bcPwrcyIVej5J241R7dNPu9xVjM6LSOX9KeGZQGud","signature":"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","header":{"ephemeralPublicKey":"MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEQwjaSlnZ3EXpwKfWAd2e1VnbS6vmioMyF6bNcq/Qd65NLQsjrPatzHWbJzG7v5vJtAyrf6WhoNx3C1VchQxYuw==","transactionId":"e220cc1504ec15835a375e9e8659e27dcbc1abe1f959a179d8308dd8211c9371","publicKeyHash":"/4UKqrtx7AmlRvLatYt9LDt64IYo+G9eaqqS6LFOAdI="}} ]]></payment_data> <test_card_number>4111111111111111</test_card_number> <!-- Remove in production --> </apple_pay> </transaction>'
The test_card_number parameter is available when you want to override the alias PAN contained in the payment data so it can be processed as a test transaction (since Apple doesn’t provide a way to generate test Apple Pay transactions, you must explicity mark it as such). You can use any test card number recognized by Spreedly here.
Apple Pay is unique in that the transaction id, amount and currency code are contained within the payment data, as is the optional customer name. These values are extracted by Spreedly and used in the transaction (as the order id, amount, currency code, and full name, respectively).
If you've requested a merchant token from Apple, also referred to as MPAN, and it is included in the encrypted payment data within the transaction, Spreedly will return the related fields and values in a
mpan_metadata
hash within the response body. You can learn more about merchant tokens and how they're used via Apple's developer documentation.Please note that Apple Pay transactions should not include attempt_3dsecure: true as a parameter. When Apple Pay payment methods are tokenized, 3DS has already been performed as part of that flow. For more information on 3DS, please refer to our Spreedly 3DS Solutions guide.
<transaction> <on_test_gateway type="boolean">true</on_test_gateway> <created_at type="dateTime">2017-07-27T17:52:55Z</created_at> <updated_at type="dateTime">2017-07-27T17:52:55Z</updated_at> <succeeded type="boolean">true</succeeded> <state>succeeded</state> <token>VLoscFsWpoxGUVCJ2MoyIVEUrN5</token> <transaction_type>Purchase</transaction_type> <order_id>e220cc1504ec15835a375e9e8659e27dcbc1abe1f959a179d8308dd8211c9371</order_id> <ip nil="true"/> <description nil="true"/> <email nil="true"/> <merchant_name_descriptor nil="true"/> <merchant_location_descriptor nil="true"/> <gateway_specific_fields nil="true"/> <gateway_specific_response_fields> </gateway_specific_response_fields> <gateway_transaction_id>65</gateway_transaction_id> <gateway_latency_ms type="integer">0</gateway_latency_ms> <amount type="integer">100</amount> <currency_code>USD</currency_code> <retain_on_success type="boolean">false</retain_on_success> <payment_method_added type="boolean">true</payment_method_added> <message key="messages.transaction_succeeded">Succeeded!</message> <gateway_token>T11bJAANtTWnxl36GYjKWvbNK0g</gateway_token> <shipping_address> <name></name> <address1 nil="true"/> <address2 nil="true"/> <city nil="true"/> <state nil="true"/> <zip nil="true"/> <country nil="true"/> <phone_number nil="true"/> </shipping_address> <response> <success type="boolean">true</success> <message>Successful purchase</message> <avs_code nil="true"/> <avs_message nil="true"/> <cvv_code nil="true"/> <cvv_message nil="true"/> <pending type="boolean">false</pending> <result_unknown type="boolean">false</result_unknown> <error_code></error_code> <error_detail nil="true"/> <cancelled type="boolean">false</cancelled> <fraud_review nil="true"/> <created_at type="dateTime">2017-07-27T17:52:55Z</created_at> <updated_at type="dateTime">2017-07-27T17:52:55Z</updated_at> </response> <api_urls> </api_urls> <payment_method> <token>RgGkf6vbV2QOuibYDq5F2hBjQy8</token> <created_at type="dateTime">2017-07-27T17:52:55Z</created_at> <updated_at type="dateTime">2017-07-27T17:52:55Z</updated_at> <email nil="true"/> <data nil="true"/> <storage_state>cached</storage_state> <test type="boolean">true</test> <last_four_digits>1111</last_four_digits> <first_six_digits>411111</first_six_digits> <card_type>visa</card_type> <first_name nil="true"/> <last_name nil="true"/> <month type="integer">3</month> <year type="integer">2018</year> <full_name></full_name> <address1 nil="true"/> <address2 nil="true"/> <city nil="true"/> <state nil="true"/> <zip nil="true"/> <country nil="true"/> <phone_number nil="true"/> <company nil="true"/> <shipping_address1 nil="true"/> <shipping_address2 nil="true"/> <shipping_city nil="true"/> <shipping_state nil="true"/> <shipping_zip nil="true"/> <shipping_country nil="true"/> <shipping_phone_number nil="true"/> <payment_method_type>apple_pay</payment_method_type> <mpan_metadata> <merchant_token_identifier>Example123</merchant_token_identifier> <merchant_token_metadata> <card_art> <name>nameoffile.png</name> <type>image/png</type> <url>www.sample-device-asset.apple.com</url> </card_art> <card_metadata> <expiration_date>null</expiration_date> <fpan_suffix>1111</fpan_suffix> </card_metadata> </merchant_token_metadata> </mpan_metadata> <errors> </errors> </payment_method> </transaction>
Already decrypted Apple Pay transactions
The majority of people using Apple Pay with Spreedly will pass the raw and encrypted JSON payment_data
parameter when transacting. However, in some cases, you may receive an already decrypted set of Apple Pay parameters or may even decrypt them yourself. If you have already decrypted parameters you can still store and transact with Apple Pay payment methods:
curl https://core.spreedly.com/v1/gateways/LlkjmEk0xNkcWrNixXa1fvNoTP4/purchase.xml \ -u 'C7cRfNJGODKh4Iu5Ox3PToKjniY:4UIuWybmdythfNGPqAqyQnYha6s451ri0fYAo4p3drZUi7q2Jf4b7HKg8etDtoKJ' \ -H 'Content-Type: application/xml' \ -d '<transaction> <apple_pay> <cardholder_name>Tim Jones</cardholder_name> <pan>4111111111111111</pan> <exp_date>200730</exp_date> <cryptogram>testcrytogramXXXXXXXXXXXX==</cryptogram> <eci_indicator>1</eci_indicator> <transaction_id>e220cc1504ec15835a375e9e8659e27dcbc1abe1f959a179d8308dd8211c9371</transaction_id> <transaction_amount>1299</transaction_amount> <currency_code>840</currency_code> </apple_pay> </transaction>'
Additional optional fields that can be included within the
apple_pay
body are related to merchant tokens, also known as MPAN. If applicable, include the following fields within theapple_pay
parameters:<mpan_metadata> <merchant_token_identifier>Example123</merchant_token_identifier> <merchant_token_metadata> <card_art> <name>nameoffile.png</name> <type>image/png</type> <url>www.sample-device-asset.apple.com</url> </card_art> <card_metadata> <expiration_date>null</expiration_date> <fpan_suffix>1111</fpan_suffix> </card_metadata> </merchant_token_metadata> </mpan_metadata>
Simply pass in the set of required Apple Pay fields instead of the payment_data JSON data and your transaction will process accordingly.
<transaction> <on_test_gateway type="boolean">true</on_test_gateway> <created_at type="dateTime">2017-07-27T17:52:56Z</created_at> <updated_at type="dateTime">2017-07-27T17:52:56Z</updated_at> <succeeded type="boolean">true</succeeded> <state>succeeded</state> <token>TnwZzXMl1pRVOsWNUDIM7Sx7VCW</token> <transaction_type>Purchase</transaction_type> <order_id>e220cc1504ec15835a375e9e8659e27dcbc1abe1f959a179d8308dd8211c9371</order_id> <ip nil="true"/> <description nil="true"/> <email nil="true"/> <merchant_name_descriptor nil="true"/> <merchant_location_descriptor nil="true"/> <gateway_specific_fields nil="true"/> <gateway_specific_response_fields> </gateway_specific_response_fields> <gateway_transaction_id>55</gateway_transaction_id> <gateway_latency_ms type="integer">0</gateway_latency_ms> <amount type="integer">1299</amount> <currency_code>USD</currency_code> <retain_on_success type="boolean">false</retain_on_success> <payment_method_added type="boolean">true</payment_method_added> <message key="messages.transaction_succeeded">Succeeded!</message> <gateway_token>T11bJAANtTWnxl36GYjKWvbNK0g</gateway_token> <shipping_address> <name>Tim Jones</name> <address1 nil="true"/> <address2 nil="true"/> <city nil="true"/> <state nil="true"/> <zip nil="true"/> <country nil="true"/> <phone_number nil="true"/> </shipping_address> <response> <success type="boolean">true</success> <message>Successful purchase</message> <avs_code nil="true"/> <avs_message nil="true"/> <cvv_code nil="true"/> <cvv_message nil="true"/> <pending type="boolean">false</pending> <result_unknown type="boolean">false</result_unknown> <error_code></error_code> <error_detail nil="true"/> <cancelled type="boolean">false</cancelled> <fraud_review nil="true"/> <created_at type="dateTime">2017-07-27T17:52:56Z</created_at> <updated_at type="dateTime">2017-07-27T17:52:56Z</updated_at> </response> <api_urls> </api_urls> <payment_method> <token>TVffCCZcddjyvZ1HstEUkSkf4Wx</token> <created_at type="dateTime">2017-07-27T17:52:56Z</created_at> <updated_at type="dateTime">2017-07-27T17:52:56Z</updated_at> <email nil="true"/> <data nil="true"/> <storage_state>cached</storage_state> <test type="boolean">true</test> <last_four_digits>1111</last_four_digits> <first_six_digits>411111</first_six_digits> <card_type>visa</card_type> <first_name>Tim</first_name> <last_name>Jones</last_name> <month type="integer">7</month> <year type="integer">2020</year> <full_name>Tim Jones</full_name> <address1 nil="true"/> <address2 nil="true"/> <city nil="true"/> <state nil="true"/> <zip nil="true"/> <country nil="true"/> <phone_number nil="true"/> <company nil="true"/> <shipping_address1 nil="true"/> <shipping_address2 nil="true"/> <shipping_city nil="true"/> <shipping_state nil="true"/> <shipping_zip nil="true"/> <shipping_country nil="true"/> <shipping_phone_number nil="true"/> <payment_method_type>apple_pay</payment_method_type> <errors> </errors> </payment_method> </transaction>
Apple Pay on the web
Implementing Apple Pay on the web is completely independent of using Spreedly iFrame. Spreedly iFrame does not interact with Apple Pay on the web nor does it need to. Apple returns the payment data to you in an encrypted form, you pass the encrypted data to Spreedly.
Certificates
Two certificates are required to use Apple Pay on the Web.
- Payment Processing Certificate: This certificate is used to securely transfer payment data. Apple uses the payment processing certificate’s public key to encrypt the payment data. Spreedly uses the private key to decrypt the data when processing payments. The same certificate can be used for both Apple Pay and Apple Pay on the Web. Implementing Apple Pay for use with Spreedly requires Spreedly hold the private key. Refer to Spreedly’s documentation for creating a Payment Processing Certificate.
- Merchant Identity Certificate: This certificate is generated by Apple. The certificate is placed on your servers and used to authenticate your merchant sessions. Step by step instructions to generate the Merchant Identity Certificate can be found in Apple’s full documentation.
Using Apple Pay JS on your web page
Using Apple Pay on the Web requires you to start an ApplePaySession (API reference) and make the necessary calls to generate a token. When the proper steps have been executed to generate a payment, the callback onpaymentauthorized will be called with an event. The event contains a payment attribute which contains a PaymentToken. The payment token contains a paymentData field. The paymentData field is used to create a payment method with Spreedly. Once Apple returns the Apple Pay token, return the Apple Pay token to your server. You can then create a payment method using an API call. You can also pass the Apple Pay token directly in for a purchase.
Recurring transactions
An Apple Pay recurring payment allows customers to perform regular payments without manually entering credit card details each time. This is especially useful for subscription services like streaming services, cloud storage, or gym memberships. From a merchant's standpoint, Apple Pay Recurring Payments offer a convenient and secure way to process recurring transactions from customers who have enabled Apple Pay on their devices.
An Apple Pay recurring payment can be done with device-specific tokens (DPANs) or with merchant tokens (MPANs). One of the main differences between DPAN and MPAN is that MPANs are not device specific so they don’t become invalid when a user upgrades to a new device. Another big difference is that DPANs are issued by Apple Pay while MPANs are issued by the issuing bank themselves. Spreedly currently supports the use of MPANs and you can learn more about them and how they're used via Apple's developer documentation .
To perform recurring Apple Pay transactions it is required for merchants to use the stored credential framework. This framework requires the use of two fields: stored_credential_initiator
and stored_credential_reason_type
. For more information on these fields and the stored credential framework in general see the Stored Credential guide .
Only certain gateways support Apple Pay recurring transactions. If a gateway does not support recurring payments, Spreedly will ignore the stored credential flagging and the transaction will get processed as a regular Apple Pay payment. The gateway may then decline any subsequent transactions. The gateways that support recurring Apple Pay are:
Apple Pay support for Merchant aggregators
Apple Pay Implementation for Merchant Aggregators will still follow the guidance provided in the above documentation with the following items in mind:
Apple Pay for mobile:
- Apple Pay will require a single Payment Processing Certificate for each mobile application. If your mobile application is shared by multiple sub-merchants, you can have the associated Payment Processing certificate at Spreedly configured as an organization level certificate so that it can be used across the sub-merchants.
- If your mobile application(s) are unique for each sub-merchant, then you can follow the general Apple Pay Guidance
Apple Pay for web:
- Create the Payment Processing Certificate as an organization level certificate following guidance on the certificates API i.e. include the parameter
level='organization'
- The organization level certificate will allow Spreedly to use the same certificate to decrypt Apple Pay data sent from your web application across all sub-merchants.
- Follow Mass Enablement Guidance from Apple Pay when onboarding or de-boarding sub-merchants.
Updated 20 days ago