nodejs开发微信小程序支付

自行准备好商户api和app密钥,需要公众号为服务号类型,还要有绑定小程序,这里使用的是小程序支付

官网链接 https://pay.weixin.qq.com/wiki/doc/apiv3/open/pay/chapter2_8_0.shtml
在这里插入图片描述

本文支付逻辑:前端先调用微信login接口拿到code,接着调用后端get_openId接口拿到openid,然后再生成预支付信息获取预支付id,再然后创建前端拉起支付需要的支付参数,最后返回支付参数给前端,前端再通过wx.requestPayment方法拉起微信支付页面,再最后用户确定并完成了支付

一、做好前端界面

在这里插入图片描述
点击开始支付就调用微信登录接口,我这里由于是测试支付就直接拉起支付弹窗。

wx.login({
  success: res => {
    wx.request({
      url: 'https://www.xxx.asia/node/weapp/pay/login',
      method: 'POST',
      data: {
        code: res.code,
        order: {
          price: 1, //单位 分。只能是分
          description: "Image形象店-深圳腾大-QQ公仔"
        }
      },
      success: (res1) => {
        wx.requestPayment({
          timeStamp: res1.data.data.timestamp,
          nonceStr: res1.data.data.nonce_str,
          package: res1.data.data.package,
          signType: res1.data.data.signType,
          paySign: res1.data.data.paySign,
          success() {
            wx.showModal({
              title: '提示',
              content: '支付成功!',
              showCancel: false,
            });
          },
          fail(err) {
            console.log('fail:' + JSON.stringify(err));
          }
        });
      }
    })
  }
})

二、后端代码

1、首先建立好一个普通的node后端服务

app.listen(3245, () => {
  console.log(
    "服务在http://localhost:3245",
    "时间:" + new Date().toLocaleString()
  );
});

2、获取openid的接口

// 根据微信code获取 openid
async function getOpenId(code = "") {
  try {
    const res = await instance({
      url: `https://api.weixin.qq.com/sns/jscode2session?appid=xxx&secret=xxx&js_code=${code}&grant_type=authorization_code`,
      method: "get",
    });
    return res.data.openid;
  } catch (error) {
    return error.response.request.data;
  }
}

3、获取支付信息获取交易会话标识 预支付id prepay_id

  async getPrepayInfo() {
    let timestamp = Math.floor(new Date().getTime() / 1000);
    let nonce_str = generateNonceStr(32);
    let wxOrderInfo = {
      mchid: "xxx",
      appid: "xxx",
      notify_url: "https://www.xxx.asia/weapp/pay/isSuccess", // 回调地址(必须是公网地址) 这里需要我们自行实现用来接收支付结果信息
      out_trade_no: nonce_str, // 上面创建的订单的订单号 我们自己自定义的
      description: this.order.description, // 商品描述
      amount: {
        total: this.order.price, // 单位为分
        currency: "CNY",
      },
      payer: {
        openid: this.openid, // 用户的openid
      },
    };
    let signature = this.createOrderSign(timestamp, nonce_str, wxOrderInfo);
    let Authorization = `WECHATPAY2-SHA256-RSA2048 mchid="商户号mchid",nonce_str="${nonce_str}",timestamp="${timestamp}",signature="${signature}",serial_no="商户API证书序列号"`;
    this.prepay_id = await getPrepayId(wxOrderInfo, Authorization);
  }
1、generateNonceStr代码
// 生成随机字符串
function generateNonceStr(len) {
  let data = "ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678";
  let str = "";
  for (let i = 0; i < len; i++) {
    str += data.charAt(Math.floor(Math.random() * data.length));
  }
  return str;
}
2、createOrderSign代码
  createOrderSign(timestamp, nonce_str, wxOrderInfo) {
    // 签名串
    let signStr = `POST\n/v3/pay/transactions/jsapi\n${timestamp}\n${nonce_str}\n${JSON.stringify(
      wxOrderInfo
    )}\n`;
    // 读取API证书文件内容 apiclient_key.pem的内容
    let cert = fs.readFileSync("./utils/cert/apiclient_key.pem", "utf-8");
    // 创建使用 RSA 算法和 SHA-256 散列算法的签名对象
    let sign = crypto.createSign("RSA-SHA256");
    // 对签名串进行加密处理
    sign.update(signStr);
    return sign.sign(cert, "base64");
  }
3、getPrepayId代码
async function getPrepayId(wxOrderInfo = {}, Authorization = "") {
  try {
    const res = await instance({
      url: "https://api.mch.weixin.qq.com/v3/pay/transactions/jsapi",
      method: "post",
      data: wxOrderInfo,
      headers: {
        Authorization,
        Accept: "application/json",
        "Content-Type": "application/json",
      },
    });
    return res.data.prepay_id;
  } catch (error) {
    return error.response.request.data;
  }
}

4、生成拉起支付需要的支付参数

  createPaySign() {
    let timeStamp = Math.floor(new Date().getTime() / 1000).toString();
    let nonceStr = generateNonceStr(32);
    let signStr = `${appid}\n${timeStamp}\n${nonceStr}\nprepay_id=${this.prepay_id}\n`;
    let cert = fs.readFileSync("./utils/cert/apiclient_key.pem", "utf-8");
    let sign = crypto.createSign("RSA-SHA256");
    sign.update(signStr);
    this.paySign = {
      paySign: sign.sign(cert, "base64"),
      timestamp: timeStamp,
      nonce_str: nonceStr,
      signType: "RSA",
      package: "prepay_id=" + this.prepay_id,
    };
  }

5、返回支付参数给前端

app.post("/weapp/pay/login", jsonParser, async (req, res) => {
  // 接收的前端数据
  const { code, order } = req.body;
  const openid = await getOpenId(code);
  const weappPayApi_v3 = new WeappPayApi_v3(openid, order);
  await weappPayApi_v3.getPrepayInfo();
  weappPayApi_v3.createPaySign();
  res.send({ data: weappPayApi_v3.paySign, success: true });
});

6、完成!如果需要demo代码可以点击下面的链接

https://download.csdn.net/download/lcc2001/89335765

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

xl__qd

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值