## 问题定位
- 现象：POST `/api/pay/wechat/notify` 返回 400，日志提示“certificate [PUB_KEY_ID_0116104396352025041000211519001600] not found in verifier”。
- 原因：微信侧请求头 `Wechatpay-Serial` 为 `PUB_KEY_ID_*` 格式，说明该商户已启用“微信支付平台公钥”模式；当前代码仅使用“平台证书”验签（`verifiers.NewSHA256WithRSAVerifier` + `downloader`），导致找不到匹配的证书序列号而验签失败。
- 代码位置：
  - 路由注册：`internal/router/router.go:252`
  - 回调处理：`internal/api/pay/wechat_notify.go:40-46`（注册证书下载器+证书验签器）
  - 客户端初始化：`internal/pkg/pay/client.go:32-39`（`WithWechatPayAutoAuthCipher` 使用平台证书模式）

## 修复方案
- 增加“平台公钥”模式配置并切换验签/签名实现：
  - 在配置新增 `wechatpay.public_key_id` 与 `wechatpay.public_key_path`（商户后台下载的 `pub_key.pem` 与对应 `PUB_KEY_ID_*`）。
  - 回调验签：当检测到已配置公钥，改用 `verifiers.NewSHA256WithRSAPubkeyVerifier(publicKeyID, publicKey)` 构造 `notify.Handler`；否则保持现有证书模式。
  - 请求侧签名与自动加密：当检测到已配置公钥，改用 `option.WithWechatPayPublicKeyAuthCipher(mchid, serialNo, privateKey, publicKeyID, publicKey)` 初始化 `core.Client`；否则保持 `WithWechatPayAutoAuthCipher`。
- 初始化时机优化：
  - 将证书下载器注册/公钥加载前置至应用启动阶段，避免首次回调时的“尚未拉取证书”竞态问题。
- 兼容策略：
  - 双模式自动选择：优先检测公钥配置；缺省走证书模式，确保对旧商户不破坏。

## 实施步骤
- 配置：
  - 在 `configs/*.toml` 的 `[wechatpay]` 增加 `public_key_id` 与 `public_key_path` 键；同时支持环境变量覆盖（如 `WECHAT_PUBLIC_KEY_ID`、`WECHAT_PUBLIC_KEY_PATH`）。
- 代码改动：
  - `internal/api/pay/wechat_notify.go`：根据配置分支选择 `verifiers.NewSHA256WithRSAPubkeyVerifier` 或现有证书验签器；加载公钥使用 `utils.LoadPublicKeyWithPath`。
  - `internal/pkg/pay/client.go`：根据配置分支选择 `option.WithWechatPayPublicKeyAuthCipher` 或现有证书选项。
  - 启动流程：在应用初始化位置集中完成下载器注册/公钥加载与复用，不在每次回调时重复注册。

## 验证步骤
- 本地联调：
  - 使用真实微信回调数据（包含 `Wechatpay-Serial: PUB_KEY_ID_*`）验证回调成功返回 `{"code":"SUCCESS","message":"OK"}`。
  - 下单→支付→回调链路验证：检查订单状态从 1→2，`paidAt` 按回调 `success_time` 生效（`internal/api/pay/wechat_notify.go:67-71`）。
- 日志与安全：
  - 打印初始化模式（证书/公钥）与关键配置是否完整，避免静默失败。
  - 不输出密钥/私钥内容，符合安全规范。

## 额外检查（关于“req 没有写”）
- 当前回调处理直接使用 `ctx.Request()` 原始请求体（`internal/api/pay/wechat_notify.go:48`），未提前读取/篡改；若上游中间件读取了 `Body`，需保证使用 `io.NopCloser` 复位请求体后再交给 `notify.Handler`。本次改造同时确认路由链路未破坏请求体传递。

请确认是否按照“平台公钥”接入（已具备 `pub_key.pem` 与 `PUB_KEY_ID_*`）。确认后我将按上述方案实现代码与配置改动，并完成联调与验证。