1. 程式人生 > >如何將PKPaymentPass新增到PKPassLibrary (即在客戶端裡執行新增卡片操作,填完之後會在wallet顯示)

如何將PKPaymentPass新增到PKPassLibrary (即在客戶端裡執行新增卡片操作,填完之後會在wallet顯示)

關鍵詞

com.apple.developer.payment-pass-provisioning

PKAddPaymentPassRequestConfiguration

PKAddPaymentPassViewController

PKAddPaymentPassRequest

PKPassLibrary

PKAddPassButton

PKPaymentPass

下面是開發的步驟及遇到的問題

1.向蘋果公司的人員申請Wallet(官方說是passKit)許可權

2.許可權配好後,在開發者中心配置一下Application Services:

 3.編輯描述檔案選擇下圖所示,並重新生成,沒有其他的什麼檔案

 4.xcode工程配置 開啟wallet

5.然後配置一下工程中的檔案 填入com.apple.developer.payment-pass-provisioning欄位,確定這個entitlements檔案已加到工程裡

6.申請沙盒賬號:就是假的icloud賬號,可以用第7步的賬號直接在wallet試試

7.官方網站提供的測試賬號可以直接在wallet應用里加上

8.申請測試卡賓:即測試賬號的前6位

9.開發中遇到報錯:蘋果查需要提供SEID,銀聯查需要提供卡號

10:有效期的格式需要傳斜槓

10.報錯"無法新增卡"有很多原因

如果把密文給蘋果直接報錯“無法新增卡”,那就是加密錯誤,祕鑰是一個數組需要都傳給後臺。

11.報錯“卡片有誤”,說明加解密已過,是我們自己這邊的卡可能被鎖

12.開發此功能的設定支援的iOS版本可以低於10.3,如果使用tesfflight測試此功能需要提高到10.3.

13.上程式碼

//設定加密型別
        PKAddPaymentPassRequestConfiguration *con = [[PKAddPaymentPassRequestConfiguration alloc]initWithEncryptionScheme:PKEncryptionSchemeRSA_V2];
        con.cardholderName = @"介面展示用";
        con.localizedDescription = @"加卡";//描述資訊
        if (IOS10_OR_LATER) {
            con.paymentNetwork = PKPaymentNetworkChinaUnionPay;//銀聯卡
        }
        con.primaryAccountSuffix =  @“1111”;卡號結尾4位
        PKAddPaymentPassViewController *vc = [[PKAddPaymentPassViewController alloc] initWithRequestConfiguration:con delegate:self];
        [XXX.rootViewController pushViewController:vc animated:YES];

然後實現下面的方法
- (void)addPaymentPassViewController:(PKAddPaymentPassViewController *)controller
 generateRequestWithCertificateChain:(NSArray<NSData *> *)certificates
                               nonce:(NSData *)nonce
                      nonceSignature:(NSData *)nonceSignature
                   completionHandler:(void(^)(PKAddPaymentPassRequest *request))handler;{
    NSString *leafBase64Encoded = [certificates[0] base64EncodedStringWithOptions:0];
    NSString *subBase64Encoded = [certificates[1] base64EncodedStringWithOptions:0];
    NSArray * cerArray = @[leafBase64Encoded,subBase64Encoded];

    
    NSString *nonceStr = [self convertDataToHexStr:nonce];
    
    NSString *nonceSignatureStr = [self convertDataToHexStr:nonceSignature];
    

    //然後往後臺發介面 注意cerArray直接發給後臺
    //後臺返回密碼等資料

    然後回傳給sdk

                           NSString *encryptedPassString = params[@"encryptedPassData"];
                           
                           encryptedPassString = [encryptedPassString stringByReplacingOccurrencesOfString:@" " withString:@""];
                           
                           encryptedPassString = [encryptedPassString stringByReplacingOccurrencesOfString:@"\r\n" withString:@""];
                           
                           encryptedPassString = [encryptedPassString stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
                           
                           NSData *encryptedPassData=[[NSData alloc] initWithBase64EncodedString:encryptedPassString options:0];
                           
                           
                           
                           NSString *activationString = params[@"activationData"];
                           
                           activationString = [NSString stringWithFormat:@"%@|%@",nonceSignatureStr, params[@"activationData"]];

                           
                           NSData *activationData = [activationString dataUsingEncoding:NSUTF8StringEncoding];
                           
                           
                           
                           NSString *wrappedKeyString = params[@"wrappedKey"];
                           
                           wrappedKeyString = [wrappedKeyString stringByReplacingOccurrencesOfString:@" " withString:@""];
                           
                           wrappedKeyString = [wrappedKeyString stringByReplacingOccurrencesOfString:@"\r\n" withString:@""];
                           
                           wrappedKeyString = [wrappedKeyString stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
                           
                           NSData *wrappedKey=[[NSData alloc] initWithBase64EncodedString:wrappedKeyString options:0];
                           
                           wrappedKey = [EncodeAndDecode dataFromHexString:wrappedKeyString];
                           encryptedPassData = [EncodeAndDecode dataFromHexString:encryptedPassString];

 
                           
                           PKAddPaymentPassRequest *request = [[PKAddPaymentPassRequest alloc] init];
                           
                           request.activationData = activationData;
                           
                           request.encryptedPassData = encryptedPassData;
                           
                           request.wrappedKey = wrappedKey;
                           
                           
                           
                           
                           
                           if (request == nil) {
                               
                               return;
                               
                           }
                           
                           
                           
                           if (handler) {

                               handler(request);
                               
                           }
//下面這個方法   失敗會走但沒什麼有用的資訊  
- (void)addPaymentPassViewController:(PKAddPaymentPassViewController *)controller didFinishAddingPaymentPass:(nullable PKPaymentPass *)pass error:(nullable NSError *)error;{
}

//進位制轉換
- (NSString *)convertDataToHexStr:(NSData *)data {
    
    if (!data || [data length] == 0) {
        
        return @"";
        
    }
    
    NSMutableString *string = [[NSMutableString alloc] initWithCapacity:[data length]];
    
    
    
    [data enumerateByteRangesUsingBlock:^(const void *bytes, NSRange byteRange, BOOL *stop) {
        
        unsigned char *dataBytes = (unsigned char*)bytes;
        
        for (NSInteger i = 0; i < byteRange.length; i++) {
            
            NSString *hexStr = [NSString stringWithFormat:@"%x", (dataBytes[i]) & 0xff];
            
            if ([hexStr length] == 2) {
                
                [string appendString:hexStr];
                
            } else {
                
                [string appendFormat:@"0%@", hexStr];
                
            }
            
        }
        
    }];
    
    
    
    return string;
    
}

注意:1.證書要編碼傳給後臺,對證書編碼這裡用base64和平時用的沒有區別 

2.nonce要轉成16進位制傳給後臺  不是做base64。使用convertDataToHexStr方法或下面這個都行

    NSString *nOnce = [NSString stringWithFormat:@"%@",nonce];

    nOnce = [nOnce stringByReplacingOccurrencesOfString:@"<" withString:@""];

    nOnce = [nOnce stringByReplacingOccurrencesOfString:@">" withString:@""];

    nOnce = [nOnce stringByReplacingOccurrencesOfString:@" " withString:@""];

3.nonceSignature同上

4.後臺返回的資料如何給蘋果,encryptedPassData和wrappedKey需要直接從16進位制字串轉為nsdata

方法是

+ (NSData *) dataFromHexString:(NSString*)hexString
{
    NSString * cleanString = [SM4EncodeAndDecode cleanNonHexCharsFromHexString:hexString];
    if (cleanString == nil) {
        return nil;
    }
    
    NSMutableData *result = [[NSMutableData alloc] init];
    
    int i = 0;
    for (i = 0; i+2 <= cleanString.length; i+=2) {
        NSRange range = NSMakeRange(i, 2);
        

        
        NSString* hexStr = [cleanString substringWithRange:range];
        NSScanner* scanner = [NSScanner scannerWithString:hexStr];
        unsigned int intValue;
        [scanner scanHexInt:&intValue];
        unsigned char uc = (unsigned char) intValue;
        [result appendBytes:&uc length:1];
    }
    
    NSData * data = [NSData dataWithData:result];
    
//    [result autorelease];//add先去掉 可能有閃退
    
    return data;
}

5.返回的activationData 轉成data就可以 和後臺約定一下就行

6.然後可能報錯 錯誤1

上圖的警告框下邊就一個按鈕“好”,這種情況應該是返給蘋果的資料型別不對

7.錯誤2  這個下邊兩個按鈕   如果在協議之前彈出來應該是加解密錯誤(後臺要用test vector驗仔細證)   或銀聯問題

如果在協議之後彈出來應該是自己後臺驗證的問題

在wallet裡新增或在客戶端裡新增應該走的鏈路沒啥區別都報相同的錯

8.錯誤3   如果在協議之前彈出來應該是已經過了加解密,而且這個是信用卡報出來的機率大,可以驗證第7步是否加解密沒有問題

9.如果下面的錯 加解密沒問題   卡賓沒有加到測試蘋果資料裡

10.如果銀聯沒有問題會彈出協議

11.然後加掛成功 

12.注意的問題

(1)- (NSArray<PKPass *> *)passesOfType:(PKPassType)passType

這個方法如果獲取不到資料需要後臺配置一下引數:teamid.bundleid  

後臺程式碼類似

"cardMetaData":{"associatedApplicationIdentifiers":[":["P2V7337495.com.elem.e","P","","P2V7337495.com.nihaom.hao"],""],"associatedStoreIdentifiers":["473489211"]

(2)名詞 fpan不太懂應該用不到

en_otp:加密驗證碼 應該指的是activationData

(3)- canAddPaymentPassWithPrimaryAccountIdentifier:  傳入的引數應該是fpan後臺給的

相關推薦

如何PKPaymentPass新增PKPassLibrary 客戶執行新增卡片操作之後wallet顯示

關鍵詞 com.apple.developer.payment-pass-provisioning PKAddPaymentPassRequestConfiguration PKAddPaymentPassViewController PKAddPaymentPass

socket間通訊_TCP客戶執行服務命令

服務端: import os import socket HOST = '172.25.254.41' PORT = 9881 # 1. 建立服務端的socket物件 with socket.socket() as serverSocket:

angular2^ typescript 文件和Json數據 合並發送到服務器1.客戶處理

src ica div .html web ready 進行 form med 首先介紹下框架基本流程 (web > webservice 【前端架構】 ) > (nodejs 【 數據中轉站 】) >(api 【後臺接口】) --web (htm

Cas 服務器 ServiceCas客戶註冊信息維護

操作 電腦 添加 img keytool eid div tro down 作為Cas服務器,允許哪些客戶端接入與否是通過配置來定義的。對Cas服務器來說,每一個接入的客戶端與一個Service配置對應;在Cas服務器啟動時加載並註冊上這些Service,與之對應的客戶端才

PHP規範PSR18HTTP客戶介紹

本文件描述了用於傳送HTTP請求和接收HTTP響應的通用介面。 本文件中的關鍵詞“必須”,“必須”,“必需”,“應該”,“不應該”,“應該”,“不應該”,“推薦”,“可以”和“可選”按照RFC 2119中的描述進行解釋。 1 目標 此PSR的目標是允許開發人員建立與HTTP客戶端實現分離的庫

動作手遊實時PVP幀同步方案圖解客戶

1、概述 1.1、基於UDP的幀同步方案   在技術選型方面,之所以選擇幀同步方案,在Kevin的一篇介紹PVP幀同步後臺實現的文章中已經做了詳細敘述,這裡簡單摘要如下:   高一致性。如果每一幀的輸入都同步了,在同樣的上下文中,計算得出的結果應該也是同步的。   低流量消耗。除了幀

重灌系統後重新安裝ORACLE加環境變數配置、客戶PL/SQL的安裝過程及注意事項避免再次踩坑

(1)首先了解什麼是OERACLE及Oracle與PL/SQL是什麼關係: ORACLE是資料庫,有客戶端和伺服器; PLSQL Developer只是第三方工具,服務於ORACLE,類似的工具還有Toad,sqlplus,sql developer等等; 安裝PLSQL Developer

skill——zbbix主動客戶自動註冊

主動客戶端自動註冊 自動註冊(agent auto-registration)功能主要用於 Agent 主動且自動向 Server 註冊。與前面的自動發現(Network discovery)具有同樣的功能 但是這個功能更適用於特定的環境:當存在一個條件未知(如 agent 端的 IP 地址段、age

(QT) C++ 版本IM通訊軟體客戶+伺服器文字聊天、檔案斷點續傳、線上使用者搜尋

緊接著上一節課程,這次的作業是要求實現一個簡易版的“QQ”,可支援“軟體需求”所列出的功能。當時由於圖方便便選擇了QTCPSocket進行整個過程的通訊(事後才知道有多坑)。服務端介面比較簡單,就幾個按鈕一個進度條,主要在客戶端實現了基本的功能和介面。整個學習和

BootStrap 表格分頁伺服器客戶

伺服器分頁表格  function InitMainTable1 () { //記錄頁面bootstrap-table全域性變數$table,方便應用 var queryUrl = "/XServer/user.do?_

推薦一款好用的國外網盤 mega客戶下載及使用教程

國內,免費好用的網盤基本絕跡了。比如百度網盤,免費各種限速,速度坑的一比,雖然有一些方法可以突破百度網盤限速,不過百度網盤演算法也一直在更新,可能之前有用的方法後面就失效了。而 115 網盤,也是需要付費才能體驗比較好的服務,而且費用還不便宜。 現在介紹國外的一款網盤,名為 mega 網

Java-TCP程式編寫TCP客戶和服務

1.TCP服務端的程式編寫 package test; import java.io.BufferedReader; import java.io.InputStreamReader; import java.net.ServerSocket; import java.net.Sock

python網路程式設計TCP客戶/伺服器實現

下面的程式實現的功能:客戶端發來訊息,伺服器端加上時間戳返回給使用者 伺服器端: from socket import * from time import ctime import os p

Oracle Instant Client即時客戶 安裝與配置

一、下載 下載地址:http://www.oracle.com/technetwork/database/features/instant-client/index-097480.html 這是Oracle Instant Client的下載首頁,有很多種版本可供下載。 但

Windows C語言 Socket程式設計 server伺服器--初級客戶——初級版

看過我的簡單版的伺服器程式碼的,會發現那段程式碼同一時間只能和一個客戶端通訊。這樣的程式碼能力很小侷限性很大。今天我來介紹一種多客戶端的伺服器程式碼。當然這段程式碼還是有問題的,至於是什麼問題我會在程式碼後面說清楚。 我的這個多客戶端的程式碼核心思想是多執行緒

Live555學習之(四)------建立RTSP連線的過程RTSP客戶

  Live555不僅實現了RTSP伺服器端,還實現了RTSP客戶端,我們通過testRTSPClient.cpp這個程式來看一下,Live555的RTSP客戶端與伺服器端建立RTSP連線的過程。   首先來看一下main函式: 1 char eventLoopWatchVariable =

Android-通過網路獲取xml檔案使用pull解析得到伺服器中的資訊新聞客戶

通過網路獲取xml檔案,使用pull解析該檔案得到伺服器中的資訊; demo中使用了一個開源的圖片載入包,故上傳原始碼方便檢視; 效果圖: 步驟: 1.連線伺服器獲取xml檔案; 2.使用pull解析xml檔案存入實體物件中; 3.解析後將實體物件存入List集合中;

簡明Github使用教程桌面客戶與網頁版

一:下載github二:安裝GitHub下載之後點選進行安裝過程,安裝之後桌面上會有兩個圖示,如下圖 三:新建專案GitHub是圖形介面模式,Git Shell是命令列模式,在Windows系統下我們使用GitHub進行程式碼管理。1:開啟GitHub圖形介面,輸入使用者名稱

DP軟體中新增一臺Windows客戶

1.遠端新增客戶端 2. 本地安裝 本地安裝完成後再匯入     DP cell manager安裝在Linux伺服器上,打算用DP備份Windows Server 2012上檔案。就需要把Windows Server新增到DP中,用遠端安裝最方便。只

MQTT Client library for C MQTT客戶C語言庫-paho

  最近在使用Paho的MQTT客戶端,由於英語看著有點慢,因此將其翻譯為中文,與大家共享。由於英語水平有限,如有翻譯不對之處,請幫忙指出。 MQTT客戶端C語言庫   MQTT客戶端的C語言庫.© Copyright IBM Corp