mpay/view/pay/console.html
技术老胡 ee49c2a0d0 1. 开发文档加载速度优化
2. 浏览器跳转支付宝异常修复
2025-03-19 23:17:58 +08:00

344 lines
14 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>收银台</title>
<link rel="stylesheet" href="/component/pear/css/pear.css" />
<style>
body {
background: #f7f7f7;
}
.card {
margin: 18px auto 18px;
padding: 38px 16px 0px;
background: #fff;
-webkit-box-shadow: 0 3px 3px 0 hsla(0, 0%, 92.5%, .44);
box-shadow: 0 3px 3px 0 hsla(0, 0%, 92.5%, .44);
border-radius: 12px;
text-align: center;
padding-bottom: 38px;
}
.order {
width: 340px;
margin: 15px auto 21px;
background: #fbfbfb;
border-radius: 6px;
line-height: 42px;
text-align: left;
}
.order span {
color: #999;
font-size: 15px;
margin-left: 14px;
}
.goods_name {
font-weight: 500;
font-size: 12px;
color: #999;
border-bottom: 1px solid #f5f5f5;
padding-bottom: 20px;
}
.price {
color: #386cfa;
width: 100%;
text-align: center;
margin-top: 16px;
margin-bottom: 8px;
}
.price>span:first-child {
font-size: 28px;
}
.price>span:last-child {
font-size: 17px;
}
.price span {
font-weight: 700;
}
.qrcode>img {
height: 200px;
}
.msg {
margin-top: 12px;
}
.msg>p {
color: red;
font-weight: 700;
line-height: 2em;
}
.msg>p:nth-child(1) {
font-size: 17px;
}
.shanxinzha {
margin-top: 32px;
width: 100%;
text-align: center;
}
.shanxinzha p {
color: #999;
font-size: 14px;
font-weight: 400;
margin-left: 5px;
}
.note {
color: red;
font-size: 22px;
}
</style>
</head>
<body>
<div id="app" class="layui-container">
<div class="layui-row">
<div class="card" style="padding-bottom: 18px;padding-top: 15px;">
<div style="text-align: center;">
<svg style="vertical-align: middle;" t="1610806307396" viewBox="0 0 1024 1024" version="1.1"
xmlns="http://www.w3.org/2000/svg" p-id="6171" width="26" height="26">
<path
d="M1024 199.18v410.38c0 110-89.54 199.18-200 199.18H200c-110.46 0-200-89.18-200-199.18V199.18C0 89.17 89.54 0 200 0h624c110.46 0 200 89.17 200 199.18z m-553.95 317v46.72q0.9 19.32 12 28.75t30.9 9.43q40.14 0 41.95-38.18v-47.58l86.6 0.45q11.73-0.9 18.49-8.76t7.67-19.54a33.48 33.48 0 0 0-7.67-19.32q-6.77-8.09-18.49-9h-86.6v-27.4l86.15-0.45q11.73-0.9 18.72-9a33.26 33.26 0 0 0 7.89-19.76q-0.9-11.23-7.67-18.42t-18.49-8.09h-66.3l69.91-113.2q9-11.68 9-24.71a50.37 50.37 0 0 0-4.28-15.27 24.48 24.48 0 0 0-7.22-9 27.29 27.29 0 0 0-9.92-4.49 74.75 74.75 0 0 0-12.4-1.8 43.43 43.43 0 0 0-19.4 7.19 54.51 54.51 0 0 0-14 13.48l-75.34 125.83L443 229.18A65.48 65.48 0 0 0 429 215a36.39 36.39 0 0 0-19.4-7.41q-18.49 2.25-25.26 10.11t-9 20.44a36.94 36.94 0 0 0 3.61 18.19 67.53 67.53 0 0 0 8.57 13.7l60.44 106H383q-12.18 0.9-18.72 8.09t-7.89 18.42q1.35 11.68 7.89 19.32t18.72 8.56l87.05 0.45v28.3H383q-12.18 0.9-18.72 8.09t-7.89 18.42a43.81 43.81 0 0 0 7.89 20.44q6.54 9.21 18.72 10.11h87.05z"
fill="#4375ff" p-id="6172"></path>
<path
d="M264.96 903.6m60.2 0l373.67 0q60.2 0 60.2 60.2l0 0q0 60.2-60.2 60.2l-373.67 0q-60.2 0-60.2-60.2l0 0q0-60.2 60.2-60.2Z"
fill="#4375ff" p-id="6173"></path>
</svg>
<img id="payType" style="vertical-align: middle;" src="" style="height:30px;">
</div>
</div>
</div>
<div class="layui-row">
<div class="card">
<div class="order"><span>商户订单号:<span id="order">
<?php echo htmlentities($out_trade_no); ?>
</span></span></div>
<div class="goods_name"><span>商品名称:<span id="goods_name">
<?php echo htmlentities($name); ?>
</span></span></div>
<div class="price"><span id="money">
<?php echo htmlentities($really_price); ?>
</span><span></span></div>
<div class="qrcode"><img id="qrcode" src="/static/img/loading.gif">
</div>
<!-- 添加跳转按钮 -->
<div style="margin: 16px auto;display: none;">
<button id="openApp" class="layui-btn layui-btn-normal">
打开支付应用
</button>
</div>
<div class="msg">
<p>请付款 <span class="note">
<?php echo htmlentities($really_price); ?>
</span> 元,注意不能多付或少付</p>
<p>付款后,请等待 5 秒查看</p>
<p id="divTime"></p>
</div>
<div class="shanxinzha">
<p id="payTypeText"></p>
</div>
</div>
</div>
</div>
<script src="/component/layui/layui.js"></script>
<script src="/static/js/awesome-qr.min.js"></script>
<script>
function detectBrowserEnvironment() {
const userAgent = navigator.userAgent.toLowerCase();
let environment = 'other';
if (userAgent.includes('micromessenger')) {
if (userAgent.includes('miniprogram')) {
environment = 'wxapp'; // 微信小程序
} else if (userAgent.includes('android') || userAgent.includes('iphone') || userAgent.includes('ipad')) {
environment = 'wxphone'; // 手机微信
} else {
environment = 'wxpc'; // PC微信
}
} else if (userAgent.includes('aliapp') || userAgent.includes('alipayclient')) {
if (userAgent.includes('android') || userAgent.includes('iphone') || userAgent.includes('ipad')) {
environment = 'aliphone'; // 手机支付宝
} else {
environment = 'alipc'; // PC支付宝
}
} else if (userAgent.includes('android') || userAgent.includes('iphone') || userAgent.includes('ipad')) {
// 先判断是否是已知的手机APP内置浏览器如果不是则认为是手机浏览器
if (!userAgent.includes('micromessenger') && !userAgent.includes('aliapp') && !userAgent.includes('qq')) {
environment = 'phone'; // 手机浏览器
}
} else {
environment = 'pc'; // 剩下的情况认为是PC浏览器
}
return environment;
}
</script>
<script>
const payCode = '<?php echo $payUrl; ?>';
const codeType = '<?php echo htmlentities($code_type); ?>';
const payType = '<?php echo htmlentities($type); ?>';
const order = '<?php echo htmlentities($order_id); ?>';
const QR = AwesomeQR.AwesomeQR;
(async () => {
// 支付类型
const payTpeyImg = document.getElementById('payType');
const payTypeText = document.getElementById('payTypeText');
if (payType === 'wxpay') {
payTpeyImg.src = '/static/img/weixin.jpg';
payTypeText.innerText = '请使用微信扫码支付'
} else if (payType === 'alipay') {
payTpeyImg.src = '/static/img/alipay.jpg';
payTypeText.innerText = '请使用支付宝扫码支付'
} else if (payType === 'unionpay') {
payTpeyImg.src = '/static/img/unionpay.jpg';
payTypeText.innerText = '请使用云闪付扫码支付'
}
// 生成二维码
if (codeType == 0) {
document.getElementById('qrcode').src = await getQrcode(payCode, QR);
} else {
document.getElementById('qrcode').src = payCode;
}
// 订单过期时间
let passtime = 0;
// 订单状态查询
let orderTimer = 0;
const queryOrder = async (url) => {
if (orderTimer) { clearTimeout(orderTimer); }
const res = await fetch(url);
const jsonData = await res.json();
orderTimer = setTimeout(() => { queryOrder(url) }, 1000);
if (jsonData.state === 1) {
clearTimeout(orderTimer);
layer.closeAll();
document.getElementById('divTime').innerHTML = '<small class="note">订单支付成功</small>';
document.getElementById('qrcode').src = '/static/img/pay_ok.png';// 输出支付成功提示图片
setTimeout(() => {
location.href = jsonData.return_url;
}, 1500);
}
passtime = jsonData.passtime;
if (passtime <= 0) {
clearTimeout(orderTimer);
}
timer(passtime);
}
queryOrder(`/getOrderState/${order}`);
})();
/* <?php if ($patt == 0 && $passtime > 0) { ?> */
// 验证支付结果
const id = '<?php echo htmlentities($id);?>';
const reVali = (step) => {
setTimeout(() => {
layer.confirm('是否已支付?', { icon: 3, title: '提示', closeBtn: 0 },
(index) => {
(async () => {
const res = await validatePayResult(id, 1);
if (res) { reVali(8000) }
})()
layer.close(index);
}, (index) => {
reVali(5000);
layer.close(index);
})
}, step);
}
reVali(10000);
// 验证支付结果
async function validatePayResult(id, patt) {
const lay = layer.load(2);
let data = { id: id, patt: patt };
const res1 = await fetch(`/validatePayResult`, { method: 'post', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(data) });
const rec1_info = await res1.json();
const info = await new Promise((resolve, reject) => {
setTimeout(() => {
data.patt = 0;
fetch(`/validatePayResult`, { method: 'post', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(data) })
.then((res2) => { return res2.json() }).then((rec2_info) => {
if (rec2_info.code == 0) {
layer.close(lay);
layer.msg('验证失败,稍后重新验证!');
resolve(true);
} else {
layer.close(lay);
layer.msg(rec2_info.msg);
resolve(false);
}
});
}, 5000);
})
return info;
}
/* <?php } ?> */
// 环境判断
const environment = detectBrowserEnvironment();
if (payType === 'wxpay' && environment === 'aliphone') {
layer.alert('请使用微信打开此页面');
} else if (payType === 'alipay' && environment === 'wxphone') {
layer.alert('请使用支付宝打开此页面');
}
// 添加按钮控制逻辑
const openAppBtn = document.getElementById('openApp');
if (environment === 'phone') {
openAppBtn.parentNode.style.display = 'block';
if (payType === 'wxpay') {
openAppBtn.innerText = '截图并打开微信';
openAppBtn.className = 'layui-btn layui-btn-green';
openAppBtn.onclick = function () {
window.location.href = 'weixin://';
};
} else if (payType === 'alipay') {
openAppBtn.innerText = '打开支付宝付款';
openAppBtn.className = 'layui-btn layui-btn-normal';
openAppBtn.onclick = function () {
if (codeType == 0) {
const payUrl = encodeURIComponent(payCode);
window.location.href = 'alipays://platformapi/startapp?appId=20000067&&url=' + payUrl;
} else {
const currentUrl = encodeURIComponent(window.location.href);
window.location.href = 'alipays://platformapi/startapp?appId=20000067&&url=' + currentUrl;
}
};
}
}
// 生成二维码
async function getQrcode(text, QR) {
const qrcodeUrl = await new Promise((resolve) => {
new QR({
text: text,
size: 500,
}).draw().then((dataURL) => { resolve(dataURL); });
})
return qrcodeUrl;
}
// 倒计时
function timer(passtime) {
let minute = 0, second = 0; // 时间默认值
if (passtime > 0) {
minute = Math.floor(passtime / 60);
second = Math.floor(passtime) - (minute * 60);
}
if (passtime <= 0) {
document.getElementById('divTime').innerHTML = '<small class="note">订单二维码已过期</small>';
document.getElementById('qrcode').src = '/static/img/qrcode_timeout.png';// 输出过期二维码提示图片
} else {
document.getElementById('divTime').innerHTML = `二维码有效时间<small class="note">${minute}</small><small class="note">${second}</small> `;
}
}
</script>
</body>
</html>