Files
servicebase/pkg/client/wechat_client.go
2025-11-18 17:48:20 +08:00

216 lines
6.2 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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
}