首页 > 其他分享 >iOS支付宝支付集成

iOS支付宝支付集成

时间:2023-06-08 19:02:33浏览次数:54  
标签:集成 支付宝 object iOS resultDic NSString 支付 order


概述


iOS支付宝支付集成


详细




支付宝和微信都是业界的老大哥,相信大家都有所觉得文档、SDK都是各种坑吧(纯粹吐槽而已),本文先整理支付宝支付集成。

一、准备工作

1、向支付宝”签约" 成为支付宝的”商户”, 签约完成后, 支付宝会提供一些必要的数据给我们(商户ID-partner,帐号ID-支付宝帐号)

注意:签约成为支付宝商户,需要提供公司营业执照[http://act.life.alipay.com/shopping/before/help/index.html](http://act.life.alipay.com/shopping/before/help/index.html)

2、获取支付相关的 '私钥' 和 '密钥'

[https://doc.open.alipay.com/doc2/detail?treeId=44&articleId=103242&docType=1](https://doc.open.alipay.com/doc2/detail?treeId=44&articleId=103242&docType=1)

3、下载支付的SDK

[https://doc.open.alipay.com/doc2/detail?treeId=54&articleId=103419&docType=1](https://doc.open.alipay.com/doc2/detail?treeId=54&articleId=103419&docType=1)

二、集成支付宝SDK步骤

1、从官方Demo中把红色标注的文件添加进入项目中,记得选copy;

iOS支付宝支付集成_Scheme


2、

点击项目名称,点击“Build Phases”选项卡,在“Link Binary with Librarles” 选项中,新增“AlipaySDK.framework”和“SystemConfiguration.framework” 两个系统库文件。如果项目中已有这两个库文件,可不必再增加;

添加下图中的库:

iOS支付宝支付集成_支付宝支付集成_02

localhost:alipay mac$ ls
APAuthV2Info.h        Order.h            libssl.a
APAuthV2Info.m        Order.m            openssl
AlipaySDK.bundle    Util
AlipaySDK.framework    libcrypto.a
导入系统库
SystemConfiguration.framework


3、

添加Pch文件新建pch成功后,在pch文件中添加#import然后按照下图所示,进行修改pch的文件路径

也可以不设置,我这个是我需要设置#import <UIKit/UIKit.h> #import <Foundation/Foundation.h>,也可以不用使用,只在当前文件里添加相对应的使用即可,但是这样针对整个项目来说方便些

iOS支付宝支付集成_Scheme_03


4、

修改SDK路径完成以上两步之后,会发现出现了一个经典的错误,找不到:#include解决这个问题,需要在Header Search Path中配置SDK中的点a(libssl.a/libcrypto.a)文件所在的路径,找到之后设置好正确的路径

iOS支付宝支付集成_iOS_04

点击项目名称,点击“Build Settings”选项卡,在搜索框中,以关键字“search” 搜索,对“Header Search Paths”增加头文件路径:“$(SRCROOT)/项目名称/IntegratedAlipay/AlipayFiles”(注意:不包括引号,如果不是放到项目根目录下,请在项目名称后面加上相应的目录名);

iOS支付宝支付集成_iOS_05

根据你文件位置,我的是:

“$(SRCROOT)/QTXStudent/Classes/Alipay/AlipayFiles”


5、 为URL Types 添加支付宝回调scheme

点击项目名称,点击“Info”选项卡,在URL types里面添加一项,Identifier可以不填,URL schemes必须和appScheme的值相同,用于支付宝处理回到应用的事件;

为URL Types 添加支付宝回调scheme

iOS支付宝支付集成_支付宝_06


6、在工程项目的plist文件中添加

iOS 9以后的系统需要添加支付宝分享的scheme到白名单中,scheme名为alipayshare

按如下形式添加即可:

iOS支付宝支付集成_字符串_07


7、在AppDelegate中处理事件回调:

/**
 这里处理微信/支付宝支付完成之后跳转回来
 */
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation
{
    //如果极简 SDK 不可用,会跳转支付宝钱包进行支付,需要将支付宝钱包的支付结果回传给 SDK
    if ([url.host isEqualToString:@"safepay"]) {
        //跳转支付宝钱包进行支付,处理支付结果
        [[AlipaySDK defaultService] processOrderWithPaymentResult:url standbyCallback:^(NSDictionary *resultDic) {
            NSLog(@"支付宝客户端支付结果result = %@",resultDic);
            if (resultDic && [resultDic objectForKey:@"resultStatus"] && ([[resultDic objectForKey:@"resultStatus"] intValue] == 9000)) {
                
                // 发通知带出支付成功结果
                [[NSNotificationCenter defaultCenter] postNotificationName:ZLAliReturnSucceedPayNotification object:resultDic];
            } else {
                
                // 发通知带出支付失败结果
                [[NSNotificationCenter defaultCenter] postNotificationName:ZLAliReturnFailedPayNotification object:resultDic];
            }
            
        }];
    }
    
    if ([url.host isEqualToString:@"platformapi"]){//支付宝钱包快登授权返回 authCode
        [[AlipaySDK defaultService] processAuthResult:url standbyCallback:^(NSDictionary *resultDic) {
            NSLog(@"支付宝网页版result = %@",resultDic);
            if (resultDic && [resultDic objectForKey:@"resultStatus"] && ([[resultDic objectForKey:@"resultStatus"] intValue] == 9000)) {
                
                // 发通知带出支付成功结果
                [[NSNotificationCenter defaultCenter] postNotificationName:ZLAliReturnSucceedPayNotification object:resultDic];
            } else {
                
                // 发通知带出支付失败结果
                [[NSNotificationCenter defaultCenter] postNotificationName:ZLAliReturnFailedPayNotification object:resultDic];
            }
        }];
    }
    
    return YES;
}

// NOTE: 9.0以后使用新API接口
- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<NSString*, id> *)options
{
    
    //如果极简 SDK 不可用,会跳转支付宝钱包进行支付,需要将支付宝钱包的支付结果回传给 SDK
    if ([url.host isEqualToString:@"safepay"]) {
        //跳转支付宝钱包进行支付,处理支付结果
        [[AlipaySDK defaultService] processOrderWithPaymentResult:url standbyCallback:^(NSDictionary *resultDic) {
            NSLog(@"支付宝客户端支付结果result = %@",resultDic);
            if (resultDic && [resultDic objectForKey:@"resultStatus"] && ([[resultDic objectForKey:@"resultStatus"] intValue] == 9000)) {
                
                // 发通知带出支付成功结果
                [[NSNotificationCenter defaultCenter] postNotificationName:ZLAliReturnSucceedPayNotification object:resultDic];
            } else {
                
                // 发通知带出支付失败结果
                [[NSNotificationCenter defaultCenter] postNotificationName:ZLAliReturnFailedPayNotification object:resultDic];
            }
        }];
    }
    
    if ([url.host isEqualToString:@"platformapi"]){//支付宝钱包快登授权返回 authCode
        [[AlipaySDK defaultService] processAuthResult:url standbyCallback:^(NSDictionary *resultDic) {
            NSLog(@"支付宝网页版result = %@",resultDic);
            if (resultDic && [resultDic objectForKey:@"resultStatus"] && ([[resultDic objectForKey:@"resultStatus"] intValue] == 9000)) {
                
                // 发通知带出支付成功结果
                [[NSNotificationCenter defaultCenter] postNotificationName:ZLAliReturnSucceedPayNotification object:resultDic];
            } else {
                
                // 发通知带出支付失败结果
                [[NSNotificationCenter defaultCenter] postNotificationName:ZLAliReturnFailedPayNotification object:resultDic];
            }
        }];
    }
    
    return YES;
}


8、 在需要用的地方导入“AlipayHeader.h”,并使用“[AlipayRequestConfig alipayWithPartner:...”方法进行支付;

/**
 *  配置请求信息,仅有变化且必要的参数
 *
 *  @param partner            合作者身份ID 以 2088 开头由 16 位纯数字组成的字符串。
 *  @param sellerID           卖家支付宝账号 以 2088 开头由 16 位纯数字组成的字符串。
 *  @param outTradeNO         商户网站唯一订单号
 *  @param subject            商品名称
 *  @param body               商品详情
 *  @param totalFee           总金额
 *  @param notifyURL          服务器异步通知页面路径
 *  @param itBPay             未付款交易的超时时间
 */
+ (void)alipayWithPartner:(NSString *)partner
                 sellerID:(NSString *)sellerID
               outTradeNO:(NSString *)outTradeNO
                  subject:(NSString *)subject
                     body:(NSString *)body
                 totalFee:(NSString *)totalFee
                notifyURL:(NSString *)notifyURL;

仅含有变化的参数:

+ (void)alipayWithPartner:(NSString *)partner
                 sellerID:(NSString *)sellerID
               outTradeNO:(NSString *)outTradeNO
                  subject:(NSString *)subject
                     body:(NSString *)body
                 totalFee:(NSString *)totalFee
                notifyURL:(NSString *)notifyURL {
    
    [self alipayWithPartner:partner sellerID:sellerID outTradeNO:outTradeNO subject:subject body:body totalFee:totalFee notifyURL:aliNotifyURL service:@"mobile.securitypay.pay" paymentType:@"1" inputCharset:@"utf-8" itBPay:@"30m" privateKey:aliPrivateKey appScheme:aliAppScheme];
    
}

包含所有必要的参数:

+ (void)alipayWithPartner:(NSString *)partner
                 sellerID:(NSString *)sellerID
                  outTradeNO:(NSString *)outTradeNO
                  subject:(NSString *)subject
                     body:(NSString *)body
                 totalFee:(NSString *)totalFee
                notifyURL:(NSString *)notifyURL
                  service:(NSString *)service
              paymentType:(NSString *)paymentType
             inputCharset:(NSString *)inputCharset
                   itBPay:(NSString *)itBPay
               privateKey:(NSString *)privateKey
                appScheme:(NSString *)appScheme {
    
    Order *order = [Order order];
    order.partner = partner;
    order.sellerID = sellerID;
    order.outTradeNO = outTradeNO;
    order.subject = subject;
    order.body = body;
    order.totalFee = totalFee;
    order.notifyURL = notifyURL;
    order.service = service;
    order.paymentType = paymentType;
    order.inputCharset = inputCharset;
    order.itBPay = itBPay;
    
    
    // 将商品信息拼接成字符串
    NSString *orderSpec = [order description];
    
    // 获取私钥并将商户信息签名,外部商户可以根据情况存放私钥和签名,只需要遵循 RSA 签名规范, 并将签名字符串 base64 编码和 UrlEncode
    
    NSString *signedString = [self genSignedStringWithPrivateKey:aliPrivateKey OrderSpec:orderSpec];
    
    // 调用支付接口
    [self payWithAppScheme:appScheme orderSpec:orderSpec signedString:signedString];
}

生成signedString:

+ (NSString *)genSignedStringWithPrivateKey:(NSString *)privateKey OrderSpec:(NSString *)orderSpec {
    
    // 获取私钥并将商户信息签名,外部商户可以根据情况存放私钥和签名,只需要遵循 RSA 签名规范, 并将签名字符串 base64 编码和 UrlEncode
    id<DataSigner> signer = CreateRSADataSigner(privateKey);
    return [signer signString:orderSpec];
}

支付:

+ (void)payWithAppScheme:(NSString *)appScheme orderSpec:(NSString *)orderSpec signedString:(NSString *)signedString {
    
    // 将签名成功字符串格式化为订单字符串,请严格按照该格式
    NSString *orderString = nil;
    if (signedString != nil) {
        orderString = [NSString stringWithFormat:@"%@&sign=\"%@\"&sign_type=\"%@\"", orderSpec, signedString, @"RSA"];
        [[AlipaySDK defaultService] payOrder:orderString fromScheme:appScheme callback:^(NSDictionary *resultDic) { // 网页版
            NSLog(@"支付宝支付结果 reslut = %@", resultDic);
            
            // 返回结果需要通过 resultStatus 以及 result 字段的值来综合判断并确定支付结果。 在 resultStatus=9000,并且 success="true"以及 sign="xxx"校验通过的情况下,证明支付成功。其它情况归为失败。较低安全级别的场合,也可以只通过检查 resultStatus 以及 success="true"来判定支付结果
            
            if (resultDic && [resultDic objectForKey:@"resultStatus"] && ([[resultDic objectForKey:@"resultStatus"] intValue] == 9000)) {
                
                // 发通知带出支付成功结果
                [ZLNotificationCenter postNotificationName:QTXAliReturnSucceedPayNotification object:resultDic];
            } else {
                
                // 发通知带出支付失败结果
                [ZLNotificationCenter postNotificationName:QTXAliReturnFailedPayNotification object:resultDic];
            }
        }];
    }
    
}


9、

在本头文件中设置aliPartnerID、aliSellerAccount、aliNotifyURL、aliAppScheme和aliPrivateKey的值(所有的值在支付宝回复的邮件里面:注意,建议除appScheme以外的字段都从服务器请求);

这时候,我们支付就直接一句话搞定:

// 支付宝支付
    [AlipayRequestConfig alipayWithPartner:aliPartnerID sellerID:aliSellerAccount outTradeNO:[self generateTradeNO] subject:@"测试" body:@"支付宝支付" totalFee:@"0.01" notifyURL:aliNotifyURL]; // notifyURL: 回调url@"http://www.xxx.com"
    
    [ZLNotificationCenter addObserver:self selector:@selector(paySucceed) name:ZLAliReturnSucceedPayNotification object:nil];
    [ZLNotificationCenter addObserver:self selector:@selector(payFailed) name:ZLAliReturnFailedPayNotification object:nil];


10、建议除appScheme以外的字段都从服务器请求!

建议除appScheme以外的字段都从服务器请求!建议除appScheme以外的字段都从服务器请求!

PS:重要的事情说三遍!!!

上面的第七步和第八步建议不要使用,直接用第九步去替代!建议除appScheme以外的字段都从服务器请求!


如果后台给你一个接口返回那些参数了,你就不用客户端去加密算法,只负责请求后台拿到这些参数再去请求支付宝即可.

下面例子是支付宝的拼接方式,请按照当前版本的相对应的拼接方式来.

// 支付宝支付
- (void)alipayPay {
    
    NSMutableDictionary *params = [NSMutableDictionary dictionary];
    params[@"orderNo"] = self.orderNo; // 订单号
    params[@"realAmt"] =  [NSString stringWithFormat:@"%.2lf", self.realAmt]; // 金额
    
    __weak __typeof(self) weakSelf = self;
    [QTXHttpTool post:QTX_aliPay_url params:params success:^(id json) {
        QTXLog(@"支付宝支付返回参数接口 请求成功-%@", json);
        
        if ([json[@"success"] isEqual:@(YES)]) {
            
            // 返回生成订单信息及签名
            NSString *signedString = json[@"data"][@"sign"];
            NSString *orderInfoEncoded = json[@"data"][@"orderInfo"];
            
            // NOTE: 如果加签成功,则继续执行支付
            if (signedString != nil) {
                // NOTE: 将签名成功字符串格式化为订单字符串,请严格按照该格式
//                NSString *orderString = [NSString stringWithFormat:@"%@&sign=%@&sign_type=RSA", orderInfoEncoded, signedString];
                NSString *orderString = [NSString stringWithFormat:@"%@&sign=\"%@\"&sign_type=\"%@\"",
                               orderInfoEncoded, signedString, @"RSA"];
                
                // NOTE: 调用支付结果开始支付
                [[AlipaySDK defaultService] payOrder:orderString fromScheme:XHHAppScheme callback:^(NSDictionary *resultDic) {
                   QTXLog(@"reslut = %@",resultDic);
                    
                    if ([resultDic[@"resultStatus"] intValue] == 9000) {
                        
                        [QTXNotificationCenter addObserver:self selector:@selector(paySucceed) name:QTXWXReturnSucceedPayNotification object:nil];
                    } else {
                        
                        [QTXNotificationCenter addObserver:self selector:@selector(payFailed) name:QTXWXReturnFailedPayNotification object:nil];
                    }
                }];
                
            }
            
        } else {
            [MBProgressHUD showError:[NSString stringWithFormat:@"%@", json[@"errorMessage"]]];
        }
        
    } failure:^(NSError *error) {
        
        [MBProgressHUD showError:@"暂无网络,稍后再试"];
        QTXLog(@"支付宝支付返回参数接口 请求失败-%@", error);
    }];
    
}


11、支付宝集成失败相关问题

1. 报错 AL159

查看金额是否是两位小数,切不可拼接"元"

2. 报错“创建交易异常,请重新创建后再付款”

返回的状态码是“6001”,取消支付

当是用公司注册支付宝App时分配的商户账号登陆的支付宝,进行支付测试的。支付宝那边检测到是商户而不是普通的支付账号,商户支付给商户自己,所以支付失败!

三、其他补充

1、压缩文件截图

iOS支付宝支付集成_字符串_08

2、Alipay 包截图

iOS支付宝支付集成_支付宝支付集成_09


目前是项目中直接操作, 在AlipayHeader.h文件里补充上你们项目的aliPartnerID, aliSellerAccount, aliNotifyURL, 具体可参考代码, 项目则能够直接运行!





标签:集成,支付宝,object,iOS,resultDic,NSString,支付,order
From: https://blog.51cto.com/u_7583030/6442290

相关文章

  • 一文讲透支付宝沙箱的基本应用
    作者主页:编程指南针 作者简介:Java领域优质创作者、多年架构师设计经验、腾讯课堂常驻讲师主要内容:Java项目、毕业设计、简历模板、学习资料、面试题库、技术互助文末获取源码  很多同学在进行毕业设计或课程设计时会开发一些相应的商城系统,都有在线支付的相关需求,而做为个人,想在......
  • springMVC集成缓存框架Ehcache
    概述Ehcache算是当前比较流行的缓存框架,使用缓存可以极大的缓解服务器和数据库的压力,提高访问效率,提高服务器的并发能力。接下来我们看怎么把缓存在springmvc种使用起来。详细Ehcache算是当前比较流行的缓存框架,使用缓存可以极大的缓解服务器和数据库的压力,提高访问......
  • xxl-job的部署及springboot集成使用
    介绍XXL-Job是一个分布式任务调度平台,可进行任务调度、管理和监控,并提供任务分片、失败重试、动态分配等功能。它是一个开源项目,基于SpringBoot和Quartz开发,支持常见的任务调度场景。XXL-Job的使用相对简单,只需要简单配置即可实现任务调度。同时,它提供了丰富的管理和监控功能,可以......
  • linux iostat命令
    作者:天之翼Linux系统出现了性能问题,一般我们可以通过top、iostat、free、vmstat等命令来查看初步定位问题。其中iostat可以给我们提供丰富的IO状态数据。基本使用$iostat-d-k110参数-d表示,显示设备(磁盘)使用状态;-k某些使用block为单位的列强制使用Kilobytes为单位;110......
  • uniapp打包所需的ios证书和证书profile文件获取的图文教程
    使用uniapp进行云打包,可以打包android和ios两种app,但是uniapp官方并不能凭空产生这两种平台所需的打包证书。那么这两种打包证书又是如何获取呢?android相对简单,使用jdk的工具生成就可以了,也可以使用香蕉云编来一键生成。但是ios证书的生成就没有这么简单,因为ios证书的生成需要......
  • iOS系统安全机制
    引言在开发过程中,经常会遇到这么一些问题:修改App结构后无法运行不能直接读取其他应用程序程序每次运行地址都不一样系统升级了不允许降级带着这些问题,我们来学习一下,iOS系统提供的安全机制。iOS系统安全架构&emsp;&emsp;上图是苹果官方的iOS系统安全架构图,他分为两个部分,第一个部分......
  • 6-8|如何使用Python语言开发IOS混淆工具
    在iOS开发中,混淆工具主要用于保护代码的安全性,避免别人通过反编译等手段获取到关键代码。Python语言是一门高效、易于编写和调试的开发语言,可以用它来编写iOS混淆工具。下面是一个简单的示例代码,用Python实现对Objective-C代码进行简单的混淆。```pythonimportosimportrandom......
  • linux环境下jenkins搭建过程+Flutter打包集成
    安装jenkins配置java环境,androidsdk环境,flutter环境配置flutter自动打包脚本安装jenkins1.下载jenkins安装包首先下载jenkins安装包,官网下载地址:https://www.jenkins.io/download/,如果嫌太慢可以使用镜像下载:http://mirrors.jenkins-ci.org/解压并安装jenkinsrpm-......
  • AUTOSAR笔记:工程代码集成与调试(七)
    目录工程代码架构、集成方法代码编译链接代码调试MCU可执行文件下载完成AUTOSAR系统级、ECU级、SWC级相关开发和代码生成后,需要进行代码集成与调试。本文对AUTOSAR工程代码架构、集成、编译链接、调试方法进行简单介绍。工程代码架构、集成方法一套完整的符合AUTOSAR规范的ECU......
  • VMware ESXi 6.7 U3 Final Unlocker & OEM BIOS 集成 REALTEK 网卡驱动和 NVMe 驱动 (
    VMwareESXi6.7U3Final最终版,集成驱动版。此版本解决的问题:VMwareHostClient无法将现有虚拟磁盘(VMDK)附加到虚拟机请访问原文链接:https://sysin.org/blog/vmware-esxi-6-sysin/,查看最新版。原创作品,转载请保留出处。作者主页:sysin.org2023-02-28,发布一个UIfix版......