1、两者的OpenID获取方式不同问题
我的预支付用的云函数payment如下:
const cloud = require('wx-server-sdk');
const {
WXPay,
WXPayUtil
} = require('wx-js-utils');
cloud.init();
const appId = 'wx***'; // 小程序appid
const mchId = '***'; // 商户号
const key = '***'; // 商户密钥
const timeout = 10000; // 超时时间
let wxpay = new WXPay({
appId,
mchId,
key,
timeout: 10000,
signType: 'MD5',
useSandbox: false // 不使用沙箱环境
});
exports.main = async (event, context) => {
const curTime = Date.now();
// 存放订单号
let orderCode = '';
// 6位随机数(加在时间戳后面)
for (var i = 0; i < 6; i++) {
orderCode += Math.floor(Math.random() * 10);
}
// 时间戳(用来生成订单号)
orderCode = 'D' + new Date().getTime() + orderCode;
const tradeNo = orderCode;
const body = '测试订单'; // 订单商品名称
const spbill_create_ip = '127.0.0.1'; // 发起支付的IP
const notify_url = 'http://www.qq.com'; // 回调地址
const total_fee = event.price * 100; // 支付金额,单位为分
var time_stamp = '' + Math.ceil(Date.now() / 1000);
console.log("Time stamp: " + time_stamp)
const out_trade_no = `${tradeNo}`;
console.log(event.openId)
let orderParam = {
body,
spbill_create_ip,
notify_url,
out_trade_no,
total_fee,
openid: event.openId,
trade_type: 'JSAPI',
timeStamp: time_stamp,
};
const {
return_code,
result_code,
...restData
} = await wxpay.unifiedOrder(orderParam); // 统一下单
console.log("#RETURN_CODE")
console.log(return_code)
if (return_code == 'SUCCESS') {
console.log("#RESTDATA")
console.log(restData)
const {
prepay_id,
nonce_str
} = restData;
const sign = WXPayUtil.generateSignature({
appId,
nonceStr: nonce_str,
package: `prepay_id=${prepay_id}`,
signType: 'MD5',
timeStamp: time_stamp
}, key); // 签名
return {
code: 0,
data: {
out_trade_no: out_trade_no,
time_stamp: time_stamp,
...restData,
sign: sign
}
}
}
return {
code: -1
}
};
我的获取OpenID用的云函数getopenid如下:
// 云函数入口文件
const cloud = require('wx-server-sdk')
cloud.init()
// 云函数入口函数
exports.main = async (event, context) => {
const wxContext = cloud.getWXContext()
return {
event,
openid: wxContext.OPENID,
appid: wxContext.APPID,
unionid: wxContext.UNIONID,
}
支付页面的代码如下:
Page({
data: {
price: 0.01,
openid: ''
},
onLoad() {
this.getOpenid()
},
// 定义调用云函数获取openid
getOpenid() {
let page = this;
wx.cloud.callFunction({
name: 'getopenid',
complete: res => {
console.log('openid--', res.result)
var openid = res.result.openid
page.setData({
openid: openid
})
}
})
},
onInput(event) {
this.getOpenid()
this.setData({
price: event.detail.value
});
},
pay() {
const price = parseFloat(this.data.price).toFixed(2);
wx.showLoading({
title: '请稍候...'
});
var openid = this.data.openid
console.log("OpenID:" + openid)
// 可以将 res 发送给i后台解码出 unionId
wx.cloud.callFunction({
name: 'payment', // 调用payment函数
data: {
price: price,
openId: openid
}, // 支付金额
success: (res) => {
wx.hideLoading();
console.log(res)
const {
result
} = res;
const {
code,
data
} = result;
if (res.result.code != 0) {
wx.showModal({
title: '提示',
content: "支付失败",
showCancel: false
});
return;
}
wx.requestPayment({
timeStamp: data.time_stamp,
nonceStr: data.nonce_str,
package: `prepay_id=${data.prepay_id}`,
signType: 'MD5',
paySign: data.sign,
total_fee: price,
success: () => {
wx.showToast({
title: '支付成功'
});
}
});
},
fail: (res) => {
wx.hideLoading();
console.log('FAIL');
console.log(res);
}
});
}
})
对于支付页面代码中的getOpenid()中的var openid = res.result.openid,仅在模拟器调试中有效,即在点击支付后,模拟器弹出二维码,手机扫描二维码后可顺利支付;但是如果在真机中运行,openid将会是undefined,导致支付失败。在真机中,只有把res.result.openid改为res.result.userInfo.openId,才能获取到openid,但是由于接下来的第2个问题,真机依然无法顺利支付。
2、出现了云函数payment的回调success中的res异常等于之前云函数getopenid的回调中的complete的res的现象,尽管这两个云函数内部没有任何联系。这个问题在真机调试时必然发生,在模拟器调试时可能发生。在模拟器调试时一旦打开云函数本地调试器,该现象即消失,payment的res恢复正常;在未知情形下,该现象会重新出现。这个现象导致了接下来的data对象为undefined,导致支付失败。
总之,这两个问题完全在我的意料之外,我认为外部的不确定性因素对程序无法正常运行有最为重要的影响。我应该怎么解决这个问题,或者采取更加可靠的解决方案?