Documentation Archive

Developer

Apple Pay Programming Guide

On This Page

Creating Payment Requests

Payment requests are instances of the PKPaymentRequest class. A payment request consists of a list of summary items that describe to the user what is being paid for, a list of available shipping methods, a description of what shipping information the user needs to provide, and information about the merchant and the payment processor.

Decide Whether the User Can Make Payments

Before creating a payment request, determine whether the user will be able to make payments using a network that you support by calling the canMakePaymentsUsingNetworks: method of the PKPaymentAuthorizationViewController class. To check whether Apple Pay is supported by this device’s hardware and parental controls, use the canMakePayments method.

If canMakePayments returns NOfalse, the device does not support Apple Pay. Do not display the Apple Pay button. Instead, fall back to another method of payment.

If canMakePayments returns YEStrue but canMakePaymentsUsingNetworks: returns NOfalse, the device supports Apple Pay, but the user has not added a card for any of the requested networks. You can, optionally, display a payment setup button, prompting the user to set up their card. As soon as the user taps this button, initiate the process of setting up a new card (for example, by calling the openPaymentSetup method).

Otherwise, as soon as the user presses the Apple Pay button, you must begin the payment authorization process. Do not ask the user to perform any other tasks before presenting the payment request. For example, if the user needs to enter a discount code, you must ask for the code before they press the Apple Pay button.

To create an Apple Pay–branded button for initiating payment request on iOS 8.3 or later, use the PKPaymentButton class. For additional guidelines on using Apple Pay buttons and payment marks, see Apple Pay in iOS Human Interface Guidelines.

Bridging from Web-Based Interfaces

If your app uses a web-based interface for purchasing goods and services, you must move the request from the web interface to native iOS code before processing an Apple Pay transaction. Listing 3-1 shows the steps needed to process requests from a web view.

Listing 3-1Buying items from a web view
  1. // Called when the web view tries to load "myShoppingApp:buyItem"
  2. -(void)webView:(nonnull WKWebView *)webView
  3. decidePolicyForNavigationAction:(nonnull WKNavigationAction *)navigationAction
  4. decisionHandler:(nonnull void (^)(WKNavigationActionPolicy))decisionHandler {
  5. // Get the URL for the selected link.
  6. NSURL *URL = navigationAction.request.URL;
  7. // If the scheme and resource specifier match those defined by your app,
  8. // handle the payment in native iOS code.
  9. if ([URL.scheme isEqualToString:@"myShoppingApp"] &&
  10. [URL.resourceSpecifier isEqualToString:@"buyItem"]) {
  11. // Create and present the payment request here.
  12. // The web view ignores the link.
  13. decisionHandler(WKNavigationActionPolicyCancel);
  14. }
  15. // Otherwise the web view loads the link.
  16. decisionHandler(WKNavigationActionPolicyAllow);
  17. }

Payment Requests Include Currency and Region Information

All of the summary amounts in a payment request use the same currency, which is specified using the currencyCode property of PKPaymentRequest. Use a three-character ISO currency code, such as USD.

The payment request’s country code indicates the country where the purchase took place or where the purchase will be processed. Use a two-character ISO country code, such as US.

The merchant ID you set in a payment request must match one of the merchant IDs in your app’s entitlement.

  1. request.currencyCode = @"USD";
  2. request.countryCode = @"US";
  3. request.merchantIdentifier = @"merchant.com.example";

Payment Requests Have a List of Payment Summary Items

Payment summary items, represented by the PKPaymentSummaryItem class, describe the different parts of the payment request to the user. Use a small number of summary items—typically the subtotal, any discount, the shipping, the tax, and the grand total. If you do not have any additional fees (for example, shipping or tax), just use the purchase’s total. Provide granular details of the item-by-item costs elsewhere in your app.

Each summary item has a label and an amount, as shown in Listing 3-2. The label is a user-readable description of what the item summarizes. The amount is the corresponding payment amount. All of the amounts in a payment request use the currency specified in the payment request. For a discount or a coupon, set the amount to a negative number.

Listing 3-2Creating a payment summary item
  1. // 12.75 subtotal
  2. NSDecimalNumber *subtotalAmount = [NSDecimalNumber decimalNumberWithMantissa:1275 exponent:-2 isNegative:NO];
  3. self.subtotal = [PKPaymentSummaryItem summaryItemWithLabel:@"Subtotal" amount:subtotalAmount];
  4. // 2.00 discount
  5. NSDecimalNumber *discountAmount = [NSDecimalNumber decimalNumberWithMantissa:200 exponent:-2 isNegative:YES];
  6. self.discount = [PKPaymentSummaryItem summaryItemWithLabel:@"Discount" amount:discountAmount];

The last payment summary item in the list is the grand total. Calculate the grand total amount by adding the amounts of all the other summary items. The grand total is displayed differently from the other summary items: Use your company’s name as its label, and use the total of all the other summary items’ amounts as its amount. Add the payment summary items to the payment request using the paymentSummaryItems property.

If you do not know the actual cost when the payment is authorized (for example, a taxi fare), make a subtotal summary item using the PKPaymentSummaryItemTypePending type and a 0.0 amount. For the grand total, use a positive non-zero amount and the PKPaymentSummaryItemTypePending type. The system then shows the cost as pending without a numeric amount.

  1. // 10.75 grand total
  2. NSDecimalNumber *totalAmount = [NSDecimalNumber zero];
  3. totalAmount = [totalAmount decimalNumberByAdding:subtotalAmount];
  4. totalAmount = [totalAmount decimalNumberByAdding:discountAmount];
  5. self.total = [PKPaymentSummaryItem summaryItemWithLabel:@"My Company Name" amount:totalAmount];
  6. self.summaryItems = @[self.subtotal, self.discount, self.total];
  7. request.paymentSummaryItems = self.summaryItems;

A Shipping Method Is a Special Payment Summary Item

Create an instance of PKShippingMethod for each available shipping method. Just like other payment summary items, shipping methods have a user-readable label such as Standard Shipping or Next Day Shipping, and an amount that is the shipping cost. Unlike other summary items, shipping methods also have a detail property—such as “Arrives by July 29” or “Ships in 24 hours”—that explains the difference between shipping methods.

To distinguish shipping methods in your delegate methods, use the identifier property. This property is used only by your app—the framework treats it as an opaque value and it doesn’t appear in the UI. Assign a unique identifier for each shipping method when you create it. For ease of debugging, use a brief or abbreviated string, such as “discount,” “standard,” or “next-day.”

Some shipping methods aren’t available in all areas or have different costs for different addresses. You can update this information when the user selects a shipping address or method, as described in Your Delegate Updates Shipping Methods and Costs.

Indicating Your Supported Payment Processing Mechanisms

Indicate which payment networks you support by populating the supportedNetworks property with an array of string constants. Indicate which payment processing protocols you support by setting a value for the merchantCapabilities property. You must support 3DS; specify EMV only if you support Apple Pay in China.

The merchant capabilities are bit masks and are combined as follows:

  1. request.supportedNetworks = @[PKPaymentNetworkAmex, PKPaymentNetworkDiscover, PKPaymentNetworkMasterCard, PKPaymentNetworkVisa];
  2. // Supports 3DS only
  3. request.merchantCapabilities = PKMerchantCapability3DS;
  4. // Supports both 3DS and EMV (add EMV only if you support Apple Pay in China)
  5. request.merchantCapabilities = PKMerchantCapability3DS | PKMerchantCapabilityEMV;

Indicating What Shipping and Billing Information Is Needed

Populate the requiredBillingAddressFields and requiredShippingAddressFields properties of the payment authorization view controller to indicate what billing and shipping information is needed. When you present this view controller, it prompts the users to supply the requested billing and shipping information. The field constants are combined as follows to set values for these properties:

  1. request.requiredBillingAddressFields = PKAddressFieldEmail;
  2. request.requiredBillingAddressFields = PKAddressFieldEmail | PKAddressFieldPostalAddress;

If you have up-to-date billing and shipping contact information, you can set those on the payment request. Apple Pay uses this information by default; however, the user can still choose other contact information as part of the payment authorization process.

  1. PKContact *contact = [[PKContact alloc] init];
  2. NSPersonNameComponents *name = [[NSPersonNameComponents alloc] init];
  3. name.givenName = @"John";
  4. name.familyName = @"Appleseed";
  5. contact.name = name;
  6. CNMutablePostalAddress *address = [[CNMutablePostalAddress alloc] init];
  7. address.street = @"1234 Laurel Street";
  8. address.city = @"Atlanta";
  9. address.state = @"GA";
  10. address.postalCode = @"30303";
  11. contact.postalAddress = address;
  12. request.shippingContact = contact;

Storing Additional Information

To store information about the payment request that is specific to your app, such as in a shopping cart identifier, use the applicationData property. This property is treated as an opaque value by the system. A hash of the application data appears in the payment token after the user authorizes the payment request.