package main import ( "crypto/sha1" "encoding/xml" "fmt" "log" "net/http" "sort" "strings" "time" "github.com/gin-gonic/gin" ) const ( appID = "wxc39301065b66300c" secret = "7fee3a1cba8c555cf6c4caec4f05844c" token = "qwertyuiopasdfghjkl" ) ////// type messageEntity struct { Signature string `form:"signature"` Timestamp string `form:"timestamp"` Nonce string `form:"nonce"` EchoStr string `form:"echostr"` } func (m *messageEntity) CheckSignature(token string) bool { item := []string{token, m.Timestamp, m.Nonce} sort.Strings(item) itemByte := strings.Join(item, "") signature := fmt.Sprintf("%x", sha1.Sum([]byte(itemByte))) return signature == m.Signature } func Check(c *gin.Context) { me := &messageEntity{} me.Signature = c.Query("signature") me.Timestamp = c.Query("timestamp") me.Nonce = c.Query("nonce") me.EchoStr = c.Query("echostr") log.Println("signature:", me.Signature, "timestamp:", me.Timestamp, "noce:", me.Nonce, "echostr:", me.EchoStr) if !me.CheckSignature(token) { log.Println("token is not ok") c.AbortWithError(http.StatusForbidden, fmt.Errorf("token invalid")) return } c.Next() } //// type foucsData struct { ToUserName string `xml:"ToUserName"` FromUserName string `xml:"FromUserName"` CreateTime int64 `xml:"CreateTime"` MsgType string `xml:"MsgType"` Event string `xml:"Event"` } //// type textMessage struct { ToUserName string `xml:"ToUserName"` FromUserName string `xml:"FromUserName"` CreateTime int64 `xml:"CreateTime"` MsgType string `xml:"MsgType"` Content string `xml:"Content"` } func cdata(data string)string{ return fmt.Sprintf(``, data) } func handleGet(c *gin.Context) { me := &messageEntity{} me.Signature = c.Query("signature") me.Timestamp = c.Query("timestamp") me.Nonce = c.Query("nonce") me.EchoStr = c.Query("echostr") log.Println("signature:", me.Signature, "timestamp:", me.Timestamp, "noce:", me.Nonce, "echostr:", me.EchoStr) log.Println("token is ok") c.String(http.StatusOK, me.EchoStr) } func handlePost(c *gin.Context) { data := foucsData{} err := c.BindXML(&data) if err != nil { log.Println(err) } log.Println("data: ", data) openID := c.Query("openid") log.Println("openid is ", openID) t := textMessage{ ToUserName: cdata(data.FromUserName), FromUserName: cdata(data.ToUserName), CreateTime: time.Now().Unix(), MsgType: cdata("text"), Content: cdata("你关注了我!"), } d, err := xml.Marshal(&t) if err != nil { log.Println("marshar message faild", err) } c.String(http.StatusOK, string(d)) } func handlePut(c *gin.Context) { data :=foucsData{} err := c.BindXML(&data) if err != nil { log.Println(err) } log.Println("data: ", data) c.String(http.StatusOK, "success") } func handleDelete(c *gin.Context) { data := foucsData{} err := c.BindXML(&data) if err != nil { log.Println(err) } log.Println("data: ", data) c.String(http.StatusOK, "success") } func main() { engine := gin.Default() engine.Use(Check) engine.GET("/api/wechat/signature", handleGet) engine.POST("/api/wechat/signature", handlePost) engine.PUT("/api/wechat/signature", handlePut) engine.DELETE("/api/wechat/signature", handleDelete) engine.Run("0.0.0.0:15043") }