因为近期项目中需要接入支付宝支付功能,自己也爬了很多的坑,所以做了一下这边文章供大家学习参考,远离爬坑,文章主要讲到以下五部分:
一、支付宝开放平台创建应用
二、签约移动支付功能
三、接入支付前的准备工作附准备工作中遇到难题的解决方法
四、配置官方Demo附BUG解决方法
五、集成项目,具体代码编写、
本文为本人学习记录笔记,如需转载,请注明出处@iOSlyon
支付宝开放平台创建应用 登录支付宝开放平台
1. 应用创建完成后点击查看我的应用详情进行移动支付功能的签约
或者
2.进入支付宝商家服务页面"https://b.alipay.com/newIndex.htm"选择移动支付功能进行签约
签约过程以下以签约移动支付功能为例子
商户签约审核签约审核具体步骤请参见支付宝官方文档签约与审核
或者
️️️️️️️ 下列图示
-
填写签约信息
上图的附件文档
因为有次文档错误导致审核不通过,所以以下贴出审核成功的文档供大家参考
上述签约步骤审核通过之后就可以开始集成工作了
接入前准备工作
第一步、商户密钥管理密钥作用
这个步骤完全可以看官方文档中的操作,官方文档写得很详细,但是其中有几点需要说明:
一、说明问题
上传密钥步骤不知道怎么上传?因为密钥是pem文件,但是上传的是字符串文本。
一、解决方法
将生成的pem文件复制一份到桌面,改成Txt文件打开即可获取我们需要的字符串,记住当我们引用这两个长的字符串时,字符串不能包括,换行,空格,以及其他误加的字符,所以复制的时候一定要小心。
二、说明问题
Mac 自带openssl环境,不用安装,直接终端输入openssl
就可以。
配置官方Demo代码部分下载Demo
支付宝官方Demo中需要配置商户的资料(如下)
//开放平台登录https://openhome.alipay.com/platform/appManage.htm
//管理中心获取APPID
#define MXAlipayAPPID @"请配置你的AppID"
//支付宝私钥(用户自主生成,使用pkcs8格式的私钥)
#define MXAlipayPrivateKey @"请配置你的支付宝pkcs8私钥"
配置以上数据后,真机编译,遇到以下问题
- 输出错误信息
如配置信息中的私钥(即上述PartnerPrivKey)使用的不适pkcs8的私钥的话,则会报以下错误
rsa_private read error : private key is NULL
- 解决方法:
-
方法一
将私钥转成PKCS8替换一下原私钥即可转换方法如下
( PHP服务端语言读取私钥不需要PKCS8转换)
OpenSSL> 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程序
-
方法二
检查PID是否写正确
接下来重新运行,上述错误已经解决,但遇到新问题如下图
-
弹框显示
-
解决方法: 可参考百度中查到的结果上述问题解决方法
- 问题源头是因为私钥跟商户上传的公钥不匹配
处理完上述问题之后,就可以进行支付操作了
测试Demo具体操作
1.创建一个AlipayDemoTest项目
2.新建一个AliSDK文件夹,提取SDK包中以下文件到此文件夹里,
3.编译项目,会出现以下问题:
1)"Unknown type name ‘NSString‘ "或"Unknown type name ‘NSData‘ "
这是因为缺少Foundation类库和UIKit类库,支付宝Demo中之所以没有出现此错误,是因为在.pch文件中导入过这些类库
解决办法:只需要在出现错误的文件中导入这些类库即可
2)‘openssl/asn1.h‘ file not found
这是openssl文件夹头文件链接问题,如果openssl文件夹随意拉进项目中,即使添加头文件链接,也可能解决不了此问题,
这也是一开始就将所需要的文件放到一个新建文件夹中再添加到项目中的原因。
解决办法:
Targets->Build Settings->Header Search Path中添加AliPaySDK文件夹的路径
4.编译项目,会出现以下问题:
解决方法:在xcode中,点击项目名,选择"target"->"Link Binary With Libraries"添加依赖库。
编辑程序,已经可以成功编译了,接下来就是集成代码了
#import "AppDelegate.h"
#import <AlipaySDK/AlipaySDK.h>
@interface AppDelegate ()
@end
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
return YES;
}
- (BOOL)application:(UIApplication *)application
openURL:(NSURL *)url
sourceApplication:(NSString *)sourceApplication
annotation:(id)annotation
{
if ([url.host isEqualToString:@"safepay"]) {
//跳转支付宝钱包进行支付,处理支付结果
[[AlipaySDK defaultService] processOrderWithPaymentResult:url standbyCallback:^(NSDictionary *resultDic) {
NSLog(@"result = %@",resultDic);
}];
}
return YES;
}
// 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);
}];
}
return YES;
}
@end
#import "ViewController.h"
#import "Order.h"
#import "DataSigner.h"
#import <AlipaySDK/AlipaySDK.h>
@interface ViewController ()
@end
@implementation ViewController
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
/*=========================================================*/
/*====客户端调用支付宝支付(实际操作请放到服务端)=================*/
/*=========================================================*/
//AppId和PrivateKey没有配置下的提示
if ( [MXAlipayAPPID length] == 0
||[MXAlipayPrivateKey length] == 0
||[MXAlipayAPPID isEqualToString:@"请配置你的AppID"]
||[MXAlipayPrivateKey isEqualToString:@"请配置你的支付宝pkcs8私钥"])
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"提示"
message:@"缺少appId或者私钥。"
delegate:self
cancelButtonTitle:@"确定"
otherButtonTitles:nil];
[alert show];
return;
}
//商品价格
NSString *price = [NSString stringWithFormat:@"%.2f", 0.01];
//将商品信息赋予AlixPayOrder的成员变量
Order* order = [Order new];
order.app_id = MXAlipayAPPID;// NOTE: app_id设置
order.method = MXUrlAlipay; // NOTE: 支付接口名称
order.charset = @"utf-8"; // NOTE: 参数编码格式
NSDateFormatter* formatter = [NSDateFormatter new];
[formatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
order.timestamp = [formatter stringFromDate:[NSDate date]]; // NOTE: 当前时间点
order.version = @"1.0"; // NOTE: 支付版本
order.sign_type = @"RSA"; // NOTE: sign_type设置
// NOTE: 商品数据
order.biz_content = [BizContent new];
order.biz_content.body = @"我是测试数据";
order.biz_content.subject = @"1";
order.biz_content.out_trade_no = [self generateTradeNO]; //订单ID(由商家自行制定)
order.biz_content.timeout_express = @"30m"; //超时时间设置
order.biz_content.total_amount = price; //商品价格
//将商品信息拼接成字符串
NSString *orderInfo = [order orderInfoEncoded:NO];
NSString *orderInfoEncoded = [order orderInfoEncoded:YES];
NSLog(@"orderSpec = %@",orderInfo);
// NOTE: 获取私钥并将商户信息签名,外部商户的加签过程请务必放在服务端,防止公私钥数据泄露;
// 需要遵循RSA签名规范,并将签名字符串base64编码和UrlEncode
id<DataSigner> signer = CreateRSADataSigner(MXAlipayPrivateKey);
NSString *signedString = [signer signString:orderInfo];
// NOTE: 如果加签成功,则继续执行支付
if (signedString != nil) {
//应用注册scheme,在AliSDKDemo-Info.plist定义URL types
NSString *appScheme = MXURLScheme;
// NOTE: 将签名成功字符串格式化为订单字符串,请严格按照该格式
NSString *orderString = [NSString stringWithFormat:@"%@&sign=%@",
orderInfoEncoded, signedString];
// NOTE: 调用支付结果开始支付
[[AlipaySDK defaultService] payOrder:orderString fromScheme:appScheme callback:^(NSDictionary *resultDic) {
NSLog(@"reslut = %@",resultDic);
}];
}
}
#pragma mark - Private Method
//==============产生随机订单号==============
+ (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
这里也可以下载我自己搭建的DEMO
已解决所有错误
下载后替换掉MXAlipayConfig.h中的配置参数即可运行,前提是你的参数不能错
使用方法可以参考Demo中的ReadMe文件
正式接入阶段
服务端
负责生成订单及签名,及接受支付异步通知。
客户端
负责使用服务端传来的订单信息调用支付宝支付接口,及根据SDK同步返回的支付结果展示结果页。
服务端接入
私钥必须放在服务端,签名过程必须放在服务端。
集成支付宝后打包ipa,报如下一系列警告:
解决方法:
- Go to Build Settings -> Build Options -> Debug Information Format
- Change the Debug setting from "DWARF with dSYM File" to "DWARF"
- Leave the Release setting at "DWARF with dSYM File"
AlipaySDK.framework 是先 build 的静态 lib ,然后转成的 framework ,但是在 build 静态 lib 时 CLANG_ENABLE_MODULES 没有被设置成 disabled 。