iOS微信支付接入以及工具类封装
在刚刚结束的一个项目中用到了微信支付,从接入微信支付到工具类的封装,在本文中做个积累,方便日后使用。
1.开始接入微信支付的准备工作
首先你需要去微信开放平台注册账号,在这里要吐槽一下,不知道这个微信平台的账号密码验证机制,忘了以前的密码,重新登录,各种找回密码都不行,实在没辙,去注册个Gmail��,登录成功后,可以看到如下界面。
点击右上角的创建移动应用,一步一步填写必要填入的信息,在这里就不做多余的赘述了。
需要注意的是这里填入的
Bundle ID需要和项目的一一对应
接下来就等一个星期左右,等待微信审核通过你就可以将微信支付SDK集成到项目中,详情可以看官方给出的文档.
pod 集成方法
pod 'WechatOpenSDK'
在Xcode中,选择你的工程设置项,选中“TARGETS”一栏,在“info”标签栏的“URL type“添加“URL scheme”为你所注册的应用程序id(如下图所示)。
完成之后可以获取到appid(微信开放平台为应用生成的唯一识别码)、商户id、商户secretKey。对于app端来说只用到appid,商户id最好通过接口从server获取,商户secretKey是用来签名的,一般只有server能用到。
2.支付流程
刚开始看这个流程图可能会觉得很复杂,所以总结了我们比较关系的流程是:
1. app客户端向服务器发送支付请求
2. 服务器在收到客户端请求之后向微信后台调用统一下单API,获得预付单信息
3. 服务端生成带签名的客户端支付信息给app
4. app客户端用户确认支付,app唤醒微信客户端进行支付
5. app获得支付结果后向服务端查询最终的结果并显示
app端的工作:
- 接入微信支付SDK
- 向服务器发送支付请求
- 支付信息唤醒微信app,然后进行支付
- 收到微信支付回调后向服务器确认支付结果
- 根据查询结果展示结果页面告知用户支付结果
服务器端的工作:
- 收到app客户端支付请求后向微信后台请求预支付订单
- 服务器端签名并返回信息给app客户端
- 接收微信后台返回的支付结果,用来app端查询
服务器端返回的字段说明:
- appId:返回的appid
- partnerId: 父级id
- prepayId: 支付id
- packages: 包名(微信默认的为“Sign=WXPay”)
- nonceStr: 生成的随机字符串
- timesTamp: 时间戳
- sign: 签名
3.iOS端使用
在AppDelegate.m
,导入微信SDK头文件WXApi.h
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[WXApi registerApp:@"注册获得的appid"];//注册appidreturn YES;
}//支持所有iOS系统回调
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation
{
// [self handleOpenURL:url];BOOL result = [[UMSocialManager defaultManager] handleOpenURL:url sourceApplication:sourceApplication annotation:annotation];if (!result) {// 其他如支付等SDK的回调[self handleOpenURL:url];}return YES;
}
- (void)handleOpenURL:(NSURL*)url {if ([url.host isEqualToString:@"pay"]) { // -- 微信支付[WXApi handleOpenURL:url delegate:[WXPayService sharedInstance]];}
}
此处的
WXPayService
就是自己单独抽出来写的一个类,遵循WXApiManagerDelegate
协议
WXPayService.h
#import <Foundation/Foundation.h>
#import "WXApi.h"
@interface WXPayService : NSObject <WXApiDelegate>
///单例来接收微信请求的回调
+ (instancetype)sharedInstance;
// -- 根据接口返回的预支付信息,构造支付请求
+ (PayReq *)getPayRequest:(NSDictionary *)prepayData;///处理非支付请求的回调
- (void)onRespCallBack:(void(^)(BaseResp * resp))callback;
///从服务器端获取到微信返回的支付请求用到的参数来发起支付请求
- (void)startPayWithReq:(PayReq *)req callback:(void(^)(BaseResp * resp))callback;
@end
WXPayService.m
#import "WXPayService.h"
@interface WXPayService ()
@property (nonatomic,copy) void(^RespCallBack)(BaseResp *);
@end
static WXPayService *sharedInstance;@implementation WXPayService
+ (instancetype)allocWithZone:(struct _NSZone *)zone{static dispatch_once_t onceToken;dispatch_once(&onceToken, ^{sharedInstance = [super allocWithZone:zone];});return sharedInstance;
}
///单例来接收微信请求的回调
+ (instancetype)sharedInstance {static dispatch_once_t onceToken;dispatch_once(&onceToken, ^{sharedInstance = [[self alloc] init];});return sharedInstance;
}// -- 根据接口返回的预支付信息,构造支付请求
+ (PayReq *)getPayRequest:(NSDictionary *)prepayData {if (prepayData) {
// 此处Tools是自己的另一个工具类,用来判断字典的PayReq *req = [[PayReq alloc] init];if ([Tools dicContain:prepayData withKey:@"partnerid"]) {req.partnerId = prepayData[@"partnerid"];}if ([Tools dicContain:prepayData withKey:@"prepayid"]) {req.prepayId = prepayData[@"prepayid"];}if ([Tools dicContain:prepayData withKey:@"noncestr"]) {req.nonceStr = prepayData[@"noncestr"];}if ([Tools dicContain:prepayData withKey:@"timestamp"]) {req.timeStamp = [prepayData[@"timestamp"] intValue];}req.package =@"Sign=WXPay";req.sign = @"null";//日志输出NSLog(@"appid=%@/npartid=%@/nprepayid=%@/nnoncestr=%@/ntimestamp=%ld/npackage=%@/nsign=%@",[prepayData objectForKey:@"appid"],req.partnerId,req.prepayId,req.nonceStr,(long)req.timeStamp,req.package,req.sign);return req;}return nil;
}///处理非支付请求的回调
- (void)onRespCallBack:(void(^)(BaseResp * resp))callback {self.RespCallBack = callback;
}
///从服务器端获取到微信返回的支付请求用到的参数来发起支付请求
- (void)startPayWithReq:(PayReq *)req callback:(void(^)(BaseResp * resp))callback {NSAssert(req !=nil , @"未成功创建微信支付请求");self.RespCallBack = callback;if ([WXApi isWXAppInstalled]) { // -- 判断是否安装微信应用//发起微信支付,设置参数[WXApi sendReq:req];}else {self.RespCallBack(nil);}
}#pragma mark WXApiDelegate
- (void)onResp:(BaseResp *)resp {if ([resp isKindOfClass:[PayResp class]]) { // -- 判断是否为支付的回调self.RespCallBack(resp);}
}
@end
在需要支付的ViewController中导入工具类WXPayService
4.注意点及问题
注意点:
- 设置好scheme,否则应用无法跳转到微信客户端
- 支付签名时的key值全部是小写的
- 如果支付显示验证签名失败
的时候,可以将packages设为默认值(Sign=WXPay)试试
问题:
系统版本大于等于iOS9的,调起微信客户端之后,可以直接点击状态栏左侧按钮返回,这时是不走回调方法的。
解决方案:
在AppDelegate.m的applicationWillEnterForeground方法中,调用查询支付结果接口然后刷新当然页面。需要设置bool变量作为标志,否则每次应用进入前台都去查询,就不符合业务要求了。
进入微信支付页面之后,不做操作,切换到自己应用中,退出当前支付页面,然后再进入微信客户端点击支付或者取消,此时自己的应用会崩溃闪退
原因:退出页面后页面已经出栈被销毁,但wx回调时还是去调用其中的代理方法,就会出现野指针。
解决方案:在页面的viewWillDisappear
方法中加入
[WXPayService sharedManager].delegate = nil;
5.结束语
微信支付签名建议和服务端协商做二次签名,以保证支付的安全性。
ps: 如有不对的地方,欢迎批评指正,另外安利一下个人的博客
iOS微信支付接入以及工具类封装相关推荐
- IOS开发基础之音频工具类封装AVAudioPlayer
IOS开发基础之音频工具类封装AVAudioPlayer 源码在我的主页下面 ,项目名称是AVAudioPlayer 关键性代码 工具类的封装 // // LJAudioTool.h // AVAud ...
- 微信支付AES解密工具类
WechatAESUtil类 public class WechatAESUtil {/*** 密钥算法*/private static final String ALGORITHM = " ...
- C#开发微信门户及应用(32)--微信支付接入和API封装使用
C#开发微信门户及应用(32)--微信支付接入和API封装使用 在微信的应用上,微信支付是一个比较有用的部分,但也是比较复杂的技术要点,在微商大行其道的年代,自己的商店没有增加微信支付好像也说不过去, ...
- iOS微信支付的步骤以及问题描述
本博客转自:http://www.jianshu.com/p/22a1ceee4d36 一.微信支付的步骤: 1.在微信开放平台注册.微信开放平台 2.创建一个App应用.(需要填写App的资料,审核 ...
- 微信支付接入的那点事儿
本文来自作者 javen 在 GitChat 上分享「微信支付接入的那点事儿」,「阅读原文」查看交流实录 「文末高能」 编辑 | 嘉仔 前言 本次 Chat 中涉及到的图片.统计数据均来自于网络,截图 ...
- 【JavaScript学习】JavaScript 常用工具类封装
文章目录 1.JavaScript 常用工具类封装 (1)获得浏览器地址所有参数 (2)将json转为get参数 (3)格式校验工具类 (4)数组操作工具类 (5)表单取值工具类 (6)时间转换工具类 ...
- Android 集成微信支付和支付宝支付工具类
Android 集成微信支付和支付宝支付工具类 1.前言 去年年底接了一个商城app 外包项目,里面尼涉及到 微信和支付宝支付,这里我整理出几个工具类,下面就和大家分享一下,废话不多说,下面我一步一步 ...
- ReactNative 安卓支付宝微信支付接入
微信支付接入 首先,在android/src/main/java/* 新建 pay支付文件夹,如下所示: 新建 wechat ,在文件夹里面新建 Const.java, WeChatPay.java ...
- 【微信小程序】微信支付接入全流程
一. 前置条件 接入支付首先得需要有企业资质,并开通企业对公户 注册微信支付并进行对公户打款认证 二. 开始接入 1. 下载微信支付的AP证书 2. 服务端接入微信支付 2.1 引入相关maven配置 ...
最新文章
- 为什么医学影像AI已进入「后深度学习时代」?
- 华为北大等联手打造的Transformer竟在CV领域超过了CNN:多项底层视觉任务达到SOTA...
- 20个必不可少的Python库
- WinForm下ListBox控件“设置DataSource属性后无法修改项集合”的问题解决方案
- CF56E Domino Principle 树状数组 + 简单dp
- java中number类型能否相除_Java中 如果复数类成员是int型,怎么实现两个复数相除...
- python中swap函数_python swap
- 【tool】常见功能测试点
- mpu6050 重力加速度_MPU6050抄底解读
- 微软最有价值专家大中华峰会开幕视频
- js数组中判断是否有重复项
- 【ArcGIS风暴】气象台站气温(降水)矢量数据插值成栅格气温(降水)空间数据
- 001.Heartbeat简介
- 让最好用的印象笔记更好用
- (2019春)软件构造:雨课堂试卷(第3章)
- SUST 2019暑期集训题解(差分约束+生成树+传递闭包)
- 神目云抗疫又出杀手锏:风险人物轨迹追溯,毫秒锁定密切接触者
- 程序员被裁员该怎么办
- PHP代码审计-sql注入
- 4g运行内存手机还能用多久_手机运行内存4G和6G区别很大吗?真的是越大越好吗?...