You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

138 lines
3.2 KiB

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(`<![CDATA[%s]]>`, 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")
}