package weixinapi import ( "net/http" "strings" "sync" "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 msgToken string msgKey string } type SNSTokenInfo struct { AccessToken string `json:"access_token"` ExpiresIn int `json:"expires_in"` RefreshToken string `json:"refresh_token"` OpenID string `json:"openid"` Scope string `json:"scope"` } type SNSUserInfo struct { OpenID string `json:"openid"` NickName string `json:"nickname"` Sex int `json:"sex"` Province string `json:"province"` City string `json:"city"` Country string `json:"country"` HeadImgURL string `json:"headimgurl"` Privilege interface{} `json:"privilege"` UnionID string `json:"unionid"` } type SessionInfo struct { OpenID string `json:"openid"` SessionKey string `json:"session_key"` UnionID string `json:"unionid"` } 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) GetAppID() string { return a.appID } func (a *API) GetSecret() string { return a.secret } func isSNSAction(action string) bool { return strings.Index(action, "sns/") == 0 } func (a *API) AccessAPI(action string, params map[string]interface{}, body string) (retVal map[string]interface{}, err error) { if params != nil && body != "" { panic("params and body can not all be empty") } params2 := make(map[string]interface{}) for k, v := range params { params2[k] = v } if params2["grant_type"] != nil { params2["appid"] = a.appID params2["secret"] = a.secret } else if !isSNSAction(action) { accessToken := a.CBGetToken() if accessToken == "" { panic("token is empty!") } params2["access_token"] = accessToken } fullURL := utils.GenerateGetURL(prodURL, action, params2) // baseapi.SugarLogger.Debug(fullURL) err = platformapi.AccessPlatformAPIWithRetry(a.client, func() *http.Request { var request *http.Request if body == "" { request, _ = http.NewRequest(http.MethodGet, fullURL, nil) } else { request, _ = http.NewRequest(http.MethodPost, fullURL, strings.NewReader(body)) } request.Close = true // todo try to fix EOF error when accessing weixin api. return request }, a.config, func(jsonResult1 map[string]interface{}) (result string, err error) { var errInfo *ErrorInfo // 微信的返回值,在错误与正常情况下,结构是完全不一样的 if errCode, ok := jsonResult1["errcode"]; ok { errInfo = &ErrorInfo{ ErrCode: int(utils.MustInterface2Int64(errCode)), ErrMsg: jsonResult1["errmsg"].(string), } if errInfo.ErrCode == 0 { retVal = jsonResult1 } } else { retVal = jsonResult1 } if retVal != nil { return platformapi.ErrLevelSuccess, nil } newErr := utils.NewErrorIntCode(errInfo.ErrMsg, errInfo.ErrCode) if errInfo.ErrCode == ResponseCodeBusy { return platformapi.ErrLevelRecoverableErr, newErr } return platformapi.ErrLevelCodeIsNotOK, newErr }) return retVal, err }