Apple Pay 接入工程

接入工程

創(chuàng)建一個工程設(shè)置其 Bundle ID 必須和描述文件中的 Bundle ID 一致。

image.png

Capability 標(biāo)簽中把 ApplePay 選項打開,并且將 Merchant ID 選中。

image.png

項目會多了一個 ApplePay 的配置文件 ApplePayDemo.entitlements。

image.png

在工程中導(dǎo)入對應(yīng)的頭文件 PassKit/PassKit.hAddressBook/AddressBook.h,并且遵循 PKPaymentAuthorizationViewControllerDelegate 協(xié)議。

#import <PassKit/PassKit.h>                                 // 用戶綁定的銀行卡信息
#import <PassKit/PKPaymentAuthorizationViewController.h>    // Apple pay的展示控件
#import <AddressBook/AddressBook.h>                         // 用戶聯(lián)系信息相關(guān)

創(chuàng)建支付請求

支付請求是 PKPayementRequest 類的一個實列。一個支持請求包含用戶支付的物品概要清單、可選配送方式列表、用戶需提供的配送信息、商家的信息以及支付處理機(jī)構(gòu)。

判斷用戶是否能夠支付

創(chuàng)建支付請求前,可以先通過調(diào)用 PKPaymentAuthorizationViewController 類的方法 canMakePaymentsUsingNetworks 判斷用戶是否能使用你支持的支付網(wǎng)絡(luò)完成付款。canMakePayments 方法可以判斷當(dāng)前設(shè)備的硬件是否支持 Apple Pay 以及家長控制是否允許使用 Apple Pay

如果 canMakePayments 返回 NO,則設(shè)備不支持 Apple Pay。不要顯示 Apple Pay 按扭,你可以選擇使用其它的支付方式。

如果 canMakePayments 返回 YES,但 canMakePayementsUsingNetworks: 返回 NO,則表示設(shè)備支持 Apple Pay,但是用戶并沒有為任何請求的支付網(wǎng)絡(luò)添加銀行卡。你可以選擇顯示一個支付設(shè)置按扭,引導(dǎo)用戶添加銀行卡。如果用戶點擊該按扭,則開始設(shè)置新的銀行卡流程 (例如,通過調(diào)用 openPaymentSetup 方法)。

在 iOS 8.3 以及以后的系統(tǒng)中,你可以選擇使用 PKPayementButton 方法在初始化支付請求時創(chuàng)建帶商標(biāo)的 Apple Pay 按扭。對于 iOS 8.2 以及更早的系統(tǒng),你可以使用《Apple Pay 標(biāo)志指南》 中提示的方法。 其它關(guān)于使用 Apple Pay 按扭以及支付標(biāo)志的指南請參考《iOS 人機(jī)界面準(zhǔn)則》 中的 Apple Pay 相關(guān)部分。

包含貨幣以及地區(qū)信息的支付請求

// 設(shè)置幣種、國家碼及merchant標(biāo)識符等基本信息
PKPaymentRequest *payRequest = [[PKPaymentRequest alloc]init];
payRequest.countryCode = @"CN";     //國家代碼
payRequest.currencyCode = @"CNY";       //RMB的幣種代碼
payRequest.merchantIdentifier = @"merchant.ApplePayDemoYasin";  //申請的merchantID
payRequest.supportedNetworks = supportedNetworks;   //用戶可進(jìn)行支付的銀行卡
payRequest.merchantCapabilities = PKMerchantCapability3DS|PKMerchantCapabilityEMV;      //設(shè)置支持的交易處理協(xié)議,3DS必須支持,EMV為可選,目前國內(nèi)的話還是使用兩者吧

在同一個支付請求中的所有匯總金額使用相同的貨幣。所使用的幣種可以通過 PKPaymentRequestcurrencyCode屬性指定。幣種由三個字符的 ISO 貨幣代碼指定,例如 USD 表示美元。

支付請求中的國家代碼表明支付發(fā)生的國家或者支付將在哪個國家處理。由三個字符的 ISO 國家代碼指定該屬性,例如 US

在請求中指定的商戶 ID 必須是應(yīng)用程序有授權(quán)的商戶 ID 中的某一個。

支付請求包括一系列的支付匯總項

PKPaymentSummaryItem 類表示支付請求中的不同部分。一個支付請求包括多個支付匯總項,一般包括:小計、折扣、配送費(fèi)用、稅以及總計。如果你沒有其它任何額外的費(fèi)用 (例如,配送或稅),那么支付的總額直接是所有購買商品費(fèi)用 的總和。關(guān)于每一項商品的費(fèi)用的詳細(xì)信息你需要在應(yīng)用程序的其它合適位置顯示。

每一個匯總項都有標(biāo)簽和金額兩個部分。標(biāo)簽是對該項的可讀描述。金額對應(yīng)于所需支付的金額。一個支付請求中的所有金額都使用該請求中指定的支付貨幣類型。對于折扣和優(yōu)惠券,其金額被設(shè)置為負(fù)值。

某些場景下,如果在支付授權(quán)的時候還不能獲取應(yīng)當(dāng)支付的費(fèi)用(例如,出租車收費(fèi)),則使用 PKPaymentSummaryItemTypePending 類型做小計項,并將其金額值設(shè)置為 0.0。系統(tǒng)隨后會設(shè)置該項的金額值。

// 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 進(jìn)制數(shù)表示。如示例代碼演示的一樣,可以通過顯示地指定小數(shù)部分與指數(shù)部分創(chuàng)建該類的實例,也可以直接使用字符串的方式指定金額。在財務(wù)計算中絕大部分情況下都是使用的 10 進(jìn)制數(shù)進(jìn)行計算的,例如,計算 5% 的折扣。
盡管 IEEE 浮點數(shù) float 或 double 計算更加方便一些,但是它們并不適用于財務(wù)計算中,因為這些數(shù)字使用 2 進(jìn)制表示。這意味著有些符點數(shù)不能被準(zhǔn)確的表示,例如 0.42 只能被近似的表示為 0.41999...。這樣的近似可能導(dǎo)致財務(wù)計算返回錯誤的結(jié)果。

匯總項列表中最后一項是總計項。總計項的金額是其它所有匯總項的金額的和??傆嬳椀娘@示不同用于其它項。在該項中,你應(yīng)該使用你的公司名稱作為其標(biāo)簽,使用所有其它項的金額之和作為其金額值。最后,使用 paymentSummaryItems 屬性將所有匯總項都添加到支付請求中。

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

配送方式是一個特殊的支付匯總項

// 設(shè)置兩種配送方式
PKShippingMethod *freeShipping = [PKShippingMethod summaryItemWithLabel:@"包郵" amount:[NSDecimalNumber zero]];
freeShipping.identifier = @"freeshipping";
freeShipping.detail = @"6-8 天 送達(dá)";
    
PKShippingMethod *expressShipping = [PKShippingMethod summaryItemWithLabel:@"極速送達(dá)" amount:[NSDecimalNumber decimalNumberWithString:@"10.00"]];
expressShipping.identifier = @"expressshipping";
expressShipping.detail = @"2-3 小時 送達(dá)";
    
payRequest.shippingMethods = @[freeShipping, expressShipping];

為每一個可選的配送方式創(chuàng)建一個 PKShippingMethod 實例。與其它支付匯總項一些,配送方式也有一個用戶可讀的標(biāo)簽,例如標(biāo)準(zhǔn)配送或者可隔天配送,和一個配送金額值。與其它匯總項不同的時,配送方法有一個 detail 屬性值,例如,7 月 29 日送達(dá)或者 24 小時之內(nèi)送達(dá)等等。該屬性值說明不同配送方式之間的區(qū)別。

為了在委托方法中區(qū)分不同的配送方式,你可以使用 identifier 屬性。這個屬性只被該應(yīng)用使用,它對于支付框架是不可見。同樣,它也不會出現(xiàn)在 UI 中。在創(chuàng)建每個配送方式的時候為其分配一個唯一的標(biāo)識符。為了便于調(diào)試,推薦使用簡短字符串或者字符串縮寫,例如 “discount”、“standard”、“next-day” 等等。

有些配送方式并不是在所有地區(qū)都是可以使用的,或者它們費(fèi)用會根據(jù)配送地址的不同而發(fā)生變化。你需要在用戶選擇配送地址或方法時更新其信息,詳情請見 委托方法更新配送方法與費(fèi)用

指定應(yīng)用程序支持的支付處理機(jī)制

supportedNetworks 屬性是一個字符串常量,通過設(shè)置該值可以指定應(yīng)用所支持的支付網(wǎng)絡(luò)。 merchantCapabilities屬性值說明應(yīng)用程序支持的支付處理協(xié)議。3DS 協(xié)議是須支持的支付處理協(xié)議, EMV 是可選的支付處理協(xié)議。

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

// Supports 3DS only
request.merchantCapabilities = PKMerchantCapability3DS;

// Supports both 3DS and EMV
request.merchantCapabilities = PKMerchantCapability3DS | PKMerchantCapabilityEMV;

說明所需的配送信息和賬單信息

修改支付授權(quán)視圖控制器的 requiredBillingAddressFields 屬性和 requiredShippingAddressFields 屬性可以設(shè)置所需的賬單信息和配送信息。當(dāng)你顯示視圖控制器時,它會提示用戶輸入必需的賬單信息和配送信息。這個域的值是通過這些屬性組合而成的,如下所示:

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

請求只包括處理支付和配送商品或服務(wù)的必需的賬單信息和配送信息。額外的非必需信息都會增加處理事務(wù)的復(fù)雜度。每個多余的步驟都可能會增加用戶取消支付的風(fēng)險。

如果已有最新賬單信息以及配送聯(lián)系信息,你可以直接為支付請求設(shè)置這些值。Apple Pay 會默認(rèn)使用這些信息。但是,用戶仍然可以選擇在本次支付中使用其它聯(lián)系信息。

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 中很多地方獲取到,請在使用它之前確保該信息是有效的。

保存其它信息

保存支付中其它與應(yīng)用相關(guān)的信息,例如購物車標(biāo)識,你可以使用 applicationData 屬性。這個屬性對于系統(tǒng)來說是不可見的。用戶授權(quán)支付后,應(yīng)用數(shù)據(jù)的哈希值也會成為支付令牌的一部分。

授權(quán)支付

支付授權(quán)過程是由支付授權(quán)視圖控制器與其委托合作完成的。支付授權(quán)視圖控制器做了兩件事:

  • 讓用戶選擇支付請求所需的賬單信息與配送信息。
  • 讓用戶授權(quán)支付操作。

用戶與視圖控制器交互時,委托方法會被系統(tǒng)調(diào)用,所以在這些方法中你的應(yīng)用可以更新所要顯示的信息。例如在配送地址修改后更新配送價格。在用戶授權(quán)支付請求后此方法還會被調(diào)用一次。

在實現(xiàn)這些委托方法時,你應(yīng)該謹(jǐn)記它們會被多次調(diào)用并且這些方法調(diào)用的順序是取決與用戶的操作順序的。

所有的這些委托方法在授權(quán)過程中都會被調(diào)用,傳入該方法的其中一個參數(shù)是一個完成塊 completion block。支付授權(quán)視圖控制器等待一個委托完成相應(yīng)的方法后 (通過調(diào)用完成塊) 再依次調(diào)用其它的委托方法。paymentAuthorizationViewControllerDidFinish: 方法是唯一例外:它并不需要一個完成塊作為參數(shù),它可以在任何時候被調(diào)用。

完成塊接受一個輸入?yún)?shù),該參數(shù)為應(yīng)用程序根據(jù)信息判斷得到的支付事務(wù)的當(dāng)前狀態(tài)。如果支付事務(wù)一切正常,則應(yīng)傳入值 PKPaymentAuthorizationStatusSuccess。否則,可以傳入能識別出錯誤的值。

創(chuàng)建 PKPaymentAuthorizationViewController 類的實例時,你需要將已初始化后的支付請求傳遞給視圖控制器初始化函數(shù)。接著,設(shè)置視圖控制器的委托;然后再顯示它:

PKPaymentAuthorizationViewController *viewController = [[PKPaymentAuthorizationViewController alloc] initWithPaymentRequest:request];
if (!viewController) { /* ... Handle error ... */ }
viewController.delegate = self;
[self presentViewController:viewController animated:YES completion:nil];

當(dāng)用戶與視圖控制器交互時,視圖控制器就會調(diào)用其委托方法:

在 Xcode 7.0 及其后的版本中,你可以在模擬器中測試支付授權(quán)視圖控制器。這些版本的模擬器提供了支持所有支付網(wǎng)絡(luò)的虛擬卡,它會以純文本的方式返回虛擬支付數(shù)據(jù)。在設(shè)備上時,這些數(shù)據(jù)會使用商戶 ID 進(jìn)行加密。
雖然模擬器可以方便快捷地測試支付代碼,但是你仍然需要在物理設(shè)備上測試你的支付功能。
如果你使用的是較早版本的 Xcode,那么你就只能在物理設(shè)備上測試你的支付功能了。

使用委托方法更新配送方式與配送費(fèi)用

當(dāng)用戶輸入配送信息時,授權(quán)視圖控制器會調(diào)用委托的 paymentAuthorizationViewController:didSelectShippingContact:completion: 方法和 paymentAuthorizationViewController:didSelectShippingMethod:completion: 方法。你可以實現(xiàn)這兩個方法來更新你的支付請求。

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

為了保護(hù)用戶隱私,提供給方法 paymentAuthorizationViewController:didSelectShippingContact:completion: 的配送信息是經(jīng)過匿名化處理后的數(shù)據(jù)。返回的 contact 包含了計算配送費(fèi)用的所有信息同時隱藏了用戶的敏感信息。只有在用戶授權(quán)支付后,你才能得到用戶完整的配送信息。此外, contact 中的數(shù)據(jù)會隨著國家的不同而不同,同時還會隨著版本的更新而變化。請仔細(xì)測試你的應(yīng)用程序。

支付被授權(quán)時創(chuàng)建了一個支付令牌

當(dāng)用戶授權(quán)一個支付請求時,支付框架的 Apple 服務(wù)器與安全模塊會協(xié)作創(chuàng)建一個支付令牌。你可以在委托方法 paymentAuthorizationViewController:didAuthorizePayment:completion: 中將支付信息以及其它你需要處理的信息,例如配送地址和購物車標(biāo)識符,一起發(fā)送至你的服務(wù)器。這個過程如下所示:

  • 支付框架將支付請求發(fā)送至安全模塊。只有安全模塊會訪問令牌化后的設(shè)備相關(guān)的支付卡號。
  • 安全模塊將特定卡的支付數(shù)據(jù)和商家信息一起加密(加密后的數(shù)據(jù)只有 Apple 可以訪問),然后將加密后的數(shù)據(jù)發(fā)送至支付框架。支付框架再將這些數(shù)據(jù)發(fā)送至 Apple 的服務(wù)器。
  • Apple 服務(wù)器使用商家標(biāo)識證書將這些支付數(shù)據(jù)重新加密。這些令牌只能由你以及那些與你共享商戶標(biāo)識證書的人讀取。隨后服務(wù)器生成支付令牌再將其發(fā)送至設(shè)備。
  • 支付框架調(diào)用 paymentAuthorizationViewController:didAuthorizePayment:completion: 方法將令牌發(fā)送至你的委托。你在委托方法中再將其發(fā)送至你的服務(wù)器。

在服務(wù)器上的處理操作取決于你是自己處理支付還是使用其它支付平臺。不過,在兩種情況下服務(wù)器都得處理訂單再將處理結(jié)果返回給設(shè)備。在設(shè)備上,委托再將處理結(jié)果傳入完成處理方法中,詳細(xì)過程請參閱 處理支付

- (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
    completion(status);
}

委托方法中釋放支付授權(quán)視圖控制器

支付框架顯示完支付事務(wù)狀態(tài)后,授權(quán)視圖控制器會調(diào)用委托的 aymentAuthorizationViewControllerDidFinish: 方法。在此方法的實現(xiàn)中,你應(yīng)該釋放授權(quán)視圖控制器然后再顯示與應(yīng)用相關(guān)的支付信息界面。

- (void)paymentAuthorizationViewControllerDidFinish:(PKPaymentAuthorizationViewController *)controller
{
    [controller dismissViewControllerAnimated:YES completion:nil];
}

處理支付

處理一次付款事務(wù)一般包括以下幾個步驟:

  • 將付款信息與其它處理訂單的必需信息一起發(fā)送至你的服務(wù)器。
  • 驗證付款數(shù)據(jù)的散列值與簽名。
  • 解密出支付數(shù)據(jù)。
  • 將支付數(shù)據(jù)提交給付款處理網(wǎng)絡(luò)。
  • 將訂單信息提交至你的訂單跟蹤系統(tǒng)。

你有兩種可選的方式處理付款過程:

  1. 利用已有的支付平臺來處理付款。
  2. 自己實現(xiàn)付款過程。一次付款的處理過程通常情況下包括上述的大部分步驟。
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 轉(zhuǎn)載自:Apple Pay的使用 Apple Pay的使用 關(guān)于Apple Pay 具體繼承步驟也可參考: 網(wǎng)址配...
    John_LS閱讀 1,150評論 5 0
  • Swift1> Swift和OC的區(qū)別1.1> Swift沒有地址/指針的概念1.2> 泛型1.3> 類型嚴(yán)謹(jǐn) 對...
    cosWriter閱讀 11,681評論 1 32
  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫、插件、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 15,632評論 4 61
  • 1.About Apple Pay Apple Pay是一種移動支付技術(shù),讓使用者把它們對真實的物品和服務(wù)的支付信...
    NEWWORLD閱讀 5,317評論 14 51
  • 關(guān)于 Apple Pay apple pay 是一種移動支付技術(shù),它可以讓用戶將自己在現(xiàn)實生活中購物、享受服務(wù)的支...
    單純的敲代碼閱讀 1,274評論 0 1

友情鏈接更多精彩內(nèi)容