前言:
最近在项目中需要接通微信支付接口,然后自己也是深受其害,一个前端小白写接口写的要哭了,也百度了很多东西,也查了很多的资料,后面发现的确是有点坑……然后就想着总结下开发中遇到的坑,让大家不要在踩我的坑了,前端小白,求轻喷
技术栈:
- nodejs
- ajax(项目封装好的)
- express
- 下载一些所需要依赖的包文件
npm install md5
npm install xml2js
- 在服务层里面写需要的请求接口,扔给前端进行请求
router.post('/payGet', function (req, res) {
1.引用一下会用到的外部依赖let MD5 = require('md5')
let request = require('request')
let xml2js = require('xml2js')
2.配置微信需要的信息let url = 'https://api.mch.weixin.qq.com/pay/unifiedorder'
let appid = xxxxxx(appid号)
let mchId = xxxxx(商户号)let notifyUrl = 'http://xxxxxxx.com/api/users/receive'(支付成功微信返回的回调函数)
let outTradeNo = req.body.outTradeNo(我们自己的订单号)
let totalFee = parseFloat(req.body.money) * 100 (这个就是钱啦,但是要注意单位是分的)
let body = '会费缴纳'(这个是我们要给这个商品的介绍)
let nonceStr = new Date().getTime() (这个是需要一个随机字符串)
let tradeType = 'NATIVE' (我个人理解是什么支付方式)
注意:还有很多可以配置的参数,请到微信官方api查看,这里就不一一介绍了
3.生成字符串和对应的签名(特别重要)let stringA = 'appid='+appid+'&body='+body+'&mch_id='+mchId+'&nonce_str='+nonceStr+'¬ify_url='+notifyUrl+'&out_trade_no='+outTradeNo+'&spbill_create_ip='ip白名单'&total_fee='+totalFee+'&trade_type='+tradeType'
let stringSignTemp = stringA + '&key=UvibcDS4s83vhZ5XVn4DK5Hnlkas0Yw0'
let sign = MD5(stringSignTemp).toUpperCase()
4.生成对应的xml并进行请求const formData = <xml><appid>${appid}</appid><body>${body}</body><mch_id>${mchId}</mch_id><nonce_str>${nonceStr}</nonce_str><notify_url>${notifyUrl}</notify_url><out_trade_no>${outTradeNo}</out_trade_no><spbill_create_ip>IP白名单</spbill_create_ip><total_fee>${totalFee}</total_fee><trade_type>NATIVE</trade_type><sign>${sign}</sign></xml>
return request({
url: url,
method: 'POST',
body: formData,
header: 'Content-Type: text/html; charset=utf-8'(这里有一个坑,没设置有时候会报"签名错误")
}, function (err, response, body) {
if (!err && response.statusCode === 200) {
xml2js.parseString(body, function (err, json) {
if (!err) {
var result = formMessage(json.xml)
res.json(result)
}
})
}
})
})
5.处理xml的对应方法(参照别人写的方法)function formMessage(result) {
var message = {}
if (typeof result === 'object') {
var keys = Object.keys(result)
for (var i = 0; i < keys.length; i++) {
var item = result[keys[i]]
var key = keys[i]
if (!(item instanceof Array) || item.length === 0) {
continue
}
if (item.length === 1) {
var val = item[0]
if (typeof val === 'object') {
message[key] = formMessage(val)
} else {
message[key] = (val || '').trim()
}
} else {
message[key] = []
for (var j = 0, k = item.length; j < k; j++) {
message[key].push(formMessage(item[j]))
}
}
}
}
return message
}
6.回调接口处理router.post('/receive', function (req) {
var xml2js = require('xml2js')
var xmlParser = new xml2js.Parser({ explicitArray: false, ignoreAttrs: true })
xmlParser.parseString(req.body, function (err, result) {
let data = JSON.parse(JSON.stringify(result)).xml.out_trade_no
//把微信返回回来的对应数据存进数据库,我是以订单号是否存在的
User.paylog(data, {'jsonData': req.body})
})
})
注意:这里是要返回给微信一个收到信息的标示,但是我不知道怎么传递,有知道的大神麻烦告诉下我,这个东西我有点懵 - 前端操作(请求对应接口去生成对应需要支付的二维码)
http.post('/api/users/payGet', {
money: $('.payMoney').data('money'),
outTradeNo: $('.payMoney').data('oid')
})
.then(c => {
$('#code').qrcode({
render: 'canvas',
size: 150,
text: JSON.parse(c).code_url
})
}) - 监控微信支付是否成功
我的做法是写一个接口去调用查订单的操作,然后根据返回的状态判断是否支付成功或是其他状态再去进行对应的逻辑操作。这个接口我是写了一个定时器,每500ms就去进行一次请求,然后但支付成功后,我会清除这个定时器。 - 接微信签名一直报错的一些地方
1.商户的密钥错了,我在开发过程中,就遇到这种情况,在微信的校验接口上面怎么测都没问题,但是我请求的接口一直报签名错误,后面看到别人也出现这个问题,就重新生成密钥,然后就可以了。。。
2.还有一个就是签名的时候没有按照正确的ascii进行先后排序,开发的时候也遇到问题了,这个还真的不怎么会注意,但是不注意就过不了
3.我们请求的时候没有在请求头加上utf-8,这个问题我没遇到过,因为一上来就写好了,但是你body介绍商品的时候肯定是会有中文的。