前端代码
weChatPay() {
uni.request({
url: 'http://www.xxxx.com/wechat/wxmporder',//调用下单接口
data: {id},
dataType: 'json',
method: 'POST'
}).then(response => {
uni.requestPayment({
provider: 'wxpay',
timeStamp: pay.timeStamp + '',//注意这里要字符串,不能是数字
nonceStr: pay.nonceStr,
package: pay.package,
signType: pay.signType,
paySign: pay.paySign,
success: function(res) {//支付成功回调
uni.showModal({
title: '提示',
content: '支付成功',
showCancel: false,
success: res => {
},
});
console.log('success:' + JSON.stringify(res));
},
fail: function(err) {
console.log('fail:' + JSON.stringify(err));
}
});
})
}
后台代码
router.all('/wxmporder', async function (req, res, next) {
const appid = '小程序appid'
//小程序登录用户openId
const openid = '';
const total_fee = 1;//整数,单位分
const body = '商品1'
const moment = require('moment')
const out_trade_no = moment(new Date()).format('YYYYMMDDHHmmss')
const notify_url = 'http://www.xxxx.com/wechat/wechatNotify'//异步通知地址
const prepay_id = await Unifiedorder(appid, openid, body, total_fee, out_trade_no, notify_url, 'JSAPI')//预支付交易会话标识
const stringUtils = require('../utils/stringUtils')
const responseData = {
appId: appid,
timeStamp: new Date().getTime(),
nonceStr: stringUtils.randomString(20),
package: 'prepay_id=' + prepay_id,
signType: 'MD5',
}
const CryptoJS = require('crypto-js');
const resultSignStr = getSignStr(responseData)
responseData.paySign = CryptoJS.MD5(resultSignStr + '&key=' + mch_key).toString().toUpperCase()
res.send({ pay: responseData })
})
拼接签名字符串方法
function getSignStr(map) {
let sortKeys = Object.keys(map).sort((a, b) => {
let index = 0;
while (true) {
let ai = index >= a.length ? 0 : a[index].charCodeAt()
let bi = index >= b.length ? 0 : b[index].charCodeAt()
let sub = ai - bi;
if (sub != 0 || (index >= a.length && index >= b.length)) {
return sub;
}
index++;
}
})
let arr = [];
for (let i in sortKeys) {
let key = sortKeys[i];
let val = map[key];
if (val == null || val == '') {
continue
}
arr.push(key + '=' + val)
}
return arr.join('&')
}
统一下单方法
//微信统一下单
function Unifiedorder(appid, openid, body, total_fee, orderNo, notify_url, trade_type) {
return new Promise(async (resolve, reject) => {
try {
const out_trade_no = orderNo
const spbill_create_ip = '192.168.3.20';
const stringUtils = require('../utils/stringUtils')
const nonce_str = stringUtils.randomString(20)
let map = {
appid, mch_id, nonce_str, body, out_trade_no, total_fee, spbill_create_ip, notify_url, trade_type, openid
}
const CryptoJS = require('crypto-js');
const signStr = getSignStr(map);
console.log('签名字符串:' + signStr)
//MD5签名转大写
const sign = CryptoJS.MD5(signStr + '&key=' + mch_key).toString().toUpperCase()
console.log(sign)
let url = 'https://api.mch.weixin.qq.com/pay/unifiedorder'
map.sign = sign
//组装xml数据
var formData = "<xml>";
formData += "<appid>" + appid + "</appid>"; //appid
formData += "<body><![CDATA[" + body + "]]></body>";
formData += "<mch_id>" + mch_id + "</mch_id>"; //商户号
formData += "<nonce_str>" + nonce_str + "</nonce_str>"; //随机字符串,不长于32位。
formData += "<notify_url>" + notify_url + "</notify_url>";
formData += "<out_trade_no>" + out_trade_no + "</out_trade_no>";
formData += "<spbill_create_ip>" + spbill_create_ip + "</spbill_create_ip>";
formData += "<total_fee>" + total_fee + "</total_fee>";
formData += "<trade_type>" + trade_type + "</trade_type>";
formData += "<openid>" + openid + "</openid>";
formData += "<sign>" + sign + "</sign>";
formData += "</xml>";
console.log('统一下单参数:' + formData)
const http = require('../utils/httpUtils')
let result = await http.post(url, formData)
console.log('统一下单结果:' + result)
var xmlreader = require("xmlreader");
xmlreader.read(result, function (errors, response) {
if (!errors) {
const return_code = response.xml.return_code.text()
if (return_code == 'SUCCESS') {
const prepay_id = response.xml.prepay_id.text()//预支付交易会话标识
resolve(prepay_id)
}
} else {
reject(errors)
}
});
} catch (error) {
reject(error)
}
})
}