马云的支付宝SDK_iOS 移动支付集成开发包--《支付宝钱包支付接口开发包2.0标准版.pdf》
我们还需要先生成一个订单,文档中描述时,是将这步也放在客户端来做了,但也可以在服务器端生成这个订单(图中支付宝会在支付成功后通知服务器端,所以在服务器端生成订单的话,你可以掌握所有订单,而且也会更安全):
1.生成订单(可以在iOS客户端内生成,也可以在服务器端生成)2.调用支付宝支付接口,发送订单3.处理支付宝返回的支付结果
其实对于业务来说,这些步骤已经够了,但是有一个安全性问题,你肯定不希望你接收到的支付结果被截获修改,所以,这就需要在生成订单和处理支付结果的时候做一个安全性校验:
生成订单时对数据签名,收到支付结果时对数据进行签名验证,以检验数据是否被篡改过。
支付宝目前只支持采用RSA加密方式做签名验证。
[RSA加密算法]
除了可加解密外,还可用来作签名校验。简单的说,RSA会生成一个私钥和一个公钥,私钥你应该独自保管,公钥你可以分发出去。做签名验证时,你可以用私钥
对需要传输的数据做签名加密,生成一个签名值,之后分发数据,接收方通过公钥对签名值做校验,如果一致则认为数据无篡改。
具体到支付宝使用RSA做签名验证,就是在生产订单时,需要使用私钥生成签名值;在处理返回的支付结果时,需要使用公钥验证返回结果是否被篡改了。
具体需要对哪些值,怎样生成签名,对哪些值最签名验证,在第一个文档中有
resultStatus,状态码,SDK里没对应信息,第一个文档里有提到:9000 订单支付成功
8000 正在处理中
4000 订单支付失败
6001 用户中途取消
6002 网络连接出错
memo, 提示信息,比如状态码为6001时,memo就是“用户中途取消”。但千万别完全依赖这个信息,如果未安装支付宝app,采用网页支付时,取消时状态码是6001,但这个memo是空的。。(当我发现这个问题的时候,我就决定,对于这么不靠谱的SDK,还是尽量靠自己吧。。)
result,订单信息,以及签名验证信息。如果你不想做签名验证,那这个字段可以忽略了。
以上就是马云宝的一些通用流程和注意事项,如果有什么不对后期再更新...谢谢!
微信支付
他跟马云宝最大的区别在于 你的设备上没有安装支付宝的话会自动掉用网页版支付,然而马化腾的微信不会
发哥的微信支付集成流程图.png
//需要的依赖库,环境搭建可以参见文档,或者直接用cocoapods倒入/**
* 微信开放平台申请得到的 appid, 需要同时添加在 URL schema
*/NSString*constWXAppId =@"wxd930ea5d5a258f4f";/**
* 微信开放平台和商户约定的支付密钥
*
* 注意:不能hardcode在客户端,建议genSign这个过程由服务器端完成
*/NSString*constWXAppKey =@"L8LrMqqeGRxST5reouB0K66CaYAWpqhAVsq7ggKkxHCOastWksvuX1uvmvQclxaHoYd3ElNBrNO2DHnnzgfVG9Qs473M3DTOZug5er46FhuGofumV8H2FVR9qkjSlC5K";/**
* 微信开放平台和商户约定的密钥
*
* 注意:不能hardcode在客户端,建议genSign这个过程由服务器端完成
*/NSString*constWXAppSecret =@"db426a9829e4b49a0dcac7b4162da6b6";/**
* 微信开放平台和商户约定的支付密钥
*
* 注意:不能hardcode在客户端,建议genSign这个过程由服务器端完成
*/NSString*constWXPartnerKey =@"8934e7d15453e97507ef794cf7b0519d";/**
* 微信公众平台商户模块生成的ID
*/NSString*constWXPartnerId =@"1900000109";调用支付的代码就比较简单了,如下所示#pragma mark - 主体流程- (void)getAccessToken{NSString*getAccessTokenUrl = [NSStringstringWithFormat:@"https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%@&secret=%@", WXAppId, WXAppSecret];NSLog(@"--- GetAccessTokenUrl: %@", getAccessTokenUrl);self.request= [ASIHTTPRequest requestWithURL:[NSURLURLWithString:getAccessTokenUrl]];__weakWXPayClient *weakSelf =self;__weakASIHTTPRequest *weakRequest =self.request;[self.requestsetCompletionBlock:^{NSError*error =nil;NSDictionary*dict = [NSJSONSerializationJSONObjectWithData:[weakRequest responseData]options:kNilOptionserror:&error];if(error) {[weakSelf showAlertWithTitle:@"错误"msg:@"获取 AccessToken 失败"];return;}else{NSLog(@"--- %@", [weakRequest responseString]);}NSString*accessToken = dict[AccessTokenKey];if(accessToken) {NSLog(@"--- AccessToken: %@", accessToken);__strongWXPayClient *strongSelf = weakSelf;[strongSelf getPrepayId:accessToken];}else{NSString*strMsg = [NSStringstringWithFormat:@"errcode: %@, errmsg:%@", dict[errcodeKey], dict[errmsgKey]];[weakSelf showAlertWithTitle:@"错误"msg:strMsg];}}];[self.requestsetFailedBlock:^{[weakSelf showAlertWithTitle:@"错误"msg:@"获取 AccessToken 失败"];}];[self.requeststartAsynchronous];}- (void)getPrepayId:(NSString*)accessToken{//token传入到此链接NSString*getPrepayIdUrl = [NSStringstringWithFormat:@"https://api.weixin.qq.com/pay/genprepay?access_token=%@", accessToken];NSLog(@"--- GetPrepayIdUrl: %@", getPrepayIdUrl);NSMutableData*postData = [selfgetProductArgs];// 文档: 详细的订单数据放在 PostData 中,格式为 jsonself.request= [ASIHTTPRequest requestWithURL:[NSURLURLWithString:getPrepayIdUrl]];[self.requestaddRequestHeader:@"Content-Type"value:@"application/json"];[self.requestaddRequestHeader:@"Accept"value:@"application/json"];[self.requestsetRequestMethod:@"POST"];[self.requestsetPostBody:postData];__weakWXPayClient *weakSelf =self;__weakASIHTTPRequest *weakRequest =self.request;[self.requestsetCompletionBlock:^{NSError*error =nil;NSDictionary*dict = [NSJSONSerializationJSONObjectWithData:[weakRequest responseData]options:kNilOptionserror:&error];//获取到了支付参数if(error) {[weakSelf showAlertWithTitle:@"错误"msg:@"获取 PrePayId 失败"];return;}else{NSLog(@"--- %@", [weakRequest responseString]);}NSString*prePayId = dict[PrePayIdKey];if(prePayId) {NSLog(@"--- PrePayId: %@", prePayId);// 调起微信支付//将支付参数传入到sdk,唤起微信客户端PayReq *request = [[PayReq alloc] init];request.partnerId= WXPartnerId;request.prepayId= prePayId;request.package=@"Sign=WXPay";// 文档为 `Request.package = _package;` , 但如果填写上面生成的 `package` 将不能支付成功request.nonceStr= weakSelf.nonceStr;request.timeStamp= [weakSelf.timeStamplongLongValue];// 构造参数列表NSMutableDictionary*params = [NSMutableDictionarydictionary];[params setObject:WXAppId forKey:@"appid"];[params setObject:WXAppKey forKey:@"appkey"];[params setObject:request.nonceStrforKey:@"noncestr"];[params setObject:request.packageforKey:@"package"];[params setObject:request.partnerIdforKey:@"partnerid"];[params setObject:request.prepayIdforKey:@"prepayid"];[params setObject:weakSelf.timeStampforKey:@"timestamp"];request.sign= [weakSelf genSign:params];// 在支付之前,如果应用没有注册到微信,应该先调用 [WXApi registerApp:appId] 将应用注册到微信[WXApi safeSendReq:request];}else{NSString*strMsg = [NSStringstringWithFormat:@"errcode: %@, errmsg:%@", dict[errcodeKey], dict[errmsgKey]];[weakSelf showAlertWithTitle:@"错误"msg:strMsg];}}];[self.requestsetFailedBlock:^{[weakSelf showAlertWithTitle:@"错误"msg:@"获取 PrePayId 失败"];}];[self.requeststartAsynchronous];}//这是微信官方给的demo,直接调用getAccessToken方法即可完成支付
银联支付 【最简单了】
发哥的银联支付集成流程图.png
- (void)viewDidLoad {[superviewDidLoad];//开始支付//第一个参数是流水号,又后台返回给我们 第二个参数传00,01,00标示正式环境,01标示测试环境,第三个参数是支付完成回到的控制器,第四个参数是设置代理[UPPayPlugin startPay:@"57855654"mode:@"01"viewController:self.navigationControllerdelegate:self];// Do any additional setup after loading the view, typically from a nib.}//监听支付结果- (void)UPPayPluginResult:(NSString*)result{}
还有一个是我在外包公司经常使用的---这家伙集成所有支付功能于一身:---->Ping++
支付流程:
ping++ //------>支持支付宝支付,微信支付,银联支付,百度钱包支付,applepay
(1)根据呢需要介入的支付方式去对应的支付平台申请账号和参数
(2)传说中的7行代码搞定所有的支付
发哥的ping++继承流程图
直接上代码:
NSDictionary* dict = @{@"channel": channel,// 渠道 alipay, wx, upacp, bfb@"amount": amount// 金额};NSData* data = [NSJSONSerializationdataWithJSONObject:dict options:NSJSONWritingPrettyPrintederror:nil];NSString*bodyData = [[NSStringalloc] initWithData:data encoding:NSUTF8StringEncoding];[postRequest setHTTPBody:[NSDatadataWithBytes:[bodyData UTF8String] length:strlen([bodyData UTF8String])]];[postRequest setHTTPMethod:@"POST"];NSOperationQueue*queue = [[NSOperationQueuealloc] init];[NSURLConnectionsendAsynchronousRequest:postRequest queue:queue completionHandler:^(NSURLResponse*response,NSData*data,NSError*connectionError) {NSHTTPURLResponse* httpResponse = (NSHTTPURLResponse*)response;NSString* charge = [[NSStringalloc] initWithData:data encoding:NSUTF8StringEncoding];// ...[Pingpp createPayment:charge viewController:viewController appURLScheme:kUrlScheme withCompletion:^(NSString*result, PingppError *error) {if([result isEqualToString:@"success"]) {// ...}else{NSLog(@"PingppError: code=%lu msg=%@", error.code, [error getMsg]);}}];}];//AppDelegate添加这行代码适用于监听支付结果的- (BOOL)application:(UIApplication*)application openURL:(NSURL*)url sourceApplication:(NSString*)sourceApplication annotation:(id)annotation {[Pingpp handleOpenURL:url withCompletion:^(NSString*result, PingppError *error) {if([result isEqualToString:@"success"]) {// ...}else{NSLog(@"PingppError: code=%lu msg=%@", error.code, [error getMsg]);}}];returnYES;}
个人感觉第三方支付终究还是第三方,只是站着公司和开发者的角度上考虑问题,减少开发难度和成本,我还是推荐大家自己去亲自集成一次支付的功能,你才会有成长