-
Notifications
You must be signed in to change notification settings - Fork 35
/
accesstoken.go
95 lines (76 loc) · 1.78 KB
/
accesstoken.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
package weixin
import (
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"sync"
"time"
"github.com/arstd/log"
)
// tick := time.Tick(7 * time.Second)
const refreshTimeout = 30 * time.Minute
const tokenURL = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s"
type accessToken struct {
AccessToken string `json:"access_token"` // 获取到的凭证
ExpiresIn int `json:"expires_in"` // 凭证有效时间,单位:秒
mutex sync.RWMutex
}
// AccessToken 取最新的 access_token,必须使用这个接口取,内部已经加锁
var AccessToken func() string
// RefreshAccessToken 定时刷新 access_token
func RefreshAccessToken(appId, appSecret string) {
// 内部变量,外部不可以调用
var _token = &accessToken{}
AccessToken = func() string {
_token.mutex.RLock()
defer _token.mutex.RUnlock()
return _token.AccessToken
}
go func() {
url := fmt.Sprintf(tokenURL, appId, appSecret)
tick := time.Tick(refreshTimeout)
for {
new := refresh(url)
log.Debugf("old access token %+v", _token)
log.Debugf("new access token %+v", new)
_token.mutex.Lock()
_token.AccessToken = new.AccessToken
_token.ExpiresIn = new.ExpiresIn
_token.mutex.Unlock()
<-tick // 等待下一个时钟周期到来
}
}()
}
func refresh(url string, ns ...int) (new *accessToken) {
n := 0
if len(ns) > 0 {
n = ns[0]
}
var err error
defer func() {
if err != nil {
log.Error(err)
time.Sleep(3 * time.Minute)
if n < 9 {
n++
new = refresh(url, n)
}
}
}()
resp, err := http.Get(url)
if err != nil {
return
}
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return
}
resp.Body.Close()
new = &accessToken{}
err = json.Unmarshal(body, new)
if err != nil {
return
}
return new
}