ApplePay 接入教程及開發(fā)過程需要注意的點(diǎn)

運(yùn)行環(huán)境##

iphone 6 以及以上,iOS 9.2 以上。目前不支持企業(yè)證書添加。
支持模擬器測試。

環(huán)境配置##

1、 Xcode 7.2.1 以及以上打開項(xiàng)目,在 Capabilities里將Apple Pay設(shè)置為on,如下圖,請忽略 Merchant IDmerchant.com.Carman.Paydemo這一項(xiàng),一會(huì)我會(huì)詳細(xì)介紹。

圖片-1

這時(shí)你會(huì)發(fā)現(xiàn) 項(xiàng)目 下 會(huì)自動(dòng) 生成一個(gè) 類似證書的東西

圖片-2

這一步做了什么?
1、自動(dòng)導(dǎo)入了需要的庫文件。
2、添加了一個(gè)權(quán)限文件(圖片-2).

2、 圖一我們看到了有個(gè) Merchant ID 選項(xiàng),而且新建時(shí)候是沒有配置的,那么需要到哪里去配置呢?
1、訪問蘋果開發(fā)賬號(hào),證書中心。
Identifiers -->Merchant IDs
輸入描述 和 ID,ID 必須以merchant. 開頭

圖-3

Continue 到下一步,前方高能警報(bào),嘀嘀嘀~~~~ 坑一出現(xiàn):報(bào)錯(cuò)?。。。。。。?br>

圖-4

說明蘋果對這個(gè)ID 格式是有要求的。多試幾次。其實(shí)仔細(xì)看 圖 -3 底下有一行小字,We recommend using a reverse-domain name style string (i.e.,merchant.com.example.merchantname). 最好按照官方要求 merchant.com.example.merchantname 這個(gè)格式來。

圖 -5

一步一步往下走。
這時(shí)候 會(huì)提示你 Identifier:merchant.com.Demo.applepaydemo已經(jīng)生成。

圖-6

點(diǎn)擊 Done
圖 -7

根據(jù)上面的提示,點(diǎn)擊Edit,接下去應(yīng)該是需要建證書了。
首次添加時(shí)候 會(huì)詢問你是否 在中國使用。選擇 YES(截圖是默認(rèn)狀態(tài)-NO),一直 continue 。
圖-8

3、新建證書
創(chuàng)建 ** Creating a Certificate Signing Request (CSR) CSR 證書,**
Keychain Access > Certificate Assistant > Request a Certificate from a Certificate Authority.
打開鑰匙串訪問 如下圖操作

圖-9

生成 CertificateSigningRequest.certSigningRequest(名稱可以自定義)
圖-10

上傳 生成證書


圖-11

滿懷信心,覺得即將成功是么?

圖-12

此證書是由未知頒發(fā)機(jī)構(gòu)簽名的?。?!什么鬼呀,老子的賬號(hào)明明是正規(guī)渠道申請的!
還好有解決方案---點(diǎn)我解決.
點(diǎn)擊下載紅線項(xiàng),刪除老的證書,重新導(dǎo)入 G2 證書
圖-13

以上,ApplePay 所需的環(huán)境就算全部配置完成了。
總結(jié)一下就一條:生成了 Merchant ID 證書。
再看 項(xiàng)目 工程,已經(jīng)自動(dòng)生成了 Merchant ID 值,打鉤就可以了,如果沒有生成,再檢查下 項(xiàng)目的 Bundle identifier是否和證書一致。
圖-14

代碼集成##

首先我們來看下模擬器上Demo 運(yùn)行的結(jié)果:

圖-15

這里要說的 重點(diǎn)不在下半部分,而是 Buy with XXPay 這個(gè)按鈕,我們知道蘋果是一個(gè)有情(偏)懷(執(zhí))的處女座公司,對很多的設(shè)計(jì)或則交互都有自己的一套規(guī)則,ApplePay 的響應(yīng) 按鈕也不例外。不要以為隨便 弄個(gè) 設(shè)計(jì)個(gè)按鈕 就能上線了,這個(gè)時(shí)候 美工和老板說了都不算,要聽蘋果的ApplePay 設(shè)計(jì)規(guī)范。不然審核也過不了。

1、
導(dǎo)入頭文件,(xcode 7.0 以上已經(jīng)自動(dòng)幫我們導(dǎo)入了庫,所以我們只需要導(dǎo)入頭文件即可)

#import <PassKit/PassKit.h>

2、
PKPaymentAuthorizationViewController Apple pay的展示控件,也是核心類。直接看代碼

- (void)actionApplePay:(UIButton *)button {

  if ([PKPaymentAuthorizationViewController canMakePayments]) {

    NSLog(@"Woo! Can make payments!");

    if ([PKPaymentAuthorizationViewController canMakePaymentsUsingNetworks:@[
          PKPaymentNetworkChinaUnionPay,
          PKPaymentNetworkMasterCard,
          PKPaymentNetworkVisa
        ]]) {

    } else {
      NSLog(@"用戶未添加銀行卡");
      return;
    }

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

    PKPaymentSummaryItem *widget1 = [PKPaymentSummaryItem
        summaryItemWithLabel:@"Widget 1"
                      amount:[NSDecimalNumber decimalNumberWithString:@"0.01"]];

    PKPaymentSummaryItem *widget2 = [PKPaymentSummaryItem
        summaryItemWithLabel:@"Widget 2"
                      amount:[NSDecimalNumber decimalNumberWithString:@"0.01"]];

    PKPaymentSummaryItem *total = [PKPaymentSummaryItem
        summaryItemWithLabel:@"Grand Total"
                      amount:[NSDecimalNumber decimalNumberWithString:@"0.02"]];

    request.paymentSummaryItems = @[ widget1, widget2, total ];
    request.countryCode = @"CN";
    request.currencyCode = @"CHW";

    //能支付的幣種
    request.supportedNetworks = @[
      PKPaymentNetworkChinaUnionPay,
      PKPaymentNetworkMasterCard,
      PKPaymentNetworkVisa
    ];
      
    //Merchant ID
    request.merchantIdentifier = @"merchant.com.Carman.Paydemo";

    // 詢問你的付款處理器 (PKMerchantCapabilityCredit
    // 信用卡,PKMerchantCapabilityDebit 借記卡)

    /*
     PKMerchantCapabilityCredit NS_ENUM_AVAILABLE_IOS(9_0)   = 1UL << 2,   //
     支持信用卡
     PKMerchantCapabilityDebit  NS_ENUM_AVAILABLE_IOS(9_0)   = 1UL << 3    //
     支持借記卡
     */
    request.merchantCapabilities = PKMerchantCapabilityCredit;
    // 添加聯(lián)系人郵箱 及送貨地址信息
    //request.requiredShippingAddressFields = PKAddressFieldAll;

    PKPaymentAuthorizationViewController *paymentPane =
        [[PKPaymentAuthorizationViewController alloc]
            initWithPaymentRequest:request];
    paymentPane.delegate = self;
    [self presentViewController:paymentPane animated:TRUE completion:nil];

  } else {
    NSLog(@"設(shè)備不支持支付");
  }
}

1、[PKPaymentAuthorizationViewController canMakePayments] 判斷設(shè)備支持不支持 ApplePay。中國區(qū) 是 iphone 6 及以上,iOS9.2
2、canMakePaymentsUsingNetworks: 判斷 設(shè)備上用戶有沒有添加銀行卡,如果沒添加,不寫這個(gè)判斷,真機(jī)上會(huì)crash。
PKPaymentNetworkChinaUnionPay //中國銀聯(lián)卡
PKPaymentNetworkMasterCard //Master卡
PKPaymentNetworkVisa //Visa卡

3、支付的類目以及總額

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

    PKPaymentSummaryItem *widget1 = [PKPaymentSummaryItem
        summaryItemWithLabel:@"Widget 1"
                      amount:[NSDecimalNumber decimalNumberWithString:@"0.01"]];

    PKPaymentSummaryItem *widget2 = [PKPaymentSummaryItem
        summaryItemWithLabel:@"Widget 2"
                      amount:[NSDecimalNumber decimalNumberWithString:@"0.01"]];

    PKPaymentSummaryItem *total = [PKPaymentSummaryItem
        summaryItemWithLabel:@"Grand Total"
                      amount:[NSDecimalNumber decimalNumberWithString:@"0.02"]];

    request.paymentSummaryItems = @[ widget1, widget2, total ];

4、countryCode 國家 code ,中國的是 CN ,不太清楚定義的可以查看 countryCode查詢網(wǎng)站
5、currencyCode 支付幣種 ,人民幣 CHW
6、supportedNetworks 能支持的卡種,同 2
7、merchantIdentifier ,終于出現(xiàn)這貨了,申請半天的 Merchant ID ,請注意保持一致。
8、
merchantCapabilities
詢問你的付款處理器
PKMerchantCapabilityCredit //支持信用卡
PKMerchantCapabilityDebit //支持借記卡
9、requiredShippingAddressFields 添加聯(lián)系人信息

typedef NS_OPTIONS(NSUInteger, PKAddressField) {
    PKAddressFieldNone                              = 0UL,      // No address fields required.
    PKAddressFieldPostalAddress                     = 1UL << 0, // Full street address including name, street, city, state/province, postal code, country.
    PKAddressFieldPhone                             = 1UL << 1,
    PKAddressFieldEmail                             = 1UL << 2,
    PKAddressFieldName NS_ENUM_AVAILABLE_IOS(8_3)   = 1UL << 3,
    PKAddressFieldAll                               = (PKAddressFieldPostalAddress|PKAddressFieldPhone|PKAddressFieldEmail|PKAddressFieldName)
} NS_ENUM_AVAILABLE(NA, 8_0);

10、調(diào)起 ** PKPaymentAuthorizationViewController**

 PKPaymentAuthorizationViewController *paymentPane =
        [[PKPaymentAuthorizationViewController alloc]
            initWithPaymentRequest:request];
    paymentPane.delegate = self;
      
    [self presentViewController:paymentPane animated:TRUE completion:nil];

當(dāng)然,我們要實(shí)現(xiàn)<PKPaymentAuthorizationViewControllerDelegate> 代理

@interface ViewController : UIViewController<PKPaymentAuthorizationViewControllerDelegate>
@end

實(shí)現(xiàn) PKPaymentAuthorizationViewControllerDelegate##

必須實(shí)現(xiàn)的兩個(gè)代理:

#pragma mark-- PKPaymentAuthorizationViewControllerDelegate
- (void)
    paymentAuthorizationViewController:
        (PKPaymentAuthorizationViewController *)controller
                   didAuthorizePayment:(PKPayment *)payment
                            completion:
                                (void (^)(PKPaymentAuthorizationStatus status))
                                    completion {
  NSLog(@"Payment was authorized: %@", payment);

  // do an async call to the server to complete the payment.
  // See PKPayment class reference for object parameters that can be passed
  BOOL asyncSuccessful = FALSE;

  if (asyncSuccessful) {
    completion(PKPaymentAuthorizationStatusSuccess);

    NSLog(@"支付成功");

  } else {
    completion(PKPaymentAuthorizationStatusFailure);
    NSLog(@"支付失敗");
  }
}

- (void)paymentAuthorizationViewControllerDidFinish:
        (PKPaymentAuthorizationViewController *)controller {
  // hide the payment window
  [controller dismissViewControllerAnimated:TRUE completion:nil];
}

1、paymentAuthorizationViewController:didAuthorizePayment:
completion

支付 狀態(tài)回調(diào)在這里處理,支付成功和失敗,訂單的地址 以及和 服務(wù)器傳輸數(shù)據(jù)-token。
2、paymentAuthorizationViewControllerDidFinish:支付結(jié)束,關(guān)閉 支付彈框。
3、可選的另外的代理 回調(diào) 請參考Apple Pay接入詳細(xì)教程 一文

我們主要來看下** PKPayment** 對象

圖-16

token 支付成功之后的回執(zhí),需要上傳給服務(wù)器。
billingAddress 用戶賬單地址
billingContact 用戶賬單信息
shippingAddress 送貨地址
shippingContact 送貨信息
shippingMethod 送貨方式
以上的 信息 可以根據(jù)自己的需求 上傳到服務(wù)器

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

}

更深入了解可以參看官方文檔

錢去哪了##

目前為止,我們完成了客戶端的ApplePay 代碼集成,假設(shè)回調(diào)的信息也成功上傳 服務(wù)器,服務(wù)器也成功對訂單進(jìn)行了處理,那么用戶支付的錢去哪了?
1、錢去了商家的 AppStore 賬號(hào)?
蘋果賬號(hào)的申請一般都是用信用卡支付 ,業(yè)務(wù)的收入不太可能直接打到信用卡里。
2、商家 AppStore 賬號(hào)綁定了商家的銀行卡?
我們生成 Merchant ID 證書的時(shí)候 并沒有這一步。

支付供應(yīng)商##

蘋果官方文檔 Apple Pay 入門 明確指出:

圖-17

就是說,蘋果官方強(qiáng)烈建議開發(fā)者接入他合作的支付供應(yīng)商SDK 來支持ApplePay,這樣就能理解了,開發(fā)者到支付供應(yīng)商網(wǎng)站注冊相關(guān)信息,綁定商戶ID ,銀行卡等,這樣用戶的錢就到了商戶在支付供應(yīng)商注冊的賬號(hào)里面。我們可以把支付供應(yīng)商 理解成付款處理結(jié)構(gòu)。 坑爹呀,上面的集成都白寫了!??!

蘋果官方在中國合作的指定付款處理結(jié)構(gòu)有 (參考ApplePay 介紹):

中國銀聯(lián)
連連支付
首信易支付
易寶支付
銀聯(lián)商務(wù)

這里選擇中國銀聯(lián)的sdk 進(jìn)行介紹,有興趣的同學(xué)可以自行去研究另外幾個(gè)供應(yīng)商的支付SDK。

中國銀聯(lián)##

選擇中國銀聯(lián) 接入 有個(gè)很大的好處 -- 文檔非常的詳細(xì)。
1、中國銀聯(lián)商戶入網(wǎng)新手指南
https://merchant.unionpay.com/join/help/director
2、銀聯(lián)商家服務(wù)
https://open.unionpay.com/ajweb/product/detail?id=80
3、銀聯(lián)Apple Pay控件開發(fā)包
https://open.unionpay.com/ajweb/help/file/techFile?productId=80

銀聯(lián)Apple Pay控件開發(fā)包####

下載 銀聯(lián)的Apple Pay 控件開發(fā)包,里面有非常詳細(xì)的 介紹,如何接入ApplePay。


圖-18

銀聯(lián)支付控件 SDK 模式 Apple Pay 支付的實(shí)現(xiàn)方式###

圖-19

1-2、 商戶生成訂單,通過商戶SERVER端將訂單信息發(fā)送給銀聯(lián)支付網(wǎng)關(guān);
3-4、銀聯(lián)支付網(wǎng)關(guān)記錄訂單信息,返回用來標(biāo)識(shí)訂單的 TN 號(hào),經(jīng)由商戶 SERVER 返回至給商戶 APP;
5、 商戶 APP 調(diào)用銀聯(lián) SDK,將 TN 號(hào)傳遞給銀聯(lián) SDK
6、 銀聯(lián) SDK 向 Apple 公司的 PASSKIT FRAMEWORK 發(fā)起支付請求;
7、 接口返回加密的支付 Token 信息;
8-9、銀聯(lián) SDK 將支付 Token 傳遞給銀聯(lián)支付網(wǎng)關(guān),完成交易認(rèn)證;
10-12、銀聯(lián)將支付結(jié)果返回給商戶 APP,商戶 SERVER,商戶 APP 負(fù)責(zé)提示用戶交易結(jié)果。

集成的測試代碼介紹##

1-2步、商戶生成訂單,通過商戶SERVER端將訂單信息發(fā)送給銀聯(lián)支付網(wǎng)關(guān); 代碼如下:

- (void) pmPayAction:(id)sender {
    //使用PM環(huán)境
    self.tnMode = @"01";
    NSURL* url = [NSURL URLWithString:@"http://101.231.204.84:8091/sim/getacptn"];
    
    NSMutableURLRequest * urlRequest=[NSMutableURLRequest requestWithURL:url];
    NSURLConnection* urlConn = [[NSURLConnection alloc] initWithRequest:urlRequest delegate:self];
    [urlConn start];
    [self showAlertWait];
}

1、 self.tnMode = @"01"; //接入模式,標(biāo)識(shí)商戶以何種方式調(diào)用支付控件,00生產(chǎn)環(huán)境,01測試環(huán)境
2、http://101.231.204.84:8091/sim/getacptn //銀聯(lián)提供測試的 URL

3-9 步:代碼如下:

#pragma mark - connection

- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse*)response
{
    NSHTTPURLResponse* rsp = (NSHTTPURLResponse*)response;
    NSInteger code = [rsp statusCode];
    if (code != 200)
    {
        
        [self showAlertMessage:kErrorNet];
        [connection cancel];
    }
    else
    {
        UPRelease(_responseData);
        _responseData = [[NSMutableData alloc] init];
    }
}

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
    [_responseData appendData:data];
}

- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
    [self hideAlert];
    NSString* tn = [[NSMutableString alloc] initWithData:_responseData encoding:NSUTF8StringEncoding];
    if (tn != nil && tn.length > 0)
    {
        if([PKPaymentAuthorizationViewController canMakePaymentsUsingNetworks:@[PKPaymentNetworkChinaUnionPay]])
        {

            [UPAPayPlugin startPay:tn mode:self.tnMode viewController:self delegate:self andAPMechantID:kAppleMerchantID];
        }

    }
    [tn release];
}

-(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
    [self showAlertMessage:kErrorNet];
}

1、** [UPAPayPlugin startPay:tn mode:self.tnMode viewController:self delegate:self andAPMechantID:kAppleMerchantID];**
1、tn / /訂單信息
2、self.tnMode //接入模式,標(biāo)識(shí)商戶以何種方式調(diào)用支付控件,00生產(chǎn)環(huán)境,01測試環(huán)境
3、kAppleMerchantID //蘋果公司分配的商戶號(hào),表示調(diào)用Apple Pay所需要的MerchantID;(接入銀聯(lián)支付時(shí)候,該 MerchantID 需要商家向銀聯(lián)申請生成)

圖 -20

10-12步,銀聯(lián)將支付結(jié)果返回給商戶 APP,商戶 SERVER,商戶 APP 負(fù)責(zé)提示用戶交易結(jié)果。 回調(diào)處理。

#pragma mark -
#pragma mark 響應(yīng)控件返回的支付結(jié)果
#pragma mark -
- (void)UPAPayPluginResult:(UPPayResult *)result
{
    if(result.paymentResultStatus == UPPaymentResultStatusSuccess) {
        NSString *otherInfo = result.otherInfo?result.otherInfo:@"";
        NSString *successInfo = [NSString stringWithFormat:@"支付成功\n%@",otherInfo];
        [self showAlertMessage:successInfo];
    }
    else if(result.paymentResultStatus == UPPaymentResultStatusCancel){

        [self showAlertMessage:@"支付取消"];
    }
    else if (result.paymentResultStatus == UPPaymentResultStatusFailure) {
        
        NSString *errorInfo = [NSString stringWithFormat:@"%@",result.errorDescription];
        [self showAlertMessage:errorInfo];
    }
    else if (result.paymentResultStatus == UPPaymentResultStatusUnknownCancel)  {
        
        //TODO UPPAymentResultStatusUnknowCancel表示發(fā)起支付以后用戶取消,導(dǎo)致支付狀態(tài)不確認(rèn),需要查詢商戶后臺(tái)確認(rèn)真實(shí)的支付結(jié)果
        NSString *errorInfo = [NSString stringWithFormat:@"支付過程中用戶取消了,請查詢后臺(tái)確認(rèn)訂單"];
        [self showAlertMessage:errorInfo];
        
    }
}

運(yùn)行效果###

圖-21
圖-22
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

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