6.0 KiB
6.0 KiB
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),对每个目标cidPOST 到配置的CLOUD_FUNC_URL(云函数),或在非云函数模式下调用推送通道。- 云函数(Uni‑Push2):实际负责把推送请求转为厂商推送(uni-push2 / 小米 / 华为 等),并返回调用结果;云函数应做鉴权、日志与重试上报。
云函数化的目标
- 把设备下发逻辑从后端移到可托管的云函数,降低后端对第三方 SDK 的依赖,便于横向扩展与运维隔离。
云函数实现要点(示例流程)
- 接收:
push-server对每个cid发起 POST 到CLOUD_FUNC_URL,body 包含:token, push_clientid, title, content, payload。 - 云函数处理:
- 兼容各云厂商:若
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,需按云平台调整)
// 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 };
}
};
依赖与打包
- 两种方式:
- 使用仓库已有的
server/tools/deploy-cloudfunc.js自动打包并上传(推荐):- 在
server目录安装依赖:npm install archiver node-fetch form-data(如脚本需要)。 - 配置环境变量
CLOUD_UPLOAD_URL、CLOUD_UPLOAD_TOKEN(按脚本要求),运行:cd server node tools/deploy-cloudfunc.js --upload - 脚本会把
uniCloud-alipay/cloudfunctions/testUnipush2打包为 ZIP 并上传。
- 在
- 手工打包上传:将云函数目录打包为 zip,使用云厂商控制台或 API 上传并发布。
- 使用仓库已有的
必备环境变量(运行时)
PUSH_TOKEN:云函数鉴权 token(与push-server中传出的 token 一致)。UNI_PUSH_APPID/UNI_PUSH_SECRET(如厂商需要)。UNI_PUSH_API_URL:可选;当云函数以 HTTP 方式调用第三方推送代理时使用。
测试方法
- 本地快速测试(若云函数开放公网可访问):
curl -X POST https://your-cloudfunc.example/handle \
-H "Content-Type: application/json" \
-d '{"token":"<PUSH_TOKEN>","push_clientid":"CID_TEST","title":"测试","content":"hello","payload":{}}'
- PowerShell 注意 UTF-8 编码,避免中文变成问号:
$json = '{"token":"<PUSH_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-serverconsumer 应实现指数退避的重试;云函数若返回非 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