iOS微信支付

<div class="iteye-blog-content-contain" style="font-size: 14px"></div>

       近期笔者开发的项目中,需要用到支付宝支付和微信支付。大概一个月前,支付宝就已经集成完毕并可以正常使用。但在集成坑爹的微信支付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签名),调用微信支付接口,就可以调用手机微信客户端进行支付

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

1
2
3
4
5
6
7
8
9
10
11
//调起微信支付
         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(时间戳)参与签名。我们只有一次签名,一直没法调起支付界面

 

 

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

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

 

猜你喜欢

转载自494075592.iteye.com/blog/2264767