文章目录

  • 判断是否可以支付
  • 网页接口桥接
  • 支付请求包含的地区和货币信息
  • 支付请求包含的支付清单
  • Shipping Method
  • 支付处理机制的支持设置
  • 运输和计费信息设置
  • 付一段代码

支付请求是PKPaymentRequest类的实例。付款请求由摘要列表组成,这些摘要向用户描述支付的内容、可用的送货方法列表、用户需要提供的送货信息的描述以及有关商家和付款处理程序的信息。

判断是否可以支付

在创建支付请求之前,通过调用PKPaymentAuthorizationViewController类的canMakePaymentsUsingNetworks:方法,确定用户是否能够使用您支持的网络进行支付。要检查Apple Pay是否受到该设备硬件和家长控制的支持,可以使用canMakePayments方法。

注意:PKPaymentAuthorizationController类执行与PKPaymentAuthorizationViewController类相同的角色,但它不依赖于UIKit框架。这意味着授权控制器可以用于视图控制器不能使用的地方(例如,在watchOS应用程序或intent扩展中)。

如果canMakePayments返回NO,则该设备不支持Apple Pay。不要显示Apple Pay按钮。回到另一种支付方式。

如果canMakePayments返回YES,而canMakePaymentsUsingNetworks:返回NO,说明设备支持Apple Pay,但是用户没有为任何请求的网络添加卡。您可以选择显示一个支付设置按钮,提示用户设置他的卡。只要用户点击此按钮,就开始设置新卡的过程(例如,通过调用openPaymentSetup方法,会跳转到wallet)。

只要用户按下Apple Pay按钮,就必须开始支付授权过程。在提交付款请求之前,不能要求用户执行任何其他任务。例如,如果用户需要输入折扣代码,您必须在他按下Apple Pay按钮之前输入。(意思是只要按下Apple Pay按钮,就只能执行付款流程,其他需要用户操作的事情放在之前去做)

网页接口桥接

如果您的应用程序使用基于web的界面来购买商品和服务,那么在处理Apple Pay事务之前,您必须将请求从web界面移动到本机iOS代码。以下是处理web视图请求所需的步骤。

// 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);
}

支付请求包含的地区和货币信息

request.currencyCode = @"USD"; //人民币是CNY
request.countryCode = @"US"; //中国是CN
request.merchantIdentifier = @"merchant.com.example"; //这是之前你设置好的Merchant ID

支付请求包含的支付清单

由PKPaymentSummaryItem类表示的付款摘要项向用户描述付款请求的不同部分。使用少量的汇总项目——通常是小计、折扣、运费、税金和总金额。如果您没有任何额外的费用(例如,运费或税),只需使用购买的总额。在应用程序的其他地方提供逐项成本的详细信息。

每个摘要项都有一个标签和一个金额,如清单3-2所示。标签是用户可读的项目摘要描述。金额为相应的支付金额。付款请求中的所有金额都使用付款请求中指定的货币。对于折扣或优惠券,将金额设置为负数。

清单3-2:创建支付清单

// 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];

注意:付款汇总项使用NSDecimalNumber类将金额存储为基数为10的数量。这个类的实例可以通过显式地指定尾数和指数(如代码清单所示)来创建,也可以通过提供数量作为字符串并指定区域设置来创建。例如,在财务计算中一定要使用基数为10的数字,以确定5%的折扣金额。
虽然看起来更方便,但是IEEE浮点数据类型(float和Double)不适合进行财务计算。这些数据类型使用以2为基础的数字表示,这意味着一些十进制数字不能被精确地表示—例如,0.42必须近似为0.41999循环。这种近似可能导致财务计算返回不正确的结果。

(NSDecimalNumber一般用于和钱打交道的数据存储,因为普通的浮点是有误差的,NSDecimalNumber弥补了这个问题)

列表中的最后一个付款汇总项是总金额。通过添加所有其他汇总项的金额来计算总金额。总计与其他汇总项的显示方式不同:使用您的公司名称作为其标签,并使用所有其他汇总项的总额作为其金额。使用paymentSummaryItems属性将付款摘要项添加到付款请求中。

如果您不知道授权支付时的实际成本(例如出租车费用),则使用PKPaymentSummaryItemTypePending类型和0.0金额创建一个小计汇总项目。对于总金额,使用正的非零金额和PKPaymentSummaryItemTypePending类型。然后,系统将成本显示为pending,没有数字数量。

注意:总金额不能是0或者负数。

// 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;

Shipping Method

为每个可用的传送方法创建PKShippingMethod的实例。与其他付款汇总项一样,shipping方法具有用户可读的标签,比如Standard shipping或Next Day shipping,以及表示运费的金额。与其他摘要项不同的是,运输方法还有一个详细的属性,比如“7月29日前到达”或“24小时内到达”,这就解释了运输方法之间的区别。

要区分委托方法中的传递方法,请使用标识符属性。此属性仅供您的应用程序使用—框架将其视为不透明值,并且它不会出现在UI中。在创建每个传送方法时,为其分配唯一标识符。为了便于调试,可以使用简短或缩写的字符串,如“discount”、“standard”或“next-day”。

有些运输方法不是在所有地区都可用,或者对于不同的地址有不同的成本。当用户选择送货地址或方法时,可以更新此信息,如委托更新送货方法和费用中所述。

支付处理机制的支持设置

通过使用字符串常量数组填充supportedNetworks属性来指示您支持哪些支付网络。通过为merchantCapabilities性属性设置一个值来指示您支持哪些支付处理协议。你必须支持3DS;只有在支持Apple Pay的情况下才能指定EMV。

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;

运输和计费信息设置

填充付款授权视图控制器的requiredBillingAddressFields和requiredShippingAddressFields属性,以指示需要哪些账单和发货信息。当您呈现这个视图控制器时,它会提示用户提供所请求的帐单和发货信息。

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

注意:只要求填写所需要的信息。请求不必要的信息会给事务增加不必要的复杂性。每一个额外的步骤都增加了用户取消支付的可能性。

如果您有最新的账单和发货联系方式,您可以在付款请求中设置这些信息。Apple Pay默认使用这些信息;但是,用户仍然可以选择其他联系方式作为支付授权过程的一部分。

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;

注意:地址信息可以来自iOS中的各种来源。在使用信息之前一定要验证它。

付一段代码

- (void)configPaymentInformation {
    //开始配置支付信息
    self.payRequest = [[PKPaymentRequest alloc] init];
    self.payRequest.countryCode = @"US";             //国家代码
    self.payRequest.currencyCode = @"USD";           //RMB的币种代码
    self.payRequest.merchantIdentifier = @"merchant.com.aspiraconnect.demo";//申请的merchantID
    
    self.payRequest.supportedNetworks = self.supportedNetworkCards; //用户可以进行支付的银行卡
    
    self.payRequest.merchantCapabilities = PKMerchantCapability3DS | PKMerchantCapabilityEMV;
    //设置支持的交易处理协议, 3DS必须支持, EMV为可选
    
    //payRequest.requiredShippingAddressFields = \
    PKAddressFieldPostalAddress | PKAddressFieldPhone | PKAddressFieldName;
    //设置发货地址
    self.payRequest.requiredShippingAddressFields = PKAddressFieldNone;
    //空发货地址
    self.payRequest.shippingMethods = @[];
    NSDecimalNumber *totalAmount = \
    [NSDecimalNumber decimalNumberWithString:@"0.01"];//创建金额
    
    PKPaymentSummaryItem *total = \
    [PKPaymentSummaryItem summaryItemWithLabel:@"My Company Name" amount:totalAmount];
    self.summaryItems = [NSMutableArray arrayWithArray:@[total]];
    self.payRequest.paymentSummaryItems = self.summaryItems;
}

示例:
LGApplePayDemo