共计 8844 个字符,预计需要花费 23 分钟才能阅读完成。
微信小程序开发的过程肯定会遇到各种问题,最让人辣手的就是领取问题,因为没有领取做商城相似的小程序就没有方法实现最要害的一步。那么领取失败到底什么起因呢?一下子收集了几个谬误相似,心愿对你有帮忙:
No.1
{err_code: "-1", err_desc: "调用领取 JSAPI 短少参数: total_fee", errMsg: "requestPayment:fail"}
errMsg:"requestPayment:fail"
err_code:"-1"
err_desc:"调用领取 JSAPI 短少参数: total_fee"
<?xml version=”1.0″ encoding=”utf-8″?>
<xml>
<appid>xx</appid>
<body><![CDATA[测试商品名称]]></body>
<mch_id>xxx</mch_id>
<nonce_str>krwub67ymmvm1nkjb9fitm6muqplqa45</nonce_str>
<notify_url>xx</notify_url>
<openid>xxx</openid>
<out_trade_no>xx</out_trade_no>
<spbill_create_ip>xxx</spbill_create_ip>
<total_fee>1</total_fee>
<trade_type>JSAPI</trade_type>
<sign>xxx</sign>
</xml>
<?xml version=”1.0″ encoding=”utf-8″?>
<xml>
<return_code><![CDATA[SUCCESS]]></return_code>
<return_msg><![CDATA[OK]]></return_msg>
<appid><![CDATA[wx64db6c2b70842ec1]]></appid>
<mch_id><![CDATA[1504167501]]></mch_id>
<nonce_str><![CDATA[Y34OjPAY9ReOCPDZ]]></nonce_str>
<sign><![CDATA[039CF2A0B217BFCCAA01CCF4ECA1B32E]]></sign>
<result_code><![CDATA[FAIL]]></result_code>
<err_code><![CDATA[ORDERPAID]]></err_code>
<err_code_des><![CDATA[该订单已领取]]></err_code_des>
</xml>
No.2
如果微信小程序在进行微信领取时若提醒 “商户号 mch_id 与 appid 不匹配” 或者是提醒 “无奈实现微信领取““签名谬误” 等,请参考以下步骤查看;
筹备工作:查看以下步骤前,请先留神核查 appid 是否是同一个。具体核查形式:
1、微信小程序核查地址为:设置 - 开发设置 有显示具体 appid,如图:
2、我司后盾受权的 小程序 appid 地址,如图:
若核查无误的前提下,筹备以下三步的查看。
第一步:登录微信领取平台 https://pay.weixin.qq.com 查看对应的商户号与密钥及证书,并重置下密钥及重新安装下证书。
第二步:登录到对应的微信小程序账户下 https://mp.weixin.qq.com(留神此处是微信小程序账户不是公众号账户),查看是否开明微信领取。
若显示未开明,请参考教程,绑定第一步外面的商户号
第三步:登录我司小程序管理后盾,填写步骤一外面的商户号和密钥及证书(注:.P12 证书)
以上步骤操作实现后,再从新去下单领取测试。
No.3
如果你应用的是第三方开源我的项目,个别都是封装好了,依照要求去填写即可,出错的时候次要是证书的配置问题,譬如来客推商城领取的谬误解决方案:
起因有几点:
1、微信小程序没有与微信领取绑定
2、来客零碎后盾领取设置不正确,如图地位:
3、我的项目的目录权限请设置为 chmod 777
No.4
ios 的微信小程序领取失败解决办法:前两天做了个小程序,波及到了领取,后果在自测 ios 零碎时碰到了钉子
苹果手机领取失败的起因是:微信早在「微信小程序经营规定」第 14 条「小程序领取标准」中已明确示意:目前,在 iOS 零碎下,微信小程序暂不得为虚构物品购买提供领取性能
这就导致,许多须要线上领取,并且无实物的领取时,每每碰壁
你须要做的就是,让后盾人员在生成预领取订单时,不要呈现,费用、领取、付费、续费、转账等与费用相干的字眼
如果改了这个还不行,那么就须要查看是否有代码中的谬误
我解决的计划就是去掉了无关费用的字眼
No.5
微信小程序领取性能开发与踩坑经验总结
(本局部起源参考图片水印)
首先是小程序领取性能的申请
在半年前我有另一个小程序我的项目,尽管过后没有开明小程序微信领取的需要,然而我注意过利用号(小程序号)后盾微信领取的相干选项。过后,这个小程序因为绑定过已认证的服务号,因而小程序领取是能够间接申请的,无需任何费用。然而这次的我的项目,同样是另一个曾经绑定过认证服务号的小程序,在微信领取界面,提醒我要认证以后的小程序号能力开明微信领取,也就是说,绑定服务号还不够,必须把这个小程序号也交 300 元认证后,才给开明领取性能!真的很坑,好在客户没有什么牢骚,十分配合地就把认证给办了…
一天后小程序号认证通过,就有了申请领取的入口:
果决选左边那个,依据给出的提醒,到商户平台外面用小程序的 appid 绑定就行了。
第二个坑,获取 openid。在网上能找到的大部分实例代码里,都把获取 openid 的接口调用间接写在了小程序代码里。这个接口的地址是这样的:https://api.weixin.qq.com/sns/jscode2session?appid=********&secret=********&js_code=********&grant_type=authorization_code
其中 js_code 是通过 wx.login 取得的,这个没问题;appid 也没问题;问题在 secret 上,即 appsecret,这个密钥如果间接写在小程序端,原本就不太平安。果不其然,开发工具报错如下:
于是我尝试把 api.weixin.qq.com 域名退出 request 非法域名列表,人家不给我加…
那就很奇怪了,为啥网上很多例子给出的代码是间接申请 api.weixin.qq.com 接口的?他人能够我就不能够,没道理啊!
花了很多工夫查证,小程序是今年年初的时候禁止了 api.weixin.qq.com 域名的间接申请的,目标就是为了防止开发者把 appsecret 间接写在小程序端的代码里,造成安全隐患。虽说是为了平安着想,但这真的很坑爹,官网在开发材料外面并没有提到这事件,导致很多人在此绕了弯路。
此外,我在开发过程中,其实是一路绕过这个坑的。因为发现尽管开发工具会报错不能申请这个域名,然而在开发工具提供的近程调试性能里,在手机上是能够间接申请这个接口的。于是获取 openid 这个过程在最后的开发调试中并没有裸露问题,而是在我感觉曾经功败垂成,行将提供对外测试的版本中,在手机上敞开了 vconsole 后,微信领取性能拉不起来,并且因为敞开了 vconsole 就看不到任何报错信息,是直觉通知我这个申请域名产生了问题。微信开发就是这么操蛋,很多时候得靠程序员的直觉,而不是文档…
解决这个问题的惟一方法就是写一个 PHP 扔到本人的服务器上,借助这个 PHP 申请 openid 的接口,再返回给小程序端。这个 PHP 的代码附在文末。
接下来第三个坑,是签名验证。首先咱们要进行商户这里的对立领取签名,把 appid、商品名、商户 id、nonce 值、notify_url、openid、订单号、金额…. 等等一连串的值,依照 key=value&key=value&…格局,key 为字母顺序排列下来,最初加上”商户 key”(在商户后盾取得),组成一个字符串,并通过 MD5 加密后生成一串签名值。
这些值,获取的中央哪里都有,光收集他们就得费一番力量;收集结束后,还要按既定顺序排列,不能颠倒,并且商户 key 值是例外,得排在最初。MD5 加密办法是 gitHub 上找的现成代码,给出地址:
https://github.com/leibing891…
以上签名实现后,还要把这些值去掉最初的商户 key,加上曾经实现的签名,封装成一个 XML 格局字符串,把这个字符串作为参数申请接口 https://api.mch.weixin.qq.com…,在返回的值中提取一串”prepay_id=”值,再用方才的连贯键值的办法取得长字符串,进行 第二次MD5 加密签名。
真 TNND 绕啊!我为了调试胜利两次签名值,也费了不少力量。好在在他人的文章里看到有微信官网提供的调试工具,帮了不少忙,这是调试工具链接:https://pay.weixin.qq.com/wik…
等到以上通通实现,连同方才取得的签名值,再依据官网文档从新组织一下各个所需参数,能力通过 wx.requestPayment 申请拉起领取。而咱们可恶的微信官网文档,仅仅介绍了这最初的一步 – wx.requestPayment 所须要的几个参数而已,给出的例程更是让人汗颜,欢送大家去围观(当初是 2018 年 8 月 16 日,我不会晓得官网在此之后多久会欠缺它的文档,但当初这个文档看来是很不敌对的):https://developers.weixin.qq….
上面我将本人调试结束的代码整顿一下,留个存档:
小程序端,保留大部分的 console 的版本
/ 微信领取 /
goWxPay: function () {
var that = this;
// 登陆获取 code
wx.login({success: function (res) {console.log("获取 login code",res.code);
// 获取 openid
that.getOpenId(res.code);
}
});
},
/ 获取 openId /
getOpenId: function (code) {
var that = this;
wx.request({
url: "https://****?code=" + code, // 服务器端的申请地址,域名已退出小程序 request 白名单
method: 'GET',
success: function (res) {console.log("获取 openid", res);
that.unitedPayRequest(res.data.openid);
},
fail: function () {console.log("获取 openid 失败", res);
},
complete: function () {console.log("获取 openid 结束", res);
}
});
},//getOpenId()
/对立领取接口/
unitedPayRequest: function(openid){
var that=this;
// 对立领取签名
var appid = '';//appid 必填
var body = '';// 商品名必填
var mch_id = '';// 商户号必填
var nonce_str = util.randomString();// 随机字符串,不长于 32 位。var notify_url = '';// 告诉地址必填
var total_fee = parseInt(0.01 * 100); // 价格,这是一分钱
var trade_type = "JSAPI";
var key = ''; // 商户 key 必填,在商户后盾取得
var out_trade_no = '';// 自定义订单号必填
var unifiedPayment = 'appid=' + appid + '&body=' + body + '&mch_id=' + mch_id + '&nonce_str=' + nonce_str + '¬ify_url=' + notify_url + '&openid=' + openid + '&out_trade_no=' + out_trade_no + '&total_fee=' + total_fee + '&trade_type=' + trade_type + '&key=' + key;
console.log("unifiedPayment", unifiedPayment);
var sign = md5.md5(unifiedPayment).toUpperCase();
console.log("签名 md5", sign);
// 封装对立领取 xml 参数
var formData = "<xml>";
formData += "<appid>" + appid + "</appid>";
formData += "<body>" + body + "</body>";
formData += "<mch_id>" + mch_id + "</mch_id>";
formData += "<nonce_str>" + nonce_str + "</nonce_str>";
formData += "<notify_url>" + notify_url + "</notify_url>";
formData += "<openid>" + openid + "</openid>";
formData += "<out_trade_no>" + that.data.ordernum + "</out_trade_no>";
formData += "<total_fee>" + total_fee + "</total_fee>";
formData += "<trade_type>" + trade_type + "</trade_type>";
formData += "<sign>" + sign + "</sign>";
formData += "</xml>";
console.log("formData", formData);
// 对立领取
wx.request({
url: 'https://api.mch.weixin.qq.com/pay/unifiedorder', // 别忘了把 api.mch.weixin.qq.com 域名退出小程序 request 白名单,这个目前能够加
method: 'POST',
head: 'application/x-www-form-urlencoded',
data: formData, // 设置申请的 header
success: function (res) {console.log("返回商户", res.data);
var result_code = util.getXMLNodeValue('result_code', res.data.toString("utf-8"));
var resultCode = result_code.split('[')[2].split(']')[0];
if (resultCode == 'FAIL') {var err_code_des = util.getXMLNodeValue('err_code_des', res.data.toString("utf-8"));
var errDes = err_code_des.split('[')[2].split(']')[0];
wx.showToast({
title: errDes,
icon: 'none',
duration: 3000
})
} else {
// 发动领取
var prepay_id = util.getXMLNodeValue('prepay_id', res.data.toString("utf-8"));
var tmp = prepay_id.split('[');
var tmp1 = tmp[2].split(']');
// 签名
var key = '';// 商户 key 必填,在商户后盾取得
var appId = '';//appid 必填
var timeStamp = util.createTimeStamp();
var nonceStr = util.randomString();
var stringSignTemp = "appId=" + appId + "&nonceStr=" + nonceStr + "&package=prepay_id=" + tmp1[0] + "&signType=MD5&timeStamp=" + timeStamp + "&key=" + key;
console.log("签名字符串", stringSignTemp);
var sign = md5.md5(stringSignTemp).toUpperCase();
console.log("签名", sign);
var param = {"timeStamp": timeStamp, "package": 'prepay_id=' + tmp1[0], "paySign": sign, "signType": "MD5", "nonceStr": nonceStr }
console.log("param 小程序领取接口参数", param);
that.processPay(param);
}
},
})
},//unitedPayRequest()
/ 小程序领取 /
processPay: function (param) {
wx.requestPayment({
timeStamp: param.timeStamp,
nonceStr: param.nonceStr,
package: param.package,
signType: param.signType,
paySign: param.paySign,
success: function (res) {
// success
console.log("wx.requestPayment 返回信息",res);
wx.showModal({
title: '领取胜利',
content: '您将在“微信领取”官网号中收到领取凭证',
showCancel: false,
success: function (res) {if (res.confirm) {} else if (res.cancel) {}}
})
},
fail: function () {console.log("领取失败");
},
complete: function () {console.log("领取实现(胜利或失败都为实现)");
}
})
}//processPay()
几个要用到的办法,除了 MD5 用从 Github 上找的代码,其余如下:
/ 工夫戳产生函数 /
function createTimeStamp() {
return parseInt(new Date().getTime() / 1000) + ”
}
/ 随机数 /
function randomString() {
var chars = ‘ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678’; // 默认去掉了容易混同的字符 oOLl,9gq,Vv,Uu,I1
var maxPos = chars.length;
var pwd = ”;
for (var i = 0; i < 32; i++) {
pwd += chars.charAt(Math.floor(Math.random() * maxPos));
}
return pwd;
}
/ 获取 XML 节点信息 /
function getXMLNodeValue(node_name, xml) {
var tmp = xml.split(“<” + node_name + “>”)
var _tmp = tmp[1].split(“</” + node_name + “>”)
return _tmp[0]
}
module.exports = {
createTimeStamp: createTimeStamp,
randomString: randomString,
getXMLNodeValue: getXMLNodeValue
}
在服务端获取 openid 的 PHP 代码
// 获取用户 openid
function getPortData($url){
$ch = curl_init();
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, 0);
curl_setopt($ch, CURLOPT_HEADER, false);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
$r = curl_exec($ch);
//$r = json_decode($r);
if($error=curl_error($ch)){die($error);
}
curl_close($ch);
return $r;
}
function getopenid(){
$code = $_GET["code"];
if(empty($code)) return array('status'=>0,'info'=>'短少 js_code');
$appid = '';// 必填
$appsecret = '';// 必填
$url = "https://api.weixin.qq.com/sns/jscode2session?appid=".$appid."&secret=".$appsecret."&js_code=".$code."&grant_type=authorization_code";
$result = getPortData($url);
//var_dump($result);
echo $result;
}
getopenid();
自此,拼拼凑凑地总算把小程序微信领取跑起来了。
写在最初:如果大家对小程序领取还有任何问题欢送大家一起沟通交流