diff --git a/server/plugin/wechat-integration/api/wechat_webhook_api.go b/server/plugin/wechat-integration/api/wechat_webhook_api.go index 86c7faa8..a15ec8a7 100644 --- a/server/plugin/wechat-integration/api/wechat_webhook_api.go +++ b/server/plugin/wechat-integration/api/wechat_webhook_api.go @@ -2,12 +2,15 @@ package api import ( "crypto/sha1" + "encoding/json" "fmt" "io" "sort" "strings" + "time" "github.com/flipped-aurora/gin-vue-admin/server/global" + "github.com/flipped-aurora/gin-vue-admin/server/plugin/wechat-integration/model" "github.com/flipped-aurora/gin-vue-admin/server/plugin/wechat-integration/service" "github.com/gin-gonic/gin" "go.uber.org/zap" @@ -30,21 +33,59 @@ var webhookMessageService = service.ServiceGroupApp.MpMessageService // @Success 200 {string} string "success" // @Router /wechat/official/webhook [get,post] func (w *WechatWebhookApi) OfficialAccountWebhook(c *gin.Context) { + startTime := time.Now() + // 获取参数 signature := c.Query("signature") timestamp := c.Query("timestamp") nonce := c.Query("nonce") echostr := c.Query("echostr") + // 准备webhook日志记录 + webhookLog := &model.MpWebhookLog{ + ConfigID: 1, // 默认配置ID,实际应该根据具体配置获取 + RequestURL: c.Request.URL.String(), + RequestMethod: c.Request.Method, + Signature: &signature, + Timestamp: ×tamp, + Nonce: &nonce, + Echostr: &echostr, + } + + // 记录请求头 + if headers, err := json.Marshal(c.Request.Header); err == nil { + headersStr := string(headers) + webhookLog.RequestHeaders = &headersStr + } + // 验证签名 if !w.verifySignature(signature, timestamp, nonce) { global.GVA_LOG.Error("微信签名验证失败") + + // 记录失败信息 + webhookLog.ResponseStatus = 403 + responseBody := "签名验证失败" + webhookLog.ResponseBody = &responseBody + errorMsg := "签名验证失败" + webhookLog.ErrorMessage = &errorMsg + webhookLog.ProcessTime = int(time.Since(startTime).Milliseconds()) + + // 保存到数据库 + w.saveWebhookLog(webhookLog) + c.String(403, "签名验证失败") return } // GET请求用于验证服务器配置 if c.Request.Method == "GET" { + webhookLog.ResponseStatus = 200 + webhookLog.ResponseBody = &echostr + webhookLog.ProcessTime = int(time.Since(startTime).Milliseconds()) + + // 保存到数据库 + w.saveWebhookLog(webhookLog) + c.String(200, echostr) return } @@ -53,16 +94,41 @@ func (w *WechatWebhookApi) OfficialAccountWebhook(c *gin.Context) { body, err := io.ReadAll(c.Request.Body) if err != nil { global.GVA_LOG.Error("读取请求体失败", zap.Error(err)) + + // 记录失败信息 + webhookLog.ResponseStatus = 400 + responseBody := "读取请求体失败" + webhookLog.ResponseBody = &responseBody + errorMsg := err.Error() + webhookLog.ErrorMessage = &errorMsg + webhookLog.ProcessTime = int(time.Since(startTime).Milliseconds()) + + // 保存到数据库 + w.saveWebhookLog(webhookLog) + c.String(400, "读取请求体失败") return } + // 记录请求体 + bodyStr := string(body) + webhookLog.RequestBody = &bodyStr + // 简化消息处理 - 暂时只记录日志 - global.GVA_LOG.Info("收到微信消息", zap.String("body", string(body))) + global.GVA_LOG.Info("收到微信消息", zap.String("body", bodyStr)) // TODO: 实现完整的消息解析和处理 // 由于微信SDK API变化,暂时简化处理 + // 记录成功响应 + webhookLog.ResponseStatus = 200 + responseBody := "success" + webhookLog.ResponseBody = &responseBody + webhookLog.ProcessTime = int(time.Since(startTime).Milliseconds()) + + // 保存到数据库 + w.saveWebhookLog(webhookLog) + c.String(200, "success") } @@ -87,3 +153,13 @@ func (w *WechatWebhookApi) verifySignature(signature, timestamp, nonce string) b // 将加密后的字符串与signature对比 return encrypted == signature } + +// saveWebhookLog 保存Webhook日志到数据库 +func (w *WechatWebhookApi) saveWebhookLog(log *model.MpWebhookLog) { + if err := global.GVA_DB.Create(log).Error; err != nil { + global.GVA_LOG.Error("保存Webhook日志失败", zap.Error(err)) + // 数据库记录失败不影响webhook正常响应 + } else { + global.GVA_LOG.Debug("Webhook日志保存成功", zap.Uint("id", log.ID)) + } +}