从云函数到客户端:UniPush 2.0全链路消息推送实战指南
在移动应用生态中,消息推送始终是用户留存和业务触达的核心能力。根据第三方统计数据显示,合理配置推送功能的应用用户活跃度可提升40%以上。本文将基于UniApp技术栈,完整演示如何通过UniPush 2.0构建从服务端触发到客户端接收的闭环推送系统。不同于零散的配置文档,我们将以电商订单通知为业务场景,贯穿云函数编写、客户端监听、厂商通道适配等全流程关键技术点。
1. 环境准备与基础配置
1.1 创建UniCloud云服务
在HBuilderX中新建uni-app项目时,需同时启用uniCloud支持。项目创建完成后,右键点击uniCloud目录选择"关联云服务空间",按向导完成阿里云或腾讯云的环境绑定。重要提示:若计划使用厂商离线推送功能,建议直接选择阿里云作为服务商,因其与个推服务有深度集成。
基础配置清单:
manifest.json中确保已勾选Push模块- 应用包名遵循
com.company.project格式 - 在DCloud开发者中心完成应用信息登记
// manifest.json示例片段 "app-plus": { "distribute": { "android": { "permissions": [ "<uses-permission android:name=\"android.permission.INTERNET\"/>", "<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\"/>" ] } } }1.2 厂商通道配置要点
针对需要离线推送的Android设备,需配置各厂商通道。以华为为例:
- 登录华为开发者联盟
- 在「应用服务」-「推送服务」中创建应用
- 申请
DEVICE_REMINDER消息分类权限 - 获取APP ID和APP Secret填入UniPush配置页
注意:vivo和OPPO平台要求应用上架后才能开通推送服务。开发阶段可通过提交测试申请临时获取权限,但需在应用发布后重新配置。
2. 云函数端实现
2.1 创建推送云函数
在uniCloud/cloudfunctions目录右键新建Node.js云函数,命名为uni-push-demo。关键步骤:
- 右键云函数选择「管理公共模块或扩展库」
- 添加
uni-cloud-push扩展库依赖 - 创建必要的opendb表(自动创建或手动执行)
// 基础云函数结构 'use strict'; const uniPush = uniCloud.getPushManager({ appId: "__UNI__XXXXXX" }) // 替换实际APPID exports.main = async (event, context) => { // 业务逻辑实现 };2.2 消息推送核心逻辑
完整实现包含参数校验、错误处理、多厂商适配的推送示例:
const payloadValidator = (params) => { const requiredFields = ['title', 'content', 'cid']; const missingFields = requiredFields.filter(field => !params[field]); if (missingFields.length > 0) { throw new Error(`缺少必要参数: ${missingFields.join(',')}`); } }; exports.main = async (event) => { try { const pushParams = JSON.parse(event.body); payloadValidator(pushParams); const result = await uniPush.sendMessage({ "push_clientid": pushParams.cid, "title": pushParams.title, "content": pushParams.content, "payload": pushParams.payload || {}, "settings": { "ttl": 86400000, // 24小时有效期 "apns": { "sound": "default" } }, "options": { "HW": { "/message/android/category": 'DEVICE_REMINDER' }, "XM": { "/extra.channel_id": "192" } } }); return { code: 0, data: result }; } catch (err) { return { code: -1, message: err.message, stack: process.env.NODE_ENV === 'development' ? err.stack : undefined }; } };3. 客户端集成方案
3.1 设备注册与CID获取
在App.vue的onLaunch生命周期中初始化推送客户端:
export default { onLaunch() { this.initPushService(); }, methods: { async initPushService() { try { const { cid } = await uni.getPushClientId(); console.log('Device CID:', cid); await this.uploadCidToServer(cid); // 上传CID到业务服务器 } catch (err) { console.error('Push init failed:', err); } } } }3.2 消息监听处理
实现前台消息和通知栏点击的统一处理:
// 在App.vue中增加监听 created() { uni.onPushMessage((res) => { this.handlePushPayload(JSON.parse(res.data)); }); }, methods: { handlePushPayload(payload) { switch(payload.type) { case 'ORDER_UPDATE': this.showOrderStatusModal(payload); break; default: uni.showToast({ title: payload.content }); } } }4. 高级场景与性能优化
4.1 消息分类策略
针对不同业务场景设计消息分级体系:
| 消息类型 | 优先级 | 过期时间 | 厂商通道要求 |
|---|---|---|---|
| 交易通知 | HIGH | 24小时 | 必须配置分类 |
| 营销活动 | MEDIUM | 6小时 | 需要用户授权 |
| 系统消息 | LOW | 1小时 | 无特殊要求 |
4.2 云函数URL化配置
为方便传统后端系统调用,可将云函数URL化:
- 在uniCloud web控制台找到目标云函数
- 进入「URL化」配置选项卡
- 设置访问路径和IP白名单(生产环境必选)
调用示例:
curl -X POST https://your-domain.com/uni-push \ -H "Content-Type: application/json" \ -d '{"title":"订单发货","content":"您的订单已出库","cid":"client-id-123"}'4.3 离线推送兼容方案
针对不同厂商平台的特性处理:
- 华为/荣耀:需在payload中添加
/do_not_store字段控制是否存离线 - 小米:消息必须包含
extra.channel_id且与申请时一致 - OPPO:需要同时设置
/channel_id和/category参数 - vivo:单日推送限额5000条,超出部分自动转为在线推送
// 厂商特殊参数示例 const vendorOptions = { "OPPO": { "/channel_id": "push_oplus_category_content", "/notify_level": 2 }, "VV": { "/skip_on_foreground": false } };5. 调试与问题排查
5.1 常见错误代码对照表
| 错误码 | 含义 | 解决方案 |
|---|---|---|
| 20001 | CID无效 | 检查设备注册流程 |
| 30003 | 配额超限 | 申请厂商配额提升 |
| 40002 | 参数缺失 | 验证title/content字段 |
| 50005 | 证书不匹配 | 重新上传厂商推送证书 |
5.2 真机调试技巧
- 使用Android Studio的Logcat过滤
UniPush标签 - 在开发者选项中开启「显示通知详情」
- 对于厂商通道问题,直接使用对应品牌的远程真机测试
调试建议:先确保在线推送正常,再测试离线场景。遇到厂商通道问题时,优先检查对应开放平台的消息状态报告。
在实际项目交付中,我们发现华为设备对payload大小限制较严格(不超过4KB),而小米设备在应用退后台时会有10秒左右的延迟。这些特性需要在业务逻辑中做兼容处理,比如添加重试机制和本地消息缓存。