-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
a345b49
commit d8a8c70
Showing
13 changed files
with
936 additions
and
15 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,11 +1,18 @@ | ||
{ | ||
"name": "example", | ||
"version": "1.0.0", | ||
"description": "", | ||
"main": "index.js", | ||
"scripts": { | ||
"example": "node index.js" | ||
}, | ||
"author": "", | ||
"license": "ISC" | ||
"name": "example", | ||
"version": "1.0.0", | ||
"description": "", | ||
"main": "index.js", | ||
"scripts": { | ||
"example": "node index.js", | ||
"example:webhook": "node webhook/index.js" | ||
}, | ||
"author": "", | ||
"license": "ISC", | ||
"dependencies": { | ||
"@types/koa-router": "^7.4.8", | ||
"koa": "^2.15.3", | ||
"koa-body": "^6.0.1", | ||
"koa-router": "^13.0.1" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
# 简介 | ||
|
||
基于官方文档 https://bot.q.qq.com/wiki/develop/api-v2/dev-prepare/interface-framework/event-emit.html 实现 | ||
|
||
此案例中 `web` 服务基于 `koa2` + `koa-router` + `koa-body` 的 `http` 服务, 官方需要使用 `https` 协议 `443`端口(其余端口亲测无法验证), 因此需要 `nginx` 设置 `ssl` 反代, `nginx` 代理设置详见同级目录下的 `nginx.conf` | ||
|
||
> `webhook` 相关功能需要在设置了 `secret` 情况下使用,此时仍要设置 `token` | ||
详细流程详见 `index.js` 代码内解释 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
/** | ||
* 基于官方文档 https://bot.q.qq.com/wiki/develop/api-v2/dev-prepare/interface-framework/event-emit.html | ||
* nginx 代理设置详见同级目录下的 nginx.conf | ||
* 注意:webhook 相关功能需要在设置了 secret 情况下使用,此时仍要设置 token | ||
*/ | ||
const { createOpenAPI } = require('qq-bot-sdk'); | ||
|
||
const Koa = require("koa"); | ||
const { koaBody } = require("koa-body"); | ||
const Router = require("koa-router"); | ||
|
||
|
||
const client = createOpenAPI({ | ||
appID: "", | ||
token: "", // 如果不使用 websocket 可留空 | ||
secret: "", // 如果使用 webhook 必填 | ||
}); // 创建 client | ||
|
||
|
||
const PORT = 2333; // 定义 web 的端口, 需要与 nginx.conf 内端口一致 | ||
const app = new Koa(); // 定义 koa 实例 | ||
const router = new Router(); // 定义路由 | ||
app.use(async (ctx, next) => { | ||
let rawData = ''; | ||
ctx.req.on('data', chunk => rawData += chunk); | ||
ctx.req.on('end', () => ctx.request.rawBody = rawData); | ||
await next(); | ||
}); // 对 body 进行验证需要原数据 (格式化后无法使用) | ||
|
||
router.post("/webhook", async (ctx, next) => { | ||
const sign = ctx.req.headers["x-signature-ed25519"]; // 获取服务器传来的 sign | ||
const timestamp = ctx.req.headers["x-signature-timestamp"]; // 获取服务器传来的 timestamp | ||
const rawBody = ctx.request.rawBody; // 获取原数据用来进行验证 | ||
const isValid = client.webhookApi.validSign(timestamp, rawBody, sign); // 进行验证, 通过后才可继续执行下一步操作 | ||
if (!isValid) { | ||
ctx.status = 400; | ||
ctx.body = { msg: "invalid signature" }; | ||
return; | ||
}// 没有通过验证就一边玩去 | ||
|
||
const body = ctx.request.body; | ||
|
||
if (body.op == 13) return ctx.body = { | ||
plain_token: body.d.plain_token, | ||
signature: client.webhookApi.getSign(body.d.event_ts, body.d.plain_token), | ||
}; // 当 op = 13 进行 webhook 验证 | ||
|
||
/** | ||
* | ||
* 此处已经正式通过验证, 你可以对数据做出相应的处理(如回复消息), 数据格式遵从 websocket 接收到的格式 | ||
* | ||
*/ | ||
console.log(body); | ||
|
||
|
||
}); // 监听对应的url | ||
|
||
app.use(async (ctx, next) => { | ||
await next(); | ||
ctx.status = ctx.body?.status || ctx.status || 200; | ||
}); // 返回的 body 里面如果有 status 时, 则返回的 status 设置为与之相同的值 | ||
app.use(koaBody({ multipart: true })); // 使用 koaBody | ||
app.use(router.routes()); // 使用路由 | ||
app.use(router.allowedMethods()); // 使用路由 | ||
app.listen(PORT, async () => { | ||
console.log("webhook 服务运行中......"); | ||
}); // 正式监听相应的端口 | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
server { | ||
listen 443 ssl; # 监听 443 端口,并设置 ssl | ||
server_name bot.example.com; # 这里设置对应的域名 | ||
|
||
ssl_certificate /path/to/it.crt; # 设置证书 公钥 | ||
ssl_certificate_key /path/to/it.key; # 设置证书 私钥 | ||
|
||
location / { | ||
add_header Access-Control-Allow-Origin *; | ||
add_header Access-Control-Allow-Methods *; | ||
|
||
if ($request_method = 'OPTIONS') { | ||
add_header 'Access-Control-Allow-Origin' '*'; | ||
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS'; | ||
add_header 'Access-Control-Allow-Headers' 'DNT,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type'; | ||
add_header 'Access-Control-Max-Age' 1728000; | ||
add_header 'Content-Type' 'text/plain; charset=utf-8'; | ||
add_header 'Content-Length' 0; | ||
return 204; | ||
} | ||
|
||
proxy_pass http://127.0.0.1:2333; # 设置代理的域名,需要与 index.js 里面的 PORT 相同 | ||
proxy_redirect off; | ||
proxy_set_header Host $host; # 传递域名 | ||
proxy_set_header X-Real-IP $remote_addr; # 传递ip | ||
proxy_set_header X-Scheme $scheme; # 传递协议 | ||
} | ||
} |
Oops, something went wrong.