手把手教你用uniCloud云函数搞定UniPush在线消息推送(附完整代码)
手把手教你用uniCloud云函数搞定UniPush在线消息推送(附完整代码)
在移动应用开发中,消息推送是提升用户活跃度和留存率的关键功能。传统推送方案往往需要开发者自建服务器,不仅增加了运维成本,还要处理复杂的推送服务对接。uniCloud云函数与UniPush的结合,为开发者提供了一种零运维、高可用的推送解决方案。
本文将重点介绍如何利用uniCloud云函数实现UniPush在线消息推送的全流程。不同于客户端配置为主的传统方案,我们将从云函数作为后端服务的角度出发,展示如何将推送逻辑完全托管在uniCloud平台。这种方案特别适合以下场景:
- 中小团队缺乏服务器运维资源
- 需要快速实现推送功能而不想搭建复杂架构
- 希望利用云函数的事件驱动特性实现定时/批量推送
- 需要与uniCloud其他服务(如数据库)深度集成
1. 环境准备与基础配置
1.1 开通UniPush服务
首先需要在DCloud开发者中心完成UniPush服务的开通:
- 登录 DCloud开发者中心
- 进入目标应用管理页面
- 在"服务开通"中找到"UniPush"并点击开通
- 建议选择2.0版本,填写必要信息后提交
注意:测试阶段可使用阿里云免费版uniCloud空间,正式环境建议根据预估推送量选择合适的付费方案。
1.2 配置应用manifest
在HBuilderX中打开项目,配置manifest.json文件:
{ "app-plus": { "push": { "unipush": { "enable": true } } } }然后右键项目,选择"创建云开发环境"并关联你的uniCloud服务空间。这一步会在项目中创建cloudfunctions目录,用于存放云函数代码。
2. 构建推送云函数
2.1 创建云函数
在cloudfunctions目录右键,选择"新建云函数",命名为uniPushSender。创建完成后,右键该函数目录选择"管理公共模块依赖",添加uni-cloud-push依赖。
2.2 编写核心推送代码
打开index.js文件,编写以下基础推送代码:
'use strict'; const uniPush = uniCloud.getPushManager({appId:"__UNI__XXXXXX"}) // 替换为你的应用ID exports.main = async (event, context) => { const { clientId, title, content, payload } = event try { const result = await uniPush.sendMessage({ "push_clientid": clientId, "force_notification": true, "title": title, "content": content, "payload": payload }) return { code: 0, message: '推送成功', data: result } } catch (e) { return { code: -1, message: '推送失败', error: e.message } } }这个基础版本实现了:
- 接收客户端传入的推送参数
- 调用UniPush API发送消息
- 返回标准化结果格式
2.3 高级功能扩展
实际项目中,我们通常需要更复杂的推送逻辑。下面是几个常见扩展点:
批量推送实现:
exports.main = async (event, context) => { const { clientIds, title, content } = event const sendTasks = clientIds.map(clientId => { return uniPush.sendMessage({ push_clientid: clientId, title: title, content: content }).catch(e => ({ error: e.message })) }) const results = await Promise.all(sendTasks) return { total: clientIds.length, success: results.filter(r => !r.error).length, details: results } }定时推送实现:
const schedule = require('node-schedule') exports.main = async (event, context) => { // 示例:每天上午10点推送 const job = schedule.scheduleJob('0 10 * * *', async () => { await uniPush.sendMessage({ push_clientid: event.clientId, title: '每日提醒', content: '这是您的每日定时提醒' }) }) return { message: '定时任务已设置' } }3. 客户端集成与调试
3.1 获取客户端CID
在App.vue中添加以下代码获取客户端唯一标识:
onLaunch() { this.getPushClientId() }, methods: { getPushClientId() { const timer = setTimeout(() => { plus.push.getClientInfoAsync(info => { if (info.clientid) { clearTimeout(timer) uni.setStorageSync('push_cid', info.clientid) console.log('ClientID:', info.clientid) // 通常这里会将CID发送到服务器与用户关联 this.uploadClientId(info.clientid) } }, error => { console.error('获取ClientID失败:', error) }) }, 3000) }, uploadClientId(cid) { uniCloud.callFunction({ name: 'saveClientId', data: { userId: getApp().globalData.userId, clientId: cid } }) } }3.2 调用云函数发送推送
在需要发送推送的页面中:
async sendTestPush() { const res = await uniCloud.callFunction({ name: 'uniPushSender', data: { clientId: uni.getStorageSync('push_cid'), title: '测试推送', content: '这是一条测试消息', payload: { type: 'test', page: '/pages/index/index' } } }) if (res.result.code === 0) { uni.showToast({ title: '推送已发送' }) } else { uni.showToast({ title: '发送失败', icon: 'error' }) } }4. 生产环境最佳实践
4.1 性能优化建议
当推送量较大时,需要考虑以下优化措施:
| 优化方向 | 具体措施 | 预期效果 |
|---|---|---|
| 批量处理 | 将多个推送合并为一个请求 | 减少API调用次数 |
| 异步处理 | 使用云函数队列 | 提高响应速度 |
| 缓存机制 | 缓存活跃用户CID | 减少数据库查询 |
| 错误处理 | 实现自动重试机制 | 提高送达率 |
4.2 安全防护措施
推送功能需要注意以下安全问题:
请求验证:
exports.main = async (event, context) => { // 验证调用来源 if (context.SOURCE !== 'http' && context.SOURCE !== 'cloud') { throw new Error('非法调用') } // 验证调用权限 const auth = await checkAuth(context) if (!auth.valid) { throw new Error('无权限操作') } }频率限制:
const rateLimit = require('uni-cloud-rate-limit') exports.main = rateLimit({ max: 100, // 每分钟最大调用次数 duration: 60 * 1000 }, async (event, context) => { // 业务代码 })敏感信息加密:
const crypto = require('crypto') function encryptClientId(cid) { const cipher = crypto.createCipheriv('aes-256-cbc', key, iv) let encrypted = cipher.update(cid, 'utf8', 'hex') encrypted += cipher.final('hex') return encrypted }
4.3 监控与统计
建议添加推送结果统计功能:
const db = uniCloud.database() async function logPushResult(clientId, status, extra = {}) { await db.collection('push_logs').add({ clientId, status, createdAt: Date.now(), ...extra }) } exports.main = async (event, context) => { try { const result = await uniPush.sendMessage(/*...*/) await logPushResult(event.clientId, 'success', { messageId: result.messageId }) return result } catch (e) { await logPushResult(event.clientId, 'failed', { error: e.message }) throw e } }这套日志系统可以帮助你:
- 统计推送成功率
- 分析失败原因
- 追踪特定���息的送达状态
- 生成推送效果报表
