iOS支付宝支付(Alipay)详细接入流程以及项目中遇到的问题分析

  
浏览: 149 发布日期: 2016-10-19  分类: ios

最近在项目中接入了微信支付和支付宝支付,总的来说没有那么坑,很多人都说文档不全什么的,确实没有面面

到,但是认真一步一步测试下还是妥妥的,再配合懂得后台,效率也是很高的,看了这篇文章,你也只要几分钟,

就能轻松接入支付宝,在别人投来崇拜的眼光的同时,你就能潇洒的回一句,略懂略懂。。。。。。

 

先给大家我写的微信支付,很详细哦,喜欢的点个赞点击打开微信支付链接

 

 

前期准备

首先商户要去支付宝申请,得到一个parnter和seller,然后在电脑上生成一组RSA,公钥给支付宝,私钥自己流程,具

体流程我不BB了,自己看点击打开链接,主要这些东西我们App也不需要怎么管理,大家随意看看知道下

1.seller ID 商户唯一ID标识符

2.parnter ID 合作身份ID,以2088开头的16位纯数字

3.加密用到的文件(私钥自己做,支付宝公钥)

下载SDK

这里SDK的文档只有最近一次更新的,没记错的话2016年Alipay有一次重大的改动,我这有一份很全的更新文档,朋

友给我的,需要注意的在最后给大家分析,这里只需要先下载下来,看看里面的代码,然后把需要的东西准备下,继

续往下分析,其实还有一个用处,就是把你生成的密钥和seller和parnter给填进去,跑一下,看能不能拉起来,但是

正常情况下是不需要这么搞得,后台处理的,项目的时候也不需要我们App做的,所以还是往下看

点击下载SDK链接

手动接入SDK

为什么手动呢,因为不支持cocoapods,又不是第三方的,这种还是自己接入安全点。

步骤1

先把这两个框架拖进来

步骤2

把四个箭头的文件拖进去,记得文件夹拖进去是选择Create Group,其实这四个文件是为了签名在客户端签名而存在

的,实际项目中,我们是要把私钥保存在自己的服务器,然后服务器进行支付订单参数的签名,返回给客户端,我还

是放到自己项目中了,毕竟其他地方也要用到,要是在服务器签名order文件就不要拉进来了


 

步骤3

配置prefix header

如果原本项目中的根目录中有以下prefix文件,例如

则在其中引入 #import<UIKit/UIKit.h>,#import<Foundation/Foundation.h>

如果不存在,那么直接把支付宝Demo里面的prefix文件拖到自己项目的根目录下,最好改下文件名,然后配置路径

(在Build Settings 中搜索 Prefix Header),添加路径 (可以直接拖拽)

 

 

 

步骤4

然后根据下图添加库文件

貌似这两个也要加上,那就加进去吧

步骤5

如果是自己Demo本地签名,不是服务器签名,那么再设置下openssl的路径

在header search paths 中添加 openssl 的路径$(SRCROOT)/XXX

$(SRCROOT)就是本工程的文件夹

网上找了个相对路径和绝对路径的文章点击打开链接


 

步骤6

配置URL Scheme,主要就是回调的时候能拉起App,这里的Scheme千万不能乱用,也别重复了,不然怎么都拉

不起来了,我就遇到过一次,和微信拉起App重复了,导致很尴尬,咱们保持唯一就好了,也就是给咱们自己的项目

增加个标识符,能够让支付宝回调拉起来

步骤7

这里就是根据上面的配置,在本地进行签名,拉起支付宝,需要的朋友直接下载Demo看吧,没什么好讲的,因为支

付宝都强调了不要在本地玩,不过你想玩,那就玩吧,后果自负

 

来来来,组装完毕,正式项目接入流程点火起飞

如果起飞有问题,可能我上面漏了什么,记得留言给我哦(写代码记得包头文件)

第一步

传订单号给自己的服务器签名,再提一次,千万别再本地写,你和后台定好规则,传需要的订单字符串给他,他把签

名之后的字符串给你

// 订单的“,”分割字符串 支付宝只是传签名,不需要再次校验,微信成功之后没有返回值,所以微信支付需要保存到沙盒

@property (nonatomic,strong)NSString *orderStr;

 

关键代码,拉取服务器的签名参数,然后传给支付宝拉起支付 (这里的block处理的是没有支付宝的时候走H5收银台的回调)

  1. - (IBAction)payMoney:(UIButton *)sender
  2. {
  3. // 配置好的回调scheme
  4. NSString *appScheme = @"上面配置好的";
  5.  
  6. // 订单拿去给服务器签名
  7. [[TWTShoppingCartLogic sharedData] goToSignOrder:@"订单字符串" way:@"1" complete:^(NSError *error, id data) {
  8.  
  9. if (error)
  10. {
  11. DSToast *toast = [[DSToast alloc] initWithText:@"连接服务器失败,请稍后再试" color:RGBA(255, 174, 1, 1)];
  12. [toast show];
  13. }
  14. else
  15. {
  16. // 拉起支付宝,2016年5月之后更新是H5回调到这里
  17. [[AlipaySDK defaultService] payOrder:data fromScheme:appScheme callback:^(NSDictionary *resultDic) {
  18.  
  19. DDLogVerbose(@"点击支付获取的直接结果===>>>>>>reslut = %@",resultDic);
  20. // NSString *memo = resultDic[@"memo"];
  21.  
  22. NSString *result = resultDic[@"result"];
  23. DDLogVerbose(@"%@",result);
  24. NSString *resultStatus = resultDic[@"resultStatus"];
  25. //9000 订单支付成功 正常流程会进入这里 如果中断了就去外面delegate那里的Block
  26. if ([resultStatus isEqualToString:@"9000"])
  27. {
  28. // "out_trade_no" = "\"74db120f0a8e5646ef5a30154e9f6deb\"";
  29. NSString *outNum = nil;
  30. NSMutableString *outTradeNum = [[NSMutableString alloc] init];
  31. NSArray *strArr = [result componentsSeparatedByString:@"&"];
  32. for (NSString *trade in strArr) {
  33. if ([trade hasPrefix:@"out_trade_no"])
  34. {
  35. outNum = [trade componentsSeparatedByString:@"="][1];
  36. [outTradeNum appendString:outNum];
  37. [outTradeNum replaceOccurrencesOfString:@"\"" withString:@"" options:NSLiteralSearch range:NSMakeRange(0, outTradeNum.length)];
  38. DDLogVerbose(@"%@",outTradeNum);
  39. break;
  40. }
  41. }
  42. // 第一个参数传的是alipay返回给我的out_trade_id 异步回调二次验证
  43. [[TWTShoppingCartLogic sharedData] goToCheckOrder:outTradeNum complete:^(NSError *error, id data) {
  44. if (error)
  45. {
  46. [TWTAlertView showAlertViewWithTitle:nil message:@"网络数据异常,请稍后刷新" cancelOnTouch:NO cancelButtonTitle:nil doneButtonTitle:@"确定" doneBlock:^(void){
  47. [self.navigationController popViewControllerAnimated:YES];
  48. }];
  49. // 匹配不到就上报异常
  50. }
  51. else
  52. {
  53. [[TWTCommonAPILogic sharedData]reportData:nil forEventKey:@"PaySucceedVC_CallBack" number:@(1)];
  54. DSToast *toast = [[DSToast alloc] initWithText:@"支付成功" color:nil];
  55. [toast show];
  56. }
  57.  
  58. }];
  59. }
  60. else
  61. {
  62. //8000 正在处理中 4000 订单支付失败 6001 用户中途取消/重复操作取消 6002 网络连接出错 ---> 从H回来
  63. // 弹出失败的界面,弹出之后的话就不支付界面消失,方便重新支付
  64. }
  65. }];
  66. }
  67. }];
  68.  
  69. }

注意啦!!!

注意啦!!!

注意啦!!!

介绍下支付宝对我来说影响最大的一次

 

首先看看官方的调用接口,根据图来讲,我们就说方法1和方法2了,各位懵逼的就看图指示


 

再来看看2016年5月份更新的文档

IOS版本号:v15.1.0
修改时间:2016-4-28
更新点:
1. 增加获取trade_token接口(收单收银分离参数,与现有业务支付不冲突);
2. 支付结果返回统一,便于用户接入。
   原有方案:payOrder:fromScheme:callback接口,业务传入callback1,用于支付结果返回;
                 processOrderWithPaymentReulst:standbyCallback接口,业务传入callback2,用于支付结果返回;

一般一次支付中(跳支付宝客户端支付),都会涉及到这两个接口;原有的规则是callback1存在,则统一调用callback1返回支付结果给业务方,若callback1不存在(app被杀掉的情况),则调用callback2返回支付结果给业务方。

现有方案:payOrder:fromScheme:callback接口,业务会传入CompletionBlock1(本地没有安装支付宝客户端的情况下(走H5收银台),会通过该CompletionBlock1反馈结果);
                 processOrderWithPaymentResult:standByCallback接口,业务会传入CompletionBlock2(本地安装了支付宝客户端的情况下,会通过该CompletionBlock2反馈结果)。

 

个人分析:

改版之前

看了这两次的介绍和图,简单来说就是原本方法1和方法2实现的情况下,方法1存在的情况下,结果返回给方法1的

block,方法1不存在,那么久回调到方法2的回调

唯一存在的用户操作就是,当你支付拉起支付宝的时候,你的商户App自杀了或者你手贱把他退出了,那么,你的方

法1自然就没了,你就需要方法2来进行回调结果的通知

 

改版之后

我感觉更正常了点了,但是咱们得改改代码逻辑啊,方法1和方法2都实现了,方法1只负责当没有支付宝客户端的时

候,走H5收银台,进行支付,结果处理回调,方法2就处理有客户端的情况下的回调,这里亲自测试,当拉起支付宝

的时候,你手贱退出了,也是回调到方法2的block里面进行结果反馈

 

我已经更新SDK到最新了,而且我这里介绍的也是最新,就是改版之后的方法,老的不介绍了,理论上都要用最新的

嘛,如果你用旧的,那我也没办法

 

第二步

处理支付结果(有支付宝的情况下回调该方法)

  1. // 当用户通过其它应用启动本应用时,会回调这个方法,url参数是其它应用调用openURL:方法时传过来的
  2. - (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation
  3. {
  4. if ([url.host isEqualToString:@"safepay"]) {
  5. //跳转支付宝钱包进行支付,处理支付结果,该方法是当去支付的时候我的进程被杀死的时候调用这里的回调,不然就调用payorder的回调
  6. [[AlipaySDK defaultService] processOrderWithPaymentResult:url standbyCallback:^(NSDictionary *resultDic)
  7. {
  8. DDLogVerbose(@"点击支付获取的直接结果===>>>>>>reslut = %@",resultDic);
  9.  
  10. NSString *result = resultDic[@"result"];
  11. NSString *resultStatus = resultDic[@"resultStatus"];
  12. //9000 订单支付成功
  13. // 支付完成需要把返回的outtradeID给解析出来,给服务器二次确认
  14. if ([resultStatus isEqualToString:@"9000"])
  15. {
  16. // "out_trade_no" = "\"74db120f0a8e5646ef5a30154e9f6deb\"";
  17. NSString *outNum = nil;
  18. NSMutableString *outTradeNum = [[NSMutableString alloc] init];
  19. NSArray *strArr = [result componentsSeparatedByString:@"&"];
  20. for (NSString *trade in strArr) {
  21. if ([trade hasPrefix:@"out_trade_no"])
  22. {
  23. outNum = [trade componentsSeparatedByString:@"="][1];
  24. [outTradeNum appendString:outNum];
  25. [outTradeNum replaceOccurrencesOfString:@"\"" withString:@"" options:NSLiteralSearch range:NSMakeRange(0, outTradeNum.length)];
  26. break;
  27. }
  28. }
  29. order.aliPayTrade = outTradeNum;
  30. // 第一个参数传的是alipay返回给我的out_trade_id 二次确认
  31. [[TWTShoppingCartLogic sharedData] goToCheckOrder:outTradeNum complete:^(NSError *error, id data) {
  32. if (error)
  33. {
  34. [TWTAlertView showAlertViewWithTitle:nil message:@"网络数据异常,请稍后刷新" cancelOnTouch:NO cancelButtonTitle:nil doneButtonTitle:@"确定" doneBlock:^(void){
  35. }];
  36. // 匹配不到就上报异常
  37. }
  38. else
  39. {
  40. [[TWTCommonAPILogic sharedData]reportData:nil forEventKey:@"PaySucceedVC_CallBack" number:@(1)];
  41. DSToast *toast = [[DSToast alloc] initWithText:@"支付成功" color:nil];
  42. [toast show];
  43. }];
  44. }
  45. else
  46. {
  47.  
  48. //8000 正在处理中 4000 订单支付失败 6001 用户中途取消/重复操作取消 6002 网络连接出错
  49. }
  50. }];
  51. }
  52. return YES;
  53. }

这里有个iOS 9的API,反正没什么卵用

  1. // NOTE: 9.0以后使用新API接口
  2. - (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<NSString*, id> *)options
  3. {

第三步(小细节)

和微信支付一样,我们不能直接用同步返回的结果来判断是否正真支付成功(也是我写的微信支付详解链接

按照官方的说法请看如下


好在支付宝和微信支付不同的地方在于,支付宝的返回数据中有带订单信息,我们就直接解析可以了,不需要像微信

一样只返回状态码,我们需要本地存起来,再和服务器二次校验

 

几个小小的坑

Cannot find interface declarationfor'NSObject', superclass of'Base64'

 
这个问题按照步骤三里面的介绍配置下pch文件就好了,在base64.h中包含缺少的头文件就搞定了
 
 

‘rsa.h’ file not found

这个问题就是步骤五提到的了,如图解决
 
 
其实,你只要按我的步骤来,交给服务器签名,做我们App该做的事,基本就没有什么问题
 
 
总结一下
1.导入Demo中框架,相关库,配置pch文件以及openssl文件路径
2.配置URL Scheme
3.把签名交给服务器
4.注意改版前后的回调机制,最好保持最新的,最新的逻辑更清晰
5.和微信一样,同步返回的结果记得二次确认,和后台约定好解析字段
 
 
官方Demo:点击打开链接
 

iOS开发支付宝支付的更多相关文章

  1. IOS开发--支付宝支付

    前言:继上次<IOS开发--微信支付>以来,一直没有太多时间,更新总结详细支付这样的长篇大论,很抱歉.今天,推出支付宝支付的详细流程. 1.开始下载和查看支付宝支付的Demo. 我们直接进 ...

  2. IOS开发之支付功能概述

    前言:本随笔将对IOS开发的支付功能进行一个概述. 内容大纲: 一.常见的支付方案简介 二.第三方支付SDK 三.苹果官方支付方案 四.Web支付方案 正文: 一.常见的支付方案简介 在微信支付中 微 ...

  3. 开发支付宝支付用DELPHI实现 RSA签名

    近来根据业务需求 在ERP中集成了微信支付,支付宝支付,开发支付宝支付时最大的障碍就是RSA签名,找了很多资料,最终用 下了个libeay32.pas  根据网上资料最终解决了问题 function  ...

  4. Laravel 开发支付宝支付与提现转账问题小结

    由于项目需要,所以需要开发支付宝支付与微信支付,支付部分采用了 yansongda/pay    https://packagist.org/packages/yansongda/pay  https ...

  5. iOS - AliPay 支付宝支付

    1.支付宝支付申请 支付宝支付官方签约集成指引 支付宝APP支付官方集成指引 蚂蚁金服开放平台 1.1 支付宝 APP 支付申请步骤 APP 支付:APP 支付是商户通过在移动端应用 APP 中集成开 ...

  6. iOS集成支付宝支付

    本文由本人原创发表于博客园,转载请注明出处 http://www.cnblogs.com/wangqw/p/5074907.html 一. 开发前准备 iOS 支付宝SDK下载地址:(内含iOS An ...

  7. iOS开发微信支付

    现在基本所有的App都会接入支付宝支付以及微信支付,也有很多第三方提供给你 SDK帮你接入,但是这种涉及到支付的东西还是自己服务器搞来的好一些,其实搞懂了 逻辑非常的简单,下面直接给大家说说下基本流程 ...

  8. IOS开发支付宝集成思路

    一般情况下支付功能的交互流程 比如我们去某个APP去支付一个产品,流程为:1.用户点击支付->2.客户端请求服务器用户支付->3.服务器接收请求生成金额订单等要给第三方支付的一切信息,并生 ...

  9. IOS开发支付宝集成

    开发准备 1.首先新建项目,然后去官网下载最新的开发包:http://doc.open.alipay.com/doc2/detail?treeId=59&articleId=103563&am ...

随机推荐

  1. Linux系统之常用文件搜索命令

    (一)常用文件搜索命令 (1)which命令 (2)find命令 (3)locate (4)updatedb (5)grep (6)man (7)whatis (一)常用文件搜索命令 (1)which ...

  2. 深度学习中 batchnorm 层是咋回事?

    作者:Double_V_ 来源:CSDN 原文:https://blog.csdn.net/qq_25737169/article/details/79048516 版权声明:本文为博主原创文章,转载 ...

  3. BZOJ.4903.[CTSC2017]吉夫特(Lucas DP)

    题目链接 首先\(C(n,m)\)为奇数当且仅当\(n\&m=m\). 简要证明: 因为是\(mod\ 2\),考虑Lucas定理. 在\(mod\ 2\)的情况下\(C(n,m)\)最后只会 ...

  4. Shiro笔记(五)JSP标签

    Shiro笔记(五)JSP标签 导入标签库 <%@taglib prefix="shiro" uri="http://shiro.apache.org/tags&q ...

  5. [HDU1392]Surround the Trees

    思路: 凸包模板题. 注意n=1和n=2的情况. 当n=1时,不需要绳子. 当n=2时,绳子长度为两棵树之间距离. 当n≥e时,Graham求凸包即可.最后将凸包上的所有相邻点距离求和. #inclu ...

  6. adblock 下载地址

    addblock 的作用: 防止追踪.恶意域名,过滤横幅广告.弹窗广告以及视频广告.   用以支持网站的非侵入式广告将不会被屏蔽 下载地址:https://pan.baidu.com/share/li ...

  7. oracle case when 用法

    原文:http://www.cnblogs.com/eshizhan/archive/2012/04/06/2435493.html 1. CASE WHEN 表达式有两种形式 --简单Case函数 ...

  8. oracle索引原理(b-tree,bitmap,聚集,非聚集索引)

    B-TREE索引 一个B树索引只有一个根节点,它实际就是位于树的最顶端的分支节点. 可以用下图一来描述B树索引的结构.其中,B表示分支节点,而L表示叶子节点. 对于分支节点块(包括根节点块)来说,其所 ...

  9. orm Lite的使用

    1.什么是ORM Lite orm Lite(Object Relationanl Mapping Lite)是一种用于持久化保存java对象的框架,相对于标准的ORM包来说. 2. Demo ●声明 ...

  10. unity 打包编译记录

    1.放到Plugins目录下的贴图不会打包进去 2.放到Plugins目录下的dll会自动打包,代码也会打包 3.放在Resources目录下的资源会自动打包 4.放在StreamingAssets目 ...