6c7eaa9734
整轮 doc 跟齐 2026-05 落地但 doc 没补全/没更新的内容. 按 P0~P3 优先级处理.
P0 - 新 API doc + index 更新:
* docs/api/user-profile.md (新) PATCH /api/v1/user/profile 改昵称
* docs/api/user-avatar.md (新) POST /api/v1/user/avatar 上传头像(魔数嗅探/旧文件清理)
* docs/api/user-delete.md (新) DELETE /api/v1/user 注销账号(软删+匿名化)
* docs/api/feedback.md (新) POST /api/v1/feedback 提交反馈(含截图)
* docs/api/README.md 加 User/Feedback 组 + /media 静态服务段 +
修 UserOut "无接口可改恒为 null" 过时描述
P0 - 美团降级 / 现有 doc 校准:
* docs/api/meituan-coupons.md 加 "未配 MT_CPS 凭证降级返空" 说明
* docs/api/meituan-referral-link.md 同上 + 客户端兜底建议
* docs/api/meituan-feed.md 区分两种空结果路径(未配 vs 调用失败) +
/health.mt_cps_configured 排障入口
* docs/integrations/meituan.md "未配凭证降级" + "feed 静默吞错" 写进集成层
* ad-reward-status.md PR #5 commit 已自带 doc 更新, 复核无需再改
P1 - 主文档大改:
* docs/后端技术实现.md
- §1 能力表加 用户资料/外卖比价/钱包/福利/广告/反馈 (从 3 条扩到 9 条)
- §1 数据模型纠正 "仅 1 张 user 表" -> 现有 10 张 + alembic_version
- §2 DB 行 PG 主 / SQLite 兜底 + 加 psycopg3 行
- §3 目录树补 user.py / feedback.py / media.py / repositories/feedback.py /
scripts 子项 / docs/postgres-migration.md
- §7 数据模型重写: 10 张业务表速查表 + alembic 合并迁移 f01db5d77dac 始末
- §8 部署: 加 init_postgres.py 一句话流程 + checklist 加 "DATABASE_URL 切 PG"
+ "psycopg3 已装" + "MEDIA_ROOT 可写"
- §10 已知问题: 加 美团降级 / agent 不鉴权 / MEDIA_ROOT serve / init_postgres bug /
alembic 多 head 风险; 删过时 SQLite 行
- 接口计数 11 -> 38
* docs/待办与技术债.md
- 已解决追加: PG 切换 / 外卖比价透传 / 用户资料反馈接口 / 美团降级 /
看广告 4 态冷却
- 新增 "P2 DB 与 Alembic 治理" 段: alembic 多 head 团队规约 (含本次撞坑实录) +
init_postgres.py 已知 5 处小 bug + MEDIA_ROOT serve
P2 - PG 迁移文档互指 + 迁移链补完:
* docs/数据库迁移.md
- 顶部加 postgres-migration.md / 后端技术实现.md 互指
- §6 迁移链 9 条 -> 12 条 (含 feedback_table / convert_dishes_jsonb /
merge_pg_jsonb_and_feedback_heads)
- §7 踩坑里 "多 head" 一行扩成完整故事 + 修复命令 + 团队预防规约
* docs/postgres-migration.md
- 顶部加 数据库迁移.md / 后端技术实现.md §10 互指
P3 - 上线清单:
* docs/看广告赚金币上线清单.md
- 设计要点加 PR #5 4 态 CTA + 后端权威派生说明 +
VIDEO_ROUND_REQUIRED_COUNT/VIDEO_ROUND_COOLDOWN_SECONDS 常量
- §E 端到端验收加 本轮冷却 / 弹窗 limit note / 跨设备一致 三项
所有最后更新日期同步到 2026-05-31.
6.7 KiB
6.7 KiB
「看广告赚金币」上线 Checklist
跨两个仓库:
shaguabijia-app-server(后端发奖)+shaguabijia-app-android(客户端看广告)。 截至 2026-05-26:本地 + debug 包已端到端验证通过(出广告 → 发奖 → 金币到账 → 明细显示「看广告奖励」), 但尚未在生产上线。本文件记录上线前必须做的事,尤其是一堆"仅本地/debug 用、上线前必须清理"的脚手架。
设计要点(别改坏)
- 发奖只走服务端:激励视频播完,穿山甲服务器 S2S 回调后端
/api/v1/ad/pangle-callback发金币。 客户端不发奖,onRewardArrived只触发"去后端刷余额"。客户端被破解也刷不到钱。 - 后端发奖幂等(按
trans_id去重)+ 每日上限(DAILY_AD_REWARD_LIMIT,按北京时间)。 - 关键常量:
app/core/rewards.py→AD_REWARD_COIN=100、DAILY_AD_REWARD_LIMIT=10(占位值,上线前按 eCPM 实测收益重定)、VIDEO_ROUND_REQUIRED_COUNT=3、VIDEO_ROUND_COOLDOWN_SECONDS=600(本轮 3 次后冷却 10 分钟)。 - 4 态 CTA(2026-05-29 PR #5):客户端任务行按钮在 Normal / Loading / Capped / CoolingDown 之间切,全由后端
reward-status的round_count+cooldown_until派生(权威源),跨设备/重装/杀进程一致。详见 api/ad-reward-status。
A. ⚠️ 上线前必须清理的"测试/调试专用"脚手架
这些是为了"没部署公网也能本地验证"加的,带到生产 = 体验差 / 绕过反作弊 / 引入废弃工具,务必清理。
A1. 后端:本地模拟发奖接口
.env删除 / 设为 false:AD_REWARD_TEST_GRANT_ENABLED=false(默认就是 false;它一开,已登录客户端就能自助发奖)- (可选)确认生产
.env没这行;/api/v1/ad/test-grant在 false 时返回 404 - 涉及:
app/api/v1/ad.py的test_grant、app/core/config.py的AD_REWARD_TEST_GRANT_ENABLED
A2. 客户端:test-grant 调用
WelfareViewModel.onAdRewardEarned()里if (BuildConfig.DEBUG) { repo.adTestGrant() }—— release 包(BuildConfig.DEBUG=false)本就跳过,确认 release 构建不含该调用即可(结构上已隔离,无需改码;打 release 包验一次)- 涉及:
WelfareViewModel.kt、WelfareRepository.adTestGrant()、WelfareApi.adTestGrant、TestGrantDto(留着无害,只要 release 不调用 + 后端 404)
A3. 客户端:穿山甲测试工具(广告预览)
app/build.gradle.kts:移除debugImplementation(files("libs/tools-release.aar"))- 删除
app/libs/tools-release.aar gradle.properties:移除android.enableJetifier=true(仅为兼容 tools-release.aar 的旧 support 库而开,Jetifier 已废弃)- 删除
app/src/debug/.../ad/TestToolLauncher.kt+app/src/release/.../ad/TestToolLauncher.kt(空桩) WelfareScreen.kt:移除「【调试】唤起穿山甲测试工具」入口(if (BuildConfig.DEBUG){...}那段)+TestToolLauncherimport- 注:这些都 debug-only,不影响 release 功能;清掉是为了不留废弃依赖
B. 生产真正发奖链路(S2S)—— 阻塞于穿山甲后台
已确认走 GroMore 广告位层级回调(客户端 useMediation(true);规范 supportcenter/26240), 不是联盟代码位层级(5416)。验签算法 / 响应格式 / reward_amount 解析代码已按 GroMore 规范实现 (2026-05-27),剩下的是后台配置 + 填密钥。
- GroMore 后台配回调:GroMore 聚合管理 → 搜广告位ID → 编辑 → 勾选「服务端激励回调」→
回调 URL 填
https://app-api.shaguabijia.com/api/v1/ad/pangle-callback(用域名,别用 IP)。 ⚠️ 广告位层级配了就别再在代码位层级重复配(会导致发奖出问题)。 - 拿 m-key(安全密钥):就在上面"编辑广告位"页获取,填到生产
.env的PANGLE_REWARD_SECRET。 (注:这是 GroMore 广告位的 m-key,不是联盟代码位那个 Security Key。) 换验签:app/integrations/pangle.py已实现sign = SHA256("{m-key}:{trans_id}")(GroMore 真实算法)。响应格式:已返回 GroMore 要求的{"is_verify": bool, "reason": int}。reward_amount:回调按reward_amount发金币(rewards.resolve_ad_reward_coin,带回退/夹紧); 后台广告位"奖励数量"须配成与AD_REWARD_COIN(=100)一致,保证"广告内展示/进度预告/到账"三者一致。透传 user_id:客户端已setUserID(userId)+setMediaExtra("uid:...")。- 生产
.env:PANGLE_CALLBACK_ENABLED=true+PANGLE_REWARD_SECRET=<m-key>(配齐才不返 503)
C. 部署 + 包名
- 后端部署到公网(由服务器管理员;
/opt/shaguabijia-app-server,uvicorn 127.0.0.1:8770,nginx 反代) - 跑迁移:
alembic upgrade head(建ad_reward_record表,迁移c8d9e0f1a2b3) - 包名定稿:当前
com.jishisongfu.shaguabijia。穿山甲(APP_ID 5830519)、极光、微信都绑"包名 + 签名",定了再上,别再换- 微信提现链路当前因复用 elderhelper 的 appid + 包名切换已 dead,要恢复需申请傻瓜比价自己的微信 appid(另见客户端 build.gradle 注释)
- (可选,提升真实填充)集成 MSA OAID SDK:申请证书(绑包名、审核几天)。App 侧当前
getDevOaid=null,有 OAID 后投放匹配 + 填充会明显改善
D. 提现对账(顺带,与本功能独立但同属上线必做)
- 生产给
scripts/reconcile_withdraws.py挂 cron / systemd timer(每 5~10 分钟跑一次)- 否则"扣款后微信无回调"的孤儿提现单没人兜底退款(客户端已加 ON_RESUME 无条件查单,但 cron 是最后防线)
E. 端到端验收(生产链路通后)
- 真机看完一条真实激励视频 → 穿山甲 S2S 回调 → 后端发奖 → 客户端余额真到账
- 幂等:同一
trans_id不重复发 - 每日上限:超过
DAILY_AD_REWARD_LIMIT返回 capped、不发币、按钮显示「已达上限」(Capped 态) - 本轮冷却(PR #5):连看 3 张 → 按钮变 CoolingDown 显 MM:SS 倒计时不可点 → 10 分钟后自动恢复 Normal
- 弹窗 limit note:
round_count==0 && cooldown_until!=null→ "本轮视频已看完,10分钟后再来";used_today>=daily_limit→ "今日视频已到限额,明天再来" - 跨设备/杀进程一致:在手机 A 看完 3 张进入冷却 → 手机 B(同账号)登录后 reward-status 也返回相同的
cooldown_until(权威源在后端,客户端不存本地) - 中途退出广告 → 客户端提示「未看完视频,本次没有奖励哦」,且不发奖
- 收益明细显示「看广告奖励」(biz_type=
ad_reward)
关键阻塞链
B(拿验签方案/配回调)→ E(端到端验收);A(清理)可随时做;C(部署)与 B 并行。