报错背景
微信小程序使用云开发实现微信支付功能,但是报错了
报错信息
报错原因
小程序想要使用微信支付,必须满足下面几个条件的
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重设了好几次,还是不行,你要看看