소스 검색

推送模板消息

kobe6258 8 달 전
부모
커밋
e55319ab8e
4개의 변경된 파일161개의 추가작업 그리고 135개의 파일을 삭제
  1. 14 16
      controllers/message.go
  2. 136 118
      services/template_msg.go
  3. 1 1
      services/wechat.go
  4. 10 0
      utils/config.go

+ 14 - 16
controllers/message.go

@@ -404,7 +404,7 @@ func (this *MessageController) SendTemplateMsg() {
 		br.Msg = "DataType为空"
 		return
 	}
-	sendData := make(map[string]interface{})
+	var template services.SendWxTemplate
 	if req.DataType == Report {
 		var report *models.Report
 		report, err = models.GetReportById(req.DataId)
@@ -432,15 +432,15 @@ func (this *MessageController) SendTemplateMsg() {
 				br.ErrMsg = fmt.Sprintf("获取eta品种信息失败,Err:%v", err)
 				return
 			}
-			sendData["keyword1"] = map[string]interface{}{"value": strings.Join(names, ","), "color": "#173177"}
+			template.Keyword1 = strings.Join(names, ",")
 		case "HT":
-			sendData["keyword1"] = map[string]interface{}{"value": "ht", "color": "#173177"}
+			template.Keyword1 = "ht"
 		default:
-			sendData["keyword1"] = map[string]interface{}{"value": "", "color": "#173177"}
+			template.Keyword1 = ""
 		}
-		sendData["keyword2"] = map[string]interface{}{"value": report.Title, "color": "#173177"}
-		sendData["keyword3"] = map[string]interface{}{"value": report.PublishedTime, "color": "#173177"}
-		sendData["keyword4"] = map[string]interface{}{"value": report.Abstract, "color": "#173177"}
+		template.Keyword2 = report.Title
+		template.Keyword3 = report.PublishedTime
+		template.Keyword4 = report.Abstract
 		err = report.UpdateSendStatus(models.SEND)
 		if err != nil {
 			br.Msg = "发送模版消息失败"
@@ -456,10 +456,9 @@ func (this *MessageController) SendTemplateMsg() {
 			br.ErrMsg = "获取音频失败"
 			return
 		}
-
-		sendData["keyword1"] = map[string]interface{}{"value": "线上音频", "color": "#173177"}
-		sendData["keyword2"] = map[string]interface{}{"value": media.MediaName, "color": "#173177"}
-		sendData["keyword3"] = map[string]interface{}{"value": media.CreatedTime.Format(time.DateTime), "color": "#173177"}
+		template.Keyword1 = "线上音频"
+		template.Keyword2 = media.MediaName
+		template.Keyword3 = media.CreatedTime.Format(time.DateTime)
 		err = media.UpdateSendStatus(models.SEND)
 		if err != nil {
 			br.Msg = "发送模版消息失败"
@@ -475,10 +474,9 @@ func (this *MessageController) SendTemplateMsg() {
 			br.ErrMsg = "获取音频失败"
 			return
 		}
-
-		sendData["keyword1"] = map[string]interface{}{"value": "线上视频", "color": "#173177"}
-		sendData["keyword2"] = map[string]interface{}{"value": media.MediaName, "color": "#173177"}
-		sendData["keyword3"] = map[string]interface{}{"value": media.CreatedTime.Format(time.DateTime), "color": "#173177"}
+		template.Keyword1 = "线上视频"
+		template.Keyword2 = media.MediaName
+		template.Keyword3 = media.CreatedTime.Format(time.DateTime)
 		err = media.UpdateSendStatus(models.SEND)
 		if err != nil {
 			br.Msg = "发送模版消息失败"
@@ -500,7 +498,7 @@ func (this *MessageController) SendTemplateMsg() {
 		}
 		openIds = append(openIds, openId)
 	}
-	err = services.SendMultiTemplateMsg(sendData, openIds, req.DataId, req.DataType)
+	err = services.SendMultiTemplateMsg(template, openIds, req.DataId, req.DataType)
 	if err != nil {
 		if req.DataType == Report {
 			var report *models.Report

+ 136 - 118
services/template_msg.go

@@ -38,84 +38,84 @@ type OpenIdList struct {
 	UserId int
 }
 
-// TemplateMsgSendClient.ClearQuota 清除发送超过当日10万次限制
-func (c *TemplateMsgSendClient) ClearQuota() (result *ClearQuotaResponse, err error) {
-	key := "CACHE_SendTemplateMsg_ERR"
-	exists := utils.Rc.IsExist(key)
-	if exists {
-		return
-	}
-	_ = utils.Rc.SetEX(key, 1, 6*time.Minute)
+//// TemplateMsgSendClient.ClearQuota 清除发送超过当日10万次限制
+//func (c *TemplateMsgSendClient) ClearQuota() (result *ClearQuotaResponse, err error) {
+//	key := "CACHE_SendTemplateMsg_ERR"
+//	exists := utils.Rc.IsExist(key)
+//	if exists {
+//		return
+//	}
+//	_ = utils.Rc.SetEX(key, 1, 6*time.Minute)
+//
+//	sendUrl := fmt.Sprintf(TemplateMsgClearQuotaUrl, c.AccessToken)
+//	client := http.Client{}
+//	clearData := make(map[string]interface{})
+//	clearData["appid"] = utils.HT_WX_APPID
+//	clearJson, _ := json.Marshal(clearData)
+//	resp, err := client.Post(sendUrl, "application/json", bytes.NewBuffer(clearJson))
+//	if err != nil {
+//		return
+//	}
+//	defer func() {
+//		_ = resp.Body.Close()
+//	}()
+//	clearBody, err := io.ReadAll(resp.Body)
+//	err = json.Unmarshal(clearBody, &result)
+//	return
+//}
 
-	sendUrl := fmt.Sprintf(TemplateMsgClearQuotaUrl, c.AccessToken)
-	client := http.Client{}
-	clearData := make(map[string]interface{})
-	clearData["appid"] = utils.HT_WX_APPID
-	clearJson, _ := json.Marshal(clearData)
-	resp, err := client.Post(sendUrl, "application/json", bytes.NewBuffer(clearJson))
-	if err != nil {
-		return
-	}
-	defer func() {
-		_ = resp.Body.Close()
-	}()
-	clearBody, err := io.ReadAll(resp.Body)
-	err = json.Unmarshal(clearBody, &result)
-	return
-}
-
-// TemplateMsgSendClient.SendMsg 推送消息
-func (c *TemplateMsgSendClient) SendMsg() (sendRes *SendTemplateResponse, err error) {
-	// 请求接口
-	sendUrl := fmt.Sprintf(TemplateMsgSendUrl, c.AccessToken)
-	client := http.Client{}
-	resp, err := client.Post(sendUrl, "application/json", bytes.NewBuffer(c.Data))
-	if err != nil {
-		return
-	}
-	defer func() {
-		_ = resp.Body.Close()
-	}()
-	body, _ := io.ReadAll(resp.Body)
-	if err = json.Unmarshal(body, &sendRes); err != nil {
-		return
-	}
-	// 模板消息发送超过当日10万次限制错误处理
-	if sendRes.Errcode == 45009 {
-		// 发送提示邮件
-		// go alarm_msg.SendAlarmMsg("模板消息发送超过当日10万次限制, SendTemplateResponse: "+string(body), 3)
-		// 清理限制
-		clearRes, e := c.ClearQuota()
-		if e != nil {
-			err = e
-			return
-		}
-		if clearRes.Errcode != 0 {
-			clearJson, er := json.Marshal(clearRes)
-			if er != nil {
-				return nil, er
-			}
-			fmt.Println("自动清理模板消息限制接口, 调用失败, ClearQuotaResponse: " + string(clearJson))
-			// go alarm_msg.SendAlarmMsg("自动清理模板消息限制接口, 调用失败, ClearQuotaResponse: "+string(clearJson), 3)
-			return
-		}
-		// 发送成功邮件
-		// go alarm_msg.SendAlarmMsg("自动清理模板消息限制接口, 调用成功", 1)
-		// 重新推送
-		go func() {
-			_, e := c.SendMsg()
-			if e != nil {
-				return
-				// reSendJson, _ := json.Marshal(reSend)
-				// alarm_msg.SendAlarmMsg("重新推送模板消息失败, SendTemplateResponse: "+string(reSendJson), 3)
-			}
-		}()
-	}
-	if sendRes.Errcode != 0 {
-		err = errors.New("推送模板消息失败, SendTemplateResponse: " + string(body))
-	}
-	return
-}
+//// TemplateMsgSendClient.SendMsg 推送消息
+//func (c *TemplateMsgSendClient) SendMsg() (sendRes *SendTemplateResponse, err error) {
+//	// 请求接口
+//	sendUrl := fmt.Sprintf(TemplateMsgSendUrl, c.AccessToken)
+//	client := http.Client{}
+//	resp, err := client.Post(sendUrl, "application/json", bytes.NewBuffer(c.Data))
+//	if err != nil {
+//		return
+//	}
+//	defer func() {
+//		_ = resp.Body.Close()
+//	}()
+//	body, _ := io.ReadAll(resp.Body)
+//	if err = json.Unmarshal(body, &sendRes); err != nil {
+//		return
+//	}
+//	// 模板消息发送超过当日10万次限制错误处理
+//	if sendRes.Errcode == 45009 {
+//		// 发送提示邮件
+//		// go alarm_msg.SendAlarmMsg("模板消息发送超过当日10万次限制, SendTemplateResponse: "+string(body), 3)
+//		// 清理限制
+//		clearRes, e := c.ClearQuota()
+//		if e != nil {
+//			err = e
+//			return
+//		}
+//		if clearRes.Errcode != 0 {
+//			clearJson, er := json.Marshal(clearRes)
+//			if er != nil {
+//				return nil, er
+//			}
+//			fmt.Println("自动清理模板消息限制接口, 调用失败, ClearQuotaResponse: " + string(clearJson))
+//			// go alarm_msg.SendAlarmMsg("自动清理模板消息限制接口, 调用失败, ClearQuotaResponse: "+string(clearJson), 3)
+//			return
+//		}
+//		// 发送成功邮件
+//		// go alarm_msg.SendAlarmMsg("自动清理模板消息限制接口, 调用成功", 1)
+//		// 重新推送
+//		go func() {
+//			_, e := c.SendMsg()
+//			if e != nil {
+//				return
+//				// reSendJson, _ := json.Marshal(reSend)
+//				// alarm_msg.SendAlarmMsg("重新推送模板消息失败, SendTemplateResponse: "+string(reSendJson), 3)
+//			}
+//		}()
+//	}
+//	if sendRes.Errcode != 0 {
+//		err = errors.New("推送模板消息失败, SendTemplateResponse: " + string(body))
+//	}
+//	return
+//}
 
 // AddUserTemplateRecord 新增模板消息推送记录
 func AddUserTemplateRecord(userId, sendStatus int, sendType string, openid, sendData, result string) (err error) {
@@ -134,7 +134,7 @@ func AddUserTemplateRecord(userId, sendStatus int, sendType string, openid, send
 }
 
 // SendMultiTemplateMsg 推送模板消息至多个用户
-func SendMultiTemplateMsg(sendData map[string]interface{}, items []*OpenIdList, Id int, sendType string) (err error) {
+func SendMultiTemplateMsg(templateData SendWxTemplate, items []*OpenIdList, Id int, sendType string) (err error) {
 	ws := GetWxChat()
 	accessToken, err := ws.GetAccessToken()
 	if err != nil {
@@ -142,7 +142,6 @@ func SendMultiTemplateMsg(sendData map[string]interface{}, items []*OpenIdList,
 		// alarm_msg.SendAlarmMsg("获取微信token失败, Err:"+err.Error(), 1)
 		return
 	}
-	sendMap := make(map[string]interface{})
 	var path string
 	switch sendType {
 	case "report":
@@ -154,46 +153,65 @@ func SendMultiTemplateMsg(sendData map[string]interface{}, items []*OpenIdList,
 	default:
 		return errors.New("非法的消息类型")
 	}
+	templateData.TemplateId = utils.TEMPLATE_ID_BY_PRODUCT
+	templateData.WxAppId = utils.HT_WX_APPID
+	templateData.RedirectUrl = fmt.Sprintf(path, Id)
+	templateData.RedirectTarget = 1
+	templateData.SendType = 8
+	templateData.Resource = utils.RESOURCE
 	for _, item := range items {
-		sendMap["template_id"] = utils.TEMPLATE_ID_BY_PRODUCT
-		sendMap["miniprogram"] = map[string]interface{}{
-			"appid":    utils.HT_MINI_APPID,
-			"pagepath": fmt.Sprintf(path, Id),
-		}
-		sendMap["touser"] = item.OpenId
-		sendMap["data"] = sendData
-		data, e := json.Marshal(sendMap)
-		if e != nil {
-			utils.FileLog.Info("新增模板消息推送记录失败, Err:" + e.Error())
-			return
-		}
-		ts := &TemplateMsgSendClient{
-			AccessToken: accessToken,
-			Data:        data,
-		}
-		result, e := ts.SendMsg()
-		if e != nil {
-			utils.FileLog.Info("新增模板消息推送记录失败, Err:" + e.Error())
-			return
-		}
-		if result == nil {
-			return
-		}
-		// 推送消息记录
-		{
-			go func() {
-				sendStatus := 1
-				if e != nil {
-					sendStatus = 0
-				}
-				resultJson, _ := json.Marshal(result)
-				err = AddUserTemplateRecord(item.UserId, sendStatus, sendType, item.OpenId, string(data), string(resultJson))
-				if err != nil {
-					utils.FileLog.Info("新增模板消息推送记录失败, Err:" + err.Error())
-					return
-				}
-			}()
-		}
+		templateData.OpenIdArr = append(templateData.OpenIdArr, item.OpenId)
+	}
+	return sendMsg(templateData)
+}
+
+type SendWxTemplate struct {
+	WxAppId        string   `description:"公众号appId"`
+	First          string   `description:"模板消息first字段"`
+	Keyword1       string   `description:"模板消息keyword1字段"`
+	Keyword2       string   `description:"模板消息keyword2字段"`
+	Keyword3       string   `description:"模板消息keyword3字段"`
+	Keyword4       string   `description:"模板消息keyword4字段"`
+	Keyword5       string   `description:"模板消息keyword5字段"`
+	Productname    string   `description:"模板消息productname字段"`
+	Date           string   `description:"模板消息date字段"`
+	Remark         string   `description:"模板消息remark字段"`
+	TemplateId     string   `description:"模板id"`
+	RedirectUrl    string   `description:"跳转地址"`
+	RedirectTarget int      `description:"小程序跳转目标:1:弘则研报小程序,2:随手办公小程序,3:查研观向"`
+	Resource       string   `description:"资源唯一标识"`
+	SendType       int      `description:"发送的消息类型:1:报告,2:指标更新提醒,3:审批通知,4:销售领取客户通知,5:活动取消通知,6活动更改时间通知,7:关注的作者发布报告通知,8:发送日报(周报、双周报、月报)模板消息,9:活动预约/报名时间通知"`
+	OpenIdArr      []string `description:"消息接收者openid"`
+}
+
+func sendMsg(template SendWxTemplate) (err error) {
+	// 设置请求 URL
+	// 设置 POST 请求的数据
+	data, err := json.Marshal(template)
+	if err != nil {
+		utils.FileLog.Error("发送消息模板失败,请求data json序列化失败,err:%v", err)
+	}
+	req, _ := http.NewRequest("POST", utils.ETA_PUB_URL, bytes.NewBuffer(data))
+	if err != nil {
+		fmt.Println("发送模板消息失败,创建请求失败:", err)
+		return
+	}
+	// 设置 Content-Type
+	req.Header.Set("Content-Type", "application/json")
+	// 发送 POST 请求
+	client := &http.Client{}
+	resp, err := client.Do(req)
+	if err != nil {
+		utils.FileLog.Error("发送消息模板失败,请求失败,err:%v", err)
+		return
+	}
+	defer resp.Body.Close()
+	// 处理响应
+	body, _ := io.ReadAll(resp.Body)
+	if resp.StatusCode != http.StatusOK {
+		utils.FileLog.Error("发送消息模板失败,请求失败,err:%v", string(body))
+		return
 	}
+	utils.FileLog.Info("发送消息模板成功,请求成功,body:%v", string(body))
 	return
 }

+ 1 - 1
services/wechat.go

@@ -38,6 +38,7 @@ func (wechat WechatAccessToken) GetAccessToken() (accessToken string, err error)
 	//如果300s就要过期了,那么就去刷新accessToken
 	wxToken, err := models.GetWxTokenById()
 	if err != nil {
+		utils.FileLog.Info("获取微信token失败,Err:", err.Error())
 		return
 	}
 	//如果300s就要过期了,那么就去刷新accessToken
@@ -47,7 +48,6 @@ func (wechat WechatAccessToken) GetAccessToken() (accessToken string, err error)
 			err = tmpErr
 			return
 		}
-
 		var updateCols = []string{"access_token", "expires_in"}
 		wxToken.AccessToken = tmpAccessToken
 		wxToken.ExpiresIn = time.Now().Unix() + expires - 600 //快过期前10分钟就刷新掉

+ 10 - 0
utils/config.go

@@ -17,6 +17,10 @@ var (
 	Rc          RedisClient //redis缓存
 )
 var ObjectStorageClient string // 目前有oss minio,默认oss
+// 推送模版消息
+var (
+	ETA_PUB_URL string
+)
 
 // 阿里云配置
 var (
@@ -75,6 +79,7 @@ var (
 	HT_WX_APPID            string
 	HT_MINI_APPID          string
 	TEMPLATE_ID_BY_PRODUCT string
+	RESOURCE               string
 )
 
 // ES索引配置
@@ -167,6 +172,10 @@ func init() {
 		STSTokenCacheKey = config["sts_token_cache_key"]
 	}
 
+	//推送模版消息
+	{
+		ETA_PUB_URL = config["eta_pub_url"]
+	}
 	// ES配置
 	{
 		ES_URL = config["es_url"]
@@ -184,6 +193,7 @@ func init() {
 		HT_WX_APP_SECRET = config["ht_wx_app_secret"]
 		TEMPLATE_ID_BY_PRODUCT = config["template_id_by_product"]
 		HT_MINI_APPID = config["ht_mini_appid"]
+		RESOURCE = config["resource"]
 	}
 	// 初始化ES
 	initEs()