浏览代码

fix:wx accesstoken获取从redis

Roc 2 年之前
父节点
当前提交
357f777e35
共有 4 个文件被更改,包括 106 次插入29 次删除
  1. 1 0
      .gitignore
  2. 23 0
      models/wechat.go
  3. 78 29
      services/wechat_send_msg.go
  4. 4 0
      utils/constants.go

+ 1 - 0
.gitignore

@@ -3,3 +3,4 @@
 /rdlucklog
 /rdlucklog
 /.idea
 /.idea
 /conf
 /conf
+.DS_Store

+ 23 - 0
models/wechat.go

@@ -85,4 +85,27 @@ func GetWxToken() (item *WxAccessToken, err error) {
 		utils.FileLog.Info(fmt.Sprintf("GetWxToken fail result:%s", string(result)))
 		utils.FileLog.Info(fmt.Sprintf("GetWxToken fail result:%s", string(result)))
 	}
 	}
 	return
 	return
+}
+
+// ModifyAccessToken 修改wx_access_token
+func ModifyAccessToken(accessToken string,expiresIn int64)(err error){
+	o := orm.NewOrm()
+	sql := `SELECT * FROM wx_token LIMIT 1`
+	wxToken := new(WxToken)
+	err = o.Raw(sql).QueryRow(&wxToken)
+	if err != nil && err.Error() != utils.ErrNoRow() {
+		utils.FileLog.Info("Get wxToken Err:", err.Error())
+		return
+	}
+	if wxToken == nil {
+		fmt.Println("wxToken is empty")
+		addSql := "insert into wx_token (access_token,expires_in) values (?,?)"
+		_, err = o.Raw(addSql, accessToken, expiresIn).Exec()
+	} else {
+		//判断token是否过期
+		updateSql := "update wx_token set access_token = ?,expires_in = ? "
+		_, err = o.Raw(updateSql, accessToken, expiresIn).Exec()
+		fmt.Println("更新 TOKEN:", err)
+	}
+	return
 }
 }

+ 78 - 29
services/wechat_send_msg.go

@@ -38,18 +38,6 @@ func SendWxTemplateMsg(sendInfo *models.SendWxTemplate) (err error) {
 		}
 		}
 	}()
 	}()
 	utils.FileLog.Info("services SendMsg")
 	utils.FileLog.Info("services SendMsg")
-
-	accessToken, err := models.GetWxAccessToken()
-	if err != nil {
-		msg = "GetWxAccessToken Err:" + err.Error()
-		return
-	}
-	if accessToken == "" {
-		msg = "accessToken is empty"
-		return
-	}
-
-	sendUrl := "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=" + accessToken
 	fmt.Println("send start")
 	fmt.Println("send start")
 	utils.FileLog.Info("send start")
 	utils.FileLog.Info("send start")
 
 
@@ -109,7 +97,7 @@ func SendWxTemplateMsg(sendInfo *models.SendWxTemplate) (err error) {
 
 
 	uniqueCode := utils.MD5(uniqueCodeStr)
 	uniqueCode := utils.MD5(uniqueCodeStr)
 
 
-	err = sendTemplateMsg(sendUrl, sendMap, sendInfo.OpenIdArr, sendInfo.Resource, uniqueCode, sendInfo.SendType)
+	err = sendTemplateMsg(sendMap, sendInfo.OpenIdArr, sendInfo.Resource, uniqueCode, sendInfo.SendType)
 	if err != nil {
 	if err != nil {
 		utils.FileLog.Info("send err:" + err.Error())
 		utils.FileLog.Info("send err:" + err.Error())
 	}
 	}
@@ -118,7 +106,8 @@ func SendWxTemplateMsg(sendInfo *models.SendWxTemplate) (err error) {
 	return
 	return
 }
 }
 
 
-func sendTemplateMsg(sendUrl string, sendMap map[string]interface{}, openIdArr []string, resource, uniqueCode string, sendType int) (err error) {
+// sendTemplateMsg 整理openid以及以往历史推送记录,移除已经推送的记录,并开始依次推送
+func sendTemplateMsg(sendMap map[string]interface{}, openIdArr []string, resource, uniqueCode string, sendType int) (err error) {
 	existList, err := models.GetTemplateRecordByUniqueCode(uniqueCode)
 	existList, err := models.GetTemplateRecordByUniqueCode(uniqueCode)
 	if err != nil && err.Error() != utils.ErrNoRow() {
 	if err != nil && err.Error() != utils.ErrNoRow() {
 		utils.FileLog.Info(fmt.Sprintf("GetTemplateRecordByUniqueCode Err:%s", err.Error()))
 		utils.FileLog.Info(fmt.Sprintf("GetTemplateRecordByUniqueCode Err:%s", err.Error()))
@@ -133,7 +122,7 @@ func sendTemplateMsg(sendUrl string, sendMap map[string]interface{}, openIdArr [
 				utils.FileLog.Info(fmt.Sprintf("SendTemplateMsgOne Marshal Err:%s", err.Error()))
 				utils.FileLog.Info(fmt.Sprintf("SendTemplateMsgOne Marshal Err:%s", err.Error()))
 				return err
 				return err
 			}
 			}
-			err = toSendTemplateMsg(sendUrl, data, resource, sendType, openId, uniqueCode)
+			err = toSendTemplateMsg(data, resource, sendType, openId, uniqueCode)
 			if err != nil {
 			if err != nil {
 				fmt.Println("send err:", err.Error())
 				fmt.Println("send err:", err.Error())
 				utils.FileLog.Info(fmt.Sprintf("ToSendTemplateMsg Err:%s", err.Error()))
 				utils.FileLog.Info(fmt.Sprintf("ToSendTemplateMsg Err:%s", err.Error()))
@@ -153,7 +142,7 @@ func sendTemplateMsg(sendUrl string, sendMap map[string]interface{}, openIdArr [
 					utils.FileLog.Info(fmt.Sprintf("SendTemplateMsgOne Marshal Err:%s", err.Error()))
 					utils.FileLog.Info(fmt.Sprintf("SendTemplateMsgOne Marshal Err:%s", err.Error()))
 					return err
 					return err
 				}
 				}
-				err = toSendTemplateMsg(sendUrl, data, resource, sendType, openId, uniqueCode)
+				err = toSendTemplateMsg( data, resource, sendType, openId, uniqueCode)
 				if err != nil {
 				if err != nil {
 					fmt.Println("send err:", err.Error())
 					fmt.Println("send err:", err.Error())
 					utils.FileLog.Info(fmt.Sprintf("ToSendTemplateMsg Err:%s", err.Error()))
 					utils.FileLog.Info(fmt.Sprintf("ToSendTemplateMsg Err:%s", err.Error()))
@@ -164,9 +153,17 @@ func sendTemplateMsg(sendUrl string, sendMap map[string]interface{}, openIdArr [
 	return
 	return
 }
 }
 
 
-func toSendTemplateMsg(sendUrl string, data []byte, resource string, sendType int, openId, uniqueCode string) (err error) {
-	var msg string
+// toSendTemplateMsg 实际推送微信
+func toSendTemplateMsg(data []byte, resource string, sendType int, openId, uniqueCode string) (err error) {
 	utils.FileLog.Info("Send:" + string(data))
 	utils.FileLog.Info("Send:" + string(data))
+	//获取accessToken
+	accessToken, err,errMsg := getWxAccessToken()
+	if err != nil {
+		utils.FileLog.Info(fmt.Sprintf("获取Token失败,err:%s,errMsg:%s",err.Error(), errMsg))
+		return
+	}
+	sendUrl := "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=" + accessToken
+
 	client := http.Client{}
 	client := http.Client{}
 	resp, err := client.Post(sendUrl, "application/json", bytes.NewBuffer(data))
 	resp, err := client.Post(sendUrl, "application/json", bytes.NewBuffer(data))
 	if err != nil {
 	if err != nil {
@@ -205,17 +202,18 @@ func toSendTemplateMsg(sendUrl string, data []byte, resource string, sendType in
 			}
 			}
 		}()
 		}()
 	}
 	}
-	accessToken, err := models.GetWxAccessToken()
-	if err != nil {
-		msg = "GetWxAccessToken Err:" + err.Error()
-		utils.FileLog.Info("获取Token失败,msg:" + msg)
-		return
-	}
-	if accessToken == "" {
-		msg = "accessToken is empty"
-		utils.FileLog.Info("accessToken为空,msg:" + msg)
-		return
+
+	//accessToken过期
+	if templateResponse.Errcode == 40001{
+		//强刷token并重新推送
+		accessToken,err,errMsg = refreshWxAccessToken()
+		if err != nil{
+			utils.FileLog.Info(fmt.Sprintf("refreshWxAccessToken Err:%s", err.Error()))
+			return err
+		}
+		return toSendTemplateMsg(data, resource, sendType, openId, uniqueCode)
 	}
 	}
+
 	//模板消息发送超过当日10万次限制错误处理
 	//模板消息发送超过当日10万次限制错误处理
 	if templateResponse.Errcode == 45009 {
 	if templateResponse.Errcode == 45009 {
 		key := "CACHE_SendTemplateMsg_ERR"
 		key := "CACHE_SendTemplateMsg_ERR"
@@ -258,8 +256,59 @@ func toSendTemplateMsg(sendUrl string, data []byte, resource string, sendType in
 			go alarm_msg.SendAlarmMsg("异常已解决,自动清理限制接口,调用成功", 3)
 			go alarm_msg.SendAlarmMsg("异常已解决,自动清理限制接口,调用成功", 3)
 			//go utils.SendEmail("异常已解决:", "自动清理限制接口,调用成功", utils.EmailSendToUsers)
 			//go utils.SendEmail("异常已解决:", "自动清理限制接口,调用成功", utils.EmailSendToUsers)
 			//重新推送一次
 			//重新推送一次
-			toSendTemplateMsg(sendUrl, data, resource, sendType, openId, uniqueCode)
+			toSendTemplateMsg(data, resource, sendType, openId, uniqueCode)
 		}
 		}
 	}
 	}
 	return
 	return
 }
 }
+
+// getWxAccessToken 获取微信token
+func getWxAccessToken()(accessToken string,err error,errMsg string){
+	accessToken, err = utils.Rc.RedisString(utils.CACHE_WX_ACCESS_TOKEN_HZ)
+	if err != nil {
+		errMsg = "GetWxAccessToken Err:" + err.Error()
+		utils.FileLog.Info("获取Token失败,msg:" + errMsg)
+		return
+	}
+	//取到数据后就直接返回了,没有后续了
+	if accessToken != ""{
+		return
+	}
+
+	//缓存中没有取到数据,那么需要去强制刷新新的accessToken
+	return refreshWxAccessToken()
+}
+
+// refreshWxAccessToken 强制刷新微信token
+func refreshWxAccessToken()(accessToken string,err error,errMsg string){
+	//调用微信官方接口获取新的accessToken
+	wxAccessToken, tmpErr := models.GetWxToken()
+	if tmpErr != nil {
+		errMsg = "通过微信接口获取accessToken失败 Err:" + err.Error()
+		err = tmpErr
+		return
+	}
+
+	//如果没有token数据
+	if wxAccessToken.AccessToken == "" {
+		errMsg = "微信返回的accessToken异常: Err:" + wxAccessToken.Errmsg
+		err = errors.New(errMsg)
+		return
+	}
+
+
+	accessToken = wxAccessToken.AccessToken
+	//更新mysql的accessToken
+	expiresIn := time.Now().Add(time.Duration(wxAccessToken.ExpiresIn) * time.Second).Unix()
+	err = models.ModifyAccessToken(wxAccessToken.AccessToken,expiresIn)
+	if err!=nil{
+		errMsg = "更新mysql中的accessToken失败 Err:" + err.Error()
+		return
+	}
+
+	//更新redis的accessToken(过期时间提前十分钟)
+	redisTimeExpire := time.Duration(wxAccessToken.ExpiresIn - 600) * time.Second
+	utils.Rc.SetNX(utils.CACHE_WX_ACCESS_TOKEN_HZ,accessToken,redisTimeExpire)
+
+	return
+}

+ 4 - 0
utils/constants.go

@@ -42,3 +42,7 @@ const (
 	WxYbAppId  = `wxb059c872d79b9967` //弘则研报小程序
 	WxYbAppId  = `wxb059c872d79b9967` //弘则研报小程序
 	WxCygxAppId  = `wxcc32b61f96720d2f` //弘则研报小程序
 	WxCygxAppId  = `wxcc32b61f96720d2f` //弘则研报小程序
 )
 )
+// 缓存key
+const (
+	CACHE_WX_ACCESS_TOKEN_HZ         = "wx:accesstoken:hzyj"                  //弘则研究公众号 微信accessToken
+)