Flight journal

A journey in ProcessOut's mission control

Open-Sourcing our Apple Pay Go Library

by Louis-Paul Dareau on

At ProcessOut, we have supported Apple Pay since last year. If you are like us and want to own your payment stack, it is critical not to rely on a single provider to handle your processing. However, Apple Pay relies on an intricate token encryption scheme which makes it both more secure and harder to implement. There is very little code available to help with the full implementation, beyond Apple’s own examples—which are client-side only. Because of that, we had to develop our own server-side Apple Pay library for ProcessOut, which we aptly call applepay. Today, we are open-sourcing this high-quality implementation in Go. Find it at https://github.com/processout/applepay.

The rest of this article will discuss both the architecture of Apple Pay for online transactions and a short introduction of the applepay library.

A Technical Primer on Apple Pay

At their core, payment methods like Apple Pay or Android Pay (now a part of Google Pay) are enabled by recent card network-related features; Apple wraps these with clever cryptography to ensure confidentiality is maintained.

Transaction Primitives

The most important part of new payment systems like Apple Pay is called network tokens. These network tokens are in principle very similar to the tokens you may already know (i.e. gateway tokens): they replace a card number and are reversed during the payment process. The fundamental difference is where the tokens come from: while standard tokens are created by a third-party Payment Service Provider (such as ProcessOut), network tokens come directly from card networks, such as Visa and Mastercard. To work with existing systems, they look like a standard card number, but carry an additional field for a digital signature: the cryptogram.

The cryptogram is a cryptographically-signed piece of data which guarantees the authenticity of the token. We will expand on how cryptograms are generated and where they are used later on. These transaction objects are card network features, not specific to Apple. Apple Pay wraps these primitives with on-device token generation and public-key cryptography.

Cryptography Primitives

One of the keys to well-designed, secure large-scale systems is a robust key hierarchy. For working with Apple Pay, merchants need two asymmetric certificate/private key combos:

  • Payment Processing Certificate: used by clients to encrypt the final tokens;
  • Merchant Identity Certificate: used by the merchant’s server to make requests to the Apple Pay Gateway API.

Both of these certificates are generated locally by the merchant and need to be signed using the Apple Developer Console. Additionally, the Merchant Identity Certificate is linked to the merchant’s domain. We have handily included a few samples and a way to generate them easily with the cfssl tool in our repository. Note that an Apple Developer Program account is required ($99/year at the time of writing).

Putting it Together in Apple Pay

For users, the Apple Pay flow consists in adding a card to the Wallet app on their device, before tapping the Apple Pay button during checkout on an app or website that supports it. As you can imagine, there is a little more depth to it, in part by using the network tokens we described previously.

When adding a card to the Wallet app, the device contacts the issuer bank to check for Apple Pay support. If Apple Pay is supported, the process (“Link and Provision”) generates a Device Account Number (DAN), which is then encrypted within the device’s Secure Element (a hardware security module). After this step, the card is available to use with Apple Pay for physical and online transactions. No actual card details are ever stored on-device or sent to Apple.

To pay online or within apps, the developer chooses whether to display the Apple Pay button—this is done by checking if the client API is available. Once the button is tapped, the payment sheet appears and an Apple Pay session is created. This session uses two pieces of data:

  • The information that will be displayed to the user, such as the final price (a PaymentRequest in Apple’s jargon);
  • The Apple Pay session payload, which is requested from the merchant’s server.

The session payload is generated by having the merchant’s server make a request to the Apple Pay Gateway, which in turn returns an opaque session payload to send to the client’s device. The reason this request needs to go through the merchant’s backend is that session requests are authenticated with the Merchant Identity Certificate and its key.

At this point in the flow, the device both has the checkout information and knows how to submit a payment. After the biometric authentication step, which is a critical part of the transaction’s security, a token is generated. The token is composed of the Device Account Number and of the cryptogram we discussed earlier. The device encrypts everything using the merchant’s Payment Processing Certificate, before the client submits the transaction details to the merchant. Some additional information is included, such as the last 4 digits of the credit card or the card’s network.

After receiving the token, the merchant’s server should be able to decrypt it. The cleartext output looks very much like the details of a standard credit card, expiration date included, with the addition of the cryptogram. Thanks to this feature, merchants only need to add the cryptogram to their usual payment processing requests.

The applepay library

Applying everything we learned previously, our library is designed around a very simple interface, to help with the two core functions the merchant’s server has to perform:

  • Creating an Apple Pay session: the Session method;
  • Decrypting a token: the DecryptToken method.

In addition to this, applepay automatically takes care of loading, parsing and validating certificates.

The Apple Pay server-side flow being very sparsely documented, we primarily used two resources for writing our library: the rather dense PassKit reference and Etsy’s PHP module (written in C). Some parts of our code are linked against OpenSSL; this is because Apple Pay makes use of PKCS7 signatures, which are not supported by the Go standard library.

Gopher illustration by Renée French

Apple, the Apple logo, and Apple Pay are trademarks of Apple Inc., registered in the U.S. and other countries.