apicloud apicloud

注册
查看: 17768|回复: 38

[APP开发技巧] wxPay用法的理解分享

管理员

UID:253705

主题:
53
帖子:
309
云币:
687

[APP开发技巧] wxPay用法的理解分享

17768 38 | 发表于 2018-3-1 21:22:51 |阅读模式 | |
wxPay 已有升级版本模块 wxPayPlus, 请使用升级版。


通过阅读模块文档及微信开放平台文档,及论坛相关帖子,总结了一些认识,分享一下。
https://docs.apicloud.com/Client-API/Open-SDK/wxPay#b2
https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=9_1
https://pay.weixin.qq.com/wiki/d ... hapter=9_12&index=2
https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=4_3


实现微信支付只需要两步:
1. 统一下单接口
商户系统先调用该接口在微信支付服务后台生成预支付交易单,返回正确的预支付交易回话标识后再在APP里面调起支付。
接口链接

URL地址:https://api.mch.weixin.qq.com/pay/unifiedorder


2. 调起支付接口 (wxPay模块的payOrder())

APP端调起支付的参数列表
接口链接



我们先看第一个下单:

模块文档上说,为安全考虑,下单应放到服务端,而不是在APP内调用模块的getOrderId()。那么该如何做呢,其实就是服务端给微信的下单接口(https://api.mch.weixin.qq.com/pay/unifiedorder)发一个http请求,关键的是参数要按微信文档的要求拼写正确,格式就是xml字符串。必填参数10个,如下表。

  1. <xml>
  2.    <appid>wx2421b1c4370ec43b</appid>
  3.    <body>支付测试</body>
  4.    <mch_id>10000100</mch_id>
  5.    <nonce_str>1add1a30ac87aa2db72f57a2375d8fec</nonce_str>
  6.    <notify_url>http://wxpay.wxutil.com/pub_v2/pay/notify.v2.php</notify_url>
  7.    <out_trade_no>1415659990</out_trade_no>
  8.    <spbill_create_ip>14.23.150.211</spbill_create_ip>
  9.    <total_fee>1</total_fee>
  10.    <trade_type>APP</trade_type>
  11.    <sign>0CB01533B8C1EF103065174F50BCA001</sign>
  12. </xml>
复制代码
最后一个参数sign是按照微信的要求计算出来的:
第一步,设所有发送或者接收到的数据为集合M,将集合M内非空参数值的参数按照参数名ASCII码从小到大排序(字典序),使用URL键值对的格式(即key1=value1&key2=value2…)拼接成字符串stringA。
    特别注意以下重要规则:
   
  • ◆ 参数名ASCII码从小到大排序(字典序);
  • ◆ 如果参数的值为空不参与签名;
  • ◆ 参数名区分大小写;
  • ◆ 验证调用返回或微信主动通知签名时,传送的sign参数不参与签名,将生成的签名与该sign值作校验。
  • ◆ 微信接口可能增加字段,验证签名时必须支持增加的扩展字段
    第二步,在stringA最后拼接上key得到stringSignTemp字符串,并对stringSignTemp进行MD5运算,再将得到的字符串所有字符转换为大写,得到sign值signValue。
         ◆ key设置路径:微信商户平台(pay.weixin.qq.com)-->账户设置-->API安全-->密钥设置
    举例:
   
假设传送的参数如下:
        appid:                wxd930ea5d5a258f4f
    mch_id:                10000100
    device_info:        1000
    body:                test
    nonce_str:        ibuaiVcKdpRxkhJA
        
    第一步:对参数按照key=value的格式,并按照参数名ASCII字典序排序如下:
        stringA="appid=wxd930ea5d5a258f4f&body=test&device_info=1000&mch_id=10000100&nonce_str=ibuaiVcKdpRxkhJA";
        
   
第二步:拼接API密钥:
        stringSignTemp=stringA+"&key=192006250b4c09247ec02edce69f6a2d" //注:key为商户平台设置的密钥key
     sign=MD5(stringSignTemp).toUpperCase()="9A0A8659F005D6984697E2CA0A9CF3B7" //注:MD5签名方式

按照要求计算出sign后,拼接出XML字符串,商户系统服务端发送http请求,如果参数无误,微信服务端就会返回一个xml字符串,格式如下,其中prepay_id(预支付交易会话标识)会在下一步用到:
  1. <xml>
  2.    <return_code><![CDATA[SUCCESS]]></return_code>
  3.    <return_msg><![CDATA[OK]]></return_msg>
  4.    <appid><![CDATA[wx2421b1c4370ec43b]]></appid>
  5.    <mch_id><![CDATA[10000100]]></mch_id>
  6.    <nonce_str><![CDATA[IITRi8Iabbblz1Jc]]></nonce_str>
  7.    <openid><![CDATA[oUpF8uMuAJO_M2pxb1Q9zNjWeS6o]]></openid>
  8.    <sign><![CDATA[7921E432F65EB8ED0CE9755F0E86D72F]]></sign>
  9.    <result_code><![CDATA[SUCCESS]]></result_code>
  10.    <prepay_id><![CDATA[wx201411101639507cbf6ffd8b0779950874]]></prepay_id>
  11.    <trade_type><![CDATA[APP]]></trade_type>
  12. </xml>
复制代码

既然获得了微信返回的prepay_id,下面就可以调起微信进行支付了。通过wxPay模块的payOrder(), 如下

  1.         var myDate = new Date();
  2.                 var now = Date.parse(new Date()) / 1000;

  3.                 var stringA = "appid=wx123456789&noncestr=abccba&package=Sign=WXPay&partnerid=123456789&prepayid=" + prepay_id+ "&timestamp=" + now;
  4.                 var stringSignTemp = stringA + "&key=123456789abc123456789";
  5.                 var sign = md5(stringSignTemp).toUpperCase();      // 为安全考虑,sign计算放到服务端,可以通过ajax传递给APP端

  6.                 var wxPay = api.require('wxPay');
  7.                 wxPay.payOrder({
  8.                         apiKey: 'wx123456789',
  9.                         orderId: prepay_id,
  10.                         mchId: '123456789',
  11.                         nonceStr: 'abccba',
  12.                         timeStamp: now,
  13.                         package: 'Sign=WXPay',
  14.                         sign: sign
  15.                 }, function(ret, err) {
  16.                         if (ret.status) {
  17.                                 //支付成功
  18.                         } else {
  19.                                 alert(err.code);
  20.                         }
  21.                 });
复制代码
这一步的sign 和下单接口的sign没有关系,不能用下单接口的sign。计算sign用微信文档上列出的参数名,不要用模块文档上的。如下图。
请求参数                                                           
字段名变量名类型必填示例值描述
应用IDappidString(32)wx8888888888888888微信开放平台审核通过的应用APPID
商户号partneridString(32)1900000109微信支付分配的商户号
预支付交易会话IDprepayidString(32)WX1217752501201407033233368018微信返回的支付交易会话ID
扩展字段packageString(128)Sign=WXPay暂填写固定值Sign=WXPay
随机字符串noncestrString(32)5K8264ILTKCH16CQ2502SI8ZNMTM67VS随机字符串,不长于32位。推荐随机数生成算法
时间戳timestampString(10)1412000000时间戳,请见接口规则-参数规定
签名signString(32)C380BEC2BFD727A4B6845133519F3AD6签名,详见签名生成算法注意:签名方式一定要与统一下单接口使用的一致





另一位开发者分享的带服务端代码的wxPay微信支付分享帖:
https://community.apicloud.com/b ... typeid%3D134&page=1







老司机

UID:253706

主题:
177
帖子:
16974
云币:
8007
发表于 2018-3-1 21:35:32 |
感谢分享。

驾校小白

UID:670892

主题:
0
帖子:
1
云币:
3
发表于 2018-6-22 17:17:22 |
楼主,我跟你的方法一样,有个问题想问一下,如果代码正确,在手机端wifi调试的话能否正常调用支付

马路杀手

UID:157451

主题:
63
帖子:
257
云币:
504
发表于 2018-7-26 03:28:57 |
分享是一种胸怀,谢谢!

马路杀手

UID:157451

主题:
63
帖子:
257
云币:
504
发表于 2018-7-26 03:45:36 |
ad666666 发表于 2018-6-22 17:17
楼主,我跟你的方法一样,有个问题想问一下,如果代码正确,在手机端wifi调试的话能否正常调用支付 ...

这个没有问题的,我自己调试的时候就完成了支付。

主题:
4
帖子:
8
云币:
12
发表于 2018-7-31 17:35:26 |
我用同样的代码,为什么老是弹-1  。

[2018-07-31 17:33:02] [WiFi log] nonceStrC912A253D1E9BA40E2C597ED2376640 at pay.html : 83
[2018-07-31 17:33:02] [WiFi log] timeStamp:1533029583 at pay.html : 84
[2018-07-31 17:33:02] [WiFi log] prepay_id:wx311733037518753dae3aa2cd3592554082 at pay.html : 85
[2018-07-31 17:33:02] [WiFi log] sign:A16924714A1DFE2A0D761114D25A342B at pay.html : 86

驾校小白

UID:97745

主题:
0
帖子:
2
云币:
2
发表于 2018-8-23 15:02:17 |
payOrder 无法拉起微信,没有任何提示,代码是这样的ret是ajax里问后端拿的数据,如下:
{"code":"0","data":{"nonce_str":"r8MFQGnsOBS72QlO","appid":"wx750ba6e15714f96c","sign":"F292D9884A59BBD8810FDDD41875B3B9","trade_type":"APP","mch_id":"1511889501","prepay_id":"wx231454233553456d06f7041e3828257729","timestamp":1535007261},"message":"success"}

sign已经是重新签名过的,用的是微信官方的java sdk:
这是统一下单
Map<String, String> $res = $wxpay.unifiedOrder($wechat);
这是签名
String $sign = WXPayUtil.generateSignature($signData, I.env("i.wx.key"));
$signData 是这几个参数,确定没有问题
$signData.put("appid", $res.get("appid"));
$signData.put("partnerid", $res.get("mch_id"));
$signData.put("prepayid", $res.get("prepay_id"));
$signData.put("noncestr", $res.get("nonce_str"));
$signData.put("package", "Sign=WXPay");
$signData.put("timestamp", Convert.toStr($time));
如图,在js那边调用payOrder 的时候,loader会退出并且重新进入,拉不起微信,payOrder的回调里有两个打印,一个err,一个ret,都不打印,也就是说,payOrder没有被执行
这是什么情况,按道理来说,就算我参数是乱填的,也能拉起微信,然后提示签名错误这样的提示吧

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x

驾校小白

UID:97745

主题:
0
帖子:
2
云币:
2
发表于 2018-8-23 15:05:08 |
沐琴 发表于 2018-8-23 15:02
payOrder 无法拉起微信,没有任何提示,代码是这样的ret是ajax里问后端拿的数据,如下:
{"code":"0","data ...

var wxPay = api.require('wxPay');
console.log(JSON.stringify(wxPay));
wxPay.payOrder({
    apiKey: ret.data.appid,
    orderId: ret.data.prepay_id,
    mchId: ret.data.mch_id,
    nonceStr: ret.data.nonce_str,
    timeStamp: ret.data.timestamp,
    package: 'Sign=WXPay',
    sign: ret.data.sign
}, function (ret, err) {
    console.log(JSON.stringify(err));
    console.log(JSON.stringify(ret));
    if (ret.status) {
        //支付成功,给予用户提示。
        api.alert({
            title: '支付成功',
            msg: '支付结果请稍后在‘我的订单’中查询。',
        }, function (ret, err) { });
    } else {
        //  alert(err.code);
    }
});
这是完整代码,wxPay模块已经加入



新手上路

UID:696075

主题:
16
帖子:
73
云币:
91
发表于 2018-8-30 18:03:01 |
沐琴 发表于 2018-8-23 15:05
var wxPay = api.require('wxPay');
console.log(JSON.stringify(wxPay));
wxPay.payOrder({

遇到同样的问题了 ,你解决了么?

主题:
10
帖子:
26
云币:
27
发表于 2018-9-3 23:12:12 |
缺少的 $key 是 自己在微信支付商户平台 自己设置的32位key
1234下一页
您需要登录后才可以回帖 登录 | 立即注册

快速回复 返回顶部 返回列表