package services import ( "bytes" "encoding/json" "errors" "eta/eta_mini_bridge/models" "eta/eta_mini_bridge/utils" "fmt" "io" "net/http" "time" ) var ( TemplateMsgSendUrl = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=%s" TemplateMsgClearQuotaUrl = "https://api.weixin.qq.com/cgi-bin/clear_quota?access_token=%s" ) type TemplateMsgSendClient struct { AccessToken string Data []byte } type SendTemplateResponse struct { Errcode int `json:"errcode"` Errmsg string `json:"errmsg"` MsgID int `json:"msgid"` } type ClearQuotaResponse struct { Errcode int `json:"errcode"` Errmsg string `json:"errmsg"` } type OpenIdList struct { OpenId string 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) sendUrl := fmt.Sprintf(TemplateMsgClearQuotaUrl, c.AccessToken) client := http.Client{} clearData := make(map[string]interface{}) clearData["appid"] = utils.DW_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 } // AddUserTemplateRecord 新增模板消息推送记录 func AddUserTemplateRecord(userId, sendStatus, sendType int, openid, sendData, result string) (err error) { item := &models.UserTemplateRecord{ UserId: userId, OpenId: openid, SendData: sendData, Result: result, CreateDate: time.Now().Format(utils.FormatDate), CreateTime: time.Now().Format(utils.FormatDateTime), SendStatus: sendStatus, SendType: sendType, } err = item.Insert() return } // SendMultiTemplateMsg 推送模板消息至多个用户 func SendMultiTemplateMsg(sendData map[string]interface{}, items []*OpenIdList, sendType, reportId int) (err error) { ws := GetWxChat() accessToken, err := ws.GetAccessToken() if err != nil { utils.FileLog.Info("获取微信token失败, Err:" + err.Error()) // alarm_msg.SendAlarmMsg("获取微信token失败, Err:"+err.Error(), 1) return } sendMap := make(map[string]interface{}) for _, item := range items { sendMap["template_id"] = utils.TEMPLATE_ID_BY_PRODUCT sendMap["miniprogram"] = map[string]interface{}{ "appid": utils.WX_MINI_APPID, "pagepath": fmt.Sprintf("pages-report/reportDetail/index?id=%d", reportId), } 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 } }() } } return }