feat(withdraw): OPPO 推送带 channel_id + category 预留

- unicast notification 带 channel_id(默认 push_oplus_category_content, OPPO 系统内容渠道)
- category 做成 config 可配(默认空); 升级 service 渠道+ACCOUNT 分类只改配置不改代码
- 客户端无需改动(OPPO 系统预置渠道 App 不自建)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-15 10:32:28 +08:00
parent 5ae4c474e4
commit 0921cb84d9
3 changed files with 21 additions and 5 deletions
+6
View File
@@ -87,6 +87,12 @@ class Settings(BaseSettings):
OPPO_PUSH_REQUEST_TIMEOUT_SEC: int = 10
# 通知点击行为(OPPO click_action_type; 0=启动应用首页)。交易类通知点开进首页即可。
OPPO_PUSH_CLICK_ACTION_TYPE: int = 0
# 通知渠道 id(Android 8+ NotificationChannel): 【客户端创建的渠道】+【OPPO 管理台登记】+
# 【服务端此值】三方必须一致, 否则真机可能不展示。客户端 OppoPushHelper.CHANNEL_ID 同值。
OPPO_PUSH_CHANNEL_ID: str = "shagua_wallet"
# OPPO 新消息分类(Android 12+ 触达; 提现属 ACCOUNT 账号资产变化)。默认空=不带该字段——
# 它依赖 OPPO 管理台的消息分类资质, 未开通就带上可能反被限制, 确认资质后再填(如 "ACCOUNT")。
OPPO_PUSH_CATEGORY: str = ""
@property
def oppo_push_configured(self) -> bool:
+12 -5
View File
@@ -134,14 +134,21 @@ def send_notification(
if click_action_type is None:
click_action_type = settings.OPPO_PUSH_CLICK_ACTION_TYPE
notification = {
"title": title,
"content": content,
"click_action_type": click_action_type,
}
# channel_id: Android 8+ 通知渠道(客户端已建同名渠道 + OPPO 管理台登记, 三方一致才展示)。
if settings.OPPO_PUSH_CHANNEL_ID:
notification["channel_id"] = settings.OPPO_PUSH_CHANNEL_ID
# category: OPPO 新消息分类(默认空不带; 依赖管理台资质, 见 config 注释)。
if settings.OPPO_PUSH_CATEGORY:
notification["category"] = settings.OPPO_PUSH_CATEGORY
message = {
"target_type": _TARGET_TYPE_REGISTRATION_ID,
"target_value": registration_id,
"notification": {
"title": title,
"content": content,
"click_action_type": click_action_type,
},
"notification": notification,
}
# OPPO unicast body 是 form 编码, message 字段为 JSON 字符串
payload = {"message": json.dumps(message, ensure_ascii=False)}
+3
View File
@@ -67,6 +67,9 @@ def test_success_flow(monkeypatch) -> None:
assert msg["target_value"] == "regid123"
assert msg["notification"]["title"] == "标题"
assert msg["notification"]["content"] == "内容"
# channel_id 必带(默认 shagua_wallet); category 默认空 → 不带
assert msg["notification"]["channel_id"] == "shagua_wallet"
assert "category" not in msg["notification"]
def test_auth_token_cached(monkeypatch) -> None: