package client import ( "encoding/json" "fmt" "io" "net/http" ) const ( UserAppID = "" UserSecret = "" DriverAppID = "" DriverSecret = "" Code2SessionAppURL = "https://api.weixin.qq.com/sns/oauth2/access_token" UserInfoAppURL = "https://api.weixin.qq.com/sns/userinfo" Code2SessionJsURL = "https://api.weixin.qq.com/sns/jscode2session" SendMessageURL = "https://api.weixin.qq.com/cgi-bin/message/subscribe/send?access_token=ACCESS_TOKEN" GetAccessTokenURL = "https://api.weixin.qq.com/cgi-bin/token" ) func WeChatNewAuthJsReqMap(code string) map[string]string { return map[string]string{ "appid": UserAppID, "secret": UserSecret, "js_code": code, "grant_type": "authorization_code"} } func WeChatNewAuthAppReqMap(code string) map[string]string { return map[string]string{ "appid": UserAppID, "secret": UserSecret, "code": code, "grant_type": "authorization_code"} } func WeChatGetAccessTokenReq(_type int) map[string]string { switch _type { case 1: // 用户 return map[string]string{ "grant_type": "client_credential", "appid": UserAppID, "secret": UserSecret, } case 2: // 其他 return map[string]string{ "grant_type": "client_credential", "appid": DriverAppID, "secret": DriverSecret, } } return nil } // 小程序换取token的返回 type WeChatLoginJsRes struct { SessionKey string `json:"session_key"` UnionID string `json:"unionid"` OpenID string `json:"openid"` ErrCode int32 `json:"errcode"` ErrMsg string `json:"errmsg"` } // APP换取token的返回 type WeChatLoginAppRes struct { AccessToken string `json:"access_token"` // 接口调用凭证 ExpiresIn int32 `json:"expires_in"` // access_token 接口调用凭证超时时间,单位(秒) RefreshToken string `json:"refresh_token"` // 用户刷新 access_token UnionID string `json:"unionid"` // 用户统一标识。针对一个微信开放平台账号下的应用,同一用户的 unionid 是唯一的 OpenID string `json:"openid"` // 授权用户唯一标识 Scope string `json:"scope"` // 用户授权的作用域,使用逗号(,)分隔 ErrCode int32 `json:"errcode"` ErrMsg string `json:"errmsg"` } // APP获取用户信息 type WeChatUserInfoAppRes struct { UnionID string `json:"unionid"` // 用户统一标识。针对一个微信开放平台账号下的应用,同一用户的 unionid 是唯一的 OpenID string `json:"openid"` // 授权用户唯一标识 Nickname string `json:"nickname"` // 普通用户昵称 Sex int32 `json:"sex"` // 普通用户性别,1 为男性,2 为女性 Province string `json:"province"` // 普通用户个人资料填写的省份 City string `json:"city"` // 普通用户个人资料填写的城市 Country string `json:"country"` // 国家,如中国为 CN Avatar string `json:"headimgurl"` // 用户头像,最后一个数值代表正方形头像大小(有 0、46、64、96、132 数值可选,0 代表 640*640 正方形头像),用户没有头像时该项为空 ErrCode int32 `json:"errcode"` ErrMsg string `json:"errmsg"` } // 换取token所用的请求 func WeChatNewAuthReqMapUser(code string) map[string]string { return map[string]string{ "appid": UserAppID, "secret": UserSecret, "js_code": code, "grant_type": "authorization_code"} } // 小程序换取token的请求 func WeChatCode2JsSession(headers map[string]string, params map[string]string) (wxLoginBody WeChatLoginJsRes, e error) { var ( client = NewClient() resp *http.Response res []byte ) req, _ := http.NewRequest(http.MethodGet, Code2SessionJsURL, nil) for k, v := range headers { req.Header.Add(k, v) } q := req.URL.Query() for k, v := range params { q.Add(k, v) } req.URL.RawQuery = q.Encode() if resp, e = client.Do(req); e != nil { return } defer func(body io.ReadCloser) { _ = body.Close() }(resp.Body) if res, e = io.ReadAll(resp.Body); e != nil { return } if !success(resp.StatusCode) { e = fmt.Errorf("status code error: %s", resp.Status) } if e = json.Unmarshal(res, &wxLoginBody); e != nil { return } if wxLoginBody.ErrCode != 0 { e = fmt.Errorf("获取微信登录凭证错误,错误码: %d 错误信息:%s", wxLoginBody.ErrCode, wxLoginBody.ErrMsg) return } return } // APP换取token的请求 func WeChatCode2AppToken(headers map[string]string, params map[string]string) (wxLoginBody WeChatLoginAppRes, e error) { var ( client = NewClient() resp *http.Response res []byte ) req, _ := http.NewRequest(http.MethodGet, Code2SessionAppURL, nil) for k, v := range headers { req.Header.Add(k, v) } q := req.URL.Query() for k, v := range params { q.Add(k, v) } req.URL.RawQuery = q.Encode() if resp, e = client.Do(req); e != nil { return } defer func(body io.ReadCloser) { _ = body.Close() }(resp.Body) if res, e = io.ReadAll(resp.Body); e != nil { return } if !success(resp.StatusCode) { e = fmt.Errorf("status code error: %s", resp.Status) } if e = json.Unmarshal(res, &wxLoginBody); e != nil { return } if wxLoginBody.ErrCode != 0 { e = fmt.Errorf("获取微信登录凭证错误,错误码: %d 错误信息:%s", wxLoginBody.ErrCode, wxLoginBody.ErrMsg) return } return } // APP获取用户信息 func WeChatUserInfoApp(token, openId string) (wxUserInfoBody WeChatUserInfoAppRes, e error) { var ( client = NewClient() resp *http.Response res []byte ) req, _ := http.NewRequest(http.MethodGet, UserInfoAppURL, nil) q := req.URL.Query() q.Add("access_token", token) q.Add("openid", openId) req.URL.RawQuery = q.Encode() if resp, e = client.Do(req); e != nil { return } defer func(body io.ReadCloser) { _ = body.Close() }(resp.Body) if res, e = io.ReadAll(resp.Body); e != nil { return } if !success(resp.StatusCode) { e = fmt.Errorf("status code error: %s", resp.Status) } if e = json.Unmarshal(res, &wxUserInfoBody); e != nil { return } if wxUserInfoBody.ErrCode != 0 { e = fmt.Errorf("获取微信登录凭证错误,错误码: %d 错误信息:%s", wxUserInfoBody.ErrCode, wxUserInfoBody.ErrMsg) return } return } func success(code int) bool { return code >= 200 && code < 400 }