iOS 集成支付宝(AliPay)
引言
移动支付越来越火,每一个应用都开始植入移动支付,比较常用的支付有支付宝、微信、银联等支付方式,今天来讲一下如何集成支付宝,讲的不好之处,请指出,共同探讨进步!
AliPay
版本号:v2.0.1 支付宝钱包支付接口开发包2.0标准版(20160516) 密码: bfj8
跟支付宝签名,商家成为支付宝的“商户”,二级商户:自己支付平台是第一级商户,加入平台的商户成为第二级商户。
流程图
大致支付流程(在服务端进行签名):用户在商户客户端下单 -> 商户客户端会获取用户的地址,收货人信息,商品ID,UID,私钥 -> 发送给商户服务端,商户服务端创建一个订单号,对订单号加密 -> 然后将加密的订单号返回给商户客户端 -> 商户客户端调用支付宝SDK,并传递信息 -> 等待支付宝支付结果,并做友好提示,支付宝服务端接收支付结果。
支付流程
业务流程
设置RSA公钥
1、如果您使用了支付宝移动支付、即时到账产品,请在【合作伙伴密钥管理】模块下添加RSA公钥。
2、如果您使用了支付宝手机网站支付产品,请在【无线产品密钥管理(wap专用)】模块下添加RSA公钥。
3、如果您使用了支付宝当面付产品(包括条码支付、扫码支付、声波支付),请在【开放平台密钥管理】接入应用为当面付的模块下添加RSA公钥
本地生成 RSA 私钥以公钥,私钥保存在本地,将公钥上传至支付宝平台,以下使用 Mac 上自带的 openssl 生成私钥和公钥1
2
3
4OpenSSL> genrsa -out rsa_private_key.pem 1024 #生成私钥
OpenSSL> pkcs8 -topk8 -inform PEM -in rsa_private_key.pem -outform PEM -nocrypt -out rsa_private_key_pkcs8.pem #Java开发者需要将私钥转换成PKCS8格式
OpenSSL> rsa -in rsa_private_key.pem -pubout -out rsa_public_key.pem #生成公钥
OpenSSL> exit #退出OpenSSL程序
Code
集成和配置
关于如何集成和配置不过多的进行介绍,eg:导入包、所需类库和引入头文件等,具体相关配置请参考官方 Demo。
ATS 说明
如果你的app基于9.0编译,那么为了适配iOS9.0中的App Transport Security(ATS)对http的限制,这里需要对支付宝的请求地址alipay.com、alipayobjects.com做例外,在app对应的info.list中添加如下配置(文中以XML格式描述)。
1 | <key>NSAppTransportSecurity</key> |
也可以用下面进行替代:1
2
3
4<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key><true/>
</dict>
配置 Model
1 | Order *order = [[Order alloc] init]; |
AppDelegate
配置支付宝客户端返回url处理方法。(外部存在支付包钱包,支付宝钱包将处理结果通过url返回。)1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23如果从另一个应用进入,将调用此方法。
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation
{
//url 支付宝传过来的结果,支付宝不建议解析url // scheme://safepay/ (scheme 自定义的, safepay 安全支付)
// url.scheme 协议头
// url.host 域名
// sourceApplication 从哪个应用来的
//如果极简开发包不可用,会跳转支付宝钱包进行支付,需要将支付宝钱包的支付结果回传给开发包
if ([url.host isEqualToString:@"safepay"]) {
[[AlipaySDK defaultService] processOrderWithPaymentResult:url standbyCallback:^(NSDictionary *resultDic) {
//【由于在跳转支付宝客户端支付的过程中,商户app在后台很可能被系统kill了,所以pay接口的callback就会失效,请商户对standbyCallback返回的回调结果进行处理,就是在这个方法里面处理跟callback一样的逻辑】
NSLog(@"result = %@",resultDic);
}];
}
if ([url.host isEqualToString:@"platformapi"]){//支付宝钱包快登授权返回authCode
[[AlipaySDK defaultService] processAuthResult:url standbyCallback:^(NSDictionary *resultDic) {
//【由于在跳转支付宝客户端支付的过程中,商户app在后台很可能被系统kill了,所以pay接口的callback就会失效,请商户对standbyCallback返回的回调结果进行处理,就是在这个方法里面处理跟callback一样的逻辑】
NSLog(@"result = %@",resultDic);
}];
}
return YES; //YES 允许调起
}
本地测试
1 | //应用注册scheme,在AlixPayDemo-Info.plist定义URL types |
回调说明
在支付过程结束后,会通过callbackBlock同步返回支付结果。返回结果需要通过resultStatus以及result字段的值来综合判断并确定支付结果。在resultStatus=9000,并且success=“true”以及sign=“xxx”校验通过的情况下,证明支付成功。其它情况归为失败。较低安全级别的场合,也可以只通过检查resultStatus以及success=“true”来判定支付结果。以下为订单支付成功的完成信息示例:1
2
3
4
5{
memo = "";
result = "partner=\"2088101568358171\"&seller_id=\"[email protected]\"&out_trade_no=\"0819145412-6177\"&subject=\"测试\"&body=\"测试测试\"&total_fee=\"0.01\"¬ify_url=\"http://notify.msp.hk/notify.htm\"&service=\"mobile.securitypay.pay\"&payment_type=\"1\"&_input_charset=\"utf-8\"&it_b_pay=\"30m\"&success=\"true\"&sign_type=\"RSA\"&sign=\"hkFZr+zE9499nuqDNLZEF7W75RFFPsly876QuRSeN8WMaUgcdR00IKy5ZyBJ4eldhoJ/2zghqrD4E2G2mNjs3aE+HCLiBXrPDNdLKCZgSOIqmv46TfPTEqopYfhs+o5fZzXxt34fwdrzN4mX6S13cr3UwmEV4L3Ffir/02RBVtU=\"";
resultStatus = "9000";
}
客户端验签
一般可以在服务器端进行验签,将支付宝返回的字段上传到服务器即可,服务器端进行判断。
1 | //验签 |
解析结果
支付结果的提取,必须通过CompletionBlock获取,禁止开发者私自解析支付结果返回的URL。获取值的Key对应resultStatus、memo与result(result中的值,开发者可以自行解析);
为了保障已有商户的正常使用,返回参数ResultStatus首字母为大写。在新的SDK中已经用统一的工具类实现了ResultStatus到resultStatus的转换,商户从CompletionBlock中获取resultStatus即可。1
2
3
4
5
6
7
8
9
10
11
12
13
14if ([resultDic[@"resultStatus"] isEqualToString:@"9000"]) {
NSString * resultStr = resultDic[@"result"];
NSRange signRange = [resultStr rangeOfString:@"&sign=\""];
NSString * sign = [resultStr substringWithRange:NSMakeRange(signRange.location + signRange.length, [resultStr length] - signRange.location - signRange.length - 1)];
NSLog(@"%@", sign);
NSRange successRange = [resultStr rangeOfString:@"&success=\""];
NSString * daiqianming = [resultStr substringToIndex:successRange.location];
NSLog(@"%@", daiqianming);
NSString * status = [resultStr substringWithRange:NSMakeRange(successRange.location + successRange.length, 1)];
if ([status isEqualToString:@"t"]) {
NSLog(@"HT 支付宝测试成功");
}
}
FQA
0、如何找到 AliPay SDK,大致方法如下:
文档中心 -> 资源下载 -> 开发工具包下载 -> 移动支付DEMO&SDK
1、如何在支付宝平台设置 RSA 公钥钥
商家服务 -> 我的商家服务 -> 查询PID、Key
参考资料
1、导入代码
2、手动集成问题解决
3、支付宝支付生成与配置RSA密钥
4、查看RSA商户公钥与支付宝公钥
5、关于iOS开发支付宝集成,客户端签名与验证
6、PING++ 开发者中心
7、BeeCloud