1. 方案选型与架构策略
1.1 云服务商选择:推荐腾讯云
在 uniCloud 的服务商选择上,针对企业级项目(尤其是涉及到工单、预警等需要稳定推送的场景),推荐选择 腾讯云。
- 核心优势 :开启"云函数 URL 化"时,腾讯云不需要重新进行域名备案(ICP备案),可以直接使用腾讯云提供的默认域名。
- 成本考量:虽然单价略高于阿里云,但省去了繁琐的行政备案流程,对于项目快速上线和维护极为有利。
1.2 核心业务流程
我们需要实现的是"点对点"的工单通知,核心逻辑如下:
- 前端(APP端) :用户登录后,获取设备的
push_clientid。 - 绑定关系 :前端调用云函数或接口,将
user_id与push_clientid存入uni-id-device表中(建立用户与设备的映射)。 - 后端触发 :由于工单状态变更通常发生在后台(Java/Python/Go等),后端通过 HTTP 请求调用 云函数 URL 化接口。
- 云函数执行 :云函数根据传入的
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 才能让消息正常响铃或震动。
-
操作路径:小米开放平台 -> 消息推送 -> 配置管理 -> 通知类别(Channel)管理。
-
申请:新建一个类别,例如"工单提醒"或"事务通知"。
-
获取 ID :申请通过后,会获得一个
Channel ID(如Channel_A)。 -
代码映射:
JavaScript
json"XM": { "/extra.channel_id": "你申请的Channel_ID" }注意:如果不填,默认走"普通消息"通道,限制较多。

3.2 华为 (Huawei) 配置
华为引入了"自分类权益",需要将消息分类为"服务与通讯"类,否则会被当做"资讯营销"处理。
-
操作路径 :华为开发者联盟 -> 我的项目 -> 推送服务 -> 配置 -> 自分类权益。
-
申请权益:点击申请,按照指引填写(通常需要上传APP截图证明场景)。
-
参数设置:
- 在代码中设置
category字段。 WORK:工作事项提醒(适合工单)。IM:即时聊天。- 如果不传,默认为
MARKETING(营销),极易被拦截。
JavaScript
json"HW":{ "/message/android/category": "WORK" } - 在代码中设置

3.3 OPPO & VIVO 注意事项
- OPPO :同样有 Channel 概念。私信通道(高权重)需要单独申请邮件报备,且门槛较高。代码中演示的
MARKETING仅供测试,正式上线建议申请IM或业务相关通道。 - VIVO :
classification为 1 代表系统消息,0 代表运营消息。系统消息配额更高,提醒更明显。
4. 故障排查流程 (Troubleshooting)
当消息没有送达时,请按以下步骤排查:
📌 阶段一:基础环境检查
-
CID 是否获取成功 :前端
uni.getPushClientId是否拿到了 ID?如果是在模拟器运行,通常无法获取有效的厂商 CID。 -
云函数报错 :查看 uniCloud Web 控制台的云函数日志,检查是否有
appId不匹配或数据库查询为空的情况。 -
打包检查:
- UniPush 2.0 严重依赖应用签名。
- 必须使用正式签名打包的自定义基座进行调试,标准基座无法测试厂商通道。
- 确保
manifest.json中勾选了 UniPush 2.0 并正确填写了各厂商的 AppID/AppKey。
📌 阶段二:离线推送检查(厂商通道)
如果 APP 打开时能收到(走的是个推在线通道),但杀掉进程后收不到(走的是厂商通道),则是厂商配置问题。
-
检查厂商后台开关:确保在华为/小米等后台,推送服务已"启用"。
-
包名与签名 SHA1:
- 华为/小米后台填写的
SHA256或SHA1必须与你打包证书的指纹完全一致。 - 这是最常见的错误原因。
- 华为/小米后台填写的
-
参数映射:
- 检查云函数代码中
options里的参数键值对是否按照厂商最新文档编写(如华为的category拼写)。
- 检查云函数代码中
-
限流与配额:
- 如果是测试阶段,某些厂商(如 VIVO/OPPO)对未上架应用的推送数量有限制(如一天只能推几条)。