feat(pay): 收款模型改为单地址+唯一金额(#34/34A Phase A-C)
从"每单唯一 HD 地址"改为"单个固定收款地址 + 每单唯一金额",归集成本 O(订单数)→O(1)。 - store: pay_orders 加 user_ref/expect_amount(唯一金额)/matched_tx_id;新 orphan_payments 表; ActiveOrderByUser(同用户单订单)、AmountRecentlyUsed(迟到窗口内金额不复用)、TxHandled(幂等)、 RecordOrphan。去掉每单派生游标。 - pay: CreateOrder(userRef,sku,priceMicro)——同用户单订单校验 + 分配唯一金额(base+随机微尾数[1,9999]、 cooldown 内不复用),address 恒为收款地址。 - tron: Transfer 加 BlockTs(区块时间秒),取 block_timestamp。 - watcher: 单地址取到账,按"金额==expect && block_ts>建单"匹配 → paid;不匹配的到账 → orphan;幂等。 - httpapi: POST /order 加 user_ref,同用户重复 → 409;main 收款地址=PAY_RECEIVE_ADDRESS 或 xpub index0。 - 测试:唯一金额/同地址、同用户单订单、精确匹配、付错成孤儿、迟到不误配新单、付款早于建单不匹配、 超时、幂等、409,全绿。README 更新为单地址模型+API(user_ref/精确金额/orphan)。 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
+16
-5
@@ -1,8 +1,13 @@
|
||||
# pangolin-pay
|
||||
|
||||
自托管 USDT(TRC20) 收款服务。给每个订单派生一个**唯一收款地址**(watch-only,从账户
|
||||
xpub 派生,**不持私钥**),轮询 TronGrid 侦测到账、确认后标记订单已付。归集(把钱扫到冷
|
||||
钱包)是**独立的离线步骤**,本服务不碰私钥。
|
||||
自托管 USDT(TRC20) 收款服务。**单个固定收款地址 + 每单唯一金额**:所有订单收到同一个地址,
|
||||
靠**唯一金额**(基准价 + 微尾数,≤0.01 USDT)区分。watcher 轮询 TronGrid,按
|
||||
**"到账 tx + 精确金额 + 区块时间晚于建单"** 匹配订单;匹配不到活跃订单的到账(付错/迟到)→
|
||||
记 `orphan_payments` 人工对账。归集(把钱扫到冷钱包)是**独立离线步骤**,本服务**不持私钥**。
|
||||
|
||||
> 收款地址 = 钱包 A 的地址 0(`m/44'/195'/0'/0/0`),配置注入或由 xpub 派生。
|
||||
> 前端契约(`POST /order` 返回 address+expect_amount)与地址模型解耦——以后要升多地址/GasFree
|
||||
> 是纯后端换实现,前端零改动。模型定稿见 `docs/pay-single-address-plan.html`。
|
||||
|
||||
> 属 #34「独角数卡 + USDT 收款闭环」的加密货币交易引擎(计划见
|
||||
> `docs/superpowers/plans/2026-07-09-crypto-tx-engine.md`)。概念见 brain
|
||||
@@ -74,13 +79,19 @@ go run ./cmd/paywatch
|
||||
## API
|
||||
|
||||
```
|
||||
POST /order {"sku":"pro-year","amount":5000000} # amount = micro-USDT(1e-6)
|
||||
POST /order {"user_ref":"buyer123","sku":"pro-year","amount":5000000} # amount = 基准价 micro-USDT(1e-6)
|
||||
→ 201 {"order_no","address","expect_amount","status":"pending","expires_at"}
|
||||
# expect_amount = 基准 + 唯一微尾数;支付页要显示"请付精确金额 expect_amount"
|
||||
→ 409 {"error":"user already has an active order"} # 同一 user_ref 同时只能一个活跃订单
|
||||
GET /order/{orderNo} → 200 {..., "status":"pending|paid|expired","tx_id"}
|
||||
GET /healthz → 200 ok
|
||||
```
|
||||
|
||||
门面(独角数卡)下单时调 `POST /order` 拿收款地址;支付页轮询 `GET /order/{id}` 直到 `paid`。
|
||||
门面(独角数卡)下单时调 `POST /order`(带 `user_ref`)拿 **address + expect_amount**;
|
||||
支付页显示"往 address 付**精确的** expect_amount"(可复制),轮询 `GET /order/{id}` 直到 `paid`。
|
||||
用户付错金额 → 该到账进 orphan,需人工对账。
|
||||
|
||||
配置:`PAY_RECEIVE_ADDRESS`(单收款地址)或 `PAY_ACCOUNT_XPUB`(自动派生 index 0)。
|
||||
|
||||
## Phase D —— 归集(气隙签名,`cmd/sweep`)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user