## 实施目标 - 复用现有订单与队列赋权,接入 Apple 自动续期(IAP),保持报表/审计/通知一致。 ## 方案选择 - 采用“平台化复用 + 合成订单”的方式:Apple 由客户端结算 + 服务器通知驱动,服务端生成“已支付订单”进入现有赋权与续费流程。 ## 具体改动(按文件) 1) 平台标识 - 更新 `pkg/payment/platform.go`:新增 `AppleIAP` 枚举与名称(仅标识,不参与 `PurchaseCheckout`)。 2) 路由与 Handler - 新增公共接口:`POST /v1/public/iap/verify` - 位置:`internal/handler/public/iap/verifyHandler.go` - 逻辑:调用 `internal/logic/public/iap/verifyLogic.go`,以 `originalTransactionId` 验证 Apple 购买,生成“已支付订阅订单”,入队激活。 - 新增通知接口:`POST /v1/iap/notifications` - 位置:`internal/handler/notify/appleIAPNotifyHandler.go` - 逻辑:调用 `internal/logic/notify/appleIAPNotifyLogic.go`,JWS 验签后按事件(初购/续期/退款)生成或更新订单,触发续费或撤销权益。 - 路由注册: - `internal/handler/routes.go` 增加 `/v1/public/iap/verify` 路由。 - `internal/handler/notify.go` 增加独立 `/v1/iap/notifications` 路由(Apple 不带 `:token`)。 3) 数据与模型 - 在用户订阅(或新建 `iap_binding` 表)绑定:`originalTransactionId`、`environment`、`latestExpiresDate`。 - 订单字段复用:`Method=AppleIAP`、`TradeNo=originalTransactionId`、`Type=1/2`(订阅/续费),`Status=2`(已支付),金额可取通知中的价格;取不到则置 `Amount=0` 保证流程。 4) 逻辑复用与改造点 - 赋权:复用 `queue/logic/order/activateOrderLogic.go:165 NewPurchase`。 - 续费:复用 `queue/logic/order/activateOrderLogic.go:529 updateSubscriptionForRenewal`。 - 不改动 `internal/logic/public/portal/purchaseCheckoutLogic.go` 的渠道路由(Apple 不走此流程)。 5) 安全与幂等 - Apple JWS 验签:拉取并缓存 JWKS 公钥,校验通知;拒绝无效签名。 - 幂等:以 `notificationId`/`transactionId` 与 `originalTransactionId` 去重处理。 6) 客户端协作 - iOS:完成 StoreKit 购买后携带 `originalTransactionId` 调用 `/v1/public/iap/verify`。 - 续费:依赖 Server Notifications v2 自动驱动,无需客户端调用。 7) 测试与监控 - 沙盒验证初购、续期、重试与宽限期、退款撤销;注意元数据延迟(~1小时)。 - 指标:通知验签失败、API 调用失败、幂等冲突、状态不一致报警。 ## 交付节奏 - 第一步:平台枚举与路由骨架; - 第二步:`verify` 验证与“合成订单”生成; - 第三步:通知验签与事件映射; - 第四步:沙盒联调,确认队列赋权与续费延长。