如何将PKPaymentPass添加到PKPassLibrary (即在客户端里执行添加卡片操作,填完之后会在wallet显示)

版权声明:本文为博主原创文章,转载请注明出处。 https://blog.csdn.net/qq_15509071/article/details/83069987

关键词

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:加密验证码

猜你喜欢

转载自blog.csdn.net/qq_15509071/article/details/83069987