package wechat import ( "fmt" "net/http" "time" "mini-chat/internal/code" "mini-chat/internal/pkg/core" "mini-chat/internal/pkg/miniprogram" "mini-chat/internal/pkg/validation" "go.uber.org/zap" "gorm.io/gorm" ) type templateRequest struct { AppID string `json:"app_id" binding:"required"` // 微信小程序 AppID } type templateResponse struct { Success bool `json:"success"` Message string `json:"message"` AppID string `json:"app_id"` // 小程序 AppID TemplateID string `json:"template_id"` // 模板 ID } // GetTemplate 获取微信小程序模板ID // @Summary 获取微信小程序模板ID // @Description 根据 AppID 获取微信小程序的模板ID // @Tags 微信 // @Accept json // @Produce json // @Param request body templateRequest true "请求参数" // @Success 200 {object} templateResponse // @Failure 400 {object} code.Failure // @Failure 404 {object} code.Failure // @Failure 500 {object} code.Failure // @Router /api/wechat/template [post] func (h *handler) GetTemplate() core.HandlerFunc { return func(ctx core.Context) { req := new(templateRequest) res := new(templateResponse) if err := ctx.ShouldBindJSON(req); err != nil { ctx.AbortWithError(core.Error( http.StatusBadRequest, code.ParamBindError, validation.Error(err), )) return } // 根据 AppID 查询小程序信息 miniProgram, err := h.readDB.MiniProgram.WithContext(ctx.RequestContext()). Where(h.readDB.MiniProgram.AppID.Eq(req.AppID)). First() if err != nil { if err == gorm.ErrRecordNotFound { ctx.AbortWithError(core.Error( http.StatusNotFound, code.ServerError, fmt.Sprintf("未找到 AppID 为 %s 的小程序", req.AppID), )) return } h.logger.Error(fmt.Sprintf("查询小程序信息失败: %s", err.Error())) ctx.AbortWithError(core.Error( http.StatusInternalServerError, code.ServerError, "查询小程序信息失败", )) return } // 检查模板ID是否存在 if miniProgram.TemplateID == "" { ctx.AbortWithError(core.Error( http.StatusNotFound, code.ServerError, "该小程序未配置模板ID", )) return } res.Success = true res.Message = "获取模板ID成功" res.AppID = miniProgram.AppID res.TemplateID = miniProgram.TemplateID ctx.Payload(res) } } type sendSubscribeMessageRequest struct { AppID string `json:"app_id" binding:"required"` // 微信小程序 AppID TemplateID string `json:"template_id" binding:"required"` // 模板 ID AppSecret string `json:"app_secret" binding:"required"` // 小程序 AppSecret Touser string `json:"touser" binding:"required"` // 接收者(用户)的 openid } type sendSubscribeMessageResponse struct { Success bool `json:"success"` Message string `json:"message"` } // SendSubscribeMessage 发送订阅消息 // @Summary 发送订阅消息 // @Description 根据模板ID发送订阅消息 // @Tags 微信 // @Accept json // @Produce json // @Param request body sendSubscribeMessageRequest true "请求参数" // @Success 200 {object} sendSubscribeMessageResponse // @Failure 400 {object} code.Failure // @Failure 404 {object} code.Failure // @Failure 500 {object} code.Failure // @Router /api/wechat/subscribe [post] func (h *handler) SendSubscribeMessage() core.HandlerFunc { return func(ctx core.Context) { req := new(sendSubscribeMessageRequest) res := new(sendSubscribeMessageResponse) // 参数绑定和验证 if err := ctx.ShouldBindJSON(req); err != nil { ctx.AbortWithError(core.Error( http.StatusBadRequest, code.ParamBindError, validation.Error(err), )) return } // 调整为实时获取 accessTokenResponse := new(miniprogram.AccessTokenResponse) if err := miniprogram.GetAccessToken(req.AppID, req.AppSecret, accessTokenResponse); err != nil { h.logger.Error("GetAccessToken failed", zap.Error(err), zap.String("app_id", req.AppID), zap.String("app_secret", req.AppSecret)) ctx.AbortWithError(core.Error( http.StatusBadRequest, code.ParamBindError, fmt.Sprintf("获取 access_token 失败: %s,请稍后重试", err.Error()), )) return } if accessTokenResponse.AccessToken == "" { ctx.AbortWithError(core.Error( http.StatusBadRequest, code.ParamBindError, "未获得到 access_token,请稍后重试", )) return } sendSubscribeMessageReq := new(miniprogram.SendSubscribeMessageRequest) sendSubscribeMessageReq.Touser = req.Touser sendSubscribeMessageReq.TemplateID = req.TemplateID sendSubscribeMessageReq.Page = "pages/index/detail?url=1" sendSubscribeMessageReq.MiniprogramState = "formal" // 需要改成正式版 目前是体验版 跳转小程序类型:developer 为开发版;trial为体验版;formal 为正式版;默认为正式版 sendSubscribeMessageReq.Lang = "zh_CN" sendSubscribeMessageReq.Data.Thing1.Value = "留言提醒" sendSubscribeMessageReq.Data.Time2.Value = time.Now().Format("2006-01-02 15:04:05") sendSubscribeMessageReq.Data.Thing3.Value = "您有一条新的消息..." sendSubscribeMessageRes := new(miniprogram.SendSubscribeMessageResponse) err := miniprogram.SendSubscribeMessage(accessTokenResponse.AccessToken, sendSubscribeMessageReq, sendSubscribeMessageRes) if err != nil { res.Success = false res.Message = "发送订阅消息失败" + err.Error() h.logger.Error(fmt.Sprintf("发送模版消息失败: %s", err.Error()), zap.String("app_id", req.AppID), zap.String("app_secret", req.AppSecret), zap.String("template_id", req.TemplateID), ) } else { res.Success = true res.Message = "订阅消息发送成功" } ctx.Payload(res) } }