一、写在前头
- 该教程目标用户是想基于golang语言开发公众号后台,实现自动回复、微信支付、客服等等一些拓展功能;
- 需要会golang、gin、web服务的部署等基础知识。
- 关于微信开发的基本配置,请通过文末的链接查看。
二、整体思路
- 基于微信消息接口的逻辑,首先定义一个消息结构体;
- 然后解析微信服务器发送过来的消息;
- 根据消息的类型(MsgType字段)和消息的内容(Content字段)进行对应的处理;
- 关键字自动回复实例,通过switch-case 结构,将
MsgType=text
并且Content=关键字
的消息,回复对应的内容;
三、部分代码
package routers import ( "blog_server_v4/config" "crypto/sha1" "encoding/hex" "encoding/xml" "fmt" "github.com/gin-gonic/gin" "log" "net/http" "sort" "strings" ) type ReqWxMessage struct { ToUserName string `json:"ToUserName"` FromUserName string `json:"FromUserName"` CreateTime int `json:"CreateTime"` MsgType string `json:"MsgType"` // text | image | voice | shortvideo | location Event string `json:"Event"` EventKey string `json:"EventKey"` Ticket string `json:"Ticket"` // 文本消息 Content string `json:"Content"` MsgId int64 `json:"MsgId"` MsgDataId int64 `json:"MsgDataId"` Idx int `json:"Idx"` // 图片消息 PicUrl string `json:"PicUrl"` MediaId string `json:"MediaId"` // 语音消息 Format string `json:"Format"` // amr | speex // 视频消息 ThumbMediaId string `json:"ThumbMediaId"` // 地理位置消息 LocationX string `json:"Location_X"` LocationY string `json:"Location_Y"` Scale string `json:"Scale"` Label string `json:"Label"` // 链接消息 Title string `json:"Title"` Description string `json:"Description"` Url string `json:"Url"` } type RespWxMessageText struct { ToUserName string `json:"ToUserName"` FromUserName string `json:"FromUserName"` CreateTime int `json:"CreateTime"` MsgType string `json:"MsgType"` Content string `json:"Content"` XMLName xml.Name `xml:"xml"` } func RouterPartner(router *gin.Engine) (interface{}, error) { routerPartner := router.Group("/xxx/xxxx") { routerPartner.POST("/xxx/xxxx/v1", func(c *gin.Context) { signature := c.Query("signature") timestamp := c.Query("timestamp") nonce := c.Query("nonce") openid := c.Query("openid") log.Println("signature:", signature, "timestamp:", timestamp, "nonce:", nonce, "openid:", openid) var wxMsg ReqWxMessage err := c.BindXML(&wxMsg) if err != nil { log.Println(err) } //log.Println("mxMsg:", wxMsg) //byteWxMsg, err := json.Marshal(wxMsg) //if err != nil { // log.Println("err: ", err) //} //log.Println("wxMsgString: ", string(byteWxMsg)) switch wxMsg.MsgType { case "text": if strings.ToLower(wxMsg.Content) == "pdf2023" { respWxMessageText := RespWxMessageText{ ToUserName: wxMsg.FromUserName, FromUserName: wxMsg.ToUserName, CreateTime: wxMsg.CreateTime + 1, MsgType: "text", Content: `链接:https://pan.baidu.com/s/1FYKllrdbZDNc5BxxLv9mcQ?pwd=pryf 提取码:pryf --来自百度网盘超级会员V5的分享`, } byteResp, err := xml.Marshal(&respWxMessageText) if err != nil { log.Println(err) break } c.String(http.StatusOK, string(byteResp)) // //log.Println(string(byteResp)) return } } c.String(http.StatusOK, "success") return }) } return routerPartner, nil }
关键点说明
- 返回的数据需要需要用
c.String()
返回,不能使用c.XML()
- 返回给微信的xml字符串,最外层应当是
<xml>
标签,不能使用默认的标签,因此,在定义结构体时,需要使用xml:"xml"
指定xml标签
四、校验
[图片上传失败...(image-107571-1699711050225)]
可以看到微信公众号对话窗口和服务端处理窗口的时间是能对上的,即校验成功。