//  AppleTool.h

//  ApplePayTool


//  Created by liangkun on 16/8/1.

//  Copyright © 2016 liangkun. All rights reserved.


#import <Foundation/Foundation.h>

#import <UIKit/UIKit.h>

#import <PassKit/PassKit.h>

@interface AppleTool : NSObject


 *  用户的姓名


@property(nonatomic,strong) NSString *userName;


 *  商品的价格


@property(nonatomic,assign) unsigned long long  price;


 *  商品的折扣(不可为零)


@property(nonatomic,assign) unsigned long long disCount;




 *  @param PayAbout 支付相关的其它内容不需要其它相关内容可直接调用init方法


 *  @return


+(instancetype)initWith:(NSObject *)PayAbout;




 *  @return 当前设备是否支持ApplePay服务


+ (BOOL)isUserCanMakePayment;




 *  @return 获取要展示的ApplePay支付界面


- (PKPaymentAuthorizationViewController*)getAuthorzationViewController;

- (void)verifyApplePayWith:(NSData *)paymentTocken Result:(void(^)(BOOL success))result;



//  AppleTool.m

//  ApplePayTool


//  Created by liangkun on 16/8/1.

//  Copyright © 2016 liangkun. All rights reserved.


//extern NSString * const PKEncryptionSchemeECC_V2 NS_AVAILABLE_IOS(9_0);


//extern NSString * const PKPaymentNetworkAmex NS_AVAILABLE(NA, 8_0);

//extern NSString * const PKPaymentNetworkChinaUnionPay NS_AVAILABLE(NA, 9_2);

//extern NSString * const PKPaymentNetworkDiscover NS_AVAILABLE(NA, 9_0);

//extern NSString * const PKPaymentNetworkInterac NS_AVAILABLE(NA, 9_2);

//extern NSString * const PKPaymentNetworkMasterCard NS_AVAILABLE(NA, 8_0);

//extern NSString * const PKPaymentNetworkPrivateLabel NS_AVAILABLE(NA, 9_0);

//extern NSString * const PKPaymentNetworkVisa NS_AVAILABLE(NA, 8_0);

//PKMerchantCapability3DS                                 = 1UL << 0,   // Merchant supports 3DS

//PKMerchantCapabilityEMV                                 = 1UL << 1,   // Merchant supports EMV

//PKMerchantCapabilityCredit NS_ENUM_AVAILABLE_IOS(9_0)   = 1UL << 2,   // Merchant supports credit

//PKMerchantCapabilityDebit  NS_ENUM_AVAILABLE_IOS(9_0)   = 1UL << 3    // Merchant supports debit

#import "AppleTool.h"

@interface AppleTool()

@property (nonatomic, strong) NSArray *SupportnetWorks;


@implementation AppleTool

- (instancetype)init



    if (self = [super init]) {






    return self;



+ (instancetype)initWith:(NSObject *)PayAbout


    AppleTool *tool = [[AppleTool alloc]init];


    if (tool) {




    return tool;




 *   检测当前的硬件和家长控制


 *  @return 硬件是否支持和是否有家长控制等原因


+ (BOOL)isUserCanMakePayment


    BOOL canMakePayment = [PKPaymentAuthorizationViewController canMakePayments];


    return canMakePayment;



 *  当前的用户是否为请求网络添加卡


 *  @return 用户是否添加银行卡为这个手机


- (BOOL)isUserCanMakePaymentUseingNetWork


    BOOL canMakePaymetUserNet = [PKPaymentAuthorizationViewController canMakePaymentsUsingNetworks:self.SupportnetWorks];


    return canMakePaymetUserNet;



- (PKPaymentRequest *)createPaymentRequest


    PKPaymentRequest *request = [[PKPaymentRequest alloc]init];


    request.supportedNetworks = @[PKPaymentNetworkAmex, PKPaymentNetworkDiscover, PKPaymentNetworkMasterCard, PKPaymentNetworkVisa,PKPaymentNetworkChinaUnionPay];


    request.merchantCapabilities = PKMerchantCapability3DS | PKMerchantCapabilityEMV|PKMerchantCapabilityCredit|PKMerchantCapabilityDebit;


    request.countryCode = @"CN";

    request.currencyCode = @"CNY";

    request.merchantIdentifier = @"商户在开发者帐号中申请的ID";





     *  配置请求的联系人


    request.shippingContact = [self getUserContact];


    NSDecimalNumber *subtotalAmount = [NSDecimalNumber decimalNumberWithMantissa:self.price exponent:0 isNegative:NO];


     PKPaymentSummaryItem *subtotal = [PKPaymentSummaryItem summaryItemWithLabel:@"小计" amount:subtotalAmount];


    // 2.00 discount

//    打折

    if (self.disCount > 0) {

        NSDecimalNumber *discountAmount = [NSDecimalNumber decimalNumberWithMantissa:self.disCount exponent:0 isNegative:YES];

        PKPaymentSummaryItem *discount = [PKPaymentSummaryItem summaryItemWithLabel:@"打折" amount:discountAmount];



        NSDecimalNumber *totalAmount = [NSDecimalNumber zero];


        totalAmount = [totalAmount decimalNumberByAdding:subtotalAmount];


        PKPaymentSummaryItem *total = [PKPaymentSummaryItem summaryItemWithLabel:@"有妖气" amount:totalAmount];


        NSArray *summaryItems = @[subtotal,discount,total];


        request.paymentSummaryItems = summaryItems;

    } else



        NSDecimalNumber *totalAmount = [NSDecimalNumber zero];


        totalAmount = [totalAmount decimalNumberByAdding:subtotalAmount];


        PKPaymentSummaryItem *total = [PKPaymentSummaryItem summaryItemWithLabel:@"有妖气" amount:totalAmount];


        NSArray *summaryItems = @[subtotal,total];


        request.paymentSummaryItems = summaryItems;







//    request.requiredShippingAddressFields = PKAddressFieldAll;



    return request;




    PKContact *contact = [[PKContact alloc] init];




    NSPersonNameComponents *name = [[NSPersonNameComponents alloc] init];

    name.nickname = self.userName;// 用户名 = name;


    return contact;


- (PKPaymentAuthorizationViewController*)getAuthorzationViewController


    PKPaymentAuthorizationViewController *viewController = [[PKPaymentAuthorizationViewController alloc] initWithPaymentRequest:[self createPaymentRequest]];

       return viewController;


- (void)verifyApplePayWith:(NSData *)paymentTocken Result:(void (^)(BOOL))result



     *  保存当前的数据到云上


    [self savePaymentDataToiCloudWith:paymentTocken];


     NSString *encodeStr = [paymentTocken base64EncodedStringWithOptions: NSDataBase64EncodingEndLineWithCarriageReturn];







- (void)savePaymentDataToiCloudWith:(NSData*)paymentTocken



    NSUbiquitousKeyValueStore *storage = [NSUbiquitousKeyValueStore defaultStore];


    [storage setObject:@[paymentTocken] forKey:@"applePayMentTocken"];


    [storage synchronize];


//- (void)clearPaymentDataIniCloud:()




        AppleTool *applePayTool = [[AppleTool alloc]init];

        applePayTool.price = (unsigned long long)100;

        applePayTool.disCount = 12;

        applePayTool.userName = @"jack Jhon";


        PKPaymentAuthorizationViewController *viewController = [applePayTool getAuthorzationViewController];


        self.viewController = viewController;


        if (!viewController)







            viewController.delegate = self;


            [self presentViewController:viewController animated:YES completion:nil];





About Apple Pay


This documentation contains preliminary information about an API or technology in development. This information is subject to change, and software implemented according to this documentation should be tested with final operating system software.


Apple Pay is a mobile payment technology that lets users give you their payment information for real-world goods and services in a way that is both convenient and secure.


For digital goods and services delivered within the app, see In-App Purchase Programming Guide.


image: ../Art/payment_intro_2x.png

Working with Apple Pay

Apps that use Apple Pay need to enable the Apple Pay capabilities in Xcode. You also register a merchant identifier and set up cryptographic keys, which are used to securely send payment data to your server.

***使用Apple Pay 的app需要去在Xcode中打开Apple Pay的能力***。你也注册一个***

商人ID和设置密码 钥匙,密码钥匙被用来安全的发送支付数据到你的服务器***,

To initiate a payment, your app creates a payment request. This request includes the subtotal for the services and goods purchased, as well as any additional charges for tax, shipping, or discounts. Pass this request to a payment authorization view controller, which displays the request to the user and prompts for any needed information, such as a shipping or billing address. Your delegate is called to update the request as the user interacts with the view controller.

去初始化一个支付,你的app创建一个支付请求。这个请求包含服务和购买的商品的小计,以及安和额外的税务,运费,或打折等。传送这个请求到一个支付授权view 控制器,控制器展示请求给用户提示任何需要的信息,比如航运或计费地址。****你的代理被调用去更新请求随着用户和这个View控制器交互****。

As soon as the user authorizes the payment, Apple Pay encrypts payment information to prevent an unauthorized third party from accessing it. On the device, Apple Pay sends the payment request to the Secure Element, which is a dedicated chip on the user’s device. The Secure Element adds the payment data for the specified card and merchant, creating an encrypted payment token. It then passes this token to Apple’s servers, where it is reencrypted using your Merchant Identifier certificate. Finally, the servers pass the token back to your app for processing.

一旦用户授权付款Apple Pay 加密支付信息去防止未授权的第三方信息去访问它。在设备上。Apple Pay 发送这个支付请求到安全元素,就是一个在用户设备上的专用芯片。这个安全元素添加支付数据到明确的卡片和商户,创建一个加密支付tocken.它然后发送这个tocken 到苹果的服务器,这里token 被使用你的商户ID 证书再次加密。最后最后这个服务器传送这个tocken 到你的app去处理。

The payment token is never accessed or stored on Apple’s servers. The servers simply reencrypt the token using your certificate. This process lets your app securely encrypt the payment information without it having to distribute your Merchant Identifier certificate as part of the app.

这个支付tocken 在苹果的服务器永远不被访问或存储。这个服务器简单的使用你的证书再次加密这个tocken。这个过程让你的app安全加密支付信息而不用去分布你的商户ID证书作为你的app的一部分。

For more information about Apple Pay’s security, see iOS Security Guide.

更多关于Apple Pay的安全信息,参见iOS Security Guide.

In most cases, your app passes the encrypted payment token to a third-party payment solution provider to decrypt and process the payment. However, if your team has an existing payment infrastructure, you can decrypt and process the payment on your own server.


For information about payment solution providers that support Apple Pay, see

更多支持Apple Pay 关于支付解决提供者信息,参见

Testing Apple Pay Transactions

测试Apple Pay 交易

Use the Apple Pay Sandbox environment to test your transactions with test payment cards.

使用Apple Pay Sandbox 环境去使用你的支付卡去测试你的交易。

In iTunes Connect, create a test account. This account works for both App Store and Apple Pay testing.

在 iTunes Connect,创建一个测试账号。这个测试账号在App Store 和Apple Pay  测试 都有用。

On a valid test device, log into iCloud using the test account.


In the Wallet app, add a new card using manual entry.

在Wallet app,使用手工输入添加一个新卡。

Logging in and out of your iCloud account removes your cards. Test cards can only be used in the Sandbox environment. Additionally, the Sandbox environment tests only the connection between your app and the test card network. It does not test the connection between your app and your payment solution provider.

登录和退出你的iCloud账号移除你的卡。测试卡只能被用来Sandbox 环境。这个Sandbox环境测试仅仅在你的app和测试卡网络之间连接。它不测试在你的app和你支付解决提供者之间的连接。

Configuring Your Environment


A merchant ID identifies you to Apple Pay as being able to accept payments. The public key and certificate associated with your merchant ID is used as part of the payment process to encrypt payment information. Before your app can use Apple Pay, you need to register a merchant ID and configure its certificate.

一个商户ID 标记你对Apple Pay 作为能去接受支付。这个公用key和与 你的商户ID 相关的证书 被用来作为支付处理的一部分去加密支付信息。在你的app能使用Apple Pay之前,你需要去注册一个商务ID和配置她的证书。

To register a merchant ID



In Member Center, select Certificates, Identifiers & Profiles.

Under Identifiers, select Merchant IDs.

在 会员中心选择  Certificates,Identifiers & Profiles.

在 Identifiers 下面,选择Merchant IDs.

Click the Add button (+) in the upper-right corner.


Enter a description and identifier, and click Continue.


Review the settings, and click Register.


Click Done.



To configure a certificate for your merchant ID


In Member Center, select Certificates, Identifiers & Profiles.

在会员中心,选择Certificates,Identifiers & Profiles.

Under Identifiers, select Merchant IDs.

在Identifiers下面,选择Merchant IDs.

Select the merchant ID from the list, and click Edit.

从列表中选择 商户ID,点击编辑。

Click Create Certificate, follow the instructions to obtain or generate your certificate signing request (CSR), and click Continue.


Click Choose File, select your CSR, and click Generate.

Download the certificate by clicking Download, and click Done.

点击 Choose File,选择 你的CSR,点击 Generate.


If you see a warning in Keychain Access that the certificate was signed by an unknown authority or that it has an invalid issuer, make sure you have the WWDR intermediate certificate - G2 and the Apple Root CA - G2 installed in your keychain. You can download them from

如果你看到一个警告证书被一个未知机构或它有一个不可用的发行者,确保你有WWDR中级证书-G2和苹果根CA-G2 安装在你的钥匙串。你下载他们从

To enable Apple Pay for your app in Xcode, open the Capabilities pane. Select the switch in the Apple Pay row, and then select the merchant IDs you want the app to use.

去可用Apple Pay 为你的app 在Xcode,打开 Capabilities 窗口。选择Apple Pay 行的开关,然后选择你想让App 去使用的商户ID。

image: ../Art/enable_apple_pay.png


When troubleshooting, it is sometimes helpful to enable Apple Pay manually. Follow these steps to manually enable Apple Pay:

遵守如下步骤去手工可用Apple Pay:

In Member Center, select Certificates, Identifiers & Profiles.

会员中心,选Certificates,Identifiers &Profiles.

Under Identifiers, select App IDs.

在Identifiers,选择 App IDs.

Select the app ID from the list, and click Edit.

 从列表中选择app ID,点击编辑。

Select Apple Pay, then click Edit.

选择Apple Pay,然后点击编辑。

Select the merchant IDs you want to use, and click Continue.


Review the settings, and click Assign.


Click Done.


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.

在创建一个支付请求之前,使用你支持的网络调用PKPaymentAuthorizationViewController 类的方法 canMakePayments UsingNetworks 方法决定是否用户将能够去产生支付。去检查是否Apple Pay 被这个设备的硬件支持和家长控制,使用canMakePayments 方法。


The PKPaymentAuthorizationController class performs the same role as the PKPaymentAuthorizationViewController class, but it does not depend on the UIKit framework. This means that the authorization controller can be used in places where a view controller cannot (for example, in watchOS apps or in Intents extensions).

这个PKPaymentAuthorizationController 类执行相同的角色和PKPaymentAuthorizationViewController类,但是它不依赖UIKit框架。这意外着授权控制器能被使用在view 控制器不能用的地方(比如在 watchOS app或内容的扩展上)

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

如果canMakePayments 返回NO,这个设备不支持Apple Pay,不要展示Apple Pay 按钮,使用支付的其他方法。

If canMakePayments returns YES but canMakePaymentsUsingNetworks: returns NO, 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).

如果 canMakePayments 返回YES 但是 canMakePaymentsUsingNetworks:返回NO,这个设备支持Apple Pay,但是用户还没有添加一个卡为任何的请求网络。你能选择性的,展示一个支付设置按钮,催促用户去设置他或她的卡。初始化设置新卡的进程(比如通过调用openPaymentSetup 方法)。

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.

否则,随着用户点击了Apple Pay 按钮,你必须开始支付授权进程。不要让用户去执行其他任务在展示支付请求之前。比如,如果用户需要去输入一个折扣代码,你必须去调用这个代码在她点击Apple Pay 按钮之前。



To create an Apple Pay–branded button for initiating payment request on iOS 8.3 or later, use the PKPaymentButton class. For iOS 8.2 or earlier, use the resources described in the Apple Pay Identity Guidelines.

去创建一个Apple Pay-品牌 按钮为初始化支付请求在iOS8.3或以后,使用PKPaymentButton 类。对iOS8.2或之前,使用在Apple Pay Identity Guidelines 中的资源描述。

For additional guidelines on using Apple Pay buttons and payment marks, see Apple Pay in iOS Human Interface Guidelines.

在使用Apple Pay 按钮和支付标记的附件指导,参见Apple Pay 在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.

如果你的app 使用一个网页-基础 接口为购买商品和服务,在处理一个Apple Pay 交易之前你必须移动这个请求从网页接口到原生iOS代码。表3-1展示了需要去处理一个web view的请求的步骤。

Listing 3-1Buying items from a web view

// Called when the web view tries to load “myShoppingApp:buyItem"

调用这个方法当web view尝试去加载“”

-(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.




    // Otherwise the web view loads the link.



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 = @“";

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.

***支付总结项目,通过PKPaymentSummaryItem Class呈现,描述支付请求的不同部分给用户。使用一个小数量的总结项目-特别是小计,任何折扣,航运,税务,总和。如果你没有任何附加费(比如,运费或税务),只要使用购买的总和。 提供项目花费的具体细节在你的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.


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. The system then marks the cost as pending.

如果你不知道真实的花费当支付被授权的时候(比如,出租车费用),使用PKPaymentSummaryItemTypePending 类型和0.0钱数做一个小计总结。这个系统然后标记花费作为未决定的。

Listing 3-2Creating a payment summary item


// 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]; = [PKPaymentSummaryItem summaryItemWithLabel:@"Discount" amount:discountAmount];


Payment summary items use the NSDecimalNumber class to store the amount as a base-10 quantity. Instances of this class can be created by explicitly specifying the mantissa and exponent (as shown in the code listings) or by providing the quantity as string and specifying a locale. Always use base-10 numbers for financial calculations—for example, to determine the amount of a 5% discount.


Although they may appear to be more convenient, IEEE floating point data types such as float and Double are not suitable for financial calculations. These data types use a base-2 representation of numbers, which means that some decimal numbers can’t be represented exactly—for example, 0.42 must be approximated as 0.41999 repeating. Such approximations can cause financial calculations to return incorrect results.

经管他们可能表现更加便利,IEEE浮点数据类型比如作为float 和 Double不适合财金计算。哪些数据类型使用2基数数字的展示,这就意外着一些十进制数字不能被准确的展示-比如,0.42一定是约等于0.41999后重复。这样的约等能造成财金计算返回错误结果。

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.

在列表中的最后支付总结是全部的。通过加和其它总结项目的钱数计算总金额。这个总金额被展示不同于其它总结项目:使用你的公司的名字作为它的label,和使用所有其它总结项目的钱数和作为它的钱数。使用 paymentSummaryItems 属性 添加 支付总结项目到支付请求。

// 10.75 grand total

NSDecimalNumber *totalAmount = [NSDecimalNumber zero];

totalAmount = [totalAmount decimalNumberByAdding:subtotalAmount];

totalAmount = [totalAmount decimalNumberByAdding:discountAmount]; = [PKPaymentSummaryItem summaryItemWithLabel:@"My Company Name" amount:totalAmount];


self.summaryItems = @[self.subtotal,,];

request.paymentSummaryItems = self.summaryItems;

A Shipping Method Is a Special Payment Summary Item

一个运输方法是一个 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.

创建一个PKShippingMethod的实例为每个可用的运输方法。就像其它支付总结项目,运输方法有一个 用户-可读标签比如 Standard Shipping 或Next Day Shipping, 和一个运输花费。不想其它总结项目,运输方法也有一个 详细属性-比如“Arrives by July 29”或“Ships in 24 hours”-解释运输方法之间的不同。

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.”

去在你的代理方法中区分运输方法,使用identifier 属性,这个属性只被你的app使用-这个框架对待它作为一个不透明的值和不展示它在UI。赋值一个非透明identifier为没一个运输方法当你创建它。对于调试场景,使用一个简单或字符串缩写,比如“打折”,“标准”,或“下一天”。

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.

一些运输方法不是可用的在所有的区域或有不同的花费为不同的地址。你能更新这个信息当用户选择一个运输地址和方法,就像描述在Your Delegate Updates Shipping Methods 和花费。

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; support of EMV is optional.

通过使用一个字符串常量数组填充supportedNetworks属性标示那个支付网络你支持。通过设置一个值为merchantCapabilities 属性标示那个支付处理协议你支持。你必须支持3DS;支持EMV 是可选的。 

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

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:

填充 支付授权 view controller 的 requiredBillingAddressFields 和 requiredShippingAddressFields 属性去标示什么账单和运输信息是需要的。当你展示这个view controller, 它促进用户去支持被请求的账单和运输信息。这个区域场景被如下组合去设置值为哪些属性。

request.requiredBillingAddressFields = PKAddressFieldEmail;

request.requiredBillingAddressFields = PKAddressFieldEmail | PKAddressFieldPostalAddress;


Request only the billing and shipping information needed to process your payment and deliver your products or services. Requesting unnecessary information adds unneeded complexity to the transaction. Each additional step increases the chance that the user will simply cancel the payment.


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.

如果你有更新到日期 账单 和 运输 联系信息,你能在支付请求设置哪些。Apple Pay通过 默认使用这个信息;然而,用户已经能选择其它联系信息作为支付授权进程的一部分。

PKContact *contact = [[PKContact alloc] init];


NSPersonNameComponents *name = [[NSPersonNameComponents alloc] init];

name.givenName = @"John";

name.familyName = @"Appleseed"; = name;


CNMutablePostalAddress *address = [[CNMutablePostalAddress alloc] init];

address.street = @"1234 Laurel Street"; = @"Atlanta";

address.state = @"GA";

address.postalCode = @"30303";


contact.postalAddress = address;


request.shippingContact = contact;



Address information can come from a wide range of sources in iOS. Always validate the information before you use it.


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.

去存储名确到你app的关于支付请求的信息,比如在一个运输卡identifier,使用applicationData 属性。这个属性被系统作为一个不透明值。一个应用数据的哈西值出现在支付tocken在用户授权了支付请求以后。

Authorizing Payments


The payment authorization process is a cooperative effort between the payment authorization view controller and its delegate. A payment authorization view controller does two things: It lets the user select the billing and shipping information that is needed by a payment request, and it lets the user authorize the payment to be made. The delegate methods are called when the user interacts with the view controller so that your app can update the information shown—for example, to update the shipping price when a shipping address is selected. The delegate is also called after the user authorizes the payment request.

支付授权进程是支付授权view controller 和它的代理的 一个合作结果。一个支付授权view controller做两件事:它让用户选择一个支付请求需要的账单和运输信息,和它让用户授权支付被创建。这个代理方法被调用当用户和view  controller交换的时候以至于你的app能更新信息展示-比如,去更新运输价格当一个运输地址被选择。这个代理也被调用在用户授权了支付请求以后。



As you implement the delegate methods, remember that they can be called multiple times and that the order in which they are called depends on the order of the user’s actions.


All of the delegate methods called during the authorization process are passed a completion block as one of their arguments. The payment authorization view controller waits for its delegate to finish responding to one method (by calling the completion block) before it calls any other delegate methods. The paymentAuthorizationViewControllerDidFinish: method is the only exception: It doesn’t take a completion block, and it can be called at any time.

所有在授权处理中被调用的代理方法 被传送一个完成闭包作为一个他们的参数。这个支付授权view controller 等待它的代理去完成响应的方法(通过调用这个完成闭包)在它调用其它代理方法之前。 这个 paymentAuthorizationViewControllerDidFinish: 方法是一个仅有的特例:它不采取一个完成闭包,它可能在任何时候被调用。

The completion blocks take an argument that lets you specify the current status of the transaction based on the information that’s available. If there are no problems with the transaction, you pass the value PKPaymentAuthorizationStatusSuccess; otherwise, you pass a value that identifies the problem.


To create an instance of the PKPaymentAuthorizationViewController class, pass the payment request to the view controller’s initializer. Set a delegate for the view controller, and then present it.

去创建一个PKPaymentAuthorizationViewController类的实例,传送支付请求到view controller的实例。设置一个代理为这个view controller,然后展示它。



The PKPaymentAuthorizationController class performs the same role as the PKPaymentAuthorizationViewController class, but it does not depend on the UIKit framework. This means that the authorization controller can be used in places where a view controller cannot (for example, in watchOS apps or in Intents extensions).

这个 PKPaymentAuthorizationController 类和PKPaymentAuthorizationViewController类执行相同角色,但是它不依赖UIKit 框架。这就意味这这个授权控制器能被用在view controller不能用的地方(比如,在watchOS中)。

To use the PKPaymentAuthorizationController class, assign an object that adopts the PKPaymentAuthorizationControllerDelegate protocol as a delegate, and call the presentWithCompletion: method to present a payment sheet. When you are done, call thedismissWithCompletion: method to dismiss the payment sheet. Otherwise, the APIs are identical.

去使用这个PKPaymentAuthorizationController 类,赋值一个遵守了PKPaymentAuthorizationControllerDelegate协议的对象作为代理,和调用这个presentWithCompletion:方法去展示一个支付表单。当你完成,调用thedismissWithCompletion:方法去消失这个支付表单。否则接口是相同的。

PKPaymentAuthorizationViewController *viewController = [[PKPaymentAuthorizationViewController alloc] initWithPaymentRequest:request];

if (!viewController) { /* ... Handle error ... */ }

viewController.delegate = self;

[self presentViewController:viewController animated:YES completion:nil];

As the user interacts with the view controller, the view controller calls its delegate methods.

随着用户和view controller 交互,这个view controller 调用它的代理方法。



******In Xcode 7.0 or later, you can test the payment authorization view controller in the simulator. It provides simulated cards for all the supported payment networks and returns dummy payment data in plain text. On a device, this data is encrypted with your merchant identifier and must be decrypted either on your server or by your payment processor.

******在Xcode 7.0或以后,你能测试支付授权view controller在模拟器中******。如果提供了模拟卡为所有支持支付网络和返回虚拟支付数据在文本中。在一个设备中,这个数据被使用你的商户ID加密和必须被你的服务器或你的支付处理者解密。

Use the Apple Pay Sandbox environment to test your app on a device with test cards.

使用Apple Pay Sandbox 环境用一个测试卡去测试你的app在一个设备上。

Although these techniques provide fast and convenient ways to test your code, you still need to thoroughly test Apple Pay on actual, physical devices with production cards.

经管哪些技术提供快速方便方法去测试你的代码,你依旧需要去彻底测试Apple Pay 在真实设备上使用产品卡。

Your Delegate Updates Shipping Methods and Costs


When the user provides shipping information, the authorization view controller calls your delegate’s paymentAuthorizationViewController:didSelectShippingContact:completion: and paymentAuthorizationViewController:didSelectShippingMethod:completion: methods. Use these methods to update the payment request based on the new information.

当用户提供运输信息,这个授权view controller 调用你的代理方法paymentAuthorizationViewController:didSelectShippingContact:completion:和paymentAuthorizationViewController:didSelectShippingMethod:completion:方法。使用哪些方法去更新支付请求基于新的信息。

- (void) paymentAuthorizationViewController:(PKPaymentAuthorizationViewController *)controller

                   didSelectShippingContact:(CNContact *)contact

                                 completion:(void (^)(PKPaymentAuthorizationStatus, NSArray *, NSArray *))completion


    self.selectedContact = contact;

    [self updateShippingCost];

    NSArray *shippingMethods = [self shippingMethodsForContact:contact];

    completion(PKPaymentAuthorizationStatusSuccess, shippingMethods, self.summaryItems);



- (void) paymentAuthorizationViewController:(PKPaymentAuthorizationViewController *)controller

                    didSelectShippingMethod:(PKShippingMethod *)shippingMethod

                                 completion:(void (^)(PKPaymentAuthorizationStatus, NSArray *))completion


    self.selectedShippingMethod = shippingMethod;

    [self updateShippingCost];

    completion(PKPaymentAuthorizationStatusSuccess, self.summaryItems);




To maintain privacy, the shipping information provided in paymentAuthorizationViewController:didSelectShippingContact:completion: is anonymized. The returned contact contains enough information to calculate shipping costs, without revealing sensitive information about the user. You do not get the user’s full shipping information until after the user approves the payment. Additionally, the data available in the contact changes from country to country, and can change from release to release. Be sure to test your app appropriately.


A Payment Token Is Created When a Payment Is Authorized

一个支付Token 被创建当一个支付被授权的时候

When the user authorizes a payment request, the framework creates a payment token by coordinating with Apple’s server and the Secure Element. You send this payment token to your server in the paymentAuthorizationViewController:didAuthorizePayment:completion: delegate method, along with any other information you need to process the purchase—for example, the shipping address and a shopping cart identifier. The process happens as follows:

***当用户授权一个支付请求,这个框架创建一个支付token通过协调 苹果的服务器 和 安全 元素***。你发送这个支付token 到你的服务器在paymentAuthorizationViewController:didAuthorizePayment:completion:代理方法,和其它你需要去处理购买的其它信息-比如,运输地址和一个运输卡ID ,这个过程发生如下:

The framework sends the payment request to the Secure Element. Only the Secure Element has access to the tokenized device-specific payment card numbers.

****这个框架发送支付请求到 安全元素。只有 安全元素能访问到标记化的 设备明确 支付卡号*****。

The Secure Element puts together payment data for the specified card and merchant, encrypts it so that only Apple can read it, and sends it to the framework. The framework then sends the payment data to Apple’s server.


Apple’s server reencrypts the payment data using your Merchant Identifier certificate. The token can only be read by you and the people with whom you have shared your Merchant Identifier certificate. The server then signs the payment token, and returns it to the device.


The framework passes the token to your delegate by calling its paymentAuthorizationViewController:didAuthorizePayment:completion: method. Your delegate sends the token to your server.

这个框架通过 调用paymentAuthorizationViewController:didAuthorizePayment:completion方法  传送token 到你的代理。你的代理发送这个token 到你的服务器。

The actions on your server vary depending on whether you process your own payments or work with a payment platform. In both cases, your server handles the order and sends a status back to the device, which your delegate passes to its completion handler, as described in Processing a Payment.

你的服务器的动作取决于是否你处理你的自己的支付或  工作使用一个支付平台。在两个情况下你的服务器处理顺序和发送 状态 到设备,你的代理传送状态到它的完成闭包,就像Processing a Payment  描述的。

- (void) paymentAuthorizationViewController:(PKPaymentAuthorizationViewController *)controller

                        didAuthorizePayment:(PKPayment *)payment

                                 completion:(void (^)(PKPaymentAuthorizationStatus))completion


    NSError *error;

    ABMultiValueRef addressMultiValue = ABRecordCopyValue(payment.billingAddress, kABPersonAddressProperty);

    NSDictionary *addressDictionary = (__bridge_transfer NSDictionary *) ABMultiValueCopyValueAtIndex(addressMultiValue, 0);

    NSData *json = [NSJSONSerialization dataWithJSONObject:addressDictionary options:NSJSONWritingPrettyPrinted error: &error];


    // ... Send payment token, shipping and billing address, and order information to your server ...


    PKPaymentAuthorizationStatus status;  // From your server



Your Delegate Dismisses the Payment Authorization View Controller

你的代理消失Payment Authorization View Controller

After the framework displays the transaction’s status, the authorization view controller calls your delegate’s paymentAuthorizationViewControllerDidFinish: method. In your implementation, dismiss the authorization view controller and then display your own app-specific order-confirmation page.

在框架展示交易的状态以后,这个授权view controller  调用你的代理的paymentAuthorizationViewControllerDidFinish: 方法。在你的实现中消失授权view controller和展示你自己的app-明确 顺序-配置页面。

- (void) paymentAuthorizationViewControllerDidFinish:(PKPaymentAuthorizationViewController *)controller


    [controller dismissViewControllerAnimated:YES completion:nil];


Processing Payments


Processing a payment involves several steps:


Sending the payment information to your server, along with other information needed to process the order


Verifying the hashes and signature of the payment data


Decrypting the encrypted payment data


Submitting payment data to the payment processing network


Submitting the order to your order-tracking system

提交订单到你的订单-追踪 系统

You have two options for processing the payment: You can take advantage of a payment platform to process the payment, or you can implement the payment processing yourself. A payment processing platform typically handles most of the steps listed above.


Reading, verifying, and processing payment information requires an understanding of several areas of cryptography such as calculating an SHA–1 hash, reading and validating a PKCS #7 signature, and performing elliptic curve Diffie-Hellman key exchange. If you don’t have a background in cryptography, consider using a payment platform that performs these operations for you. For information about payment platforms that support Apple Pay,

读取,验证和处理支付信息需要理解加密的几个区域比如计算SHA-1哈西,读取和可用一个PKCS #7签名,和执行椭圆曲线Diffe-Hellman 钥匙转化。如果你没有一个加密北京,考虑使用一个支付平台执行哪些操作为你。关于支持Apple Pay 的支付平台信息,参见

The information used to process a payment has a nested data structure, as shown in Figure 5-1. A payment token is an instance of the PKPaymentToken class. The value of its paymentData property is a JSON dictionary, which has a header with information used for validation, and encrypted payment data. The encrypted data includes information such as the amount and cardholder name and other information used for the specific payment processing protocol.

用来去处理一个支付的信息有一个巢数据结构,就像在表5-1中。一个支付token 是 一个PKPaymentToken 类的实例。它的paymentData属性值是一个JSON字典,它有一个有可用信息的头,和被加密的支付数据。这个加密数据保护信息比如钱数和持卡人的名字和其它用来明确支付处理协议的信息。

个人分类: API翻译
想对作者说点什么? 我来说一句