package JD import ( "crypto/hmac" "crypto/sha256" "encoding/hex" "encoding/json" "fmt" "github.com/gogf/gf/util/gconv" "github.com/gomodule/redigo/redis" "github.com/guonaihong/gout" "github.com/syyongx/php2go" "golang_open_platform/pkg/gredis" "strconv" "time" ) type JdRequest struct { GrantType interface{}`json:"grantType"` AppKey interface{} `json:"appKey"` UserName interface{} `json:"userName"` Password interface{} `json:"password"` RequestTime interface{} `json:"requestTime"` Sign interface{} `json:"sign"` Scope interface{} `json:"scope"` } type AccessTokenData struct { AccessToken string `json:"accessToken"` Time int64 `json:"time"` ExpiresIn int64 `json:"expires_in"` RefreshTokenExpires int64 `json:"RefreshTokenExpires` } type Token struct { } func (this *Token) getKoken() string { //return "E9E647D9DEEF17B1770C02153D8A4DCA" token:=this.getTokenCache() if(token!=""){ return token } return this.getRealToken() } //获取真实token func (this *Token)getRealToken() string { requestTime:=strconv.FormatInt(time.Now().UnixNano()/1e6, 10) jdRes:=JdRes{} jdRequest:=JdRequest{} jdRequest.GrantType="accessToken" jdRequest.AppKey=Appkey jdRequest.UserName=UserName jdRequest.Password=php2go.Strtoupper(php2go.Md5(php2go.Base64Encode(Password+requestTime))) jdRequest.RequestTime=requestTime jdRequest.Sign=this.getSignString(jdRequest) jdRequest.Scope="" err:=gout.POST(GetTokenUrl).Debug(true).SetForm(jdRequest).BindJSON(&jdRes).Do() if(err!=nil){ panic(err.Error()) } if(jdRes.Success==false){ msg:=fmt.Sprintf("code:%v,msg:%v",jdRes.ResponseCode,jdRes.ResponseMessage) panic(msg) } if tokenDataMap,ok:= jdRes.ResponseData.(map[string]interface{});ok{ this.setTokenCache(tokenDataMap)//存token return gconv.String(tokenDataMap["accessToken"])//返回token }else{ panic("responseData 不符合格式 ") } } //设置缓存token func (this *Token) setTokenCache(tokenMapData map[string]interface{}) { redisWriteConn := gredis.Conn("search_w") defer redisWriteConn.Close() tokenMapData["realExpires"]=gconv.Int64(tokenMapData["expiresIn"])+gconv.Int64(tokenMapData["time"])*1000//毫秒 bytes,err:=json.Marshal(tokenMapData) if(err!=nil){ RecordErrLog("设置缓存token,json.Marshal 报错,err:"+err.Error()) panic("") } _,err=redisWriteConn.Do("Set",jd_client_token_redis_key,string(bytes)) if(err!=nil){ RecordErrLog("设置缓存token,redis SET 报错,err:"+err.Error()) panic("") } } /** 1.先从redis读出token的数据(map) 2.后通过过期时间验证是否过期(或者是否离过期还有一个小时),如果是,返回空 3.如果不是,返回token */ func (this *Token) getTokenCache() string { redisReadConn := gredis.Conn("search_r") defer redisReadConn.Close() bytes,err:=redis.Bytes(redisReadConn.Do("GET",jd_client_token_redis_key)) if(err!=nil && err!=redis.ErrNil){ RecordErrLog("获取缓存token,redis GET 报错,err:"+err.Error()) panic("") } if(err==redis.ErrNil||bytes==nil){ return "" } tokenInfo:=make(map[string]interface{}) err=json.Unmarshal(bytes,&tokenInfo) if(err!=nil){ RecordErrLog(jdserver_err,"获取缓存token,json数据有误,err:"+err.Error()+"json:"+string(bytes)) panic(nil) } timeNow:=time.Now().Unix()*1000 realExpires:=gconv.Int64(tokenInfo["realExpires"]) s:=int64(55*60*1000) if(realExpires-timeNow<=s){//距离过期小于等于55分钟就重新获取 return this.getRealToken() }else{ return gconv.String(tokenInfo["accessToken"]) } } /** 签名加密 按照以下顺序将字符串拼接起来 appKey + userName + password + requestTime + grantType+ secretKey 将上述拼接的字符串使用 HMACSHA256 加密, */ func (this *Token) getSignString(jdRequest JdRequest) string{ str:=gconv.String(jdRequest.AppKey)+gconv.String(jdRequest.UserName)+gconv.String(jdRequest.Password) str=str+gconv.String(jdRequest.RequestTime)+gconv.String(jdRequest.GrantType)+gconv.String(secretKey) hmac:=hmac.New(sha256.New,gconv.Bytes(secretKey)) hmac.Write([]byte(str)) return hex.EncodeToString(hmac.Sum([]byte(""))) }