iOS支付宝(Alipay)接入详细流程,比微信支付更简单,项目实战中的问题分析
最近在项目中接入了微信支付和支付宝支付,总的来说没有那么坑,很多人都说文档不全什么的,确实没有面面
俱到,但是认真一步一步测试下还是妥妥的,再配合懂得后台,效率也是很高的,看了这篇文章,你也只要几分钟,
就能轻松接入支付宝,在别人投来崇拜的眼光的同时,你就能潇洒的回一句,略懂略懂。。。。。。
先给大家我写的微信支付,很详细哦,喜欢的点个赞点击打开微信支付链接
前期准备
首先商户要去支付宝申请,得到一个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收银台的回调)
- - (IBAction)payMoney:(UIButton *)sender
- {
- // 配置好的回调scheme
- NSString *appScheme = @"上面配置好的";
- // 订单拿去给服务器签名
- [[TWTShoppingCartLogic sharedData] goToSignOrder:@"订单字符串" way:@"1" complete:^(NSError *error, id data) {
- if (error)
- {
- DSToast *toast = [[DSToast alloc] initWithText:@"连接服务器失败,请稍后再试" color:RGBA(255, 174, 1, 1)];
- [toast show];
- }
- else
- {
- // 拉起支付宝,2016年5月之后更新是H5回调到这里
- [[AlipaySDK defaultService] payOrder:data fromScheme:appScheme callback:^(NSDictionary *resultDic) {
- DDLogVerbose(@"点击支付获取的直接结果===>>>>>>reslut = %@",resultDic);
- // NSString *memo = resultDic[@"memo"];
- NSString *result = resultDic[@"result"];
- DDLogVerbose(@"%@",result);
- NSString *resultStatus = resultDic[@"resultStatus"];
- //9000 订单支付成功 正常流程会进入这里 如果中断了就去外面delegate那里的Block
- if ([resultStatus isEqualToString:@"9000"])
- {
- // "out_trade_no" = "\"74db120f0a8e5646ef5a30154e9f6deb\"";
- NSString *outNum = nil;
- NSMutableString *outTradeNum = [[NSMutableString alloc] init];
- NSArray *strArr = [result componentsSeparatedByString:@"&"];
- for (NSString *trade in strArr) {
- if ([trade hasPrefix:@"out_trade_no"])
- {
- outNum = [trade componentsSeparatedByString:@"="][1];
- [outTradeNum appendString:outNum];
- [outTradeNum replaceOccurrencesOfString:@"\"" withString:@"" options:NSLiteralSearch range:NSMakeRange(0, outTradeNum.length)];
- DDLogVerbose(@"%@",outTradeNum);
- break;
- }
- }
- // 第一个参数传的是alipay返回给我的out_trade_id 异步回调二次验证
- [[TWTShoppingCartLogic sharedData] goToCheckOrder:outTradeNum complete:^(NSError *error, id data) {
- if (error)
- {
- [TWTAlertView showAlertViewWithTitle:nil message:@"网络数据异常,请稍后刷新" cancelOnTouch:NO cancelButtonTitle:nil doneButtonTitle:@"确定" doneBlock:^(void){
- [self.navigationController popViewControllerAnimated:YES];
- }];
- // 匹配不到就上报异常
- }
- else
- {
- [[TWTCommonAPILogic sharedData]reportData:nil forEventKey:@"PaySucceedVC_CallBack" number:@(1)];
- DSToast *toast = [[DSToast alloc] initWithText:@"支付成功" color:nil];
- [toast show];
- }
- }];
- }
- else
- {
- //8000 正在处理中 4000 订单支付失败 6001 用户中途取消/重复操作取消 6002 网络连接出错 ---> 从H回来
- // 弹出失败的界面,弹出之后的话就不支付界面消失,方便重新支付
- }
- }];
- }
- }];
- }
注意啦!!!
注意啦!!!
注意啦!!!
介绍下支付宝对我来说影响最大的一次
首先看看官方的调用接口,根据图来讲,我们就说方法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到最新了,而且我这里介绍的也是最新,就是改版之后的方法,老的不介绍了,理论上都要用最新的
嘛,如果你用旧的,那我也没办法
第二步
处理支付结果(有支付宝的情况下回调该方法)
- // 当用户通过其它应用启动本应用时,会回调这个方法,url参数是其它应用调用openURL:方法时传过来的
- - (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation
- {
- if ([url.host isEqualToString:@"safepay"]) {
- //跳转支付宝钱包进行支付,处理支付结果,该方法是当去支付的时候我的进程被杀死的时候调用这里的回调,不然就调用payorder的回调
- [[AlipaySDK defaultService] processOrderWithPaymentResult:url standbyCallback:^(NSDictionary *resultDic)
- {
- DDLogVerbose(@"点击支付获取的直接结果===>>>>>>reslut = %@",resultDic);
- NSString *result = resultDic[@"result"];
- NSString *resultStatus = resultDic[@"resultStatus"];
- //9000 订单支付成功
- // 支付完成需要把返回的outtradeID给解析出来,给服务器二次确认
- if ([resultStatus isEqualToString:@"9000"])
- {
- // "out_trade_no" = "\"74db120f0a8e5646ef5a30154e9f6deb\"";
- NSString *outNum = nil;
- NSMutableString *outTradeNum = [[NSMutableString alloc] init];
- NSArray *strArr = [result componentsSeparatedByString:@"&"];
- for (NSString *trade in strArr) {
- if ([trade hasPrefix:@"out_trade_no"])
- {
- outNum = [trade componentsSeparatedByString:@"="][1];
- [outTradeNum appendString:outNum];
- [outTradeNum replaceOccurrencesOfString:@"\"" withString:@"" options:NSLiteralSearch range:NSMakeRange(0, outTradeNum.length)];
- break;
- }
- }
- order.aliPayTrade = outTradeNum;
- // 第一个参数传的是alipay返回给我的out_trade_id 二次确认
- [[TWTShoppingCartLogic sharedData] goToCheckOrder:outTradeNum complete:^(NSError *error, id data) {
- if (error)
- {
- [TWTAlertView showAlertViewWithTitle:nil message:@"网络数据异常,请稍后刷新" cancelOnTouch:NO cancelButtonTitle:nil doneButtonTitle:@"确定" doneBlock:^(void){
- }];
- // 匹配不到就上报异常
- }
- else
- {
- [[TWTCommonAPILogic sharedData]reportData:nil forEventKey:@"PaySucceedVC_CallBack" number:@(1)];
- DSToast *toast = [[DSToast alloc] initWithText:@"支付成功" color:nil];
- [toast show];
- }];
- }
- else
- {
- //8000 正在处理中 4000 订单支付失败 6001 用户中途取消/重复操作取消 6002 网络连接出错
- }
- }];
- }
- return YES;
- }
这里有个iOS 9的API,反正没什么卵用
- // NOTE: 9.0以后使用新API接口
- - (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<NSString*, id> *)options
- {
第三步(小细节)
和微信支付一样,我们不能直接用同步返回的结果来判断是否正真支付成功(也是我写的微信支付详解链接)
按照官方的说法请看如下
好在支付宝和微信支付不同的地方在于,支付宝的返回数据中有带订单信息,我们就直接解析可以了,不需要像微信
一样只返回状态码,我们需要本地存起来,再和服务器二次校验
几个小小的坑
Cannot find interface declarationfor 'NSObject', superclass of'Base64'
‘rsa.h’ file not found
写的比较仓促,基本逻辑是写好了,注意的事项也差不多,如有漏的,或者不同意见的
请留言告诉我哦
有帮到你的帮忙点个赞,各位的认可是我分享的最大动力
相关文章:

LIVE555简介及在Windows上通过VS2013编译操作步骤
LIVE555是使用开放标准协议(RTP/RTCP, RTSP, SIP)形成的一组用于多媒体流C库。这些库支持的平台包括Unix(包括Linux和Mac OS X)、Windows和QNX(以及其它符号POSIX的系统)。这些库已经被用于实现的应用例如LIVE555媒体服务器、LIVE555代理服务器(RTSP服务器应用)以及vobStreamer…

GitHub App终于来了,iPhone用户可尝鲜,「同性交友」更加便捷
整理 | 夕颜出品 | AI科技大本营(ID:rgznai100)【导读】据外媒 VentureBeat 报道,在 11 月 13 日举行的 GitHub Universe 上,微软宣布了面向程序员和开发人员的一系列升级,包括针对 iOS 智能手机和 iPad 推出的 GitHub…
[NHibernate]代码生成器的使用
目录 写在前面 文档与系列文章 代码生成器的使用 总结 写在前面 前面的文章介绍了nhibernate的相关知识,都是自己手敲的代码,有时候显得特别的麻烦,比如你必须编写持久化类,映射文件等等,举得例子比较简单,…

RapidJSON简介及使用
RapidJSON是腾讯开源的一个高效的C JSON解析器及生成器,它是只有头文件的C库。RapidJSON是跨平台的,支持Windows, Linux, Mac OS X及iOS, Android。它的源码在https://github.com/Tencent/rapidjson/,稳定版本为2016年发布的1.1.0版本。 Rap…

高德地图关键字搜索oc版
.h文件 // MapSearchViewController.h // JMT // // Created by walker on 16/10/11. // Copyright © 2016年 BOOTCAMP. All rights reserved. // #import <UIKit/UIKit.h> #import <AMapNaviKit/MaMapKit.h> #import <AMapSearchKit/AMapSearchKit.h&…

同一个内容,对比Java、C、PHP、Python的代码量,结局意外了
为什么都说Python容易上手!是真的吗?都说Python通俗易懂,容易上手,甚至不少网友表示「完成同一个任务,C 语言要写 1000 行代码,Java 只需要写 100 行,而 Python 可能只要 20 行」到底是真的还是…

图片存储思考:
http://blog.csdn.net/liuruhong/article/details/4072386

LIVE555中RTSP客户端接收媒体流分析及测试代码
LIVE555中testProgs目录下的testRTSPClient.cpp代码用于测试接收RTSP URL指定的媒体流,向服务器端发送的命令包括:DESCRIBE、SETUP、PLAY、TERADOWN。 1. 设置使用环境:new一个BasicTaskScheduler对象;new一个BasicUsageEnvironm…

swift代理传值
比如我们这个场景,B要给A传值,那B就拥有代理属性, A就是B的代理,很简单吧!有代理那就离不开协议,所以第一步就是声明协议。在那里声明了?谁拥有代理属性就在那里声明,所以代码就是这…

重磅:腾讯正式开源图计算框架Plato,十亿级节点图计算进入分钟级时代
整理 | 唐小引 来源 | CSDN(ID:CSDNnews)腾讯开源进化 8 年,进入爆发期。 继刚刚连续开源 TubeMQ、Tencent Kona JDK、TBase、TKEStack 四款重点开源项目后,腾讯开源再次迎来重磅项目!北京时间 11 月 14 日…

类似ngnix的多进程监听用例
2019独角兽企业重金招聘Python工程师标准>>> 多进程监听适合于短连接,且连接间无交集的应用。前两天简单写了一个,在这里保存一下。 #include <sys/types.h>#include <stdarg.h>#include <signal.h>#include <unistd.h&…

今日头条李磊等最新论文:用于文本生成的核化贝叶斯Softmax
译者 | Raku 出品 | AI科技大本营(ID:rgznai100)摘要用于文本生成的神经模型需要在解码阶段具有适当词嵌入的softmax层,大多数现有方法采用每个单词单点嵌入的方式,但是一个单词可能具有多种意义,在不同的背景下&#…

FFmpeg中RTSP客户端拉流测试代码
之前在https://blog.csdn.net/fengbingchun/article/details/91355410中给出了通过LIVE555实现拉流的测试代码,这里通过FFmpeg来实现,代码量远小于LIVE555,实现模块在libavformat。 在4.0及以上版本中,FFmpeg有了些变动ÿ…

虚拟机下运行linux通过nat模式与主机通信、与外网连接
首先:打开虚拟机的编辑菜单下的虚拟网络编辑器,选中VMnet8 NAT模式。通过NAT设置获取网关IP,通过DHCP获取可配置的IP区间。同时,将虚拟机的虚拟机菜单的设置选项中的网络适配器改为NAT模式。即可! 打开linux࿰…

远程过程调用RPC简介
RPC(Remote Procedure Call, 远程过程调用):是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的思想。 RPC是一种技术思想而非一种规范或协议,常见RPC技术和框架有: (1). 应用级的服务框架:阿里的…
iOS开发:沙盒机制以及利用沙盒存储字符串、数组、字典等数据
iOS开发:沙盒机制以及利用沙盒存储字符串、数组、字典等数据 1、初识沙盒:(1)、存储在内存中的数据,程序关闭,内存释放,数据就会丢失,这种数据是临时的。要想数据永久保存,将数据保存成文件&am…

支撑亿级用户“刷手机”,百度Feed流背后的新技术装备有多牛?
导读:截止到2018年底,我国网民使用手机上网的比例已高达98.6%,移动互联网基本全方位覆盖。智能手机的操作模式让我们更倾向于通过简单的“划屏”动作,相对于传统的文本交互方式来获取信息,用户更希望一拿起手机就能刷到…

玩转高性能超猛防火墙nf-HiPAC
中华国学,用英文讲的,稀里糊涂听了个大概,不得不佩服西方人的缜密的逻辑思维,竟然把玄之又玄的道家思想说的跟牛顿定律一般,佩服。归家,又收到了邮件,还是关于nf-hipac的,不知不觉就…

ios 沙盒 plist 数据的读取和存储
plist 只能存储基本的数据类型 和 array 字典 [objc] view plaincopy - (void)saveArray { // 1.获得沙盒根路径 NSString *home NSHomeDirectory(); // 2.document路径 NSString *docPath [home stringByAppendingPathComponent:"Document…

FFmpeg实现获取USB摄像头视频流测试代码
通过USB摄像头(注:windows7/10下使用内置摄像头,linux下接普通的usb摄像头(Logitech))获取视频流用到的模块包括avformat和avdevice。头文件仅include avdevice.h即可,因为avdevice.h中会include avformat.h。libavdevice库是libavformat的一…

重磅!明略发布数据中台战略和三大解决方案
11月15日,明略科技在上海举办以“FASTER 聚变增长新动力”为主题的2019数据智能峰会,宣布“打造智能时代的企业中台”新战略,同时推出了两大新产品“新一代数据中台”和“营销智能平台”,以及三大行业解决方案,分别是“…

Android程序完全退出的三种方法
1. Dalvik VM的本地方法 android.os.Process.killProcess(android.os.Process.myPid()) //获取PID,目前获取自己的也只有该API,否则从/proc中自己的枚举其他进程吧,不过要说明的是,结束其他进程不一定有权限,不然就…

FFmpeg通过摄像头实现对视频流进行解码并显示测试代码(旧接口)
这里通过USB摄像头(注:windows7/10下使用内置摄像头,linux下接普通的usb摄像头(Logitech))获取视频流,然后解码,最后再用opencv显示。用到的模块包括avformat、avcodec和avdevice。libavdevice库是libavformat的一个补充库(comple…

IOS数据存储之文件沙盒存储
前言: 之前学习了数据存储的NSUserDefaults,归档和解档,对于项目开发中如果要存储一些文件,比如图片,音频,视频等文件的时候就需要用到文件存储了。文件沙盒存储主要存储非机密数据,大的数据。 …
剖析Focal Loss损失函数: 消除类别不平衡+挖掘难分样本 | CSDN博文精选
作者 | 图像所浩南哥来源 | CSDN博客论文名称:《 Focal Loss for Dense Object Detection 》论文下载:https://arxiv.org/pdf/1708.02002.pdf论文代码:https://github.com/facebookresearch/Detectron/tree/master/configs/12_2017_baselines…

windows下mysql开启慢查询
mysql在windows系统中的配置文件一般是my.ini,我的路径是c:\mysql\my.ini,你根据自己安装mysql路径去查找[mysqld]#The TCP/IP Port the MySQL Server will listen onport3306#开启慢查询log-slow-queries E:\Program Files\MySQL\MySQL Server 5.5\mysql_slow_query.loglong_…

FFmpeg通过摄像头实现对视频流进行解码并显示测试代码(新接口)
在https://blog.csdn.net/fengbingchun/article/details/93975325 中给出了通过旧接口即FFmpeg中已废弃的接口实现通过摄像头获取视频流然后解码并显示的测试代码,这里通过使用FFmpeg中的新接口再次实现通过的功能,主要涉及到的接口函数包括:…

iOS经典讲解之获取沙盒文件路径写入和读取简单对象
#import "RootViewController.h" interface RootViewController () end 实现文件: implementation RootViewController - (void)viewDidLoad { [super viewDidLoad]; [self path]; [self writeFile]; [self readingFi…
Google最新论文:Youtube视频推荐如何做多目标排序
作者 | 深度传送门来源 | 深度传送门(ID:deep_deliver)导读:本文是“深度推荐系统”专栏的第十五篇文章,这个系列将介绍在深度学习的强力驱动下,给推荐系统工业界所带来的最前沿的变化。本文主要介绍下Google在RecSys …

Jmeter 笔记
Apache JMeter是Apache组织开发的基于Java的压力测试工具。用于对软件做压力测试,它最初被设计用于Web应用测试但后来扩展到其他测试领域。 它可以用于测试静态和动态资源例如静态文件、Java 小服务程序、CGI 脚本、Java 对象、数据库, FTP 服务器&#…