iOS 微信支付开发(最新版)

1. 介绍

本文为以前做的项目总结,由于相关支付 SDK 迭代,原文已经不满足需求,故作如下更新,供大家参考,另外增加常见问题总结。

项目中要用到支付功能,需要支付宝支付、微信支付、银联支付、Apple_pay,所以打算总结一下,方便以后的查阅,也方便大家, 用到的地方避免再次被坑。

今天我们就主要介绍一下微信支付,其他支付介绍后面会尽快更新出来。

集成前首先要看看文档,微信支付开发文档里面有详细的字段和说明。 微信支付是需要签名的,跟支付宝一样,可以在客户端签名,也可以在后台签名(当然,为了安全还是推荐在服务器上做签名,逻辑也比较好理解)

加微信:FBY-fan 领源码

2. 业务流程

以下是交互时序图,统一下单API、支付结果通知API和查询订单API等都涉及签名过程,调用都必须在商户服务器端完成。

交互时序图

商户系统和微信支付系统主要交互说明:

    1. 用户在商户APP中选择商品,提交订单,选择微信支付。
    1. 商户后台收到用户支付单,调用微信支付统一下单接口。
    1. 统一下单接口返回正常的prepay_id,再按签名规范重新生成签名后,将数据传输给APP。参与签名的字段名为appid,partnerid,prepayid,noncestr,timestamp,package。
    1. 商户APP调起微信支付。
    1. 商户后台接收支付通知。
    1. 商户后台查询支付结果。

3. 下载微信SDK

如果集成了友盟分享里的微信,那就不用下载,也不用配置环境,因为配置友盟分享的时候已经把微信支付的环境都配置好了(包括框架,schema跳转,白名单)如果没有集成过友盟分享那么请到微信开放平台下载SDK

下载微信SDK

建议把iOS头文件和支付示例都下载下来

4. 导入库集成 SDK

4.1 导入 SDK 库

导入上面那个iOS头文件和库下载下载出来的SDK包的就行,然后需要链接上依赖库,在Target —> BuildPhases —> Link Binary With Libraries— 点击+号 -> 搜索你需要的系统库。

  • SystemConfiguration.framework
  • libz.tbd
  • libsqlite3.0.tbd
  • CoreTelephony.framework
  • QuartzCore.framework

导入SDK库

4.2 设置URL Scheme

商户在微信开放平台申请开发APP应用后,微信开放平台会生成APP的唯一标识APPID,在APP端开发步骤里面说得很清楚了,需要填在URL Schemes这个地方。

URL Scheme

4.3 在Appdelegate中注册APPID

首先要在Appdelegate中引用头文件

1//微信支付 2#import "WXApi.h"

然后注册APPID

1- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 2 3// 向微信终端注册ID 4 5 [WXApi registerApp:@"wxd930ea5d5a258f4f"]; 6 7 return YES; 8}

在支付成功之后,支付结果返回,需要获取url,也需要在Appdelegate中完成,代码如下:

1- (BOOL)application:(UIApplication *)application 2 openURL:(NSURL *)url 3 sourceApplication:(NSString *)sourceApplication 4 annotation:(id)annotation { 5 6 if ([url.host isEqualToString:@"safepay"]) { 7 //跳转支付宝钱包进行支付,处理支付结果 8 [[AlipaySDK defaultService] processOrderWithPaymentResult:url standbyCallback:^(NSDictionary *resultDic) { 9 NSLog(@"result = %@",resultDic); 10 }]; 11 }else if ([url.host isEqualToString:@"pay"]) { 12 // 处理微信的支付结果 13 [WXApi handleOpenURL:url delegate:self]; 14 } 15 return YES; 16} 17 18// NOTE: 9.0以后使用新API接口 19- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<NSString*, id> *)options 20{ 21 if ([url.host isEqualToString:@"safepay"]) { 22 //跳转支付宝钱包进行支付,处理支付结果 23 [[AlipaySDK defaultService] processOrderWithPaymentResult:url standbyCallback:^(NSDictionary *resultDic) { 24 NSLog(@"result = %@",resultDic); 25 }]; 26 }else if ([url.host isEqualToString:@"pay"]) { 27 // 处理微信的支付结果 28 [WXApi handleOpenURL:url delegate:self]; 29 } 30 return YES; 31}

微信SDK自带的方法,处理从微信客户端完成操作后返回程序之后的回调方法,显示支付结果的:

1-(void) onResp:(BaseResp*)resp 2{ 3 //启动微信支付的response 4 NSString *payResoult = [NSString stringWithFormat:@"errcode:%d", resp.errCode]; 5 if([resp isKindOfClass:[PayResp class]]){ 6 //支付返回结果,实际支付结果需要去微信服务器端查询 7 switch (resp.errCode) { 8 case 0: 9 payResoult = @"支付结果:成功!"; 10 break; 11 case -1: 12 payResoult = @"支付结果:失败!"; 13 break; 14 case -2: 15 payResoult = @"用户已经退出支付!"; 16 break; 17 default: 18 payResoult = [NSString stringWithFormat:@"支付结果:失败!retcode = %d, retstr = %@", resp.errCode,resp.errStr]; 19 break; 20 } 21 } 22}

4.4 调用支付接口

在调用微信支付类里面,首先增加头文件引用。

#import "WXApi.h"

在调起支付的方法中,需要上传的参数包括:appid、partid(商户号)、prepayid(预支付订单ID)、noncestr(参与签名的随机字符串)、timestamp(参与签名的时间戳)、sign(签名字符串)这六个。 在点击支付的控制器中使用核心代码来调起微信客户端支付,这些个参数都是后台传给你的。 加上了注释,应该很好理解的。代码如下:

1#pragma mark 微信支付方法 2- (void)WechatPay{ 3 4 //需要创建这个支付对象 5 PayReq *req = [[PayReq alloc] init]; 6 //由用户微信号和AppID组成的唯一标识,用于校验微信用户 7 req.openID = appid; 8 // 商家id,在注册的时候给的 9 req.partnerId = partnerid; 10 // 预支付订单这个是后台跟微信服务器交互后,微信服务器传给你们服务器的,你们服务器再传给你 11 req.prepayId = prepayid; 12 // 根据财付通文档填写的数据和签名 13 req.package = package; 14 // 随机编码,为了防止重复的,在后台生成 15 req.nonceStr = noncestr; 16 // 这个是时间戳,也是在后台生成的,为了验证支付的 17 NSString * stamp = timestamp; 18 req.timeStamp = stamp.intValue; 19 // 这个签名也是后台做的 20 req.sign = sign; 21 //发送请求到微信,等待微信返回onResp 22 [WXApi sendReq:req]; 23 24}

4.5 判断手机是否安装微信客户端

在需要微信支付的地方调用封装的类方法之后会跳转到微信app,如果没有安装则没有任何反应。这里需要注意,因为没有安装微信,必须要提供webview的方式登录微信来支付,否则苹果公司会拒绝应用上架。但是微信又不自带webview的方式,(支付宝是自带的)所以要判断用户有没有安装微信,如果没有安装微信就不显示微信支付这个按钮。

1// 判断手机有没有微信 2 if ([WXApi isWXAppInstalled]) { 3 wechatButton.hidden = NO; 4 }else{ 5 wechatButton.hidden = YES; 6 }

到这里微信支付就基本完成了,如果小伙伴们在集成过程中遇到什么问题,可以留言给我或者添加qq,在线帮你解决。

5. 常见问题解决

5.1 支付后无法返回 App

如果支付完成后,一直留在微信,那就检查下URLType中的Scheme设置问题。

5.2 参数过期

能够打开微信客户端,但是打开后只有中间一个白色的 “确定按钮”,点击后会回到客户端上,如果是这样,那应该是prepayid 参数的问题,过期了,或者不是真实的id。

5.3 微信支付的单位是分

5.4 程序没有找到sdk库

工程->build setttings -> 搜索other linker flags 添加-Objc -all_load ,运行工程可能会崩溃,原因是程序没有找到sdk库。

5.5 白名单

不配置白名单也可以调起支付,如果调不起支付,查看是否是白名单的问题。

打开工程里的info.plist文件 添加LSApplicationQueriesSchemes数组并添加wechat 和 weixin字符串。

或者info.plist右键->source code打开添加下面这段代码

1<key>LSApplicationQueriesSchemes</key> 2<array><string>wechat</string> 3 <string>weixin </string> 4</array>

5.6 中文名的工程报错

中文名的工程会报这个错误,英文名则不会,这是因为缺少UIKit库 在WXApiObject.h里导入库#import <UIKit/UIKit.h>。

5.7 找不到对应的编译包

微信 sdk 的问题,找不到对应的编译包,把 libc++ 这个导入就解决了

希望可以帮助大家 如果哪里有什么不对或者不足的地方,还望读者多多提意见或建议 iOS技术交流群:668562416

源码Demo获取方法

获取源码方式:关注「网罗开发」回复 “微信支付” 即可获取

转载

本文已在公众号「网罗开发」发布,如果转载长白请加微信:FBY-fan,备注转载长白

福利

面试.png

扫码加微信:FBY-fan 回复「面试题」,领取 11 类面试题,包含:多线程、内存管理、设计模式、数据安全及加密、数据结果与算法、网络、性能优化、Block、RunLoop、Runtime、UI 相关

点赞
收藏

评论区

加载中...

相关推荐

MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1

文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s

Oracle 分组与拼接字符串同时使用

SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(

MySQL部分从库上面因为大量的临时表tmp_table造成慢查询

背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_

皕杰报表之UUID

​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为

thinkcmf+jsapi 实现微信支付

首先从小程序端接收订单号、金额等参数,然后后台进行统一下单,把微信支付的订单号返回,在把订单号发送给前台,前台拉起支付,返回参数后更改支付状态。。。回调publicfunctionnotify(){$wechatDb::name('wechat')where('status',1)find();

2020年前端实用代码段,为你的工作保驾护航

有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )