Nodejs 实现微信支付 v3 与 v2

2,927 阅读1分钟

微信支付v3

const Koa = require("koa");
const app = new Koa();
const axios = require("axios");
const fs = require("fs");
const crypto = require("crypto");

/**
 * 生成随机字符串
 * @param {number} len 字符串长度
 */
function createRandomString(len) {
  let data = "ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678";
  let str = "";
  for (let i = 0; i < len; i++) {
    str += data.charAt(Math.floor(Math.random() * data.length));
  }
  return str;
}

/**
 * 微信支付v3 签名生成
 * @param {string} method 请求方法
 * @param {string} url
 * @param {number} timestamp 时间戳 秒级
 * @param {string} nonce_str 随机字符串
 * @param {Object} order 主体信息
 */
function createSign(method, url, timestamp, nonce_str, order) {
  let signStr = `${method}\n${url}\n${timestamp}\n${nonce_str}\n${JSON.stringify(
    order
  )}\n`;
  let cert = fs.readFileSync("./apiclient_key.pem", "utf-8");
  let sign = crypto.createSign("RSA-SHA256");
  sign.update(signStr);
  return sign.sign(cert, "base64");
}

/**
 * 微信支付v3
 * @param {Object} order 订单信息
 */
function v3Pay(order, serial_no) {
  let timestamp = Math.floor(new Date().getTime() / 1000);
  let nonce_str = createRandomString(32);
  let signature = createSign(
    "POST",
    "/v3/pay/transactions/native",
    timestamp,
    nonce_str,
    order
  );
  let Authorization = `WECHATPAY2-SHA256-RSA2048 mchid="xxxx",nonce_str="${nonce_str}",timestamp="${timestamp}",signature="${signature}",serial_no="${serial_no}"`;
  axios
    .post("https://api.mch.weixin.qq.com/v3/pay/transactions/native", order, {
      headers: { Authorization: Authorization },
    })
    .then((res) => {
      console.log(res);
    })
    .catch((err) => {
      console.log(err);
    });
}
let order = {
  appid: "xxxx",
  mchid: "xxxx",
  description: "测试扫码支付",
  out_trade_no: "wzm20210209",
  amount: {
    total: 1,
  },
  notify_url: "https://xxx.cn/",
};
v3Pay(order, "证书序列号");

app.listen(3000);

可上证书(apiclient_cert.pem)到 myssl.com/cert_decode… 查看序列号 微信文档 pay.weixin.qq.com/wiki/doc/ap…

微信支付v2

const Koa = require("koa");
const app = new Koa();
const xml2js = require("xml2js");
const axios = require("axios");
const crypto = require("crypto");
const hash = crypto.createHash("md5");

let info = {
  appid: "xxxx",
  mch_id: "xxxx",
  nonce_str: "xxxx",
  spbill_create_ip: "123.12.12.123", // 貌似随便填
  body: "测试扫码支付",
  out_trade_no: "wzm20210215",
  total_fee: 1,
  notify_url: "https://xxxx.cn/",
  trade_type: "NATIVE",
};

/**
 *
 * @param {object} info 订单信息
 * @param {string} key 商户key
 */
function createSignV2(info, key) {
  let stringA = "";
  let keys = Object.keys(info);
  keys.sort();
  console.log(keys);
  for (let item of keys) {
    stringA += `${item}=${info[item]}&`;
  }
  let stringSignTemp = `${stringA}key=${key}`;
  return hash.update(stringSignTemp).digest("hex");
}
/**
 * 微信支付 v2
 */
function v2Pay(info) {
  let sign = createSignV2(info, "xxxx");
  info.sign = sign;
  let builder = new xml2js.Builder();
  let xmlData = builder.buildObject(info);
  axios
    .post("https://api.mch.weixin.qq.com/pay/unifiedorder", {
      xmlData,
      headers: { "Content-Type": "application/xml" },
    })
    .then((res) => {
      var parser = new xml2js.Parser({ explicitArray: false });
      parser
        .parseStringPromise(res.data)
        .then(function (result) {
          console.dir(result);
        })
        .catch(function (err) {
          // Failed
        });
    });
}
v2Pay(info);

微信文档 pay.weixin.qq.com/wiki/doc/ap…