当前位置: 首页 > 工具软件 > go-openid > 使用案例 >

golang 微信小程序access_token获取刷新和登陆(openid和其他信息的获取)

司马同
2023-12-01

     微信小程序的绝大多数的后台接口都需使用 access_token,本片文章主要说明一下golang的基础功能实现,不做业务场景分析。

获取access_token

    首先贴上获取token的官方文档。https://developers.weixin.qq.com/miniprogram/dev/api-backend/getAccessToken.html

    官方给出的token的请求地址:

GET https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET

    可以看到请求方式是get,地址为https://api.weixin.qq.com/cgi-bin/token

    所需参数:

属性类型默认值必填说明
grant_typestring 填写 client_credential,固定值
appidstring 小程序唯一凭证,即 AppID,可在「微信公众平台 - 设置 - 开发设置」页中获得。(需要已经成为开发者,且帐号没有异常状态)
secretstring 小程序唯一凭证密钥,即 AppSecret,获取方式同 appid

    返回参数:

属性类型说明
access_tokenstring获取到的凭证
expires_innumber凭证有效时间,单位:秒。目前是7200秒之内的值。
errcodenumber错误码
errmsgstring错误信息

代码如下:

package wechat

import (
	"encoding/json"
	"errors"
	"io/ioutil"
	"log"
	"net/http"
	"net/url"
)

func requestToken(appid, secret string) (string, error) {
	u, err := url.Parse("https://api.weixin.qq.com/cgi-bin/token")
	if err != nil {
		log.Fatal(err)
	}
	paras := &url.Values{}
	//设置请求参数
	paras.Set("appid", appid)
	paras.Set("secret", secret)
	paras.Set("grant_type", "client_credential")
	u.RawQuery = paras.Encode()
	resp, err := http.Get(u.String())
	//关闭资源
	if resp != nil && resp.Body != nil {
		defer resp.Body.Close()
	}
	if err != nil {
		return "", errors.New("request token err :" + err.Error())
	}

	jMap := make(map[string]interface{})
	err = json.NewDecoder(resp.Body).Decode(&jMap)
	if err != nil {
		return "", errors.New("request token response json parse err :" + err.Error())
	}
	if jMap["errcode"] == nil || jMap["errcode"] == 0 {
		accessToken, _ := jMap["access_token"].(string)
		return accessToken, nil
	} else {
		//返回错误信息
		errcode := jMap["errcode"].(string)
		errmsg := jMap["errmsg"].(string)
		err = errors.New(errcode + ":" + errmsg)
		return "", err
	}

}

关于accessToken刷新的说明:

  • access_token 的存储至少要保留 512 个字符空间;
  • access_token 的有效期目前为 2 个小时,需定时刷新,重复获取将导致上次获取的 access_token 失效;
  • 建议开发者使用中控服务器统一获取和刷新 access_token,其他业务逻辑服务器所使用的 access_token 均来自于该中控服务器,不应该各自去刷新,否则容易造成冲突,导致 access_token 覆盖而影响业务;
  • access_token 的有效期通过返回的 expire_in 来传达,目前是7200秒之内的值,中控服务器需要根据这个有效时间提前去刷新。在刷新过程中,中控服务器可对外继续输出的老 access_token,此时公众平台后台会保证在5分钟内,新老 access_token 都可用,这保证了第三方业务的平滑过渡;
  • access_token 的有效时间可能会在未来有调整,所以中控服务器不仅需要内部定时主动刷新,还需要提供被动刷新 access_token 的接口,这样便于业务服务器在API调用获知 access_token 已超时的情况下,可以触发 access_token 的刷新流程。

以上官方说明可以看出,目前有效时间是7200秒,为了保证业务的平滑新token获取的时候,老token保持5分钟。

我们可以使用go的ticker来设置7000秒请求一次来保证token的持续可用

func init() {
	appid := ""
	secret := ""
	freshTokenTicker := time.NewTicker(7000 * time.Second)
	//requestToken()

	go func() {
   
		for  range freshTokenTicker.C {
		   
			
		
			 accessToken, err := requestToken(appid, secret)
			 if err != nil {
					//TODO 错误处理
			 }
			 log.Printf("token refresh :%s", accessToken)
		}
	}()

}

登陆

    小程序的登陆功能是通过前端获取js_code传入后台,然后后台来调code2session接口获取用户信息。

    接口文档链接:https://developers.weixin.qq.com/miniprogram/dev/api-backend/code2Session.html

    请求地址:

https://api.weixin.qq.com/sns/jscode2session?appid=APPID&secret=SECRET&js_code=JSCODE&grant_type=authorization_code

    请求参数:

属性类型默认值必填说明
appidstring 小程序 appId
secretstring 小程序 appSecret
js_codestring 登录时获取的 code,前端获取
grant_typestring 授权类型,此处只需填写 authorization_code,固定值

    返回参数:

属性类型说明
openidstring用户唯一标识
session_keystring会话密钥
unionidstring用户在开放平台的唯一标识符,在满足 UnionID 下发条件的情况下会返回,详见 UnionID 机制说明
errcodenumber错误码
errmsgstring错误信息

    可以看到,所需要的参数都在返回值当中,解析之后,返回给业务层来处理

    代码:

//返回的map可以替换为专门的结构体
func WechatLogin(js_code, appid, secret string) (map[string]interface{}, error) {

	Code2SessURL := "https://api.weixin.qq.com/sns/jscode2session?appid={appid}&secret={secret}&js_code={code}&grant_type=authorization_code"
	Code2SessURL = strings.Replace(Code2SessURL, "{appid}", appid, -1)
	Code2SessURL = strings.Replace(Code2SessURL, "{secret}", secret, -1)
	Code2SessURL = strings.Replace(Code2SessURL, "{code}", js_code, -1)
	resp, err := http.Get(Code2SessURL)
	//关闭资源
	if resp != nil && resp.Body != nil {
		defer resp.Body.Close()
	}
	if err != nil {
		return nil, errors.New("WechatLogin request err :" + err.Error())
	}

	var jMap map[string]interface{}
	err = json.NewDecoder(resp.Body).Decode(&jMap)

	if err != nil {
		return nil, errors.New("request token response json parse err :" + err.Error())

	}
	if _,ok:=jMap["errcode"] ;!ok || jMap["errcode"] == 0 {

		return jMap, nil
	} else {
		//返回错误信息
		errcode := jMap["errcode"].(string)
		errmsg := jMap["errmsg"].(string)
		err = errors.New(errcode + ":" + errmsg)
		return nil, err
	}
}

 

 类似资料: