iOS- 微信支付总结

前言:本篇文章目的在于梳理知识,巩固思想,学习总结。有什么好的建议,都可以留言。互相促进!

总观,微信支付,也没心思,好好看文档。文档微微有些乱。感觉,微信demo,内部功能都集成到一块了,不好查找。终于,在各种坑下,仔细看了一遍文档,默默的弄完了。

会用到的网址如下:
微信开放平台
微信商户平台
iOS微信支付在线文档
SDK集成文档

大体方向:

1.注册微信开放平台,创建应用获取appid,APPSecret,申请支付功能,申请成功之后会返回一些参数.

2.下载微信支付SDK.

3.客户端请求订单,后台与微信后台交互,返回给客户端支付参数.

4.调用微信客户端,由微信客户端和微信服务器打交道.

5.客户端和服务器都会收到支付结果.

1.准备工作

(我们公司的微信支付申请是公司申请完之后,创建完应用后给我的,但是还要清楚一下大概流程)

a.注册开发者账号

进入微信开放平台,注册开发者账号(必须申请)。申请开发者资质认证,300元一年。除了能使用微信开放平台的一些高级功能外,可以不用认证。


开发者资质认证

b.注册应用

拿到微信开发者账号后,登录微信开放平台,进入管理中心,创建新的移动应用。


注册应用

创建应用我向大家都会,具体细节就不截图了。

c. 获取app ID和appSecret

创建成功,获得appid和appSecret。点击查看,如下图。


获取app ID和appSecret

验证之后,会返回我们要获得的app ID和appSecret如下图,保留好。


验证后获得

d. 申请开通支付权限

登录微信开放平台——管理中心——创建移动应用,找到注册的相应的应用,接口名称——微信支付——申请开通支付去权限。资料填写完毕,等待审核。

成功后,则收到一封邮件,获得商户号,商户登录账号以及登录密码。

e. 账户验证

登录微信开放平台——管理中心,找到相对应的应用,查看——微信支付(接口状态—已获得)——查看详情,按照它的提示步骤操作。

获知收到的确认金,进行验证。验证通过,准备工作完毕。

申请开通支付权限

开通微信支付,有的不一定,有的一个星期,有的很长。我也不知道大概时间,我们这个申请好长时间了。
点击-->查看详情(了解一下支付的详情)
支付申请流程

签约

f.获得API密钥

f.1用获得的商户登录账号和密码
f.2登录微信商户平台——账户中心——账户设置——API安全——API密钥
f.3安装操作证书,再设置密钥。

获得API密钥

(这步千万别忘了,其实按照邮件上的说明走就OK了。微信流程一步错了,就容易出问题,谨记按部就班走,不要浪费没有必要的时间,微信支付申请,基本工作准备就完毕了。)

小结:
1.创建应用获取app IDappSecre
2.开通支付功能
3.获取邮件里商户号和账号密码
4.商户平台,下载证书,获得api秘钥

补充:创建移动应用并成功之后会受到腾讯发来的邮件如下

邮件内容

注意:
通过邮件我们能获得重要的参数:
(1):AppID
(2):微信支付商户号
(3):前往商户平台完成入驻
(4):API秘钥(自己设置即可,注意一定要32位字母加数字的组合)记得保存好秘钥,以后要使用。

$_$; 有了这些参数后,我们就可以开发自己的项目了。

2. SDK集成及环境配置

下面让我们一起创建工程,一起去集成微信支付的SDK吧。下载地址如下:
官方SDK及Demo下载地址


如上图,SDK版本1.7.9,ios9_v3_pay

  • 1.将我们下载的SDK导入我们的工程。

  • 2.在Target —> General —> Link Binary With Libraries— 点击+号 -> 搜索你需要的系统库,如下:

    SystemConfiguration.framework
    
    libz.tbd
    
    libsqlite3.0.tbd
    
    CoreTelephony.framework
    
    QuartzCore.framework
    
添加依赖库
  • 3 设置URL Scheme:为了app之间的跳转
    在注册微信平台APP的时候,会给一个唯一识别标识符(APPID)。
    这里的url schemes就填在微信开发平台申请的appID
    打开工程->info->URL types
URL Scheme
  • 4.配置白名单(貌似不配置白名单也能跳转,但还是写全了为妙)。

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

<key>LSApplicationQueriesSchemes</key>
<array><string>wechat</string>
<string>weixin </string>
</array>

  • 4.有的时候会出现莫名奇妙的问题例如下面:
    Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSArrayM enqueue:]: unrecognized selector sent to instance 0x60000024ef40'

    在buddle Seeting 里面的Other Linker Flags 中添加-ObjC就可以了。

    Com + R,如果不出什么问题,基本上就集成完毕了,环境也配置好呢。

3.代码布局吊起微信支付

在吊起微信之前,必须要知道微信支付是一个怎么样的过程。

【了解一下-官方流程】


商户系统和微信支付系统主要交互说明:
步骤1:用户在商户APP中选择商品,提交订单,选择微信支付。
步骤2:商户后台收到用户支付单,调用微信支付统一下单接口。参见【统一下单API】。
步骤3:统一下单接口返回正常的prepay_id,再按签名规范重新生成签名后,将数据传输给APP。参与签名的字段名为appid,partnerid,prepayid,noncestr,timestamp,package。注意:package的值格式为Sign=WXPay
步骤4:商户APP调起微信支付。api参见本章节【app端开发步骤说明
步骤5:商户后台接收支付通知。api参见【支付结果通知API
步骤6:商户后台查询支付结果。,api参见【查询订单API

【网上好的流程分享】

1、用户使用APP客户端,选择商品下单。

2、商户客户端(就是你做的APP)将用户的商品数据传给商户服务器,请求生成支付订单。

3、商户后台调用统一下单API向微信的服务器发送请求,微信服务器生成预付单,并生成一个prepay_id返回给商户后台。

4、商户后台将这个prepay_id返回给商户客户端。

5、用户点击确认支付,这时候商户客户端调用SDK打开微信客户端,进行微信支付。

6、微信客户端向微信服务器发起支付请求并返回支付结果(他们之间交互用的就是prepay_id这个参数,微信的服务器要验证微信客户端传过去的参数是否跟第三步中生成的那个id一致)。

7、用户输入支付密码后,微信客户端提交支付授权,跟微信服务器交互,完成支付。

8、微信服务器给微信客户端发送支付结果提示,并异步给商户服务器发送支付结果通知。

9、商户客户端通过支付结果回调接口查询支付结果,并向后台检查支付结果是否正确,后台返回支付结果。

10、商户客户端显示支付结果,完成订单,发货。

客户端主要工作

1.调起微信客户端发起支付
2.显示支付结果

吊起准备

调用微信支付前,需要下单、签名等操作,以便获取微信支付所必要的参数。为了提高安全性,下单、签名操作一般是在后台完成。

需要的参数包括:appid、partid(商户号)、prepayid(预支付订单ID)、noncestr(参与签名的随机字符串)、timestamp(参与签名的时间戳)、sign(签名字符串)这六个。

[代码示例①:]

如果所有信息的生成都在前端完成,包括对订单进行sign签名以及MD5签名加密(此方法相对来说有些复杂,没有官方给的方法简单)您可以看参考文章iOS应用之微信支付集成

官方给的是v3&v4支付流程,签名和加密都是在[服务器端],我们也是这样做的,服务器做的2次签名如下:

  • 1、在项目工程Appdelegate.m文件里面添加注册微信支付信息,注:如果项目中第三方分享用的是友盟,在注册的时候要把友盟注册放在微信注册的前面执行。如下:

     #import "AppDelegate.h"
     #import "WXApi.h"
    
     @interface AppDelegate ()
    
     @end
    
     @implementation AppDelegate
    
    
     - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
       //注册APP,
      [WXApi registerApp:@"wxb4ba3c02aa476ea1"];
      return YES;
      }
    
    - (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<NSString *,id> *)options
      {
       // 跳转到URL scheme中配置的地址
       //NSLog(@"跳转到URL scheme中配置的地址-->%@",url);
       return [WXApi handleOpenURL:url delegate:(id<WXApiDelegate>)self];
      }
       //支付成功时调用,回到第三方应用中
    - (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation
      {
       // NSLog(@"****************url.host -- %@",url.host);
        if ([url.scheme isEqualToString:@"wx23a1f7f291ef4b3d"])
       {
         return  [WXApi handleOpenURL:url delegate:(id<WXApiDelegate>)self];
       }
        return YES;
       }
    
  • 2、给服务器发送订单信息,获取预付订单参数,吊起微信。

  • WechatPayViewController.m

    #import "WechatPayViewController.h"
    #import "HYBNetworking.h"
    #import "WXApi.h"
    #import "NSString+MD5.h"
    
    @interface WechatPayViewController ()
    
    //商户关键信息 ,微信分配给商户的appID,商户号,商户的密钥
    @property (nonatomic,strong) NSString *appId,*mchId,*spKey;
    
    @end
    
    @implementation WechatPayViewController
    
    - (void)viewDidLoad {
     [super viewDidLoad];
    // Do any additional setup after loading the view.
    self.view.backgroundColor = [UIColor greenColor];
    
    UIButton *payButton = [UIButton buttonWithType:UIButtonTypeCustom];
    payButton.center = self.view.center;
    payButton.bounds = CGRectMake(0, 0, 200, 200);
    [payButton setImage:[UIImage imageNamed:@"wechatPay_icon@2x"] forState:UIControlStateNormal];
    [payButton addTarget:self action:@selector(payClick) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:payButton];
    
    // 判断 用户是否安装微信
    //如果判断结果一直为NO,可能appid无效,这里的是无效的
    if([WXApi isWXAppInstalled])
    
     {
    // 监听一个通知
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(getOrderPayResult:) name:@"ORDER_PAY_NOTIFICATION" object:nil];
    }
    
    }
    
    -(void)payClick {
     [self easyPay];
     }
    
     /**
     http://wxpay.weixin.qq.com/pub_v2/app/app_pay.php为测试数据,一般可以从这儿拿
     到的数据都可以让服务器端去完成,客户端只需获取到然后配置到PayReq,即可吊起微信;
     */
      -(void)easyPay {
      [HYBNetworking getWithUrl:@"http://wxpay.weixin.qq.com/pub_v2/app/app_pay.php" params:nil success:^(id response) {
       NSLog(@"%@",response);
    
      //配置调起微信支付所需要的参数
    
     PayReq *req  = [[PayReq alloc] init];
    
     req.partnerId = [response objectForKey:@"partnerid"];
     req.prepayId = [response objectForKey:@"prepayid"];
     req.package = [response objectForKey:@"package"];
     req.nonceStr = [response objectForKey:@"noncestr"];
     req.timeStamp = [[response objectForKey:@"timestamp"]intValue];
     req.sign = [response objectForKey:@"sign"];
    
     //调起微信支付
     if ([WXApi sendReq:req]) {
      NSLog(@"吊起成功");
     }
    
    
     } fail:^(NSError *error) {
       NSLog(@"%@",error);
      }];
     }
    
     #pragma mark - 收到支付成功的消息后作相应的处理
     - (void)getOrderPayResult:(NSNotification *)notification
     {
         if ([notification.object isEqualToString:@"success"]) {
             NSLog(@"支付成功");
     } else {
      NSLog(@"支付失败");
     }
    
     }
    

注意点:

1、你创建应用的boundId一定要跟你项目中得一样。

2、应用跳转不要忘记配置URL Scheme

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

4、能够打开微信客户端,但是打开后只有中间一个白色的 “确定按钮”,点击后会回到客户端上,如果是这样,那应该是prepayid 参数的问题,过期了,或者不是真实的id。代码没有问题的。特别注意的是,微信要两次签名,两次~~~~

5、网上说、如果APP里面使用了友盟或者ShareSDK做分享,那就不用再导入SDK了,否则会出现一些诡异的问题,例如无法调起手机微信客户端、无法调起微信客户端web页面,调起了但是一闪而过。。。这都基本上都是因为分享的SDK里面已经包括了微信的SDK。所以如果出现诡异的错误了看看是不是两个冲突了!我这没有冲突,是因为,微信我是手动集成的,shareSDK是pod集成的。

6、微信支付的单位是分,被坑过的人都知道了!

7、二次签名的过程:第一次签名:客服端向服务器发起支付请求,服务器根据所必须的参数进行一次签名,在与微信的服务器进行交互,获得成功地返回数据,进行第二次签名。将信息(预付订单参数等)返回给客户端。客户端在根据所获参数,将微信吊起。
参考文章:
从零开始微信app支付v3-iOS版
iOS开发集成微信支付
iOS应用之微信支付集成
扩展文章
微信支付-简易实例代码(可以了解一下后台代码)
iOS开发傻瓜式微信支付的方法教程
iOS-微信支付流程

Demo地址
如果这篇文章,对您有用,或者帮助了您,请点👍,赏个冰棍吃,消消暑。不瞎闹了,共同学习,如果有什么更好的建议,请提出,或是有什么好的方法。thanks!!!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,378评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,356评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,702评论 0 342
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,259评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,263评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,036评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,349评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,979评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,469评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,938评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,059评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,703评论 4 323
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,257评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,262评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,485评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,501评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,792评论 2 345

推荐阅读更多精彩内容