废话不多说直接上代码:
const getTradeNo = function() {
let date = new Date();
let arr = [
date.getFullYear(),
((date.getMonth() + 1)>=10?(date.getMonth() + 1):'0'+(date.getMonth() + 1)),
date.getDate(),
date.getHours(),
date.getMinutes(),
date.getSeconds(),
date.getMilliseconds(),
Math.floor(Math.random() * 100000)
]
let orderNo = arr.join('');
if (orderNo.length < 22) {
let len = 22 - orderNo.length;
orderNo = orderNo + Math.floor(Math.random() * len * 10).toString();
}
return orderNo;
}
生成随机字符串
// 随机字符
const getNonceStr = function() {
let str = "";
let possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
for (let i = 0; i< 32; i++) {
str += possible.charAt(Math.floor(Math.random() * possible.length))
}
return str;
};
微信支付预签名
// 微信支付预签名
const getPrePaySign = function(appid, mchId, notifyUrl, productIntro, nonceStr, openId, tradeNo, ip, price, trade_type, apiKey) {
let ret = {
appid: appid,
attach: tradeNo,
body: productIntro,
mch_id: mchId,
nonce_str: nonceStr,
notify_url: notifyUrl,
openid: openId,
out_trade_no: tradeNo,
spbill_create_ip: ip,
total_fee: price,
trade_type: 'JSAPI'
};
let stringSignTemp = raw(ret, apiKey);
let sign = md5(stringSignTemp).toUpperCase();
return sign;
}
使用axios向微信发送支付请求
productIntro: 支付的产品信息,自定义就好
appid: 小程序appid
mchId::微信支付的商户号
apiKey::商户号的apikey
notifyUrl: 支付结果的通知地址,用来微信支付服务器向我们通知支付结果
const util = require('util')
const axios = require('axios')
const parser = require('fast-xml-parser');
let J2XParse = parser.j2xParser;
const {
generateToken,
getNonceStr,
getPrePaySign,
getTradeNo
} = require('../../../core/util')
const { V_User} = require('../../models/violin/v_user')
const { Order } = require('../../models/violin/v_order')
const j2xParser = new J2XParse();
class WXPlay {
// 支付
static async requestWXPay(wxInfo) {
let tradeNo = getTradeNo();
let nonceStr = getNonceStr();
let productIntro = wxInfo.productIntro;
let appid = global.config.violinWx.appid;
let mchId = global.config.violinWx.mchId;
let notifyUrl = global.config.violinWx.notifyUrl;
let apiKey = global.config.violinWx.payApiKey;
let signStr = getPrePaySign(appid, mchId, notifyUrl, productIntro, nonceStr, wxInfo.openId, tradeNo, wxInfo.ip, wxInfo.payAmount, 'JSAPI', apiKey);
let xmlData = {
xml: {
appid: global.config.violinWx.appid,
attach: tradeNo,
body: productIntro,
mch_id: global.config.violinWx.mchId,
nonce_str: nonceStr,
notify_url: global.config.violinWx.notifyUrl,
openid: wxInfo.openId,
out_trade_no: tradeNo,
spbill_create_ip: wxInfo.ip,
total_fee: wxInfo.payAmount,
trade_type: 'JSAPI',
sign: signStr
}
}
let sendData = j2xParser.parse(xmlData);
let wxUrl = global.config.violinWx.payUrl
const result = await axios({
method: 'POST',
url: wxUrl,
headers: {
'Content-Type': 'text/xml'
},
data: sendData
});
if (result.err) {
return err;
}
if (result.data && parser.validate(result.data)) {
let jsonObj = parser.parse(result.data);
if (jsonObj.xml.return_code === 'SUCCESS' && jsonObj.xml.result_code === 'SUCCESS') {
let order = {
appid: global.config.violinWx.appid,
orderNo: tradeNo,
orderName: wxInfo.productIntro,
orderType: wxInfo.orderType,
userId: wxInfo.userId,
mch_id: global.config.violinWx.mchId,
payAmount: wxInfo.money,
orderStatus: 0,
prepay_id: jsonObj.xml.prepay_id,
entriesId: wxInfo.entriesId
}
await Order.addOrder(order);
}
return jsonObj;
}
return result;
}
}
module.exports = {
WXPlay
}
谢谢!