main.go
package main
import (
"crypto/aes"
"crypto/cipher"
"encoding/base64"
"encoding/xml"
"fmt"
"io/ioutil"
"net/http"
"strings"
)
const (
Token = "your_token" // 微信公众号Token
AppID = "your_app_id" // 微信公众号AppID
AppSecret = "your_app_secret" // 微信公众号AppSecret
EncodingAESKey = "your_aes_key" // 消息加解密密钥
)
type Message struct {
XMLName xml.Name `xml:"xml"`
ToUserName string `xml:"ToUserName"`
Encrypt string `xml:"Encrypt"`
}
func main() {
http.HandleFunc("/", handleRequest)
http.ListenAndServe(":80", nil)
}
func handleRequest(w http.ResponseWriter, r *http.Request) {
// 读取请求Body
body, _ := ioutil.ReadAll(r.Body)
// 解析XML消息
var message Message
xml.Unmarshal(body, &message)
// 根据加密方式进行相应的解密操作
content := decryptMessage(message.Encrypt)
// 解析XML消息内容
var data map[string]string
xml.Unmarshal([]byte(content), &data)
// 根据消息类型进行相应的处理
switch data["MsgType"] {
case "text":
fmt.Fprintf(w, "您发送了一条文本消息")
case "image":
fmt.Fprintf(w, "您发送了一条图片消息")
case "voice":
fmt.Fprintf(w, "您发送了一条语音消息")
case "video":
fmt.Fprintf(w, "您发送了一条视频消息")
case "location":
fmt.Fprintf(w, "您发送了一条位置消息")
case "link":
fmt.Fprintf(w, "您发送了一条链接消息")
case "event":
switch data["Event"] {
case "subscribe":
fmt.Fprintf(w, "感谢您的关注")
case "unsubscribe":
// 用户取消关注,可以在此处进行相应的业务处理
case "CLICK":
// 用户点击自定义菜单事件,可以在此处进行相应的业务处理
}
}
}
func decryptMessage(encrypted string) string {
// 对密钥进行base64解码
aesKey, _ := base64.StdEncoding.DecodeString(EncodingAESKey + "=")
// 对密文进行base64解码
ciphertext, _ := base64.StdEncoding.DecodeString(encrypted)
// 对密文进行AES解密,获取原始消息
block, _ := aes.NewCipher(aesKey)
iv := ciphertext[:aes.BlockSize]
mode := cipher.NewCBCDecrypter(block, iv)
mode.CryptBlocks(ciphertext[aes.BlockSize:], ciphertext[aes.BlockSize:])
ciphertext = ciphertext[aes.BlockSize:]
content := ciphertext[:len(ciphertext)-int(ciphertext[len(ciphertext)-1])]
// 去除消息头部的16个随机字节和4个消息长度字节
content = content[20:]
// 去除消息尾部的AppID
content = content[:len(content)-len(AppID)-1]
return string(content)
}
评论区