项目中要用到支付功能,需要支付宝,微信,银联三大支付,所以打算总结一下,写两篇文章,方便以后的查阅, 大家在做的时候也能稍微参考下,用到的地方避免再次被坑。这是第二篇支付宝集成,第一篇银联支付在这里。本来要用那个ping++的神器,可以集成各种支付手段,异常的方便,但是考虑到安全性问题的话,支付的渠道还是不让第三方参与的好,不然会不安全,于是就苦逼地慢慢的一个一个集成了。。。。这里就代理支付宝的集成过程:
刚开始以为支付宝集成还是比较简单的,看了几个文章,网上的各位大神也是各种秀操作,说集成很简单,但是,真正做起来就不是那回事了, 特别是新版的1月11号更新的,我正好是这一天开始看的,网上的经验什么的 大都是比较老的,比较新的能用到的文章不多(但是好文章还是有的,对我帮助也很大),现在我就来一步一步说一下自己集成支付宝的血泪史!
下载支付宝SDK
首先是开发包下载,还是比较难发现的,网上以前文章中的链接都打不开,我找了好久才找到的。最新的地址在这里(注意的是下载出来的SDK包里面并没有传说中的开发文档,需要其他地方找或者看网页上的)。
公钥、私钥、PID、sellerID、key这些东西的用途和获取方式在文档上都有详细的说明,这里不再赘述,一定要把概念分清楚再去做,不然一会就乱了。如果遇到问题的话咱们可以再一起探讨。
支付流程理解
开发文档、开发文档、开发文档,重要的事情一定要说三遍!!!建议先把开发文档仔仔细细看一遍,一定要看,本小白刚开始的时候没有老老实实地看完,结果遇到很多很多的坑,以血和泪劝解大家,浪费的挺多的时间的,所以建议一定要好好看看,特别是交互流程这一部分
流程就是跟咱们平时在手机上买东西是一样的:
1.用户选好了商品后,点击提交订单(一般是这样),选择使用支付宝付款。
2.手机客户端(你做的APP)把用户选择的商品的信息传给你们后台服务器。
3.后台的服务器将各种数据拼接签名后生成一个签名后的字符串,回传到客户端APP上。
4.用户点击确认支付按钮,调用手机支付宝客户端(在你手机上装的那个),利用后台传过来的那个参数调起支付宝,让支付宝客户端传给他们服务器交互,进行付款。(这一步是支付宝自己完成的,安全性高)
5.支付宝的服务器将支付的结果(可能成功也可能不成功)返回给手机支付宝客户端和你们公司的后台服务器。
6.你们公司后台服务器收到后一般是更新下数据信息(这个咱们不用管),手机支付宝客户端会显示一下支付成功,咱们的客户端也可以显示一个订单支付成功之类的东西(就像在手机12306订票,用支付宝支付后支付宝客户端会说一次支付成功,12306也会说一次支付成功,咱们就像12306客户端一样,需要再说一次订单支付成功)。
到这里就完成了支付的过程了。我觉得这个流程还是很容易理解的。
其中咱们就是商户客户端需要做的就是:
• 调用支付宝支付接口
• 处理支付宝返回的支付结果
支付宝文档上的应用范例:
ps:签名部分为了安全起见都放在了后台,如果你们执意要在手机客户端做签名,不怕被拦截那就再加上一步签名。也才三步,还是很简单。
调用支付接口
在调用支付宝支付接口前,我们需要先生成一个订单,文档中描述时,是将这步也放在客户端来做了,但这个最好是 放在服务器端来做,后台生成订单然后拼接,签名,然后服务器端直接给客户端传一个加密签名过的参数就可以了,这样比较安全,官方demo上放在客户端生成订单并且签名是因为没有服务给你用啊,所以就客户端上生成了~~~。
我做的时候,为了安全,生成订单,拼接字符串,签名,都是在服务器上做的,所有的订单信息,商户信息等都掌握在自己的手中,这样的话APP端就不怕被拦截数据,并且调用起来也就特别简单了,只需要调用支付的接口,打开支付宝APP客户端进行支付就行了,没有用户的手机上没有安装支付宝客户端的话会调用网页来支付,也是一样的。
如果只需要发送订单和处理支付返回结果,只需要添加AlipaySDK.bundle和AlipaySDK.framework这两个就行了,下载的SDK中很容易发现。
快捷支付方法是这个:
-(void)payOrder:(NSString *)orderStr fromScheme:(NSString *)schemeStr callback:(CompletionBlock)completionBlock;
在支付的按钮中,试用支付宝这个类,再调用这个方法就行啦!如下如:
在调用支付宝接口的时候,我们需要两个参数,orderString
和APPScheme
, APPScheme是app在info.plist注册的scheme。
orderstring 这个是一个订单的字符串,由后台拼接生成的,还需要签名的。例如:
partner="2088101568358171"&seller_id="xxx@alipay.com"&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_bpay="30m"&sign="lBBK%2F0w5LOajrMrji7DUgEqNjIhQbidR13GovA5r3TgIbNqv231yC1NksLdw%2Ba3JnfHXoXuet6XNNHtn7VE%2BeCoRO1O%2BR1KugLrQEZMtG5jmJIe2pbjm%2F3kb%2FuGkpG%2BwYQYI51%2BhA3YBbvZHVQBYveBqK%2Bh8mUyb7GM1HxWs9k4%3D"&sign_type="RSA".
流程就这么简单,接下来是集成SDK的时间,这部分很坑,因为是我们是商品的数据签名什么的都在后台做的,所以客户端做的时候遇到的坑就不多说了,可以参考这篇文章,基本上遇到的坑都能找到。
还有这篇是有人对这个进行的一个简单的封装,如果签名,数据部分需要在APP上做的话,可以直接用这个,封装很简单,也是加了个类目进行做出来的,实现很简单。大家可以参考一下。
支付宝的SDK给了一个处理返回结果的方法,就是那个openURL的那个,在demo的appdelegate里面有。
if ([url.host isEqualToString:@"safepay"]) {
[[AlipaySDK defaultService] processOrderWithPaymentResult:url
standbyCallback:^(NSDictionary *resultDic) {
NSLog(@"result = %@",resultDic);
}];
}
关于签名(主要是在客户端签名时候注意的)
支付宝上要用那个RSA,这是个算法,所以为了方便,可以使用第三方的方法,或者找demo上的代码粘贴上去!不过还是那句话,为了安全,最好还是后台的做,不怕被拦截了 。
签名的时候,涉及到了RSA公钥、私钥的生产,RSA的签名、验证签名,SHA1值的计算,base64和URL编码等等等等烦人的东西,估计支付的程序猿也不想麻烦,就用了一个开源的代码来统一解决这些问题,就是openssl这个文件夹。
如果你执意要在客户端上签名(前面说过,并不安全),也可以用demo中的openssl这个文件夹,那你需要导入这几个文件夹:DEMO中的openssl目录头文件,两个库文件libcrypto.a libssl.a,DEMO里支付宝自己写的Util目录,如下图:
支付宝文档上的集成流程详解,写的很详细了,一般遇到的问题都有提到。
推荐几篇好文章,可以参考下,减少点坑(1、4、5务必看看,很有启发的):
1.集成支付宝钱包支付iOS SDK的方法与经验
2.IOS集成到支付宝的步骤及问题
3.这个也是遇到的一些问题和解决方法
4.iOS应用之支付宝集成总结
5.iOS 集成支付宝
这篇文章是在客户端做签名的,写的也很详细
今天又遇到个问题:调起了支付宝客户端,但是支付不了。
这个是因为,如果订单来自服务器此错误表示后台返回的签名订单含有特殊字符 ,需要编码。
由于RSA签名机制每次生成的签名都不一样,也就是是二进制数,后台返回签名的订单时,是基于base64位编码的 。可能基于base64位编码生成带有+=/等在url序列中不被允许的字符。当我们拿着后台不进行特殊字符处理的订单作为参数去调用支付宝的接口时,便会出现由于支付宝客户端吊起支付宝服务器是URL有问题,导致错误ALI64 。
解决办法是 让后台处理一下参数中的特殊字符,具体的这里有示例.