iOS第三方支付集成——微信支付

近期笔者开发的项目中,需要用到支付宝支付和微信支付。大概一个月前,支付宝就已经集成完毕并可以正常使用。但在集成坑爹的微信支付SDK时,遇到了诸多问题,搞了将近三个星期。期间不断的跟后台同事核对代码(签名、下单),支付流程,其中的血泪艰辛,不言而喻。现笔者把集成过程中遇到的一些问题记录下来,供自己和大家参考。如果有什么不对的地方,也请大家多多指正:

吐槽完了,下面出正文。

补充说明:第一准备阶段不需要开发者负责操作,如果你是iOS开发人员,只想找到调用微信支付的代码,可直接跳过 第一准备阶段。

一、准备阶段

(1)笔者公司用户是微信开放平台下开通的微信支付功能,网址:https://open.weixin.qq.com/?qq-pf-to=pcqq.c2c网上大部分资料讲的都是微信公众平台下的微信支付集成,其实原理和代码实现上大同小异。

(2)到微信开放平台的管理中心创建移动应用,待移动应用审核通过以后,申请获得微信支付能,这个流程走下来,大概需要 2 - 3 周。笔者建议提前到开放平台审核为好。网址:https://open.weixin.qq.com/cgi-bin/applist?t=manage/list&lang=zh_CN&token=478d1d01575659fb7b53ee40d1f37c5cfc8689e5

移动应用审核通过后,获取APP_IDAppSecret,附上截图:

(3)等到移动应用审核通过,获得微信支付能力之后,进入微信商户商户平台。商户平台的账号和密码,在公司账号开通微信支付功能以后,财付通就会下发。微信商户平台网址:https://pay.weixin.qq.com/index.php/home/login?return_url=/

进入微信商户平台后,获取商户号和商户API密钥。附上截图:

二、获取微信支付IOS头文件和库下载及APP支付示例和解读

(1)进入网址https://pay.weixin.qq.com/wiki/doc/api/app.php?chapter=11_1,下载微信支付APP支付示例。在APP支付示例中,已经包含了头文件和库,所以不需要在下载头文件和库。

(2)解压文件,会得到文件名为:wechat_sdk_sample_ios_v3_pay的文件夹。从名字可以知道,这是一份v3版本的代码,目前v2版本的微信支付几乎已经不用,新添加的微信支付SDK几乎都是v3版本的。集成的时候,要明白这点,很重要。

(3)文件目录及作用

readme.txt:首次集成微信支付SDK时,读读没坏处。

设置appid.jpg:直接运行demo是无法调用微信客户端的,需要按钮图片的内容,设置 URL Schemes 和 APP_ID 才能运行。

wechat_sdk_sample_ios_payV3:

~ lib:配置文件,配置了微信支付所要设置的相关内容

~ SDKExport:微信支付头文件和库文件

~ SDKSample:项目功能实现代码

(4)代码准备工作

Xcode打开工程代码,点击AppDelegate.m文件,可以查看到微信支付的实现代码。

~[WXApi registerApp:APP_ID withDescription:@"demo 2.0"];向微信注册,必写代码。

~ -(void) onReq:(BaseReq*)req:发送信息给微信客户端,请查看微信支付demo具体代码实现

~ -(void) onResp:(BaseResp*)resp:收到微信客户端信息的代理方法,请查看微信支付demo具体代码实现

(5)调起微信支付

重点来了!!!通过调试,我们可以知道,"微信支付测试签名"、“微信支付demo”两个按钮,分别对应的是 

- (void)sendPay - (void)sendPay_demo 两个方法,那么这两个方法都做了什么呢?什么是签名呢?

在解释上面的问题前,有必要先解释一下微信支付的签名流程。

      微信支付demo和微信支付开发文档多处提到以下几点:

       ~ 后台服务器做签名、下单请求,从微信服务器获取到 预支付ID 和 sign 签名等多个参数;

       ~ APP通过获取后台返回的参数(openID、partnerID商户号、prepayID预支付ID、nonceStr随机字符串、timeStamp时间戳、package包、sign签名),调用微信支付接口,就可以调用手机微信客户端进行支付

       ~ 调用微信支付的代码如下(核心代码哦,我们所有的操作都是为了这段核心的参数做准备):

//调起微信支付
        PayReq* req             = [[[PayReq alloc] init]autorelease];
        req.openID              = [dict objectForKey:@"appid"];    
        req.partnerId           = [dict objectForKey:@"partnerid"];
        req.prepayId            = [dict objectForKey:@"prepayid"];
        req.nonceStr            = [dict objectForKey:@"noncestr"];
        req.timeStamp           = stamp.intValue;
        req.package             = [dict objectForKey:@"package"];
        req.sign                = [dict objectForKey:@"sign"];
        
        [WXApi sendReq:req];

       根据上面的说明,童鞋们不知道明白了没。其实所有的代码,都是为了上面的核心作准备的,目的地就是为了获取上面核心代码的参数,已调用微信支付的接口。我们回到最初点:

       ~ - (void)sendPay:模拟签名的过程。为了更好的安全性,关于微信支付的下单和签名的过程,一般都是在后台完成,后台再把这些参数传回到APP,APP再调用。这个方法却是在APP端完成下单和签名的操作,这其实只是一个演示的过程“//本实例只是演示签名过程, 请将该过程在商户服务器上实现”

       ~ - (void)sendPay_demo:使用微信后台提供的参数,做支付演示。调用这个方法,控制台会打印出这样一串东西:url:http://wxpay.weixin.qq.com/pub_v2/app/app_pay.php?plat=ios&order_no=1444376336&product_name=Ios%B7%FE%CE%F1%C6%F7%B6%CB%C7%A9%C3%FB%D6%A7%B8%B6%20%B2%E2%CA%D4&order_price=0.01。这串字符串中,包含了调用微信支付接口所需的所有的参数。核心代码通过使用这些参数,就可以成功调用微信客户端完成支付。

     微信支付提供的官方文档:

     统一下单,获取预支付ID:https://pay.weixin.qq.com/wiki/doc/api/app.php?chapter=9_1

     调起支付接口,调起手机微信客户端:https://pay.weixin.qq.com/wiki/doc/api/app.php?chapter=9_12&index=2

     通过上面的描述,童鞋们明白了签名、下单、调用微信支付调用的原理和代码实现了没?

     三、代码实现微信支付

     通过上面的描述,我们可以得知一下几点:

(0)在- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 函数中添加以下代码://向微信注册  [WXApi registerApp:APP_ID withDescription:@"demo 2.0"];

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

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

(2)APP端获取后台的参数数据,调用一下的核心代码,调起微信支付

//调起微信支付
        PayReq* req             = [[[PayReq alloc] init]autorelease];
        req.openID              = [dict objectForKey:@"appid"];
        req.partnerId           = [dict objectForKey:@"partnerid"];
        req.prepayId            = [dict objectForKey:@"prepayid"];
        req.nonceStr            = [dict objectForKey:@"noncestr"];
        req.timeStamp           = stamp.intValue;
        req.package             = [dict objectForKey:@"package"];
        req.sign                = [dict objectForKey:@"sign"];
        
        [WXApi sendReq:req];

   (3)笔者提供一段亲测成功的核心代码,演示如何后台获取参数,调起微信支付:

    //请求网络数据
    [[TDNetworkingHelper sharedInstane] postRequestWithPath:[NSString stringWithFormat:@"%@%@", BASE_URL, orders_pay_wxpay_sign] parameter:paramDic whenSuccessed:^(id json) {
        
        if ([[json objectForKey:@"code"] integerValue]==1)   //数据获取成功
        {
            //调用微信支付
            [self sendWeChatReqWithOrderData:[json objectForKey:@"data"]];
        }
        else        //获取失败
        {
            ALERT([json objectForKey:@"msg"]);
        }
        
        [self hideHub];
        self.view.userInteractionEnabled = true;
        
    } whenFailed:^(NSError *error) {
        [self hideHub];
        self.view.userInteractionEnabled = true;
        //判断网络状态
        [self judgeNetworkStaus];
    }];
    
    
 -(void)sendWeChatReqWithOrderData:(NSDictionary*)orderData
  {
      NSLog(@"提交的参数:%@", orderData);
        
      //调起微信支付
      PayReq* req             = [[PayReq alloc] init];
      req.openID              = [orderData objectForKey:@"appid"];
      req.partnerId           = [orderData objectForKey:@"partnerid"];
      req.prepayId            = [orderData objectForKey:@"prepayid"];
      req.nonceStr            = [orderData objectForKey:@"noncestr"];
      req.timeStamp           = (UInt32)[[orderData objectForKey:@"timestamp"] integerValue];
      req.package             = [orderData objectForKey:@"package"];
      req.sign                = [orderData objectForKey:@"sign"];
      [WXApi sendReq:req];
  }

     五、无法完成微信支付的各种异常状态分与处理

笔者在开发过程中,也遇到过不少的异常状态,现记录如下:

(1)无法调起手机微信客户端、无法调起微信客户端页面,一闪而过

原因分析:第一种如果您的APP集成了友盟或者shareSDK的第三方分享SDK,会导致WechaSDK包的重复冲突;

处理方法:删除友盟或者shareSDK里面的WechaSDK包;在调用微信支付接口的文件里,后缀改为 .mm

(2)中间只有一个确定按钮,点击按钮,返回APP,提示 “支付结果:失败!retcode=-2,retstr=nil ”

原因分析:到这里,说明代码没有问题,是传递的参数有问题,任何一个参数出错都可能导致这样的问题。

处理方法:与后台完成签名、下单的同事沟通,检查后台的代码。

备注:我就是卡在这里两个多星期,后来检查发现是后台同事在签名的时候出现了问题。微信支付要求有两次签名,第二次需要timestamp(时间戳)参与签名。我们只有一次签名,一直没法调起支付界面

希望这篇可以帮到你,让你少走弯路。

对以上内容有任何疑问的童鞋,请留言指教!

时间: 2024-12-25 09:02:47

iOS第三方支付集成——微信支付的相关文章

iOS 集成微信支付

目前项目里有微信支付的需求,调研过一段时间后,发现其实并没有想象中的那么困难.如果你只是想实现该功能,一个方法足以,但是若你想深入了解实现原理.就需要花费更多的功夫了.目前我只清楚微信支付需要做签名,一种是在后台签名,一种是自己在前端签名.其实这对前端来说代码量并没有多大的改变,最大的区别是在后台签名逻辑更容易理解,而在前端签名逻辑有些混乱. 现在,小编也只是知道怎么使用,而不得其精髓,现在我附上我的学习链接,为了避免以后链接出现不可用情况,请各位理解小编的粘贴复制. 博客园(幻想无极) htt

小程序服务端集成微信支付

摘要: 换取openid->统一下单->发起支付,三步走,其中二次签名比较坑人. 该demo源码已托管到码云:http://git.oschina.net/dotton/lendoo-wx,欢迎下载. 理论上集成微信支付的全部工作可以在小程序端完成,因为小程序js有访问网络的能力,但是为了安全,不暴露敏感key,而且可以使用官方提供的现成php demo更省力,于是在服务端完成签名与发起请求,小程序端只做一个wx.requestPayment(OBJECT)接口的对接. 整体集成过程与JSAP

安卓 集成微信支付和支付宝

最近比较闲,公司项目更换后台,于是自己来研究微信支付和支付宝支付,把自己学习的过程写下来,以备以后查看. 注:要集成微信支付和支付宝功能,必须要有以下几个配置信息,而这写信息需要公司去微信支付和支付宝开放平台申请并提供给开发者,当然自己也可以去申请,这里作者用的是公司提供的,这里不纠结这些过程.获得这些信息以后 将配置信息放到一个静态类中,以共统一使用,但是处于安全考虑,微信与支付宝推荐这些数据放到服务器,这里作者把他们都放在前端,整个过程都是前端处理,实际开发尽量预处理订单生成放到后端处理.

androidAPP 集成微信支付

最近项目里面需要支付功能,boss一致决定用微信支付,所以在网上查了很多资料,说的不全,完了就找以前的同事指教.算是成功集成上去了.在这里做个总结记录. 1.在APP上集成微信支付,首先当然是当官网上去注册并获取到支付功能.这些不涉及到开发,官网上说的很详细,这里就不多做文章.获取到这些能力了就为开发提供了条件了.开发中会用到的就是平台给的APPID.APPsercet.以及商户平台上设置的APP_key. 2.具备了支付能力等前提条件之后,就是开发过程了.代码里面怎么才能吊起支付了,参照官网上

PC端网站集成微信支付的关键代码

目前来看,PC段实现微信支付,需要生成二维码,然后用微信扫码支付. 微信支付官网DEMO没有ASP.NET的,只能自己从帮助文档里扣代码摸索.这里需要说明几点特别要注意的. 看了下微信官网的文档,总结支付方式应该是两种: 1.Navite 静态链接方式. 2.JSAPI 方式.这种应该是手机端用到的.只支持微信内置浏览器. 我使用的是第一种方式. 但是据文档描述,这种方式还分为两种.请求流程不同,如下: 1.发送支付请求到微信 -> 微信返回支付Prepay_ID -> 发送支付信息到微信 -

MD5加密支付宝支付与微信支付

在做支付宝支付与微信支付时看到两家公司给的dom其中关于MD5加密的 支付宝的dom: DigestUtils.md5Hex(test).toUpperCase(); 微信的dom: private static String MD5(String sourceStr) throws UnsupportedEncodingException { String result = ""; try { MessageDigest md = MessageDigest.getInstance(

微信公众号中的支付宝支付与微信支付

一般,在微信公众号中的商城都是需要支持微信支付和支付宝支付的,当然,较大的公司对于鹅厂和阿里的站队就不说了,所以这里简单记录一下支付宝支付和微信支付的主要流程.说是简单介绍,这是因为确实不难,因为前端在这方面,包括微信授权登陆这一块需要做的都不是很多,而主要的工作量都在后端部分. 支付宝支付 无论是支付宝支付还是微信支付,最开始的步骤当然是将商品列表.商家相关信息.用户remark.运费.总价等等支付需要的信息通过post请求向后端传递,这里介绍支付宝支付,所以假设用户选择的是支付宝支付,那么后

如何申请三方支付接口 微信支付 支付宝支付 网银支付 钱包支付 扫码支付等

如何申请三方支付接口 微信支付 支付宝支付 网银支付 钱包支付  扫码支付等 首先,需要提供一整套申请支付接口的资料,如下 一.企业3证加盖公司公章 二.法人手持身份证照片 三.对应企业ICP备案的交易网站域名 资料审核初步审核之后,请把支付合作协议打印出来一式二份附带企业三证打印盖章邮寄到三方支付公司进一步审核 审核通过后,进行支付接口的对接 联调 最终正式环境上线

支付宝支付与微信支付服务端回调notify_url数据的区别

这两天优化了一下支付宝支付和微信支付订单回调的问题,之前我们的订单都是用手动回调给服务器,现在改成支付宝和微信原生的异步回调,结果并没有像我们想象的那么简单,支付宝是很顺利的解决回调,用一般的方式接收即可,但是微信接收时用普通的接收方式是不行的必须用另一种方式,如下且看: 支付宝和微信的回调地址 notifyUrl = RequestUrl.BASE_URL+"order/order_payment"+"?order_code="+orderCode; 服务器端是P