| "time" | "time" | ||||
| ) | ) | ||||
| //SaveToPath : where the authtoken json file is stored | |||||
| const SaveToPath = "/tmp/wechat_hitxy_token" | |||||
| //SaveToPath : where the AuthToken json file is stored | |||||
| //const SaveToPath = "/tmp/wechat_hitxy_token" | |||||
| type authToken struct { | |||||
| //AuthToken Access Token, for temporary access WechatAPI | |||||
| type AuthToken struct { | |||||
| AccessToken string `json:"access_token"` | AccessToken string `json:"access_token"` | ||||
| ExpireIn int64 `json:"expires_in"` | ExpireIn int64 `json:"expires_in"` | ||||
| Time time.Time `json:"created_at"` | Time time.Time `json:"created_at"` | ||||
| } | } | ||||
| //WechatAccessToken Global AccessToken | |||||
| var WechatAccessToken AuthToken | |||||
| //GetAccessToken returns a valid access_token for wechat_api | //GetAccessToken returns a valid access_token for wechat_api | ||||
| // the token is auomatically renewed if it's about to expire | // the token is auomatically renewed if it's about to expire | ||||
| // if error happens, return empty string and error | // if error happens, return empty string and error | ||||
| // if success, return token string and nil | // if success, return token string and nil | ||||
| func GetAccessToken() (string, error) { | func GetAccessToken() (string, error) { | ||||
| t, err := readTokenFromFile("/tmp/wechat_hitxy_token") | |||||
| t, err := readTokenFromFile(APIConfig.AuthTokenSaveTo) | |||||
| if isAuthTokenExpired(t) { | if isAuthTokenExpired(t) { | ||||
| t, err = renewAuthtoken() | |||||
| t, err = renewAuthToken() | |||||
| if err != nil { | if err != nil { | ||||
| return "", err // cannot get token | return "", err // cannot get token | ||||
| } | } | ||||
| } | } | ||||
| WechatAccessToken = t | |||||
| return t.AccessToken, nil | return t.AccessToken, nil | ||||
| } | } | ||||
| func isAuthTokenExpired(t authToken) bool { | |||||
| func isAuthTokenExpired(t AuthToken) bool { | |||||
| seconds := fmt.Sprintf("%ds", t.ExpireIn) //7200s | seconds := fmt.Sprintf("%ds", t.ExpireIn) //7200s | ||||
| duration, _ := time.ParseDuration(seconds) | duration, _ := time.ParseDuration(seconds) | ||||
| expire := t.Time.Add(duration) | expire := t.Time.Add(duration) | ||||
| //save token to perminant storage | //save token to perminant storage | ||||
| func writeTokenToFile(body []byte, path string) { | func writeTokenToFile(body []byte, path string) { | ||||
| log.Printf("writing authtoke to %s\r\n", path) | |||||
| log.Printf("writing authtoken to %s\r\n", path) | |||||
| ioutil.WriteFile(path, body, 0600) | ioutil.WriteFile(path, body, 0600) | ||||
| } | } | ||||
| //read token from permenant storage | //read token from permenant storage | ||||
| func readTokenFromFile(path string) (authToken, error) { | |||||
| var m authToken | |||||
| func readTokenFromFile(path string) (AuthToken, error) { | |||||
| var m AuthToken | |||||
| log.Printf("read authtoke from %s\r\n", path) | log.Printf("read authtoke from %s\r\n", path) | ||||
| body, err := ioutil.ReadFile(path) | body, err := ioutil.ReadFile(path) | ||||
| json.Unmarshal(body, &m) | json.Unmarshal(body, &m) | ||||
| } | } | ||||
| //issue web request to get token from wechat | //issue web request to get token from wechat | ||||
| func renewAuthtoken() (authToken, error) { | |||||
| func renewAuthToken() (AuthToken, error) { | |||||
| //url := "http://vimeo.com/api/v2/brad/info.json" | //url := "http://vimeo.com/api/v2/brad/info.json" | ||||
| url := fmt.Sprintf("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s", APIConfig.Appid, APIConfig.AppSecret) | url := fmt.Sprintf("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s", APIConfig.Appid, APIConfig.AppSecret) | ||||
| var myClient = &http.Client{Timeout: 20 * time.Second} | var myClient = &http.Client{Timeout: 20 * time.Second} | ||||
| r, err := myClient.Get(url) | r, err := myClient.Get(url) | ||||
| if err != nil { | if err != nil { | ||||
| return authToken{}, err | |||||
| return AuthToken{}, err | |||||
| } | } | ||||
| defer r.Body.Close() | defer r.Body.Close() | ||||
| var t authToken | |||||
| var t AuthToken | |||||
| err = json.NewDecoder(r.Body).Decode(&t) | err = json.NewDecoder(r.Body).Decode(&t) | ||||
| if err != nil { | if err != nil { | ||||
| return authToken{}, err | |||||
| return AuthToken{}, err | |||||
| } | } | ||||
| t.Time = time.Now() | t.Time = time.Now() | ||||
| b, _ := json.Marshal(&t) | b, _ := json.Marshal(&t) | ||||
| writeTokenToFile(b, SaveToPath) | |||||
| writeTokenToFile(b, APIConfig.AuthTokenSaveTo) | |||||
| return t, nil | return t, nil | ||||
| } | } | ||||