企业微信自建应用-golang校验回调
文章发布较早,内容可能过时,阅读注意甄别。
# 前言
写了 chatgpt-dingtalk 项目,不少人对接钉钉很嗨皮,但是一个 issue 里有人提到能否对接到企业微信,于是我了解了一下,这里记录一下企业微信自建应用的一些细节及注意事项。
首先来说,钉钉中支持创建机器人类型的应用,然后给机器人配置回调,且这个机器人支持添加到群聊,然后通过艾特机器人发消息,回调给应用进行交互。
而企业微信则不支持上述这种模式,企业微信支持的是可以在管理后台创建一个应用,也可以给这个应用绑定回调地址,但是有一个问题是,这个应用只支持用户单独聊天,而不支持添加到群聊。不过单独聊天也有一定的应用场景,比如做一些审批的时候,是可以用到的,因此这里也把已经了解到的成果做一个记录。
# 创建应用
创建应用的流程比较简单,就不多赘述。
点击链接 (opens new window)访问企业微信的管理后台,然后在 应用管理
栏 创建应用
。
进入应用,点击接收消息的设置 API 接收
:
进入回调地址配置页面:
此处来到第一个门槛,需要校验填入的 URL,否则会报一个 openapi 回调地址请求不通过
而无法保存成功。
这里需要了解阅读的一些文档有:
- 企业内部开发配置域名指引 (opens new window) :当然如果不是企业级应用,这篇文档可以先跳过。
- 开启接收消息 (opens new window) :这个内容十分重要,它介绍了如何才能完成 URL 请求的验证。一堆参数,加密解密这里就不对赘述了,后边会直接给代码,来完成这里的校验。
如上三个框的内容,第一个是填写我们的服务接口,后两个点击随机获取自动生成。
点击保存,企业微信会向 URL 发送一个 GET 请求,请求内容大概如下:
http://8.136.215.57:8090/?msg_signature=ASDFQWEXZCVAQFASDFASDFSS×tamp=13500001234&nonce=123412323&echostr=ENCRYPT_STR
参数说明
参数 | 必须 | 说明 |
---|---|---|
msg_signature | 是 | 企业微信加密签名,msg_signature 结合了企业填写的 token、请求中的 timestamp、nonce 参数、加密的消息体 |
timestamp | 是 | 时间戳 |
nonce | 是 | 随机数 |
echostr | 是 | 加密的字符串。需要解密得到消息内容明文 (opens new window),解密后有 random、msg_len、msg、CorpID 四个字段,其中 msg 即为消息内容明文 |
我们要做的就是:
- 获取到这些参数
- 通过参数 msg_signature 对请求进行校验 (opens new window),确认调用者的合法性。
- 解密 echostr (opens new window) 参数得到消息内容(即 msg 字段)
- 在 1 秒内原样返回明文消息内容(不能加引号,不能带 bom 头,不能带换行符)
这里我通过 go 启动一个简单的服务,来完成这个校验:
package main
import (
"fmt"
"github.com/gin-gonic/gin"
"github.com/sbzhu/weworkapi_golang/wxbizmsgcrypt"
)
func main() {
Start()
}
const (
CorpId = "xxxxxxxx" // 企业微信 ID
Token = "xxxxxxxxxxx" // 添加回调时自动生成的 Token
EncodingAESKey = "xxxxxxxxxxxxxx" // 添加回调时自动生成的 EncodingAESKey
)
func Start() {
r := gin.Default()
r.GET("/", func(c *gin.Context) {
// 获取到请求参数
msgSignature := c.Query("msg_signature")
timestamp := c.Query("timestamp")
nonce := c.Query("nonce")
echostr := c.Query("echostr")
// 调用企业微信官方提供的接口进行解析校验
wxcpt := wxbizmsgcrypt.NewWXBizMsgCrypt(Token, EncodingAESKey, CorpId, wxbizmsgcrypt.XmlType)
echoStr, cryptErr := wxcpt.VerifyURL(msgSignature, timestamp, nonce, echostr)
if nil != cryptErr {
fmt.Println("verifyUrl fail", cryptErr)
}
fmt.Println("verifyUrl success echoStr", string(echoStr))
// 将解密出来的字符串返回出去
c.String(200, string(echoStr))
})
r.Run(":8090")
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
服务在服务器启动之后,再次点击保存就能验证通过了。
本文暂时写到这里,以后再有需求,再进行深入探索。
上次更新: 2024/09/26, 21:41:44