6da6964451
- Go/Gin/GORM + 纯 Go SQLite(无 cgo) - Channel 多渠道接口:支付宝当面付(precreate)/电脑网站支付(page.pay) 已实现,微信占位 - 多商户 merchants 表,回调验签+金额核对+幂等+查单兜底 - 收款页/结果页/二维码端点;docs/ 设计文档与部署 Runbook - 密钥走环境变量/Bitwarden,不入库 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
71 lines
3.3 KiB
HTML
71 lines
3.3 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>支付结果</title>
|
|
<style>
|
|
:root{--bg:#0d1117;--card:#161b22;--border:#283041;--fg:#e6edf3;--fg-soft:#aeb9c7;--muted:#7d8896;--accent:#58a6ff;--green:#3fb950;--orange:#d29922;--radius:14px}
|
|
*{box-sizing:border-box}
|
|
body{margin:0;min-height:100vh;background:radial-gradient(1000px 500px at 80% -10%,rgba(88,166,255,.08),transparent 60%),var(--bg);color:var(--fg);font:15px/1.6 -apple-system,BlinkMacSystemFont,"PingFang SC","Microsoft YaHei",sans-serif;display:flex;align-items:center;justify-content:center;padding:24px}
|
|
.card{width:100%;max-width:420px;background:var(--card);border:1px solid var(--border);border-radius:var(--radius);padding:30px 26px;text-align:center}
|
|
.icon{font-size:52px;line-height:1;margin-bottom:10px}
|
|
h1{font-size:21px;margin:6px 0 16px}
|
|
.row{display:flex;justify-content:space-between;padding:9px 0;border-top:1px solid var(--border);font-size:14px}
|
|
.row .k{color:var(--muted)}
|
|
.row .v{color:var(--fg-soft);word-break:break-all;text-align:right;max-width:60%}
|
|
.paid{color:var(--green)} .pending{color:var(--orange)}
|
|
a{display:inline-block;margin-top:20px;color:var(--accent);text-decoration:none;font-size:14px}
|
|
.hint{color:var(--muted);font-size:12.5px;margin-top:8px}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<div class="card">
|
|
<div class="icon" id="icon">⏳</div>
|
|
<h1 id="title">正在确认支付结果…</h1>
|
|
<div id="detail"></div>
|
|
<div class="hint" id="hint">到账以异步通知为准,正在轮询…</div>
|
|
<a href="/">← 返回收款页</a>
|
|
</div>
|
|
<script>
|
|
const params = new URLSearchParams(location.search);
|
|
const out = params.get('out_trade_no');
|
|
const iconEl = document.getElementById('icon');
|
|
const titleEl = document.getElementById('title');
|
|
const detailEl = document.getElementById('detail');
|
|
const hintEl = document.getElementById('hint');
|
|
|
|
function render(o){
|
|
const paid = o.status === 'paid';
|
|
iconEl.textContent = paid ? '✅' : '⏳';
|
|
titleEl.textContent = paid ? '支付成功' : '等待支付确认';
|
|
titleEl.className = paid ? 'paid' : 'pending';
|
|
detailEl.innerHTML = `
|
|
<div class="row"><span class="k">商品</span><span class="v">${o.subject||'-'}</span></div>
|
|
<div class="row"><span class="k">金额</span><span class="v">¥${o.amount}</span></div>
|
|
<div class="row"><span class="k">状态</span><span class="v ${paid?'paid':'pending'}">${paid?'已支付':'待支付'}</span></div>
|
|
<div class="row"><span class="k">订单号</span><span class="v">${o.out_trade_no}</span></div>
|
|
${o.trade_no?`<div class="row"><span class="k">支付宝流水</span><span class="v">${o.trade_no}</span></div>`:''}`;
|
|
return paid;
|
|
}
|
|
|
|
let tries = 0;
|
|
async function poll(){
|
|
if(!out){ titleEl.textContent='缺少订单号'; iconEl.textContent='⚠️'; hintEl.textContent=''; return; }
|
|
try{
|
|
const r = await fetch('/api/v1/orders/'+encodeURIComponent(out));
|
|
const j = await r.json();
|
|
if(r.ok){
|
|
const paid = render(j.data);
|
|
if(paid){ hintEl.textContent=''; return; }
|
|
}
|
|
}catch(e){}
|
|
tries++;
|
|
if(tries < 10){ setTimeout(poll, 2000); }
|
|
else { hintEl.textContent = '尚未确认到账。异步通知可能稍有延迟,可稍后刷新本页。'; }
|
|
}
|
|
poll();
|
|
</script>
|
|
</body>
|
|
</html>
|