This is an explanation of the video content.
 用技术延续对ACG的热爱
203

 |   | 

企业微信自建应用-Go校验回调

点击链接 (opens new window)访问企业微信的管理后台,然后在 应用管理 栏 创建应用。

进入应用,点击接收消息的设置 API 接收:

进入回调地址配置页面:

此处来到第一个门槛,需要校验填入的 URL,否则会报一个 openapi 回调地址请求不通过 而无法保存成功。

这里需要了解阅读的一些文档有:

企业内部开发配置域名指引 (opens new window):当然如果不是企业级应用,这篇文档可以先跳过。 开启接收消息 (opens new window):这个内容十分重要,它介绍了如何才能完成 URL 请求的验证。一堆参数,加密解密这里就不对赘述了,后边会直接给代码,来完成这里的校验。 如上三个框的内容,第一个是填写我们的服务接口,后两个点击随机获取自动生成。

点击保存,企业微信会向 URL 发送一个 GET 请求,请求内容大概如下:

http://xxx.xxx.xxx.xxx:8000/?msg_signature=ASDFQWEXZCVAQFASDFASDFSS&timestamp=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 即为消息内容明文

我们要做的就是:

  1. 获取到这些参数
  2. 通过参数 msg_signature 对请求进行校验 (opens new window),确认调用者的合法性。
  3. 解密echostr (opens new window)参数得到消息内容(即 msg 字段)
  4. 在 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(":8000")
    }
    
    

203 服务端 ↦ Go开发技巧 __ 213 字
 Go开发技巧 #5