nodejs后端,调用微信支付恶心瞬间

近期我各种百度搜索wx支付功能,不过好多文章都有各种Bug,再加上微信小程序的微信支付真的恶心至极~~~~然后机制的我东拼西凑的功夫不负有心人我终于把微信支付功能拼接起来了。
首先nodejs需要的库。
xml2js、request、axios、crypto
怎么安装相信大家都懂了,废话不多说上才艺~
首先需要获取微信openID。

/** 小程序代码 */
wx.login({
  success:function(res){
    // 发送后端校验
    wx.request({
      url: url+'/all/wx',
      data:{
        code: res.code,
      },
      success(res){
        var openid = res.data.openid
        // 保存storage
        wx.setStorageSync('openid', openid)
      }
    })
  }
})

/** node代码 */
/**获取wxOpenID */
router.get('/wx', async(req, res)=>{
  var query = req.query
  let {data} = await axios.get('https://api.weixin.qq.com/sns/jscode2session?',{
    params:{
      appid: 小程序 appId,// 小程序 appId
      secret: 小程序 appSecret,// 小程序 appSecret
      js_code:`${query.code}`,// 登录时获取的 code
      grant_type:'authorization_code',// 授权类型,此处只需填写 authorization_code
    }
  })
  res.send(data)
})

获取到openID发到后端

/** 小程序代码 */
wx.request({
  url: url+'/all/wxPay',
  data:{
    money:1,// 支付金额
    openid: wx.getStorageSync('openid'),// openID
    title:title,// 标题
    id:id,// 支付ID这里我做了一个随机ID
  },
  success:res =>{
    let data = res.data.result
    if (res.data.error_code == 0) {
      var _signtext = "appId=" + APPID + "&nonceStr=" + res.data.result.nonceStr + "&package=prepay_id=" + res.data.result.package + "&signType=MD5&timeStamp=" + res.data.result.timeStamp + "&key=" + MchKey;
      // Md5签名,所谓签名就是再次加密一下然后再进行调取
      var sign = hexMD5(_signtext)
      //成功调用requestPayment
      // 注意星号一定要注意注意
      wx.requestPayment({
        timeStamp: data.timeStamp + '',//*** 一定要在后面 + '',否则没办法调取
        nonceStr: data.nonceStr,
        package: "prepay_id=" + data.package,//*** 一定要在前面加prepay_id=,否则也是没办法调取
        signType: 'MD5', //签名算法
        paySign: sign.toUpperCase(),// 二次签名
        success:e =>{
          console.log(e)
        },
        fail:err =>{
          console.log(err)
        }
      })
    } else {
      console.log(res, "支付失败!"+res.msg);
    }
  }
})

/** node代码 */
router.get('/wxPay',async (req, res)=>{
  var {money,openid,id,title} = req.query

  var nonceStr = util.randomStr()// 随机字符串

  //签名
  var signoption = {
    appid: config.wxConfig.APPID,//小程序appid
    body: title,//商品描述
    mch_id: config.wxConfig.mchID,//商户号
    nonce_str: nonceStr,//随机字符串
    notify_url:  'http://XXXXXX/', //回调地址
    openid: openid,//交易类型是JSAPI的话,此参数必传   可从过code获取openid
    out_trade_no: id,//商品订单号
    spbill_create_ip: '000.000.0.0',//因为微信支付需要有回调url,所以没法确定你的公网ip就没法发送订单支付通知给你,所以提供一个解析的正常ip就好
    total_fee: money,//商品价格
    trade_type: 'JSAPI'//交易类型,JSAPI为小程序交易类型
  };
  var sign = util.createSign(signoption)

  let reqUrl = 'https://api.mch.weixin.qq.com/pay/unifiedorder';

  // xml格式
  //这个顺序要和签名顺序一致  
  let formData = `<xml>
                      <appid>${signoption.appid}</appid>
                      <body>${title}</body>
                      <mch_id>${config.wxConfig.mchID}</mch_id>
                      <nonce_str>${nonceStr}</nonce_str>
                      <notify_url>http://localhost:XXXXX/</notify_url>
                      <openid>${openid}</openid>
                      <out_trade_no>${id}</out_trade_no>
                      <spbill_create_ip>000.000.0.0</spbill_create_ip>
                      <total_fee>${money}</total_fee>
                      <trade_type>JSAPI</trade_type>
                      <sign>${sign}</sign>
                  </xml>
  `
  // 发送请求
  request({
      url: reqUrl,
      method: "POST",
      json: true,
      headers: {
          "content-type": "application/json"
      },
      body: formData
  },function(error, response, body){
      if (!error && response.statusCode === 200) {
          try {
              xml2js.parseString(body, function (error, result) {
                  let reData = result.xml;

                  let responseData = {
                      timeStamp: new Date().getTime(),// 时间戳
                      nonceStr: reData.nonce_str[0],// 随机字符串
                      package: reData.prepay_id[0],// 微信返回链接
                      paySign: reData.sign[0],// 签名
                  };
                // 返回客户端
                res.json({ error_code: 0, result: responseData });
              });
          } catch (e) {
              console.log(e);
          }
      }
  })

node这里面所需要注意就是签名和xml,还有随机字符串

  //签名【一定严格要求顺序】
  var signoption = {
    appid: config.wxConfig.APPID,//小程序appid
    body: title,//商品描述
    mch_id: config.wxConfig.mchID,//商户号
    nonce_str: nonceStr,//随机字符串
    notify_url:  'http://XXXXXX/', //回调地址
    openid: openid,//交易类型是JSAPI的话,此参数必传   可从过code获取openid
    out_trade_no: id,//商品订单号
    spbill_create_ip: '000.000.0.0',//因为微信支付需要有回调url,所以没法确定你的公网ip就没法发送订单支付通知给你,所以提供一个解析的正常ip就好
    total_fee: money,//商品价格
    trade_type: 'JSAPI'//交易类型,JSAPI为小程序交易类型
  };
  // 调取createSign进行签名
  var sign = util.createSign(signoption)

//签名算法(把所有的非空的参数,按字典顺序组合起来+key,然后md5加密,再把加密结果都转成大写的即可
createSign(obj){
    var stringA = 'appid=' + obj.appid + '&body=' + obj.body + '&mch_id=' + obj.mch_id + '&nonce_str=' + obj.nonce_str + '&notify_url=' + obj.notify_url + '&openid=' + obj.openid + '&out_trade_no=' + obj.out_trade_no + '&spbill_create_ip=' + obj.spbill_create_ip + '&total_fee=' + obj.total_fee + '&trade_type=' + obj.trade_type;
    var stringSignTemp = stringA + '&key=' + config.wxConfig.SHOP_KEY;
    var hash = crypto.createHash('md5');
    stringSignTemp = hash.update(stringSignTemp);
    var signValue = hash.digest('hex');
    return signValue.toUpperCase();
},

xml格式

//这个顺序要和签名顺序一致  
  let formData = `<xml>
                      <appid>${signoption.appid}</appid>
                      <body>${title}</body>
                      <mch_id>${config.wxConfig.mchID}</mch_id>
                      <nonce_str>${nonceStr}</nonce_str>
                      <notify_url>http://localhost:8080/</notify_url>
                      <openid>${openid}</openid>
                      <out_trade_no>${id}</out_trade_no>
                      <spbill_create_ip>000.000.0.0</spbill_create_ip>
                      <total_fee>${money}</total_fee>
                      <trade_type>JSAPI</trade_type>
                      <sign>${sign}</sign>
                  </xml>
  `

随机字符串

//产生一个随机字符串【32位】
    randomStr(){
        var str = "";    
        var arr = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'];
         
         for(var i=1;i<=32;i++){
             var random = Math.floor(Math.random()*arr.length);
             str += arr[random];
         }
            
        return str;
    },

还有还有最重要的就是记得微信支付要用APIV2密钥啊,一定一定32位字符串,不然会失败的我就是倒霉鬼,用了V3密钥在官网测试就提示成功,结果在小程序一致签名错误,结果换V2的成功了

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

橙子cms

node+express扫码获

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

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

打赏作者

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

抵扣说明:

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

余额充值