2026-02-05 11:35:57 +08:00
|
|
|
|
# 当前小程序开发细则
|
|
|
|
|
|
|
|
|
|
|
|
> 汇总当前 Soul 创业派对小程序的架构、经验与规划,便于新人上手与后续迭代。
|
|
|
|
|
|
> 最后整理:2026-02
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 一、概述与定位
|
|
|
|
|
|
|
|
|
|
|
|
- **产品**:Soul 创业派对 — 微信小程序,内容为《一场 SOUL 的创业实验场》章节阅读 + 找伙伴 + 分销。
|
|
|
|
|
|
- **技术**:原生微信小程序(非 uni-app / Taro),与 Next.js 后端同仓,接口统一走 `apiBase`(如 `https://soul.quwanzhi.com`)。
|
|
|
|
|
|
- **核心能力**:章节阅读(免费/付费)、单章/全书支付、邀请码分销、找伙伴(匹配次数购买)、推广中心、我的订单/设置。
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 二、目录与页面结构
|
|
|
|
|
|
|
|
|
|
|
|
### 2.1 目录结构(miniprogram/)
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
miniprogram/
|
|
|
|
|
|
├── app.js / app.json / app.wxss # 入口、全局配置、样式
|
|
|
|
|
|
├── custom-tab-bar/ # 自定义底部 tabBar
|
|
|
|
|
|
├── pages/
|
|
|
|
|
|
│ ├── index/ # 首页(推荐章节、已读统计)
|
|
|
|
|
|
│ ├── chapters/ # 目录(全书章节列表)
|
|
|
|
|
|
│ ├── read/ # 阅读页(核心:权限、支付、分享)
|
|
|
|
|
|
│ ├── match/ # 找伙伴(匹配 + 购买次数)
|
|
|
|
|
|
│ ├── my/ # 我的(入口:订单、推广、设置)
|
|
|
|
|
|
│ ├── referral/ # 推广中心(邀请码、收益、海报)
|
|
|
|
|
|
│ ├── purchases/ # 我的订单(当前为本地已购章节列表)
|
|
|
|
|
|
│ ├── settings/ # 设置(提现、绑定账号等)
|
|
|
|
|
|
│ ├── search/ # 搜索
|
|
|
|
|
|
│ ├── about/ # 关于
|
|
|
|
|
|
│ └── addresses/ # 地址(若启用)
|
|
|
|
|
|
├── utils/
|
|
|
|
|
|
│ ├── chapterAccessManager.js # 章节权限与状态
|
|
|
|
|
|
│ ├── readingTracker.js # 阅读进度追踪
|
|
|
|
|
|
│ ├── payment.js # 旧支付封装(部分场景仍用)
|
|
|
|
|
|
│ └── util.js
|
|
|
|
|
|
└── assets/ # 图标等静态资源
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 2.2 TabBar 与主要页面
|
|
|
|
|
|
|
|
|
|
|
|
| Tab | 页面 | 说明 |
|
|
|
|
|
|
|-----|------|------|
|
|
|
|
|
|
| 首页 | pages/index/index | 推荐章节、已读/待读、入口到阅读 |
|
|
|
|
|
|
| 目录 | pages/chapters/chapters | 全书章节列表 |
|
|
|
|
|
|
| 找伙伴 | pages/match/match | 匹配 + 购买匹配次数 |
|
|
|
|
|
|
| 我的 | pages/my/my | 已读/已购、推广中心、订单、设置 |
|
|
|
|
|
|
|
|
|
|
|
|
非 Tab 页:阅读页 read、推广中心 referral、订单 purchases、设置 settings、搜索 search、关于 about。
|
|
|
|
|
|
|
|
|
|
|
|
### 2.3 全局状态(app.js globalData)
|
|
|
|
|
|
|
|
|
|
|
|
- `userInfo`:登录后用户信息(id、openId、nickname、purchasedSections、hasFullBook、referralCode、referralCount 等)。
|
|
|
|
|
|
- `openId` / `isLoggedIn`:微信登录态。
|
|
|
|
|
|
- `readSectionIds`:已读章节 ID 列表(有权限打开全文时打点)。
|
|
|
|
|
|
- `pendingReferralCode`:待绑定推荐码(带 ref 进入时写入,登录后绑定)。
|
|
|
|
|
|
- `apiBase`:后端 API 根地址。
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 三、核心流程与经验
|
|
|
|
|
|
|
|
|
|
|
|
### 3.1 阅读与章节权限
|
|
|
|
|
|
|
|
|
|
|
|
- **权威数据源**:章节是否可读以**服务端**为准(`/api/user/check-purchased`、`/api/user/purchase-status`),不依赖前端缓存做最终判断。
|
|
|
|
|
|
- **权限状态**:设计上支持 `unknown / free / locked_not_login / locked_not_purchased / unlocked_purchased / error`(见《章节阅读付费标准流程设计》);阅读页通过 `chapterAccessManager` 与 `determineAccessState` 等做状态判断。
|
|
|
|
|
|
- **免费章节**:来自后端配置(如 `/api/db/config` 的 freeChapters),页面 onLoad 时拉取最新免费列表再判断;首帧可用本地默认 freeIds,拉取完成后需能刷新当前章状态,避免竞态误判。
|
|
|
|
|
|
- **已读 vs 已购**:
|
|
|
|
|
|
- **已读**:仅统计“有权限打开并看到全文”的章节(`canAccess=true` 时 `app.markSectionAsRead(sectionId)`),存 `readSectionIds`。
|
|
|
|
|
|
- **已购**:来自服务端 `userInfo.purchasedSections`、`hasFullBook` 及 orders 表,用于付费墙与购买按钮展示。
|
|
|
|
|
|
- **登录后防误解锁**:登录成功(含支付流程中登录)后必须 `refreshPurchaseFromServer()`,再对当前章节做 `recheckCurrentSectionAndRefresh()`(先拉最新免费列表,再请求 check-purchased),避免“刚登录”时误用旧缓存解锁付费章。
|
|
|
|
|
|
- **内容接口**:当前 `GET /api/book/chapter/[id]` 不校验登录与购买,前端按 `canAccess` 控制展示全文或预览;若未来开放 Web/API,建议章节接口侧做鉴权。
|
|
|
|
|
|
|
2026-02-06 12:29:56 +08:00
|
|
|
|
详见:`开发文档/8、部署/章节阅读付费标准流程设计.md`。
|
2026-02-05 11:35:57 +08:00
|
|
|
|
|
|
|
|
|
|
### 3.2 支付流程(章节 + 找伙伴)
|
|
|
|
|
|
|
|
|
|
|
|
- **统一入口**:章节支付 `pages/read/read.js` 调 `POST /api/miniprogram/pay`;找伙伴支付 `pages/match/match.js` 同样调该接口,传 `productType: 'match'`。
|
|
|
|
|
|
- **订单先行**:支付前**必须先创建订单**并插入 `orders` 表(status=`created`),再调微信统一下单;即使插库失败也继续支付流程,避免用户卡在“创建订单失败”。
|
|
|
|
|
|
- **请求体约定**:`openId`、`userId`、`productType`(section/fullbook/match)、`productId`、`amount`、`description`;**必须带 `referralCode`**(见下节)。
|
|
|
|
|
|
- **支付成功**:依赖微信回调 `POST /api/miniprogram/pay/notify` 更新订单为 `paid`、解锁用户权限、分佣、清理同产品未支付订单;前端支付成功后调用 `refreshUserPurchaseStatus()` 再 `initSection()` 刷新当前页。
|
2026-02-06 12:29:56 +08:00
|
|
|
|
- **兜底**:若回调丢失,依赖**订单状态同步定时任务**(如每 5 分钟调 `GET /api/cron/sync-orders`)查询微信侧状态并同步到本地 orders,保证最终一致。详见 `开发文档/8、部署/宝塔面板配置订单同步定时任务.md`。
|
2026-02-05 11:35:57 +08:00
|
|
|
|
|
|
|
|
|
|
### 3.3 邀请码与分销(必传、必记)
|
|
|
|
|
|
|
|
|
|
|
|
- **绑定逻辑**:带 `ref` 或 `referralCode` 的链接进入 → `app.js` 的 `handleReferralCode` 写入 `pendingReferralCode` 并**同步写入 `referral_code`**(`wx.setStorageSync('referral_code', refCode)`);登录后调用 `/api/referral/bind` 完成绑定(30 天有效、可续期/抢夺)。
|
|
|
|
|
|
- **支付必带邀请码**:章节支付、找伙伴支付创建订单时都要传 `referralCode`,来源为 `wx.getStorageSync('referral_code')`;后端据此(或先查 referral_bindings)写入订单的 `referrer_id` 与 **`referral_code`**(下单时使用的邀请码,便于对账与后台展示)。
|
|
|
|
|
|
- **订单表字段**:`orders.referrer_id`(推荐人用户ID)、`orders.referral_code`(下单时邀请码)。若表尚未加字段,需执行 `scripts/add_orders_referrer_id.py`、`scripts/add_orders_referral_code.py`。
|
|
|
|
|
|
- **推荐人 vs 邀请码**:全局只认「推荐人 = 用户ID」;邀请码仅用于解析出 referrer_id,不会混用。分佣以 `referral_bindings` 为准,不依赖订单上的 referrer_id。详见 `开发文档/8、部署/邀请码分销规则说明.md`。
|
|
|
|
|
|
|
|
|
|
|
|
### 3.4 分享与落地
|
|
|
|
|
|
|
|
|
|
|
|
- 阅读页分享:`onShareAppMessage` / `onShareTimeline` 带 `id=章节ID&ref=当前用户邀请码`,落地后 ref 写入 storage,绑定与订单归属同上。
|
|
|
|
|
|
- 文章/章节分销与全局同一套:不按“哪篇文章带来”单独分成或统计,仅按“谁发的链接(ref=谁)”归属。
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 四、数据与接口约定
|
|
|
|
|
|
|
|
|
|
|
|
### 4.1 关键接口
|
|
|
|
|
|
|
|
|
|
|
|
| 接口 | 用途 |
|
|
|
|
|
|
|------|------|
|
|
|
|
|
|
| POST /api/miniprogram/login | 微信登录,返回 userInfo(含 purchasedSections、referralCode 等) |
|
|
|
|
|
|
| GET /api/user/purchase-status | 拉取购买状态(已购章节、全书) |
|
|
|
|
|
|
| GET /api/user/check-purchased | 校验指定章节/全书是否已购买 |
|
|
|
|
|
|
| POST /api/miniprogram/pay | 创建订单 + 微信预支付,**需传 referralCode** |
|
|
|
|
|
|
| POST /api/miniprogram/pay/notify | 微信支付回调(服务端) |
|
|
|
|
|
|
| GET /api/cron/sync-orders | 订单状态同步(定时任务,需 secret) |
|
|
|
|
|
|
| POST /api/referral/bind | 绑定推荐关系 |
|
|
|
|
|
|
| GET /api/db/config | 免费章节等配置 |
|
|
|
|
|
|
|
|
|
|
|
|
### 4.2 Storage 约定
|
|
|
|
|
|
|
|
|
|
|
|
- `referral_code`:落地 ref 或 app 检测到 ref 时写入;支付时读取并传后端。
|
|
|
|
|
|
- `pendingReferralCode` / `boundReferralCode`:待绑定/已绑定推荐码(app 层)。
|
|
|
|
|
|
- `readSectionIds`:已读章节 ID 列表。
|
|
|
|
|
|
- `openId`、用户信息等由 app 与登录逻辑维护。
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 五、已知问题与修复要点
|
|
|
|
|
|
|
|
|
|
|
|
- **免费章节配置竞态**:onLoad 时若未 await 免费列表再 initSection,首帧可能用默认 freeIds 误判;建议先拉配置再判断当前章,或拉取完成后对当前页再刷一次权限。
|
|
|
|
|
|
- **check-purchased 失败降级**:失败时应**保守**设为无权限(不信任本地缓存),避免误解锁。
|
|
|
|
|
|
- **支付回调丢失**:必须部署订单同步定时任务(如宝塔 crontab 调 `/api/cron/sync-orders`),否则会出现“已扣款但订单仍 created、内容未解锁”。
|
|
|
|
|
|
- **订单表缺字段**:新环境或老库需执行 `add_orders_referrer_id.py`、`add_orders_referral_code.py`,否则下单可能 fallback 成不写这两列(功能仍可用,但订单无推荐人/邀请码记录)。
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 六、部署与运维
|
|
|
|
|
|
|
|
|
|
|
|
- **后端**:Next.js 部署至 soul.quwanzhi.com,小程序 `app.globalData.apiBase` 指向该域名。
|
2026-02-06 12:29:56 +08:00
|
|
|
|
- **订单同步**:生产环境配置 crontab 每 5 分钟请求 `GET /api/cron/sync-orders?secret=YOUR_SECRET`(如宝塔定时任务),保证回调丢失时仍能同步为 paid 并解锁。见 `开发文档/8、部署/宝塔面板配置订单同步定时任务.md`。
|
2026-02-05 11:35:57 +08:00
|
|
|
|
- **数据库**:orders 表需含 `referrer_id`、`referral_code`;若为已有表,执行上述两个 Python 迁移脚本。
|
|
|
|
|
|
- **小程序发布**:按微信后台流程上传代码、提交审核;注意域名白名单、支付商户号与回调 URL 配置。
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 七、规划与待办(可选)
|
|
|
|
|
|
|
|
|
|
|
|
- **我的订单页**:当前 `purchases` 页为本地已购章节列表;若需“真实订单列表+邀请码展示”,可对接 `GET /api/orders?userId=xxx` 并展示订单维度数据。
|
|
|
|
|
|
- **阅读进度**:已设计阅读进度状态与 `readingTracker`、可上报服务端;是否全量接入与埋点可按产品需求推进。
|
|
|
|
|
|
- **章节接口鉴权**:若开放 Web 或对外 API,建议在章节内容接口侧按用户与购买记录返回全文/预览,防止直连拿全文。
|
|
|
|
|
|
- **按文章/章节维度的分销统计**:当前未实现;若需要“某章节带来的访问/订单数”,需在访问或订单上增加来源章节等字段并在报表中汇总。
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 八、相关文档索引
|
|
|
|
|
|
|
|
|
|
|
|
| 文档 | 说明 |
|
|
|
|
|
|
|------|------|
|
|
|
|
|
|
| 开发文档/8、部署/邀请码分销规则说明.md | 分销规则、订单 referrer_id/referral_code、推荐人 vs 邀请码 |
|
|
|
|
|
|
| 开发文档/8、部署/章节阅读付费标准流程设计.md | 阅读状态机、权限判断、阅读进度设计 |
|
|
|
|
|
|
| 开发文档/4、前端/ui/06-分销系统说明.md | 分销规则与推广方式 |
|
|
|
|
|
|
| 开发文档/4、前端/ui/08-支付系统说明.md | 支付方式与价格体系 |
|