Uni‑Push2 云函数化指南 概述 - 后台实现概览: - `webhook-receiver`(pages/mall/delivery/webhook-server):接收第三方/Mock Webhook,验签并写入 `platform_express_tracking_events`(原始留痕 `platform_express_event_raw`)。 - `notify_queue`(或触发器):新事件入队,作为消息生成的可靠中间件。 - `notify-worker.js`:消费 `notify_queue`,为每个收件人生成/upsert 到 `express_notifications`(含 `message_id`/`dedupe_key`、`event_text_safe` 等)。 - `push-server.js`:提供设备管理 API(`push/register` 等)并作为推送消费者(轮询 `express_notifications`),对每个目标 `cid` POST 到配置的 `CLOUD_FUNC_URL`(云函数),或在非云函数模式下调用推送通道。 - 云函数(Uni‑Push2):实际负责把推送请求转为厂商推送(uni-push2 / 小米 / 华为 等),并返回调用结果;云函数应做鉴权、日志与重试上报。 云函数化的目标 - 把设备下发逻辑从后端移到可托管的云函数,降低后端对第三方 SDK 的依赖,便于横向扩展与运维隔离。 云函数实现要点(示例流程) 1) 接收:`push-server` 对每个 `cid` 发起 POST 到 `CLOUD_FUNC_URL`,body 包含:`token, push_clientid, title, content, payload`。 2) 云函数处理: - 兼容各云厂商:若 `event.body` 为字符串,先 JSON.parse;兼容 `event` 直接对象场景。 - 鉴权:校验 `event.token` 与环境变量 `PUSH_TOKEN`。 - 校验:要求 `push_clientid` 存在,否则返回 4xx。 - 调用 uni-push2:用云端可用的 SDK 或 HTTP 接口下发推送(参见示例代码)。 - 返回统一响应:HTTP 2xx + JSON { errCode:0, errMsg:'success' } 表示成功。 云函数示例(Node.js,需按云平台调整) ```javascript // index.js const fetch = require('node-fetch'); // 如果云平台不提供 fetch module.exports.main = async (event, context) => { let input = event || {}; if (typeof input.body === 'string') { try { input = JSON.parse(input.body); } catch (e) { /* ignore */ } } const { token, push_clientid, title, content, payload } = input; if (process.env.PUSH_TOKEN && token !== process.env.PUSH_TOKEN) { return { errCode:401, errMsg:'unauthorized' }; } if (!push_clientid) return { errCode:400, errMsg:'push_clientid required' }; // TODO: 替换为你云函数环境支持的 uni-push2 调用 // 示例:调用一个第三方/自托管的推送服务 API const uniPushUrl = process.env.UNI_PUSH_API_URL; // 可选:如果使用自建转发层 const body = { appid: process.env.UNI_PUSH_APPID, clientid: push_clientid, title, content, payload }; try { // 如果你在云函数中安装了 uni-push2 SDK,请在此调用 SDK // 下面为通用 fetch 示例(替换为真实厂商 API) const r = await fetch(uniPushUrl, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(body) }); const txt = await r.text(); if (!r.ok) return { errCode: 500, errMsg: 'push-failed', detail: txt }; return { errCode:0, errMsg:'success', data: txt }; } catch (e) { return { errCode:500, errMsg:'exception', detail: e && e.message }; } }; ``` 依赖与打包 - 两种方式: 1) 使用仓库已有的 `server/tools/deploy-cloudfunc.js` 自动打包并上传(推荐): - 在 `server` 目录安装依赖:`npm install archiver node-fetch form-data`(如脚本需要)。 - 配置环境变量 `CLOUD_UPLOAD_URL`、`CLOUD_UPLOAD_TOKEN`(按脚本要求),运行: ```powershell cd server node tools/deploy-cloudfunc.js --upload ``` - 脚本会把 `uniCloud-alipay/cloudfunctions/testUnipush2` 打包为 ZIP 并上传。 2) 手工打包上传:将云函数目录打包为 zip,使用云厂商控制台或 API 上传并发布。 必备环境变量(运行时) - `PUSH_TOKEN`:云函数鉴权 token(与 `push-server` 中传出的 token 一致)。 - `UNI_PUSH_APPID` / `UNI_PUSH_SECRET`(如厂商需要)。 - `UNI_PUSH_API_URL`:可选;当云函数以 HTTP 方式调用第三方推送代理时使用。 测试方法 - 本地快速测试(若云函数开放公网可访问): ```bash curl -X POST https://your-cloudfunc.example/handle \ -H "Content-Type: application/json" \ -d '{"token":"","push_clientid":"CID_TEST","title":"测试","content":"hello","payload":{}}' ``` - PowerShell 注意 UTF-8 编码,避免中文变成问号: ```powershell $json = '{"token":"","push_clientid":"CID_TEST","title":"测试","content":"内容"}' $bytes = [System.Text.Encoding]::UTF8.GetBytes($json) Invoke-RestMethod -Uri 'https://your-cloudfunc.example/handle' -Method POST -ContentType 'application/json; charset=utf-8' -Body $bytes ``` 运维与监控建议 - 日志:云函数应把每次调用的 request/response 摘要记录到云日志(包括 `push_clientid`、status、耗时、ret code),便于排查。不要在日志中输出完整敏感 payload。 - 重试:`push-server` consumer 应实现指数退避的重试;云函数若返回非 2xx,被视为失败并重试。云函数内部也应对推送通道失败做重试或将错误上报。 - 鉴权与安全:`PUSH_TOKEN` 放在云函数的环境变量中并由 `push-server` 透传;上传/部署脚本的 `CLOUD_UPLOAD_TOKEN` 等密钥使用 CI Secrets。 常见坑 - Cloud 函数平台把请求体放在 `event.body`(字符串)——必须解析。示例代码已处理此场景。 - PowerShell 发送 JSON 时编码问题,导致中文变问号——请用 UTF-8 bytes 或 `curl.exe`。 - 若云函数调用 uni-push SDK,需要在函数包中包含对应 SDK 并在打包时一并上传。 参考文件 - push-server 实现:server/push-server.js - notify-worker:server/notify-worker.js - 云函数目录(示例):uniCloud-alipay/cloudfunctions/testUnipush2 - 自动部署脚本:server/tools/deploy-cloudfunc.js --- 作者:自动生成文档(可手动微调) 日期:2026-03-11