fix(posts): apply consultant round-1 audit to 01 and 03
Deploy / build (push) Successful in 32s

01 architecting-sea-payment-and-offline-licensing-pipelines (EN+ZH)
- rewrite toyyibPay callback: hash = MD5(secretKey+status+order_id+refno+"ok")
  with hash_equals, transBegin + lockForUpdateByBillCode (no TOCTOU),
  integer-cents money comparison, fulfilment queued after commit so a
  gateway outage cannot roll back a paid order
- abstract hardware fingerprint to multi-dimensional immutable registers;
  add k-of-n (4 choose 3) threshold matching section
- drop unmeasured metrics (99.8% / 1.8s / 70%); fix duplicated 离线离线 typo

03 traefik-yaegi-plugin-package-name-trap (EN+ZH)
- title: drop second-person "Your"
- fix YAIEGI -> YAEGI code comment typo
- add Go-spec root cause (hyphen is subtraction, go.mod decoupling vs Yaegi)
- add .traefik.yml manifest contract paragraph
- sanitize YAML thresholds as illustrative; add "where Yaegi stops being
  the right tool" boundary section
- de-second-person the closing paragraph

Consultant review pack v1.1 shipped separately (docx 05 = response ledger).
This commit is contained in:
hoelee committed 2026-10-29 13:59:02 +08:00
1 parent c0ea7ea066
commit a7077a3a1d
4 files changed
+209 -46

No files matched your search

@@ -13,10 +13,10 @@ summary:
audience: "金融科技工程师、SaaS 架构师与技术业务负责人"
painPoint: "在东南亚地区销售桌面客户端软件时,直接采用西方主流支付(Stripe/PayPal)会因极低的信用卡普及率导致弃单率高企,且原始二进制极易遭遇跨机器盗版传播。"
impact:
- metric: "99.8% 本地支付成功率"
detail: "原生对接 toyyibPay 聚合网关,覆盖马来西亚 FPX 本地在线网银与 DuitNow QR 直付通道,消解信用卡结算门槛。"
- metric: "零信用卡收银通道"
detail: "原生对接 toyyibPay 聚合网关,覆盖马来西亚 FPX 本地在线网银与 DuitNow QR 直付通道,从根上移除信用卡结算门槛,而不是在卡片表单上做优化。"
- metric: "机器码硬件级防盗"
detail: "通过 Keygate 将软件授权与 CPU/主板硬件指纹强绑定并签名,彻底杜绝一码多用,同时支持内网离线离线验活。"
detail: "通过 Keygate 将软件授权与 CPU/主板硬件指纹强绑定并签名,彻底杜绝一码多用,同时支持内网纯离线验活。"
- metric: "100% 幂等状态机履约"
detail: "设计带分布式锁的 Webhook 消费引擎,确保在银行网络波动与重试风暴下绝不发生重复发码与状态覆盖。"
stack: ["toyyibPay API", "Keygate 授权服务", "PHP/CodeIgniter", "PostgreSQL", "Telegram 自动化"]
@@ -32,7 +32,7 @@ dynamicCta: true
在面向东南亚区域(尤其是马来西亚、新加坡和印尼)的企业客户与独立专业人员交付桌面客户端工具时,直接套用欧美的常规 SaaS 支付架构往往会在上线第一天遭遇滑铁卢。
如果在结账页面上直接套用常规的 Stripe Elements 或 PayPal,系统会立即撞上两堵现实高墙:
1. **信用卡渗透率低下**:在马来西亚本地企业主与从业者中,超过 **70% 的线上交易严重依赖 FPX(Financial Process Exchange)本地在线网银直连或 DuitNow QR 扫码支付**,绝大多数人不习惯或根本没有可用于扣费的企业信用卡。
1. **信用卡渗透率低下**:在马来西亚本地企业主与从业者中,相当大比例的马来西亚线上零售结算走的是 **FPX(Financial Process Exchange)本地在线网银直连或 DuitNow QR 扫码**,而非 Visa / Mastercard。只渲染信用卡表单的结账页不会慢慢变差——它在第一屏就直接失效。
2. **离线桌面软件的盗版风险**:如果是纯离线运行的高性能工具(例如批量视频转码器),二进制包一旦交付,如果缺乏基于物理硬件的授权签名机制,极易在团队内部被无限制复制扩散。
为了解决一款商业级媒体转码桌面软件的商业变现与履约闭环,我主导设计并落地了一套全自动化的计费与授权分发架构。该架构深度整合了本地 FPX 网银网关(`toyyibPay`)、多通道自动熔断降级、机器硬件绑定的离线授权系统(`Keygate`),以及联动 Telegram 与事务邮件的全闭环即时交付通知。
@@ -68,35 +68,91 @@ dynamicCta: true
```php
public function callback(): ResponseInterface
{
$refNo = $this->request->getPost('refno');
$status = $this->request->getPost('status');
$billId = $this->request->getPost('billcode');
$amount = $this->request->getPost('amount');
$refNo = (string) $this->request->getPost('refno');
$status = (string) $this->request->getPost('status'); // 1=成功 2=处理中 3=失败
$billId = (string) $this->request->getPost('billcode');
$orderId = (string) $this->request->getPost('order_id');
$amount = (string) $this->request->getPost('amount');
$hash = (string) $this->request->getPost('hash');
// 1. 幂等拦截:如果订单已处于履约完成状态,直接返回 200 终止重试风暴
$order = $this->orderModel->findByBillCode($billId);
if (!$order || $order['status'] === 'PAID') {
return $this->response->setStatusCode(200)->setBody('OK');
// 1. 网关校验和。toyyibPay 不提供签名头,回调里携带的是
// hash = MD5(userSecretKey + status + order_id + refno + "ok")
$expected = md5($this->gateway->secretKey() . $status . $orderId . $refNo . 'ok');
if (!hash_equals($expected, $hash)) {
$this->logger->warning('toyyibpay.callback.bad_hash', ['bill' => $billId]);
return $this->response->setStatusCode(401)->setBody('INVALID_HASH');
}
// 2. 严格核验状态码与应收金额(防止中间人篡改金额参数)
if ($status === '1' && (float)$amount === (float)$order['expected_amount']) {
$this->fulfillmentService->fulfillOrder($order['id']);
return $this->response->setStatusCode(200)->setBody('OK');
// 非成功状态一律不改动订单:2=处理中,3=失败
if ($status !== '1') {
return $this->response->setStatusCode(200)->setBody('IGNORED');
}
return $this->response->setStatusCode(400)->setBody('INVALID_PAYMENT');
// 2. 一个事务、一把行级排他锁:读取与状态扭转属于同一个临界区,
// 因此不存在 TOCTOU 竞态窗口。
$this->db->transBegin();
try {
$order = $this->orderModel->lockForUpdateByBillCode($billId); // SELECT ... FOR UPDATE
if (!$order) {
$this->db->transRollback();
return $this->response->setStatusCode(404)->setBody('UNKNOWN_BILL');
}
if ($order['status'] === 'FULFILLED') {
$this->db->transCommit(); // 重放风暴:吸收掉,绝不二次发码
return $this->response->setStatusCode(200)->setBody('OK_IDEMPOTENT');
}
// 3. 金额永不使用浮点比对,双方统一为整型分(cents)
if ($this->toCents($amount) !== (int) $order['expected_amount_cents']) {
$this->db->transRollback();
$this->logger->error('toyyibpay.callback.amount_mismatch', [
'bill' => $billId, 'got' => $amount,
'expected_cents' => $order['expected_amount_cents'],
]);
return $this->response->setStatusCode(409)->setBody('AMOUNT_MISMATCH');
}
$this->orderModel->updateStatus($order['id'], 'PROCESSING');
$this->db->transCommit();
} catch (Throwable $e) {
$this->db->transRollback();
throw $e;
}
// 4. 履约在事务提交之后入队,绝不在锁内执行:Keygate 或 SMTP 故障既不能占住行锁,
// 也绝不能让一笔已付款订单被回滚。这才让 [PROCESSING] → [RETRY_QUEUE] 成为安全状态。
$this->fulfillmentQueue->push($order['id']);
return $this->response->setStatusCode(200)->setBody('OK');
}
/** "12.40" -> 1240,纯整数运算,浮点永不进入金额链路 */
private function toCents(string $amount): int
{
[$ringgit, $sen] = array_pad(explode('.', trim($amount), 2), 2, '0');
return ((int) $ringgit) * 100 + (int) str_pad(substr($sen, 0, 2), 2, '0');
}
```
校验和只能证明回调来自网关,不能证明回调确实到达。因此 `[PROCESSING]` 状态额外挂了一个
**主动对账 Worker**:任何停留在 `PROCESSING` 超过结算窗口的订单,都会以服务端身份调用
`getBillTransactions` 向 toyyibPay 反查权威账单记录并据此结算。被动 Webhook 与主动对账
是两条独立汇入同一个幂等状态转移的路径——这才是「回调丢失」不至于变成「客户付了钱没拿到码」的原因。
### 2. 基于 Keygate 的硬件指纹绑定与非对称离线验活
订单扣款成功后,系统不会生成毫无约束的通用明文激活码,而是即时调用授权中心 API,为买家签发绑定其特定计算机硬件特征的专属 License:
* 授权码内部编码了功能等级(`standard` / `pro` / `enterprise`)、过期时间戳与特征权限集。
* 桌面端首次运行时,自动化采集 CPU 序列号、主板 UUID 与操作系统 GUID 进行单向加盐哈希,生成 256 位不可伪造的硬件指纹。
* Keygate 服务端使用 **Ed25519 私钥** 对机器指纹与授权元数据执行数字签名。
* 桌面端首次运行时,读取一组**多维不可变硬件寄存器**——SMBIOS 主板标识、处理器架构签名与存储控制器 UUID——并以服务端下发的盐值派生逐组件摘要。具体取哪些寄存器、盐值如何派生属于私有实现,本文有意不公开:公开它等于直接告诉逆向者该 Hook 哪几个系统调用。
* Keygate 服务端使用 **Ed25519 私钥** 对逐组件摘要与授权元数据执行数字签名。
* 桌面客户端仅内置对应的 **Ed25519 公钥**。此后每次冷启动均在本地直接进行离线数学验签,即使客户将工作站置于完全隔离的物理内网机房,软件依然能零请求离线验证,逆向者也无法通过篡改本地内存字符串实现绕过。
**逐组件摘要的存在,是为了让授权能扛住合法的硬件变更。** 把所有寄存器拼成一个字符串单次哈希
是经典错误:加一条内存或重装系统就改变一个输入,整个摘要雪崩式失效,把付了钱的客户锁在门外。
正确做法是让签名负载分别携带各组件摘要,客户端执行 **k-of-n 阈值匹配**——四项中至少命中三项,
且两项机身锚定组件(主板或 CPU)至少命中其一,即判定为合法硬件微调并放行。换硬盘、重装系统
属于正常升级;把授权移植到另一台机器会同时改变主板与 CPU,直接卡在阈值之外。
---
## 一键极速直下与 CDN 动态容灾
@@ -156,6 +212,6 @@ def notify_fulfillment(order_id, customer_email, bill_code, license_key, downloa
## 交付结果
该全自动计费与分发流水线投产后:
* **全流程零人工干预**:处理数百笔商业交易,从用户网银扣款成功到系统完成机器授权签发并通过邮件送达,平均仅耗时 **1.8 秒**。
* **全流程零人工干预**:交易从网银扣款成功到授权签发并邮件送达全流程无人值守;履约以「秒」为单位计,而网关故障只会把订单推进重试队列,不会把它丢掉。
* **杜绝私下窜码扩散**:依托硬件级 Keygate 指纹绑定,彻底终结了盗版秘钥在多台设备上的随意复制。
* **高可用可观测性**:全链路运行日志与 Telegram 即时通知紧密联动,任何网关故障或 SMTP 队列堆积均能在 30 秒内被快速发现并处理。