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:

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:

  1. Generate a certificate signing request using the certificates API
  2. Send the CSR to Apple, which will sign the certificate
  3. Update the certificate record at Spreedly with the signed certificate PEM
  4. 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>security@yourorg.com</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>security@yourorg.com</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 cert

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>security@yourorg.com</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":"MIAGCSqGSIb3DQEHAqCAMIACAQExDzANBglghkgBZQMEAgEFADCABgkqhkiG9w0BBwEAAKCAMIID4jCCA4igAwIBAgIIJEPyqAad9XcwCgYIKoZIzj0EAwIwejEuMCwGA1UEAwwlQXBwbGUgQXBwbGljYXRpb24gSW50ZWdyYXRpb24gQ0EgLSBHMzEmMCQGA1UECwwdQXBwbGUgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxEzARBgNVBAoMCkFwcGxlIEluYy4xCzAJBgNVBAYTAlVTMB4XDTE0MDkyNTIyMDYxMVoXDTE5MDkyNDIyMDYxMVowXzElMCMGA1UEAwwcZWNjLXNtcC1icm9rZXItc2lnbl9VQzQtUFJPRDEUMBIGA1UECwwLaU9TIFN5c3RlbXMxEzARBgNVBAoMCkFwcGxlIEluYy4xCzAJBgNVBAYTAlVTMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEwhV37evWx7Ihj2jdcJChIY3HsL1vLCg9hGCV2Ur0pUEbg0IO2BHzQH6DMx8cVMP36zIg1rrV1O/0komJPnwPE6OCAhEwggINMEUGCCsGAQUFBwEBBDkwNzA1BggrBgEFBQcwAYYpaHR0cDovL29jc3AuYXBwbGUuY29tL29jc3AwNC1hcHBsZWFpY2EzMDEwHQYDVR0OBBYEFJRX22/VdIGGiYl2L35XhQfnm1gkMAwGA1UdEwEB/wQCMAAwHwYDVR0jBBgwFoAUI/JJxE+T5O8n5sT2KGw/orv9LkswggEdBgNVHSAEggEUMIIBEDCCAQwGCSqGSIb3Y2QFATCB/jCBwwYIKwYBBQUHAgIwgbYMgbNSZWxpYW5jZSBvbiB0aGlzIGNlcnRpZmljYXRlIGJ5IGFueSBwYXJ0eSBhc3N1bWVzIGFjY2VwdGFuY2Ugb2YgdGhlIHRoZW4gYXBwbGljYWJsZSBzdGFuZGFyZCB0ZXJtcyBhbmQgY29uZGl0aW9ucyBvZiB1c2UsIGNlcnRpZmljYXRlIHBvbGljeSBhbmQgY2VydGlmaWNhdGlvbiBwcmFjdGljZSBzdGF0ZW1lbnRzLjA2BggrBgEFBQcCARYqaHR0cDovL3d3dy5hcHBsZS5jb20vY2VydGlmaWNhdGVhdXRob3JpdHkvMDQGA1UdHwQtMCswKaAnoCWGI2h0dHA6Ly9jcmwuYXBwbGUuY29tL2FwcGxlYWljYTMuY3JsMA4GA1UdDwEB/wQEAwIHgDAPBgkqhkiG92NkBh0EAgUAMAoGCCqGSM49BAMCA0gAMEUCIHKKnw+Soyq5mXQr1V62c0BXKpaHodYu9TWXEPUWPpbpAiEAkTecfW6+W5l0r0ADfzTCPq2YtbS39w01XIayqBNy8bEwggLuMIICdaADAgECAghJbS+/OpjalzAKBggqhkjOPQQDAjBnMRswGQYDVQQDDBJBcHBsZSBSb290IENBIC0gRzMxJjAkBgNVBAsMHUFwcGxlIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MRMwEQYDVQQKDApBcHBsZSBJbmMuMQswCQYDVQQGEwJVUzAeFw0xNDA1MDYyMzQ2MzBaFw0yOTA1MDYyMzQ2MzBaMHoxLjAsBgNVBAMMJUFwcGxlIEFwcGxpY2F0aW9uIEludGVncmF0aW9uIENBIC0gRzMxJjAkBgNVBAsMHUFwcGxlIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MRMwEQYDVQQKDApBcHBsZSBJbmMuMQswCQYDVQQGEwJVUzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABPAXEYQZ12SF1RpeJYEHduiAou/ee65N4I38S5PhM1bVZls1riLQl3YNIk57ugj9dhfOiMt2u2ZwvsjoKYT/VEWjgfcwgfQwRgYIKwYBBQUHAQEEOjA4MDYGCCsGAQUFBzABhipodHRwOi8vb2NzcC5hcHBsZS5jb20vb2NzcDA0LWFwcGxlcm9vdGNhZzMwHQYDVR0OBBYEFCPyScRPk+TvJ+bE9ihsP6K7/S5LMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUu7DeoVgziJqkipnevr3rr9rLJKswNwYDVR0fBDAwLjAsoCqgKIYmaHR0cDovL2NybC5hcHBsZS5jb20vYXBwbGVyb290Y2FnMy5jcmwwDgYDVR0PAQH/BAQDAgEGMBAGCiqGSIb3Y2QGAg4EAgUAMAoGCCqGSM49BAMCA2cAMGQCMDrPcoNRFpmxhvs1w1bKYr/0F+3ZD3VNoo6+8ZyBXkK3ifiY95tZn5jVQQ2PnenC/gIwMi3VRCGwowV3bF3zODuQZ/0XfCwhbZZPxnJpghJvVPh6fRuZy5sJiSFhBpkPCZIdAAAxggFfMIIBWwIBATCBhjB6MS4wLAYDVQQDDCVBcHBsZSBBcHBsaWNhdGlvbiBJbnRlZ3JhdGlvbiBDQSAtIEczMSYwJAYDVQQLDB1BcHBsZSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTETMBEGA1UECgwKQXBwbGUgSW5jLjELMAkGA1UEBhMCVVMCCCRD8qgGnfV3MA0GCWCGSAFlAwQCAQUAoGkwGAYJKoZIhvcNAQkDMQsGCSqGSIb3DQEHATAcBgkqhkiG9w0BCQUxDxcNMTUwMjI0MTgzNTU5WjAvBgkqhkiG9w0BCQQxIgQgohbm8d0A42OAyMnc5fsgQoCNYjtEd/W/dW6+yezIwoAwCgYIKoZIzj0EAwIERzBFAiEAtEkap+JHypwfL1EdabD7RWPZol3na0LhMk9XzLhis0oCIGwxzOhQnMw+Td8WglTMNYcidqeYILTGzn3zMEXmW3j7AAAAAAAA","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).

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>
    <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>'

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

Recurring payments with Apple Pay are unfortunately not supported at this time.