OpenClaw—AI研究OpenClaw—AI研究
  • AI动态
  • OpenClaw教程
  • 技术解读
  • 用户故事

【开发日志】ShopSystem Day 23: 邀请分销(2026-09-05)

【开发日志】ShopSystem Day 23: 邀请分销(2026-09-05)

2026年9月5日 by WoodStone

ShopSystem Day 23 邀请分销(分享链接 + 首购奖励)上线,从「商品维度社交」(Day 22 店铺关注)延伸到「跨用户维度社交」,开启第四阶段「邀请分销」新篇章。3 个新 migration:`users` 加 `invited_by` 自引用 FK(邀请人删号时自动归 NULL)+ 新建 `invitations` 表(11 列 + UNIQUE 一人只被邀一次 + 2 FK ON DELETE 双策略)+ 种入 `INVITE_REWARD` ¥10 平台券模板。4 个新 API:GET `/api/invitations/lookup` 公开(uid → 邀请人名字,供注册页 banner)、GET `/api/invitations/mine` 鉴权(我的链接 + 3 统计 + 明细)、POST `/api/auth/register` body 透传 `invite` 整数(事务内写 invited_by + invitations pending;邀请人失效静默降级不报错)、POST `/api/payment/mock` 事务内结算首购奖励(`SELECT invitations FOR UPDATE` 锁行 + `reward_status=’pending’` 状态过滤 + `INSERT user_coupons` UNIQUE 兜底三层幂等)。

ShopSystem /register?invite=45 注册页邀请 banner - 由好友 Day13QA 邀请文案

分享链接机制:`/register?invite=` 路径(uid 即邀请人整数 id),`RegisterForm` 用 `useSearchParams` 读参数 → 调 lookup API 拿名字 → 顶部展示「由好友 X 邀请,注册后首单成功,好友可获 ¥10 奖励券」banner,提交时 body 带 invite 字段。注册接口的 invite 校验走「静默降级」哲学:邀请人不存在/已停用/非整数/0,全部不报错,降级为普通注册 — 避免泄漏「哪些 id 是 active」,防止探测攻击。注册事务内双写:`UPDATE users SET invited_by=合法邀请人id` + `INSERT invitations (inviter_id, invitee_id, ‘pending’, ‘coupon’, 10.00)`,数据一致。`invitations` 表 `UNIQUE(invitee_id)` 防脚本刷邀请关系,UNIQUE 冲突兜底当幂等成功。

ShopSystem /account?tab=invite 我的邀请 - 链接 + 3 统计卡 + 明细表 + 玩法说明

奖励形式决策:¥10 平台券 vs 账户余额 — 7 维对比(复用 Day 12 全栈 / 用户感知 / 防套现 / 数据审计 / 跨商家一致性 / 改色可追溯 / 退券处理),全部维度平台券胜出,选券不选余额。结算触发点:`/api/payment/mock` 事务内 `UPDATE orders SET status=’paid’` 之后新增奖励结算块:锁行 `SELECT invitations WHERE invitee_id=? AND reward_status=’pending’ FOR UPDATE` + 校验「除当前订单外无其他 paid/shipped/delivered/refunded 单」才算首单(防后续刷单)+ 拿 INVITE_REWARD 模板券 + `INSERT user_coupons` + `UPDATE coupons.used_count +1` + `UPDATE invitations SET reward_status=’paid’, reward_paid_at=NOW()`。返回 `reward: { invited: true, inviterId, couponId }`。邀请人 user_coupons 表即时增加一张 ¥10 unused 券,可在「我的优惠券」tab 看到「邀请好友奖励 ¥10 券」。

ShopSystem /account?tab=coupons 我的优惠券 - 含「邀请好友奖励 ¥10 券」unused

邀请页 `/account?tab=invite` SSR 直出:Server Component 一次性拉 `SELECT COUNT(*)/SUM(CASE WHEN reward_status=…) FROM invitations WHERE inviter_id=me` + 明细 `invitations JOIN users LIMIT 50`,注入 `InviteTab` props;客户端只负责「复制链接」按钮(`navigator.clipboard.writeText` + `execCommand(‘copy’)` 兜底)。NAV 顺序沿用 Day 22 低调处理 — 邀请好友 tab 放最末(避免一进用户中心就诱导分享)。FK ON DELETE 双策略:`invitee_id NOT NULL + CASCADE`(被邀者删号时邀请关系一并清理,MySQL 不允许 NOT NULL 列做 SET NULL FK,这是必要妥协);`inviter_id NULL + SET NULL`(邀请人删号时保留邀请历史,被邀者 invited_by 自动归 NULL)。users.invited_by 单 FK SET NULL,沿用 Day 17 「FK SET NULL 让 DB 自动兜底」哲学。Day 23 收官踩了 2 个坑:① B 段首购结算初期直接 SELECT 后 INSERT user_coupons 出现「reward 已发但状态未更新」竞态 — 改 `SELECT … FOR UPDATE` 锁行 + status 双过滤根治;② 注册接口的 invite 校验最初返 400 报错,被攻击探测风险高 — 改「静默降级为普通注册」,邀请人失效不阻断流程。Day 24 预告:优惠券分享/转赠(券码生成 + 转赠 + 领取),从用户增长延伸到券流通,完成券体系闭环。

关于作者:WoodStoneShopSystem 项目负责人,专注网商平台与电商 AI 集成

← 返回文章列表
分类: 技术解读 标记: Day23, Next.js, ShopSystem, 开发日志, 电商, 邀请分销

© 2026 OpenClaw—AI研究 版权所有

沪ICP备2026010690号-1