如何将PKPaymentPass添加到PKPassLibrary中

关键词

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应用里加上

https://developer.apple.com/apple-pay/sandbox-testing/

 

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后台给的

 

20181214补充

银联还有一些限制,同一张卡同设备一天只能绑定成功两次,一天只能错10次

 

20181221补充

这两个地方传入的primaryAccountIdentifier是银联给的不是自己拼的 应该叫实体卡id 类似FAPLUPCEBb660e3aac30447599dd06ecfbf53a9f1  不写的话测试环境没事 

// Returns YES if either the current device or an attached device both supports adding payment passes and does not already contain

// a payment pass with the supplied primary account identifier.

- (BOOL)canAddPaymentPassWithPrimaryAccountIdentifier:(NSString *)primaryAccountIdentifier API_AVAILABLE(ios(9.0));




/* Pass Library Filters:

 *  If the filtered set is empty, then all filter will be ignored.

 */

@property (nonatomic, copy, nullable) NSString *primaryAccountIdentifier;

后台投产后需要把下面两个发邮件给苹果加白名单才可以正式在生产上使用,只能用生产证书打包

team id 从Membership中查

adam ID从此app的appstore下载链接中取

 

20190124 如何判断某张卡是不是其他设备上的:BOOL canAdd = [passLibrary canAddPaymentPassWithPrimaryAccountIdentifier:fpanID]; 通过这个方法返回的NO表示本设备已经加载了

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值