iOS支付宝支付(Alipay)详细接入

2023-11-30 05:38

本文主要是介绍iOS支付宝支付(Alipay)详细接入,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

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

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

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

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


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

支付宝同一订单号产生多个不同out_trade_no的问题,同步状态码是否要post给服务器的问题已经更新在了上面微信支付的文章中,需要的去看吧



前期准备

首先商户要去支付宝申请,得到一个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
{// 配置好的回调schemeNSString *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那里的Blockif ([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'


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


‘rsa.h’ file not found
这个问题就是步骤五提到的了,如图解决



其实,你只要按我的步骤来,交给服务器签名,做我们App该做的事,基本就没有什么问题


总结一下
1.导入Demo中框架,相关库,配置pch文件以及openssl文件路径
2.配置URL Scheme
3.把签名交给服务器
4.注意改版前后的回调机制,最好保持最新的,最新的逻辑更清晰
5.和微信一样,同步返回的结果记得二次确认,和后台约定好解析字段


官方Demo:点击打开链接
微信支付接入分析:点击打开链接

这篇关于iOS支付宝支付(Alipay)详细接入的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/435829

相关文章

Python与MySQL实现数据库实时同步的详细步骤

《Python与MySQL实现数据库实时同步的详细步骤》在日常开发中,数据同步是一项常见的需求,本篇文章将使用Python和MySQL来实现数据库实时同步,我们将围绕数据变更捕获、数据处理和数据写入这... 目录前言摘要概述:数据同步方案1. 基本思路2. mysql Binlog 简介实现步骤与代码示例1

基于C#实现PDF转图片的详细教程

《基于C#实现PDF转图片的详细教程》在数字化办公场景中,PDF文件的可视化处理需求日益增长,本文将围绕Spire.PDFfor.NET这一工具,详解如何通过C#将PDF转换为JPG、PNG等主流图片... 目录引言一、组件部署二、快速入门:PDF 转图片的核心 C# 代码三、分辨率设置 - 清晰度的决定因

Java中HashMap的用法详细介绍

《Java中HashMap的用法详细介绍》JavaHashMap是一种高效的数据结构,用于存储键值对,它是基于哈希表实现的,提供快速的插入、删除和查找操作,:本文主要介绍Java中HashMap... 目录一.HashMap1.基本概念2.底层数据结构:3.HashCode和equals方法为什么重写Has

Java使用正则提取字符串中的内容的详细步骤

《Java使用正则提取字符串中的内容的详细步骤》:本文主要介绍Java中使用正则表达式提取字符串内容的方法,通过Pattern和Matcher类实现,涵盖编译正则、查找匹配、分组捕获、数字与邮箱提... 目录1. 基础流程2. 关键方法说明3. 常见场景示例场景1:提取所有数字场景2:提取邮箱地址4. 高级

Unity新手入门学习殿堂级知识详细讲解(图文)

《Unity新手入门学习殿堂级知识详细讲解(图文)》Unity是一款跨平台游戏引擎,支持2D/3D及VR/AR开发,核心功能模块包括图形、音频、物理等,通过可视化编辑器与脚本扩展实现开发,项目结构含A... 目录入门概述什么是 UnityUnity引擎基础认知编辑器核心操作Unity 编辑器项目模式分类工程

Springboot项目构建时各种依赖详细介绍与依赖关系说明详解

《Springboot项目构建时各种依赖详细介绍与依赖关系说明详解》SpringBoot通过spring-boot-dependencies统一依赖版本管理,spring-boot-starter-w... 目录一、spring-boot-dependencies1.简介2. 内容概览3.核心内容结构4.

MySQL中优化CPU使用的详细指南

《MySQL中优化CPU使用的详细指南》优化MySQL的CPU使用可以显著提高数据库的性能和响应时间,本文为大家整理了一些优化CPU使用的方法,大家可以根据需要进行选择... 目录一、优化查询和索引1.1 优化查询语句1.2 创建和优化索引1.3 避免全表扫描二、调整mysql配置参数2.1 调整线程数2.

Java实现TXT文件导入功能的详细步骤

《Java实现TXT文件导入功能的详细步骤》在实际开发中,很多应用场景需要将用户上传的TXT文件进行解析,并将文件中的数据导入到数据库或其他存储系统中,本文将演示如何用Java实现一个基本的TXT文件... 目录前言1. 项目需求分析2. 示例文件格式3. 实现步骤3.1. 准备数据库(假设使用 mysql

MySQL 临时表创建与使用详细说明

《MySQL临时表创建与使用详细说明》MySQL临时表是存储在内存或磁盘的临时数据表,会话结束时自动销毁,适合存储中间计算结果或临时数据集,其名称以#开头(如#TempTable),本文给大家介绍M... 目录mysql 临时表详细说明1.定义2.核心特性3.创建与使用4.典型应用场景5.生命周期管理6.注

在 Spring Boot 中连接 MySQL 数据库的详细步骤

《在SpringBoot中连接MySQL数据库的详细步骤》本文介绍了SpringBoot连接MySQL数据库的流程,添加依赖、配置连接信息、创建实体类与仓库接口,通过自动配置实现数据库操作,... 目录一、添加依赖二、配置数据库连接三、创建实体类四、创建仓库接口五、创建服务类六、创建控制器七、运行应用程序八