117 lines
6.0 KiB
Markdown
117 lines
6.0 KiB
Markdown
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_TOKEN>","push_clientid":"CID_TEST","title":"测试","content":"hello","payload":{}}'
|
||
```
|
||
- PowerShell 注意 UTF-8 编码,避免中文变成问号:
|
||
```powershell
|
||
$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-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
|