A Better Guide For Setting Up Apple Pay

By Aaron Ritchie & Jeffrey Rodrigues

Apple Pay is becoming ever more popular as it allows for in-store, in-app, and in-browser purchasing to be made easier. More companies are looking to implement it, and it is becoming a necessity in any m-commerce type apps.

When one of our clients decided to introduce m-commerce into their app recently, Apple Pay implementation was inevitable. Difficulties arose when trying to activate Apple Pay as we found gaps in the existing documentation. In an attempt to ease the process for others on our team, as well as anyone else trying to implement Apple Pay in their own apps, we created a tutorial to illustrate our process and how we were able to achieve a successful implementation of Apple Pay.

Setting Up Apple Pay Requirements

Before writing any code, there are a number of steps you will have to take to prepare your app to handle payments. You will also need to choose a payment platform to handle processing credit card payments. Apple provides a list of recommended platforms on their Apple Pay Developer Page. For our project, we used Bambora (formerly Beanstream).

Setting Up a Merchant ID

The first step involves creating your Merchant ID.

Log into your developer account on the Apple Developer Portal (https://developer.apple.com/) website and navigate to the Certificates, Identifiers & Profiles (https://developer.apple.com/account/ios/identifier/merchant) section. In the Identifiers subsection, select Merchant IDs.

Note: This section is not available for Enterprise accounts (apps that are not distributed to customers via the App Store.) Enterprise apps do not support Apple Pay.

  1. Click the Add [+] button.
  2. Give your Merchant ID a description.
  3. Give your Merchant ID an identifier. This should be in reverse-domain format and be prefixed with the word “merchant”. A good convention to follow is to use the Bundle Identifier of your app (for example, if your app’s bundle identifier is com.mycompany.myapp, your merchant identifier would be merchant.com.mycompany.myapp).
  4. Click Continue. Then Register. Then Done. Now you’re done.

Creating a Payment Processing Certificate

The next step involves creating your payment processing certificate. This certificate is explicitly tied to your Merchant ID and will reside on your payment platform’s server. It is responsible for decrypting the encrypted credit card information that your app will send to the payment platform.

  1. After creating your Merchant ID, select it from the list and click Edit.
  2. In the Payment Processing Certificate section, click Create Certificate.

At this point you will need to upload a CSR (Certificate Signing Request) file. Some payment platforms will provide a CSR for you to use, for others you can create your own. For Bambora, we created our own CSR by following the steps outlined below:

  1. Launch Keychain Access on your Mac.
  2. In the toolbar select Keychain Access > Certificate Assistant > Request a Certificate From a Certificate Authority…
  3. Fill in your Email Address and Name, and select “Saved to disk” and “Let me specify key pair information” then click Continue.
  4. Select a location to save the file to.
  5. Specify the following key pair information:
    • Key Size: 256 bits
    • Algorithm: ECC

Now upload the CSR file. The final step in the process will present you with the option to download the Payment Processing Certificate as a .cer file. Do this now and upload it to your payment platform.

Enabling Apple Pay Capabilities in Your App

The last step in setting up your app to support Apple Pay is to enable capabilities within your Xcode project. This is where you will be specifying your Merchant ID. All Apple Pay encrypted payments made in your app will only be able to be decrypted by the certificate with the matching Merchant ID (the certificate uploaded in the previous step).

  1. In Xcode’s project navigator, select your project file.
  2. With your main target selected, select the Capabilities tab.
  3. Switch on the Apple Pay capability and add your Merchant ID. Make sure it is selected.

Now you are ready to start writing code to implement Apple Pay in your project.

Availability

There are two main aspects to the availability of Apple Pay:

  • Device compatibility
  • Payment card availability

Device Availability

Apple Pay has been available since the release of iOS 8.1 in October 2014, and is now directly compatible with 7 iPhone devices dating back to the iPhone 6. The PassKit framework allows for simple recognition for if the user’s device meets all necessary requirements to use Apple Pay. Both the PKPaymentAuthorizationController and PKPaymentAuthorizationViewController classes can be utilized to determine the device compatibility. These classes differ in the dependency on the UIKit, allowing the authorization controller to be used in watchOS apps or SiriKit extensions.


if PKPaymentAuthorizationViewController.canMakePayments()
{
    // Apple Pay is available.
}
else
{
    // Apple Pay is unavailable.
}

The above code uses the canMakePayments() function to return whether the user is able to make payments based on if their device is Apple Pay compatible.

Payment Card Availability

The second step in determining Apple Pay availability is verifying that the user has payment cards set up in their Wallet app. Apple Pay supports up to ten payment networks including Visa, MasterCard, American Express, and debit cards. Any combination of these payment networks can be specified as compatible payment options.

Using the PKPaymentAuthorizationViewController class, compare the Wallet app payment cards to an array of payment networks to validate payment card availability.


if PKPaymentAuthorizationViewController.canMakePayments(
    usingNetworks: [PKPaymentNetworks])
{
    // Apple Pay is available.
}
else
{
    // Apple Pay needs to be set up.
}

Setting up UI Elements

The PassKit framework also provides a PKPaymentButton class that is to be used for any Apple Pay buttons. After receiving responses for device and payment availability, present the user with the proper payment button configuration. Apple has provided black, white, and white with black outline styled buttons to contrast various background colours. It is important to not customize a UIButton and follow the Apple Identity guidelines for PKPayment buttons. Using these guidelines there are three possibilities from the available results above that will alter the interface of the application.

For each Apple Pay button that needs to be displayed, a new PKPayment Button will need to be created and initialized. This can be done as follows:


init(paymentButtonType: PKPaymentButtonType,
    paymentButtonStyle: PKPaymentButtonStyle)

Device Not Compatible

In the situation that Apple Pay is unavailable for the device being used, the user interface needs to be adjusted as to display any options available for other payment methods. Often this will include hiding any Apple Pay payment buttons and only displaying an option for manual entry of payment information.

Device Compatible, Payment Cards Not Set Up

The next possibility is the case that the device is compatible but the Wallet app does not have a payment card that matches the desired payment networks. For this case, the setup button type is used to allow the user to set up their payment cards in their Wallet App.

The button first is initialized:


PKPaymentButton(type: .setup, style: .black)

Add an action to the setup button that uses the PKPassLibrary class of the PassKit framework to initiate the process of setting up payment cards in the Wallet app.


let passLibrary = PKPassLibrary()
passLibrary.openPaymentSetup()

When returning to the app, make sure to send a notification that the app has become active and update the display of the Apple Pay button. Otherwise, the user may be caught being prompted to setup payment cards that have already been added to their Wallet app.

Device Compatible, Payment Cards Set Up

In the case that the device is compatible and cards are already setup, the user should be presented with an opportunity to buy using Apple Pay. This is also the state the user should be displayed after returning from setting up payment cards in their Wallet app. Create the button using the same initialization step as in setup, though changing the PKPaymentButtonType to the buy case.


PKPaymentButton(type: .buy, style: .black)

When the buy button is invoked, the payment request needs to be created and displayed.

Requesting Payment

In order to request a payment using Apple Pay, a collection of payment networks, merchant information, processing capabilities, payment amounts, contact fields, and other application data is needed. To do so, this information is added to an instance of the PKPaymentRequest class.


let request = PKPaymentRequest()
request.supportedNetworks    = [PKPaymentNetworks]
request.countryCode          = "CA">
request.currencyCode         = "CAD"
request.merchantIdentifier   = "Merchant ID name"
request.merchantCapabilities = .capability3DS

The request can also take information related to billing and shipping information, contact information, shipping methods, and shipping type. The other important thing to add is PKSummaryItems. Summary items will be displayed in the Apple Pay sheet as the receipt items. For this example, the following summary items will be created:


let item1 = PKPaymentSummaryItem(label: “Item 1”, amount: 19.99)
let item2 = PKPaymentSummaryItem(label: “Item 2”, amount: 24.99)
let shipping = PKPaymentSummaryItem(label: “Shipping”, amount: 10.00)
let tax = PKPaymentSummaryItem(label: “Tax”, amount: 7.15)
let total = PKPaymentSummaryItem(label: “Total”, amount: 62.13)

The summary items can then be added to the request as an array of PKSummaryItems.


request.paymentSummaryItems = [item1, item2, shipping, tax, total]

When all the necessary information is added to the PKSummaryRequest, the request can be passed to a PKPaymentAuthorizationViewController and displayed.


let viewController = PKPaymentAuthorizationViewController(
    paymentRequest: request)
viewController.delegate = self
self.present(viewController, animated: true, completion: nil)

Payment Sheet Interaction

When interacting with the PKPaymentAuthorizationViewController, there are two scenarios that need to be considered: authorization of the payment, and navigation when the view controller has been dismissed. These scenarios are covered by the two required protocol methods of the PKPaymentAuthorizationViewControllerDelegate.


func paymentAuthorizationViewController(_ controller:
    PKPaymentAuthorizationViewController,
    didAuthorizePayment payment: PKPayment,
    completion: @escaping (PKPaymentAuthorizationStatus) -> Void)

func paymentAuthorizationViewControllerDidFinish(_ controller:
    PKPaymentAuthorizationViewController)

The first method will provide the payment token that contains billing information for the user from the Wallet app. The token can be passed to an e-commerce solution for payment authorization. Based on the server result for placing the order, complete the block using a PKPaymentAuthorizationStatus of success or failure.


func paymentAuthorizationViewController(_ controller:
    PKPaymentAuthorizationViewController,
    didAuthorizePayment payment: PKPayment,
    completion: @escaping (PKPaymentAuthorizationStatus) -> Void)
{
    let paymentToken =
        payment.token.paymentData.base64EncodedString()
    // Place order using paymentToken

    if place order is successful
        completion(PKPaymentAuthorizationStatus.success)
    else
        PKPaymentAuthorizationStatus.failure
}

Using the PKPaymentAuthorizationStatus will automatically provide the user with an indication of the place order result.

The second required delegate method is where navigation from the payment screen is performed. There are two cases by which this delegate method will be called: after the user has been displayed the status of the previous completion block, or if the payment sheet is canceled by the user without attempting to authorize the payment.


func paymentAuthorizationViewControllerDidFinish(_ controller:
    PKPaymentAuthorizationViewController)
{
    if successful place order
    {
        self.dismiss(animated: true, completion: {
            // navigate to home screen
        })
    }
    else if failed place order
    {
        self.dismiss(animated: true, completion: {
            // show errors
        })
    }
    else // if cancelled
    {
        self.dismiss(animated: true)
    }
}

In each case above the Apple Pay payment sheet is dismissed and the previous action dictates the state of the application.

Sandbox Testing

Now that you’ve finished writing your code, it’s time to test making payments. You probably don’t want to test using your actual credit card out of fear of accidental charges at the end of the month. Fortunately, the Apple Pay Sandbox provides developers with a way to test their Apple Pay setup in a risk-free environment.

  1. To begin, you will need to log in to your iTunes Connect account (https://itunesconnect.com/).
  2. Navigate into the Users and Roles section and click on Sandbox Testers.
  3. Click Add [+], fill out your test account information, and Save.

Now that your account is set up, you will need to set your test account in your iCloud settings on your testing device. Once this is complete, you can add one or several of Apple’s available test cards to your Wallet. Apple provides a list of test cards here: https://developer.apple.com/support/apple-pay-sandbox/.