ios集成支付宝支付2016.8
1.签约与审核
签约:和支付宝签约,登记商家的信息,然后支付宝会给商家凭据,PID和key。
签约审核很快的,一般一天内就搞定了。
2.PID和密钥管理
PID:合作者身份id,就像你的身份证号码一样,唯一的。
key:密钥,支付宝提供商户接口产品时,会自主提供一个保障商户接入安全的一组信息及其对应的配置平台,这组信息就是密钥。由商户密钥与支付宝密钥交换后与支付宝商户标识(如partnerID、APPID等)绑定。
合作伙伴密钥
在服务市场签约获得的大部分接口,签约主体是商户,接口权限属于具体的商户,这部分接口需要使用PID和密钥来调用,此类接口网关一般为mapi(https://mapi.alipay.com/gateway.do),PID对应的密钥一共有三种签名方式,分别是MD5、RSA、DSA。由于产品的特殊性,每个产品支持哪些签名方式不尽相同,具体需参考各个产品的接口技术文档。
使用合作伙伴密钥的典型功能包括:
快捷登录、移动支付、即时到账收款、手机网站支付等。
补充:公钥和私钥是成对的,它们互相解密。
公钥加密,私钥解密。
私钥数字签名,公钥验证。
如何生成相应的公钥私钥文件(加密签名用)?
Mac下生成很方便,终端切换都某个目录,输入openssl,就可以打开openssl工具来生成。接着只要二句命令就可以搞定。
1、生成私钥pem, 执行命令 openssl genrsa -out rsa_private_key.pem 1024
23F95D24-F951-4FE1-9A5F-22BACAAD0649.png2、生成公钥,执行命令 openssl rsa -in rsa_private_key.pem -pubout -out rsa_public_key.pem
该目录下就会生成两个文件,可以用文本编辑器打开就可以查看字符串了。
F028F40D-DC0A-4CA1-BB73-4E036D9E3BAE.png公钥字符串需要复制粘贴到支付宝后台
AC1AFD65-3619-4C5D-B3D1-3EC9E100F24F.png各个RSA都添加一遍,暂时不知道各个业务的具体区别。暂时不提。
3.接口调用
首先下载支付宝的SDK,集成到你的工程中,编译成功后,就可以开始编写代码,进行
接口调用了。具体代码参考本文第5部分工程代码!
4.遇到问题
错误一: rsa_private read error : private key is NULL
两种解决方法
1解决方法:
1)在RSADataSigner.m文件中 搜索代码 [result appendString:@"-----BEGIN PRIVATE KEY-----\n"]; 将其改成 [result appendString:@"-----BEGIN RSA PRIVATE KEY-----\n"];
2)在RSADataSigner.m文件中 搜索代码 [result appendString:@"\n-----END PRIVATE KEY-----"]; 将其改成 [result appendString:@"\n-----END RSA PRIVATE KEY-----"];
我采用第一种方法!截图如下:
510806AB-216E-4768-8375-011F40AFB20E.png
2解决方法:
将RSA私钥转换成PKCS8格式,终端命令执行 openssl pkcs8 -topk8 -inform PEM -in rsa_private_key.pem -outform PEM -nocrypt ( PHP服务端语言读取私钥不需要PKCS8转换)密码为空就行(直接回车)
错误二:LaunchServices: ERROR: There is no registered handler for URL scheme alipay
这句话其实是在告诉你 设备上没有安装 支付宝的客户端,此时会走网页端
错误三:NSURLSession/NSURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9824)
原因是没有适配ios9
5.工程代码
//以下代码也是参考简述简书某个高手的,演示用的.
#import "ViewController.h"
#import <AlipaySDK/AlipaySDK.h>
#import "Order.h"
#import "DataSigner.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
UIButton *button1 = [[UIButton alloc]initWithFrame:CGRectMake(20, 20, 200, 44)];
[button1 setTitle:@"0.01" forState:UIControlStateNormal];
button1.backgroundColor = [UIColor redColor];
[button1 addTarget:self action:@selector(click1) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:button1];
UIButton *button2 = [[UIButton alloc]initWithFrame:CGRectMake(20, 120, 200, 44)];
[button2 addTarget:self action:@selector(click2) forControlEvents:UIControlEventTouchUpInside];
[button2 setTitle:@"0.02" forState:UIControlStateNormal];
button2.backgroundColor = [UIColor lightGrayColor];
[self.view addSubview:button2];
}
- (void)click1
{
[self pushAliPay:@"0.01"];
}
- (void)click2
{
[self pushAliPay:@"0.02"];
}
- (void)pushAliPay:(NSString *)str_price
{
//需要填写商户app申请
NSString *partner = @"2088开头的";//签约成功,支付宝提供给你的PID
NSString *seller = @"cj25??@163.com";//你的支付宝账号
NSString *privateKey = @"MIICXQIBAAKBgQCmIu4gNNn2VmAL7V2i7Y57dsiRG2DiustWKqcRnHyF5vr6cWXDHrr\neSKx86ClTlFDPNBdZ6SKsBVC1fpbGQ3WIJPooQ2cl11l";
//私钥和公钥都是你自己利用工具手动生成的,在这里私钥有很多,我删了大部分
//partner和seller获取失败,提示
if ([partner length] == 0 ||
[seller length] == 0 ||
[privateKey length] == 0)
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"提示"
message:@"缺少partner或者seller或者私钥。"
delegate:self
cancelButtonTitle:@"确定"
otherButtonTitles:nil];
[alert show];
return;
}
/*
*生成订单信息及签名
*/
//将商品信息赋予AlixPayOrder的成员变量
Order *order = [[Order alloc] init];
order.partner = partner;
order.sellerID = seller;
order.outTradeNO = [self generateTradeNO]; //订单ID(由商家自行制定)
order.subject = @"商品标题"; //商品标题
order.body = @"我是商品描述"; //商品描述
order.totalFee = [NSString stringWithFormat:@"%.2f",[str_price doubleValue]]; //商品价格
order.notifyURL = @"http://www.xxx.com/AliNotify.php"; //回调URL.问后台要, 注意不带参数,完整的,而且是可以网上访问的地址,我用的是PHP。
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;
if (signedString != nil) {
orderString = [NSString stringWithFormat:@"%@&sign=\"%@\"&sign_type=\"%@\"",
orderSpec, signedString, @"RSA"];
[[AlipaySDK defaultService] payOrder:orderString fromScheme:appScheme callback:^(NSDictionary *resultDic) {
NSLog(@"reslut = %@",resultDic);
}];
}
}
#pragma mark -
#pragma mark ==============产生随机订单号==============
- (NSString *)generateTradeNO
{
static int kNumber = 15;
NSString *sourceStr = @"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
NSMutableString *resultStr = [[NSMutableString alloc] init];
srand((unsigned)time(0));
for (int i = 0; i < kNumber; i++)
{
unsigned index = rand() % [sourceStr length];
NSString *oneStr = [sourceStr substringWithRange:NSMakeRange(index, 1)];
[resultStr appendString:oneStr];
}
return resultStr;
}
@end
AppDelegate.m文件
#import "AppDelegate.h"
#import <AlipaySDK/AlipaySDK.h>
@interface AppDelegate ()
@end
@implementation AppDelegate
// NOTE: 9.0以后使用新API接口
- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<NSString*, id> *)options
{
if ([url.host isEqualToString:@"safepay"]) {
//跳转支付宝钱包进行支付,处理支付结果
[[AlipaySDK defaultService] processOrderWithPaymentResult:url standbyCallback:^(NSDictionary *resultDic) {
NSLog(@"result = %@",resultDic);
//结果代码
/* 9000 订单支付成功 8000 正在处理中 4000 订单支付失败 6001 用户中途取消 6002 网络连接出错 */
}];
}
NSLog(@"%s",__func__);
return YES;
}
6.其他小细节
配置URL Schemes:点击项目名称,点击“Info”选项卡,在“URL Types”选项中,点击“+”, 在“URL Schemes”中输入“alisdkdemo”。
这里要和工程代码中的 NSString *appScheme = @"alisdkdemo";//这里设置支付宝回调,两者要保持一致。
注意:正式接入支付宝支付的阶段,注意以下几点:
1服务端:负责生成订单及签名,及接收支付异步通知。
2客户端:负责使用服务端传来的订单信息调用支付宝支付接口,及根据SDK同步返回3的支付结果展示结果页。
3服务端接入:私钥必须放在服务端,签名过程必须放在服务端。(上面测试例子是直接把私钥写在了客户端的代码中了,仅仅是测试)
4.notifyURL:算个人总结吧,我是搞前端的,也去了解了下这后端的知识,这是服务器端的回调,采用的是POST请求,所以
获取参数是用 $_POST['trade_status'];
遇到问题:客户端支付成功,钱也到账了,但以为notify.php没有执行,实际上它是有访问的,可以查看日志,有记录时间访问这个文件的。另外它没有得到它想要的,它会访问很多次,所以这个文件要及时给echo "success"。
另外获取参数它有三个状态值,
一个空,
一个TRADE_SUCCESS,高级版,只是说明支付成功,但交易没有结束的,可能有退款处理
一个TRADE_FINISHED,简单版,即时到账,交易就完成了。
具体区别就看网上的http://blog.163.com/lisoaring@126/blog/static/19205606201521222851548/