// Worker入口 export default { async fetch(request, env, ctx) { const url = new URL(request.url); if (url.pathname === "/skin") { return htmlResponse(createSkinHTML( url.searchParams.get("title") || "消息推送", url.searchParams.get("message") || "无告警信息", url.searchParams.get("date") || "无时间信息" )); } const singleSeg = url.pathname.match(/^\/([^\/]+)\/?$/); if (singleSeg && singleSeg[1] && singleSeg[1] !== "wxsend" && singleSeg[1] !== "index.html") { const token = singleSeg[1]; const err = validateToken(token, env); if (err) return err; return htmlResponse(createTestHTML(escapeHTML(token))); } if (url.pathname === "/wxsend") { return handleWxSend(request, env); } if (request.method === "GET" && (url.pathname === "/" || url.pathname === "/index.html")) { const hasParams = url.searchParams.get("title") || url.searchParams.get("message") || url.searchParams.get("date"); if (hasParams) { return htmlResponse(createSkinHTML( url.searchParams.get("title") || "消息推送", url.searchParams.get("message") || "无告警信息", url.searchParams.get("date") || "无时间信息" )); } return htmlResponse(createHomeHTML()); } return new Response("Not Found", { status:404 }); } }; // 微信发送 async function handleWxSend(request, env) { const params = await getParams(request); const token = getRequestToken(params, request); if (!params.content || !params.title || !token) { return jsonResponse({msg:"Missing required parameters: content, title, token"},400); } const tokenErr = validateToken(token, env); if (tokenErr) return tokenErr; // 对IP地址进行转义,避免微信识别为链接触发下载 const title = escapeIP(params.title); const content = escapeIP(params.content); const appid = params.appid || env.WX_APPID; const secret = params.secret || env.WX_SECRET; const useridStr = params.userid || env.WX_USERID; const template_id = params.template_id || env.WX_TEMPLATE_ID; const base_url = params.base_url || env.WX_BASE_URL; if (!appid || !secret || !useridStr || !template_id) { return jsonResponse({ msg:"Missing required environment variables: WX_APPID, WX_SECRET, WX_USERID, WX_TEMPLATE_ID" },500); } try { const accessToken = await getStableToken(appid, secret); if (!accessToken) return jsonResponse({msg:"Failed to get access token"},500); const results = await Promise.all( parseUsers(useridStr).map(userid => sendMessage(accessToken, userid, template_id, base_url, title, content) ) ); const success = results.filter(r => r.errmsg === "ok"); if (success.length > 0) { return jsonResponse({ msg:`Successfully sent messages to ${success.length} user(s). First response: ok` }); } return jsonResponse({ msg:`Failed to send messages. First error: ${results[0]?.errmsg || "Unknown error"}` },500); } catch(e) { console.error(e); return jsonResponse({msg:`An error occurred: ${e.message}`},500); } } // 参数解析 async function getParams(request) { const {searchParams} = new URL(request.url); const urlParams = Object.fromEntries(searchParams.entries()); let bodyParams = {}; if (["POST","PUT","PATCH"].includes(request.method)) { const type = (request.headers.get("content-type") || "").toLowerCase(); try { if (type.includes("application/json")) { const body = await request.json(); bodyParams = typeof body === "string" ? {content:body} : (body?.params || body?.data || body || {}); } else if ( type.includes("application/x-www-form-urlencoded") || type.includes("multipart/form-data") ) { bodyParams = Object.fromEntries((await request.formData()).entries()); } else { const text = await request.text(); if (text) { try { const body = JSON.parse(text); bodyParams = body && typeof body === "object" ? (body.params || body.data || body) : {content:text}; } catch { bodyParams = {content:text}; } } } } catch(e) { console.error("parse body error",e); } } return {...urlParams,...bodyParams}; } // Token验证 function validateToken(token, env) { if (token !== env.API_TOKEN) { return jsonResponse({msg:"Invalid token"},403); } return null; } // 获取请求Token function getRequestToken(params, request) { let token = params.token; if (!token) { const auth = request.headers.get("Authorization") || request.headers.get("authorization"); if (auth) { const parts = auth.trim().split(/\s+/); token = parts.length === 2 && /^Bearer$/i.test(parts[0]) ? parts[1] : auth; } } return token; } // 用户处理 function parseUsers(str) { return str.split("|").map(x=>x.trim()).filter(Boolean); } // JSON响应 function jsonResponse(body,status=200) { return new Response(JSON.stringify(body),{ status, headers:{ "Content-Type":"application/json;charset=utf-8" } }); } // HTML响应 function htmlResponse(html) { return new Response(html,{ headers:{ "Content-Type":"text/html;charset=UTF-8" } }); } // HTML转义 function escapeHTML(str) { return String(str) .replace(/&/g,"&") .replace(//g,">") .replace(/"/g,""") .replace(/'/g,"'"); } // IP地址转义:将点号替换为中间点,避免微信识别为链接。仅匹配合法IPv4(每段0-255),避免误伤版本号 function escapeIP(str) { return String(str).replace( /\b(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|1\d\d|[1]?\d\d?)\b/g, (match) => match.replace(/\./g, "·") ); } // 微信token async function getStableToken(appid,secret) { const res = await fetch( "https://api.weixin.qq.com/cgi-bin/stable_token", { method:"POST", headers:{ "Content-Type":"application/json;charset=utf-8" }, body:JSON.stringify({ grant_type:"client_credential", appid, secret, force_refresh:false }) } ); const data = await res.json(); return data.access_token; } // 微信发送 async function sendMessage(accessToken,userid,template_id,base_url,title,content) { const sendUrl = `https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=${accessToken}`; const date = new Date(Date.now()+8*60*60*1000) .toISOString() .slice(0,19) .replace("T"," "); const separator = base_url?.includes("?") ? "&" : "?"; const payload = { touser:userid, template_id, url: `${base_url}${separator}message=${encodeURIComponent(content)}&date=${encodeURIComponent(date)}&title=${encodeURIComponent(title)}`, data:{ title:{value:title}, content:{value:content} } }; const res = await fetch(sendUrl,{ method:"POST", headers:{ "Content-Type":"application/json;charset=utf-8" }, body:JSON.stringify(payload) }); return await res.json(); } // HTML皮肤页 function createSkinHTML(title,message,date){ return ` ${escapeHTML(title)}
${escapeHTML(title)}
通知内容:
${escapeHTML(message)}
时间:
${escapeHTML(date)}
`; } // 测试页 function createTestHTML(token){ return ` 微信消息推送服务 测试页

微信消息推送服务 测试页

当前 Token:${token}

`; } // 首页 function createHomeHTML(){ return ` 微信消息推送服务

微信消息推送服务

一个极简、可靠的微信消息推送服务,通过简单的 Webhook 请求,即可向微信用户发送模板消息。

`; }