使用golang快速开发微信公众平台(二):获取accessToken

前端之家收集整理的这篇文章主要介绍了使用golang快速开发微信公众平台(二):获取accessToken前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

微信的文档有个很有意思的地方,刚开始你顺着文档看,就可以一步一步完成自己需要的功能,但走着走着,就感到有些混乱,你再顺着文档做,就掉坑里了。

我们在使用golang快速开发微信公众平台(一)微信验证服务器通过后,就要开始着手获取accessToken,这个东西很重要,在菜单、客服、支付等操作中都需要用到


在文档中,有以下2点很重要:

  1. access_token每日限额获取2000次,相当于允许你以43秒的频率来取,但明显这样做会显得很傻。
  2. access_token有效时间是7200秒


以get请求获取一段json并解析来获取access_token,看起来很简单对不对?但应用到实际中就稍微有些麻烦了:

  1. 需要找个什么东西来存,可以是文件、可以是数据库、甚至可以直接就扔到全局变量里。嗯,我选数据库
  2. 定时发送这个get请求,更新数据库
  3. 这个get请求是可能失败的 是可能失败的 是可能失败的,虽然这个概率极低,但对于如此重要的参数,一旦在2个小时的空档期内都无法调用,会产生极其灾难性的后果,别问我怎么知道的

好,思路捋一下,3件事:拼接get请求json解析,建个表来存取更新,定时任务

开始搓代码

access_token的存取

WxAccTokenUtil.go

package WxPlatUtil

import (
    "strings"
    "net/http"
    "fmt"
    "io/IoUtil"
    "bytes"
    "encoding/json"
    "mlshop/shopUtils/logUtils"
    "mlshop/models"
)

type AccessTokenResponse struct {
    AccessToken string  `json:"access_token"`
    ExpiresIn   float64 `json:"expires_in"`
}

//type AccessTokenErrorResponse struct {
// Errcode float64
// Errmsg string
//}
//获取wx_AccessToken 拼接get请求 解析返回json结果 返回 AccessToken和err
func FetchAccessToken(appID,appSecret,accessTokenFetchUrl string) (string,error) {

    requestLine := strings.Join([]string{accessTokenFetchUrl,"?grant_type=client_credential&appid=",appID,"&secret=",appSecret},"")

    resp,err := http.Get(requestLine)
    if err != nil || resp.StatusCode != http.StatusOK {
        fmt.Println("发送get请求获取 atoken 错误",err)
        logUtils.GetLog().Error("发送get请求获取 atoken 错误",err)
        return "",err
    }

    defer resp.Body.Close()
    body,err := IoUtil.ReadAll(resp.Body)
    if err != nil {
        fmt.Println("发送get请求获取 atoken 读取返回body错误",err)
        logUtils.GetLog().Error("发送get请求获取 atoken 读取返回body错误",err
    }

    if bytes.Contains(body,[]byte("access_token")) {
        atr := AccessTokenResponse{}
        err = json.Unmarshal(body,&atr)
        if err != nil {
            fmt.Println("发送get请求获取 atoken 返回数据json解析错误",err)
            logUtils.GetLog().Error("发送get请求获取 atoken 返回数据json解析错误",err)
            return "",err
        }
        return atr.AccessToken,atr.ExpiresIn,nil
    } else {
        fmt.Println("发送get请求获取 微信返回 err")
        ater := models.AccessTokenErrorResponse{}
        err = json.Unmarshal(body,&ater)
        fmt.Printf("发送get请求获取 微信返回 的错误信息 %+v\n",ater)
        if err != nil {
            return "",err
        }
        return "",fmt.Errorf("%s",ater.Errmsg)
    }
}
//type WxAccessToken struct {
// Id int `orm:"auto"`
// AccessToken string
//}
//微信公众平台的参数
//type WxBase struct {
// Id int `orm:"auto"`
// AppID string
// AppSecret string
// Token string
// EncodingAESKey string
//}
//数据库存取更新access_token
func GetAndUpdateDBWxAToken(o orm.Ormer) error {

    at := models.WxAccessToken{Id: 1}
    o.ReadOrCreate(&at,"id")

    wxBase := models.WxBase{Id:1}
    err := orm.NewOrm().Read(&wxBase)
    if err != nil {
        fmt.Println("从数据库查询WxBase失败",err)
        return err
    }

    //向微信服务器发送获取accessToken的get请求
    accessToken,err := WxPlatUtil.FetchAccessToken(wxBase.AppID,wxBase.AppSecret,"https://api.weixin.qq.com/cgi-bin/token")
    if err != nil {
        fmt.Println("向微信服务器发送获取accessToken的get请求失败",err)
        logUtils.GetLog().Error("向微信服务器发送获取accessToken的get请求失败",err)
        return err
    }

    at.AccessToken = accessToken
    o.Update(&at,"access_token")

    return nil
}

得益于go语言方便的json与struct转换和beego的orm,第一个任务很快就可以完成。
接下来,我们要考虑定时任务的问题。

定时任务

定时的话time包倒是有个ticker,出现在脑子里的第一个思路是把时间段时间点都转化为秒数,然后开始倒计时。。。好傻
可以搜到很多关于golang的time使用方法,比如下面这个

func startTimer(f func()) {
        go func() {
            for {
                f()
                now := time.Now()
                // 计算下一个零点
                next := now.Add(time.Hour * 24)
                next = time.Date(next.Year(),next.Month(),next.Day(),0,next.Location())
                t := time.NewTimer(next.Sub(now))
                <-t.C
            }
        }()
    }

嗯 看起来还是很不错的,群里讨论的时候,大家都喜欢在当前时间上+24小时获取明天,然后取0点,然后加上自己想要的时间段

但是 GRD的需求是会变来变去的

今天要求是明天2点,后天要求是明天2点半,大后天又变成了9个小时来一次。结合咱们的定时任务,要是既能传时间段,又能传时间点就好了。

github上go的time库倒是有,可我一个都没用到。嗯 因为懒。

这就是为啥我推荐大家用pycharm、PHPstrom、webstrom来写go,看库多方便,而且还自带ssh ftp工具,是人都知道在Win Mac 上找不同的ftp工具是多么的痛苦。表用IDEA…等你用了就知道为啥。

beego自带的定时任务模块很强,而且使用简单,虽然传参很丑,不适合装逼,丑到啥地步呢:

如果是集团军作战,传这样的参数肯定是被骂的,但咱是单兵作战,好用即可。到这里,咱们的定时任务也可以出炉了:

//从task_test.go文件里找使用方法
func shopTiMetask(o orm.Ormer) {

    timeStr2 := "0 */60 * * * *" // 获取wx token
    t2 := toolBox.NewTask("getAtoken",timeStr2,func() error {

         err := WxPlatUtil.GetAndUpdateDBWxAToken(o)
         if err != nil{
            //todo 向微信请求access_token失败 结合业务逻辑处理
        }
         return nil
    })
    toolBox.AddTask("tk2",t2)
    toolBox.StartTask()

}

唉咋知道怎么用的?test文件啊;唉这命名真不规范,我还有数据库备份也用代码写的。。。 ok,就这么几句,23步咱们都干完了,第三步其实大家自行处理就好。虽然说的很严重,但是只要有处理就不会那么惨。。。

原文链接:https://www.f2er.com/go/189331.html

猜你在找的Go相关文章