Files
baseapi/platformapi/weixinapi/weixinapi.go
2018-06-27 10:37:07 +08:00

134 lines
3.1 KiB
Go

package weixinapi
import (
"net/http"
"net/url"
"sync"
"git.rosy.net.cn/baseapi"
"git.rosy.net.cn/baseapi/platformapi"
"git.rosy.net.cn/baseapi/utils"
)
const (
prodURL = "https://api.weixin.qq.com"
)
const (
ResponseCodeBusy = -1
ResponseCodeSuccess = 0
)
type TokenInfo struct {
AccessToken string `json:"access_token"`
ExpiresIn int `json:"expires_in"`
}
type ErrorInfo struct {
ErrCode int `json:"errcode"`
ErrMsg string `json:"errmsg"`
}
type API struct {
token string
appID string
secret string
client *http.Client
config *platformapi.APIConfig
locker sync.RWMutex
}
func New(appID, secret string, config ...*platformapi.APIConfig) *API {
curConfig := platformapi.DefAPIConfig
if len(config) > 0 {
curConfig = *config[0]
}
return &API{
appID: appID,
secret: secret,
client: &http.Client{Timeout: curConfig.ClientTimeout},
config: &curConfig,
}
}
func (a *API) SetToken(newToken string) bool {
curToken := a.GetToken()
if curToken != newToken {
a.locker.Lock()
defer a.locker.Unlock()
a.token = newToken
return true
}
return false
}
func (a *API) GetToken() string {
a.locker.RLock()
defer a.locker.RUnlock()
return a.token
}
func (a *API) AccessAPI(action string, params map[string]interface{}) (retVal interface{}, err error) {
if params == nil {
panic("params is nil!")
}
params2 := make(map[string]interface{})
for k, v := range params {
params2[k] = v
}
params2["appid"] = a.appID
params2["secret"] = a.secret
fullURL, _ := url.Parse(utils.GenerateGetURL(prodURL, action, params2))
// baseapi.SugarLogger.Debug(url.String())
request := &http.Request{
Method: "GET",
URL: fullURL,
}
err = platformapi.AccessPlatformAPIWithRetry(a.client, request, a.config, func(response *http.Response) (result string, err error) {
jsonResult1, err := utils.HTTPResponse2Json(response)
if err != nil {
return platformapi.ErrLevelGeneralFail, platformapi.ErrResponseDataFormatWrong
}
var errInfo *ErrorInfo
// 微信的返回值,在错误与正常情况下,结构是完全不一样的
if errCode, ok := jsonResult1["errcode"]; ok {
errInfo = &ErrorInfo{
ErrCode: int(utils.MustInterface2Int64(errCode)),
ErrMsg: jsonResult1["errmsg"].(string),
}
} else {
retVal = &TokenInfo{
AccessToken: jsonResult1["access_token"].(string),
ExpiresIn: int(utils.MustInterface2Int64(jsonResult1["expires_in"])),
}
}
if retVal != nil {
return platformapi.ErrLevelSuccess, nil
}
baseapi.SugarLogger.Warnf("response business code is not ok, data:%v, code:%v", jsonResult1, errInfo.ErrCode)
newErr := utils.NewErrorIntCode(errInfo.ErrMsg, errInfo.ErrCode)
if errInfo.ErrCode == ResponseCodeBusy {
return platformapi.ErrLevelRecoverableErr, newErr
}
return platformapi.ErrLevelCodeIsNotOK, newErr
})
return retVal, err
}
func (a *API) RefreshToken() (tokenInfo *TokenInfo, err error) {
result, err := a.AccessAPI("cgi-bin/token", utils.Params2Map("grant_type", "client_credential"))
if err != nil {
return nil, err
}
tokenInfo = result.(*TokenInfo)
// update my token too.
a.SetToken(tokenInfo.AccessToken)
return tokenInfo, nil
}