Skip to content

Commit ce33239

Browse files
committed
wxopen
1 parent eca5a21 commit ce33239

30 files changed

+4411
-67
lines changed

README.md

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ fmt.Println(string(resp),err)
3737

3838
- 小程序 [doc/apilist.md](doc/apilist.md)
3939
- 小游戏 [minigame/doc/apilist.md](minigame/doc/apilist.md)
40+
- 开放平台 [wxopen/doc/apilist.md](wxopen/doc/apilist.md)
4041

4142
## 架构设计
4243

@@ -69,9 +70,6 @@ fmt.Println(string(resp),err)
6970

7071
每个关键环节都为你完整记录,Debug 倍轻松,你可以自由定义日志输出,甚至可以关闭日志
7172

72-
### 多账号支持
73-
74-
一套服务支持多个账号,轻松成为第三方开发服务平台,业务节节高
7573

7674
### 支持服务集群
7775

client.go

Lines changed: 113 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,12 @@ import (
2727
"time"
2828
)
2929

30-
/*
31-
微信 api 服务器地址
32-
*/
33-
var WXServerUrl = "https://api.weixin.qq.com"
30+
var (
31+
WXServerUrl = "https://api.weixin.qq.com" // 微信 api 服务器地址
32+
UserAgent = "fastwego/miniprogram"
33+
ErrorAccessTokenExpire = errors.New("access token expire")
34+
ErrorSystemBusy = errors.New("system busy")
35+
)
3436

3537
/*
3638
HttpClient 用于向公众号接口发送请求
@@ -41,36 +43,104 @@ type Client struct {
4143

4244
// HTTPGet GET 请求
4345
func (client *Client) HTTPGet(uri string) (resp []byte, err error) {
44-
uri, err = client.applyAccessToken(uri)
46+
newUrl, err := client.applyAccessToken(uri)
4547
if err != nil {
4648
return
4749
}
48-
if client.Ctx.Logger != nil {
49-
client.Ctx.Logger.Printf("GET %s", uri)
50-
}
51-
response, err := http.Get(WXServerUrl + uri)
50+
51+
req, err := http.NewRequest(http.MethodGet, WXServerUrl+newUrl, nil)
5252
if err != nil {
5353
return
5454
}
55-
defer response.Body.Close()
56-
return responseFilter(response)
55+
56+
return client.httpDo(req)
5757
}
5858

5959
//HTTPPost POST 请求
6060
func (client *Client) HTTPPost(uri string, payload io.Reader, contentType string) (resp []byte, err error) {
61-
uri, err = client.applyAccessToken(uri)
61+
newUrl, err := client.applyAccessToken(uri)
6262
if err != nil {
6363
return
6464
}
65+
66+
req, err := http.NewRequest(http.MethodPost, WXServerUrl+newUrl, payload)
67+
if err != nil {
68+
return
69+
}
70+
71+
req.Header.Add("Content-Type", contentType)
72+
73+
return client.httpDo(req)
74+
}
75+
76+
//httpDo 执行 请求
77+
func (client *Client) httpDo(req *http.Request) (resp []byte, err error) {
78+
req.Header.Add("User-Agent", UserAgent)
79+
6580
if client.Ctx.Logger != nil {
66-
client.Ctx.Logger.Printf("POST %s", uri)
81+
client.Ctx.Logger.Printf("%s %s Headers %v", req.Method, req.URL.String(), req.Header)
6782
}
68-
response, err := http.Post(WXServerUrl+uri, contentType, payload)
83+
84+
response, err := http.DefaultClient.Do(req)
6985
if err != nil {
7086
return
7187
}
7288
defer response.Body.Close()
73-
return responseFilter(response)
89+
90+
resp, err = responseFilter(response)
91+
92+
// 发现 access_token 过期
93+
if err == ErrorAccessTokenExpire {
94+
95+
// 主动 通知 access_token 过期
96+
err = client.Ctx.AccessToken.NoticeAccessTokenExpireHandler(client.Ctx)
97+
if err != nil {
98+
return
99+
}
100+
101+
// 通知到位后 access_token 会被刷新,那么可以 retry 了
102+
var accessToken string
103+
accessToken, err = client.Ctx.AccessToken.GetAccessTokenHandler(client.Ctx)
104+
if err != nil {
105+
return
106+
}
107+
108+
// 换新
109+
q := req.URL.Query()
110+
q.Set("access_token", accessToken)
111+
req.URL.RawQuery = q.Encode()
112+
113+
if client.Ctx.Logger != nil {
114+
client.Ctx.Logger.Printf("%v retry %s %s Headers %v", ErrorAccessTokenExpire, req.Method, req.URL.String(), req.Header)
115+
}
116+
117+
response, err = http.DefaultClient.Do(req)
118+
if err != nil {
119+
return
120+
}
121+
defer response.Body.Close()
122+
123+
resp, err = responseFilter(response)
124+
}
125+
126+
// -1 系统繁忙,此时请开发者稍候再试
127+
// 重试一次
128+
if err == ErrorSystemBusy {
129+
130+
if client.Ctx.Logger != nil {
131+
client.Ctx.Logger.Printf("%v : retry %s %s Headers %v", ErrorSystemBusy, req.Method, req.URL.String(), req.Header)
132+
}
133+
134+
response, err = http.DefaultClient.Do(req)
135+
if err != nil {
136+
return
137+
}
138+
defer response.Body.Close()
139+
140+
resp, err = responseFilter(response)
141+
}
142+
143+
return
74144
}
75145

76146
/*
@@ -116,11 +186,23 @@ func responseFilter(response *http.Response) (resp []byte, err error) {
116186
return
117187
}
118188

189+
// 40001(覆盖刷新超过5min后,使用旧 access_token 报错) 获取 access_token 时 AppSecret 错误,或者 access_token 无效。请开发者认真比对 AppSecret 的正确性,或查看是否正在为恰当的公众号调用接口
190+
// 42001(超过 7200s 后 报错) - access_token 超时,请检查 access_token 的有效期,请参考基础支持 - 获取 access_token 中,对 access_token 的详细机制说明
191+
if errorResponse.Errcode == 42001 || errorResponse.Errcode == 40001 {
192+
err = ErrorAccessTokenExpire
193+
return
194+
}
195+
196+
// -1 系统繁忙,此时请开发者稍候再试
197+
if errorResponse.Errcode == -1 {
198+
err = ErrorSystemBusy
199+
return
200+
}
201+
119202
if errorResponse.Errcode != 0 {
120203
err = errors.New(string(resp))
121204
return
122205
}
123-
124206
return
125207
}
126208

@@ -148,17 +230,12 @@ func GetAccessToken(ctx *Miniprogram) (accessToken string, err error) {
148230
return
149231
}
150232

151-
if ctx.Logger != nil {
152-
ctx.Logger.Printf("refreshAccessTokenFromWXServer appid = %s secret = %s\n", ctx.Config.Appid, ctx.Config.Secret)
153-
}
154-
155233
accessToken, expiresIn, err := refreshAccessTokenFromWXServer(ctx.Config.Appid, ctx.Config.Secret)
156234
if err != nil {
157235
return
158236
}
159237

160-
// 提前过期 提供冗余时间
161-
expiresIn = int(0.9 * float64(expiresIn))
238+
// 本地缓存 access_token
162239
d := time.Duration(expiresIn) * time.Second
163240
_ = ctx.AccessToken.Cache.Save(ctx.Config.Appid, accessToken, d)
164241

@@ -169,6 +246,20 @@ func GetAccessToken(ctx *Miniprogram) (accessToken string, err error) {
169246
return
170247
}
171248

249+
/*
250+
NoticeAccessTokenExpire 只需将本地存储的 access_token 删除,即完成了 access_token 已过期的 主动通知
251+
252+
retry 请求的时候,会发现本地没有 access_token ,从而触发refresh
253+
*/
254+
func NoticeAccessTokenExpire(ctx *Miniprogram) (err error) {
255+
if ctx.Logger != nil {
256+
ctx.Logger.Println("NoticeAccessTokenExpire")
257+
}
258+
259+
err = ctx.AccessToken.Cache.Delete(ctx.Config.Appid)
260+
return
261+
}
262+
172263
/*
173264
从微信服务器获取新的 AccessToken
174265

0 commit comments

Comments
 (0)