iOS支付宝支付集成

支付宝和微信都是业界的老大哥,相信大家都有所觉得文档、SDK都是各种坑吧(纯粹吐槽而已),本文先整理支付宝支付集成。

一、准备工作

1、向支付宝”签约" 成为支付宝的”商户”, 签约完成后, 支付宝会提供一些必要的数据给我们(商户ID-partner,帐号ID-支付宝帐号)

注意:签约成为支付宝商户,需要提供公司营业执照[http://act.life.alipay.com/shopping/before/help/index.html](http://act.life.alipay.com/shopping/before/help/index.html)

2、获取支付相关的 '私钥' 和 '密钥'

[https://doc.open.alipay.com/doc2/detail?treeId=44&articleId=103242&docType=1](https://doc.open.alipay.com/doc2/detail?treeId=44&articleId=103242&docType=1)

3、下载支付的SDK

[https://doc.open.alipay.com/doc2/detail?treeId=54&articleId=103419&docType=1](https://doc.open.alipay.com/doc2/detail?treeId=54&articleId=103419&docType=1)

二、集成支付宝SDK步骤

1、从官方Demo中把红色标注的文件添加进入项目中,记得选copy;

iOS支付宝支付集成_第1张图片


2、

点击项目名称,点击“Build Phases”选项卡,在“Link Binary with Librarles” 选项中,新增“AlipaySDK.framework”和“SystemConfiguration.framework” 两个系统库文件。如果项目中已有这两个库文件,可不必再增加;

添加下图中的库:

iOS支付宝支付集成_第2张图片

1
2
3
4
5
6
7
localhost:alipay mac$ ls
APAuthV2Info.h        Order.h            libssl.a
APAuthV2Info.m        Order.m            openssl
AlipaySDK.bundle    Util
AlipaySDK.framework    libcrypto.a
导入系统库
SystemConfiguration.framework


3、

添加Pch文件新建pch成功后,在pch文件中添加#import然后按照下图所示,进行修改pch的文件路径

也可以不设置,我这个是我需要设置#import #import ,也可以不用使用,只在当前文件里添加相对应的使用即可,但是这样针对整个项目来说方便些

iOS支付宝支付集成_第3张图片


4、

修改SDK路径完成以上两步之后,会发现出现了一个经典的错误,找不到:#include解决这个问题,需要在Header Search Path中配置SDK中的点a(libssl.a/libcrypto.a)文件所在的路径,找到之后设置好正确的路径

iOS支付宝支付集成_第4张图片

点击项目名称,点击“Build Settings”选项卡,在搜索框中,以关键字“search” 搜索,对“Header Search Paths”增加头文件路径:“$(SRCROOT)/项目名称/IntegratedAlipay/AlipayFiles”(注意:不包括引号,如果不是放到项目根目录下,请在项目名称后面加上相应的目录名);

iOS支付宝支付集成_第5张图片

根据你文件位置,我的是:

“$(SRCROOT)/QTXStudent/Classes/Alipay/AlipayFiles”


5、 为URL Types 添加支付宝回调scheme

 点击项目名称,点击“Info”选项卡,在URL types里面添加一项,Identifier可以不填,URL schemes必须和appScheme的值相同,用于支付宝处理回到应用的事件;

 为URL Types 添加支付宝回调scheme

iOS支付宝支付集成_第6张图片


6、在工程项目的plist文件中添加

 iOS 9以后的系统需要添加支付宝分享的scheme到白名单中,scheme名为alipayshare

按如下形式添加即可:

iOS支付宝支付集成_第7张图片


7、在AppDelegate中处理事件回调:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
/**
  这里处理微信/支付宝支付完成之后跳转回来
  */
- ( 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);
             if  (resultDic && [resultDic objectForKey:@ "resultStatus" ] && ([[resultDic objectForKey:@ "resultStatus" ] intValue] == 9000)) {
                 
                 // 发通知带出支付成功结果
                 [[NSNotificationCenter defaultCenter] postNotificationName:ZLAliReturnSucceedPayNotification object:resultDic];
             else  {
                 
                 // 发通知带出支付失败结果
                 [[NSNotificationCenter defaultCenter] postNotificationName:ZLAliReturnFailedPayNotification object:resultDic];
             }
             
         }];
     }
     
     if  ([url.host isEqualToString:@ "platformapi" ]){ //支付宝钱包快登授权返回 authCode
         [[AlipaySDK defaultService] processAuthResult:url standbyCallback:^(NSDictionary *resultDic) {
             NSLog(@ "支付宝网页版result = %@" ,resultDic);
             if  (resultDic && [resultDic objectForKey:@ "resultStatus" ] && ([[resultDic objectForKey:@ "resultStatus" ] intValue] == 9000)) {
                 
                 // 发通知带出支付成功结果
                 [[NSNotificationCenter defaultCenter] postNotificationName:ZLAliReturnSucceedPayNotification object:resultDic];
             else  {
                 
                 // 发通知带出支付失败结果
                 [[NSNotificationCenter defaultCenter] postNotificationName:ZLAliReturnFailedPayNotification object:resultDic];
             }
         }];
     }
     
     return  YES;
}
 
// NOTE: 9.0以后使用新API接口
- ( BOOL )application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary *)options
{
     
     //如果极简 SDK 不可用,会跳转支付宝钱包进行支付,需要将支付宝钱包的支付结果回传给 SDK
     if  ([url.host isEqualToString:@ "safepay" ]) {
         //跳转支付宝钱包进行支付,处理支付结果
         [[AlipaySDK defaultService] processOrderWithPaymentResult:url standbyCallback:^(NSDictionary *resultDic) {
             NSLog(@ "支付宝客户端支付结果result = %@" ,resultDic);
             if  (resultDic && [resultDic objectForKey:@ "resultStatus" ] && ([[resultDic objectForKey:@ "resultStatus" ] intValue] == 9000)) {
                 
                 // 发通知带出支付成功结果
                 [[NSNotificationCenter defaultCenter] postNotificationName:ZLAliReturnSucceedPayNotification object:resultDic];
             else  {
                 
                 // 发通知带出支付失败结果
                 [[NSNotificationCenter defaultCenter] postNotificationName:ZLAliReturnFailedPayNotification object:resultDic];
             }
         }];
     }
     
     if  ([url.host isEqualToString:@ "platformapi" ]){ //支付宝钱包快登授权返回 authCode
         [[AlipaySDK defaultService] processAuthResult:url standbyCallback:^(NSDictionary *resultDic) {
             NSLog(@ "支付宝网页版result = %@" ,resultDic);
             if  (resultDic && [resultDic objectForKey:@ "resultStatus" ] && ([[resultDic objectForKey:@ "resultStatus" ] intValue] == 9000)) {
                 
                 // 发通知带出支付成功结果
                 [[NSNotificationCenter defaultCenter] postNotificationName:ZLAliReturnSucceedPayNotification object:resultDic];
             else  {
                 
                 // 发通知带出支付失败结果
                 [[NSNotificationCenter defaultCenter] postNotificationName:ZLAliReturnFailedPayNotification object:resultDic];
             }
         }];
     }
     
     return  YES;
}


8、 在需要用的地方导入“AlipayHeader.h”,并使用“[AlipayRequestConfig alipayWithPartner:...”方法进行支付;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/**
  *  配置请求信息,仅有变化且必要的参数
  *
  *  @param partner            合作者身份ID 以 2088 开头由 16 位纯数字组成的字符串。
  *  @param sellerID           卖家支付宝账号 以 2088 开头由 16 位纯数字组成的字符串。
  *  @param outTradeNO         商户网站唯一订单号
  *  @param subject            商品名称
  *  @param body               商品详情
  *  @param totalFee           总金额
  *  @param notifyURL          服务器异步通知页面路径
  *  @param itBPay             未付款交易的超时时间
  */
+ ( void )alipayWithPartner:(NSString *)partner
                  sellerID:(NSString *)sellerID
                outTradeNO:(NSString *)outTradeNO
                   subject:(NSString *)subject
                      body:(NSString *)body
                  totalFee:(NSString *)totalFee
                 notifyURL:(NSString *)notifyURL;

仅含有变化的参数:

1
2
3
4
5
6
7
8
9
10
11
+ ( void )alipayWithPartner:(NSString *)partner
                  sellerID:(NSString *)sellerID
                outTradeNO:(NSString *)outTradeNO
                   subject:(NSString *)subject
                      body:(NSString *)body
                  totalFee:(NSString *)totalFee
                 notifyURL:(NSString *)notifyURL {
     
     [self alipayWithPartner:partner sellerID:sellerID outTradeNO:outTradeNO subject:subject body:body totalFee:totalFee notifyURL:aliNotifyURL service:@ "mobile.securitypay.pay"  paymentType:@ "1"  inputCharset:@ "utf-8"  itBPay:@ "30m"  privateKey:aliPrivateKey appScheme:aliAppScheme];
     
}

包含所有必要的参数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
+ ( void )alipayWithPartner:(NSString *)partner
                  sellerID:(NSString *)sellerID
                   outTradeNO:(NSString *)outTradeNO
                   subject:(NSString *)subject
                      body:(NSString *)body
                  totalFee:(NSString *)totalFee
                 notifyURL:(NSString *)notifyURL
                   service:(NSString *)service
               paymentType:(NSString *)paymentType
              inputCharset:(NSString *)inputCharset
                    itBPay:(NSString *)itBPay
                privateKey:(NSString *)privateKey
                 appScheme:(NSString *)appScheme {
     
     Order *order = [Order order];
     order.partner = partner;
     order.sellerID = sellerID;
     order.outTradeNO = outTradeNO;
     order.subject = subject;
     order.body = body;
     order.totalFee = totalFee;
     order.notifyURL = notifyURL;
     order.service = service;
     order.paymentType = paymentType;
     order.inputCharset = inputCharset;
     order.itBPay = itBPay;
     
     
     // 将商品信息拼接成字符串
     NSString *orderSpec = [order description];
     
     // 获取私钥并将商户信息签名,外部商户可以根据情况存放私钥和签名,只需要遵循 RSA 签名规范, 并将签名字符串 base64 编码和 UrlEncode
     
     NSString *signedString = [self genSignedStringWithPrivateKey:aliPrivateKey OrderSpec:orderSpec];
     
     // 调用支付接口
     [self payWithAppScheme:appScheme orderSpec:orderSpec signedString:signedString];
}

生成signedString:

1
2
3
4
5
6
+ (NSString *)genSignedStringWithPrivateKey:(NSString *)privateKey OrderSpec:(NSString *)orderSpec {
     
     // 获取私钥并将商户信息签名,外部商户可以根据情况存放私钥和签名,只需要遵循 RSA 签名规范, 并将签名字符串 base64 编码和 UrlEncode
     id signer = CreateRSADataSigner(privateKey);
     return  [signer signString:orderSpec];
}

支付:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
+ ( void )payWithAppScheme:(NSString *)appScheme orderSpec:(NSString *)orderSpec signedString:(NSString *)signedString {
     
     // 将签名成功字符串格式化为订单字符串,请严格按照该格式
     NSString *orderString = nil;
     if  (signedString != nil) {
         orderString = [NSString stringWithFormat:@ "%@&sign=\"%@\"&sign_type=\"%@\"" , orderSpec, signedString, @ "RSA" ];
         [[AlipaySDK defaultService] payOrder:orderString fromScheme:appScheme callback:^(NSDictionary *resultDic) {  // 网页版
             NSLog(@ "支付宝支付结果 reslut = %@" , resultDic);
             
             // 返回结果需要通过 resultStatus 以及 result 字段的值来综合判断并确定支付结果。 在 resultStatus=9000,并且 success="true"以及 sign="xxx"校验通过的情况下,证明支付成功。其它情况归为失败。较低安全级别的场合,也可以只通过检查 resultStatus 以及 success="true"来判定支付结果
             
             if  (resultDic && [resultDic objectForKey:@ "resultStatus" ] && ([[resultDic objectForKey:@ "resultStatus" ] intValue] == 9000)) {
                 
                 // 发通知带出支付成功结果
                 [ZLNotificationCenter postNotificationName:QTXAliReturnSucceedPayNotification object:resultDic];
             else  {
                 
                 // 发通知带出支付失败结果
                 [ZLNotificationCenter postNotificationName:QTXAliReturnFailedPayNotification object:resultDic];
             }
         }];
     }
     
}


9、

在本头文件中设置aliPartnerID、aliSellerAccount、aliNotifyURL、aliAppScheme和aliPrivateKey的值(所有的值在支付宝回复的邮件里面:注意,建议除appScheme以外的字段都从服务器请求);

这时候,我们支付就直接一句话搞定:

1
2
3
4
5
     // 支付宝支付
     [AlipayRequestConfig alipayWithPartner:aliPartnerID sellerID:aliSellerAccount outTradeNO:[self generateTradeNO] subject:@ "测试"  body:@ "支付宝支付"  totalFee:@ "0.01"  notifyURL:aliNotifyURL];  // notifyURL: 回调url@"http://www.xxx.com"
     
     [ZLNotificationCenter addObserver:self selector:@selector(paySucceed) name:ZLAliReturnSucceedPayNotification object:nil];
     [ZLNotificationCenter addObserver:self selector:@selector(payFailed) name:ZLAliReturnFailedPayNotification object:nil];


10、建议除appScheme以外的字段都从服务器请求!

建议除appScheme以外的字段都从服务器请求!建议除appScheme以外的字段都从服务器请求!

PS:重要的事情说三遍!!!

上面的第七步和第八步建议不要使用,直接用第九步去替代!建议除appScheme以外的字段都从服务器请求!


如果后台给你一个接口返回那些参数了,你就不用客户端去加密算法,只负责请求后台拿到这些参数再去请求支付宝即可.

下面例子是支付宝的拼接方式,请按照当前版本的相对应的拼接方式来.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
// 支付宝支付
- ( void )alipayPay {
     
     NSMutableDictionary *params = [NSMutableDictionary dictionary];
     params[@ "orderNo" ] = self.orderNo;  // 订单号
     params[@ "realAmt" ] =  [NSString stringWithFormat:@ "%.2lf" , self.realAmt];  // 金额
     
     __weak __typeof(self) weakSelf = self;
     [QTXHttpTool post:QTX_aliPay_url params:params success:^(id json) {
         QTXLog(@ "支付宝支付返回参数接口 请求成功-%@" , json);
         
         if  ([json[@ "success" ] isEqual:@(YES)]) {
             
             // 返回生成订单信息及签名
             NSString *signedString = json[@ "data" ][@ "sign" ];
             NSString *orderInfoEncoded = json[@ "data" ][@ "orderInfo" ];
             
             // NOTE: 如果加签成功,则继续执行支付
             if  (signedString != nil) {
                 // NOTE: 将签名成功字符串格式化为订单字符串,请严格按照该格式
//                NSString *orderString = [NSString stringWithFormat:@"%@&sign=%@&sign_type=RSA", orderInfoEncoded, signedString];
                 NSString *orderString = [NSString stringWithFormat:@ "%@&sign=\"%@\"&sign_type=\"%@\"" ,
                                orderInfoEncoded, signedString, @ "RSA" ];
                 
                 // NOTE: 调用支付结果开始支付
                 [[AlipaySDK defaultService] payOrder:orderString fromScheme:XHHAppScheme callback:^(NSDictionary *resultDic) {
                    QTXLog(@ "reslut = %@" ,resultDic);
                     
                     if  ([resultDic[@ "resultStatus" ] intValue] == 9000) {
                         
                         [QTXNotificationCenter addObserver:self selector:@selector(paySucceed) name:QTXWXReturnSucceedPayNotification object:nil];
                     else  {
                         
                         [QTXNotificationCenter addObserver:self selector:@selector(payFailed) name:QTXWXReturnFailedPayNotification object:nil];
                     }
                 }];
                 
             }
             
         else  {
             [MBProgressHUD showError:[NSString stringWithFormat:@ "%@" , json[@ "errorMessage" ]]];
         }
         
     } failure:^(NSError *error) {
         
         [MBProgressHUD showError:@ "暂无网络,稍后再试" ];
         QTXLog(@ "支付宝支付返回参数接口 请求失败-%@" , error);
     }];
     
}


11、支付宝集成失败相关问题

1. 报错 AL159 

查看金额是否是两位小数,切不可拼接"元"

2. 报错“创建交易异常,请重新创建后再付款”

   返回的状态码是“6001”,取消支付

当是用公司注册支付宝App时分配的商户账号登陆的支付宝,进行支付测试的。支付宝那边检测到是商户而不是普通的支付账号,商户支付给商户自己,所以支付失败!

三、其他补充

1、压缩文件截图

iOS支付宝支付集成_第8张图片

2、Alipay 包截图

iOS支付宝支付集成_第9张图片


目前是项目中直接操作, 在AlipayHeader.h文件里补充上你们项目的aliPartnerID, aliSellerAccount, aliNotifyURL, 具体可参考代码, 项目则能够直接运行!

如需看详情版,请到这里下载!

你可能感兴趣的:(iOS支付宝支付集成)