IOS开发支付宝集成

字数 1262阅读 7657

开发准备


1.首先新建项目,然后去官网下载最新的开发包:
http://doc.open.alipay.com/doc2/detail?treeId=59&articleId=103563&docType=1,
当然也可以用CocoaPods来下载不过用这个下载的话只会下载到单纯的客户端与网络服务请求的SDK不包含加密的那些代码,而有些公司是要把加密做到本地的所以选择哪种方式看开发者的习惯于公司需求.
2.下载后打开点击开发包可以打开更新日志来比对当前版本不要去一些非官网的地方下载SDK有可能不是最新版本会出现BUG
3.打开客户端开发包找到IOS对应的包文件解压得到开发包,包含1个framework文件一个bundle文件一个Demo文件夹

一般情况下支付功能的交互流程


比如我们去某个APP去支付一个产品,流程为:
1.用户点击支付->
2.客户端请求服务器用户支付->
3.服务器接收请求生成金额订单等要给第三方支付的一切信息,并生成回调参数传给客户端->
4.客户端接收信息(一般会再让用户确认支付或者干脆购买后是生成订单,然后才是付款)并将服务器给的信息分别传入SDK需要的参数中,调用SDK的支付方法->
5.由SDK向SDK自己的服务器发出支付请求,SDK自己的服务器接收支付请求处理成功后,给客户端本身与公司的后台都发送一条支付成功的消息,客户端与后台根据这条消息再做处理.

针对开发环境的一些设置


支付又分为2种情况本地签名,和服务器签名,我用到正好都是公司要求本地签,服务器的我就稍微说1点.

服务器签名:
/**
 *  支付接口
 *
 *  @param orderStr       订单信息
 *  @param schemeStr      调用支付的app注册在info.plist中的scheme
 *  @param compltionBlock 支付结果回调Block
 */
- (void)payOrder:(NSString *)orderStr
      fromScheme:(NSString *)schemeStr
        callback:(CompletionBlock)completionBlock;

服务器签名注意的是在callback:回调中要进行验签,就是把服务器给的订单签名信息在用公钥解密,比对订单细节,检查是否被他人篡改,并且如果是wap支付,不会反回在appDelegateapplication:openURL方法.

本地签名:

先拖入实现加密的文件与模型:

加密的文件.png

这时候会报错(补充一点: 有些朋友找不到NSString或者一些数据类型报错都是因为缺少Foundation头文件,可能我写的不太明白,有些朋友还是不太懂)大部分错误都是因为一些文件中在支付宝的Demo的Pch文件中统一添加的#import <Foundation/Foundation.h>,如果我们的项目中没有这一步,那么要么也建立pch要么单独添加上.

这时还会有一个错误:

路径找不到.png

注意这里的Header Search Paths 路径为空:

路径为空.png

打开电脑这个文件的所在地 双击Header Search Paths将电脑的文件拖入Header Search Paths会生成一个路径:

生成的路径.png

导入一来框架: 这个最好跟着Demo一个一个往里添加,也不要光看网上资料主要还是看Demo:

导入框架.png

添加SDK和静态库:


SDK静态库.png

报错:这个错误与另外一种说SDK不支持64位比较常见,都是把静态库或者SDK都删了重新导入就行了


错误信息.png
到这里应该已经可以运行程序了.
如果还是出现了编译错误等问题,导入框架不全与SDK静态库的路径错误比例比较大.
建议等能够运行程序后在进行开发.

正式开发

首先我们介绍一段代码:

  NSString *orderSpec = [order description];

将商品的信息添加为字符串order是一个对象,而description]是将这个对象的属性进行拼接返回一个字符串.

在介绍3个属性:

//合作商户ID。用签约支付宝账号登录ms.alipay.com后,在账户信息页面获取。
NSString *partner = @"";
//账户ID。用签约支付宝账号登录ms.alipay.com后,在账户信息页面获取。
NSString *seller = @"";
//商户私钥,自助生成
NSString *privateKey = @"";

这3个属性必须是个人或公司申请后才能得到的..我用的公司的就不写上了请自行填写.

//将商品信息赋予AlixPayOrder的成员变量
    Order *order = [[Order alloc] init];
    order.partner = partner;
    order.seller = seller;
    order.tradeNO = @"G111111111111"; //订单ID(由商家自行制定)
    order.productName = @"我的测试"; //商品标题
    order.productDescription = @"我的商品描述"; //商品描述
    order.amount = @"0.01"; //商品价格
    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 = @"alisdkdemo";
    
    //将商品信息拼接成字符串
    NSString *orderSpec = [order description];
    NSLog(@"orderSpec = %@",orderSpec);
    
    //获取私钥并将商户信息签名,外部商户可以根据情况存放私钥和签名,只需要遵循RSA签名规范,并将签名字符串base64编码和UrlEncode
    id<DataSigner> signer = CreateRSADataSigner(privateKey);
    NSString *signedString = [signer signString:orderSpec];
    
    
    NSString *orderString = nil;

生成加密后的字符串 注意的是NSString *appScheme = @"alisdkdemo";这个值是从支付宝的商户地址中填写的,请保持一致.

最后处理结果:

if (signedString != nil) {
        orderString = [NSString stringWithFormat:@"%@&sign=\"%@\"&sign_type=\"%@\"",
                       orderSpec, signedString, @"RSA"];
        
        [[AlipaySDK defaultService] payOrder:orderString fromScheme:appScheme callback:^(NSDictionary *resultDic) {
            
            //结果处理,其实就是取字典里面的内容,这个取字符串然后变个模型就好了 或者直接取不便模型,方法很多.
            NSLog(@"开始确认支付状态 %@",resultDic[@"resultStatus"]);
            AlixPayResult* resultModel = [AlixPayResult itemWithDictory:resultDic];
            if (resultModel)
            {
                //状态返回9000为成功
                if (resultModel.statusCode == 9000)
                {
                    /*
                     *用公钥验证签名 严格验证请使用result.resultString与result.signString验签
                     */
                    NSLog(@"支付宝交易成功");
                    
                    /*
                     *用公钥验证签名 严格验证请使用result.resultString与result.signString验签
                     */
                    
                    //交易成功
                    NSString* key = AlipayPubKey;//签约帐户后获取到的支付宝公钥
                    id<DataVerifier> verifier;
                    verifier = CreateRSADataVerifier(key);
                    
                    // 验证签名
                    if ([verifier verifyString:resultModel.resultString withSign:resultModel.signString])
                    {
                        //验证签名成功,交易结果无篡改
                        NSLog(@"验证成功");
                    }
                }
            }
            else if([resultDic[@"resultStatus"]isEqualToString:@"6001"])
            {
                               //用户取消
                NSLog(@"用户主动取消支付");
            }else
            {
               
            }
        }];
}

这里注意:if([resultDic[@"resultStatus"]isEqualToString:@"6001"])支付宝有BUG 这个6001 不要信,可以和公司商量下,是加个确认接口还是一定时间内检查后台,总之很有可能用户付钱成功,SDK通知你用户手动取消,这个BUG是在弱网状态下比较多.

然后记得在 AppDelegate里面加上如下代码:

//只要是调用手机上的支付宝客户端,在支付宝客户端操作完成返回自己的app时,都会调用这个方法,
- (BOOL)application:(UIApplication *)application
            openURL:(NSURL *)url
  sourceApplication:(NSString *)sourceApplication
         annotation:(id)annotation {
    //跳转支付宝钱包进行支付,需要将支付宝钱包的支付结果回传给SDK(这个是将支付宝客户端的支付结果传回给SDK)
    if ([url.host isEqualToString:@"safepay"]) {
        [[AlipaySDK defaultService]
         processOrderWithPaymentResult:url
         standbyCallback:^(NSDictionary *resultDic)
         {
             NSLog(@" ------result = %@",resultDic);//返回的支付结果
         }];
    }
    return YES;
}

最后记得把这里写了:

URL.Types.png

NSString *appScheme = @"alisdkdemo"代码 网页上申请的 图片上那里填写的保持一致.


补充: 如果要用swift来调用支付宝SDK 最好把支付的与回调的逻辑单独建立工具类传递数据便好,从流程上本身无太大区别稍微注意的是在swiftAlipaySDK.h有可能因为语言环境问题出现缺少引入类的情况,少什么补什么就好,其他也一样.

如有问题欢迎留言...

推荐阅读更多精彩内容