Files
pangolin/docs/crypto-tx-engine-plan.html
wangjia 5fd0d3c148 feat(pay): 同源收款测试页 GET /_test(Phase E 手动闭环验证)
pay-server 自带 /_test 测试页:创建订单→显示收款地址+精确金额(可复制)
+过期倒计时→轮询状态到 paid。同源、无 CORS/CSP 摩擦,不碰营销站安全头;
纯调 POST /order + GET /order/{id},无私钥无密钥。生产收银台后续走独角数卡门面。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-09 15:51:10 +08:00

105 lines
6.8 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>pangolin-pay 加密货币交易引擎 实现计划</title>
<style>
:root{
--bg:#0f1117; --panel:#171a22; --panel2:#1d2129; --fg:#e6e8ee; --fg2:#a8afbd;
--accent:#e0884f; --accent2:#5fb0c9; --ok:#5ec27a; --bad:#e06a6a; --warn:#e0b84f;
--border:#272c36; --mono:"SF Mono",ui-monospace,Menlo,Consolas,monospace;
--sans:-apple-system,"PingFang SC","Helvetica Neue",Arial,sans-serif;
}
*{box-sizing:border-box}
body{margin:0;background:var(--bg);color:var(--fg);font-family:var(--sans);line-height:1.7;font-size:15px}
.wrap{max-width:960px;margin:0 auto;padding:48px 24px 96px}
h1{font-size:29px;line-height:1.3;margin:0 0 8px;letter-spacing:-.01em}
.sub{color:var(--fg2);font-size:15px;margin:0 0 32px}
h2{font-size:20px;margin:40px 0 12px;padding-bottom:8px;border-bottom:1px solid var(--border);color:var(--accent)}
p{margin:10px 0}
code{font-family:var(--mono);font-size:.85em;background:var(--panel2);padding:1px 6px;border-radius:5px;color:#f0d9c4}
pre{background:#0a0c11;border:1px solid var(--border);border-radius:10px;padding:14px 16px;overflow-x:auto;font-family:var(--mono);font-size:12.5px;line-height:1.5;color:#cdd3df}
.tag{display:inline-block;font-size:12px;font-weight:600;padding:2px 9px;border-radius:999px;vertical-align:middle}
.tag.info{background:rgba(95,176,201,.16);color:var(--accent2)}
ul.ck{list-style:none;padding-left:4px}
ul.ck li{position:relative;padding-left:26px;margin:7px 0}
ul.ck li::before{content:"☐";position:absolute;left:0;color:var(--fg2)}
ul{padding-left:22px}
li{margin:6px 0}
.lead{background:linear-gradient(180deg,rgba(224,136,79,.10),transparent);border:1px solid var(--border);border-radius:12px;padding:18px 20px;margin:0 0 8px}
.small{color:var(--fg2);font-size:13px}
a{color:var(--accent2)}
.back{display:inline-block;margin-bottom:24px;font-size:13px}
b{color:#fff}
.warnbox{background:rgba(224,106,106,.08);border:1px solid rgba(224,106,106,.35);border-radius:12px;padding:14px 18px;margin:14px 0}
.warnbox b{color:var(--bad)}
</style>
</head>
<body>
<div class="wrap">
<a class="back" href="index.html">← 文档索引</a>
<h1>pangolin-pay 加密货币交易引擎</h1>
<p class="sub">2026-07-09 · <span class="tag info">阅读版</span> · 执行真相源 <code>docs/superpowers/plans/2026-07-09-crypto-tx-engine.md</code> · #34 的第一块(可独立执行 + 真实小额验证)</p>
<div class="lead">
#34 的<b>第一块、可独立执行、能用真实小额 USDT 端到端验证</b>的基础件。<b>只做加密货币"交易"核心</b>——派生地址、侦测到账、归集(sweep)——<b>不含</b>独角数卡对接、不含发码。成果=独立 Go 服务 <code>pangolin-pay</code>,提供"建单→收款地址→侦测到账→标记已付"+ 离线归集工具。跑通后任何门面都能挂上来。
</div>
<div class="warnbox">
<b>安全铁律:</b>热服务只持 <b>xpub</b>(watch-only 派生)+ TronGrid key + 金库收款地址,<b>绝不持私钥</b>;私钥/助记词冷存,归集在离线端签名。关键常量(核对无误再写死):USDT-TRC20 合约 <code>TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t</code>(6 位小数)· 派生 <code>m/44'/195'/0'/0/i</code> · TronGrid <code>api.trongrid.io</code>
</div>
<h2>Phase A — 钱包与密钥(全程离线)</h2>
<ul class="ck">
<li><b>A.1</b> 离线生成<b>两套</b>助记词(断网,Ian Coleman/bip_utils,TRX/24词/English):钱包 A 运营收款、钱包 B 冷备金库。</li>
<li><b>A.2</b> 导出<b>钱包 A account xpub</b>(<code>m/44'/195'/0'</code>);取<b>钱包 B 地址0</b> 当归集目标。</li>
<li><b>A.3</b> 冷存助记词 A/B(分开)+ Bitwarden;只把 xpub_A + sweep_addr_B 放进配置。</li>
<li><b>A.4</b> <b>交叉核对</b>:Go 派生出的地址 0..4 必须与 Ian Coleman 逐个一致(防收款地址对不上)。</li>
</ul>
<h2>Phase B — 服务骨架 + HD 派生</h2>
<ul class="ck">
<li><b>B.1</b> 建 Go 服务 <code>pangolin-pay</code>(独立)。配置:xpub_A / sweep_addr_B / TronGrid key / 确认数 / 超时。自带 SQLite。</li>
<li><b>B.2</b> HD 派生:go-bip39 + hdkeychain 从 xpub_A watch-only 派生 <code>.../0/i</code> 公钥 → TRON 地址(Keccak 后20字节 + <code>0x41</code> + Base58Check)。<b>单测对齐 Ian Coleman</b></li>
<li><b>B.3</b> 数据模型:<code>pay_orders(order_no, sku, expect_amount, addr_index, address, status, tx_id, confirmations, created_at, expires_at)</code> + <code>addr_cursor(next_index)</code>(地址不复用)。</li>
</ul>
<h2>Phase C — 收款(建单 + 侦测到账)</h2>
<ul class="ck">
<li><b>C.1</b> <code>POST /order</code> → cursor++ 派生新地址 → 写单(expect_amount 唯一尾数、expires +15min)→ 返回 <code>{order_no, address, expect_amount, expires_at}</code></li>
<li><b>C.2</b> <code>GET /order/{order_no}</code> → status(pending/paid/expired)。</li>
<li><b>C.3</b> TronGrid watcher 轮询:<code>/v1/accounts/{addr}/transactions/trc20?only_confirmed=true&amp;contract_address=&lt;USDT&gt;</code>,匹配 to+金额(6位小数)+确认 → paid、记 tx_id。</li>
<li><b>C.4</b> 幂等(同 tx 只认一次)+ 超时 expired(地址不复用)+ 崩溃恢复。</li>
<li><b>C.5</b> 限流退避 + 重试;mock TronGrid 测试:匹配/确认/超时/幂等/恢复。</li>
</ul>
<h2>Phase D — 归集(sweep,离线签名)</h2>
<ul class="ck">
<li><b>D.1</b> watcher(xpub)列出有余额地址清单。</li>
<li><b>D.2</b> gas:gas 钱包给待归集地址打少量 TRX(或能量租赁)。</li>
<li><b>D.3</b> 离线机导入<b>钱包 A 助记词</b> → 派生 address_i 私钥 → 构造 TRC20 <code>transfer(sweep_addr_B, balance)</code><b>离线签名</b></li>
<li><b>D.4</b> 广播:签好的交易经 TronGrid <code>/wallet/broadcasttransaction</code> 上链(私钥不出门)。</li>
<li><b>D.5</b> 半自动脚本 + 归集 runbook;阈值/定时触发;热地址不囤大额。</li>
</ul>
<h2>Phase E — 端到端验证(真实小额)</h2>
<ul class="ck">
<li><b>E.1</b> 真单:<code>POST /order</code> → 转 1 USDT(TRC20)→ watcher 确认 → status=paid。</li>
<li><b>E.2</b> 归集:D 流程 → USDT 到钱包 B 冷地址。</li>
<li><b>E.3</b> 安全核对:热服务无私钥、密钥不入 git、地址不复用。</li>
</ul>
<h2>不在本轮</h2>
<ul>
<li>独角数卡门面对接 + epay 支付口(下一块:接门面)。</li>
<li><code>/internal/codes/mint</code> JIT 发码 + 兑换闭环(发货侧,#34 后续)。</li>
<li>HD 自动 sweep(先人工)、多币种、watcher 高可用。</li>
</ul>
<p class="small" style="margin-top:32px">相关:<a href="payment-clean-usdt-plan.html">#34 收款闭环全景</a> · <a href="payment-channels-overview.html">渠道选型</a> · 知识:brain <code>notes/dev/crypto-hd-wallet-basics.html</code></p>
</div>
</body>
</html>