diff --git a/.planning/phases/04-refund-pay-ops/04-CONTEXT.md b/.planning/phases/04-refund-pay-ops/04-CONTEXT.md
new file mode 100644
index 0000000..306250b
--- /dev/null
+++ b/.planning/phases/04-refund-pay-ops/04-CONTEXT.md
@@ -0,0 +1,164 @@
+# Phase 4: 退款 + 支付 + 运营修复 - Context
+
+**Gathered:** 2026-03-28
+**Status:** Ready for planning
+
+
+## Phase Boundary
+
+实现完整退款流程(REFUND-01~03)、补全富友支付 JSAPI/小程序接口(PAY-01~04)、修复运营逻辑断点(OPS-01~02)。共 9 个需求:
+- **REFUND**:新功能模块(退款申请→审批→佣金回扣)
+- **PAY**:留桩替换(富友支付 JSAPI/小程序,平台代购场景修复)
+- **OPS**:业务逻辑修复(卡/设备 status 3/4 触发、payment_status 枚举统一)
+
+
+
+
+## Implementation Decisions
+
+### Plan 分组策略
+
+- **D-01:** 拆分为 **2 个 Plan**:
+ - **Plan 1(REFUND)**:REFUND-01 先行(DB 迁移 + Model + Store),然后串行完成 REFUND-02(7 个接口)+ REFUND-03(佣金扣减逻辑嵌入 Approve)
+ - **Plan 2(PAY + OPS 合并)**:PAY-01~04 + OPS-01~02 共 6 个需求,两者互相独立可并行编排
+- **D-02:** REFUND-01 必须先于 REFUND-02/03 执行(DB 迁移和模型是所有上层代码的基础)
+- **D-03:** 每个子任务独立一个 commit(延续 Phase 1/2/3 粒度规范)
+
+### 退款状态机(REFUND)
+
+- **D-04:** 退款单号生成规则:`{order_no}-RF{seq}`(同一订单第 1 次退款为 RF1,第 2 次为 RF2,以此类推)。Create 时查询该订单现有退款数量 +1 作为序号
+- **D-05:** 同一订单同时只允许一个"待处理"状态的退款申请(status=pending/returned),防止重复退款
+- **D-06:** 退款状态流转:
+ - `pending` → `approved`(审批通过,触发佣金扣减 + 更新订单 payment_status=4)
+ - `pending` → `rejected`(审批拒绝,必填拒绝原因)
+ - `pending` → `returned`(审批人退回,申请人可重提)
+ - `returned` → `pending`(申请人 Resubmit 重提)
+- **D-07:** **Return(退回)由审批人操作**,退回后状态变为 `returned`,申请人可调用 Resubmit 重新提交变回 `pending`
+- **D-08:** **审批人可修改退款金额**(approved_refund_amount 可与 requested_refund_amount 不同)。佣金扣减以 approved_refund_amount 为准
+- **D-09:** 审批通过后**同步更新订单 payment_status = 4**(已退款),与 OPS-02 的 payment_status 枚举统一对齐
+
+### 退款佣金扣减(REFUND-03)
+
+- **D-10:** 佣金扣减**内嵌在 Approve() 事务内同步执行**(不走 Asynq 异步任务)。原子性:退款审批通过、佣金扣减、订单状态更新在同一事务中完成,失败可回滚
+- **D-11:** 佣金扣减算法(**禁用 float64,使用整数算术**):
+ ```go
+ deductAmount := commission.Amount * refund.ApprovedRefundAmount / refund.ActualReceivedAmount
+ ```
+ 先乘后除,全程 int64,防止整数除法精度丢失。对该订单所有佣金记录逐一计算扣减额,写负向交易流水
+- **D-12:** 佣金扣减允许余额变为负数(规格书明确:允许为负数)
+
+### 富友支付(PAY)
+
+- **D-13:** `FuiouPayJSAPI` 和 `FuiouPayMiniApp` 函数签名需从 `error` 改为 `(*dto.FuiouPayJSAPIResponse, error)`,参考 `WechatPayJSAPI` 的返回结构
+- **D-14:** 新建 `FuiouPayJSAPIResponse` DTO,字段从 `pkg/fuiou/types.go` 的 `WxPreCreateResponse` SDK 字段映射(SdkAppid, SdkTimestamp, SdkNoncestr, SdkPrepayid, SdkPackage, SdkSigntype, SdkPaysign),与微信官方 `wx.requestPayment()` 参数对齐
+- **D-15:** JSAPI(公众号)tradeType = `JSAPI`;小程序 tradeType = `LETPAY`(两者逻辑相同,仅此字段不同)
+- **D-16:** 已有富友 SDK 实现(`pkg/fuiou/client.go` + `wxprecreate.go`),直接调用 `client.WxPreCreate()` 方法
+
+### 平台代理钱包代购(PAY-04)
+
+- **D-17:** 修改 **`CreateAdminOrder`**(**不是 CreateLegacy**,CreateLegacy 已废弃,Handler 实际调用的是 CreateAdminOrder)
+- **D-18:** 触发条件:`buyerType == ""` && `resourceShopID != nil`(平台用户在 Handler 层传入 buyerType="" buyerID=0)
+- **D-19:** 钱包和成本价均来自**资产所属代理(*resourceShopID)**的钱包和成本价(等同于代理自购场景)
+- **D-20:** 订单标记:`purchaseRole = purchased_by_platform`,`operatorType = "platform"`
+- **D-21:** `sellerCostPrice = resourceShop 代理的成本价`(与代理自购相同,上下级佣金链照常计算)
+
+### 卡/设备 status 3/4 触发(OPS-01)
+
+- **D-22:** **status=3(已激活)**:在 `activation_service.go` 套餐激活事务内同步更新卡/设备表的 status=3(不走 goroutine,保证原子性)
+- **D-23:** **status=4(已停用)**:在 `activation_service.go` 的套餐到期检测逻辑中,调用 `activateNextMainPackage` 后,若无法找到下一个待激活套餐(即无剩余 active/pending 套餐),则同步更新卡/设备 status=4
+- **D-24:** 卡和设备**分开更新两张表**(tb_iot_card 和 tb_device),根据 carrierType 分支处理,无需统一封装
+- **D-25:** status 更新在已有套餐激活/到期事务内完成,失败可回滚
+
+### payment_status 枚举统一(OPS-02)
+
+- **D-26:** **删除所有 C 端映射函数**:
+ - `internal/service/client_order/service.go` 中的 `orderStatusToClientStatus()`
+ - `internal/handler/app/client_order.go` 中的 `orderStatusToClientPaymentStatus()` 和 `clientPaymentStatusToOrderStatus()`
+- **D-27:** C 端直接输出 DB 原始 `payment_status` 字段(1=待支付, 2=已支付, 3=已取消, 4=已退款),与管理端完全一致
+
+### the Agent's Discretion
+
+- 富友支付 `WxPreCreate` 调用时的 `goodsDesc` 字段内容(可从 order.OrderNo 或套餐名称组合)
+- 退款 Store 层具体查询方法(参考现有 commission_withdrawal_request_store.go 风格)
+- status=3/4 更新时的日志内容(按项目中文日志规范)
+- `getCostPrice` 函数参数(已有现成封装,直接复用)
+
+
+
+
+## Canonical References
+
+**Downstream agents MUST read these before planning or implementing.**
+
+### 修复规格(核心参考)
+- `.sisyphus/plans/修正业务-完整方案.md` — 完整修复规格书:
+ - 方案 I(REFUND-01~03):第 1716 行起(退款表结构、7 个接口清单、佣金扣减逻辑)
+ - 方案 J(PAY + OPS):第 1862 行起(J-1/J-2/J-3/J-4 各子方案代码片段、人工验收清单)
+ - J-1:富友支付 JSAPI/小程序(PAY-01/02/03)
+ - J-2:平台钱包代购(PAY-04)—— **注意:规格书错误引用了 CreateLegacy(已废弃),实际修改目标是 CreateAdminOrder**
+ - J-3:status 3/4 触发逻辑(OPS-01)
+ - J-4:payment_status 枚举统一(OPS-02)
+
+### 核心修改文件
+- `internal/service/order/service.go` — FuiouPayJSAPI/FuiouPayMiniApp 留桩替换;CreateAdminOrder 钱包支付 platform 分支(PAY)
+- `pkg/fuiou/client.go` + `pkg/fuiou/wxprecreate.go` — 富友 SDK(直接调用 WxPreCreate)
+- `pkg/fuiou/types.go` — WxPreCreateResponse 字段(FuiouPayJSAPIResponse DTO 来源)
+- `internal/service/package/activation_service.go` — 套餐激活/到期逻辑(OPS-01 插入点)
+- `internal/service/client_order/service.go` — orderStatusToClientStatus() 删除(OPS-02)
+- `internal/handler/app/client_order.go` — orderStatusToClientPaymentStatus() / clientPaymentStatusToOrderStatus() 删除(OPS-02)
+
+### 参考结构(REFUND 设计参照)
+- `internal/service/commission_withdrawal/service.go` — Approve/Reject 风格参考(REFUND-02 接口设计)
+- `internal/model/dto/commission_withdrawal_dto.go` — DTO 字段风格参考(REFUND DTO 设计)
+- `internal/store/postgres/commission_withdrawal_request_store.go` — Store 层风格参考(REFUND Store)
+
+### 依赖项与约束
+- `.planning/REQUIREMENTS.md` — REFUND-01~03, PAY-01~04, OPS-01~02 完整需求定义
+- `internal/handler/admin/order.go` — PAY-04:Handler 层传入 buyerType="" buyerID=0 的逻辑(了解上下游)
+
+
+
+
+## Existing Code Insights
+
+### Reusable Assets
+- `pkg/fuiou/client.go:WxPreCreate()` — 富友预下单接口,PAY-01/02 直接调用,无需重写
+- `internal/service/order/service.go:WechatPayJSAPI()` — 参考模板:验证 wechatPayment != nil → 查订单 → 调用 SDK → 返回 DTO
+- `internal/service/commission_withdrawal/service.go:Approve()` — REFUND Approve 逻辑的最佳参考
+- `internal/service/package/activation_service.go` — status=3/4 的插入位置:activateMainPackage(激活)+ 到期检测循环(到期)
+- `internal/model/order.go:PurchaseRolePurchasedByPlatform` — PAY-04 购买角色常量已存在
+
+### Established Patterns
+- 佣金扣减:参考 `internal/service/commission_withdrawal/service.go` 的钱包扣款方式(使用 version 乐观锁)
+- DB 迁移:双文件形式(`.up.sql` / `.down.sql`),编号接续现有最大值(当前 Phase 3 使用了 000090/91)
+- 退款单号:参考提现单号的生成逻辑(WD+时间戳+随机数 → 改为 {order_no}-RF{seq})
+- 路由注册:所有新接口通过 `internal/routes/registry.go` 的 `Register()` 注册,并同步更新 `cmd/api/docs.go` 和 `cmd/gendocs/main.go`
+
+### Integration Points
+- REFUND Handler 注册到 `/api/admin/refunds` 路由组(参考 commission_withdrawal 的路由注册方式)
+- PAY-04 修改 `CreateAdminOrder` 的 wallet 分支,Handler 层无需改动
+- OPS-01/02 在 activation_service.go 和 client_order 两个文件内修改,无新增路由
+- 富友支付 JSAPI/小程序的 Handler 已存在留桩(`internal/handler/app/`),替换 Service 层即可
+
+
+
+
+## Specific Ideas
+
+- **退款佣金允许负数**:规格书明确允许,代理佣金钱包余额可降至负值(为了确保退款公平性)
+- **CreateLegacy 废弃问题**:规格书 J-2 错误引用了已废弃的 CreateLegacy,实际修改目标是 CreateAdminOrder(这一决策在讨论中由用户确认)
+- **富友 SDK 已完整**:`pkg/fuiou/` 包含完整 client + types + notify + wxprecreate,PAY 工作量主要是替换留桩和编写 DTO
+
+
+
+
+## Deferred Ideas
+
+None — discussion stayed within phase scope.
+
+
+
+---
+
+*Phase: 04-refund-pay-ops*
+*Context gathered: 2026-03-28*
diff --git a/.planning/phases/04-refund-pay-ops/04-DISCUSSION-LOG.md b/.planning/phases/04-refund-pay-ops/04-DISCUSSION-LOG.md
new file mode 100644
index 0000000..37fd170
--- /dev/null
+++ b/.planning/phases/04-refund-pay-ops/04-DISCUSSION-LOG.md
@@ -0,0 +1,200 @@
+# Phase 4: 退款 + 支付 + 运营修复 - Discussion Log
+
+> **Audit trail only.** Do not use as input to planning, research, or execution agents.
+> Decisions are captured in CONTEXT.md — this log preserves the alternatives considered.
+
+**Date:** 2026-03-28
+**Phase:** 04-退款-支付-运营修复
+**Areas discussed:** Plan 分组策略, 退款状态机细节, OPS-01 卡/设备 status=4 触发路径, PAY-04 平台代购的具体场景
+
+---
+
+## Plan 分组策略
+
+| Option | Description | Selected |
+|--------|-------------|----------|
+| REFUND 一个 Plan | DB迁移+Model+Store+Service+Handler+路由全部一次完成 | ✓ |
+| REFUND 拆两个 Plan | Plan A: DB迁移+基础层;Plan B: 功能层 | |
+
+**User's choice:** 一个 Plan(推荐)
+
+---
+
+| Option | Description | Selected |
+|--------|-------------|----------|
+| PAY + OPS 合并一个 Plan | PAY 和 OPS 彼此独立,合并一个 Plan 减少上下文切换 | ✓ |
+| PAY 和 OPS 各自独立 | 两个 Plan,粒度更细 | |
+
+**User's choice:** PAY + OPS 合并一个 Plan(推荐)
+
+---
+
+| Option | Description | Selected |
+|--------|-------------|----------|
+| 内嵌同步(Approve 事务内) | 退款审批和佣金扣减原子,失败可回滚 | ✓ |
+| 异步 Asynq 任务 | 入队 TaskTypeRefundCommissionDeduct,审批响应快 | |
+
+**User's choice:** 内嵌同步(推荐)
+
+---
+
+| Option | Description | Selected |
+|--------|-------------|----------|
+| REFUND-01 先行,再做 REFUND-02+03 | 与 Phase 3 DEVICE 基础层先行规范一致 | ✓ |
+| 一次性全部完成 | DB迁移先执行,所有上层代码同时完成 | |
+
+**User's choice:** REFUND-01 先行,再做 REFUND-02+03(推荐)
+
+---
+
+| Option | Description | Selected |
+|--------|-------------|----------|
+| 不需要,OPS-01 独立实现 | OPS-01 是套餐激活/到期直接更新 status,不经过 StopResumeCallback | ✓ |
+| 需要,提前将 CLEAN-06 并入本阶段 | 一并修复 bootstrap 注入 | |
+
+**Notes:** 用户对 CLEAN-06 和 OPS-01 的关系有疑问,确认两者独立后选择不提前。CLEAN-06 保留在 Phase 5。
+
+---
+
+## 退款状态机细节
+
+| Option | Description | Selected |
+|--------|-------------|----------|
+| 审批人退回 | 审批人退回申请人(信息不全/待补充等),返回 returned 状态,申请人可重提 | ✓ |
+| 申请人自撤回 | 申请人主动撤销,运营后可重提 | |
+
+**User's choice:** 审批人退回(推荐)
+
+---
+
+| Option | Description | Selected |
+|--------|-------------|----------|
+| RF + 时间戳 + 随机数 | 独立生成,不关联订单号 | |
+| 基于订单号迭代 | {order_no}-RF{seq},关联清晰,seq 解决冲突 | ✓ |
+
+**User's choice:** 基于订单号迭代,冲突解法用 {order_no}-RF{seq}
+
+---
+
+| Option | Description | Selected |
+|--------|-------------|----------|
+| 允许多次退款 | 同一订单可有多条退款记录,审批退款总额不超过实收金额 | |
+| 同时只有一个待处理申请 | 上一次退款完成前不允许新申请 | ✓ |
+
+**User's choice:** 同一订单同时只能有一个待处理的退款申请(推荐)
+
+---
+
+| Option | Description | Selected |
+|--------|-------------|----------|
+| 可修改金额 | 审批人可调整 approved_refund_amount,以此为佣金扣减基准 | ✓ |
+| 只能审批全额 | 简化 Approve 逻辑 | |
+
+**User's choice:** 可修改金额(推荐)
+
+---
+
+| Option | Description | Selected |
+|--------|-------------|----------|
+| amount * approvedRefund / actualReceived(int64) | 先乘后除,禁用 float64 | ✓ |
+| 先确认字段含义再决定 | — | |
+
+**Notes:** 用户初始想先确认字段含义。解释了 actual_received_amount(实收)/ approved_refund_amount(审批退款额)以及"先乘后除"的整数精度含义后确认使用 int64 算法。
+
+---
+
+| Option | Description | Selected |
+|--------|-------------|----------|
+| 是,更新 payment_status=4 | 审批通过同时更新订单状态 | ✓ |
+| 不更新订单状态 | 退款表独立记录 | |
+
+**User's choice:** 是,更新 payment_status=4
+
+---
+
+## OPS-01 卡/设备 status=4 触发路径
+
+| Option | Description | Selected |
+|--------|-------------|----------|
+| 事务内同步更新 | 套餐激活和卡状态更新原子,失败可回滚 | ✓ |
+| 异步 goroutine | 套餐激活后异步更新卡/设备状态 | |
+
+**User's choice:** 事务内同步更新(推荐)
+
+---
+
+| Option | Description | Selected |
+|--------|-------------|----------|
+| activateNextMainPackage 后检查 active/pending count | 在现有到期处理循环内,激活下一个失败时检查剩余套餐数量 | ✓ |
+| 独立轮询任务定期检查 | 新建 Asynq 定时任务扫描无 active 套餐的卡/设备 | |
+
+**User's choice:** 调用 activateNextMainPackage 后检查无剩余 active/pending 套餐(推荐)
+
+---
+
+| Option | Description | Selected |
+|--------|-------------|----------|
+| 分开更新两张表 | 根据 carrierType 分支到 iot_card/device 各自的 Store | ✓ |
+| 统一封装 UpdateCarrierStatus() | 新建封装方法处理两种类型 | |
+
+**User's choice:** 分开更新两张表(推荐)
+
+---
+
+| Option | Description | Selected |
+|--------|-------------|----------|
+| 直接输出 DB 字段,删除所有映射函数 | DB 存的 payment_status 与管理端完全一致(1/2/3/4) | ✓ |
+| 先确认 DB 存在的实际值 | 不确定 DB 值是否真的 1/2/3/4 | |
+
+**User's choice:** 是,直接输出 DB 字段,删除所有映射函数
+
+---
+
+## PAY-04 平台代购的具体场景
+
+| Option | Description | Selected |
+|--------|-------------|----------|
+| 仅 CreateLegacy | 规格书指定 | |
+| 仅 CreateAdminOrder | Handler 实际调用的是 CreateAdminOrder,CreateLegacy 已废弃 | ✓ |
+
+**Notes:** 用户指出 CreateLegacy 已废弃,讨论后确认修改目标为 CreateAdminOrder。规格书中的引用有误,这是本次讨论中最重要的一个勘误。
+
+---
+
+| Option | Description | Selected |
+|--------|-------------|----------|
+| 资产所属代理的钱包(*resourceShopID) | 平台帮代理买,用代理自己的钱包 | ✓ |
+| 平台自己的测试钱包 | 平台先垫付 | |
+
+**User's choice:** 资产所属代理的钱包(*resourceShopID)(推荐)
+
+---
+
+| Option | Description | Selected |
+|--------|-------------|----------|
+| purchaseRole=purchased_by_platform, operatorType=platform | 使用已有枚举 | ✓ |
+| purchaseRole=self_purchase | 按代理自购处理 | |
+
+**User's choice:** purchaseRole=purchased_by_platform, operatorType=platform(推荐)
+
+---
+
+| Option | Description | Selected |
+|--------|-------------|----------|
+| 与代理自购相同(sellerCostPrice=资产所属代理成本价) | 上下级佣金链照常计算 | ✓ |
+| sellerCostPrice=0(不计佣金差) | 平台代购无差价 | |
+
+**Notes:** 用户初始对 sellerCostPrice 含义不清楚,解释了佣金差价逻辑后确认:平台代购等同于代理自购,佣金链正常计算。
+
+---
+
+## the Agent's Discretion
+
+- 富友支付 WxPreCreate 调用时的 goodsDesc 字段内容
+- 退款 Store 层具体查询方法实现
+- status=3/4 更新时的日志内容
+- 富友 DTO 字段命名(参考 WechatPayJSAPIResponse 风格)
+
+## Deferred Ideas
+
+None — discussion stayed within phase scope.