在刚刚结束的一个项目中用到了微信支付,从接入微信支付到工具类的封装,在本文中做个积累,方便日后使用。

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微信支付接入以及工具类封装相关推荐

  1. IOS开发基础之音频工具类封装AVAudioPlayer

    IOS开发基础之音频工具类封装AVAudioPlayer 源码在我的主页下面 ,项目名称是AVAudioPlayer 关键性代码 工具类的封装 // // LJAudioTool.h // AVAud ...

  2. 微信支付AES解密工具类

    WechatAESUtil类 public class WechatAESUtil {/*** 密钥算法*/private static final String ALGORITHM = " ...

  3. C#开发微信门户及应用(32)--微信支付接入和API封装使用

    C#开发微信门户及应用(32)--微信支付接入和API封装使用 在微信的应用上,微信支付是一个比较有用的部分,但也是比较复杂的技术要点,在微商大行其道的年代,自己的商店没有增加微信支付好像也说不过去, ...

  4. iOS微信支付的步骤以及问题描述

    本博客转自:http://www.jianshu.com/p/22a1ceee4d36 一.微信支付的步骤: 1.在微信开放平台注册.微信开放平台 2.创建一个App应用.(需要填写App的资料,审核 ...

  5. 微信支付接入的那点事儿

    本文来自作者 javen 在 GitChat 上分享「微信支付接入的那点事儿」,「阅读原文」查看交流实录 「文末高能」 编辑 | 嘉仔 前言 本次 Chat 中涉及到的图片.统计数据均来自于网络,截图 ...

  6. 【JavaScript学习】JavaScript 常用工具类封装

    文章目录 1.JavaScript 常用工具类封装 (1)获得浏览器地址所有参数 (2)将json转为get参数 (3)格式校验工具类 (4)数组操作工具类 (5)表单取值工具类 (6)时间转换工具类 ...

  7. Android 集成微信支付和支付宝支付工具类

    Android 集成微信支付和支付宝支付工具类 1.前言 去年年底接了一个商城app 外包项目,里面尼涉及到 微信和支付宝支付,这里我整理出几个工具类,下面就和大家分享一下,废话不多说,下面我一步一步 ...

  8. ReactNative 安卓支付宝微信支付接入

    微信支付接入 首先,在android/src/main/java/* 新建 pay支付文件夹,如下所示: 新建 wechat ,在文件夹里面新建 Const.java, WeChatPay.java ...

  9. 【微信小程序】微信支付接入全流程

    一. 前置条件 接入支付首先得需要有企业资质,并开通企业对公户 注册微信支付并进行对公户打款认证 二. 开始接入 1. 下载微信支付的AP证书 2. 服务端接入微信支付 2.1 引入相关maven配置 ...

最新文章

  1. 为什么医学影像AI已进入「后深度学习时代」?
  2. 华为北大等联手打造的Transformer竟在CV领域超过了CNN:多项底层视觉任务达到SOTA...
  3. 20个必不可少的Python库
  4. WinForm下ListBox控件“设置DataSource属性后无法修改项集合”的问题解决方案
  5. CF56E Domino Principle 树状数组 + 简单dp
  6. java中number类型能否相除_Java中 如果复数类成员是int型,怎么实现两个复数相除...
  7. python中swap函数_python swap
  8. 【tool】常见功能测试点
  9. mpu6050 重力加速度_MPU6050抄底解读
  10. 微软最有价值专家大中华峰会开幕视频
  11. js数组中判断是否有重复项
  12. 【ArcGIS风暴】气象台站气温(降水)矢量数据插值成栅格气温(降水)空间数据
  13. 001.Heartbeat简介
  14. 让最好用的印象笔记更好用
  15. (2019春)软件构造:雨课堂试卷(第3章)
  16. SUST 2019暑期集训题解(差分约束+生成树+传递闭包)
  17. 神目云抗疫又出杀手锏:风险人物轨迹追溯,毫秒锁定密切接触者
  18. 程序员被裁员该怎么办
  19. PHP代码审计-sql注入
  20. 4g运行内存手机还能用多久_手机运行内存4G和6G区别很大吗?真的是越大越好吗?...

热门文章

  1. 快手宣布全链路支持iPhone12系列 HDR视频拍摄、编辑、上传和播放
  2. Q2营收环比下滑,荔枝变“苦”了?
  3. Java自制绘图软件
  4. Xpath helper插件
  5. Open web start 1.5.2
  6. c加加语言三体问题,一道典型三体问题的四种别致解法
  7. 国产CPU借助Arm由终端逆推进军服务器市场
  8. python pyecharts Bar柱状堆叠图
  9. mysql安装后怎么打开_mysql安装配置和启动
  10. 数字中国城市巡礼之福州:数字中国建设的东南坐标