主要更新: 1. 按H5网页端完全重构匹配功能(match页面) - 4种匹配类型: 创业合伙/资源对接/导师顾问/团队招募 - 资源对接等类型弹出手机号/微信号输入框 - 去掉重新匹配按钮,改为返回按钮 2. 修复所有卡片对齐和宽度问题 - 目录页附录卡片居中 - 首页阅读进度卡片满宽度 - 我的页面菜单卡片对齐 - 推广中心分享卡片统一宽度 3. 修复目录页图标和文字对齐 - section-icon固定40rpx宽高 - section-title与图标垂直居中 4. 更新真实完整文章标题(62篇) - 从book目录读取真实markdown文件名 - 替换之前的简化标题 5. 新增文章数据API - /api/db/chapters - 获取完整书籍结构 - 支持按ID获取单篇文章内容
749 lines
23 KiB
HTML
749 lines
23 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="zh-CN">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>通用收银台 v4.0</title>
|
|
<style>
|
|
/*
|
|
* 通用收银台样式 - 支持多种支付方式
|
|
* 作者: 卡若
|
|
* 适配: PC + 移动端
|
|
*/
|
|
|
|
:root {
|
|
--primary-color: #1890ff;
|
|
--success-color: #52c41a;
|
|
--warning-color: #faad14;
|
|
--error-color: #ff4d4f;
|
|
--text-color: #333;
|
|
--text-secondary: #666;
|
|
--border-color: #e8e8e8;
|
|
--bg-color: #f5f5f7;
|
|
--card-bg: #ffffff;
|
|
}
|
|
|
|
* {
|
|
margin: 0;
|
|
padding: 0;
|
|
box-sizing: border-box;
|
|
}
|
|
|
|
body {
|
|
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
|
|
background: var(--bg-color);
|
|
color: var(--text-color);
|
|
min-height: 100vh;
|
|
padding: 20px;
|
|
}
|
|
|
|
.cashier-container {
|
|
max-width: 480px;
|
|
margin: 0 auto;
|
|
}
|
|
|
|
.cashier-card {
|
|
background: var(--card-bg);
|
|
border-radius: 16px;
|
|
padding: 24px;
|
|
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.08);
|
|
margin-bottom: 16px;
|
|
}
|
|
|
|
/* 订单信息 */
|
|
.order-section {
|
|
text-align: center;
|
|
padding-bottom: 20px;
|
|
border-bottom: 1px dashed var(--border-color);
|
|
margin-bottom: 20px;
|
|
}
|
|
|
|
.order-title {
|
|
font-size: 16px;
|
|
color: var(--text-secondary);
|
|
margin-bottom: 8px;
|
|
}
|
|
|
|
.order-amount {
|
|
font-size: 42px;
|
|
font-weight: 700;
|
|
color: var(--text-color);
|
|
letter-spacing: -1px;
|
|
}
|
|
|
|
.order-amount .currency {
|
|
font-size: 24px;
|
|
font-weight: 400;
|
|
margin-right: 4px;
|
|
}
|
|
|
|
.order-info {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
font-size: 14px;
|
|
color: var(--text-secondary);
|
|
margin-top: 12px;
|
|
}
|
|
|
|
.countdown {
|
|
color: var(--warning-color);
|
|
font-weight: 500;
|
|
}
|
|
|
|
/* 支付方式选择 */
|
|
.payment-section h3 {
|
|
font-size: 14px;
|
|
color: var(--text-secondary);
|
|
margin-bottom: 12px;
|
|
}
|
|
|
|
.payment-methods {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 10px;
|
|
}
|
|
|
|
.payment-method {
|
|
display: flex;
|
|
align-items: center;
|
|
padding: 16px;
|
|
border: 2px solid var(--border-color);
|
|
border-radius: 12px;
|
|
cursor: pointer;
|
|
transition: all 0.2s ease;
|
|
background: var(--card-bg);
|
|
}
|
|
|
|
.payment-method:hover {
|
|
border-color: var(--primary-color);
|
|
background: rgba(24, 144, 255, 0.04);
|
|
}
|
|
|
|
.payment-method.active {
|
|
border-color: var(--primary-color);
|
|
background: rgba(24, 144, 255, 0.08);
|
|
}
|
|
|
|
.payment-method .icon {
|
|
width: 36px;
|
|
height: 36px;
|
|
border-radius: 8px;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
font-size: 24px;
|
|
margin-right: 12px;
|
|
}
|
|
|
|
.payment-method .icon.alipay { background: #1677ff; color: white; }
|
|
.payment-method .icon.wechat { background: #07c160; color: white; }
|
|
.payment-method .icon.paypal { background: #003087; color: white; }
|
|
.payment-method .icon.stripe { background: #635bff; color: white; }
|
|
.payment-method .icon.usdt { background: #26a17b; color: white; }
|
|
|
|
.payment-method .info {
|
|
flex: 1;
|
|
}
|
|
|
|
.payment-method .name {
|
|
font-size: 16px;
|
|
font-weight: 500;
|
|
margin-bottom: 2px;
|
|
}
|
|
|
|
.payment-method .desc {
|
|
font-size: 12px;
|
|
color: var(--text-secondary);
|
|
}
|
|
|
|
.payment-method .radio {
|
|
width: 20px;
|
|
height: 20px;
|
|
border: 2px solid var(--border-color);
|
|
border-radius: 50%;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
transition: all 0.2s ease;
|
|
}
|
|
|
|
.payment-method.active .radio {
|
|
border-color: var(--primary-color);
|
|
background: var(--primary-color);
|
|
}
|
|
|
|
.payment-method.active .radio::after {
|
|
content: '✓';
|
|
color: white;
|
|
font-size: 12px;
|
|
}
|
|
|
|
/* 二维码区域 */
|
|
.qrcode-section {
|
|
text-align: center;
|
|
padding: 24px;
|
|
display: none;
|
|
}
|
|
|
|
.qrcode-section.show {
|
|
display: block;
|
|
}
|
|
|
|
.qrcode-box {
|
|
width: 200px;
|
|
height: 200px;
|
|
margin: 0 auto 16px;
|
|
border: 1px solid var(--border-color);
|
|
border-radius: 12px;
|
|
overflow: hidden;
|
|
background: white;
|
|
}
|
|
|
|
.qrcode-box img {
|
|
width: 100%;
|
|
height: 100%;
|
|
object-fit: contain;
|
|
}
|
|
|
|
.qrcode-text {
|
|
font-size: 14px;
|
|
color: var(--text-secondary);
|
|
}
|
|
|
|
.qrcode-tip {
|
|
margin-top: 8px;
|
|
font-size: 12px;
|
|
color: var(--warning-color);
|
|
}
|
|
|
|
/* USDT 地址显示 */
|
|
.usdt-address {
|
|
background: #f9f9f9;
|
|
border-radius: 8px;
|
|
padding: 16px;
|
|
word-break: break-all;
|
|
font-family: monospace;
|
|
font-size: 14px;
|
|
margin-top: 12px;
|
|
}
|
|
|
|
.copy-btn {
|
|
margin-top: 8px;
|
|
padding: 8px 16px;
|
|
background: var(--primary-color);
|
|
color: white;
|
|
border: none;
|
|
border-radius: 6px;
|
|
cursor: pointer;
|
|
font-size: 14px;
|
|
}
|
|
|
|
/* 支付按钮 */
|
|
.pay-btn {
|
|
width: 100%;
|
|
padding: 16px;
|
|
background: linear-gradient(135deg, #1890ff 0%, #096dd9 100%);
|
|
color: white;
|
|
border: none;
|
|
border-radius: 12px;
|
|
font-size: 18px;
|
|
font-weight: 600;
|
|
cursor: pointer;
|
|
transition: all 0.3s ease;
|
|
margin-top: 24px;
|
|
}
|
|
|
|
.pay-btn:hover {
|
|
transform: translateY(-2px);
|
|
box-shadow: 0 8px 20px rgba(24, 144, 255, 0.3);
|
|
}
|
|
|
|
.pay-btn:disabled {
|
|
background: #ccc;
|
|
cursor: not-allowed;
|
|
transform: none;
|
|
box-shadow: none;
|
|
}
|
|
|
|
.pay-btn.loading {
|
|
position: relative;
|
|
color: transparent;
|
|
}
|
|
|
|
.pay-btn.loading::after {
|
|
content: '';
|
|
position: absolute;
|
|
width: 20px;
|
|
height: 20px;
|
|
border: 2px solid transparent;
|
|
border-top-color: white;
|
|
border-radius: 50%;
|
|
animation: spin 0.8s linear infinite;
|
|
left: 50%;
|
|
top: 50%;
|
|
margin-left: -10px;
|
|
margin-top: -10px;
|
|
}
|
|
|
|
@keyframes spin {
|
|
to { transform: rotate(360deg); }
|
|
}
|
|
|
|
/* 支付成功 */
|
|
.success-section {
|
|
text-align: center;
|
|
padding: 40px 20px;
|
|
display: none;
|
|
}
|
|
|
|
.success-section.show {
|
|
display: block;
|
|
}
|
|
|
|
.success-icon {
|
|
width: 80px;
|
|
height: 80px;
|
|
border-radius: 50%;
|
|
background: var(--success-color);
|
|
color: white;
|
|
font-size: 48px;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
margin: 0 auto 20px;
|
|
animation: scaleIn 0.5s ease;
|
|
}
|
|
|
|
@keyframes scaleIn {
|
|
0% { transform: scale(0); }
|
|
50% { transform: scale(1.2); }
|
|
100% { transform: scale(1); }
|
|
}
|
|
|
|
.success-section h2 {
|
|
font-size: 24px;
|
|
margin-bottom: 8px;
|
|
}
|
|
|
|
.success-section p {
|
|
color: var(--text-secondary);
|
|
}
|
|
|
|
.return-btn {
|
|
margin-top: 24px;
|
|
padding: 12px 32px;
|
|
background: var(--primary-color);
|
|
color: white;
|
|
border: none;
|
|
border-radius: 8px;
|
|
font-size: 16px;
|
|
cursor: pointer;
|
|
}
|
|
|
|
/* 安全提示 */
|
|
.security-tips {
|
|
text-align: center;
|
|
padding: 12px;
|
|
font-size: 12px;
|
|
color: var(--text-secondary);
|
|
}
|
|
|
|
.security-tips span {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: 4px;
|
|
}
|
|
|
|
/* 响应式 */
|
|
@media (max-width: 480px) {
|
|
body {
|
|
padding: 0;
|
|
}
|
|
|
|
.cashier-container {
|
|
max-width: 100%;
|
|
}
|
|
|
|
.cashier-card {
|
|
border-radius: 0;
|
|
padding: 20px 16px;
|
|
}
|
|
|
|
.order-amount {
|
|
font-size: 36px;
|
|
}
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
|
|
<div class="cashier-container">
|
|
<!-- 订单信息卡片 -->
|
|
<div class="cashier-card" id="orderCard">
|
|
<div class="order-section">
|
|
<div class="order-title" id="orderTitle">VIP会员月卡</div>
|
|
<div class="order-amount">
|
|
<span class="currency">¥</span>
|
|
<span id="displayAmount">99.00</span>
|
|
</div>
|
|
<div class="order-info">
|
|
<span>订单号: <span id="orderSn">202401170001</span></span>
|
|
<span class="countdown" id="countdown">29:59</span>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 支付方式选择 -->
|
|
<div class="payment-section" id="paymentSection">
|
|
<h3>选择支付方式</h3>
|
|
<div class="payment-methods" id="paymentMethods">
|
|
<!-- 支付宝 -->
|
|
<div class="payment-method" data-gateway="alipay_wap" onclick="selectMethod(this)">
|
|
<div class="icon alipay">💙</div>
|
|
<div class="info">
|
|
<div class="name">支付宝</div>
|
|
<div class="desc">推荐有支付宝账户的用户使用</div>
|
|
</div>
|
|
<div class="radio"></div>
|
|
</div>
|
|
|
|
<!-- 微信支付 -->
|
|
<div class="payment-method" data-gateway="wechat_native" onclick="selectMethod(this)">
|
|
<div class="icon wechat">💚</div>
|
|
<div class="info">
|
|
<div class="name">微信支付</div>
|
|
<div class="desc">扫码支付,微信用户首选</div>
|
|
</div>
|
|
<div class="radio"></div>
|
|
</div>
|
|
|
|
<!-- PayPal -->
|
|
<div class="payment-method" data-gateway="paypal" onclick="selectMethod(this)">
|
|
<div class="icon paypal">🅿️</div>
|
|
<div class="info">
|
|
<div class="name">PayPal</div>
|
|
<div class="desc">支持信用卡,海外用户推荐</div>
|
|
</div>
|
|
<div class="radio"></div>
|
|
</div>
|
|
|
|
<!-- USDT -->
|
|
<div class="payment-method" data-gateway="usdt" onclick="selectMethod(this)">
|
|
<div class="icon usdt">₮</div>
|
|
<div class="info">
|
|
<div class="name">USDT (TRC20)</div>
|
|
<div class="desc">加密货币支付</div>
|
|
</div>
|
|
<div class="radio"></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 二维码区域 -->
|
|
<div class="qrcode-section" id="qrcodeSection">
|
|
<div class="qrcode-box">
|
|
<img id="qrcodeImg" src="" alt="支付二维码">
|
|
</div>
|
|
<div class="qrcode-text" id="qrcodeText">请使用微信扫描二维码支付</div>
|
|
<div class="qrcode-tip">二维码有效期 30 分钟,请尽快支付</div>
|
|
|
|
<!-- USDT 地址 -->
|
|
<div class="usdt-address" id="usdtAddress" style="display: none;"></div>
|
|
<button class="copy-btn" id="copyBtn" style="display: none;" onclick="copyAddress()">复制地址</button>
|
|
</div>
|
|
|
|
<!-- 支付按钮 -->
|
|
<button class="pay-btn" id="payBtn" onclick="doPay()">确认支付 ¥99.00</button>
|
|
</div>
|
|
|
|
<!-- 支付成功 -->
|
|
<div class="cashier-card success-section" id="successSection">
|
|
<div class="success-icon">✓</div>
|
|
<h2>支付成功</h2>
|
|
<p>感谢您的购买,订单已完成</p>
|
|
<button class="return-btn" onclick="goBack()">返回商户</button>
|
|
</div>
|
|
|
|
<!-- 安全提示 -->
|
|
<div class="security-tips">
|
|
<span>🔒 安全支付由卡若私域提供技术支持</span>
|
|
</div>
|
|
</div>
|
|
|
|
<script>
|
|
/**
|
|
* 通用收银台 JavaScript v4.0
|
|
* 作者: 卡若
|
|
*
|
|
* 使用方法:
|
|
* 1. 修改 API_BASE 为你的后端地址
|
|
* 2. 通过 URL 参数传入订单信息: ?order_sn=xxx&amount=99.00&title=商品名称
|
|
*/
|
|
|
|
// 配置
|
|
const API_BASE = '/api/payment'; // 你的后端接口地址
|
|
const POLL_INTERVAL = 3000; // 轮询间隔 (毫秒)
|
|
const ORDER_TIMEOUT = 30 * 60; // 订单超时时间 (秒)
|
|
|
|
// 状态
|
|
let selectedGateway = null;
|
|
let orderSn = '';
|
|
let orderAmount = 0;
|
|
let countdownTimer = null;
|
|
let pollTimer = null;
|
|
let remainingSeconds = ORDER_TIMEOUT;
|
|
|
|
// 初始化
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
// 从 URL 解析订单信息
|
|
const params = new URLSearchParams(window.location.search);
|
|
orderSn = params.get('order_sn') || '202401170001';
|
|
orderAmount = parseFloat(params.get('amount')) || 99.00;
|
|
const title = params.get('title') || 'VIP会员月卡';
|
|
|
|
// 更新UI
|
|
document.getElementById('orderSn').textContent = orderSn;
|
|
document.getElementById('orderTitle').textContent = title;
|
|
document.getElementById('displayAmount').textContent = orderAmount.toFixed(2);
|
|
document.getElementById('payBtn').textContent = `确认支付 ¥${orderAmount.toFixed(2)}`;
|
|
|
|
// 启动倒计时
|
|
startCountdown();
|
|
|
|
// 检测微信环境
|
|
if (isWechat()) {
|
|
// 微信环境默认选择JSAPI
|
|
const wechatMethod = document.querySelector('[data-gateway="wechat_native"]');
|
|
if (wechatMethod) {
|
|
wechatMethod.dataset.gateway = 'wechat_jsapi';
|
|
wechatMethod.querySelector('.desc').textContent = '微信内直接支付';
|
|
}
|
|
}
|
|
});
|
|
|
|
// 选择支付方式
|
|
function selectMethod(element) {
|
|
// 移除其他选中状态
|
|
document.querySelectorAll('.payment-method').forEach(el => {
|
|
el.classList.remove('active');
|
|
});
|
|
|
|
// 设置选中状态
|
|
element.classList.add('active');
|
|
selectedGateway = element.dataset.gateway;
|
|
|
|
// 隐藏二维码区域
|
|
document.getElementById('qrcodeSection').classList.remove('show');
|
|
document.getElementById('paymentSection').style.display = 'block';
|
|
document.getElementById('payBtn').style.display = 'block';
|
|
|
|
// 更新金额显示 (USDT显示美元)
|
|
if (selectedGateway === 'usdt') {
|
|
const usdtAmount = (orderAmount / 7.2).toFixed(2); // 简单汇率转换
|
|
document.getElementById('displayAmount').textContent = usdtAmount;
|
|
document.querySelector('.currency').textContent = '₮';
|
|
document.getElementById('payBtn').textContent = `确认支付 ₮${usdtAmount}`;
|
|
} else if (selectedGateway === 'paypal') {
|
|
const usdAmount = (orderAmount / 7.2).toFixed(2);
|
|
document.getElementById('displayAmount').textContent = usdAmount;
|
|
document.querySelector('.currency').textContent = '$';
|
|
document.getElementById('payBtn').textContent = `确认支付 $${usdAmount}`;
|
|
} else {
|
|
document.getElementById('displayAmount').textContent = orderAmount.toFixed(2);
|
|
document.querySelector('.currency').textContent = '¥';
|
|
document.getElementById('payBtn').textContent = `确认支付 ¥${orderAmount.toFixed(2)}`;
|
|
}
|
|
}
|
|
|
|
// 发起支付
|
|
async function doPay() {
|
|
if (!selectedGateway) {
|
|
alert('请选择支付方式');
|
|
return;
|
|
}
|
|
|
|
const payBtn = document.getElementById('payBtn');
|
|
payBtn.classList.add('loading');
|
|
payBtn.disabled = true;
|
|
|
|
try {
|
|
// 调用后端接口
|
|
const response = await fetch(`${API_BASE}/checkout`, {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify({
|
|
order_sn: orderSn,
|
|
gateway: selectedGateway,
|
|
return_url: window.location.href
|
|
})
|
|
});
|
|
|
|
const result = await response.json();
|
|
|
|
if (result.code !== 200) {
|
|
throw new Error(result.message || '支付发起失败');
|
|
}
|
|
|
|
const { type, payload, trade_sn } = result.data;
|
|
|
|
switch (type) {
|
|
case 'url':
|
|
// 跳转支付 (支付宝H5, PayPal, Stripe)
|
|
window.location.href = payload;
|
|
break;
|
|
|
|
case 'qrcode':
|
|
// 显示二维码 (微信Native, 支付宝扫码)
|
|
showQrcode(payload, selectedGateway);
|
|
startPolling(trade_sn);
|
|
break;
|
|
|
|
case 'json':
|
|
// 调起SDK (微信JSAPI)
|
|
callWechatPay(payload);
|
|
break;
|
|
|
|
case 'address':
|
|
// 显示钱包地址 (USDT)
|
|
showUsdtAddress(payload);
|
|
startPolling(trade_sn);
|
|
break;
|
|
|
|
case 'direct':
|
|
// 直接完成 (虚拟币支付)
|
|
showSuccess();
|
|
break;
|
|
}
|
|
|
|
} catch (error) {
|
|
console.error('支付失败:', error);
|
|
alert(error.message || '支付发起失败,请重试');
|
|
} finally {
|
|
payBtn.classList.remove('loading');
|
|
payBtn.disabled = false;
|
|
}
|
|
}
|
|
|
|
// 显示二维码
|
|
function showQrcode(content, gateway) {
|
|
document.getElementById('paymentSection').style.display = 'none';
|
|
document.getElementById('payBtn').style.display = 'none';
|
|
document.getElementById('qrcodeSection').classList.add('show');
|
|
|
|
// 使用在线服务生成二维码
|
|
const qrcodeUrl = `https://api.qrserver.com/v1/create-qr-code/?size=200x200&data=${encodeURIComponent(content)}`;
|
|
document.getElementById('qrcodeImg').src = qrcodeUrl;
|
|
|
|
// 更新提示文字
|
|
const texts = {
|
|
'wechat_native': '请使用微信扫描二维码支付',
|
|
'alipay_qr': '请使用支付宝扫描二维码支付'
|
|
};
|
|
document.getElementById('qrcodeText').textContent = texts[gateway] || '请扫描二维码支付';
|
|
}
|
|
|
|
// 显示USDT地址
|
|
function showUsdtAddress(addressInfo) {
|
|
document.getElementById('paymentSection').style.display = 'none';
|
|
document.getElementById('payBtn').style.display = 'none';
|
|
document.getElementById('qrcodeSection').classList.add('show');
|
|
|
|
const { address, amount_usdt, memo } = addressInfo;
|
|
|
|
document.getElementById('qrcodeImg').src = `https://api.qrserver.com/v1/create-qr-code/?size=200x200&data=${encodeURIComponent(address)}`;
|
|
document.getElementById('qrcodeText').textContent = `请向以下地址转账 ${amount_usdt} USDT (TRC20)`;
|
|
document.getElementById('usdtAddress').textContent = address;
|
|
document.getElementById('usdtAddress').style.display = 'block';
|
|
document.getElementById('copyBtn').style.display = 'inline-block';
|
|
}
|
|
|
|
// 复制地址
|
|
function copyAddress() {
|
|
const address = document.getElementById('usdtAddress').textContent;
|
|
navigator.clipboard.writeText(address).then(() => {
|
|
alert('地址已复制');
|
|
});
|
|
}
|
|
|
|
// 调用微信JSAPI支付
|
|
function callWechatPay(params) {
|
|
if (typeof WeixinJSBridge === 'undefined') {
|
|
alert('请在微信中打开此页面');
|
|
return;
|
|
}
|
|
|
|
WeixinJSBridge.invoke('getBrandWCPayRequest', params, function(res) {
|
|
if (res.err_msg === 'get_brand_wcpay_request:ok') {
|
|
showSuccess();
|
|
} else {
|
|
alert('支付取消或失败');
|
|
}
|
|
});
|
|
}
|
|
|
|
// 轮询支付状态
|
|
function startPolling(tradeSn) {
|
|
if (pollTimer) clearInterval(pollTimer);
|
|
|
|
pollTimer = setInterval(async () => {
|
|
try {
|
|
const response = await fetch(`${API_BASE}/status/${orderSn}`);
|
|
const result = await response.json();
|
|
|
|
if (result.data && result.data.status === 'paid') {
|
|
clearInterval(pollTimer);
|
|
showSuccess();
|
|
}
|
|
} catch (error) {
|
|
console.error('查询状态失败:', error);
|
|
}
|
|
}, POLL_INTERVAL);
|
|
}
|
|
|
|
// 显示支付成功
|
|
function showSuccess() {
|
|
document.getElementById('orderCard').style.display = 'none';
|
|
document.getElementById('successSection').classList.add('show');
|
|
|
|
// 停止轮询和倒计时
|
|
if (pollTimer) clearInterval(pollTimer);
|
|
if (countdownTimer) clearInterval(countdownTimer);
|
|
}
|
|
|
|
// 返回商户
|
|
function goBack() {
|
|
const returnUrl = new URLSearchParams(window.location.search).get('return_url');
|
|
if (returnUrl) {
|
|
window.location.href = returnUrl;
|
|
} else {
|
|
window.history.back();
|
|
}
|
|
}
|
|
|
|
// 倒计时
|
|
function startCountdown() {
|
|
countdownTimer = setInterval(() => {
|
|
remainingSeconds--;
|
|
|
|
if (remainingSeconds <= 0) {
|
|
clearInterval(countdownTimer);
|
|
alert('订单已超时,请重新下单');
|
|
window.history.back();
|
|
return;
|
|
}
|
|
|
|
const minutes = Math.floor(remainingSeconds / 60);
|
|
const seconds = remainingSeconds % 60;
|
|
document.getElementById('countdown').textContent =
|
|
`${String(minutes).padStart(2, '0')}:${String(seconds).padStart(2, '0')}`;
|
|
}, 1000);
|
|
}
|
|
|
|
// 检测微信环境
|
|
function isWechat() {
|
|
return /MicroMessenger/i.test(navigator.userAgent);
|
|
}
|
|
</script>
|
|
|
|
</body>
|
|
</html>
|