微信小程序使用云开发实现微信支付功能 报错Error: 签名错误,史上最全解决办法,不服留言骂我

  • Post author:
  • Post category:小程序



报错背景

微信小程序使用云开发实现微信支付功能,但是报错了


报错信息


报错原因


小程序想要使用微信支付,必须满足下面几个条件的


1,必须是非个人小程序(个人小程序用不了支付)


企业小程序需要认证!



2,必须申请微信支付的商户号。


也就是微信支付商户平台的商户Id



3,必须配置商户号密匙。


微信支付商户平台的私钥



4,必须在自己小程序里关联你的商户号


https://pay.weixin.qq.com/static/pay_setting/appid_protocol.shtml


你以为到这里就结束了,没有!

简直就是血的教训啊,我搞了三天,官网上平台上所有的方法都试过了,简直就是血泪啊。

1、有一个是tenpay实现的,这个方法简单而且有用

具体代码是这样的;

这个是mypay.wxml文件

<view class='container'>
  <input class='ipt' value='{{price}}' bindinput='onInput' type='digit' />
  <button class='btn-pay' bindtap='pay'>Pay</button>
  </view>

这个是mypay.js文件

注意这里的payment是我云函数的名称,你要写你自己云函数文件的名称

Page({
  data: {
    price: 0.01
  },

  onInput(event) {
    this.setData({ price: event.detail.value });
  },

  pay() {
    wx.cloud.callFunction({
      name: 'payment',
      data: {total_fee:1}, // 可传入相关参数。
      success: res => {
        console.log(res.result)
        if (!res.result.appId) return
        wx.requestPayment({
          ...res.result,
          success: res => {
            console.log(res)
          }
        })
      }
    })
  }
});

1、开通云开发,点击左上角的云开发按钮就可以了,填写环境名称

2、在app.js里面配置环境名称

      wx.cloud.init({
        env: 'tjn-k3u19',
        traceUser: true,
      })

3、开通云开发以后,我们上面会有一个像蘑菇云一样的cloudfunction,也就是云函数了


4、在云函数右击,新建Node.js云函数,名称为payment

5、打开里面的index.js,把这个文件复制进去,记住,把appid,mchid,partnerKey这三个改成自己的,知不知道!!!

//云开发实现支付
const cloud = require('wx-server-sdk')
cloud.init()

//1,引入支付的三方依赖
const tenpay = require('tenpay');
//2,配置支付信息
const config = {
  appid: '你小程序对于的appid',
  mchid: '商户号',
  partnerKey: '商户平台的秘钥',
  notify_url: 'https://mysite.com/notify',
  spbill_create_ip: '127.0.0.1' //这里填这个就可以
};

exports.main = async (event, context) => {
  const wxContext = cloud.getWXContext()
  let {
    total_fee
  } = event;
  //3,初始化支付
  const api = tenpay.init(config);
  const nonceStr = Math.random().toString(36).substr(2, 15)
  const timeStamp = parseInt(Date.now() / 1000) + ''
  const out_trade_no = "otn" + nonceStr + timeStamp
  let result = await api.getPayParams({
    out_trade_no: out_trade_no,
    body: '牌位',
    total_fee: total_fee, //订单金额(分),
    openid: wxContext.OPENID //付款用户的openid
  });
  return result;
}

因为我们依赖了两个包,所以我们需要安装这两个包wx-server-sdk和tenpay,但是安装这个两个包需要node.js环境

这个环境是要求我们的电脑安装node.js

去官网下载,然后安装,安装成功以后,cmd命令行输入node -v  显示版本号的话,就说明安装成功

这个时候我们再安装这个两个依赖包wx-server-sdk和tenpay

右击payment云行数,在终端打开,输入

npm install --save wx-server-sdk

安装tenpay

npm i tenpay

这个时候你的package.json里面就多了两个依赖了

到这里,我们可以上传并部署这个payment云函数了

出现这样的提示才是成功的

我们一般默认的下面还有一个login云函数,这个云函数我们也上传并部署,目的是为了获取用户名的openid;非常方便便捷

我们需要在app.js里面调用这个login云函数

  //获取openid
      /**
     * 打开小程序的时候首先获得用户openid
     */
      wx.cloud.callFunction({
        name: 'login',
        data: {},
        success: res => {
          this.globalData.openid = res.result.openid
        },
        fail: err => {
          console.error('[云函数] [login] 调用失败', err)
        }
      })
    //获取openid
      //获取openid

这里的env对应的是你自己云开发环境的id,打开云开发控制台上面就有

这个时候点击前端支付按钮

有手机扫描,就可以出现支付的页面了;

如果你是签名错误的话;

1、确定商户名是否正确,比如多了一个数字;

2、微信支付接口签名校验工具;如果校验不通过,你要仔细看一下参数拼写问题以及值的问题;

我觉得这种方式太累,拼接太累了,怕自己眼拙,咋办?

我推荐一个云函数,虽然代码多,但是很原始,有xml拼接结果,可以直接把结果和Key输入进去,然后出来校验结果

你新建一个wx云函数,然后安装crypto与request-promise依赖,都是npm i 依赖名


//2 openid 就是支付用户的识别号
const mch_id = '商户号';             // 商户号
const key = '商户key';   // 商户密钥
const cloud = require('wx-server-sdk')
const rp = require('request-promise')
const crypto = require('crypto')
cloud.init()

function getSign(args) {
  let sa = []
  for (let k in args) sa.push(k + '=' + args[k])
  sa.push('key=' + key)
  return crypto.createHash('md5').update(sa.join('&'), 'utf8').digest('hex').toUpperCase()
}

function getXml(args) {
  let sa = []
  for (let k in args) sa.push('<' + k + '>' + args[k] + '</' + k + '>')
  sa.push('<sign>' + getSign(args) + '</sign>')
  let axml = '<xml>' + sa.join('') + '</xml>'
  console.log("最后签名:",axml)
  return axml
}

exports.main = async (event, context) => {
  const wxContext = cloud.getWXContext()
  const appId = appid = wxContext.APPID
  console.log("appid是:", appid, appId)
  const openid = wxContext.OPENID
  const attach = 'attach'
  const body = 'body'
  const total_fee = 1
  const notify_url = "https://mysite.com/notify"
  const spbill_create_ip = "118.89.40.200"
  const nonceStr = nonce_str = Math.random().toString(36).substr(2, 15)
  const timeStamp = parseInt(Date.now() / 1000) + ''
  const out_trade_no = "otn" + nonce_str + timeStamp
  const trade_type = "JSAPI"
  const xmlArgs = {
    appid,
    attach,
    body,
    mch_id,
    nonce_str,
    notify_url,
    openid,
    out_trade_no,
    spbill_create_ip,
    total_fee,
    trade_type
  }
  let xml = (await rp({
    url: "https://api.mch.weixin.qq.com/pay/unifiedorder",
    method: 'POST',
    body: getXml(xmlArgs)
  })).toString("utf-8")
console.log("签名是:",xml)
  if (xml.indexOf('prepay_id') < 0) return xml
  let prepay_id = xml.split("<prepay_id><![CDATA[")[1].split("]]></prepay_id>")[0]
  let payArgs = {
    appId,
    nonceStr,
    package: ('prepay_id=' + prepay_id),
    signType: 'MD5',
    timeStamp
  }
  return {
    ...payArgs,
    paySign: getSign(payArgs)
  }
}

在mypay.wxml里面把云函数名称改为wx就可以了,不要忘记把wx云函数上传并部署到云端,然后再刷新前端页面,点击支付;

这个wx云函数是最全面最不会出问题的,如果你没有支付成功的话,就不是代码的问题,是你的appid 商户号与秘钥的问题了!!

不过我们重点在于打印签名信息,然后校验

打开云开发平台,点击云函数,有一个日志

把这个签名复制过去,到微信支付接口签名校验工具里面,然后复制key的值,点击校验!


https://pay.weixin.qq.com/wiki/doc/api/micropay.php?chapter=20_1

如果校验通过的话,说明很有可能是key秘钥的问题,再重置一遍,就是这么喜剧,我重置了好多次才成功的!

15分钟以后生效!


如果你的签名工具校验通过,你的key重设了好几次,还是不行,你要看看



版权声明:本文为tian_jiangnan原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。