eb5f0dc460
- 新增 POST /api/v1/ad/ecpm-report:激励视频展示后客户端上报本次 eCPM,落 ad_ecpm_record 做内部收益统计(model/repository/schema/alembic 迁移 + 接口文档) - 看广告冷却策略抽到 app/core/ad_cooldown.py 纯函数;ad_reward.today_status 只取数据,换策略只改这一处 - savings.dishes 改 JSON().with_variant(JSONB,"postgresql"):SQLite 无 visit_JSONB 会让 create_all 编译崩,修复后测试套件恢复 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
37 lines
1.9 KiB
Markdown
37 lines
1.9 KiB
Markdown
# POST /api/v1/ad/ecpm-report — 上报本次广告展示的 eCPM(内部收益统计)
|
||
|
||
> 所属:Ad 组(前缀 `/api/v1/ad`) | 鉴权:Bearer | [← 返回 API 索引](./README.md)
|
||
|
||
## 入参
|
||
请求体:`EcpmReportIn`
|
||
|
||
| 字段 | 类型 | 必填 | 说明 |
|
||
|---|---|---|---|
|
||
| `ad_type` | str | 是 | 广告类型:`reward_video`(激励视频) / `draw`(Draw 信息流) 等 |
|
||
| `ecpm` | str | 是 | 穿山甲 `getShowEcpm().getEcpm()` 原始字符串,**单位待确认(分/元)**,原样上报 |
|
||
| `adn` | str\|null | 否 | 实际投放 ADN(`getSdkName`),如 `pangle` |
|
||
| `slot_id` | str\|null | 否 | 实际展示代码位(底层 mediation rit,非客户端配置位) |
|
||
|
||
`user_id` 不在 body 里——由 JWT 取(Bearer),防伪造。
|
||
|
||
## 出参
|
||
响应 `200`:`EcpmReportOut`
|
||
|
||
| 字段 | 类型 | 说明 |
|
||
|---|---|---|
|
||
| `ok` | bool | 落库即 `true` |
|
||
|
||
## 说明
|
||
客户端在广告**展示后**(`onAdShow` 读 `getShowEcpm()`)调用,把本次展示的 eCPM 落库做**内部收益统计/对账**。
|
||
|
||
- **best-effort**:客户端 fire-and-forget,丢一两条不影响业务;穿山甲后台报表是结算权威兜底。
|
||
- 落 `ad_ecpm_record` 表,`report_date` 用北京时间当天,供「按用户/按天聚合」对账。
|
||
- **与发奖是两条独立流**:发奖走 [ad-pangle-callback](./ad-pangle-callback.md)(穿山甲 S2S,有 `trans_id`、无 ecpm),本接口客户端上报(有 ecpm、无 `trans_id`)。两者无公共键,**不逐条一一对应**,只做按用户/按天聚合口径。
|
||
- eCPM 是**每千次展示预估**,单条展示预估收益 ≈ `ecpm / 1000`,且为客户端预估口径,非最终结算。
|
||
- ⚠️ eCPM **单位(分/元)截至 2026-05-31 未最终确认**,故 `ecpm_raw` 原样存字符串;确认后再加一列解析好的数值。
|
||
- 限流:同 IP 120 次/分钟。
|
||
|
||
## 相关
|
||
- [ad-pangle-callback](./ad-pangle-callback.md) — 穿山甲 S2S 发奖回调
|
||
- [ad-reward-status](./ad-reward-status.md) — 今日看广告发奖进度
|