feat(jpush): add vendor-specific message classification support for push notifications
- Add OPPO category/notify_level support (2024.11.20 regulation: category required when notify_level present) - Add Honor importance field (NORMAL=service/LOW=marketing) for notification classification - Add vivo category field (IM/ACCOUNT) for message scenario identification - Set Xiaomi channel/template defaults in code (system=153609, chat=153608, templates P10761/M10289) - Add classification option to JPush push payloads (0=operation, 1=system) - Update xiaomi template keywords mapping to match actual template placeholders - Add keyword search support for GetFollowers and GetFollowing endpoints - Bind new config fields to environment variables for OPPO/Honor/vivo
This commit is contained in:
@@ -198,8 +198,8 @@ func Load(configPath string) (*Config, error) {
|
||||
// 各厂商 channel_id 通过环境变量配置(见下方 BindEnv)
|
||||
viper.SetDefault("jpush.channel.system", "")
|
||||
viper.SetDefault("jpush.channel.chat", "")
|
||||
viper.SetDefault("jpush.channel.vendor.xiaomi.system", "")
|
||||
viper.SetDefault("jpush.channel.vendor.xiaomi.chat", "")
|
||||
viper.SetDefault("jpush.channel.vendor.xiaomi.system", "153609")
|
||||
viper.SetDefault("jpush.channel.vendor.xiaomi.chat", "153608")
|
||||
viper.SetDefault("jpush.channel.vendor.huawei.system", "")
|
||||
viper.SetDefault("jpush.channel.vendor.huawei.chat", "")
|
||||
viper.SetDefault("jpush.channel.vendor.oppo.system", "")
|
||||
@@ -213,11 +213,29 @@ func Load(configPath string) (*Config, error) {
|
||||
viper.SetDefault("jpush.channel.vendor.fcm.system", "")
|
||||
viper.SetDefault("jpush.channel.vendor.fcm.chat", "")
|
||||
// 小米/OPPO 模板 id 默认值
|
||||
viper.SetDefault("jpush.channel.vendor.xiaomi.mi_system_template_id", "")
|
||||
viper.SetDefault("jpush.channel.vendor.xiaomi.mi_chat_template_id", "")
|
||||
viper.SetDefault("jpush.channel.vendor.xiaomi.mi_system_template_id", "P10761")
|
||||
viper.SetDefault("jpush.channel.vendor.xiaomi.mi_chat_template_id", "M10289")
|
||||
viper.SetDefault("jpush.channel.vendor.oppo.oppo_system_private_template_id", "")
|
||||
viper.SetDefault("jpush.channel.vendor.oppo.oppo_chat_private_template_id", "")
|
||||
// iOS 通知分组 thread-id 默认值
|
||||
// OPPO 消息分类默认值(category / notify_level)
|
||||
// OPPO 消息分类默认值(2024.11.20 新规)
|
||||
// chat: category=IM(即时通讯), notify_level=16(通知栏+锁屏+横幅+震动+铃声,强提醒)
|
||||
// system: category=ACCOUNT(账号动态/互动通知), notify_level=2(通知栏+锁屏,避免打扰)
|
||||
// 注:使用 notify_level 时 category 必传,此处两者同时配置
|
||||
viper.SetDefault("jpush.channel.vendor.oppo.oppo_system_category", "ACCOUNT")
|
||||
viper.SetDefault("jpush.channel.vendor.oppo.oppo_chat_category", "IM")
|
||||
viper.SetDefault("jpush.channel.vendor.oppo.oppo_system_notify_level", 2)
|
||||
viper.SetDefault("jpush.channel.vendor.oppo.oppo_chat_notify_level", 16)
|
||||
// 荣耀 importance 默认值
|
||||
// chat: NORMAL(服务与通讯,及时送达), system: LOW(资讯营销,避免打扰)
|
||||
// 注:classification 优先级更高,会覆盖 importance
|
||||
viper.SetDefault("jpush.channel.vendor.honor.honor_system_importance", "LOW")
|
||||
viper.SetDefault("jpush.channel.vendor.honor.honor_chat_importance", "NORMAL")
|
||||
// vivo category 默认值(classification=1 时必须为系统消息类)
|
||||
// chat: IM(即时通讯), system: ACCOUNT(账号动态/互动通知)
|
||||
viper.SetDefault("jpush.channel.vendor.vivo.vivo_system_category", "ACCOUNT")
|
||||
viper.SetDefault("jpush.channel.vendor.vivo.vivo_chat_category", "IM")
|
||||
// iOS 通知分组 thread-id 默认值(留空,不分组)
|
||||
viper.SetDefault("jpush.channel.ios.chat_thread_id", "")
|
||||
viper.SetDefault("jpush.channel.ios.system_thread_id", "")
|
||||
// JPush 厂商 channel_id 环境变量显式绑定
|
||||
@@ -244,6 +262,17 @@ func Load(configPath string) (*Config, error) {
|
||||
viper.BindEnv("jpush.channel.vendor.xiaomi.mi_chat_template_id", "APP_JPUSH_CHANNEL_XIAOMI_MI_CHAT_TEMPLATE_ID")
|
||||
viper.BindEnv("jpush.channel.vendor.oppo.oppo_system_private_template_id", "APP_JPUSH_CHANNEL_OPPO_SYSTEM_PRIVATE_TEMPLATE_ID")
|
||||
viper.BindEnv("jpush.channel.vendor.oppo.oppo_chat_private_template_id", "APP_JPUSH_CHANNEL_OPPO_CHAT_PRIVATE_TEMPLATE_ID")
|
||||
// OPPO category / notify_level 环境变量绑定
|
||||
viper.BindEnv("jpush.channel.vendor.oppo.oppo_system_category", "APP_JPUSH_CHANNEL_OPPO_SYSTEM_CATEGORY")
|
||||
viper.BindEnv("jpush.channel.vendor.oppo.oppo_chat_category", "APP_JPUSH_CHANNEL_OPPO_CHAT_CATEGORY")
|
||||
viper.BindEnv("jpush.channel.vendor.oppo.oppo_system_notify_level", "APP_JPUSH_CHANNEL_OPPO_SYSTEM_NOTIFY_LEVEL")
|
||||
viper.BindEnv("jpush.channel.vendor.oppo.oppo_chat_notify_level", "APP_JPUSH_CHANNEL_OPPO_CHAT_NOTIFY_LEVEL")
|
||||
// 荣耀 importance 环境变量绑定
|
||||
viper.BindEnv("jpush.channel.vendor.honor.honor_system_importance", "APP_JPUSH_CHANNEL_HONOR_SYSTEM_IMPORTANCE")
|
||||
viper.BindEnv("jpush.channel.vendor.honor.honor_chat_importance", "APP_JPUSH_CHANNEL_HONOR_CHAT_IMPORTANCE")
|
||||
// vivo category 环境变量绑定
|
||||
viper.BindEnv("jpush.channel.vendor.vivo.vivo_system_category", "APP_JPUSH_CHANNEL_VIVO_SYSTEM_CATEGORY")
|
||||
viper.BindEnv("jpush.channel.vendor.vivo.vivo_chat_category", "APP_JPUSH_CHANNEL_VIVO_CHAT_CATEGORY")
|
||||
// iOS thread-id 环境变量绑定
|
||||
viper.BindEnv("jpush.channel.ios.chat_thread_id", "APP_JPUSH_CHANNEL_IOS_CHAT_THREAD_ID")
|
||||
viper.BindEnv("jpush.channel.ios.system_thread_id", "APP_JPUSH_CHANNEL_IOS_SYSTEM_THREAD_ID")
|
||||
|
||||
@@ -60,4 +60,24 @@ type VendorChannelID struct {
|
||||
// 见:OPUSH 私信模版校验能力接入说明
|
||||
OppoSystemPrivateTemplateID string `mapstructure:"oppo_system_private_template_id"` // 系统消息私信模板 id
|
||||
OppoChatPrivateTemplateID string `mapstructure:"oppo_chat_private_template_id"` // 私聊消息私信模板 id
|
||||
|
||||
// OPPO 消息分类(可选,2024.11.20 新规)
|
||||
// category 消息场景标识,使用 notify_level 时必传;notify_level 提醒等级
|
||||
// 取值:category 如 IM/ACCOUNT;notify_level 1=通知栏, 2=通知栏+锁屏, 16=通知栏+锁屏+横幅+震动+铃声
|
||||
OppoSystemCategory string `mapstructure:"oppo_system_category"` // 系统消息 category(如 ACCOUNT)
|
||||
OppoChatCategory string `mapstructure:"oppo_chat_category"` // 私聊消息 category(如 IM)
|
||||
OppoSystemNotifyLevel int `mapstructure:"oppo_system_notify_level"` // 系统消息提醒等级(如 2)
|
||||
OppoChatNotifyLevel int `mapstructure:"oppo_chat_notify_level"` // 私聊消息提醒等级(如 16)
|
||||
|
||||
// 荣耀通知栏消息智能分类(可选,importance 字段)
|
||||
// 取值:"NORMAL"=服务与通讯,"LOW"=资讯营销
|
||||
// 注:classification 优先级更高,会覆盖 importance 设置的值
|
||||
HonorSystemImportance string `mapstructure:"honor_system_importance"` // 系统消息 importance(如 LOW)
|
||||
HonorChatImportance string `mapstructure:"honor_chat_importance"` // 私聊消息 importance(如 NORMAL)
|
||||
|
||||
// vivo 厂商消息场景标识(可选,category 字段)
|
||||
// 用于标识消息类型,确定提醒方式;classification=1 时 category 必须为系统消息类
|
||||
// 不携带 category 会默认按运营消息下发,受频控限制
|
||||
VivoSystemCategory string `mapstructure:"vivo_system_category"` // 系统消息 category(如 ACCOUNT 账号动态)
|
||||
VivoChatCategory string `mapstructure:"vivo_chat_category"` // 私聊消息 category(如 IM 即时通讯)
|
||||
}
|
||||
|
||||
82
internal/config/jpush_default_test.go
Normal file
82
internal/config/jpush_default_test.go
Normal file
@@ -0,0 +1,82 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// TestXiaomiDefaultValuesFromViper 验证:config.yaml 中小米字段留空时,
|
||||
// viper.SetDefault 设置的默认值(153608/153609 + M10289/P10761)能正确填充到 Config 结构体。
|
||||
// 这证明:不配置环境变量/yaml 值时,代码内置默认值生效。
|
||||
func TestXiaomiDefaultValuesFromViper(t *testing.T) {
|
||||
// 加载仓库内的 config.yaml(小米字段已留空,依赖代码默认值)
|
||||
yamlPath := filepath.Join("..", "..", "configs", "config.yaml")
|
||||
cfg, err := Load(yamlPath)
|
||||
if err != nil {
|
||||
t.Fatalf("Load config failed: %v", err)
|
||||
}
|
||||
|
||||
x := cfg.JPush.Channel.Vendor.Xiaomi
|
||||
if x.System != "153609" {
|
||||
t.Errorf("xiaomi.system default = %q, want 153609", x.System)
|
||||
}
|
||||
if x.Chat != "153608" {
|
||||
t.Errorf("xiaomi.chat default = %q, want 153608", x.Chat)
|
||||
}
|
||||
if x.MiSystemTemplateID != "P10761" {
|
||||
t.Errorf("xiaomi.mi_system_template_id default = %q, want P10761", x.MiSystemTemplateID)
|
||||
}
|
||||
if x.MiChatTemplateID != "M10289" {
|
||||
t.Errorf("xiaomi.mi_chat_template_id default = %q, want M10289", x.MiChatTemplateID)
|
||||
}
|
||||
t.Logf("小米默认值生效: system=%s chat=%s mi_sys=%s mi_chat=%s",
|
||||
x.System, x.Chat, x.MiSystemTemplateID, x.MiChatTemplateID)
|
||||
}
|
||||
|
||||
// TestVendorDefaultValuesFromViper 验证:OPPO/vivo/荣耀的分类字段在 yaml 留空时,
|
||||
// viper.SetDefault 设置的默认值能正确填充到 Config 结构体。
|
||||
// channel_id 类字段需厂商后台注册,不在默认值范围(留空)。
|
||||
func TestVendorDefaultValuesFromViper(t *testing.T) {
|
||||
yamlPath := filepath.Join("..", "..", "configs", "config.yaml")
|
||||
cfg, err := Load(yamlPath)
|
||||
if err != nil {
|
||||
t.Fatalf("Load config failed: %v", err)
|
||||
}
|
||||
|
||||
// OPPO: chat=IM/16, system=ACCOUNT/2
|
||||
oppo := cfg.JPush.Channel.Vendor.OPPO
|
||||
if oppo.OppoChatCategory != "IM" {
|
||||
t.Errorf("oppo.oppo_chat_category default = %q, want IM", oppo.OppoChatCategory)
|
||||
}
|
||||
if oppo.OppoSystemCategory != "ACCOUNT" {
|
||||
t.Errorf("oppo.oppo_system_category default = %q, want ACCOUNT", oppo.OppoSystemCategory)
|
||||
}
|
||||
if oppo.OppoChatNotifyLevel != 16 {
|
||||
t.Errorf("oppo.oppo_chat_notify_level default = %d, want 16", oppo.OppoChatNotifyLevel)
|
||||
}
|
||||
if oppo.OppoSystemNotifyLevel != 2 {
|
||||
t.Errorf("oppo.oppo_system_notify_level default = %d, want 2", oppo.OppoSystemNotifyLevel)
|
||||
}
|
||||
|
||||
// vivo: chat=IM, system=ACCOUNT
|
||||
vivo := cfg.JPush.Channel.Vendor.VIVO
|
||||
if vivo.VivoChatCategory != "IM" {
|
||||
t.Errorf("vivo.vivo_chat_category default = %q, want IM", vivo.VivoChatCategory)
|
||||
}
|
||||
if vivo.VivoSystemCategory != "ACCOUNT" {
|
||||
t.Errorf("vivo.vivo_system_category default = %q, want ACCOUNT", vivo.VivoSystemCategory)
|
||||
}
|
||||
|
||||
// 荣耀: chat=NORMAL, system=LOW
|
||||
honor := cfg.JPush.Channel.Vendor.Honor
|
||||
if honor.HonorChatImportance != "NORMAL" {
|
||||
t.Errorf("honor.honor_chat_importance default = %q, want NORMAL", honor.HonorChatImportance)
|
||||
}
|
||||
if honor.HonorSystemImportance != "LOW" {
|
||||
t.Errorf("honor.honor_system_importance default = %q, want LOW", honor.HonorSystemImportance)
|
||||
}
|
||||
|
||||
t.Logf("OPPO: chat=%s/%d system=%s/%d", oppo.OppoChatCategory, oppo.OppoChatNotifyLevel, oppo.OppoSystemCategory, oppo.OppoSystemNotifyLevel)
|
||||
t.Logf("vivo: chat=%s system=%s", vivo.VivoChatCategory, vivo.VivoSystemCategory)
|
||||
t.Logf("荣耀: chat=%s system=%s", honor.HonorChatImportance, honor.HonorSystemImportance)
|
||||
}
|
||||
Reference in New Issue
Block a user