Skip to content

sarices/FlareMsg

Repository files navigation

FlareMsg

基于 Cloudflare Workers 的微信消息推送服务,提供简单的 HTTP API 接口,自动管理微信 Access Token,支持发送模版消息。

功能特性

  • ✅ 无服务器架构,部署在 Cloudflare 边缘网络
  • ✅ 自动管理微信 Access Token(KV 缓存 + 自动刷新)
  • ✅ Token 失效自动重试机制
  • ✅ 支持 GET 和 POST 双重请求方式
  • ✅ 支持用户级 Token(sk_ 前缀,无需提供 openid)
  • ✅ Web 管理界面,可视化管理用户 Token
  • ✅ 支持参数优先级配置(请求参数 > 环境变量 > 默认值)
  • ✅ 支持自定义消息内容和跳转链接
  • ✅ 完整的鉴权机制(全局 Token + 用户 Token)

快速开始

1. 前置准备

  • 注册 Cloudflare 账号
  • 安装 Node.js (推荐 v20+, Wrangler v4 要求)
  • 获取微信测试公众号:
    • 访问 微信公众平台测试号
    • 记录 appIDappSecret
    • 创建模版消息
      1. 点击"新增测试模版"
      2. 模版标题:随意填写(如"系统通知")
      3. 模版内容:必须使用以下格式
        {{FROM.DATA}}
        {{DESC.DATA}}
        {{REMARK.DATA}}
        
      4. 点击"确定"后,记录生成的 template_id(形如 xBxxxxxxxxxxxxxx
    • 关注测试号,获取个人 openid

2. 安装依赖

npm install

3. 配置项目

3.1 创建 KV Namespace

Cloudflare Workers KV 是一个全球分布的键值存储服务,用于存储微信 Access Token 和用户 Token 数据。

什么是 KV Namespace?

KV Namespace 是 Cloudflare Workers 提供的键值对存储空间,类似于 Redis,但具有全球低延迟访问的特点。在本项目中,KV 用于:

  • 缓存微信 Access Token(避免频繁调用微信 API)
  • 存储用户 Token(sk_ 前缀的 token 与 openid 的映射关系)

创建生产环境 KV Namespace

npx wrangler kv namespace create WECHAT_KV

执行后会返回类似以下内容:

🌀 Creating namespace with title "flaremsg-WETCHAT_KV"
✨ Success!
Add the following to your configuration file in your kv_namespaces array:
{ binding = "WECHAT_KV", id = "xxxxxxxxxxxxxxxxxxxxxxxxxxxx" }

理解 Worker 与 KV 的绑定关系

wrangler.toml 中,KV Namespace 通过两个关键参数绑定到 Worker:

[[kv_namespaces]]
binding = "WECHAT_KV"  # 绑定名称:在代码中通过这个名称访问 KV
id = "xxxxxxxxxxxx"    # 命名空间 ID:Cloudflare 分配的唯一标识
  • binding(绑定名称):在代码中使用的变量名

    • 例如在代码中:env.WECHAT_KV.get("access_token")
    • 就像给 KV 存储空间起了一个"别名",方便代码引用
  • id(命名空间 ID):KV 在 Cloudflare 系统中的唯一标识

    • 由 Cloudflare 自动生成
    • 类似于数据库的连接字符串

配置方式

方式一:手动配置(用于本地开发)

  1. 复制命令返回的 id
  2. wrangler.toml 中解除 id 字段的注释:
    [[kv_namespaces]]
    binding = "WECHAT_KV"
    id = "xxxxxxxxxxxxxxxxxxxxxxxxxxxx"  # 替换为实际 ID

方式二:GitHub Actions 自动配置(推荐用于生产环境)

保持 id 字段注释状态,在 GitHub Secrets 中添加:

  • KV_NAMESPACE_ID:运行 npx wrangler kv namespace create WECHAT_KV 返回的 ID

GitHub Actions 会在部署前自动将 wrangler.toml 中的占位符替换为实际值。

验证 KV 绑定是否成功

部署后,访问以下 URL 测试:

curl https://your-worker.workers.dev/

如果返回正常网页,说明 Worker 与 KV 绑定成功。

3.2 配置环境变量

编辑 wrangler.toml,配置微信模版 ID:

方式一:直接修改(推荐用于本地部署)

WECHAT_TEMPLATE_ID 的值 YOUR_TEMPLATE_ID 替换为你的实际模版 ID:

WECHAT_TEMPLATE_ID = "xBxxxxxxxxxxxxxx"  # 替换为你的模版 ID

方式二:使用 GitHub Actions(推荐用于自动部署)

保持占位符不变,在 GitHub Secrets 中添加 WECHAT_TEMPLATE_ID,部署时会自动替换。

其他可选配置(默认消息内容、颜色等)可根据需要调整。

3.3 设置敏感信息(Secrets)

npx wrangler secret put WECHAT_APP_ID
# 输入你的微信 AppID

wrangler secret put WECHAT_APP_SECRET
# 输入你的微信 AppSecret

wrangler secret put CLIENT_AUTH_TOKEN
# 输入你自定义的 API 鉴权密钥

4. 本地开发

npm run dev

访问 http://localhost:8787 进行测试。

5. 部署到 Cloudflare

npm run deploy

部署成功后,你会得到一个 *.workers.dev 的 URL。

API 使用

网页测试界面(推荐用于快速测试)

访问 https://your-worker.workers.dev/ 即可打开网页测试界面。

功能特性

  • 📝 可视化表单,无需编写代码
  • 🔒 安全的密码输入框保护 Token
  • ⚡ 实时反馈发送结果
  • 🎨 精美的暗黑/浅色主题

使用步骤

  1. 打开首页,填写以下字段:
    • 鉴权密钥:输入 CLIENT_AUTH_TOKEN 的值(必填)
    • 微信 OpenID:输入接收者的 OpenID(必填)
    • 消息来源:例如"系统监控"(可选)
    • 消息内容:例如"服务器 CPU 使用率过高"(必填)
    • 备注信息:例如"请及时查看"(可选)
    • 跳转链接:点击消息后跳转的 URL(可选)
  2. 点击"发送消息"按钮
  3. 查看发送结果,成功时会显示消息 ID

重要提示

  • 消息内容(desc)是必填字段,这是显示在微信消息中的主要内容
  • 如果收到消息但看不到内容,请检查:
    • 模版内容是否为 {{FROM.DATA}}{{DESC.DATA}}{{REMARK.DATA}}
    • 发送时是否填写了"消息内容"字段
    • wrangler.toml 中是否配置了 WECHAT_TEMPLATE_ID

鉴权机制

FlareMsg 支持两种 Token 鉴权方式:

1. 全局 Token(原有方式)

  • 使用 CLIENT_AUTH_TOKEN 环境变量配置的密钥
  • 需要同时提供 openid 参数
  • 适合管理员或系统级别的消息发送

2. 用户 Token(推荐)

  • 格式:sk_ 开头的随机字符串(如 sk_abc123xyz
  • 存储在 KV 中,Key 为 token,Value 为对应的 openid
  • 无需提供 openid 参数,系统自动从 KV 获取
  • 适合为单个用户或应用分配独立的推送密钥

请求格式

方式一:GET 请求

Endpoint: GET /send

Query 参数:

token=your_auth_token
&openid=user_openid (可选,使用用户 Token 时不需要)
&from=消息来源
&desc=消息内容
&remark=备注
&url=跳转链接

示例:

# 使用全局 Token
curl "https://your-worker.workers.dev/send?token=YOUR_TOKEN&openid=USER_OPENID&desc=测试消息"

# 使用用户 Token(无需 openid)
curl "https://your-worker.workers.dev/send?token=sk_abc123&desc=测试消息"

方式二:POST 请求

Endpoint: POST /send

Headers:

Content-Type: application/json

Body:

{
  "token": "your_auth_token",
  "openid": "user_openid",
  "from": "服务器 A",
  "desc": "磁盘使用率达到 90%",
  "remark": "请及时处理",
  "url": "https://console.example.com"
}

参数说明:

  • token (必填): API 鉴权密钥
    • 全局 Token:需与 CLIENT_AUTH_TOKEN 一致
    • 用户 Token:sk_ 开头的字符串,自动关联 openid
  • openid (条件必填): 微信用户的 OpenID
    • 使用全局 Token 时必填
    • 使用用户 Token(sk_ 开头)时不需要
  • from (可选): 消息来源/标题
  • desc (可选): 消息主要内容
  • remark (可选): 备注信息
  • url (可选): 点击消息跳转的链接

响应格式

成功:

{
  "errcode": 0,
  "errmsg": "ok",
  "msgid": 123456789
}

失败:

{
  "errcode": -1,
  "errmsg": "错误描述"
}

使用示例

cURL

# 使用全局 Token(需要 openid)
curl -X POST https://your-worker.workers.dev/send \
  -H "Content-Type: application/json" \
  -d '{
    "token": "your_client_auth_token",
    "openid": "oABCD1234567890",
    "from": "监控系统",
    "desc": "服务器 CPU 使用率过高",
    "remark": "当前使用率: 95%",
    "url": "https://monitor.example.com"
  }'

# 使用用户 Token(无需 openid)
curl -X POST https://your-worker.workers.dev/send \
  -H "Content-Type: application/json" \
  -d '{
    "token": "sk_abc123xyz",
    "from": "监控系统",
    "desc": "服务器 CPU 使用率过高"
  }'

# GET 请求方式
curl "https://your-worker.workers.dev/send?token=sk_abc123xyz&desc=测试消息&from=API调用"

Python

import requests

# 使用用户 Token(推荐)
url = "https://your-worker.workers.dev/send"
payload = {
    "token": "sk_abc123xyz",
    "from": "监控系统",
    "desc": "服务器 CPU 使用率过高",
    "remark": "当前使用率: 95%",
    "url": "https://monitor.example.com"
}

response = requests.post(url, json=payload)
print(response.json())

Node.js

// 使用用户 Token(推荐)
const response = await fetch("https://your-worker.workers.dev/send", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    token: "sk_abc123xyz",
    from: "监控系统",
    desc: "服务器 CPU 使用率过高",
    remark: "当前使用率: 95%",
    url: "https://monitor.example.com",
  }),
});

const result = await response.json();
console.log(result);

JavaScript / Browser

// 使用 GET 请求和用户 Token
const url = new URL('https://your-worker.workers.dev/send');
url.searchParams.set('token', 'sk_abc123xyz');
url.searchParams.set('desc', '测试消息');
url.searchParams.set('from', 'Web应用');

fetch(url)
  .then(res => res.json())
  .then(data => console.log(data));

管理功能

FlareMsg 提供了 Web 管理界面和 REST API,用于管理用户 Token。

Web 管理界面

访问 https://your-worker.workers.dev/admin 即可进入管理页面。

功能特性

  • 🔐 安全的登录验证(需要 CLIENT_AUTH_TOKEN
  • 📋 查看所有用户 Token(仅 sk_ 开头的 Token)
  • ➕ 添加新 Token(自动生成 sk_ 前缀的随机 Token)
  • 🗑️ 删除指定 Token
  • 📋 一键复制 Token 到剪贴板

使用步骤

  1. 访问 /admin 页面
  2. 输入管理员 Token(CLIENT_AUTH_TOKEN
  3. 登录后可以:
    • 在"添加用户 Token"区域输入用户的 OpenID
    • 系统自动生成形如 sk_abc123xyz 的 Token
    • 查看、复制或删除现有 Token

管理 API

列出所有用户 Token

curl -H "Authorization: Bearer CLIENT_AUTH_TOKEN" \
  https://your-worker.workers.dev/admin/api/tokens

响应

{
  "tokens": [
    {
      "key": "sk_abc123xyz",
      "value": "oABCD1234567890"
    },
    {
      "key": "sk_def456uvw",
      "value": "oEFGH9876543210"
    }
  ]
}

添加新用户 Token

curl -X POST https://your-worker.workers.dev/admin/api/tokens \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer CLIENT_AUTH_TOKEN" \
  -d '{"openid": "oABCD1234567890"}'

响应

{
  "success": true,
  "key": "sk_abc123xyz",
  "value": "oABCD1234567890"
}

删除用户 Token

curl -X DELETE "https://your-worker.workers.dev/admin/api/tokens?key=sk_abc123xyz" \
  -H "Authorization: Bearer CLIENT_AUTH_TOKEN"

响应

{
  "success": true,
  "message": "Token deleted successfully"
}

安全建议

  1. 保护管理员 Token

    • CLIENT_AUTH_TOKEN 应该妥善保管
    • 不要在前端代码中暴露
    • 定期更换
  2. 用户 Token 分配

    • 为不同的用户/应用分配独立的 Token
    • Token 泄露时只需删除对应的 Token,不影响其他用户
    • 定期审计 Token 使用情况
  3. 访问控制

    • 管理页面应该通过 IP 白名单或 VPN 限制访问
    • 可以通过 Cloudflare Workers 的 Access 功能添加额外保护

配置说明

参数优先级

所有消息字段都遵循三级优先级:

HTTP 请求参数 > 环境变量默认值 > 代码内置默认值

例如,from 字段的取值逻辑:

  1. 如果请求中提供了 from,使用请求值
  2. 否则使用 wrangler.toml 中的 DEFAULT_FROM
  3. 否则使用代码默认值 "系统通知"

环境变量列表

变量名 类型 必填 说明
WECHAT_APP_ID Secret 微信公众号 AppID
WECHAT_APP_SECRET Secret 微信公众号 AppSecret
WECHAT_TEMPLATE_ID Var 微信消息模版 ID
CLIENT_AUTH_TOKEN Secret API 调用鉴权密钥
KV_BINDING_NAME Var KV Namespace 的 binding 名称(默认: "WECHAT_KV")
DEFAULT_FROM Var 默认来源标题
DEFAULT_DESC Var 默认消息内容
DEFAULT_REMARK Var 默认备注
DEFAULT_URL Var 默认跳转链接
COLOR_FROM Var 标题颜色(十六进制)
COLOR_DESC Var 内容颜色(十六进制)
COLOR_REMARK Var 备注颜色(十六进制)

技术架构

核心流程

  1. 请求验证: 检查 HTTP Method 和鉴权 Token
  2. 参数解析: 提取消息内容和目标用户
  3. Token 管理: 从 KV 读取或刷新 Access Token
  4. 消息发送: 调用微信 API 发送模版消息
  5. 自动重试: Token 失效时自动刷新并重试

Token 管理机制

  • Access Token 缓存在 Cloudflare KV 中
  • TTL 设置为 7000 秒(略低于微信官方 7200 秒)
  • 检测到 errcode: 40001 时自动删除缓存并重试
  • 避免频繁调用微信 Token 接口
  • 支持自定义 KV Namespace binding 名称,避免与现有项目冲突
    • 默认使用 WECHAT_KV binding
    • 可通过 KV_BINDING_NAME 环境变量指定其他 binding 名称

故障排查

常见错误

401 Unauthorized

  • 检查 CLIENT_AUTH_TOKEN 是否正确设置
  • 确认请求中的 token 参数与环境变量一致

400 Missing required parameter: openid

  • 确保请求中包含 openid 字段

Token 获取失败

  • 检查 WECHAT_APP_IDWECHAT_APP_SECRET 是否正确
  • 确认微信公众号状态正常

消息发送失败 (errcode: 40001)

  • 系统会自动重试一次
  • 如果持续失败,检查微信公众号配置

查看日志

npx wrangler tail

项目文档

以下是本项目的详细文档:

许可证

MIT License

About

基于 Cloudflare Workers 的微信消息推送服务,提供简单的 HTTP API 接口,自动管理微信 Access Token,支持发送模版消息。

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors