Files
pet-ai/server/plugin/wechat-integration/api/wechat_webhook_api.go
T
2025-08-05 17:46:15 +08:00

90 lines
2.4 KiB
Go

package api
import (
"crypto/sha1"
"fmt"
"io"
"sort"
"strings"
"github.com/flipped-aurora/gin-vue-admin/server/global"
"github.com/flipped-aurora/gin-vue-admin/server/plugin/wechat-integration/service"
"github.com/gin-gonic/gin"
"go.uber.org/zap"
)
type WechatWebhookApi struct{}
var webhookMessageService = service.ServiceGroupApp.MpMessageService
// OfficialAccountWebhook 公众号消息接收
// @Tags WechatWebhook
// @Summary 公众号消息接收
// @Description 接收微信公众号推送的消息和事件
// @Accept xml
// @Produce xml
// @Param signature query string true "微信加密签名"
// @Param timestamp query string true "时间戳"
// @Param nonce query string true "随机数"
// @Param echostr query string false "随机字符串"
// @Success 200 {string} string "success"
// @Router /wechat/official/webhook [get,post]
func (w *WechatWebhookApi) OfficialAccountWebhook(c *gin.Context) {
// 获取参数
signature := c.Query("signature")
timestamp := c.Query("timestamp")
nonce := c.Query("nonce")
echostr := c.Query("echostr")
// 验证签名
if !w.verifySignature(signature, timestamp, nonce) {
global.GVA_LOG.Error("微信签名验证失败")
c.String(403, "签名验证失败")
return
}
// GET请求用于验证服务器配置
if c.Request.Method == "GET" {
c.String(200, echostr)
return
}
// POST请求处理消息
body, err := io.ReadAll(c.Request.Body)
if err != nil {
global.GVA_LOG.Error("读取请求体失败", zap.Error(err))
c.String(400, "读取请求体失败")
return
}
// 简化消息处理 - 暂时只记录日志
global.GVA_LOG.Info("收到微信消息", zap.String("body", string(body)))
// TODO: 实现完整的消息解析和处理
// 由于微信SDK API变化,暂时简化处理
c.String(200, "success")
}
// verifySignature 验证微信签名
func (w *WechatWebhookApi) verifySignature(signature, timestamp, nonce string) bool {
token := global.GVA_CONFIG.Wechat.OfficialToken
if token == "" {
global.GVA_LOG.Error("微信公众号Token未配置")
return false
}
// 将token、timestamp、nonce三个参数进行字典序排序
strs := []string{token, timestamp, nonce}
sort.Strings(strs)
// 将三个参数字符串拼接成一个字符串进行sha1加密
str := strings.Join(strs, "")
h := sha1.New()
h.Write([]byte(str))
encrypted := fmt.Sprintf("%x", h.Sum(nil))
// 将加密后的字符串与signature对比
return encrypted == signature
}