+
+ 警告
+
+ 提交后将在程序的根目录创建一个 .env 文件,之后程序将自动关闭,请确保你已经使用了诸如 pm2 的进程守护程序来自动重启本程序。提交之后如果想要对配置内容进行修改,则你必须手动删除 .env 文件。
+
+diff --git a/README.md b/README.md index 27b8e20..096687a 100644 --- a/README.md +++ b/README.md @@ -9,24 +9,14 @@ 3. 安装依赖:`npm i`。 4. 安装 pm2:`npm i -g pm2`。 5. 使用 Nginx 反代我们的 Node.js 服务,默认端口 3000。 -6. 使用 pm2 启动应用:`pm2 start ./app.js --name wechat-message-push-service`。 ### 微信公众平台端配置 -1. 首先前往[此页面](https://mp.weixin.qq.com/debug/cgi-bin/sandboxinfo?action=showinfo&t=sandbox/index) 拿到 APP_ID 以及 APP_SECRET。 +1. 首先前往[此页面](https://mp.weixin.qq.com/debug/cgi-bin/sandboxinfo?action=showinfo&t=sandbox/index)拿到 APP_ID 以及 APP_SECRET。 2. 填写接口配置信息,URL 填 `https://你的域名/verify`,TOKEN 随意,之后点击验证。 3. 使用微信扫描下方的测试号二维码,拿到你的 OPEN_ID。 4. 新增模板消息模板,模板标题随意,模板内容填 `{{text.DATA}}`,提交后可以拿到 TEMPLATE_ID。 ### 启动服务 -1. 至此,我们已经拿到所有我们需要的信息,接下来设置环境变量,方法很多,例如可以通过在应用的根目录创建 .env 文件,设置以下环境变量: - ``` - APP_ID=wx***** - APP_SECRET=***** - TOKEN=你的 TOKEN - TEMPLATE_ID=**** - OPEN_ID=**** - PORT=3000 - ``` - -2. 使用 `pm2 restart wechat-message-push-service` 重启服务。 -3. 之后访问 `https://你的域名/push?content=Hi`,如果微信能够收到消息一条内容为 Hi 的模板消息,则配置成功。 \ No newline at end of file +1. 使用 pm2 启动应用:`pm2 start ./app.js --name wechat-message-push-service`。 +2. 访问首页填写配置项并提交。 +2. 之后访问 `https://你的域名/push?content=Hi`,如果微信能够收到消息一条内容为 Hi 的模板消息,则配置成功。 \ No newline at end of file diff --git a/app.js b/app.js index 3ace53e..cd6b696 100644 --- a/app.js +++ b/app.js @@ -13,6 +13,11 @@ const app = express(); requestToken(app); setInterval(() => requestToken(app), 100 * 60 * 1000); +const port = parseInt(process.env.PORT || "3000"); +app.set("port", port); +app.set("views", path.join(__dirname, "views")); +app.set("view engine", "ejs"); + app.use(logger("dev")); app.use(express.json()); app.use(express.urlencoded({ extended: false })); @@ -21,8 +26,6 @@ app.use(express.static(path.join(__dirname, "public"))); app.use("/", indexRouter); -const port = parseInt(process.env.PORT || "3000"); -app.set("port", port); const server = http.createServer(app); server.listen(port); diff --git a/package.json b/package.json index c9fb773..d942950 100644 --- a/package.json +++ b/package.json @@ -10,6 +10,7 @@ "cookie-parser": "~1.4.4", "debug": "~2.6.9", "dotenv": "^8.2.0", + "ejs": "^3.1.5", "express": "~4.16.1", "morgan": "~1.9.1" }, diff --git a/routes.js b/routes.js index 9292613..69b00e3 100644 --- a/routes.js +++ b/routes.js @@ -2,12 +2,55 @@ const express = require("express"); const router = express.Router(); const crypto = require("crypto"); const axios = require("axios"); +const fs = require("fs"); +const requestToken = require("./utils").requestToken; -router.get("/", (req, res, next) => { - res.send("OK"); +router.all("/", (req, res, next) => { + fs.promises + .access("./.env") + .then(() => { + res.render("message", { + message: "服务已在运行。", + }); + }) + .catch(() => { + res.render("configure"); + }); }); -router.get("/verify", (req, res, next) => { +router.post("/configure", (req, res, next) => { + fs.promises + .access("./.env") + .then(() => { + res.render("message", { + message: ".env 文件已经存在,请手动删除该文件后重试!", + }); + }) + .catch(() => { + let content = + `APP_ID=${req.body.APP_ID}\n` + + `APP_SECRET=${req.body.APP_SECRET}\n` + + `TOKEN=${req.body.TOKEN}\n` + + `TEMPLATE_ID=${req.body.TEMPLATE_ID}\n` + + `OPEN_ID=${req.body.OPEN_ID}`; + fs.promises + .writeFile("./.env", content, "utf8") + .then(() => { + res.render("message", { + message: + ".env 文件写入成功,程序即将自动关闭以应用写入的新的环境变量,需要进程守护程序自动重启应用或者手动重启。", + }); + process.exit(); + }) + .catch((e) => { + res.render("message", { + message: "在尝试写入 .env 文件时发生错误:" + e, + }); + }); + }); +}); + +router.all("/verify", (req, res, next) => { // 验证消息来自微信服务器:https://developers.weixin.qq.com/doc/offiaccount/Basic_Information/Access_Overview.html const { signature, timestamp, nonce, echostr } = req.query; const token = process.env.TOKEN; @@ -21,10 +64,9 @@ router.get("/verify", (req, res, next) => { } }); -router.get("/push", (req, res, next) => { +router.all("/push", (req, res, next) => { // Reference: https://mp.weixin.qq.com/debug/cgi-bin/readtmpl?t=tmplmsg/faq_tmpl let content = req.query.content || req.body.content; - console.log(`Get content: ${content}`); let access_token = req.app.access_token; let request_data = { touser: process.env.OPEN_ID, @@ -37,6 +79,9 @@ router.get("/push", (req, res, next) => { request_data ) .then((response) => { + if (response.data && response.data.errcode === "40001") { + requestToken(req.app); + } res.json(response.data); }) .catch((error) => { diff --git a/utils.js b/utils.js index f20ddfa..9e968f7 100644 --- a/utils.js +++ b/utils.js @@ -9,7 +9,7 @@ module.exports = { ) .then((res) => { if (res.data && res.data.access_token) { - console.log("Get token: ", res.data.access_token); + console.log("Token requested."); token = res.data.access_token; app.access_token = token; } else { diff --git a/views/configure.ejs b/views/configure.ejs new file mode 100644 index 0000000..a63bc83 --- /dev/null +++ b/views/configure.ejs @@ -0,0 +1,56 @@ +<%- include('./header') %> +
\ No newline at end of file diff --git a/views/header.ejs b/views/header.ejs new file mode 100644 index 0000000..0f18087 --- /dev/null +++ b/views/header.ejs @@ -0,0 +1,11 @@ + + +
+ + + +
+ +