| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889 |
- package dialog
- import (
- stdcontext "context"
- "encoding/json"
- "errors"
- "fmt"
- "sync"
- "time"
- "github.com/silenceper/wechat/v2/aispeech/config"
- "github.com/silenceper/wechat/v2/cache"
- )
- const accessTokenCacheKeyPrefix = "gowechat_aispeech_"
- var errEmptyAccessToken = errors.New("aispeech access_token is empty")
- // AccessToken 微信智能对话 access token.
- type AccessToken struct {
- cfg *config.Config
- accessTokenLock *sync.Mutex
- }
- // NewAccessToken new AccessToken.
- func NewAccessToken(cfg *config.Config) *AccessToken {
- if cfg.Cache == nil {
- panic("cache is needed")
- }
- return &AccessToken{
- cfg: cfg,
- accessTokenLock: new(sync.Mutex),
- }
- }
- // GetAccessToken 获取 access token.
- func (ak *AccessToken) GetAccessToken() (string, error) {
- return ak.GetAccessTokenContext(stdcontext.Background())
- }
- // GetAccessTokenContext 获取 access token.
- func (ak *AccessToken) GetAccessTokenContext(ctx stdcontext.Context) (string, error) {
- cacheKey := fmt.Sprintf("%s_access_token_%s_%s", accessTokenCacheKeyPrefix, ak.cfg.AppID, ak.cfg.Account)
- if val := cache.GetContext(ctx, ak.cfg.Cache, cacheKey); val != nil {
- if accessToken, ok := val.(string); ok && accessToken != "" {
- return accessToken, nil
- }
- }
- ak.accessTokenLock.Lock()
- defer ak.accessTokenLock.Unlock()
- if val := cache.GetContext(ctx, ak.cfg.Cache, cacheKey); val != nil {
- if accessToken, ok := val.(string); ok && accessToken != "" {
- return accessToken, nil
- }
- }
- accessToken, err := ak.getAccessTokenFromServer(ctx)
- if err != nil {
- return "", err
- }
- if err = cache.SetContext(ctx, ak.cfg.Cache, cacheKey, accessToken, 110*time.Minute); err != nil {
- return "", err
- }
- return accessToken, nil
- }
- func (ak *AccessToken) getAccessTokenFromServer(ctx stdcontext.Context) (string, error) {
- req := &AccessTokenRequest{Account: ak.cfg.Account}
- body, err := json.Marshal(req)
- if err != nil {
- return "", err
- }
- response, err := post(ctx, ak.cfg, tokenPath, body, "application/json", "", ak.cfg.AppID)
- if err != nil {
- return "", err
- }
- var res accessTokenData
- if _, err = decodeResponse(response, &res, "AISpeechGetAccessToken"); err != nil {
- return "", err
- }
- if res.AccessToken == "" {
- return "", errEmptyAccessToken
- }
- return res.AccessToken, nil
- }
|