🆕 add ui
This commit is contained in:
@@ -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 的模板消息,则配置成功。
|
||||
1. 使用 pm2 启动应用:`pm2 start ./app.js --name wechat-message-push-service`。
|
||||
2. 访问首页填写配置项并提交。
|
||||
2. 之后访问 `https://你的域名/push?content=Hi`,如果微信能够收到消息一条内容为 Hi 的模板消息,则配置成功。
|
||||
@@ -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);
|
||||
|
||||
@@ -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"
|
||||
},
|
||||
|
||||
@@ -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) => {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
<%- include('./header') %>
|
||||
<h2 class="subtitle">配置页面</h2>
|
||||
<article class="message is-warning">
|
||||
<div class="message-header">
|
||||
<p>警告</p>
|
||||
</div>
|
||||
<div class="message-body">
|
||||
提交后将在程序的根目录创建一个 .env 文件,之后程序将自动关闭,请确保你已经使用了诸如 pm2 的进程守护程序来自动重启本程序。提交之后如果想要对配置内容进行修改,则你必须手动删除 .env 文件。
|
||||
</div>
|
||||
</article>
|
||||
<form action="/configure" method="post">
|
||||
<div class="field">
|
||||
<label class="label">APP ID</label>
|
||||
<div class="control">
|
||||
<input class="input" name="APP_ID" type="text" required placeholder="请输入 APP ID">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="field">
|
||||
<label class="label">APP SECRET</label>
|
||||
<div class="control">
|
||||
<input class="input" name="APP_SECRET" type="text" required placeholder="请输入 APP SECRET">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="field">
|
||||
<label class="label">OPEN ID</label>
|
||||
<div class="control">
|
||||
<input class="input" name="OPEN_ID" type="text" required placeholder="请输入你的 OPEN ID">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="field">
|
||||
<label class="label">TEMPLATE ID</label>
|
||||
<div class="control">
|
||||
<input class="input" name="TEMPLATE_ID" type="text" required placeholder="请输入一个模板文章 ID">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="field">
|
||||
<label class="label">TOKEN</label>
|
||||
<div class="control">
|
||||
<input class="input" name="TOKEN" type="text" required placeholder="请输入你的 TOKEN">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="field is-grouped is-grouped-right">
|
||||
<div class="control">
|
||||
<input type="submit" class="button is-link" value="提交">
|
||||
</div>
|
||||
<div class="control">
|
||||
<input type="reset" class="button is-link is-light" value="重置">
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
<%- include('./footer') %>
|
||||
@@ -0,0 +1,2 @@
|
||||
</div>
|
||||
</body>
|
||||
@@ -0,0 +1,11 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bulma@0.9.0/css/bulma.min.css">
|
||||
<title>WeChat Message Push Service</title>
|
||||
</head>
|
||||
<body style="width: 100%;">
|
||||
<div style="margin: auto; max-width: 960px">
|
||||
<h1 class="title" style="margin-top: 16px"><a style="color: black; text-decoration: none">微信消息通知服务</a></h1>
|
||||
@@ -0,0 +1,10 @@
|
||||
<%- include('./header') %>
|
||||
<article class="message is-primary">
|
||||
<div class="message-header">
|
||||
<p>注意</p>
|
||||
</div>
|
||||
<div class="message-body">
|
||||
<%= message %>
|
||||
</div>
|
||||
</article>
|
||||
<%- include('./footer') %>
|
||||
Reference in New Issue
Block a user