趟平微信支付中的那些坑儿
这两天一直在研究微信支付,在此跟大家分享一下我遇到并解决的问题,希望能为大家提供便利,也便于后续深入研究。
两套文档问题
微信 H5 支付有两份文档,一份在微信公众平台,另一份在商户平台,且内容存在差异。下面是新版的前端代码(后端代码较多,贴上前端代码以理顺思路):
$(function() {
wx.config({
debug: true,
appId: '<?php echo $signPackage["appId"];?>',
timestamp: <?php echo $signPackage["timestamp"];?>,
nonceStr: '<?php echo $signPackage["nonceStr"];?>',
signature: '<?php echo $signPackage["signature"];?>',
jsApiList: [
"chooseWXPay" // 支付
] // 所有要调用的 API 都要加到这个列表中
});
$('#aaa').on('click', function() {
wx.ready(function() {
wx.chooseWXPay({
appId: '<?php echo $da['appId'] ?>',
timestamp: '<?php echo $da['timeStamp'] ?>',
nonceStr: '<?php echo $da['nonceStr'] ?>',
package: '<?php echo $da['package'] ?>',
signType: 'MD5',
paySign: '<?php echo $da['paySign'] ?>',
success: function(res) {
if (res.errMsg == "chooseWXPay:ok") {
alert('支付成功');
} else {
alert(res.errMsg);
}
},
cancel: function(res) {
alert('支付取消');
}
});
});
});
});
这里的 $da
数组是在后台使用微信支付的 DEMO 里面提供的。两份支付文档的区别主要在于前端。实际上,拿到预支付标识 prepay_id
后,选择哪套前端代码都可以完成支付流程。
商户订单号重复问题
官方文档提到,调用统一下单接口时可能会出现商户订单号重复的错误。但我使用官方的 PHP DEMO 进行测试,多次点击支付(不实际支付)再返回,订单号一直保持不变,却未收到重复提示。经过在网上查找资料并反复测试,我发现:要想重复提交订单而不出现错误,商品描述、商品金额和商户订单号这三个参数必须与创建订单时保持一致。也就是说,调用统一订单 API 时,这三个参数提交相同就不会提示重复,任何一个参数发生变化都会提示重复。
签名问题
签名环节很容易出错。无论是使用微信 JSSDK 支付还是微信 DEMO 的方法,都需要进行两次签名,签名方法如下:
- 将需要 POST 到微信服务器的参数(除
sign
外)赋值到一个数组array
中,并按照字典顺序排序,在 PHP 中可使用ksort
函数实现。 - 将数组转换为字符串,格式为
k1=v1&k2=v2&...kN=vN
。 - 在该字符串后面加上 KEY 值(此 KEY 值在微信支付商户后台由用户自行设定),此时字符串变为
k1=v1&k2=v2&...kN=vN&key=KEY
。 - 对该字符串进行 MD5 加密,即
string = md5(string)
。 - 将加密后的字符串转换为大写,即
sign = strtoupper(string)
。
此外,签名还有一个容易出错的地方,在 JS 中时间戳使用 timestamp
,而在后端(PHP 端)则要求使用 timeStamp
。
支付授权目录问题
最后,我遇到了一个让我十分困惑的问题,我怀疑是微信支付授权目录存在问题。我的情况如下:
前一天下午,我发起支付的页面是 域名/abc/def/pay.php
,测试目录我设置为 域名/abc/
,下午测试时支付正常。但晚上给老板测试支付时,却提示支付授权目录不对。仔细检查后发现,正确的测试目录应该是 域名/abc/def/
。然而,将测试目录修改正确,把真正的支付授权目录也修改好,并将微信号加入白名单后,支付仍然失败。半小时后,支付又突然恢复正常。
第二天,我测试官方 DEMO,发现将其放在域名下的任何一个文件夹都能正常支付,无论该目录是否授权。将我从白名单中删除后,在我的测试目录下支付依然成功。但当我取消关注公众号再重新关注时,就会提示不在白名单。
总结来说,我遇到的问题是:为什么支付授权目录一会管用一会不管用呢?期待各位大佬的回复,关注“泰斗社区”了解更多。