首先要去获取接入支付的商户号以及各种信息
这是自己第一次接入微信支付,xml2js插件主要用于解析xml文本,以及将自己的信息转换为微信支付所需要的xml字符串类型。
在接入v2支付过程中比较简单,建议还是写法以面向对象编程为主,方便后期添加其他的支付方式,native支付接入我主要是适用于网站上使用,在此做个备忘录,避免下次写忘记。
const xml2js = require("xml2js");
const axios = require("axios");
const crypto = require("crypto");
// 订单号生成函数
function randomNumber(length = 32) {
const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
let noceStr = '', maxPos = chars.length;
while (length--) noceStr += chars[Math.random() * maxPos | 0];
return noceStr;
}
// 加密签名
function createSignV2(info, key) {
const hash = crypto.createHash("md5");
let stringA = "";
let keys = Object.keys(info);
keys.sort();
for (let item of keys) {
stringA += `${item}=${info[item]}&`;
}
let stringSignTemp = `${stringA}key=${key}`;
return hash.update(stringSignTemp).digest("hex");
}
/**
* 购买下单
* @param {*} money 购买金额
* @returns 下单结果
*/
async function wxpay(money) {
let orderInfo = {
// 商户号ID
mch_id: "162xxxxxxx",
// 公共账号ID
appid: "wx0xxxxxxxxxxx",
// 商品描述
body: "我是在购买名叫xx的商品",
// 支付通知地址 post 接口 在线能访问的
notify_url: "https://www.osdaklshad.cn",
// 支付类型
trade_type: "NATIVE",
// 随机字符串 支付必传
nonce_str: randomNumber(),
// 订单号
out_trade_no: randomNumber(),
// 金额 以分为单位
total_fee: Number(money) * 100
};
// 签名密钥
orderInfo.sign = createSignV2(orderInfo, "2962bxxxxxxxxxxxxxxxxxxxxxxxxa4f")
let builder = new xml2js.Builder();
let xmlData = builder.buildObject(orderInfo);
try {
const wx_pay = await axios
.post("https://api.mch.weixin.qq.com/pay/unifiedorder", {
xmlData,
headers: { "Content-Type": "application/xml" },
});
var parser = new xml2js.Parser({ explicitArray: false });
const wx_result = await parser.parseStringPromise(wx_pay.data);
wx_result.xml.out_trade_no = orderInfo.out_trade_no;
wx_result.xml.total_fee = orderInfo.total_fee;
return wx_result.xml;
} catch (err) {
console.log('支付报错:', err)
}
}
/**
* 取消订单
* @param {*} goods 订单号
* @returns
*/
async function closeGood(goods) {
let closeInfo = {
// 商户号ID
mch_id: "162xxxxxxx",
// 公共账号ID
appid: "wx08ae8bxxxxxxxxx",
out_trade_no: goods,
nonce_str: randomNumber(),
}
closeInfo.sign = createSignV2(closeInfo, "2962b0e189xxxxxxxxxxxxxxxxx")
let builder = new xml2js.Builder();
let xmlData = builder.buildObject(closeInfo);
try {
const wx_close = await axios
.post("https://api.mch.weixin.qq.com/pay/closeorder", {
xmlData,
headers: { "Content-Type": "application/xml" },
});
var parser = new xml2js.Parser({ explicitArray: false });
const wx_result = await parser.parseStringPromise(wx_close.data);
console.log('取消:', wx_result.xml)
return wx_result.xml;
} catch (err) {
console.log('支付报错:', err)
}
}
/**
* 订单状态查询
* @param {*} goods 订单号
* @returns
*/
async function queryGood(goods) {
let queryInfo = {
// 商户号ID
mch_id: "162xxxxxxxx2",
// 公共账号ID
appid: "wx08axxxxxxx",
out_trade_no: goods,
nonce_str: randomNumber(),
}
queryInfo.sign = createSignV2(queryInfo, "2962b0e1xxxxxxxxxxxxxxxxx")
let builder = new xml2js.Builder();
let xmlData = builder.buildObject(queryInfo);
try {
const wx_query = await axios
.post("https://api.mch.weixin.qq.com/pay/orderquery", {
xmlData,
headers: { "Content-Type": "application/xml" },
});
var parser = new xml2js.Parser({ explicitArray: false });
const wx_result = await parser.parseStringPromise(wx_query.data);
console.log('查询值:', wx_result.xml)
return wx_result.xml;
} catch (err) {
console.log('支付报错:', err)
}
}
module.exports = {
wxpay,
closeGood,
queryGood
};
ps:切记回调地址是在线能访问的https或http 的post接口,才能回调成功。
我这里只写了几种实用的方法