最近开发的公众号中,接入了微信的点金计划,就是在支付完成后,点击完成按钮会跳转到微信的一个页面,页面上可以展示订单和商户的基本信息,下部还有自带的广告信息,详细的可以了解下微信的官方文档:微信点金计划,文档里介绍了产品信息、接入方法等内容。
但是,众所周知某些开发文档对于初次开发的人员来说并不友好,甚至文档都快背下来了,依旧不知道怎么去开发,并且中途遇到问题在文档里也找不到合理的解决办法,这时候还得是靠广大的网友的聪明智慧了......
这里先上一下全部代码,然后再说明遇到的问题和解决问题思路。对于点金计划页面,可以使用路由做一个页面,也可以单独写个html页面,这里我使用的是html+万能的jquery
。
xml
<!DOCTYPE html>
<html lang="en" data-design-width="750" data-design-font="100" >
<head>
<meta charset="UTF-8">
<link rel="icon" href="../favicon.png" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, viewport-fit=cover" />
<title>支付完成页</title>
<!-- 点金计划必须接入的js -->
<script type="text/javascript" charset="UTF-8" src="https://wx.gtimg.com/pay_h5/goldplan/js/jgoldplan-1.0.0.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.0/jquery.min.js" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script>
// 字号转换rem
(function (window, undefined) {
var html_dom = document.getElementsByTagName('html')[0];
var design_width = parseInt(html_dom.dataset.designWidth, 10);
var design_font = parseInt(html_dom.dataset.designFont, 10);
var isMobile = /Mobile/.test(window.navigator.userAgent);
window.onresize = function () {
resizeRoot();
}
function resizeRoot() {
var client_width = document.documentElement.clientWidth;
if (client_width >= 750) {
client_width = 750;
}
var fs = client_width / design_width * design_font;
html_dom.style.fontSize = fs + "px";
};
resizeRoot();
})(window)
</script>
<script th:inline="javascript">
//获取url中返回参数
function getQueryString(name) {
var query = window.location.search.substring(1);
var vars = query.split("&");
for (var i = 0; i < vars.length; i++) {
var pair = vars[i].split("=");
if (pair[0] == name) {
return pair[1];
}
}
return null;
}
// 获取cookie
function getck(sname) { //获取单个cookies
if(document.cookie){
var acookie = document.cookie.split("; ");
for (var i = 0; i < acookie.length; i++) {
var arr = acookie[i].split("=");
if (sname == arr[0]) {
if (arr.length > 1) {
console.log('arr', arr[1])
return unescape(arr[1]);
} else {
return "";
}
}
}
return "";
}
}
window.onload = function(){
var out_trade_no = getQueryString("out_trade_no"); //商户订单号
$.ajax({
type: "POST",
url: window.location.origin + '/payResult',
data: JSON.stringify({
orgId: out_trade_no
}),
contentType: "application/json; charset=utf-8",
dataType: "json",
headers: {
'token': getck('token')
},
success: function (res) {
console.log('请求成功',res)
if (res && res.code == 200 && res.data) {
// 根据页面需要展示的内容进行修改
$('.merTitle').html(res.data.merName)
$('.name').html(res.data.nickName)
$('.amt strong').html(res.data.amt)
$('.headImg').attr('src', res.data.picUrl)
var mchData = { action: 'onIframeReady', displayStyle: 'SHOW_CUSTOM_PAGE', height: 404 };
let postData = JSON.stringify(mchData);
// window.parent.postMessage(postData, 'https://payapp.weixin.qq.com');
top.postMessage(postData, '*');
// 注册点击事件,即点击页面上按钮跳转出去
document.querySelector('#goOrder').onclick = function () {
let pathname = window.location.pathname
let pathnameArr = pathname.split('/')
var mchData = {
action: 'jumpOut',
jumpOutUrl: window.location.origin + '/' + pathnameArr[1] + '/#/bbb?id=' + res.data.id //跳转的页面
}
console.log('调用成功',mchData);
var postData = JSON.stringify(mchData)
// parent.postMessage(postData, "https://payapp.weixin.qq.com")
top.postMessage(postData, "*")
}
}
},
error: function(err){
console.log('请求出错',err)
}
});
}
</script>
<style>
*{
margin: 0;
padding: 0;
}
.pay_over .content {
text-align: center;
background-color: rgba(246, 246, 246, 1);
width: 99%;
margin: .5rem auto 0;
position: relative;
}
.pay_over .content .headImg {
width: 1.5rem;
height: 1.5rem;
border-radius: 50%;
position: absolute;
left: 50%;
top: -.25rem;
margin-left: -.75rem;
}
.pay_over .content .merTitle {
font-size: .42rem;
font-family: PingFangSC-Medium, PingFang SC;
font-weight: 500;
color: #333333;
margin: 0 0 .56rem;
padding-top: 1.5rem;
}
.pay_over .content .name {
font-size: .42rem;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #333333;
margin: 0 0 .16rem;
}
.pay_over .content .amt {
font-size: .8rem;
font-family: PingFangSC-Medium, PingFang SC;
font-weight: 500;
color: #333333;
margin: 0 0 .4rem;
}
.pay_over .content .amt span {
font-size: .36rem;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
padding-left: .1rem;
}
.pay_over .content .link {
font-size: .32rem;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #1677FF;
padding-bottom: .42rem;
}
.pay_over .content .link a {
text-decoration: underline;
font-family: PingFangSC-Regular, PingFang SC;
}
</style>
</head>
<body>
<div class="pay_over">
<div class="content">
<img class="headImg" src="" alt="">
<div class="merTitle"></div>
<div class="name"></div>
<div class="amt"><strong></strong><span>元</span></div>
<div class="link" id="goOrder"><a href="javascript:void 0">查看订单详情</a></div>
</div>
</div>
</body>
</html>
上面就是出版的点金计划页面代码,在本地调试接口是没问题的,但是如果真的需要模拟点金计划完整页面的效果,需要把这个页面放到服务器上,并把路径配到微信商家配置里,才可以进行调试,这部分文档有相关方法,不再赘述。
重点说一下开发中遇到的问题,就是能够支付完成,也能够跳转到点金页面,但是部分(基本就是IOS)手机会显示无法获取订单信息
,这也是小伙伴们遇到的最多的问题。
针对这个问题,官方也给出了几条建议:
1、已打开特约商户的商家小票及点金计划开关
2、商家小票页面需调用父页面"onIframeReady事件"的jsapi,具体请查看商家小票开发指引
3、从加载商家小票到调用JSAPI之间的用时不可超过3s
4、调试时,扫描二维码的微信号和支付该笔测试订单的微信号需为同一个
5、商家小票页面可正常访问
6、检查商家小票请求的Response Headers中X-Frame-Options是否允许payapp.weixin.qq.com访问
7、如果是使用VUE,onIframeReady不能放在created里执行
8、如果上述方法都不行,请先编写一个最简单的demo页面,看看demo页面是否成功
9、商家URL是否有进行重定向,是否重定向到http的链接
不过这些建议有的可以验证,有的真的无从下手...所以针对上面的问题楼主联合了后端一起排查,通过日志发现,在请求的时候实际上已经报错了,问题就出在通过cookie获取token上面,此时cookie为空了,自然接口的登录信息校验就过不去了。
这里也是楼主的疏忽,本来觉得点金页面和实际业务页都在一个域名下,cookie是可以共享的,能够完美获取;但是实际上,到真实环境中上面开发的页面是通过iframe被嵌入到微信官方页面中的;大部分安卓和一部分IOS 能够正常显示页面,只有部分IOS无法正常显示,借用网上其他小伙伴的说法,这就是系统的差异,能够正常显示的在跳转时没有清除登录信息,但是IOS把登录信息都清掉了
。所以如果涉及缓存存取,还是要慎重!!!
到这里问题原因就很明确了,后端做了相应的修改,给这个接口加白名单,不去校验token(当然是在业务允许的情况下),前端代码获取不获取token就无所谓了。
最后,在上边官方给出的九条建议上再加一条:
10、检查业务逻辑请求是否涉及到登录信息存取,如无业务需求,尽量避免登录相关校验