iOS之“支付宝支付”开发流程

支付宝快捷支付的主要步骤:

  • 先与支付宝签约,获得商户ID(partner)和账号ID(seller);
  • 下载相应的公钥私钥文件(加密签名用);
  • 下载支付宝SDK;
  • 生成订单信息;
  • 调用支付宝客户端,由支付宝客户端跟支付宝安全服务器打交道;
  • 支付完毕后返回支付结果给商户客户端和服务。

而iOS客户端需要做的是:

  • 调用支付宝支付接口;
  • 处理支付宝返回的支付结果。

在调用支付宝支付接口前,还需要先生成一个订单,下载的支付宝文档中描述时,是将这步也放在客户端来做了,但也可以在服务器端生成这个订单(支付宝会在支付成功后通知服务器端,所以在服务器端生成订单的话,开发者掌握所有订单,而且也会更安全)。

  • 生成订单(可以在iOS客户端内生成,也可以在服务器端生成);
  • 调用支付宝支付接口,发送订单;
  • 处理支付宝返回的支付结果。

支付宝支付的安全问题,需要在生成订单和处理支付结果的时候做一个安全性校验:即生成订单时对数据签名,收到支付结果时对数据进行签名验证,以检验数据是否被篡改过(支付宝目前只支持采用RSA加密方式做签名验证)。简单地说,就是在生产订单时,需要使用私钥生成签名值;在处理返回的支付结果时,需要使用公钥验证返回结果是否被篡改。

支付宝iOS SDK的官方下载地址:
https://b.alipay.com/order/productDetail.htm?productId=2013080604609654&tabId=4#ps-tabinfo-hash

压缩包里有两个相关文档:
《支付宝钱包支付接口开发包2.0标准版.pdf》
《支付宝钱包支付接口开发包2.0标准版接入与使用规则.pdf》

集成支付宝支付的主要流程:

  • 将需要的文件,静态库等拖入工程中,这里有include,libs,Utilities,libcrypto.a,libssl.a文件(如果只需要发送订单和处理支付返回结果,只需要添加AlipaySDK.bundle和AlipaySDK.framework)。如下图:
    iOS之“支付宝支付”开发流程_第1张图片

  • 设置Head Search Paths 和 Library Search Paths
    即:targets->Build Setting ->Search Paths->Always Search User Paths和 Library Search Paths,注意:Always Search User Paths 和 Library Search Paths的路径一定要根据这个地址能找到对应的头文件。

这里写图片描述

  • 设置partner、seller、RSA private key、RSA public key
    一般是设置在-info文件中。
    这里写图片描述

  • 支付成功后,回到应用程序中
    需要设置回调的标示,同样在-info文件中,添加个节点:
    这里写图片描述

  • 发送订单的方法:

- (void)payOrder:(NSString *)orderStr
      fromScheme:(NSString *)schemeStr
        callback:(CompletionBlock)completionBlock;

如果手机内没安装支付宝的app,会直接展现支付宝web支付界面,通过callback返回支付结果;如果手机内安装了支付宝的app,会跳转到支付宝的app支付,然后通过openURL的回调返回支付结果。

  • 调用支付宝
[[AlipaySDK defaultService] payOrder:orderString fromScheme:appScheme callback:^(NSDictionary *resultDic) {
     if ([resultDic[@"resultStatus"] intValue] == 9000) {
         //支付成功
      }
      else{
         NSString *resultMes = resultDic[@"memo"];
         resultMes = (resultMes.length<=0?@"支付失败":resultMes);
         NSLog(@"%@",resultMes);                       }
    }];

支付宝的SDK只给了一个处理返回结果的方法,没有提供处理openURL的方法:

if ([url.host isEqualToString:@"safepay"]) {
    [[AlipaySDK defaultService] processOrderWithPaymentResult:url
    standbyCallback:^(NSDictionary *resultDic) {
              NSLog(@"result = %@",resultDic);
    }]; }

SDK提供了处理openURL返回结果的方法:

- (void)processOrderWithPaymentResult:(NSURL *)resultUrl standbyCallback:(CompletionBlock)completionBlock;

两个回调block都统一定义为typedef void(^CompletionBlock)(NSDictionary *resultDic)。

resultStatus状态码对应的信息:

  • 9000:订单支付成功
  • 8000:正在处理中
  • 4000:订单支付失败
  • 6001:用户中途取消
  • 6002:网络连接出错

result是订单信息,以及签名验证信息。

代码过程展示:

  • 在AppDelegate中:

- (BOOL)application:(UIApplication *)application
            openURL:(NSURL *)url
  sourceApplication:(NSString *)sourceApplication
         annotation:(id)annotation {
         //跳转支付宝钱包进行支付,处理支付结果
    [[AlipaySDK defaultService] processOrderWithPaymentResult:url standbyCallback:^(NSDictionary *resultDic) {
        NSLog(@"result = %@",resultDic);
    }];
    return YES;
}

- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url {
    [self parseURL:url application:application];
    return YES;
}

//签名验证
- (void)parseURL:(NSURL *)url application:(UIApplication *)application {
    AlixPay *alixpay = [AlixPay shared];
    AlixPayResult *result = [alixpay handleOpenURL:url];
    if (result) {
        //是否支付成功
        if (9000 == result.statusCode) {
            /*
             *用公钥验证签名
             */
            id verifier = CreateRSADataVerifier([[NSBundle mainBundle] objectForInfoDictionaryKey:@"RSA public key"]);
            if ([verifier verifyString:result.resultString withSign:result.signString]) {
                UIAlertView * alertView = [[UIAlertView alloc] initWithTitle:@"提示" 
                                                                     message:result.statusMessage 
                                                                    delegate:nil 
                                                           cancelButtonTitle:@"确定" 
                                                           otherButtonTitles:nil];
                [alertView show];
            }//验签错误
            else {
                UIAlertView * alertView = [[UIAlertView alloc] initWithTitle:@"提示" 
                                                                     message:@"签名错误" 
                                                                    delegate:nil 
                                                           cancelButtonTitle:@"确定" 
                                                           otherButtonTitles:nil];
                [alertView show];
            }
        }
        //如果支付失败,可以通过result.statusCode查询错误码
        else {
            UIAlertView * alertView = [[UIAlertView alloc] initWithTitle:@"提示" 
                                                                 message:result.statusMessage 
                                                                delegate:nil 
                                                       cancelButtonTitle:@"确定" 
                                                       otherButtonTitles:nil];
            [alertView show];
        }
    }   
}
  • 在需要支付的页面选中商品调用支付宝安全支付
- (void)payTreasurePay {
    /*
     *商户的唯一的parnter和seller。
     *签约后,支付宝会为每个商户分配一个唯一的 parnter 和 seller。
     */
    //如果partner和seller数据存于其他位置,请改写下面两行代码
    NSString *partner = @"商户的parnter";
    NSString *seller  = @"商户的seller";

    //partner和seller获取失败,提示
    if ([partner length] == 0 || [seller length] == 0)
    {
        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"提示"
                                                        message:@"缺少partner或者seller"
                                                       delegate:self
                                              cancelButtonTitle:@"确定"
                                              otherButtonTitles:nil];
        [alert show];
        return;
    }

    /*
     *生成订单信息及签名
     */
    //将商品信息赋予AlixPayOrder的成员变量
    AlixPayOrder *order = [[AlixPayOrder alloc] init];
    order.partner = partner;
    order.seller = seller;
    order.tradeNO = @"订单ID";             //订单ID(由商家自行制定)
    order.productName = @"商品标题";        //商品标题
    order.productDescription = @"商品描述"; //商品描述
    order.amount = [NSString stringWithFormat:@"%.2f",2.5]; //商品价格
    order.notifyURL =  @"http://www.xxx.com"; //回调URL

    order.service = @"mobile.securitypay.pay";
    order.paymentType = @"1";
    order.inputCharset = @"utf-8";
    order.itBPay = @"30m";
    order.showUrl = @"m.alipay.com";

    //应用注册scheme,在AlixPayDemo-Info.plist定义URL types,用于安全支付成功后重新唤起商户应用
    NSString *appScheme = URLScheme;

    //将商品信息拼接成字符串
    NSString *orderSpec = [order description];
    NSLog(@"orderSpec = %@",orderSpec);

    //获取私钥并将商户信息签名,外部商户可以根据情况存放私钥和签名,只需要遵循RSA签名规范,并将签名字符串base64编码和UrlEncode
    NSString *privateKey = @"私钥";
    id signer = CreateRSADataSigner(privateKey);
    NSLog(@"prikey = %@",privateKey);

    NSString *signedString = [signer signString:orderSpec];
    //将签名成功字符串格式化为订单字符串,请严格按照该格式
    NSString *orderString = nil;
    if (signedString != nil) {
        orderString = [NSString stringWithFormat:@"%@&sign=\"%@\"&sign_type=\"%@\"",
                       orderSpec, signedString, @"RSA"];
        //调用支付宝
        [[AlipaySDK defaultService] payOrder:orderString fromScheme:appScheme callback:^(NSDictionary *resultDic) {
           NSString *resultStatus=resultDic[@"resultStatus"];

           if([resultStatus isEqualToString: @"9000"]){
              [self alert:@"恭喜" msg:@"您已成功支付啦!"];
           }else{
              [self alert:@"提示" msg:@"支付失败,可在待付款订单中查看"];
       }
          [self.navigationController popToRootViewControllerAnimated:YES];
        }];

        /*
        //获取安全支付单例并调用安全支付接口
        AlixPay * alixpay = [AlixPay shared];
        int ret = [alixpay pay:orderString applicationScheme:appScheme];
        if(ret == 9000){
            [self alert:@"恭喜" msg:@"您已成功支付啦!"];
        }else{
            [self alert:@"提示" msg:@"支付失败,可在待付款订单中查看"];
        }
        [self.navigationController popToRootViewControllerAnimated:YES];

        if (ret == kSPErrorAlipayClientNotInstalled) {
            UIAlertView * alertView = [[UIAlertView alloc] initWithTitle:@"提示"
                                                                 message:@"您还没有安装支付宝快捷支付,请先安装。"
                                                                delegate:self
                                                       cancelButtonTitle:@"确定"
                                                       otherButtonTitles:nil];
            [alertView show];
        }
        else if (ret == kSPErrorSignError) {
            NSLog(@"签名错误!");
        }  
    */
    }
}

- (void)alert:(NSString *)title msg:(NSString *)msg
{
    UIAlertView *alter = [[UIAlertView alloc] initWithTitle:title message:msg delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
    [alter show];
}

注:
RSA加密算法,除了可加解密外,还可用来作签名校验。简单的说,RSA会生成一个私钥和一个公钥,私钥应该独自保管,公钥可以分发出去。做签名验证时,可以用私钥对需要传输的数据做签名加密,生成一个签名值,之后分发数据,接收方通过公钥对签名值做校验,如果一致则认为数据无篡改。

支付宝demo(包括ios,android,wp)下载地址:
http://download.csdn.net/download/pearlhuzhu/5736965

解决在iOS9上调用支付宝不可回调的问题以及支付宝的嵌入流程:
http://blog.csdn.net/baby_hua/article/details/51004405

你可能感兴趣的:(iOS开发,iOS开发进阶)