package youngee_talent_service import ( "bytes" "encoding/json" "errors" "fmt" "io/ioutil" "net/http" "strings" "youngmini_server/app/model/youngee_talent_model" "github.com/gogf/gf/encoding/gjson" "github.com/gogf/gf/frame/g" "github.com/gogf/gf/net/ghttp" ) const ( accessTokenUrlFormat = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s" qrCodeUrlFormat = "https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=%s" wxAccesssTokenKey = "wx_access_token" ) // getAndCacheWxAccessToken 获取并缓存微信的access token func getAndCacheWxAccessToken() (string, error) { appId := g.Config().GetString("miniapp.appid") secret := g.Config().GetString("miniapp.appsecret") url := fmt.Sprintf(accessTokenUrlFormat, appId, secret) resp, err := http.Get(url) if err != nil { return "", errors.New("request access token failed") } defer resp.Body.Close() // 解析微信服务端返回的信息 var accessTokenRes youngee_talent_model.WxAccessTokenResponse decoder := json.NewDecoder(resp.Body) if err = decoder.Decode(&accessTokenRes); err != nil { return "", errors.New("decode wx response failed") } if accessTokenRes.Errcode != 0 { return "", errors.New("request access token failed") } // 缓存获取的access token,比微信返回的有效时间短5分钟失效 _, err = g.Redis().Do("SETEX", wxAccesssTokenKey, accessTokenRes.ExpiresIn-300, accessTokenRes.AccessToken) return accessTokenRes.AccessToken, nil } func RequestShareInfo(r *ghttp.Request) *TalentHttpResult { var requestArg *youngee_talent_model.ShareRequest if err := r.ParseForm(&requestArg); err != nil { return &TalentHttpResult{Code: -1, Msg: "param error"} } // 获取access_token var accessToken string accessTokenVar, err := g.Redis().DoVar("GET", "wx_access_token") if err != nil { return &TalentHttpResult{Code: -2, Msg: "get access token from cache err"} } if accessTokenVar.IsEmpty() { // 如果没有缓存的access token 则获取并缓存 accessToken, err = getAndCacheWxAccessToken() } else { // 取缓存的access token accessToken = accessTokenVar.String() } qrRequest := youngee_talent_model.WxQrCodeRequest{ Scene: requestArg.Scene, Page: requestArg.Page, Width: 430, CheckPath: false, EnvVersion: "release", } jsonBody, err := gjson.Encode(qrRequest) if err != nil { return &TalentHttpResult{Code: -3, Msg: ""} } qrCodeUrl := fmt.Sprintf(qrCodeUrlFormat, accessToken) resp, err := http.Post(qrCodeUrl, "application/json; charset=utf8", bytes.NewReader(jsonBody)) if err != nil { return &TalentHttpResult{Code: -4, Msg: "request from wx server failed"} } defer resp.Body.Close() var qrcodeBytes []byte switch header := resp.Header.Get("content-Type"); { case strings.HasPrefix(header, "application/json"): // 如果返回的是json结构,说明发生错误 var qrResponse *youngee_talent_model.WxQrCodeResponse decoder := json.NewDecoder(resp.Body) if err = decoder.Decode(&qrResponse); err != nil { return &TalentHttpResult{Code: -5, Msg: "request qrcode failed"} } return &TalentHttpResult{Code: -6, Msg: "wx request error", Data: qrResponse} case strings.HasPrefix(header, "image"): qrcodeBytes, err = ioutil.ReadAll(resp.Body) if err != nil { return &TalentHttpResult{Code: -6, Msg: "read resp body error"} } } return &TalentHttpResult{Code: 0, Msg: "success", Data: qrcodeBytes} }