淘先锋技术网

首页 1 2 3 4 5 6 7
     前言:
              2016是个真正开始走向解放钱包的时代了,从各种卡片开始流行起,不管你用的是磁条卡还是芯片卡,肯定是慢慢的塞满了你的钱包,但随着2月18日Apple Pay在中国上线,越来越多的人开始使用。Apple Pay 是行业称呼,也有叫苹果支付,其实它叫连连付。下面,我们就进入接入前的准备环节。
     准备:
             Apple Pay的接入相对支付宝简单,对于微信更是简单。但是,Apple Pay的接入流程可以说是和微信支付是半亲。为什么说是半亲?因为Apple Pay的重点接入和微信的第二词签名是80%一样的。对于准备也是所有支付里面最难的一种。困难的种类:
       1、Apple Pay 的正式支付网站还不可以登录。同时他们也给出了,跨域登录和动态登录。

       2、这里我们要登录(正式登录)为了签名秘钥获取及IP域名配置。后续再说(不能正式登录就不能获得秘钥)。
       3、现在有一个测试登录入口。
       
     4、登录后,你的工作就来了。请看下图(3相里面的内容没有点开,怕吓着人了)。

      5、下面进行的也是重要的也是很麻烦的。我就用语言描述了,就不上图了(图,后续完善)。首先,你要登录苹果开发者账号。进入证书模块。如果是第一次的话。你的MerchantID 这个模块是没有东西的。我们要进行添加。添加的时候会让你写两个东西。分别是:MerchantID  和   BundleID。然后,你进行在连连付的账户里创建应用,如下图:

其中BundelID 和你开发者账号里面生成MerchantID 的时候要一样。第二步是提交,你开发者中心里面你填写的MerchantID 。第三步,你下载一个CRS 的文件。保存到重要的位置。然后。我们现在要切换到,苹果开发者中心证书生生模块。在这个模块里面,进行证书的创建。在第三步的时候,会让你提交一个CRS文件。这个文件就是,你刚才下在的文件。(后续完善)。
      6、我们进行工程的配置。
            1.我们要导入必要的支持库(保证,支付的安全,定位)。要导入的库如下:
               
            2.我们要进行开发SDK 的导入。(这里我将其融合)
               
            3.我们要挑选开发者。
            4.进入项目Build Seting 里面的OtherLinkerFlags 设置为 _all_load.
            5.进入项目 CApAbilities 模块,打开Apple Pay模块。并点击更新按钮。成功后会有三个对号。同时项目里面会出现一个证书。如下图:
              
第一:我们进行效果展示。
             
第二:功能介绍
        1、动态的边框。
          2、TableView的独立创建,界面。
          3、Pay支付和Auth的预授权。
第二:代码的编写。
       1.进行订单的签名,和部分算法代码。
       签名代码:
         

-(NSString*)GetString:(NSDictionary*)anyobjiect_dict{

    // 创建一个局部数组,防止OrderInfoAllKeysArray 为空

    NSArray * AllKeys =@[@"busi_partner",@"dt_order",@"info_order",

                          @"money_order",@"name_goods",@"no_order",

                          @"notify_url",@"oid_partner",@"risk_item",@"sign_type",

                          @"valid_order"];

    if (self.OrderInfoAllKeysArray !=nil) {

        // 如果OrderInfoAllKeysArray 存在将 Allkeys 替代

        AllKeys = self.OrderInfoAllKeysArray;

    }

    if (ErrorMessageDictInfo) {

        [ErrorMessageDictInfosetObject:@"OrderInfoAllKeysArray没有传入"forKey:@"AllKeys"];

    }

    // 将一个不可变的数组,可变化。进行数组对象字母排序

    NSMutableArray * LetterKeysArray = [NSMutableArrayarrayWithArray:AllKeys];

    [LetterKeysArray sortedArrayUsingComparator:^NSComparisonResult(id _Nonnull obj1, id _Nonnull obj2) {

        return [obj1 compare:obj2];

    }];

    // 声明一个可变的字符串,将字典转化为字符串

    NSMutableString * PiecedMutableString = [[NSMutableStringalloc]initWithCapacity:0];

    for (NSString * tempstrin LetterKeysArray) {

        if ([anyobjiect_dict[tempstr] length] != 0) {

            [PiecedMutableString appendFormat:@"&%@=%@",tempstr,anyobjiect_dict[tempstr]];

        }

    }

    // 进行可变的字符串进行处理

    if (PiecedMutableString.length !=0) {

        // 删除字符串的第一个字符:@“&”

         [PiecedMutableString deleteCharactersInRange:NSMakeRange(0,1)];

    }else{

        if(ErrorMessageDictInfo){

            [ErrorMessageDictInfosetObject:@"65可变字符串不存在"forKey:@"PiecedMutableString"];

        }

    }

    if ([anyobjiect_dict[@"sign_type"]isEqualToString:@"MD5"]) {

        // 拼接上签名的Key-Value

        [PiecedMutableString appendFormat:@"&key=%@",self.SingKey];

    }

    // 声明要输出的字符串对象

    NSString * Return_SignString = nil;

    if([anyobjiect_dict[@"sign_type"]isEqualToString:@"MD5"]){

      Return_SignString = [ApplePayAlgorithm GetMd5String:PiecedMutableString];

    }else{

      // 哈希加密

      Return_SignString = [ApplePayAlgorithm signHmacString:PiecedMutableString withKey:self.SingKey];

    }

#ifdef kLLPayUtilNeedRSASign

    id<LLPDataSigner> signer = LLPCreateRSADataSigner(self.signKey);

    signString = [signer signString:paramString];

#endif

    // 输出加密后的字符串

    NSLog(@"签名字符串:%@",Return_SignString);

    return Return_SignString;

}


      2.加密算法代码
 MD5

+(NSString*)GetMd5String:(NSString*)anyobject_string{

    // 进行编码转换成字符

    const char *original_str = [anyobject_stringUTF8String];

    unsigned char result[32];

    CC_MD5(original_str, (CC_LONG)strlen(original_str), result);//调用md5

    NSMutableString * MD5_String = [NSMutableStringstring];

    for (int i =0; i < 16; i++){

        [ MD5_String appendFormat:@"%02x", result[i]];

    }

    return MD5_String;

}


哈希

+ (NSString *)signHmacString:(NSString*)text withKey:(NSString*)key{

    constchar *cKey  = [keycStringUsingEncoding:NSUTF8StringEncoding];

    constchar *cData = [textcStringUsingEncoding:NSUTF8StringEncoding];

    uint8_t cHMAC[CC_SHA256_DIGEST_LENGTH];

    CCHmac(kCCHmacAlgSHA256, cKey,strlen(cKey), cData, strlen(cData), cHMAC);

    NSString *hash= nil;

    NSMutableString* output = [NSMutableStringstringWithCapacity:CC_SHA256_DIGEST_LENGTH *2];

    for(int i =0; i < CC_SHA256_DIGEST_LENGTH; i++){

        [output appendFormat:@"%02x", cHMAC[i]];

    }

    hash = output;

    return hash;

}

     3. 配置文件。其中商户秘钥是不正确的。

//  ApplePayCommont.h

//  Apple_Pay

//

//  Created by 周双建 on 16/2/25.

//  Copyright © 2016周双建. All rights reserved.

//

#ifndef ApplePayCommont_h

#define ApplePayCommont_h

商户号

static NSString *kLLOidPartner =@"201602190000022156";

// 商户秘钥

static NSString *kLLPartnerKey =@"201601250000011007";//这个不匹配,切记

NSString *kAPMerchantID =@"merchant.com.zsj.ApplePay";

#endif

      4.订单的创建。

#pragma mark 创建订单

-(void)CreateOrderInfo{

    // 获取当前时间

    NSDateFormatter * DateFormatter = [[NSDateFormatteralloc]init];

    [DateFormatter setDateFormat:@"yyyyMMddHHmmss"];

    // 将时间转化成字符串

    NSString * PresentTimeString = [DateFormatterstringFromDate:[NSDatedate]];

    // 订单前的标志

    NSString * OrderPresentSign = @"LL";

    // 加密的形式 MD5   RSA   哈希

    NSString * SignType = @"MD5";

    // 声明一个可变的参数字典

    self.OrderInfoMutableDict = [NSMutableDictionarydictionaryWithCapacity:0];

    NSMutableDictionary * PrameMutableDict  = [NSMutableDictionarydictionary];

    [PrameMutableDict setDictionary:@{

                          //签名方式String RSA  或者 MD5

                           @"sign_type":SignType,

                           //商户业务类型是String(6)虚拟商品销售:101001

                           @"busi_partner":@"101001",

                           //商户订单时间dt_orderString(14)格式:YYYYMMDDH24MISS  14位数字,精确到秒

                           @"dt_order":PresentTimeString,

                           //交易金额money_order Number(8,2) 该笔订单的资金总额,单位为RMB-元。大于0的数字,精确到小数点后两位。如:49.65

                           @"money_order":@"0.10",

                           //服务器异步通知地址notify_url String(64) 连连钱包支付平台在用户支付成功后通知商户服务端的地址。

                           @"notify_url":@"http://test.yintong.com.cn:80/apidemo/API_DEMO/notifyUrl.htm",

                           //商户唯一订单号no_order String(32) 商户系统唯一订单号

                           @"no_order":[NSStringstringWithFormat:@"%@%@",OrderPresentSign,PresentTimeString],

                           //商品名称name_goods String(40)

                           @"name_goods":@"琴女的皮肤",

                           //订单附加信息info_order String(255) 商户订单的备注信息,还可以详细描述。

                           @"info_order":PresentTimeString,

                          //分钟为单位,默认为10080分钟(7天),从创建时间开始,过了此订单有效时间此笔订单就会被设置为失败状态不能再重新进行支付。

                           @"valid_order":@"10080",

                           //@"shareing_data":@"201412030000035903^101001^10^分账说明1|201310102000003524^101001^11^分账说明2|201307232000003510^109001^12^分账说明3"

                           // 分账信息数据 shareing_data  (1024)

                           //@"risk_item":@"{\"user_info_bind_phone\":\"13958069593\",\"user_info_dt_register\":\"20131030122130\"}",

                          //风险控制参数 此字段填写风控参数,采用json串的模式传入,字段名和字段内容彼此对应好

                          //商户用户唯一编号 该用户在商户系统中的唯一编号,要求是该编号在商户系统中唯一标识该用户

                           // user_id,一个user_id标示一个用户

                           // user_id为必传项,需要关联商户里的用户编号,一个user_id下的所有支付银行卡,身份证必须相同

                           // demo中需要开发测试自己填入user_id,可以先用自己的手机号作为标示,正式上线请使用商户内的用户编号

                           @"risk_item" : [ApplePayAlgorithmGetString:@{@"user_info_dt_register":@"20131030122130",@"cinema_name":@"大电影院",@"book_phone":@"18811520397"}],@"user_id":@"xu20160215",

                           @"oid_partner":kLLOidPartner

                            }];

    self.OrderInfoMutableDict = PrameMutableDict;

    // matech ID   预支付AP ID

    self.OrderInfoMutableDict[@"ap_merchant_id"] =kAPMerchantID;

    if (kLLOidPartner.length >0) {

        // 商户秘钥

        self.OrderInfoMutableDict[@"oid_partner"] =kLLOidPartner;

        return;

    }

}


  5.Pay支付代码。

// 进行支付

- (void)payWithSignedOrder:(NSDictionary*)signedOrder

{

    [LLAPPaySDK sharedSdk].sdkDelegate =self;

    [[LLAPPaySDKsharedSdk] payWithTraderInfo:signedOrder

                             inViewController:self];

}

  6.Auth 授权。

#pragma mark  预授权

- (void)authWithSignedOrder:(NSDictionary*)signedOrder{

    [LLAPPaySDK sharedSdk].sdkDelegate =self;

    [[LLAPPaySDKsharedSdk] preauthWithTraderInfo:signedOrder

                                 inViewController:self];

}


7.支付的回调。

#pragma mark  支付结果的返回

- (void)paymentEnd:(LLPayResult)resultCode withResultDic:(NSDictionary*)dic{

    [selfalertView:[ApplePayAlgorithmGetString:dic]];

    switch (resultCode) {

        casekLLPayResultSuccess:{

          // 支付成功

            NSString* result_pay = dic[@"result_pay"];

            if ([result_pay isEqualToString:@"SUCCESS"])

            {

                [self alertView:@"SUCCESS"];


            }

            else if ([result_payisEqualToString:@"PROCESSING"])

            {

                //@"支付单处理中";

                [self alertView:@"支付单处理中"];


            }

            else if ([result_payisEqualToString:@"FAILURE"])

            {

                // @"支付单失败";

                [self alertView:@"支付单失败"];


            }

            else if ([result_payisEqualToString:@"REFUND"])

            {

                // @"支付单已退款";

                [self alertView:@"支付单已退款"];


            }


        }

            break;

        casekLLPayResultFail:{

          // 支付失败

           [self alertView:@"支付失败"];

            


        }

            break;

        casekLLPayResultCancel:{

           // 用户取消支付

            [self alertView:@"用户取消支付"];


        }

            break;

        casekLLPayResultInitError:{

            [selfalertView:@"支付初始化错误,订单信息有误,签名失败等"];


           //支付初始化错误,订单信息有误,签名失败等

        }

            break;

        casekLLPayResultInitParamError:{

            [selfalertView:@"支付订单参数有误,无法进行初始化,未传必要信息等"];

        }

            

            break;

        casekLLPayResultUnknow:{

            //其他

            [self alertView:@"其他"];

        }

            

            break;

        default:

            break;

    }

    

}

8.切记,不要忘记添加代理。

LLPaySdkDelegate


9.下载地址。
https://github.com/zhoushuangjian/Apple_Pay.git