🚨 2026-06-12 转化率暴跌根因调查

注册→首充率 6/10 44.5% → 6/12 36.5%(-8pp 连降两天)· 充值发起→支付成功率 6/11 60.5% → 6/12 50.6%(-10pp)
🎯 高置信度根因:v3.3.3 (6/10) 部署的 API contract 改名 + 浏览器旧 JS 缓存

核心 KPI 对比

6/12 attempt→paid
62.2%
-10pp vs 6/11 (72.2%)
6/12 nihaopay paid_pct
50.6%
-10pp vs 6/11 (60.5%)
6/12 平均存活时间
15.2 min
+3 min vs 历史 12 min
6/12 注册量
326
-22% vs 6/11 (419)

📅 时间线(确认根因部署窗口)

2026-06-09 09:47 SH
v3.3.0 release — fix(referral/rental) 钱包改绑邮件
无相关性 ✓
2026-06-10 02:04 UTC (10:04 SH)
PR #468 合并 — refactor(openapi): 路由改挂根 /v1/* 免 CF Origin Rule + 启用子域硬绑
真正的炸弹:实际改动远超 PR 标题,同时把 topup 后端 API contract 整个改名:
gatewaySlugchannelId(请求字段,binding:"required"
gatewayPaymentUrlpaymentUrl(响应字段)
gatewayCheckoutFormcheckoutForm(响应字段)
• 删除 gatewayName / gatewayOrderId / paymentMethod / userId / derivationIndex 等字段
2026-06-10 08:56 SH
v3.3.3 release — 部署 PR #468 + PR #481 到 production
含 backwards-incompatible API rename,但 changes/ 文档自己写"旧客户端需要切换为 channelId"——没做 dual-read 兼容
2026-06-10 — 全天数据
paid_pct 58.1% — 表面看不出问题
部署当天大多用户首次访问 dashboard 拿到的是新 JS,问题不显著
2026-06-11 全天
paid_pct 60.5% — 暂时回升,但 attempt_pct 开始跌(55.5%)
用户看到 dashboard 不点充值的比例增加,疑似前端组件 partial broken
2026-06-12 全天
paid_pct 50.6% / attempt→paid 62.2% — 全面暴跌
第三天浏览器缓存广泛失效,更多用户碰到 broken UI;CF/Vercel CDN 边缘缓存渐进失效

1. 数据证据链(按因果链排序)

1.1 转化率连续 3 天下降,6/12 为低点

日期注册attempt_pctfirst_paid_pctattempt→paid
6/0851860-62%40.7%73%
6/0951260-62%46.1%75%
6/10 部署47261.2%43.4%71.0%
6/1141955.5%40.0%72.2%
6/1232660.3%37.5%62.2%

1.2 主力 gateway nihaopay 同步下滑 -10pp

日期nihaopay 单量paidpaid_pct
6/1039122758.1%
6/1130618560.5%
6/1225512950.6%

1.3 stripe 同步下跌排除"nihaopay 渠道单点故障"

stripe 6/12 paid_pct 37.5% vs 6/11 46.2%(-9pp)。两条独立 gateway 同步下滑,不是单 gateway 故障,根因在前端。

1.4 用户停留时间 +3 min — 找不到支付入口的特征

日期nihaopay 平均 lifetime (min)已付款平均付款时间 (min)
6/1012.40.6
6/1112.10.6
6/1215.2 (+3 min)0.7

付款的人付款时间没变(0.6-0.7 min),但没付款的人停留更久(+3 min)。完全符合"用户看到了页面但找不到支付入口"模式。

1.5 后端没故障 — 排除 API/支付通道问题

2. 🎯 根因:PR #468 backwards-incompatible API rename

PR #468 在 v3.3.3 (6/10 SH 08:56) 部署,做了系统级 API contract 改名,且没做 dual-read 兼容

2.1 后端 createTopupRequest 强制要求新字段

- GatewaySlug string `json:"gatewaySlug" binding:"required"`
+ ChannelID string `json:"channelId" binding:"required"`

2.2 后端 response 字段全部改名

- "gatewayName": topup.GatewayName,
- "gatewayOrderId": topup.GatewayOrderID,
- "gatewayPaymentUrl": topup.GatewayPaymentURL,
- "gatewayCheckoutForm": topup.GatewayCheckoutForm,
- "paymentMethod": topup.PaymentMethod,
- "userId": topup.UserID,
+ "channelId": ChannelIDForGatewaySlug(topup.GatewayName),
+ "paymentUrl": topup.GatewayPaymentURL,
+ "checkoutForm": topup.GatewayCheckoutForm,

2.3 前端 openTopupHostedPayment 改读新字段

- if (topup.gatewayCheckoutForm) submitHostedPaymentForm(topup.gatewayCheckoutForm)
- if (topup.gatewayPaymentUrl) window.location.assign(topup.gatewayPaymentUrl)
+ if (topup.checkoutForm) submitHostedPaymentForm(topup.checkoutForm)
+ if (topup.paymentUrl) window.location.assign(topup.paymentUrl)
  throw new ApiError('Missing hosted payment target')

2.4 用户侧失败模式(高置信度推断)

用户场景后果
浏览器缓存了 6/10 之前的旧 JS 的 active tab 用户旧 JS 发 gatewaySlug 请求被新后端 400 拒;或拿到 response 后读 gatewayPaymentUrl = undefined,跳转失败 → 看不到支付页 → expired
CF/Vercel CDN 边缘节点未刷新到新版 chunk新用户访问拿到旧 hash 的 JS,同上结局
Service Worker / Next.js precache 持有旧版PWA-style 缓存 → 用户离线时拿到旧版,进入同样陷阱

PR #468 的 changes/2026-06-05-topup-payment-channel-redaction.md 文档自己写明"旧客户端需要切换为 channelId"——已知风险但没做兼容,没有 dual-read pattern 双周窗口。

3. 不能 100% 确定的 caveats

4. 🚨 紧急处置建议

P0-A · 立即 hotfix:后端做 dual-read 兼容(30 分钟修复)

backend/internal/api/topup/handler.gocreateTopupRequest 同时接 channelIdgatewaySlug

type createTopupRequest struct {
  ...
  ChannelID string `json:"channelId"`
  GatewaySlug string `json:"gatewaySlug"` // 兼容旧客户端,至少保留 14 天
}

// 在 handler 解析:
channelID := strings.TrimSpace(req.ChannelID)
if channelID == "" { channelID = topupsvc.ChannelIDForGatewaySlug(req.GatewaySlug) }
if channelID == "" { return 400 }

response 端同步 双写新旧字段名gatewayPaymentUrl + paymentUrl 同时存在),至少保留 14 天兼容窗口。

预期效果:4-6 小时内 nihaopay paid_pct 应回弹到 58%+ 历史水位。

P0-B · 联系运维:检查 CF/Vercel 边缘缓存 + 强制 purge
P1 · 复盘 + 流程改进
P1 · 监控加固

5. 验证 hotfix 效果的 KPI

指标当前(6/12 已沦陷)部署 P0-A 后 4h 预期
nihaopay paid_pct50.6%≥ 56%
整体 attempt→paid62.2%≥ 70%
注册→首充率37.5%≥ 43%
平均 topup lifetime15.2 min≤ 13 min