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 NO
false
, 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 YES
true
but canMakePaymentsUsingNetworks:
returns NO
false
, 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 his or her 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 he or she presses 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.
// Called when the web view tries to load "myShoppingApp:buyItem"
-(void)webView:(nonnull WKWebView *)webView
decidePolicyForNavigationAction:(nonnull WKNavigationAction *)navigationAction
decisionHandler:(nonnull void (^)(WKNavigationActionPolicy))decisionHandler {
// Get the URL for the selected link.
NSURL *URL = navigationAction.request.URL;
// If the scheme and resource specifier match those defined by your app,
// handle the payment in native iOS code.
if ([URL.scheme isEqualToString:@"myShoppingApp"] &&
[URL.resourceSpecifier isEqualToString:@"buyItem"]) {
// Create and present the payment request here.
// The web view ignores the link.
decisionHandler(WKNavigationActionPolicyCancel);
}
// Otherwise the web view loads the link.
decisionHandler(WKNavigationActionPolicyAllow);
}
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.
request.currencyCode = @"USD";
request.countryCode = @"US";
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.
// 12.75 subtotal
NSDecimalNumber *subtotalAmount = [NSDecimalNumber decimalNumberWithMantissa:1275 exponent:-2 isNegative:NO];
self.subtotal = [PKPaymentSummaryItem summaryItemWithLabel:@"Subtotal" amount:subtotalAmount];
// 2.00 discount
NSDecimalNumber *discountAmount = [NSDecimalNumber decimalNumberWithMantissa:200 exponent:-2 isNegative:YES];
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.
// 10.75 grand total
NSDecimalNumber *totalAmount = [NSDecimalNumber zero];
totalAmount = [totalAmount decimalNumberByAdding:subtotalAmount];
totalAmount = [totalAmount decimalNumberByAdding:discountAmount];
self.total = [PKPaymentSummaryItem summaryItemWithLabel:@"My Company Name" amount:totalAmount];
self.summaryItems = @[self.subtotal, self.discount, self.total];
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:
request.supportedNetworks = @[PKPaymentNetworkAmex, PKPaymentNetworkDiscover, PKPaymentNetworkMasterCard, PKPaymentNetworkVisa];
// Supports 3DS only
request.merchantCapabilities = PKMerchantCapability3DS;
// Supports both 3DS and EMV (add EMV only if you support Apple Pay in China)
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:
request.requiredBillingAddressFields = PKAddressFieldEmail;
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.
PKContact *contact = [[PKContact alloc] init];
NSPersonNameComponents *name = [[NSPersonNameComponents alloc] init];
name.givenName = @"John";
name.familyName = @"Appleseed";
contact.name = name;
CNMutablePostalAddress *address = [[CNMutablePostalAddress alloc] init];
address.street = @"1234 Laurel Street";
address.city = @"Atlanta";
address.state = @"GA";
address.postalCode = @"30303";
contact.postalAddress = address;
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.
Copyright © 2018 Apple Inc. All rights reserved. Terms of Use | Privacy Policy | Updated: 2017-03-16