体验资格发放文档
baozi 体验资格(trial):注册用户通过专属渠道链接领取 7 天 ¥38 coding-lite 套餐体验,先验证产品被接受和需求真实存在,再考虑商业化。限额总 100 名 = 9 渠道独立配额之和,邀请机制可累加。
1. 用户视角流程
1.1 领体验资格
微信群/微博/V2EX 渠道专属链接
↓
点链接 → 进 baozi 首页
↓
未登录 → 走 Logto OIDC 注册/登录
↓
登录后自动调 POST /api/v1/trial/claim { channel_code: "wechat-group" }
↓
扣减渠道配额 +1 + 写 trial_claims + 返体验额度
↓
前端跳 /dashboard 看到体验激活 (7 天倒计时 + ¥38 配额)
1.2 看自己状态
# 登录后调
GET /api/v1/trial/status
# 返: has_trial=true, active=[{remaining_days:7, quota_yuan:38}], invite_code="<user_id>"
1.3 邀请好友(飞轮)
# 查自己的邀请链接
GET /api/v1/trial/invite-link
# 返: invite_url="https://baozi.ohoooho.com/trial/invite-123"
# 好友点链接注册 → 好友填 channel_code=invite + invite_code=123 领体验
# → 邀请人配额 +1 名 + 体验延期 +7 天
2. 渠道配额总览
2.1 9 渠道默认配额(总 100 名)
| 渠道 | 名额 | 入口形态 |
|---|---|---|
微信群 (wechat-group) |
20 | 群内专属链接 |
微博 (weibo) |
15 | 文章末尾链接 |
Twitter/X (twitter) |
10 | 推文链接 |
即刻 (jike) |
10 | 动态链接 |
V2EX (v2ex) |
10 | 帖子链接 |
GitHub (github) |
10 | README 链接 |
少数派 (sspai) |
5 | 文章链接 |
邀请链接 (invite) |
20 | 用户邀请飞轮(可累加) |
2.2 公开查询(无需登录)
GET /api/v1/trial/quotas
返回示例(200):
{
"success": true,
"data": {
"channels": [
{ "code": "invite", "name": "邀请链接", "total": 20, "used": 0, "remaining": 20, "enabled": true },
{ "code": "wechat-group", "name": "微信群", "total": 20, "used": 0, "remaining": 20, "enabled": true },
{ "code": "weibo", "name": "微博", "total": 15, "used": 0, "remaining": 15, "enabled": true },
{ "code": "github", "name": "GitHub", "total": 10, "used": 0, "remaining": 10, "enabled": true },
{ "code": "jike", "name": "即刻", "total": 10, "used": 0, "remaining": 10, "enabled": true },
{ "code": "twitter", "name": "Twitter/X","total": 10, "used": 0, "remaining": 10, "enabled": true },
{ "code": "v2ex", "name": "V2EX", "total": 10, "used": 0, "remaining": 10, "enabled": true },
{ "code": "sspai", "name": "少数派", "total": 5, "used": 0, "remaining": 5, "enabled": true }
],
"total": 100,
"used": 0,
"remaining": 100,
"duration_days": 7,
"quota_yuan": 38,
"package_id": "coding-lite"
}
}
3. API 全清单(5 端点)
3.1 GET /api/v1/trial/quotas — 公开
见 2.2 节。
3.2 POST /api/v1/trial/claim — 登录态
请求体:
{ "channel_code": "wechat-group" }
或邀请场景:
{ "channel_code": "invite", "invite_code": "123" }
返回示例(200):
{
"success": true,
"data": {
"claim_id": 1,
"user_id": 42,
"username": "baozi-e2e-user-001",
"channel_code": "wechat-group",
"quota_yuan": 38,
"package_id": "coding-lite",
"expires_at": 1752384000000,
"expires_at_iso": "2026-09-17T10:59:33.000Z",
"duration_days": 7
}
}
错误码:
| 状态码 | code | 含义 |
|---|---|---|
| 401 | auth_required |
未登录 |
| 400 | — | channel_code 必填 |
| 404 | — | 渠道不存在 |
| 403 | — | 渠道已停用 |
| 409 | quota_exhausted |
渠道配额用完 |
| 409 | already_claimed |
同一用户同渠道已领 |
3.3 GET /api/v1/trial/status — 登录态
返回示例(200):
{
"success": true,
"data": {
"has_trial": true,
"active": [
{
"claim_id": 1,
"channel_code": "wechat-group",
"quota_yuan": 38,
"package_id": "coding-lite",
"expires_at": 1752384000000,
"expires_at_iso": "2026-09-17T10:59:33.000Z",
"remaining_days": 7
}
],
"converted": [],
"expired_count": 0,
"invite_code": "42"
}
}
3.4 GET /api/v1/trial/invite-link — 登录态
返回示例(200):
{
"success": true,
"data": {
"invite_code": "42",
"invite_url": "https://baozi.ohoooho.com/trial/invite-42",
"invited_count": 0,
"my_claim": null,
"reward_rule": "邀请 1 人体验, 你的配额 +1 名 + 你的体验延期 7 天"
}
}
3.5 GET /api/v1/admin/trial/stats — admin 角色
返回示例(200):
{
"success": true,
"data": {
"channels": [
{
"code": "wechat-group",
"name": "微信群",
"used": 3,
"total": 20,
"remaining": 17,
"enabled": true,
"claims_total": 3,
"converted": 1,
"conversion_rate_pct": "33.33"
}
],
"totals": {
"used": 5,
"total": 100,
"claims": 5,
"converted": 2,
"remaining": 95,
"overall_conversion_rate_pct": "40.00"
},
"last_updated": 1751777973000,
"last_updated_iso": "2026-09-10T11:00:00.000Z"
}
}
4. 数据库设计
4.1 trial_quotas(渠道配额表)
| 字段 | 类型 | 说明 |
|---|---|---|
channel_code |
TEXT PK | 渠道 code(wechat-group / weibo / ...) |
channel_name |
TEXT | 显示名 |
total_quota |
INTEGER | 总配额 |
used_quota |
INTEGER | 已用(默认 0) |
enabled |
INTEGER | 1=启用 / 0=停用 |
reset_at |
INTEGER NULL | 配额重置时间(NULL=永久) |
created_at |
INTEGER | 创建时间(毫秒) |
updated_at |
INTEGER | 更新时间(毫秒) |
4.2 trial_claims(用户领取记录表)
| 字段 | 类型 | 说明 |
|---|---|---|
id |
INTEGER PK AUTOINCREMENT | |
user_id |
INTEGER FK → users.id | |
channel_code |
TEXT | 领取渠道 |
invite_code |
TEXT NULL | 邀请人 code(仅 invite 渠道) |
quota_yuan |
INTEGER | 体验额度(默认 38) |
expires_at |
INTEGER | 体验到期时间(毫秒) |
claimed_at |
INTEGER | 领取时间 |
converted_at |
INTEGER NULL | 转付费时间(NULL=未转) |
converted_order_id |
TEXT NULL | 转付费的订单 ID |
唯一约束:UNIQUE(user_id, channel_code) 防同一用户重复领。
4.3 索引
CREATE INDEX idx_trial_claims_user ON trial_claims(user_id);
CREATE INDEX idx_trial_claims_channel ON trial_claims(channel_code, claimed_at DESC);
CREATE INDEX idx_trial_claims_invite ON trial_claims(invite_code) WHERE invite_code IS NOT NULL;
CREATE INDEX idx_trial_claims_conversion ON trial_claims(converted_at) WHERE converted_at IS NOT NULL;
5. 邀请机制(增长飞轮)
5.1 触发
- 用户 A 调
/api/v1/trial/invite-link→ 拿invite_url = https://baozi.ohoooho.com/trial/invite-${A.id} - 用户 B 点链接注册 → 注册流程自动带
?invite=A.id - 用户 B 登录后调
POST /api/v1/trial/claim { channel_code: "invite", invite_code: "A.id" }
5.2 奖励(事务内)
- 扣减
invite渠道配额 +1(claim 已自动) invite渠道total_quota+1(邀请人奖励)- 邀请人 A 的 trial_claims
expires_at+7 天
5.3 防滥用
- invite_code 不能是自己(
inviterId === me.id→ 400) - invite_code 必须对应真实 user(user_id 404 → 404)
6. 转化追踪(验证 PMF)
6.1 trial → 付费链路
用户体验到期前
↓
续费提醒 (cron) 调 /api/v1/trial/status 查 remaining_days <= 1
↓
发邮件 / 站内信 → "你的体验还剩 1 天, ¥38 续 coding-lite?"
↓
用户下单 → POST /api/v1/orders
↓
订单支付成功 → 写 trial_claims.converted_at + converted_order_id
6.2 PMF 验证指标
| 指标 | 目标 | 查询 |
|---|---|---|
| 渠道转化率 | > 10% | admin/trial/stats 的 conversion_rate_pct |
| 整体转化率 | > 15% | admin/trial/stats 的 overall_conversion_rate_pct |
| 邀请转化率 | > 20% | invite 渠道 conversion_rate_pct |
| 体验期用户活跃 | > 60% | trial_claims.claimed_at + 7 天内 user_tokens 有调用 |
7. Phase 2+ 待办
- [ ] 前端 UI: 首页「领体验资格」卡片,实时显示各渠道剩余配额 + 一键登录领
- [ ] playwright e2e: 注册 → 领体验 → 查 status → 邀请 → 转化全链路真浏览器跑
- [ ] admin 看板: baozi-system-admin 加渠道 ROI 图表(转化率 + 配额水位 + 时间趋势)
- [ ] 转化提醒: cron 每天扫
trial_claims.expires_at <= now + 1d发提醒邮件 - [ ] 渠道动态调整: admin 端点 PUT/POST 调 total_quota / enabled
- [ ] 过期清理: 过期体验不主动删 user_tokens,仅打 expired(已实现)
8. 真实部署记录
2026-09-10 Phase 1 部署
- 代码:
/Users/xuyu/xianyun/projects/baozi-service/server.js(2001 行) - 部署:
/opt/baozi-service/server.json140.143.246.15 - 启动:
systemctl restart baozi-service - journal 验证:
[trial] ✓ 默认 8 渠道配额 seed 完成 (总 100 名)+baozi-auth running on port 3041 - 端点真测: 5 端点全 200/401 预期(0 个 500 错)