docs: 新建 docs/integrations 集成层文档 + api 文档变薄

- 新增 docs/integrations/(README + jiguang/sms/meituan/pangle/wxpay 各一篇):
  记录各 SDK 集成的签名/验签/加解密/协议细节与踩坑(对齐 app/integrations 分层)
- docs/api 接口文档变薄: 受影响接口头部加「集成实现」链接,把验签/RSA/CPS 签名
  等重逻辑描述移到集成文档;ad-pangle-callback 验签段精简为指针
- docs/api/README 补架构说明(api 薄 / 重逻辑在 integrations)
- 后端技术实现.md 目录树补全(福利/钱包/签到/省钱/发奖端点 + crud/integrations 现状),
  pangle/wxpay 标注移入 integrations
- ad_reward_golive_checklist 路径同步 core→integrations

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
OuYingJun1024
2026-05-27 20:45:12 +08:00
parent 6f2731ee2d
commit 3d1e8969e6
21 changed files with 293 additions and 34 deletions
+29
View File
@@ -0,0 +1,29 @@
# 穿山甲激励视频发奖回调 — 验签(pangle)
> 文件:`app/integrations/pangle.py` | 关联接口:[ad-pangle-callback](../api/ad-pangle-callback.md) | [← 集成索引](./README.md)
## 作用
穿山甲激励视频播完后,穿山甲**服务器**会 GET 回调我们的 `/api/v1/ad/pangle-callback`(带 `user_id` / `trans_id` / `sign` 等 query)。本模块负责**验签**,确认回调真来自穿山甲而非伪造请求;验签通过后由 crud 幂等发金币。客户端不参与发奖,被破解也刷不到钱。
## 验签方案(关键)
**`sign = SHA256("{m-key}:{trans_id}")` 的十六进制串。**
- 是**普通 SHA256**,不是 HMAC,也不是 RSA。
- **只对 `m-key:trans_id` 这一个字符串**签名,`user_id` / `reward_amount` 等其余参数**不参与**签名。它们的可信度由"能算出正确 sign = 知道 m-key"间接保证——伪造者没有 m-key 连合法 sign 都造不出,自然无法注入假 `user_id`
- 这是穿山甲 **GroMore「广告位 → 服务端激励回调」官方规范**supportcenter/26240)。我们客户端是 `useMediation(true)` 融合,回调走 **GroMore 广告位层级**,不是联盟代码位层级。
## 函数
| 函数 | 说明 |
|---|---|
| `build_sign(trans_id, secret) -> str` | 计算 `SHA256("{secret}:{trans_id}")` hex。自验签测试 / 模拟回调脚本共用,保证两端一致 |
| `verify_callback_sign(params, secret) -> bool` | 校验回调签名。密钥空 / 缺 `trans_id` 一律失败;比较用 `hmac.compare_digest` 定长比较防时序侧信道 |
## 配置
| 配置项 | 说明 |
|---|---|
| `PANGLE_REWARD_SECRET` | m-key(安全密钥)。后台「GroMore 聚合管理 → 搜广告位 ID → 编辑」处获取 |
## 踩坑
- **别用联盟代码位那套**:联盟代码位层级用的是另一套 Security Key + `isValid` 响应体,与 GroMore 广告位层级不通用。我们走 GroMore,别接错。
- 验签失败时 api 层返 `403`(留给真请求重试);验签过但参数缺/坏或 user 不存在,则受理不发奖、不让穿山甲重试。
- 本地无公网、回调打不到时,用 [ad-test-grant](../api/ad-test-grant.md) 模拟(仅联调,开关控制)。