UniPush 2.0 实战指南:工单提醒与多厂商通道配置

1. 方案选型与架构策略

1.1 云服务商选择:推荐腾讯云

在 uniCloud 的服务商选择上,针对企业级项目(尤其是涉及到工单、预警等需要稳定推送的场景),推荐选择 腾讯云

  • 核心优势 :开启"云函数 URL 化"时,腾讯云不需要重新进行域名备案(ICP备案),可以直接使用腾讯云提供的默认域名。
  • 成本考量:虽然单价略高于阿里云,但省去了繁琐的行政备案流程,对于项目快速上线和维护极为有利。

1.2 核心业务流程

我们需要实现的是"点对点"的工单通知,核心逻辑如下:

  1. 前端(APP端) :用户登录后,获取设备的 push_clientid
  2. 绑定关系 :前端调用云函数或接口,将 user_idpush_clientid 存入 uni-id-device 表中(建立用户与设备的映射)。
  3. 后端触发 :由于工单状态变更通常发生在后台(Java/Python/Go等),后端通过 HTTP 请求调用 云函数 URL 化接口
  4. 云函数执行 :云函数根据传入的 user_id 查库找到 CID,调用 uniPush 下发消息。

2. 云函数实现(Core Code)

此云函数作为统一的推送入口,处理了设备查找和多厂商参数适配。

JavaScript

javascript 复制代码
'use strict';
const uniPush = uniCloud.getPushManager({ appId: "__UNI__XXXXXX" }) // 替换你的 appId
const db = uniCloud.database();
const dbCmd = db.command;

exports.main = async (event, context) => {
    // 假设后端通过 POST 请求传入 JSON body
    let body = event.body;
    if(event.isBase64Encoded){
        body = Buffer.from(body, 'base64').toString('utf8');
    }
    const { userIds, title, content } = JSON.parse(body);

    try {
        // --- 3. 查库:获取目标用户的 Push Client ID ---
        const deviceRes = await db.collection('uni-id-device')
            .where({
                user_id: dbCmd.in(userIds)
            })
            .field({ 'push_clientid': true })
            .get();

        if (deviceRes.data.length === 0) {
            return { code: 404, msg: '指定的用户均未绑定任何设备' };
        }

        // 去重,防止同一设备收到多条(如果用户多端登录)
        const cids = [...new Set(deviceRes.data.map(item => item.push_clientid))];

        // --- 4. 执行推送:配置多厂商通道 ---
        const pushRes = await uniPush.sendMessage({
            "push_clientid": cids,
            "title": title,
            "content": content,
            "force_notification": true, // 强制显示通知栏
            "request_id": context.requestId,
            "options": {
                "android": {
                    // --- 小米 (XM) 配置 ---
                    "XM": {
                        // 必须在小米后台申请 Channel ID,否则可能被折叠或静音
                        "/extra.channel_id": "你的小米ChannelID", 
                    },
                    // --- 华为 (HW) 配置 ---
                    "HW": {
                        // 必须配置自分类权益,"SERVICE" 为服务提醒,权重高于默认
                        "/message/android/category": "WORK", // 或 SERVICE
                    },
                    // --- OPPO (OP) 配置 ---
                    "OP": {
                        "/channel_id": "你的OPPO通道ID",
                        "/category": "MARKETING", // 注意:OPPO 营销类消息限制较多,重要通知建议申请私信通道
                        "/notify_level": 16
                    },
                    // --- VIVO (VV) 配置 ---
                    "VV": {
                        "/classification": 1, // 1: 系统类消息 (需要申请),0: 运营类
                    }
                }
            }
        });

        // --- 5. 返回结果 ---
        return {
            code: 0,
            msg: '推送请求已下发',
            target_user_count: userIds.length,
            target_device_count: cids.length,
            uni_push_result: pushRes
        };

    } catch (e) {
        console.error(e);
        return {
            code: 500,
            msg: '服务端内部错误',
            error: e.message
        };
    }
};

3. 安卓厂商特殊配置(必读)

随着 Android 8.0+ 通知渠道(Notification Channels)的引入,如果不进行额外配置,工单提醒很可能会被归类为"营销广告"从而静音折叠

3.1 小米 (Xiaomi) 配置

小米需要创建自定义 Channel 才能让消息正常响铃或震动。

  1. 操作路径:小米开放平台 -> 消息推送 -> 配置管理 -> 通知类别(Channel)管理。

  2. 申请:新建一个类别,例如"工单提醒"或"事务通知"。

  3. 获取 ID :申请通过后,会获得一个 Channel ID(如 Channel_A)。

  4. 代码映射

    JavaScript

    json 复制代码
    "XM": {
        "/extra.channel_id": "你申请的Channel_ID" 
    }

    注意:如果不填,默认走"普通消息"通道,限制较多。

3.2 华为 (Huawei) 配置

华为引入了"自分类权益",需要将消息分类为"服务与通讯"类,否则会被当做"资讯营销"处理。

  1. 操作路径 :华为开发者联盟 -> 我的项目 -> 推送服务 -> 配置 -> 自分类权益

  2. 申请权益:点击申请,按照指引填写(通常需要上传APP截图证明场景)。

  3. 参数设置

    • 在代码中设置 category 字段。
    • WORK:工作事项提醒(适合工单)。
    • IM:即时聊天。
    • 如果不传,默认为 MARKETING(营销),极易被拦截。

    JavaScript

    json 复制代码
    "HW":{
        "/message/android/category": "WORK" 
    }

3.3 OPPO & VIVO 注意事项

  • OPPO :同样有 Channel 概念。私信通道(高权重)需要单独申请邮件报备,且门槛较高。代码中演示的 MARKETING 仅供测试,正式上线建议申请 IM 或业务相关通道。
  • VIVOclassification 为 1 代表系统消息,0 代表运营消息。系统消息配额更高,提醒更明显。

4. 故障排查流程 (Troubleshooting)

当消息没有送达时,请按以下步骤排查:

📌 阶段一:基础环境检查

  1. CID 是否获取成功 :前端 uni.getPushClientId 是否拿到了 ID?如果是在模拟器运行,通常无法获取有效的厂商 CID。

  2. 云函数报错 :查看 uniCloud Web 控制台的云函数日志,检查是否有 appId 不匹配或数据库查询为空的情况。

  3. 打包检查

    • UniPush 2.0 严重依赖应用签名。
    • 必须使用正式签名打包的自定义基座进行调试,标准基座无法测试厂商通道。
    • 确保 manifest.json 中勾选了 UniPush 2.0 并正确填写了各厂商的 AppID/AppKey。

📌 阶段二:离线推送检查(厂商通道)

如果 APP 打开时能收到(走的是个推在线通道),但杀掉进程后收不到(走的是厂商通道),则是厂商配置问题

  1. 检查厂商后台开关:确保在华为/小米等后台,推送服务已"启用"。

  2. 包名与签名 SHA1

    • 华为/小米后台填写的 SHA256SHA1 必须与你打包证书的指纹完全一致
    • 这是最常见的错误原因。
  3. 参数映射

    • 检查云函数代码中 options 里的参数键值对是否按照厂商最新文档编写(如华为的 category 拼写)。
  4. 限流与配额

    • 如果是测试阶段,某些厂商(如 VIVO/OPPO)对未上架应用的推送数量有限制(如一天只能推几条)。

参考文档

相关推荐
Hi_kenyon7 小时前
VUE3套用组件库快速开发(以Element Plus为例)二
开发语言·前端·javascript·vue.js
起名时在学Aiifox7 小时前
Vue 3 响应式缓存策略:从页面状态追踪到智能数据管理
前端·vue.js·缓存
李剑一8 小时前
uni-app实现本地MQTT连接
前端·trae
EndingCoder8 小时前
Any、Unknown 和 Void:特殊类型的用法
前端·javascript·typescript
oden8 小时前
代码高亮、数学公式、流程图... Astro 博客进阶全指南
前端
GIS之路8 小时前
GDAL 实现空间分析
前端
JosieBook9 小时前
【Vue】09 Vue技术——JavaScript 数据代理的实现与应用
前端·javascript·vue.js
pusheng20259 小时前
算力时代的隐形防线:数据中心氢气安全挑战与技术突破
前端·安全
起名时在学Aiifox9 小时前
前端文件下载功能深度解析:从基础实现到企业级方案
前端·vue.js·typescript