Files
shaguabijia-app-server/docs/api/push-vendor-test.md
T
左辰勇 a8ac5dc0c7 消息通知中心 3 接口(mock 阶段) + 五厂商推送(补华为/通用发送/测试三件套)
- GET /api/v1/notifications(分页,时间倒序不分组)/unread-count /read(ids|all),
  对外 camelCase(PRD 前端契约);数据为内存 mock(13 类型全覆盖,重启复位),
  接真实数据只换 repositories/notification_mock.py
- vendor_push 补华为 Push Kit(OAuth+messages:send),抽通用 send_notification
  (任意文案+extras+mock 模式),send_accessibility_disabled 改薄封装行为不变
- 新增 /api/v1/push/{vendors,templates,test}:凭据状态/13 类 PRD 文案模板/测试发送
  (默认 mock,mock=false 真发,可联动插站内 mock 消息闭环验证已读)
- .env.example 补 HUAWEI_* 键;docs/api 新增 notifications.md + push-vendor-test.md
- alembic merge 1a924c274fce 收拢 direct_vendor_push_fields/feedback_type_reply
  双 head,恢复 upgrade head 可用
- tests: test_notifications + test_push_center 共 35 例

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-14 18:57:04 +08:00

6.0 KiB

厂商推送测试三件套(push 族)

所属:push 组(前缀 /api/v1/push,源 app/api/v1/push.py) | 鉴权:全部 Bearer | ← 返回 API 索引

发送实现:app/integrations/vendor_push.py(荣耀 / 华为 / 小米 / OPPO / vivo 五通道, send_notification() 通用入口)。站内消息中心见 notifications.md。 与 POST /api/v1/device/push-test(无障碍召回通道延迟自测)互补:本组面向消息中心 13 类 push 的文案/参数/通道联调。

字段命名同 notifications 族:camelCase

链路总览

真实业务事件(奖励过期/提现回执/审核通过/…)
      └→ vendor_push.send_notification(vendor, token, title, body, extras)
              extras = { type, notificationId, ...业务参数 }        ← 客户端深链 + 已读联动的钥匙
客户端点击 push → 按 extras.type 直达落地页(与站内点击一致)
              → 调 POST /notifications/read {ids:[extras.notificationId]} 同步消红点(PRD §4)

推送目标来源:客户端集成各厂商 push SDK 拿到 regId/token 后,通过 POST /api/v1/device/register 上报 push_vendor + push_token,服务端存 device_liveness 表。

GET /api/v1/push/vendors — 厂商配置状态

检查 5 家厂商服务端凭据是否配齐(只读 .env,不打厂商接口)。missingKeys 即还要补的配置键;mock 测试不依赖任何凭据。

{ "vendors": [
    { "vendor": "honor",  "label": "荣耀", "configured": false, "missingKeys": ["HONOR_PUSH_APP_ID", "HONOR_PUSH_CLIENT_ID", "HONOR_PUSH_CLIENT_SECRET"] },
    { "vendor": "huawei", "label": "华为", "configured": false, "missingKeys": ["HUAWEI_PUSH_APP_ID", "HUAWEI_PUSH_APP_SECRET"] },
    { "vendor": "xiaomi", "label": "小米", "configured": true,  "missingKeys": [] },
    { "vendor": "oppo",   "label": "OPPO", "configured": false, "missingKeys": ["OPPO_PUSH_APP_KEY", "OPPO_PUSH_MASTER_SECRET"] },
    { "vendor": "vivo",   "label": "vivo", "configured": false, "missingKeys": ["VIVO_PUSH_APP_ID", "VIVO_PUSH_APP_KEY", "VIVO_PUSH_APP_SECRET"] }
] }

GET /api/v1/push/templates — 13 类通知的 push 模板预览

PRD §5 的 13 条 push 文案(标题固定 ≤11 字不带变量;正文 {var} 为变量,示例值即 PRD 示例)。对文案、看变量名用。

{ "templates": [
    {
      "type": "withdraw_success",
      "category": "withdraw_assistant", "categoryLabel": "提现助手", "cardStyle": "withdraw",
      "pushTitle": "提现到账提醒",
      "pushBodySample": "¥0.50已存入您的微信钱包,点击查看到账详情",   // 用示例值渲染后的效果
      "pushBodyTemplate": "¥{amount}已存入您的微信钱包,点击查看到账详情",
      "variables": ["amount"],
      "sampleVars": { "amount": "0.50" }
    }
    // ... 共 13 条,顺序即 PRD 编号
] }

POST /api/v1/push/test — 测试发送(默认 mock)

入参(JSON)

字段 类型 必填 说明
vendor string * honor/huawei/xiaomi/oppo/vivo,中文「华为」「小米」等别名也识别;留空时用 deviceId 设备上报的 vendor
pushToken string * 厂商 push token/regId;留空则按 deviceId 反查已注册设备(mock 模式两者都缺时用占位 token,只看渲染结果)
deviceId string 客户端 DeviceId.get() 的设备 id,用于反查 vendor+token
type string 13 种类型 key 之一 → 按 PRD 模板渲染;不传且没直给文案 → 发通用测试文案
vars object 覆盖模板变量,如 {"coins":"520","cash":"6.66"};缺省用 PRD 示例值
title / content string 直接指定标题/正文(优先于 type 模板)
createNotification bool true = 同时往该用户消息中心插一条同类型未读 mock 通知,extras 带其 notificationId → 可闭环验证「点 push → 调 /notifications/read 消红点」(仅 type 合法时生效)
mock bool 默认 true = 不真调厂商 API,回显渲染结果;false = 真发到手机(要求该厂商凭据已配)

出参

{
  "ok": true, "mock": true, "vendor": "huawei",
  "title": "反馈奖励已到账",
  "body": "谢谢您帮傻瓜比价变得更好,300金币已到账,还有一条给您的留言~",
  "extras": { "type": "feedback_reward", "feedbackId": "3002", "notificationId": "90017" },
  "notificationId": 90017,          // createNotification=true 时的站内 mock 通知 id
  "missingKeys": ["HUAWEI_PUSH_APP_ID", "HUAWEI_PUSH_APP_SECRET"],  // 真发前还缺的配置(真发成功时必为空)
  "vendorResponse": null            // 真发时为厂商 API 原始响应
}

错误:400 vendor/type 非法、真发但凭据未配(detail 列缺失键);409 真发但拿不到 pushToken;502 厂商 API 返回失败(detail 带厂商原始错误)。

真发注意:

  • 目标手机必须先装 App 且客户端已集成对应厂商 SDK、/device/register 上报过 token;
  • vivo 未上架前走测试推送(VIVO_PUSH_MODE=1),目标手机需在 vivo 开放平台加入测试设备;
  • 小米新设备需在开放平台把签名/包名配好,token 才有效。

厂商凭据怎么拿(.env 键名)

厂商 后台 需要的键
华为 AGC 控制台 → 项目设置 → 常规 → 应用 HUAWEI_PUSH_APP_IDHUAWEI_PUSH_APP_SECRET(OAuth client_id 即 AppId)
荣耀 荣耀开发者服务平台 → 推送服务 HONOR_PUSH_APP_IDHONOR_PUSH_CLIENT_IDHONOR_PUSH_CLIENT_SECRET
小米 开放平台 → 消息推送 → 应用秘钥 XIAOMI_PUSH_APP_SECRET(服务端只要这个;AppID/AppKey 是客户端 SDK 用)
OPPO 开放平台 → 推送服务 OPPO_PUSH_APP_KEYOPPO_PUSH_MASTER_SECRET(注意是服务端 MasterSecret)
vivo 开放平台 → 推送 VIVO_PUSH_APP_IDVIVO_PUSH_APP_KEYVIVO_PUSH_APP_SECRET

各家发送协议差异(鉴权方式/成功码/payload 结构)封装在 integrations/vendor_push.py,业务侧只面对 send_notification()