diff --git a/.cursor/README.md b/.cursor/README.md index 9fdb20da..4bc0db12 100644 --- a/.cursor/README.md +++ b/.cursor/README.md @@ -2,6 +2,8 @@ 本目录的 rules 与 skills 均为**当前项目(Soul 创业派对)**服务,用于约束开发、防止互窜、减少漏改。 +**开发团队**:2 前端(小程序开发工程师、管理端开发工程师)+ 1 后端 + 1 产品经理 + 1 助理橙子。开发团队有**经验库**,根据经验自动升级 Skills。完整职责与 Skills 分配见 [开发团队职责定义.md](./docs/开发团队职责定义.md),经验库见 [经验库 README](./经验库/README.md)。 + **会话启动自检**:新 Cursor 打开本项目时,应优先执行 soul-project-boundary 中的「会话启动自检」,仅沿用本项目的 rules、skills、开发风格与配置参数,排除无关的全局或其它项目规则。 --- @@ -18,33 +20,39 @@ | **soul-api-boundary.mdc** | soul-api/**/*.go | ❌ | soul-api:路由按使用方归类 | | **soul-api-coding.mdc** | soul-api/**/*.go | ❌ | soul-api:GORM、Model、响应等编码规范 | | **api-reliability.mdc** | next-project/**/* | ❌ | 仅 next-project 参考(TypeScript/Next API) | +| **product-manager.mdc** | 开发文档/1、需求/、临时需求池/、开发文档/10、项目管理/ | ❌ | 产品经理:需求、验收,加载 SKILL-产品经理 | **执行逻辑**:alwaysApply 的规则始终生效;其余按当前编辑文件路径匹配 glob,匹配到的规则同时生效,无先后依赖。 --- -## 二、Skills 索引(按角色驱动) +## 二、Skills 索引(按团队角色驱动) -各角色在各自端内开发时,**必须**遵循对应主 Skill 的开发风格;辅助 Skill 按「何时选用」选用,顺序表示推荐查阅先后。 +团队:**小程序开发工程师**、**管理端开发工程师**、**后端开发**、**产品经理**、**助理橙子**。各开发角色在各自端内**必须**遵循对应主 Skill;辅助 Skill 按「何时选用」选用。 -### 速查:目录 → 角色 → 应加载 Skills +### 速查:目录/场景 → 角色 → 应加载 Skills -| 当前编辑目录 | 当前角色 | 主 Skill(必加载) | 辅助 Skill(按需) | -|--------------|----------|-------------------|--------------------| -| miniprogram/ | 小程序开发者 | SKILL-小程序开发.md | 三端架构 → API开发 → 变更关联检查 | -| soul-admin/ | 管理端开发者 | SKILL-管理端开发.md | 三端架构 → API开发 → 变更关联检查 | -| soul-api/ | 后端 API 开发者 | SKILL-API开发.md | soul-api-coding → 三端架构 → 变更关联检查 → MySQL直接操作 | +| 当前编辑目录/场景 | 角色 | 主 Skill | 辅助 Skill(按需) | +|------------------|------|----------|--------------------| +| miniprogram/ | 小程序开发工程师 | SKILL-小程序开发.md | 三端架构 → API开发 → 变更关联检查 | +| soul-admin/ | 管理端开发工程师 | SKILL-管理端开发.md | 三端架构 → API开发 → 变更关联检查 | +| soul-api/ | 后端开发 | SKILL-API开发.md | soul-api-coding → 三端架构 → 变更关联检查 → MySQL直接操作 | +| 开发文档/1、需求/、临时需求池/ | 产品经理 | SKILL-产品经理.md | 需求汇总、运营与变更 | +| 说 小橙、橙子、讨论完毕、记录、同步文档 | 助理橙子 | SKILL-助理橙子-文档同步.md | - | -**跨端功能开发时**:无论当前角色,加载 **SKILL-角色流程控制.md**。 -**变更完成后**:无论当前角色,**必过** **SKILL-变更关联检查.md** + **soul-change-checklist.mdc**。 +**跨端功能开发**:加载 **SKILL-角色流程控制.md**。 +**变更完成**:**必过** **SKILL-变更关联检查.md** + **soul-change-checklist.mdc**。 ### 快速决策(Agent 执行时) ``` 当前编辑目录? - → miniprogram/ → 主:SKILL-小程序开发 - → soul-admin/ → 主:SKILL-管理端开发 - → soul-api/ → 主:SKILL-API开发 + → miniprogram/ → 主:SKILL-小程序开发 + → soul-admin/ → 主:SKILL-管理端开发 + → soul-api/ → 主:SKILL-API开发 + → 开发文档/1、需求/、临时需求池/ → 主:SKILL-产品经理 + +说 小橙橙子讨论完毕记录同步? → 主:SKILL-助理橙子-文档同步 涉及多端? → 加载 SKILL-角色流程控制 改完准备提交? → 必过 SKILL-变更关联检查 + soul-change-checklist @@ -53,7 +61,7 @@ API 需操作数据库且 MCP 不可用? → 加载 SKILL-MySQL直接操作 --- -### 角色一:小程序开发者 +### 角色一:小程序开发工程师 | 类型 | Skill | 何时选用 | |------|-------|----------| @@ -63,11 +71,11 @@ API 需操作数据库且 MCP 不可用? → 加载 SKILL-MySQL直接操作 | 辅助 3 | SKILL-变更关联检查.md | 变更完成后,过三端关联 | | 协同 | SKILL-角色流程控制.md | 跨端功能开发(新增/优化)时 | -**负责目录**:miniprogram/ +**负责**:miniprogram/ --- -### 角色二:管理端开发者 +### 角色二:管理端开发工程师 | 类型 | Skill | 何时选用 | |------|-------|----------| @@ -77,11 +85,11 @@ API 需操作数据库且 MCP 不可用? → 加载 SKILL-MySQL直接操作 | 辅助 3 | SKILL-变更关联检查.md | 变更完成后,过三端关联 | | 协同 | SKILL-角色流程控制.md | 跨端功能开发时 | -**负责目录**:soul-admin/ +**负责**:soul-admin/ --- -### 角色三:后端 API 开发者 +### 角色三:后端开发 | 类型 | Skill | 何时选用 | |------|-------|----------| @@ -92,7 +100,29 @@ API 需操作数据库且 MCP 不可用? → 加载 SKILL-MySQL直接操作 | 辅助 4 | SKILL-MySQL直接操作.md | MCP 无法连接、需增减字段/执行迁移时 | | 协同 | SKILL-角色流程控制.md | 跨端功能开发时 | -**负责目录**:soul-api/ +**负责**:soul-api/ + +--- + +### 角色四:产品经理 + +| 类型 | Skill | 何时选用 | +|------|-------|----------| +| **主** | SKILL-产品经理.md | 需求分析、需求文档、验收、编辑 开发文档/1、需求/、临时需求池/ 时 | +| 辅助 | 需求汇总、运营与变更 | 查阅需求清单、项目推进表时 | + +**负责**:需求、验收、与开发协调 + +--- + +### 角色五:助理橙子 + +| 类型 | Skill | 何时选用 | +|------|-------|----------| +| **主** | SKILL-助理橙子-文档同步.md | 小橙、橙子、橙橙、🍊、「讨论完毕」「记录一下」「同步到开发文档」 | +| 规则 | assistant-xiaofeng.mdc | 同上 | + +**负责**:讨论后记录、文档同步 --- @@ -100,17 +130,15 @@ API 需操作数据库且 MCP 不可用? → 加载 SKILL-MySQL直接操作 | 场景 | Skill | 何时选用 | |------|-------|----------| -| 跨端协同 | SKILL-角色流程控制.md | 小程序/管理端/API 任一有功能开发且涉及多端时;流程图见 `.cursor/docs/角色协同流程图.html` | -| 变更检查 | SKILL-变更关联检查.md、soul-change-checklist.mdc | **无论改哪端,改完必过** | -| **文档同步** | **SKILL-助理橙子-文档同步.md** | **讨论完毕、记录内容、同步到开发文档时**;对应规则 `assistant-xiaofeng.mdc` | +| 跨端协同 | SKILL-角色流程控制.md | 开发涉及多端时;流程图见 `.cursor/docs/角色协同流程图.html` | +| 变更检查 | SKILL-变更关联检查.md、soul-change-checklist.mdc | **开发改完必过** | +| 文档同步 | SKILL-助理橙子-文档同步.md | 讨论完毕、记录、同步文档 | | next-project | SKILL-next-project仅预览.md | 编辑 next-project/ 或需区分线上后端时 | | 项目拆解 | SKILL-Next全栈拆解为前后端分离与小程序.md | 拆解 Next.js 全栈时;拆解前必读 SKILL-三端架构与框架分析.md | ---- +**助理橙子**:当用户说小橙、橙子、橙橙、🍊、「讨论完毕」「记录一下」「同步到开发文档」等时,加载 **SKILL-助理橙子-文档同步.md**,以小橙身份记录讨论要点并更新 `开发文档/`、`临时需求池/`。 -**小橙(橙子/橙橙/🍊)**:当用户说小橙、橙子、橙橙、🍊、「讨论完毕」「记录一下」「同步到开发文档」等时,加载 **SKILL-助理橙子-文档同步.md**,以小橙身份记录讨论要点并更新 `开发文档/`、`临时需求池/`,保持项目文档与讨论结论一致。 - -**Skills 迭代**:Skills 会随 bug 修复与项目演进持续升级。修 bug 时若发现规则、流程或约定有遗漏或错误,应同步更新对应 Skill,避免同类问题复现。详见 `.cursor/docs/角色驱动Skills分析.md`。 +**Skills 迭代**:开发团队经验库(`.cursor/经验库/`)沉淀经验,根据经验自动升级 Skills。用户说「吸收经验」「升级 skills」时,助理橙子执行:提炼 → 入库 → 更新对应 Skill。修 bug 时若发现规则/流程遗漏,建议写入经验库并升级 Skill。详见 [经验库 README](./经验库/README.md)。 --- diff --git a/.cursor/docs/三角色边界定义.md b/.cursor/docs/三角色边界定义.md new file mode 100644 index 00000000..39bd6612 --- /dev/null +++ b/.cursor/docs/三角色边界定义.md @@ -0,0 +1,174 @@ +# Soul 创业派对 - 三角色边界定义(开发) + +> 按各自负责的**源码目录**与**业务功能**定义,防止互窜、明确职责。团队为 **2 前端 + 1 后端 + 1 产品 + 1 助理**,详见 [开发团队职责定义.md](./开发团队职责定义.md)。 + +--- + +## 一、开发角色总览 + +| 角色 | 源码目录 | 对接 API 前缀 | 技术栈 | +|------|----------|---------------|--------| +| 小程序开发工程师 | miniprogram/ | /api/miniprogram/* | 微信原生 WXML/WXSS/JS | +| 管理端开发工程师 | soul-admin/ | /api/admin/*、/api/db/* | React + Vite + TypeScript + Tailwind | +| 后端开发 | soul-api/ | 实现上述全部 | Go + Gin + GORM + PowerWeChat | + +--- + +## 二、小程序开发工程师 + +### 2.1 负责源码 + +| 路径 | 说明 | +|------|------| +| miniprogram/pages/* | 页面(index、chapters、read、my、referral、match、settings、withdraw-records、vip 等) | +| miniprogram/utils/* | 工具(scene、payment、chapterAccessManager、readingTracker) | +| miniprogram/components/* | 组件 | +| miniprogram/custom-tab-bar/* | 自定义 TabBar | +| miniprogram/app.js、app.json、app.wxss | 全局配置与入口 | + +### 2.2 负责业务功能 + +| 功能域 | 页面/入口 | 对接接口 | +|--------|-----------|----------| +| 首页与浏览 | index、chapters、search | /api/miniprogram/book/*、config | +| 阅读与付费 | read | /api/miniprogram/pay、pay/notify、user/check-purchased、user/purchase-status | +| 找伙伴 | match | /api/miniprogram/match/*、ckb/* | +| 推广与分销 | referral | /api/miniprogram/referral/*、earnings | +| 提现 | 推广中心申请、我的待确认、withdraw-records | /api/miniprogram/withdraw、withdraw/records、withdraw/pending-confirm | +| 我的 | my | /api/miniprogram/user/*、vip/*、withdraw/* | +| 设置 | settings | /api/miniprogram/login、phone、config | +| 地址 | addresses | /api/miniprogram/user/addresses | + +### 2.3 边界约束 + +- **禁止**:调用 `/api/admin/*`、`/api/db/*`;不得使用 next-project 接口。 +- **请求**:统一通过 `getApp().request(url, options)`,baseUrl 指向 soul-api。 + +--- + +## 三、管理端开发工程师 + +### 3.1 负责源码 + +| 路径 | 说明 | +|------|------| +| soul-admin/src/pages/* | 页面(Dashboard、Content、Chapters、Orders、Users、Withdrawals、Payment、Settings、QRCodes、Distribution 等) | +| soul-admin/src/components/* | 组件(ui、modules 等) | +| soul-admin/src/api/* | 请求封装(client.ts、auth.ts) | +| soul-admin/src/layouts/* | 布局 | +| soul-admin/src/hooks/* | hooks | + +### 3.2 负责业务功能 + +| 功能域 | 页面 | 对接接口 | +|--------|------|----------| +| 仪表盘 | DashboardPage | /api/admin/* | +| 内容管理 | ContentPage | /api/admin/content | +| 章节管理 | ChaptersPage | /api/admin/chapters | +| 订单 | OrdersPage | /api/orders | +| 用户管理 | UsersPage | /api/db/users | +| 提现审核 | WithdrawalsPage | /api/admin/withdrawals | +| 支付配置 | PaymentPage | /api/admin/payment | +| 推广设置 | ReferralSettingsPage | /api/admin/referral-settings | +| 系统设置 | SettingsPage | /api/admin/settings | +| 二维码 | QRCodesPage | /api/db/config 等 | +| 分销概览 | DistributionPage | /api/admin/distribution/overview | +| VIP 角色 | VipRolesPage | /api/db/vip-roles | + +### 3.3 边界约束 + +- **允许**:`/api/admin/*`、`/api/db/*`,以及 `/api/orders` 等与现网一致的管理端接口。 +- **禁止**:调用 `/api/miniprogram/*`;不得使用小程序登录或小程序 token。 +- **请求**:统一通过 `client.ts` 的 get/post/put/del;鉴权用 `auth.ts` 的 Bearer admin_token。 + +--- + +## 四、后端开发 + +### 4.1 负责源码 + +| 路径 | 说明 | +|------|------| +| soul-api/internal/router | 路由注册(miniprogram、admin、db、payment 各组) | +| soul-api/internal/handler | 业务 handler | +| soul-api/internal/model | 数据模型 | +| soul-api/internal/wechat | 微信、支付、转账等封装 | +| soul-api/internal/config | 配置加载 | +| soul-api/internal/database | 数据库连接 | +| soul-api/internal/auth | 鉴权(JWT) | +| soul-api/internal/middleware | 中间件 | + +### 4.2 负责路由分组与业务 + +| 路由组 | 前缀 | 使用方 | 典型业务 | +|--------|------|--------|----------| +| miniprogram | /api/miniprogram/* | 小程序 | 登录、支付、书籍、推荐、提现、VIP、用户 | +| admin | /api/admin/* | 管理端 | 登录、章节、内容、支付配置、提现审核、设置、分销 | +| db | /api/db/* | 管理端 | 用户、配置、书籍、章节、VIP 角色、初始化 | +| payment | /api/payment/* | 微信/支付宝回调 | 支付回调、订单、商家转账回调 | + +### 4.3 边界约束 + +- **按使用方挂路由**:小程序接口只挂 miniprogram;管理端接口只挂 admin/db;不得混用。 +- **禁止**:在 miniprogram 组挂仅 admin 用的接口;在 admin/db 组挂小程序专属逻辑。 + +### 4.4 特殊路由说明 + +| 类型 | 示例 | 说明 | +|------|------|------| +| 微信/支付宝回调 | /api/payment/*、/api/miniprogram/pay/notify | 由微信/支付宝主动调用,无鉴权;后端负责验签、解密 | +| 管理端扁平路径 | /api/orders | 管理端使用,与 /api/admin/*、/api/db/* 并列 | + +--- + +## 五、支付/提现相关职责归属 + +| 环节 | 小程序开发工程师 | 管理端开发工程师 | 后端开发 | +|------|--------------|--------------|----------------| +| 支付下单 | 调 /api/miniprogram/pay,调起 wx.requestPayment | - | 实现 Pay handler,调用微信统一下单 | +| 支付回调 | - | - | 实现 PayNotify,验签、更新订单、分佣 | +| 提现申请 | 调 /api/miniprogram/withdraw | - | 实现 WithdrawPost;校验余额、写 withdrawals | +| 提现审核 | - | 调 /api/admin/withdrawals 列表、通过/拒绝 | 实现 AdminWithdrawalsList、Action;调微信打款 | +| 提现回调 | - | - | 实现 PaymentWechatTransferNotify;验签、解密、更新状态 | +| 待确认收款 | 调 /api/miniprogram/withdraw/pending-confirm | - | 实现 WithdrawPendingConfirm | + +--- + +## 六、速查:编辑目录 → 角色 + +| 编辑目录 | 角色 | 必遵守 | 主 Skill | +|----------|------|--------|----------| +| miniprogram/** | 小程序开发工程师 | soul-miniprogram-boundary | SKILL-小程序开发.md | +| soul-admin/** | 管理端开发工程师 | soul-admin-boundary | SKILL-管理端开发.md | +| soul-api/** | 后端开发 | soul-api-boundary、soul-api-coding | SKILL-API开发.md | + +--- + +## 七、跨端协同与变更检查 + +| 场景 | 动作 | +|------|------| +| **跨端功能开发** | 加载 SKILL-角色流程控制.md,按「需求分析 → 并行开发 → 管理端启动」执行 | +| **变更完成准备提交** | **必过** soul-change-checklist.mdc + SKILL-变更关联检查.md | +| **接口契约** | 后端开发输出(路径、请求/响应、字段);小程序/管理端按契约对接 | + +--- + +## 八、排除项 + +- **next-project/**:仅预览,不参与线上;新增/优化以 miniprogram、soul-admin、soul-api 为准。 + +--- + +## 九、相关文档 + +| 文档 | 说明 | +|------|------| +| [开发团队职责定义](./开发团队职责定义.md) | 五角色团队、Skills 分配 | +| [角色驱动Skills分析](./角色驱动Skills分析.md) | Skills 组织方式、改进点 | +| [SKILL-角色流程控制](../skills/SKILL-角色流程控制.md) | 跨端协同流程、决策表 | +| soul-project-boundary.mdc | 项目边界、防互窜原则 | + +--- + +**更新日期**:2026-02 diff --git a/.cursor/docs/开发团队职责定义.md b/.cursor/docs/开发团队职责定义.md new file mode 100644 index 00000000..dedd1b19 --- /dev/null +++ b/.cursor/docs/开发团队职责定义.md @@ -0,0 +1,134 @@ +# Soul 创业派对 - 开发团队职责定义 + +> **开发团队**:2 前端(小程序开发工程师、管理端开发工程师)+ 1 后端 + 1 产品 + 1 助理。按职责分配 Skills,防止互窜、明确协同。开发团队有**经验库**,根据经验自动升级 Skills。 + +--- + +## 一、开发团队总览 + +| 角色 | 职责 | 负责目录/场景 | 主 Skill | +|------|------|---------------|----------| +| **小程序开发工程师** | 微信原生小程序 C 端 | miniprogram/ | SKILL-小程序开发.md | +| **管理端开发工程师** | React 管理后台 | soul-admin/ | SKILL-管理端开发.md | +| **后端开发** | Go + Gin + GORM 接口服务 | soul-api/ | SKILL-API开发.md | +| **产品经理** | 需求、验收、协调 | 开发文档/1、需求/、临时需求池/ | SKILL-产品经理.md | +| **助理橙子** | 讨论后记录、文档同步 | 触发词:小橙、橙子、讨论完毕 | SKILL-助理橙子-文档同步.md | + +--- + +## 二、开发角色(源码) + +### 2.1 小程序开发工程师 + +| 项目 | 说明 | +|------|------| +| **源码** | miniprogram/pages、utils、components、app.js | +| **API** | 只调 `/api/miniprogram/*` | +| **禁止** | 不调 `/api/admin/*`、`/api/db/*` | +| **主 Skill** | SKILL-小程序开发.md | +| **辅助** | 三端架构 → API开发 → 变更关联检查 | +| **协同** | SKILL-角色流程控制.md(跨端时) | + +### 2.2 管理端开发工程师 + +| 项目 | 说明 | +|------|------| +| **源码** | soul-admin/src/pages、components、api、layouts | +| **API** | 只调 `/api/admin/*`、`/api/db/*`、`/api/orders` 等 | +| **禁止** | 不调 `/api/miniprogram/*` | +| **主 Skill** | SKILL-管理端开发.md | +| **辅助** | 三端架构 → API开发 → 变更关联检查 | +| **协同** | SKILL-角色流程控制.md(跨端时) | + +### 2.3 后端开发 + +| 项目 | 说明 | +|------|------| +| **源码** | soul-api/internal/router、handler、model、wechat、config | +| **路由** | 按使用方挂 miniprogram / admin / db / payment | +| **主 Skill** | SKILL-API开发.md | +| **辅助** | soul-api-coding → 三端架构 → 变更关联检查 → MySQL直接操作 | +| **协同** | SKILL-角色流程控制.md(跨端时) | + +--- + +## 三、非开发角色 + +### 3.1 产品经理 + +| 项目 | 说明 | +|------|------| +| **职责** | 需求分析、需求文档、验收标准、与开发协调 | +| **文档** | 开发文档/1、需求/、临时需求池/、开发文档/10、项目管理/ | +| **主 Skill** | SKILL-产品经理.md | +| **产出** | 需求汇总、需求分析、验收清单、项目推进表 | + +### 3.2 助理橙子 + +| 项目 | 说明 | +|------|------| +| **职责** | 讨论后记录、文档同步、更新开发文档 | +| **触发** | 小橙、橙子、橙橙、🍊、「讨论完毕」「记录一下」「同步到开发文档」 | +| **主 Skill** | SKILL-助理橙子-文档同步.md | +| **规则** | assistant-xiaofeng.mdc | + +--- + +## 四、Skills 分配速查 + +| 角色 | 主 Skill | 辅助 Skill | 协同 Skill | +|------|----------|------------|------------| +| 小程序开发工程师 | SKILL-小程序开发 | 三端架构、API开发、变更关联检查 | 角色流程控制 | +| 管理端开发工程师 | SKILL-管理端开发 | 三端架构、API开发、变更关联检查 | 角色流程控制 | +| 后端开发 | SKILL-API开发 | soul-api-coding、三端架构、变更关联检查、MySQL直接操作 | 角色流程控制 | +| 产品经理 | SKILL-产品经理 | 需求汇总、运营与变更 | - | +| 助理橙子 | SKILL-助理橙子-文档同步 | - | - | + +### 通用 / 场景 Skill(全员) + +| 场景 | Skill | 何时选用 | +|------|-------|----------| +| 跨端功能开发 | SKILL-角色流程控制 | 开发涉及多端时 | +| 变更完成 | SKILL-变更关联检查、soul-change-checklist | **开发改完必过** | +| 文档同步 | SKILL-助理橙子-文档同步 | 讨论完毕、记录、同步文档 | +| next-project | SKILL-next-project仅预览 | 编辑 next-project/ 或区分线上后端 | + +--- + +## 五、角色推断 + +| 触发条件 | 推断角色 | 加载 | +|----------|----------|------| +| 编辑 miniprogram/** | 小程序开发工程师 | SKILL-小程序开发 + soul-miniprogram-boundary | +| 编辑 soul-admin/** | 管理端开发工程师 | SKILL-管理端开发 + soul-admin-boundary | +| 编辑 soul-api/** | 后端开发 | SKILL-API开发 + soul-api-boundary、soul-api-coding | +| 编辑 开发文档/1、需求/、临时需求池/ | 产品经理 | SKILL-产品经理 | +| 说 小橙、橙子、讨论完毕、记录、同步文档 | 助理橙子 | SKILL-助理橙子-文档同步 | + +--- + +## 六、开发团队经验库 + +| 项目 | 说明 | +|------|------| +| **位置** | `.cursor/经验库/` | +| **用途** | 沉淀 bug 修复、最佳实践、决策、踩坑;根据经验**自动升级 Skills** | +| **触发** | 用户说「吸收经验」「升级 skills」「记录经验」→ 助理橙子执行入库 + 升级 | +| **流程** | 提炼 → 入库(经验清单.md)→ 更新对应 SKILL-xxx.md | + +详见 [经验库 README](../经验库/README.md)。 + +--- + +## 七、相关文档 + +| 文档 | 说明 | +|------|------| +| [经验库 README](../经验库/README.md) | 经验入库流程、Skills 升级触发 | +| [三角色边界定义](./三角色边界定义.md) | 开发三角色源码与业务边界 | +| [角色驱动Skills分析](./角色驱动Skills分析.md) | Skills 组织方式 | +| [SKILL-角色流程控制](../skills/SKILL-角色流程控制.md) | 跨端协同流程 | + +--- + +**更新日期**:2026-02 diff --git a/.cursor/docs/角色驱动Skills分析.md b/.cursor/docs/角色驱动Skills分析.md index 9c529299..9a1fe344 100644 --- a/.cursor/docs/角色驱动Skills分析.md +++ b/.cursor/docs/角色驱动Skills分析.md @@ -2,10 +2,12 @@ ## 一、当前方式概述 -Skills 按**三角色**(小程序开发者、管理端开发者、后端 API 开发者)组织,每个角色有: +Skills 按**五角色**(小程序开发工程师、管理端开发工程师、后端开发、产品经理、助理橙子)组织,每个角色有: + +> **团队职责**:完整定义见 [开发团队职责定义.md](./开发团队职责定义.md)。开发三角色源码边界见 [三角色边界定义.md](./三角色边界定义.md)。 - **主 Skill**:开发风格与规范(必须遵循) - **辅助 Skill**:按顺序 1→2→3→4 选用 -- **协同 Skill**:跨端功能开发时使用 +- **协同 Skill**:跨端功能开发时使用(开发角色) --- diff --git a/.cursor/rules/assistant-xiaofeng.mdc b/.cursor/rules/assistant-xiaofeng.mdc index 1d3ed25a..695520e9 100644 --- a/.cursor/rules/assistant-xiaofeng.mdc +++ b/.cursor/rules/assistant-xiaofeng.mdc @@ -1,14 +1,14 @@ --- -description: 小橙/橙子/橙橙/🍊 - 讨论后记录内容并同步更新开发文档 +description: 小橙/橙子/橙橙/🍊 - 开发团队文档同步与经验升级助理 globs: ["**"] alwaysApply: false --- -# 小橙(橙子/橙橙/🍊)- 文档同步助理 +# 小橙(橙子/橙橙/🍊)- 开发团队文档同步与经验升级助理 ## 角色定义 -**小橙**(橙子、橙橙、🍊)是项目文档同步助理。以下任一表述均可唤醒:小橙、橙子、橙橙、🍊、「讨论完毕」「记录一下」「同步到开发文档」「更新文档」等。讨论告一段落需要沉淀时,以小橙身份执行文档同步。 +**小橙**(橙子、橙橙、🍊)是开发团队文档同步与经验升级助理。以下任一表述均可唤醒:小橙、橙子、橙橙、🍊、「讨论完毕」「记录一下」「同步到开发文档」「吸收经验」「升级 skills」等。讨论告一段落需要沉淀时,以小橙身份执行文档同步;用户说「吸收经验」「升级 skills」时,执行经验入库并升级对应 Skill。 ## 执行时机 @@ -21,6 +21,7 @@ alwaysApply: false 1. **记录讨论要点**:提炼本次讨论的结论、决策、待办 2. **更新开发文档**:按内容类型写入对应文档 3. **保持文档一致**:确保 需求汇总、运营与变更、临时需求池 等相互引用一致 +4. **经验吸收与 Skills 升级**(当用户说「吸收经验」「升级 skills」时):提炼经验 → 写入 `.cursor/经验库/` → 更新对应 `.cursor/skills/SKILL-xxx.md` ## 文档更新映射 @@ -30,6 +31,7 @@ alwaysApply: false | 近期讨论、项目状态 | `开发文档/10、项目管理/运营与变更.md` | 第五部分或新增「近期讨论」节 | | 技术方案、待实现 | `临时需求池/` 或 `开发文档/8、部署/` | 新建或更新对应分析/说明文档 | | 项目推进、里程碑 | `开发文档/10、项目管理/项目落地推进表.md` | 第十二节或对应阶段 | +| 经验沉淀、Skills 升级 | `.cursor/经验库/` | 经验清单索引 + 更新对应 Skill | ## 输出格式 diff --git a/.cursor/rules/product-manager.mdc b/.cursor/rules/product-manager.mdc new file mode 100644 index 00000000..360c3f0e --- /dev/null +++ b/.cursor/rules/product-manager.mdc @@ -0,0 +1,11 @@ +--- +description: 产品经理需求与验收。编辑需求文档时加载 SKILL-产品经理 +globs: ["开发文档/1、需求/**", "临时需求池/**", "开发文档/10、项目管理/**"] +alwaysApply: false +--- + +# 产品经理 + +当编辑 **开发文档/1、需求/**、**临时需求池/**、**开发文档/10、项目管理/** 时,推断当前角色为**产品经理**,加载 **SKILL-产品经理.md**。 + +职责:需求分析、需求文档、验收标准、与开发协调。 diff --git a/.cursor/rules/soul-project-boundary.mdc b/.cursor/rules/soul-project-boundary.mdc index f1aa75b0..916e6d8f 100644 --- a/.cursor/rules/soul-project-boundary.mdc +++ b/.cursor/rules/soul-project-boundary.mdc @@ -11,7 +11,7 @@ alwaysApply: true 当新的 Cursor 会话打开本项目时,**先进行自检**,确保仅沿用本项目的开发风格与配置: 1. **Rules 与 Skills 范围**:仅使用本项目 `.cursor/rules/` 与 `.cursor/skills/` 下的规则与技能;不套用与本项目无关的全局或其它项目的 rules/skills(如存客宝AI、React 转 Vue、Next 全栈拆分等与本项目无关的能力)。 -2. **开发风格**:按**角色**(小程序开发者/管理端开发者/后端 API 开发者)遵守对应 boundary 与 Skill;Skills 索引按角色驱动,见 `.cursor/README.md` 第二节;API 路径、路由分组、变更检查清单等均以本规则为准。 +2. **开发风格**:按**团队角色**(小程序开发工程师/管理端开发工程师/后端开发/产品经理/助理橙子)遵守对应 boundary 与 Skill;Skills 索引按角色驱动,见 `.cursor/README.md` 第二节;API 路径、路由分组、变更检查清单等均以本规则为准。 3. **配置参数**:baseUrl、鉴权方式、路由前缀(`/api/miniprogram/*`、`/api/admin/*`、`/api/db/*`)等以项目内实际配置为准,不引入外部项目的默认值或约定。 4. **清理无关项**:若发现会话上下文中存在与本项目无关的 rules 或 skills 引用,应忽略或排除,仅以本项目 `.cursor` 为准。 @@ -43,9 +43,11 @@ alwaysApply: true | 编辑目录 | 推断角色 | 必遵守 | 必参考主 Skill | |----------|----------|--------|----------------| -| miniprogram/ | 小程序开发者 | soul-miniprogram-boundary | SKILL-小程序开发.md | -| soul-admin/ | 管理端开发者 | soul-admin-boundary | SKILL-管理端开发.md | -| soul-api/ | 后端 API 开发者 | soul-api-boundary、soul-api-coding | SKILL-API开发.md | +| miniprogram/ | 小程序开发工程师 | soul-miniprogram-boundary | SKILL-小程序开发.md | +| soul-admin/ | 管理端开发工程师 | soul-admin-boundary | SKILL-管理端开发.md | +| soul-api/ | 后端开发 | soul-api-boundary、soul-api-coding | SKILL-API开发.md | +| 开发文档/1、需求/、临时需求池/ | 产品经理 | - | SKILL-产品经理.md | +| 说 小橙、橙子、讨论完毕 | 助理橙子 | assistant-xiaofeng | SKILL-助理橙子-文档同步.md | | 场景 | 动作 | |------|------| @@ -53,3 +55,4 @@ alwaysApply: true | **跨端功能开发** | 加载 **SKILL-角色流程控制.md**,按协同流程执行 | | **变更完成准备提交** | **必过** **soul-change-checklist.mdc** + **SKILL-变更关联检查.md**,未过即视为漏改 | | **小橙/橙子/橙橙/🍊、讨论完毕、记录、同步文档** | 加载 **SKILL-助理橙子-文档同步.md**,以小橙身份更新开发文档 | +| **吸收经验、升级 skills、记录经验** | 助理橙子执行经验入库(`.cursor/经验库/`)+ 升级对应 Skill | diff --git a/.cursor/skills/SKILL-产品经理.md b/.cursor/skills/SKILL-产品经理.md new file mode 100644 index 00000000..f58e1b33 --- /dev/null +++ b/.cursor/skills/SKILL-产品经理.md @@ -0,0 +1,71 @@ +--- +name: soul-product-manager +description: Soul 创业派对产品经理需求与验收。需求分析、需求文档、验收标准、与开发对接。Use when 需求分析, 需求文档, 验收, 产品经理. +--- + +# Soul 创业派对 - 产品经理 Skill + +当你在**需求分析、需求文档、验收标准**或与开发对接时,使用本 Skill。产品经理不参与源码编写,主要负责需求产出与验收。 + +--- + +## 1. 职责范围 + +| 职责 | 说明 | 产出 | +|------|------|------| +| 需求分析 | 业务需求拆解、优先级、技术可行性 | 需求分析文档、临时需求池 | +| 需求文档 | 需求清单、业务规则、验收标准 | 需求汇总.md、运营与变更.md | +| 验收 | 功能验收、回归检查 | 验收清单、项目推进表 | +| 协调 | 与开发沟通、排期、变更 | 运营与变更、项目落地推进表 | + +--- + +## 2. 文档目录 + +| 文档 | 说明 | +|------|------| +| `开发文档/1、需求/需求汇总.md` | 需求清单、业务需求 | +| `临时需求池/` | 需求分析、技术分析 | +| `开发文档/10、项目管理/项目落地推进表.md` | 里程碑、永平落地 | +| `开发文档/10、项目管理/运营与变更.md` | 近期讨论、变更记录 | + +--- + +## 3. 需求分析流程 + +1. **收集需求**:从用户、运营、开发反馈中提取 +2. **拆解**:按功能域拆解(小程序、管理端、后端) +3. **判定管理端需求**:该功能在管理端是否需要?配置/开关/审核/统计? +4. **输出**:需求分析文档 → 临时需求池 或 需求汇总 + +--- + +## 4. 与开发对接 + +| 对接方 | 对接内容 | +|--------|----------| +| 小程序开发工程师 | 小程序功能、页面、交互、miniprogram 接口契约 | +| 管理端开发工程师 | 管理端配置、审核、列表、admin/db 接口契约 | +| 后端开发 | 接口契约(路径、请求/响应、字段)、验收标准 | + +**接口契约**:由后端开发输出;产品经理可参与验收标准定义。 + +--- + +## 5. 验收清单 + +- 功能是否符合需求清单描述 +- 小程序、管理端、后端是否按契约对接 +- 边界约束是否遵守(路径、鉴权) + +--- + +## 6. 何时选用 + +- 编辑 `开发文档/1、需求/`、`临时需求池/`、`开发文档/10、项目管理/` 时 +- 进行需求分析、需求文档编写、验收标准定义时 +- 用户说「需求分析」「产品经理」「验收」时 + +--- + +**更新日期**:2026-02 diff --git a/.cursor/skills/SKILL-助理橙子-文档同步.md b/.cursor/skills/SKILL-助理橙子-文档同步.md index 2104381e..cd3bcf11 100644 --- a/.cursor/skills/SKILL-助理橙子-文档同步.md +++ b/.cursor/skills/SKILL-助理橙子-文档同步.md @@ -6,8 +6,8 @@ - **唤醒名**:小橙、橙子、橙橙、🍊 - 「讨论完毕」「记录一下」「同步到开发文档」「更新文档」 -- 「吸收经验,升级 skills」「将项目情况同步更新到开发文档」 -- 「每次讨论完毕后记录内容并更新开发文档」 +- **「吸收经验」「升级 skills」「记录经验」** → 执行**经验入库 + Skills 升级**流程 +- 「将项目情况同步更新到开发文档」 ## 执行流程 @@ -40,6 +40,29 @@ - 若新建了 `临时需求池/xxx.md`,在需求汇总或运营与变更中可引用 - 若更新了需求清单,检查项目落地推进表是否需要同步 +### 5. 经验吸收与 Skills 升级(开发团队经验库) + +当用户说**「吸收经验」「升级 skills」「记录经验」**时,执行: + +1. **提炼经验**:从对话中提取 + - 问题/场景 + - 解决方案 + - 适用角色(小程序/管理端/后端/产品) + - 应升级的 Skill + +2. **入库**:写入 `.cursor/经验库/` + - 追加到 `经验清单.md` 索引 + - 或新建 `YYYY-MM/xxx.md` 详细条目 + +3. **升级 Skill**:根据经验类型,更新对应 `.cursor/skills/SKILL-xxx.md` + - bug 修复 → 补充规则/流程/常见问题 + - 最佳实践 → 补充示例或新章节 + - 决策记录 → 补充到相关 Skill 或 boundary + +4. **回复**:已吸收经验并升级 Skills,详见 经验库/经验清单.md + +**经验库说明**:见 `.cursor/经验库/README.md`。 + ## 文档结构速查 ``` @@ -50,6 +73,9 @@ │ ├── 项目落地推进表.md # 里程碑、永平落地 │ └── 运营与变更.md # 近期更新、变更记录 临时需求池/ # 需求分析、技术分析、待办 +.cursor/经验库/ # 开发团队经验沉淀,用于升级 Skills +├── README.md # 经验库说明、入库流程 +└── 经验清单.md # 经验索引 ``` ## 示例 @@ -62,3 +88,16 @@ 2. 更新 `需求汇总.md`:新增「需求清单」行 3. 更新 `运营与变更.md`:第五部分追加近期讨论 4. 回复:已记录并更新开发文档,详见 xxx + +--- + +**示例 2:吸收经验、升级 Skills** + +**用户**:吸收经验,升级 skills。 + +**小橙**执行: + +1. 提炼:本次 bug 修复发现「支付回调需以 openId 解析买家,不信任 attach.userId」 +2. 入库:追加到 `.cursor/经验库/经验清单.md` +3. 升级:在 SKILL-API开发 或 相关部署文档中补充该规则 +4. 回复:已吸收经验并升级 Skills,详见 经验库/经验清单.md diff --git a/.cursor/skills/SKILL-角色流程控制.md b/.cursor/skills/SKILL-角色流程控制.md index 5e71dc36..7ccdeb13 100644 --- a/.cursor/skills/SKILL-角色流程控制.md +++ b/.cursor/skills/SKILL-角色流程控制.md @@ -1,20 +1,20 @@ --- name: soul-role-workflow -description: Soul 创业派对三角色协同流程。小程序开发者、管理端开发者、后端API开发者职责与协同。跨端功能开发、新增/优化时使用。Use when 跨端协同, 角色流程, 功能开发协作. +description: Soul 创业派对开发协同流程。小程序开发工程师、管理端开发工程师、后端开发职责与协同。跨端功能开发、新增/优化时使用。Use when 跨端协同, 角色流程, 功能开发协作. --- # Soul 创业派对 - 角色流程控制 Skill -当进行**跨端功能开发**(小程序新增/优化、管理端配置、API 变更)时,使用本 Skill 明确**三角色职责**与**协同流程**,保证开发顺畅、减少漏改与返工。 +当进行**跨端功能开发**(小程序新增/优化、管理端配置、API 变更)时,使用本 Skill 明确**开发三角色职责**与**协同流程**,保证开发顺畅、减少漏改与返工。 --- -## 1. 三角色定义 +## 1. 开发三角色定义 | 角色 | 负责目录 | 职责概要 | 开发风格规范 | |------|----------|----------|--------------| -| **小程序开发者** | miniprogram/ | 微信原生小程序 C 端功能,只调 `/api/miniprogram/*` | **SKILL-小程序开发.md**:WXML/WXSS/JS、app.request、scene 编解码、权限与支付约定 | -| **管理端开发者** | soul-admin/ | React 管理后台,只调 `/api/admin/*`、`/api/db/*` | **SKILL-管理端开发.md**:React + Vite + Tailwind、client.ts、Radix UI、鉴权与列表约定 | -| **后端 API 开发者** | soul-api/ | Go + Gin + GORM 接口服务,按使用方挂 miniprogram / admin / db 路由 | **SKILL-API开发.md**、soul-api-coding.mdc:GORM、Gin、路由分组、响应格式 | +| **小程序开发工程师** | miniprogram/ | 微信原生小程序 C 端功能,只调 `/api/miniprogram/*` | **SKILL-小程序开发.md**:WXML/WXSS/JS、app.request、scene 编解码、权限与支付约定 | +| **管理端开发工程师** | soul-admin/ | React 管理后台,只调 `/api/admin/*`、`/api/db/*` | **SKILL-管理端开发.md**:React + Vite + Tailwind、client.ts、Radix UI、鉴权与列表约定 | +| **后端开发** | soul-api/ | Go + Gin + GORM 接口服务,按使用方挂 miniprogram / admin / db 路由 | **SKILL-API开发.md**、soul-api-coding.mdc:GORM、Gin、路由分组、响应格式 | **开发风格约定**:各角色在各自端内开发时,**必须**按上表对应的 Skill 与 boundary 执行,保持代码风格、目录结构、命名与接口约定一致。不得跨路径调用(详见 soul-project-boundary)。 @@ -176,7 +176,7 @@ sequenceDiagram 各角色在执行下列动作时,**均按各自端的开发风格 Skill** 编写代码(小程序→SKILL-小程序开发、管理端→SKILL-管理端开发、API→SKILL-API开发)。 -### 3.1 小程序开发者 +### 3.1 小程序开发工程师 | 阶段 | 动作 | |------|------| @@ -185,7 +185,7 @@ sequenceDiagram | 完成自测 | 完成并自测通过后,通知管理端开发者(若管理端需要) | | 收尾 | 参与联调,过 soul-change-checklist | -### 3.2 管理端开发者 +### 3.2 管理端开发工程师 | 阶段 | 动作 | |------|------| @@ -194,7 +194,7 @@ sequenceDiagram | 管理端启动 | 小程序变更完成后,若需要则开始管理端调整 | | 收尾 | 参与联调,过 soul-change-checklist | -### 3.3 后端 API 开发者 +### 3.3 后端开发 | 阶段 | 动作 | |------|------| @@ -216,7 +216,7 @@ sequenceDiagram | 纯展示/活动 | ❌ 或仅统计 | 活动页、弹窗 | | 用户行为 | 视情况 | 若需审核/统计则要 | -**原则**:不确定时,管理端开发者主动与产品/小程序开发者确认。 +**原则**:不确定时,管理端开发工程师主动与产品/小程序开发工程师确认。 --- @@ -228,8 +228,8 @@ Skills 索引按**角色驱动**,见 `.cursor/README.md` 第二节。 |------|------| | soul-change-checklist.mdc | 阶段 4 必过清单 | | SKILL-变更关联检查.md | 详细关联检查思路 | -| **SKILL-小程序开发.md** | 小程序开发者**主 Skill**:请求、scene、支付、权限等约定 | -| **SKILL-管理端开发.md** | 管理端开发者**主 Skill**:client、auth、Radix UI、列表等约定 | +| **SKILL-小程序开发.md** | 小程序开发工程师**主 Skill**:请求、scene、支付、权限等约定 | +| **SKILL-管理端开发.md** | 管理端开发工程师**主 Skill**:client、auth、Radix UI、列表等约定 | | **SKILL-API开发.md** | API 开发者**主 Skill**:GORM、路由分组、响应格式等约定 | 三角色在各自端内开发时,必须遵循对应主 Skill 的开发风格,保证三端风格统一、规范一致。 diff --git a/.cursor/经验库/README.md b/.cursor/经验库/README.md new file mode 100644 index 00000000..d5414318 --- /dev/null +++ b/.cursor/经验库/README.md @@ -0,0 +1,76 @@ +# 开发团队经验库 + +> 开发团队(小程序开发工程师、管理端开发工程师、后端开发、产品经理、助理橙子)的集体经验沉淀,用于**根据经验自动升级 Skills**。 + +--- + +## 一、用途 + +| 用途 | 说明 | +|------|------| +| **沉淀经验** | 记录 bug 修复、决策、最佳实践、踩坑与规避 | +| **升级 Skills** | 经验入库后,对应更新 `.cursor/skills/` 下相关 Skill,避免同类问题复现 | +| **可追溯** | 每条经验可关联日期、角色、相关 Skill | + +--- + +## 二、经验类型 + +| 类型 | 说明 | 升级目标 | +|------|------|----------| +| **bug 修复** | 修 bug 时发现的规则/流程遗漏 | 对应角色主 Skill、变更关联检查 | +| **最佳实践** | 表单、列表、路由等实现模式 | SKILL-管理端开发、SKILL-API开发 等 | +| **决策记录** | 技术选型、接口约定、边界决策 | 相关 Skill、boundary、开发文档 | +| **踩坑规避** | 已知坑及规避方式 | 对应 Skill 的「常见问题」或新章节 | + +--- + +## 三、经验入库流程 + +``` +1. 触发:用户说「吸收经验」「升级 skills」「记录经验」或讨论完毕时主动提炼 +2. 提炼:从对话中提取 问题/场景、解决方案、适用角色 +3. 入库:写入 经验库/YYYY-MM-xxx.md 或追加到 经验库/经验清单.md +4. 升级:根据经验类型,更新对应 .cursor/skills/SKILL-xxx.md +``` + +**执行者**:助理橙子(SKILL-助理橙子-文档同步)在「吸收经验、升级 skills」时执行完整流程。 + +--- + +## 四、经验条目格式 + +```markdown +## YYYY-MM-DD | 标题 + +- **类型**:bug 修复 / 最佳实践 / 决策记录 / 踩坑规避 +- **角色**:小程序 / 管理端 / 后端 / 产品 +- **升级 Skill**:SKILL-xxx.md +- **内容**:问题描述、解决方案、补充到 Skill 的要点 +``` + +--- + +## 五、自动升级触发 + +| 触发词 | 动作 | +|--------|------| +| 吸收经验、升级 skills、记录经验 | 助理橙子执行:提炼 → 入库 → 升级 Skill | +| 讨论完毕、记录一下 | 若有可沉淀经验,提示「是否吸收经验并升级 Skills」 | +| 修 bug 完成 | 若发现规则/流程遗漏,建议写入经验库并更新 Skill | + +--- + +## 六、目录结构 + +``` +.cursor/经验库/ +├── README.md # 本说明 +├── 经验清单.md # 经验条目索引(可选) +└── YYYY-MM/ # 按月份归档(可选) + └── xxx.md +``` + +--- + +**更新日期**:2026-02 diff --git a/.cursor/经验库/经验清单.md b/.cursor/经验库/经验清单.md new file mode 100644 index 00000000..1249a864 --- /dev/null +++ b/.cursor/经验库/经验清单.md @@ -0,0 +1,23 @@ +# 开发团队经验清单 + +> 经验入库后在此索引,便于追溯与升级 Skills。 + +--- + +## 索引说明 + +| 日期 | 类型 | 角色 | 升级 Skill | 摘要 | +|------|------|------|------------|------| +| (示例)2026-02-26 | 最佳实践 | 管理端 | SKILL-管理端开发 | SetVipModal 表单弹窗可选+可手动填写 | +| (示例)2026-02-26 | 最佳实践 | 后端 | SKILL-API开发 | vip_roles 新增表/字段完整流程 | + +--- + +## 已吸收经验(示例) + +- **SetVipModal 经验**:已写入 SKILL-管理端开发 4.1 表单弹窗 +- **vip_roles 经验**:已写入 SKILL-API开发 3.2、SKILL-MySQL直接操作 8 + +--- + +**更新日期**:2026-02 diff --git a/开发文档/2、架构/soul-api技术栈.md b/开发文档/2、架构/soul-api技术栈.md new file mode 100644 index 00000000..2a479f92 --- /dev/null +++ b/开发文档/2、架构/soul-api技术栈.md @@ -0,0 +1,54 @@ +# soul-api Go 技术栈 + +## 语言与运行时 + +- **Go 1.25** + +## Web 框架与 HTTP + +- **Gin**(`github.com/gin-gonic/gin`):HTTP 路由与请求处理 +- **gin-contrib/cors**:跨域 +- **unrolled/secure**:安全头(HTTPS 重定向、HSTS 等,在 `middleware.Secure()` 中使用) + +## 数据层 + +- **GORM**(`gorm.io/gorm`):ORM +- **GORM MySQL 驱动**(`gorm.io/driver/mysql`):连接 MySQL +- **go-sql-driver/mysql**:底层 MySQL 驱动(GORM 间接依赖) + +## 微信生态 + +- **PowerWeChat**(`github.com/ArtisanCloud/PowerWeChat/v3`):微信开放能力(小程序、支付、商家转账等) +- **PowerLibs**(`github.com/ArtisanCloud/PowerLibs/v3`):PowerWeChat 依赖 + +## 配置与环境 + +- **godotenv**(`github.com/joho/godotenv`):从 `.env` 加载环境变量 +- 业务配置集中在 `internal/config`,通过 `config.Load()` 读取 + +## 鉴权与安全 + +- **golang-jwt/jwt/v5**:管理端 JWT 签发与校验(`internal/auth/adminjwt.go`) +- 管理端路由使用 `middleware.AdminAuth()` 做 JWT 校验 + +## 工具与间接依赖 + +- **golang.org/x/time**:时间/限流相关(如 `rate`) +- **gin-contrib/sse**:SSE(Gin 间接) +- **bytedance/sonic**:JSON 编解码(Gin 默认) +- **go-playground/validator**:请求体校验(Gin 的 `ShouldBindJSON` 等) +- **redis/go-redis**:仅在依赖图中出现(PowerWeChat 等间接引入),项目代码中未直接使用 Redis + +## 项目结构(技术栈视角) + +| 层级 | 技术/约定 | +|----------|------------| +| 入口 | `cmd/server/main.go`,标准库 `net/http` + Gin | +| 路由 | `internal/router`,Gin Group(`/api`、`/admin`、`/miniprogram` 等) | +| 中间件 | CORS、Secure、限流(`middleware.RateLimiter`)、管理端 JWT | +| 业务逻辑 | `internal/handler`,GORM + `internal/model` | +| 数据访问 | `internal/database` 提供 `DB() *gorm.DB`,统一用 GORM | +| 微信相关 | `internal/wechat`(小程序、支付、转账等封装) | +| 开发工具 | `.air.toml` 热重载、Makefile | + +整体上是一个 **Gin + GORM + MySQL + 微信 PowerWeChat + JWT 管理端鉴权** 的 Go 后端,面向小程序与管理端 API。 diff --git a/开发文档/6、后端/管理端鉴权设计.md b/开发文档/6、后端/管理端鉴权设计.md new file mode 100644 index 00000000..53cf9add --- /dev/null +++ b/开发文档/6、后端/管理端鉴权设计.md @@ -0,0 +1,120 @@ +# soul-api 管理端登录判断与权限校验 + +> 来源:soul-api/管理端鉴权设计.md + +--- + +## 一、有没有登录的依据(JWT) + +**依据:请求中的 JWT。优先从 `Authorization: Bearer ` 读取,兼容从 Cookie `admin_session` 读取。** + +| 项目 | 说明 | +|------|------| +| 推荐方式 | 请求头 `Authorization: Bearer ` | +| 兼容方式 | Cookie 名 `admin_session`,值为 JWT 字符串 | +| JWT 算法 | HS256,密钥为 `ADMIN_SESSION_SECRET` | +| 有效期 | 7 天(exp claim) | +| 载荷 | sub=admin, username, role=admin | +| 校验 | 验签 + 未过期 → 视为已登录 | + +- 配置:`ADMIN_USERNAME` / `ADMIN_PASSWORD` 用于登录校验;`ADMIN_SESSION_SECRET` 用于签发/校验 JWT。 +- 未带有效 JWT → 401。 + +--- + +## 二、权限校验设计(路由分层) + +- **不校验登录**:只做业务逻辑(登录、登出、鉴权检查) + - `GET /api/admin` → 鉴权检查(读 Cookie,有效 200 / 无效 401) + - `POST /api/admin` → 登录(校验账号密码,写 Cookie) + - `POST /api/admin/logout` → 登出(删 Cookie) + +- **必须已登录**:挂 `AdminAuth()` 中间件,从请求读 `admin_session` 并验签+过期,不通过直接 401,不进入 handler + - `/api/admin/*`(如 chapters、content、withdrawals、settings 等) + - `/api/db/*` + +- **其它**:如 `/api/miniprogram/*`、`/api/book/*` 等不加 AdminAuth,按各自接口鉴权(如小程序 token)。 + +--- + +## 三、框图 + +```mermaid +flowchart TB + subgraph 前端["soul-admin 前端"] + A[用户打开后台 / 请求接口] + A --> B{请求类型} + B -->|登录| C[POST /api/admin] + B -->|登出| D[POST /api/admin/logout] + B -->|进后台前检查| E[GET /api/admin] + B -->|业务接口| F[GET/POST /api/admin/xxx] + end + + subgraph 请求["每次请求"] + G[浏览器自动携带 Cookie: admin_session] + G --> H[发往 soul-api] + end + + subgraph soul-api["soul-api 路由"] + I["/api/admin 三条(无中间件)"] + J["/api/admin/* 与 /api/db/*"] + J --> K[AdminAuth 中间件] + end + + subgraph 鉴权["AdminAuth 与 AdminCheck 逻辑"] + K --> L[从请求读 Cookie admin_session] + L --> M{有 Cookie?} + M -->|无| N[401 未授权] + M -->|有| O[解析 exp.signature] + O --> P{未过期 且 验签通过?} + P -->|否| N + P -->|是| Q[放行 / 返回 200] + end + + C --> I + D --> I + E --> I + F --> J + H --> soul-api + I --> E2[GET: 同鉴权逻辑 200/401] + I --> C2[POST: 校验账号密码 写 Cookie] + I --> D2[POST: 清 Cookie] +``` + +**路由与中间件关系:** + +```mermaid +flowchart LR + subgraph 无鉴权["不经过 AdminAuth"] + R1[GET /api/admin] + R2[POST /api/admin] + R3[POST /api/admin/logout] + end + + subgraph 需登录["经过 AdminAuth"] + R4["/api/admin/chapters"] + R5["/api/admin/withdrawals"] + R6["/api/admin/settings"] + R7["/api/db/*"] + end + + subgraph 中间件["AdminAuth()"] + M[读 Cookie → 验 token → 通过/401] + end + + H1[直接进 handler] + H2[通过则进 handler] + 无鉴权 --> H1 + 需登录 --> M --> H2 +``` + +--- + +## 四、相关代码位置 + +| 作用 | 位置 | +|------|------| +| JWT 签发/校验/从请求取 token | `internal/auth/adminjwt.go` | +| 登录、登出、GET 鉴权检查 | `internal/handler/admin.go` | +| 管理端中间件 | `internal/middleware/admin_auth.go` | +| 路由挂载 | `internal/router/router.go`(api.Group + admin.Use(AdminAuth())) | diff --git a/开发文档/8、部署/分销提现流程图.md b/开发文档/8、部署/分销提现流程图.md new file mode 100644 index 00000000..45835765 --- /dev/null +++ b/开发文档/8、部署/分销提现流程图.md @@ -0,0 +1,127 @@ +# 分销提现流程图 + +## 一、整体流程 + +``` +┌─────────────────────────────────────────────────────────────────────────────────┐ +│ 小 程 序 端 │ +└─────────────────────────────────────────────────────────────────────────────────┘ + + [用户] 推广中心 → 可提现金额 ≥ 最低额 → 点击「申请提现」 + │ + ▼ + POST /api/miniprogram/withdraw (WithdrawPost) + │ 校验:可提现余额、最低金额、用户 openId + ▼ + 写入 withdrawals:status = pending + │ + ▼ + 提示「提现申请已提交,审核通过后将打款至您的微信零钱」 + +───────────────────────────────────────────────────────────────────────────────── + +┌─────────────────────────────────────────────────────────────────────────────────┐ +│ 管 理 端 (soul-admin) │ +└─────────────────────────────────────────────────────────────────────────────────┘ + + [管理员] 分销 / 提现审核 → GET /api/admin/withdrawals 拉列表 + │ + ├── 点「拒绝」 → PUT /api/admin/withdrawals { action: "reject" } + │ ▼ + │ status = failed,写 error_message + │ + └── 点「通过」 → PUT /api/admin/withdrawals { action: "approve" } + │ + ▼ + 调 wechat.InitiateTransferByFundApp (FundApp 单笔) + │ + ┌───────────────┼───────────────┐ + ▼ ▼ ▼ + [微信报错] [未返回单号] [成功受理] + │ │ │ + ▼ ▼ ▼ + status=failed status=failed status=processing + 返回报错信息 返回提示 写 detail_no,batch_no,batch_id + 返回「已发起打款,微信处理中」 + +───────────────────────────────────────────────────────────────────────────────── + +┌─────────────────────────────────────────────────────────────────────────────────┐ +│ 微 信 侧 与 回 调 │ +└─────────────────────────────────────────────────────────────────────────────────┘ + + 微信异步打款 + │ + ▼ + 打款结果 → POST /api/payment/wechat/transfer/notify (PaymentWechatTransferNotify) + │ 验签、解密,得到 out_bill_no / transfer_bill_no / state / fail_reason + │ 用 detail_no = out_bill_no 找到提现记录,且仅当 status 为 processing / pending_confirm 时更新 + ▼ + state=SUCCESS → status = success + state=FAIL/CANCELLED → status = failed,写 fail_reason + +───────────────────────────────────────────────────────────────────────────────── + +┌─────────────────────────────────────────────────────────────────────────────────┐ +│ 可 选:主 动 同 步 │ +└─────────────────────────────────────────────────────────────────────────────────┘ + + 管理端 POST /api/admin/withdrawals/sync(可带 id 同步单条,或不带 id 同步所有) + │ 只处理 status IN (processing, pending_confirm) + │ FundApp 单笔:用 detail_no 调 QueryTransferByOutBill + ▼ + 按微信返回的 state 更新 status = success / failed(与回调逻辑一致) + +───────────────────────────────────────────────────────────────────────────────── + +┌─────────────────────────────────────────────────────────────────────────────────┐ +│ 小 程 序「我 的」- 待 确 认 收 款 │ +└─────────────────────────────────────────────────────────────────────────────────┘ + + [用户] 我的页 → 仅登录显示「待确认收款」区块 + │ + ▼ + GET /api/miniprogram/withdraw/pending-confirm?userId=xxx (WithdrawPendingConfirm) + │ 只返回 status IN (processing, pending_confirm) 的提现(审核通过后的) + ▼ + 展示列表:金额、日期、「确认收款」按钮 + │ + ▼ + 点击「确认收款」→ 需要 item.package + mchId + appId 调 wx.requestMerchantTransfer + │ 当前后端 list 里 package 为空,故会提示「请稍后刷新再试」 + └─ 若后续接入微信返回的 package,可在此完成「用户确认收款」闭环 +``` + +## 二、状态流转 + +| 阶段 | 状态 (status) | 含义 | +|--------------|----------------|------| +| 用户申请 | **pending** | 待审核,已占可提现额度 | +| 管理员通过 | **processing** | 已发起打款,微信处理中 | +| 微信回调成功 | **success** | 打款成功(已到账) | +| 微信回调失败/拒绝 | **failed** | 打款失败,写 fail_reason | +| 预留 | **pending_confirm** | 待用户确认收款(当前流程未改此状态,仅接口可返回) | + +## 三、可提现与待确认口径 + +- **可提现** = 累计佣金 − 已提现 − 待审核金额 + 待审核金额 = 所有 status 为 `pending`、`processing`、`pending_confirm` 的提现金额之和。 +- **待确认收款列表**:仅包含 **审核已通过** 的提现,即 status 为 `processing` 或 `pending_confirm`,不包含 `pending`。 + +## 四、主要接口与代码位置 + +| 环节 | 接口/行为 | 代码位置 | +|------------|-----------|----------| +| 用户申请 | POST `/api/miniprogram/withdraw` | soul-api `internal/handler/withdraw.go` WithdrawPost | +| 可提现计算 | referral/data、withdraw 校验 | `withdraw.go` computeAvailableWithdraw;`referral.go` 提现统计 | +| 管理端列表 | GET `/api/admin/withdrawals` | `internal/handler/admin_withdrawals.go` AdminWithdrawalsList | +| 管理端通过/拒绝 | PUT `/api/admin/withdrawals` | `admin_withdrawals.go` AdminWithdrawalsAction | +| 微信打款 | FundApp 单笔 | soul-api `internal/wechat/transfer.go` InitiateTransferByFundApp | +| 微信回调 | POST `/api/payment/wechat/transfer/notify` | `internal/handler/payment.go` PaymentWechatTransferNotify | +| 管理端同步 | POST `/api/admin/withdrawals/sync` | `admin_withdrawals.go` AdminWithdrawalsSync | +| 待确认列表 | GET `/api/miniprogram/withdraw/pending-confirm` | `withdraw.go` WithdrawPendingConfirm | + +## 五、说明 + +- 当前实现:审核通过后直接调微信 FundApp 单笔打款,最终由**微信回调**或**管理端同步**把状态更新为 success/failed。 +- 「待确认收款」列表只展示已审核通过的记录;点击「确认收款」需后端下发的 `package` 才能调起 `wx.requestMerchantTransfer`,目前该字段为空,前端会提示「请稍后刷新再试」。若后续接入微信返回的 package,可在此完成用户确认收款闭环。 diff --git a/开发文档/8、部署/商家转账.md b/开发文档/8、部署/商家转账.md new file mode 100644 index 00000000..dc2e15cb --- /dev/null +++ b/开发文档/8、部署/商家转账.md @@ -0,0 +1,40 @@ +# 商家转账 PowerWeChat 调用示例 + +> 来源:soul-api/商家转账.md。完整实现见 [提现功能完整技术文档](提现功能完整技术文档.md)。 + +--- + +## 请求示例(PowerWeChat) + +```go +req := &request.RequestTransferBills{ + Appid: "Appid", + OutBillNo: "OutBillNo", + TransferSceneId: "TransferSceneId", + Openid: "Openid", + UserName: "UserName", + TransferAmount: 1, + TransferRemark: "TransferRemark", + NotifyUrl: "NotifyUrl", + UserRecvPerception: "UserRecvPerception", + TransferSceneReportInfos: []request.TransferSceneReportInfo{ + { + InfoType: "InfoType", + InfoContent: "InfoContent", + }, + }, +} +ctx := c.Request.Context() +rs, err := services.PaymentApp.FundApp.TransferBills(ctx, req) +if err != nil { + panic(err) +} +c.JSON(http.StatusOK, rs) +``` + +--- + +## 相关文档 + +- [提现功能完整技术文档](提现功能完整技术文档.md) — 微信支付商家转账到零钱 API 集成 +- [分销提现流程图](分销提现流程图.md) — 提现业务流程图 diff --git a/开发文档/8、部署/提现功能完整技术文档.md b/开发文档/8、部署/提现功能完整技术文档.md new file mode 100644 index 00000000..457aa941 --- /dev/null +++ b/开发文档/8、部署/提现功能完整技术文档.md @@ -0,0 +1,1030 @@ +# 提现功能技术文档(微信支付API集成) + +> 来源:soul-api/提现功能完整技术文档.md。已整理至开发文档。 + +## 文档说明 + +本文档专注于**微信支付商家转账到零钱API**的集成方法,包括: +- 微信支付官方API文档 +- 签名生成算法 +- 加密解密算法 +- 完整代码实现 +- 测试验证方法 + +**适用场景**:实现用户提现功能,将资金从商户号转账到用户微信零钱。 + +--- + +## 目录 + +1. [业务场景](#业务场景) +2. [微信支付官方API文档](#微信支付官方api文档) +3. [前置准备](#前置准备) +4. [API集成](#api集成) +5. [签名算法](#签名算法) +6. [加密解密](#加密解密) +7. [代码实现](#代码实现) +8. [测试验证](#测试验证) + +--- + +## 业务场景 + +### 典型流程 + +``` +用户申请提现 + ↓ +系统审核通过 + ↓ +调用微信支付【商家转账到零钱API】 + ↓ +微信返回处理中(PROCESSING) + ↓ +微信异步处理(7-15秒) + ↓ +微信【主动回调】通知转账结果 + ↓ +系统接收回调,验签、解密 + ↓ +更新提现状态 + ↓ +用户确认收款 +``` + +### 关键步骤 + +1. **发起转账**:调用微信API发起转账 +2. **接收回调**:接收微信异步通知 +3. **验证签名**:验证回调的真实性 +4. **解密数据**:解密回调中的加密数据 +5. **查询状态**:主动查询转账状态 + +--- + +## 微信支付官方API文档 + +### 核心API + +| API名称 | 官方文档地址 | +|--------|------------| +| 🔥 **商家转账到零钱** | https://pay.weixin.qq.com/doc/v3/merchant/4012716434 | +| 📋 **查询转账单(商户单号)** | https://pay.weixin.qq.com/doc/v3/merchant/4012716456 | +| 📋 **查询转账单(微信单号)** | https://pay.weixin.qq.com/doc/v3/merchant/4012716457 | +| 🔐 **签名生成与验证** | https://pay.weixin.qq.com/doc/v3/merchant/4013053249 | +| 🔒 **敏感信息加密** | https://pay.weixin.qq.com/doc/v3/merchant/4012070130 | +| 🔓 **回调通知解密** | https://pay.weixin.qq.com/doc/v3/merchant/4012071382 | +| 📝 **转账场景报备** | https://pay.weixin.qq.com/doc/v3/merchant/4012716437 | +| ❌ **错误码查询** | https://pay.weixin.qq.com/doc/v3/merchant/4012070193 | +| 📜 **平台证书管理** | https://pay.weixin.qq.com/doc/v3/merchant/4012154180 | + +### 开发指引 + +- **API V3 开发总览**:https://pay.weixin.qq.com/doc/v3/merchant/4012065168 + + +--- + +## 前置准备 + +### 1. 获取配置信息 + +登录微信商户平台:https://pay.weixin.qq.com + +| 配置项 | 说明 | 获取路径 | +|-------|------|---------| +| **商户号(mch_id)** | 微信支付商户号 | 账户中心 → 商户信息 | +| **APIv3密钥(api_v3_key)** | 32字节密钥,用于加密解密 | 账户中心 → API安全 → 设置APIv3密钥 | +| **商户私钥(apiclient_key.pem)** | 用于请求签名 | 账户中心 → API安全 → 申请证书 | +| **证书序列号(cert_serial_no)** | 商户证书标识 | 从证书文件提取 | +| **平台证书(wechat_pay_pub_key)** | 用于验证回调签名 | 下载或通过API获取 | +| **小程序AppId** | 小程序标识 | 小程序管理后台 | + +### 2. 提取证书序列号 + +**使用OpenSSL命令**: + +```bash +openssl x509 -in apiclient_cert.pem -noout -serial +``` + +输出: +``` +serial=4A1DB62CD5C9BE0B6FC51C30621D6F99686E75C5 +``` + +**使用PHP**: + +```php + +``` + +### 3. 配置IP白名单 + +路径:微信商户平台 → 账户中心 → API安全 → IP配置 + +添加服务器公网IP地址。 + +**获取服务器IP**: + +```bash +curl ifconfig.me +``` + +### 4. 配置转账场景 + +路径:微信商户平台 → 产品中心 → 商家转账到零钱 → 前往功能 + +可选场景: +- **1000**:现金营销 +- **1005**:营销活动 + +**检查环境**: + + +--- + +## API集成 + +### 1. 商家转账到零钱API + +#### 基本信息 + +- **接口地址**:`https://api.mch.weixin.qq.com/v3/transfer/batches` +- **请求方法**:POST +- **Content-Type**:application/json + +#### 请求头 + +``` +Authorization: WECHATPAY2-SHA256-RSA2048 mchid="商户号",nonce_str="随机字符串",signature="签名",timestamp="时间戳",serial_no="证书序列号" +Content-Type: application/json +Accept: application/json +User-Agent: YourApp/1.0 +``` + +#### 请求参数 + +```json +{ + "appid": "wx6489c26045912fe1", + "out_batch_no": "BATCH202601291234567890", + "batch_name": "提现", + "batch_remark": "用户提现", + "total_amount": 5000, + "total_num": 1, + "transfer_detail_list": [ + { + "out_detail_no": "TX202601291234567890", + "transfer_amount": 5000, + "transfer_remark": "提现", + "openid": "odq3g5IOG-Z1WLpbeG_amUme8EZk" + } + ], + "transfer_scene_id": "1005", + "transfer_scene_report_infos": [ + { + "info_type": "岗位类型", + "info_content": "兼职人员" + }, + { + "info_type": "报酬说明", + "info_content": "当日兼职费" + } + ] +} +``` + +**参数说明**: + +| 字段 | 类型 | 必填 | 说明 | +|------|------|------|------| +| appid | string | 是 | 小程序AppId | +| out_batch_no | string | 是 | 商户批次单号,商户下唯一 | +| batch_name | string | 是 | 批次名称 | +| batch_remark | string | 是 | 批次备注 | +| total_amount | integer | 是 | 转账总金额,单位:**分** | +| total_num | integer | 是 | 转账总笔数 | +| transfer_detail_list | array | 是 | 转账明细列表 | +| transfer_scene_id | string | 是 | 转账场景ID:1000或1005 | +| transfer_scene_report_infos | array | 否 | 场景报备信息 | + +**transfer_detail_list说明**: + +| 字段 | 类型 | 必填 | 说明 | +|------|------|------|------| +| out_detail_no | string | 是 | 商户明细单号 | +| transfer_amount | integer | 是 | 转账金额,单位:**分** | +| transfer_remark | string | 是 | 转账备注 | +| openid | string | 是 | 收款用户OpenId | + +**场景报备信息(场景ID=1005)**: + +```json +[ + { + "info_type": "岗位类型", + "info_content": "兼职人员" + }, + { + "info_type": "报酬说明", + "info_content": "当日兼职费" + } +] +``` + +**重要**: +- `info_type` 必须是固定值 +- 金额单位是**分**:`元 * 100` + +#### 响应数据 + +**成功响应**: + +```json +{ + "out_batch_no": "BATCH202601291234567890", + "batch_id": "1030000071100999991182020050700019480001", + "create_time": "2026-01-29T12:30:00+08:00", + "batch_status": "PROCESSING" +} +``` + +**字段说明**: + +| 字段 | 说明 | +|------|------| +| out_batch_no | 商户批次单号 | +| batch_id | 微信批次单号 | +| create_time | 批次创建时间 | +| batch_status | 批次状态:PROCESSING/SUCCESS/FAIL | + +**失败响应**: + +```json +{ + "code": "PARAM_ERROR", + "message": "参数错误" +} +``` + +### 2. 查询转账单API + +#### 按商户单号查询 + +**接口地址**: + +``` +GET https://api.mch.weixin.qq.com/v3/transfer/batches/batch-id/{batch_id}/details/detail-id/{detail_id} +``` + +**路径参数**: +- `batch_id`:商户批次单号(需URL编码) +- `detail_id`:商户明细单号(需URL编码) + +**示例**: + +``` +GET /v3/transfer/batches/batch-id/BATCH202601291234567890/details/detail-id/TX202601291234567890 +``` + +**响应示例**: + +```json +{ + "mchid": "1318592501", + "out_batch_no": "BATCH202601291234567890", + "batch_id": "1030000071100999991182020050700019480001", + "out_detail_no": "TX202601291234567890", + "detail_id": "1040000071100999991182020050700019500100", + "detail_status": "SUCCESS", + "transfer_amount": 5000, + "transfer_remark": "提现", + "openid": "odq3g5IOG-Z1WLpbeG_amUme8EZk", + "initiate_time": "2026-01-29T12:30:00+08:00", + "update_time": "2026-01-29T12:30:15+08:00" +} +``` + +**状态说明**: + +| detail_status | 说明 | +|--------------|------| +| PROCESSING | 转账中 | +| SUCCESS | 转账成功 | +| FAIL | 转账失败 | + +### 3. 转账结果通知(回调) + +#### 回调触发 + +当转账状态变更时,微信支付会主动向配置的 `notify_url` 发送POST请求。 + +#### 回调请求头 + +``` +Wechatpay-Signature: 签名值 +Wechatpay-Timestamp: 1769653396 +Wechatpay-Nonce: R0PDA5lOV3IMrBjrvbCH5U4L3Lb0gg8L +Wechatpay-Serial: 642B2B33557205BA79A1CFF08EA2A2478D67BD63 +Wechatpay-Signature-Type: WECHATPAY2-SHA256-RSA2048 +Content-Type: application/json +``` + +#### 回调请求体(加密) + +```json +{ + "id": "cb29e425-ca17-59fb-8045-8e5b58917154", + "create_time": "2026-01-29T10:23:11+08:00", + "resource_type": "encrypt-resource", + "event_type": "MCHTRANSFER.BILL.FINISHED", + "summary": "商家转账单据终态通知", + "resource": { + "original_type": "mch_payment", + "algorithm": "AEAD_AES_256_GCM", + "ciphertext": "加密的数据...", + "associated_data": "mch_payment", + "nonce": "随机字符串" + } +} +``` + +#### 解密后的数据 + +```json +{ + "mch_id": "1318592501", + "out_bill_no": "TX202601291234567890", + "transfer_bill_no": "1330000114850082601290057112302122", + "transfer_amount": 5000, + "state": "SUCCESS", + "openid": "odq3g5IOG-Z1WLpbeG_amUme8EZk", + "create_time": "2026-01-29T12:30:00+08:00", + "update_time": "2026-01-29T12:30:15+08:00" +} +``` + +**state状态说明**: + +| state | 说明 | +|-------|------| +| PROCESSING | 转账中 | +| SUCCESS | 转账成功 | +| FAIL | 转账失败 | +| WAIT_USER_CONFIRM | 待用户确认 | +| TRANSFERING | 正在转账 | + +#### 回调响应 + +处理完成后,返回给微信: + +```json +{ + "code": "SUCCESS" +} +``` + +--- + +## 签名算法 + +### 1. 签名生成(请求签名) + +#### 签名串格式 + +``` +请求方法\n +请求URL路径\n +请求时间戳\n +随机字符串\n +请求报文主体\n +``` + +**示例**: + +``` +POST +/v3/transfer/batches +1234567890 +RandomString123456 +{"appid":"wx6489c26045912fe1"} +``` + +**重要**:每部分末尾都有 `\n` 换行符。 + +#### 签名步骤 + +1. 构建签名串 +2. 使用商户私钥进行SHA256withRSA签名 +3. 对签名结果进行Base64编码 + +#### PHP实现 + +```php +function buildSignature($method, $url, $timestamp, $nonce, $body, $privateKeyPath) { + // 1. 构建签名串 + $signStr = $method . "\n" + . $url . "\n" + . $timestamp . "\n" + . $nonce . "\n" + . $body . "\n"; + + // 2. 加载私钥 + $privateKeyContent = file_get_contents($privateKeyPath); + $privateKeyResource = openssl_pkey_get_private($privateKeyContent); + + // 3. 使用私钥签名 + openssl_sign($signStr, $signature, $privateKeyResource, 'sha256WithRSAEncryption'); + + // 4. Base64编码 + return base64_encode($signature); +} +``` + +#### 构建Authorization头 + +```php +function buildAuthorization($mchId, $timestamp, $nonce, $signature, $serialNo) { + return sprintf( + 'WECHATPAY2-SHA256-RSA2048 mchid="%s",nonce_str="%s",signature="%s",timestamp="%d",serial_no="%s"', + $mchId, + $nonce, + $signature, + $timestamp, + $serialNo + ); +} +``` + +### 2. 签名验证(回调验签) + +#### 验签串格式 + +``` +时间戳\n +随机字符串\n +请求报文主体\n +``` + +**示例**: + +``` +1769653396 +R0PDA5lOV3IMrBjrvbCH5U4L3Lb0gg8L +{"id":"cb29e425-ca17-59fb-8045-8e5b58917154",...} +``` + +#### PHP实现 + +```php +function verifySignature($timestamp, $nonce, $body, $signature, $publicKeyPath) { + // 1. 构建验签串 + $verifyStr = $timestamp . "\n" + . $nonce . "\n" + . $body . "\n"; + + // 2. Base64解码签名 + $signatureDecode = base64_decode($signature); + + // 3. 加载平台公钥 + $publicKeyContent = file_get_contents($publicKeyPath); + $publicKeyResource = openssl_pkey_get_public($publicKeyContent); + + // 4. 验证签名 + $result = openssl_verify( + $verifyStr, + $signatureDecode, + $publicKeyResource, + 'sha256WithRSAEncryption' + ); + + return $result === 1; // 1表示验证成功 +} +``` + +**重要**:验签使用的是**微信支付平台公钥**,不是商户私钥! + +--- + +## 加密解密 + +### 回调数据解密 + +#### 算法信息 + +- **算法**:AEAD_AES_256_GCM +- **密钥**:APIv3密钥(32字节) +- **密文格式**:实际密文 + 认证标签(16字节) + +#### 解密步骤 + +1. 提取加密数据(ciphertext、nonce、associated_data) +2. Base64解码密文 +3. 分离密文和认证标签(最后16字节) +4. 使用AES-256-GCM解密 +5. 解析JSON数据 + +#### PHP实现 + +```php +function decryptCallbackData($ciphertext, $nonce, $associatedData, $apiV3Key) { + // 1. 检查APIv3密钥长度(必须32字节) + if (strlen($apiV3Key) !== 32) { + throw new Exception('APIv3密钥长度必须为32字节'); + } + + // 2. Base64解码密文 + $ciphertextDecoded = base64_decode($ciphertext); + + // 3. 分离密文和认证标签 + $authTag = substr($ciphertextDecoded, -16); + $ctext = substr($ciphertextDecoded, 0, -16); + + // 4. 使用AES-256-GCM解密 + $decrypted = openssl_decrypt( + $ctext, // 密文 + 'aes-256-gcm', // 算法 + $apiV3Key, // 密钥 + OPENSSL_RAW_DATA, // 选项 + $nonce, // 随机串 + $authTag, // 认证标签 + $associatedData // 附加数据 + ); + + if ($decrypted === false) { + throw new Exception('解密失败'); + } + + // 5. 解析JSON + return json_decode($decrypted, true); +} +``` + +**使用示例**: + +```php +$resource = $callbackData['resource']; +$decrypted = decryptCallbackData( + $resource['ciphertext'], + $resource['nonce'], + $resource['associated_data'], + 'wx3e31b068be59ddc131b068be59ddc2' // APIv3密钥 +); +``` + +--- + +## 代码实现 + +### 完整的微信支付转账类 + +```php +mchId = $config['mch_id']; + $this->appId = $config['app_id']; + $this->apiV3Key = $config['api_v3_key']; + $this->certSerialNo = $config['cert_serial_no']; + + // 加载私钥 + $privateKeyContent = file_get_contents($config['private_key']); + $this->privateKey = openssl_pkey_get_private($privateKeyContent); + } + + /** + * 发起转账 + */ + public function createTransfer($params) + { + $url = '/v3/transfer/batches'; + $method = 'POST'; + + // 构建请求数据 + $data = [ + 'appid' => $this->appId, + 'out_batch_no' => 'BATCH' . date('YmdHis') . mt_rand(1000, 9999), + 'batch_name' => $params['batch_name'] ?? '提现', + 'batch_remark' => $params['batch_remark'] ?? '用户提现', + 'total_amount' => $params['transfer_amount'], + 'total_num' => 1, + 'transfer_detail_list' => [ + [ + 'out_detail_no' => $params['out_detail_no'], + 'transfer_amount' => $params['transfer_amount'], + 'transfer_remark' => $params['transfer_remark'], + 'openid' => $params['openid'], + ] + ], + 'transfer_scene_id' => $params['transfer_scene_id'] ?? '1005', + ]; + + // 添加场景报备信息 + if (!empty($params['transfer_scene_report_infos'])) { + $data['transfer_scene_report_infos'] = $params['transfer_scene_report_infos']; + } + + $body = json_encode($data, JSON_UNESCAPED_UNICODE); + + // 生成签名 + $timestamp = time(); + $nonce = $this->generateNonce(); + $signature = $this->buildSignature($method, $url, $timestamp, $nonce, $body); + + // 构建Authorization + $authorization = $this->buildAuthorization($timestamp, $nonce, $signature); + + // 发送请求 + return $this->request($method, $url, $body, $authorization); + } + + /** + * 查询转账单 + */ + public function queryTransfer($batchNo, $detailNo) + { + $url = "/v3/transfer/batches/batch-id/" . urlencode($batchNo) + . "/details/detail-id/" . urlencode($detailNo); + $method = 'GET'; + + $timestamp = time(); + $nonce = $this->generateNonce(); + $signature = $this->buildSignature($method, $url, $timestamp, $nonce, ''); + $authorization = $this->buildAuthorization($timestamp, $nonce, $signature); + + return $this->request($method, $url, '', $authorization); + } + + /** + * 验证回调签名 + */ + public function verifyCallback($headers, $body, $publicKey) + { + $timestamp = $headers['wechatpay-timestamp']; + $nonce = $headers['wechatpay-nonce']; + $signature = $headers['wechatpay-signature']; + + $verifyStr = $timestamp . "\n" . $nonce . "\n" . $body . "\n"; + $signatureDecode = base64_decode($signature); + + $publicKeyContent = file_get_contents($publicKey); + $publicKeyResource = openssl_pkey_get_public($publicKeyContent); + + $result = openssl_verify($verifyStr, $signatureDecode, $publicKeyResource, 'sha256WithRSAEncryption'); + + return $result === 1; + } + + /** + * 解密回调数据 + */ + public function decryptCallbackResource($resource) + { + $ciphertext = $resource['ciphertext']; + $nonce = $resource['nonce']; + $associatedData = $resource['associated_data']; + + if (strlen($this->apiV3Key) !== 32) { + throw new \Exception('APIv3密钥长度必须为32字节'); + } + + $ciphertextDecoded = base64_decode($ciphertext); + $authTag = substr($ciphertextDecoded, -16); + $ctext = substr($ciphertextDecoded, 0, -16); + + $decrypted = openssl_decrypt( + $ctext, + 'aes-256-gcm', + $this->apiV3Key, + OPENSSL_RAW_DATA, + $nonce, + $authTag, + $associatedData + ); + + if ($decrypted === false) { + throw new \Exception('解密失败'); + } + + return json_decode($decrypted, true); + } + + /** + * 生成签名 + */ + private function buildSignature($method, $url, $timestamp, $nonce, $body) + { + $signStr = $method . "\n" + . $url . "\n" + . $timestamp . "\n" + . $nonce . "\n" + . $body . "\n"; + + openssl_sign($signStr, $signature, $this->privateKey, 'sha256WithRSAEncryption'); + + return base64_encode($signature); + } + + /** + * 构建Authorization头 + */ + private function buildAuthorization($timestamp, $nonce, $signature) + { + return sprintf( + 'WECHATPAY2-SHA256-RSA2048 mchid="%s",nonce_str="%s",signature="%s",timestamp="%d",serial_no="%s"', + $this->mchId, + $nonce, + $signature, + $timestamp, + $this->certSerialNo + ); + } + + /** + * 生成随机字符串 + */ + private function generateNonce($length = 32) + { + $chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'; + $nonce = ''; + for ($i = 0; $i < $length; $i++) { + $nonce .= $chars[mt_rand(0, strlen($chars) - 1)]; + } + return $nonce; + } + + /** + * 发送HTTP请求 + */ + private function request($method, $url, $body, $authorization) + { + $fullUrl = 'https://api.mch.weixin.qq.com' . $url; + + $headers = [ + 'Authorization: ' . $authorization, + 'Content-Type: application/json', + 'Accept: application/json', + 'User-Agent: YourApp/1.0' + ]; + + $ch = curl_init(); + curl_setopt($ch, CURLOPT_URL, $fullUrl); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true); + curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2); + curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); + + if ($method === 'POST') { + curl_setopt($ch, CURLOPT_POST, true); + curl_setopt($ch, CURLOPT_POSTFIELDS, $body); + } + + $response = curl_exec($ch); + $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); + curl_close($ch); + + $result = json_decode($response, true); + + if ($httpCode >= 200 && $httpCode < 300) { + return ['success' => true, 'data' => $result]; + } else { + return [ + 'success' => false, + 'error_code' => $result['code'] ?? 'UNKNOWN', + 'error_msg' => $result['message'] ?? '未知错误' + ]; + } + } +} +``` + +### 使用示例 + +#### 1. 发起转账 + +```php +// 初始化配置 +$config = [ + 'mch_id' => '1318592501', + 'app_id' => 'wx6489c26045912fe1', + 'api_v3_key' => 'wx3e31b068be59ddc131b068be59ddc2', + 'private_key' => '/path/to/apiclient_key.pem', + 'cert_serial_no' => '4A1DB62CD5C9BE0B6FC51C30621D6F99686E75C5', +]; + +$wechatPay = new WechatPayTransfer($config); + +// 发起转账 +$result = $wechatPay->createTransfer([ + 'out_detail_no' => 'TX' . date('YmdHis') . mt_rand(1000, 9999), + 'transfer_amount' => 5000, // 50元 = 5000分 + 'transfer_remark' => '提现', + 'openid' => 'odq3g5IOG-Z1WLpbeG_amUme8EZk', + 'transfer_scene_id' => '1005', + 'transfer_scene_report_infos' => [ + ['info_type' => '岗位类型', 'info_content' => '兼职人员'], + ['info_type' => '报酬说明', 'info_content' => '当日兼职费'], + ], +]); + +if ($result['success']) { + echo "转账成功: " . json_encode($result['data']); +} else { + echo "转账失败: " . $result['error_msg']; +} +``` + +#### 2. 查询转账单 + +```php +$result = $wechatPay->queryTransfer('BATCH202601291234567890', 'TX202601291234567890'); + +if ($result['success']) { + echo "状态: " . $result['data']['detail_status']; +} else { + echo "查询失败: " . $result['error_msg']; +} +``` + +#### 3. 处理回调 + +```php +// 接收回调 +$headers = [ + 'wechatpay-signature' => $_SERVER['HTTP_WECHATPAY_SIGNATURE'], + 'wechatpay-timestamp' => $_SERVER['HTTP_WECHATPAY_TIMESTAMP'], + 'wechatpay-nonce' => $_SERVER['HTTP_WECHATPAY_NONCE'], + 'wechatpay-serial' => $_SERVER['HTTP_WECHATPAY_SERIAL'], +]; + +$body = file_get_contents('php://input'); +$callbackData = json_decode($body, true); + +// 验证签名 +$verified = $wechatPay->verifyCallback($headers, $body, '/path/to/wechat_pay_pub_key.pem'); + +if ($verified) { + // 解密数据 + $decrypted = $wechatPay->decryptCallbackResource($callbackData['resource']); + + // 处理转账结果 + if ($decrypted['state'] === 'SUCCESS') { + echo "转账成功: " . $decrypted['out_bill_no']; + } + + // 返回成功 + echo json_encode(['code' => 'SUCCESS']); +} else { + echo json_encode(['code' => 'FAIL', 'message' => '签名验证失败']); +} +``` + +--- + +## 测试验证 + +### 1. 签名生成测试 + +```php +$method = 'POST'; +$url = '/v3/transfer/batches'; +$timestamp = time(); +$nonce = 'RandomString123456'; +$body = '{"appid":"wx6489c26045912fe1"}'; + +$signature = buildSignature($method, $url, $timestamp, $nonce, $body, 'apiclient_key.pem'); + +echo "签名: " . $signature . "\n"; +``` + +### 2. 小额转账测试 + +```php +// 测试金额:0.01元 = 1分 +$result = $wechatPay->createTransfer([ + 'out_detail_no' => 'TEST' . time(), + 'transfer_amount' => 1, // 1分 + 'transfer_remark' => '测试', + 'openid' => 'test_openid', + 'transfer_scene_id' => '1005', + 'transfer_scene_report_infos' => [ + ['info_type' => '岗位类型', 'info_content' => '测试'], + ['info_type' => '报酬说明', 'info_content' => '测试'], + ], +]); +``` + +### 3. 解密测试 + +```php +$resource = [ + 'ciphertext' => 'xxx', + 'nonce' => 'xxx', + 'associated_data' => 'mch_payment', +]; + +try { + $decrypted = decryptCallbackData( + $resource['ciphertext'], + $resource['nonce'], + $resource['associated_data'], + 'wx3e31b068be59ddc131b068be59ddc2' + ); + print_r($decrypted); +} catch (Exception $e) { + echo "解密失败: " . $e->getMessage(); +} +``` + +### 4. 常见问题 + +| 问题 | 原因 | 解决方法 | +|------|------|---------| +| 签名验证失败 | 证书序列号错误 | 重新提取证书序列号 | +| IP白名单错误 | 服务器IP未配置 | 添加到微信商户平台 | +| 解密失败 | APIv3密钥错误 | 检查密钥长度(32字节) | +| 场景报备错误 | info_type不正确 | 使用固定值 | +| 余额不足 | 商户号余额不足 | 充值商户号 | + +--- + +## 附录 + +### A. 错误码对照表 + +https://pay.weixin.qq.com/doc/v3/merchant/4012070193 + +| 错误码 | 说明 | 处理建议 | +|-------|------|---------| +| PARAM_ERROR | 参数错误 | 检查请求参数格式 | +| NOTENOUGH | 商户余额不足 | 充值商户号 | +| INVALID_REQUEST | 不符合业务规则 | 检查业务逻辑 | +| SYSTEM_ERROR | 系统错误 | 稍后重试 | +| FREQUENCY_LIMITED | 频率限制 | 降低请求频率 | +| APPID_MCHID_NOT_MATCH | appid和mch_id不匹配 | 检查配置 | + +### B. 转账状态说明 + +| 状态 | 说明 | 处理方式 | +|------|------|---------| +| PROCESSING | 转账中 | 等待回调或主动查询 | +| SUCCESS | 转账成功 | 完成流程 | +| FAIL | 转账失败 | 检查失败原因 | +| WAIT_USER_CONFIRM | 待用户确认 | 等待用户操作 | +| TRANSFERING | 正在转账 | 等待处理完成 | + +### C. 开发工具 + +- **Postman**:API测试工具 +- **OpenSSL**:证书和密钥管理 +- **微信支付调试工具**:https://pay.weixin.qq.com/ + +--- + +**文档版本**:v3.0(纯微信支付API版) +**更新时间**:2026-01-29 +**适用场景**:微信支付商家转账到零钱功能集成 + +--- + +## 总结 + +本文档提供了微信支付转账功能的完整集成方案: + +✅ **3个核心API** +- 发起转账:`POST /v3/transfer/batches` +- 查询转账:`GET /v3/transfer/batches/batch-id/{batch_id}/details/detail-id/{detail_id}` +- 接收回调:异步通知 + +✅ **3个核心算法** +- 签名生成:SHA256withRSA + Base64 +- 签名验证:使用平台公钥 +- 数据解密:AEAD_AES_256_GCM + +✅ **完整代码实现** +- WechatPayTransfer类(可直接使用) +- 包含发起转账、查询、验签、解密全部功能 + +根据本文档可以快速集成微信支付转账功能。 + +--- + +## 相关文档(开发文档内) + +- [分销提现流程图](分销提现流程图.md) — 提现业务流程图 +- [订阅消息](订阅消息.md) — 提现成功订阅消息 +- [商家转账](商家转账.md) — PowerWeChat 调用示例 diff --git a/开发文档/8、部署/订阅消息.md b/开发文档/8、部署/订阅消息.md new file mode 100644 index 00000000..924640e1 --- /dev/null +++ b/开发文档/8、部署/订阅消息.md @@ -0,0 +1,43 @@ +# 提现订阅消息(PowerWeChat) + +> 来源:soul-api/订阅消息.md。提现成功后向用户发送订阅消息。 + +--- + +## 数据结构示例 + +```go +data := &power.HashMap{ + "phrase4": power.StringMap{ + "value": "提现成功", // 提现结果:提现成功、提现失败 + }, + "amount5": power.StringMap{ + "value": "¥8.6", // 提现金额 + }, + "thing8": power.StringMap{ + "value": "微信打款成功,请点击查收", // 备注,打款失败则提示请联系官方客服 + }, +} +MiniProgramApp.SubscribeMessage.Send(ctx, &request.RequestSubscribeMessageSend{ + ToUser: "OPENID", // 根据订单号联表查询,提现表 user_id 即 openid + TemplateID: "u3MbZGPRkrZIk-I7QdpwzFxnO_CeQPaCWF2FkiIablE", + Page: "/pages/my/my", + // developer=开发版;trial=体验版;formal=正式版 + // 开发环境 souldev.quwanzhi.com,正式环境 soulapi.quwanzhi.com + MiniProgramState: "formal", + Lang: "zh_CN", + Data: data, +}) +``` + +## 回调示例(转账结果) + +```json +{ + "create_time": "2026-02-10T18:02:54+08:00", + "out_bill_no": "WD1770691555206100", + "package_info": "ABBQO+oYAAABAAAAAAAk+...", + "state": "WAIT_USER_CONFIRM", + "transfer_bill_no": "1330000114850082602100071440076263" +} +``` diff --git a/开发文档/8、部署/部署总览.md b/开发文档/8、部署/部署总览.md index c995c017..0add6dce 100644 --- a/开发文档/8、部署/部署总览.md +++ b/开发文档/8、部署/部署总览.md @@ -36,7 +36,10 @@ | [章节阅读付费标准流程设计](章节阅读付费标准流程设计.md) | 阅读页付费流程 | | [阅读页标准流程改造说明](阅读页标准流程改造说明.md) | 阅读页改造要点 | | [支付接口清单](支付接口清单.md) | 支付相关接口列表 | -| [提现功能完整技术文档](../../soul-api/提现功能完整技术文档.md) | 微信支付商家转账到零钱 API 集成(soul-api 目录) | +| [提现功能完整技术文档](提现功能完整技术文档.md) | 微信支付商家转账到零钱 API 集成 | +| [分销提现流程图](分销提现流程图.md) | 提现业务流程图(申请→审核→打款→回调) | +| [订阅消息](订阅消息.md) | 提现成功订阅消息(PowerWeChat 示例) | +| [商家转账](商家转账.md) | PowerWeChat RequestTransferBills 调用示例 | --- diff --git a/开发文档/README.md b/开发文档/README.md index 1f59b173..b4f3df43 100644 --- a/开发文档/README.md +++ b/开发文档/README.md @@ -28,6 +28,7 @@ | 文档 | 说明 | |------|------| | [2、架构/系统与技术](2、架构/系统与技术.md) | 系统与技术栈 | +| [2、架构/soul-api技术栈](2、架构/soul-api技术栈.md) | soul-api Go 技术栈(Gin、GORM、PowerWeChat、JWT) | | [2、架构/链路与变现](2、架构/链路与变现.md) | 业务链路 | | [4、前端/前端开发规范](4、前端/前端开发规范.md) | 前端规范 | | [6、后端/后端开发规范](6、后端/后端开发规范.md) | 后端规范 | @@ -38,6 +39,10 @@ |------|------| | [5、接口/API接口完整文档](5、接口/API接口完整文档.md) | API 完整文档 | | [8、部署/部署总览](8、部署/部署总览.md) | 部署入口、分销与流程 | +| [8、部署/提现功能完整技术文档](8、部署/提现功能完整技术文档.md) | 微信支付商家转账到零钱 API 集成 | +| [8、部署/分销提现流程图](8、部署/分销提现流程图.md) | 提现业务流程图 | +| [8、部署/订阅消息](8、部署/订阅消息.md) | 提现成功订阅消息 | +| [8、部署/商家转账](8、部署/商家转账.md) | PowerWeChat 商家转账示例 | ### 临时需求池