diff --git a/configs/fat_configs.toml b/configs/fat_configs.toml index a4170df..3258a2f 100644 --- a/configs/fat_configs.toml +++ b/configs/fat_configs.toml @@ -2,6 +2,7 @@ local = 'zh-cn' [mysql.read] +<<<<<<< Updated upstream addr = "mysql:3306" user = "root" pass = "bindbox2025kdy" @@ -57,4 +58,19 @@ api_key = "bindbox-internal-secret-2024" [otel] enabled = true -endpoint = "tempo:4318" \ No newline at end of file +endpoint = "tempo:4318" +======= +addr = '127.0.0.1:3306' +name = 'mini_chat' +pass = 'zRXiHTHzRHTdShFZ' +user = 'mini_chat' + +[mysql.write] +addr = '127.0.0.1:3306' +name = 'mini_chat' +pass = 'zRXiHTHzRHTdShFZ' +user = 'mini_chat' + +[jwt] +admin_secret = "X9Rm9ycFr66w9syuYTWCc" +>>>>>>> Stashed changes diff --git a/internal/api/wechat/mini_template.go b/internal/api/wechat/mini_template.go new file mode 100644 index 0000000..4e44624 --- /dev/null +++ b/internal/api/wechat/mini_template.go @@ -0,0 +1,164 @@ +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" + + "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 + } + + // 发送模版消息 + accessToken, err := h.servicesMiniProgram.GetAccessToken(req.AppID, req.AppSecret, ctx) + if err != nil { + h.logger.Error(fmt.Sprintf("获取access_token失败: %s", err.Error())) + } else { + sendSubscribeMessageRequest := new(miniprogram.SendSubscribeMessageRequest) + sendSubscribeMessageRequest.Touser = req.Touser + sendSubscribeMessageRequest.TemplateID = req.TemplateID + sendSubscribeMessageRequest.Page = "pages/index/detail?url=1" + sendSubscribeMessageRequest.MiniprogramState = "formal" // 需要改成正式版 目前是体验版 跳转小程序类型:developer 为开发版;trial为体验版;formal 为正式版;默认为正式版 + sendSubscribeMessageRequest.Lang = "zh_CN" + sendSubscribeMessageRequest.Data.Thing1.Value = "留言提醒" + sendSubscribeMessageRequest.Data.Time2.Value = time.Now().Format("2006-01-02 15:04:05") + sendSubscribeMessageRequest.Data.Thing3.Value = "您有一条新的消息..." + + sendSubscribeMessageResponse := new(miniprogram.SendSubscribeMessageResponse) + err = miniprogram.SendSubscribeMessage(accessToken, sendSubscribeMessageRequest, sendSubscribeMessageResponse) + if err != nil { + res.Success = false + res.Message = "发送订阅消息失败" + err.Error() + h.logger.Error(fmt.Sprintf("发送模版消息失败: %s", err.Error())) + } else { + res.Success = true + res.Message = "订阅消息发送成功" + } + } + + ctx.Payload(res) + } +}