Skip to content

Commit 87e4bdb

Browse files
committed
Merge remote-tracking branch 'upstream/v2' into v2
# Conflicts: # credential/default_access_token.go
2 parents 4b412ef + 71c8ab5 commit 87e4bdb

File tree

8 files changed

+98
-22
lines changed

8 files changed

+98
-22
lines changed

credential/access_token.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,16 @@ type AccessTokenHandle interface {
77
GetAccessToken() (accessToken string, err error)
88
}
99

10+
// AccessTokenCompatibleHandle 同时实现 AccessTokenHandle 和 AccessTokenContextHandle
11+
type AccessTokenCompatibleHandle struct {
12+
AccessTokenHandle
13+
}
14+
15+
// GetAccessTokenContext 获取access_token,先从cache中获取,没有则从服务端获取
16+
func (c AccessTokenCompatibleHandle) GetAccessTokenContext(_ context.Context) (accessToken string, err error) {
17+
return c.GetAccessToken()
18+
}
19+
1020
// AccessTokenContextHandle AccessToken 接口
1121
type AccessTokenContextHandle interface {
1222
AccessTokenHandle

credential/default_access_token.go

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -195,15 +195,21 @@ type WorkAccessToken struct {
195195
accessTokenLock *sync.Mutex
196196
}
197197

198-
// NewWorkAccessToken new WorkAccessToken
198+
// NewWorkAccessToken new WorkAccessToken (保持向后兼容)
199199
func NewWorkAccessToken(corpID, corpSecret, agentID, cacheKeyPrefix string, cache cache.Cache) AccessTokenContextHandle {
200+
// 调用新方法,保持兼容性
201+
return NewWorkAccessTokenWithAgentID(corpID, corpSecret, agentID, cacheKeyPrefix, cache)
202+
}
203+
204+
// NewWorkAccessTokenWithAgentID new WorkAccessToken with agentID
205+
func NewWorkAccessTokenWithAgentID(corpID, corpSecret, agentID, cacheKeyPrefix string, cache cache.Cache) AccessTokenContextHandle {
200206
if cache == nil {
201-
panic("cache the not exist")
207+
panic("cache is needed")
202208
}
203209
return &WorkAccessToken{
204210
CorpID: corpID,
205211
CorpSecret: corpSecret,
206-
AgentID: agentID, // agentID可以为空,兼容历史版本
212+
AgentID: agentID,
207213
cache: cache,
208214
cacheKeyPrefix: cacheKeyPrefix,
209215
accessTokenLock: new(sync.Mutex),
@@ -223,8 +229,6 @@ func (ak *WorkAccessToken) GetAccessTokenContext(ctx context.Context) (accessTok
223229

224230
// 构建缓存key
225231
var accessTokenCacheKey string
226-
// 每个应用有独立的secret,获取到的access_token只能本应用使用,所以每个应用的access_token应该分开来获取
227-
// API文档:https://developer.work.weixin.qq.com/document/path/91039
228232
if ak.AgentID != "" {
229233
// 如果设置了AgentID,使用新的key格式
230234
accessTokenCacheKey = fmt.Sprintf("%s_access_token_%s_%s", ak.cacheKeyPrefix, ak.CorpID, ak.AgentID)
@@ -248,6 +252,9 @@ func (ak *WorkAccessToken) GetAccessTokenContext(ctx context.Context) (accessTok
248252

249253
expires := resAccessToken.ExpiresIn - 1500
250254
err = ak.cache.Set(accessTokenCacheKey, resAccessToken.AccessToken, time.Duration(expires)*time.Second)
255+
if err != nil {
256+
return
257+
}
251258

252259
accessToken = resAccessToken.AccessToken
253260
return

miniprogram/business/phone_number.go

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package business
22

33
import (
4+
"context"
45
"fmt"
56

67
"github.com/silenceper/wechat/v2/util"
@@ -28,13 +29,18 @@ type PhoneInfo struct {
2829

2930
// GetPhoneNumber code换取用户手机号。 每个code只能使用一次,code的有效期为5min
3031
func (business *Business) GetPhoneNumber(in *GetPhoneNumberRequest) (info PhoneInfo, err error) {
31-
accessToken, err := business.GetAccessToken()
32+
return business.GetPhoneNumberWithContext(context.Background(), in)
33+
}
34+
35+
// GetPhoneNumberWithContext 利用context将code换取用户手机号。 每个code只能使用一次,code的有效期为5min
36+
func (business *Business) GetPhoneNumberWithContext(ctx context.Context, in *GetPhoneNumberRequest) (info PhoneInfo, err error) {
37+
accessToken, err := business.GetAccessTokenContext(ctx)
3238
if err != nil {
3339
return
3440
}
3541

3642
uri := fmt.Sprintf(getPhoneNumberURL, accessToken)
37-
response, err := util.PostJSON(uri, in)
43+
response, err := util.PostJSONContext(ctx, uri, in)
3844
if err != nil {
3945
return
4046
}

miniprogram/context/context.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,5 @@ import (
88
// Context struct
99
type Context struct {
1010
*config.Config
11-
credential.AccessTokenHandle
11+
credential.AccessTokenContextHandle
1212
}

miniprogram/miniprogram.go

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,15 +42,22 @@ func NewMiniProgram(cfg *config.Config) *MiniProgram {
4242
defaultAkHandle = credential.NewDefaultAccessToken(cfg.AppID, cfg.AppSecret, cacheKeyPrefix, cfg.Cache)
4343
}
4444
ctx := &context.Context{
45-
Config: cfg,
46-
AccessTokenHandle: defaultAkHandle,
45+
Config: cfg,
46+
AccessTokenContextHandle: defaultAkHandle,
4747
}
4848
return &MiniProgram{ctx}
4949
}
5050

5151
// SetAccessTokenHandle 自定义 access_token 获取方式
5252
func (miniProgram *MiniProgram) SetAccessTokenHandle(accessTokenHandle credential.AccessTokenHandle) {
53-
miniProgram.ctx.AccessTokenHandle = accessTokenHandle
53+
miniProgram.ctx.AccessTokenContextHandle = credential.AccessTokenCompatibleHandle{
54+
AccessTokenHandle: accessTokenHandle,
55+
}
56+
}
57+
58+
// SetAccessTokenContextHandle 自定义 access_token 获取方式
59+
func (miniProgram *MiniProgram) SetAccessTokenContextHandle(accessTokenContextHandle credential.AccessTokenContextHandle) {
60+
miniProgram.ctx.AccessTokenContextHandle = accessTokenContextHandle
5461
}
5562

5663
// GetContext get Context

openplatform/miniprogram/miniprogram.go

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package miniprogram
22

33
import (
4+
originalContext "context"
45
"fmt"
56

67
"github.com/silenceper/wechat/v2/credential"
@@ -37,6 +38,22 @@ func (miniProgram *MiniProgram) GetAccessToken() (string, error) {
3738
return akRes.AccessToken, nil
3839
}
3940

41+
// GetAccessTokenContext 利用ctx获取ak
42+
func (miniProgram *MiniProgram) GetAccessTokenContext(ctx originalContext.Context) (string, error) {
43+
ak, akErr := miniProgram.openContext.GetAuthrAccessTokenContext(ctx, miniProgram.AppID)
44+
if akErr == nil {
45+
return ak, nil
46+
}
47+
if miniProgram.authorizerRefreshToken == "" {
48+
return "", fmt.Errorf("please set the authorizer_refresh_token first")
49+
}
50+
akRes, akResErr := miniProgram.GetComponent().RefreshAuthrTokenContext(ctx, miniProgram.AppID, miniProgram.authorizerRefreshToken)
51+
if akResErr != nil {
52+
return "", akResErr
53+
}
54+
return akRes.AccessToken, nil
55+
}
56+
4057
// SetAuthorizerRefreshToken 设置代执操作业务授权账号authorizer_refresh_token
4158
func (miniProgram *MiniProgram) SetAuthorizerRefreshToken(authorizerRefreshToken string) *MiniProgram {
4259
miniProgram.authorizerRefreshToken = authorizerRefreshToken
@@ -68,7 +85,7 @@ func (miniProgram *MiniProgram) GetBasic() *basic.Basic {
6885
// GetURLLink 小程序URL Link接口 调用前需确认已调用 SetAuthorizerRefreshToken 避免由于缓存中 authorizer_access_token 过期执行中断
6986
func (miniProgram *MiniProgram) GetURLLink() *urllink.URLLink {
7087
return urllink.NewURLLink(&miniContext.Context{
71-
AccessTokenHandle: miniProgram,
88+
AccessTokenContextHandle: miniProgram,
7289
})
7390
}
7491

work/config/config.go

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,11 @@ import (
77

88
// Config for 企业微信
99
type Config struct {
10-
CorpID string `json:"corp_id"` // corp_id
11-
CorpSecret string `json:"corp_secret"` // corp_secret,如果需要获取会话存档实例,当前参数请填写聊天内容存档的Secret,可以在企业微信管理端--管理工具--聊天内容存档查看
12-
AgentID string `json:"agent_id"` // agent_id
13-
Cache cache.Cache
14-
RasPrivateKey string // 消息加密私钥,可以在企业微信管理端--管理工具--消息加密公钥查看对用公钥,私钥一般由自己保存
15-
10+
CorpID string `json:"corp_id"` // corp_id
11+
CorpSecret string `json:"corp_secret"` // corp_secret,如果需要获取会话存档实例,当前参数请填写聊天内容存档的Secret,可以在企业微信管理端--管理工具--聊天内容存档查看
12+
AgentID string `json:"agent_id"` // agent_id
13+
Cache cache.Cache
14+
RasPrivateKey string // 消息加密私钥,可以在企业微信管理端--管理工具--消息加密公钥查看对用公钥,私钥一般由自己保存
1615
Token string `json:"token"` // 微信客服回调配置,用于生成签名校验回调请求的合法性
1716
EncodingAESKey string `json:"encoding_aes_key"` // 微信客服回调p配置,用于解密回调消息内容对应的密文
1817
}

work/kf/account.go

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ type AccountAddSchema struct {
3333
}
3434

3535
// AccountAdd 添加客服账号
36+
// see https://developer.work.weixin.qq.com/document/path/94662
3637
func (r *Client) AccountAdd(options AccountAddOptions) (info AccountAddSchema, err error) {
3738
var (
3839
accessToken string
@@ -59,6 +60,7 @@ type AccountDelOptions struct {
5960
}
6061

6162
// AccountDel 删除客服账号
63+
// see https://developer.work.weixin.qq.com/document/path/94663
6264
func (r *Client) AccountDel(options AccountDelOptions) (info util.CommonError, err error) {
6365
var (
6466
accessToken string
@@ -86,7 +88,8 @@ type AccountUpdateOptions struct {
8688
MediaID string `json:"media_id"` // 客服头像临时素材。可以调用上传临时素材接口获取, 不多于128个字节
8789
}
8890

89-
// AccountUpdate 修复客服账号
91+
// AccountUpdate 修改客服账号
92+
// see https://developer.work.weixin.qq.com/document/path/94664
9093
func (r *Client) AccountUpdate(options AccountUpdateOptions) (info util.CommonError, err error) {
9194
var (
9295
accessToken string
@@ -109,9 +112,10 @@ func (r *Client) AccountUpdate(options AccountUpdateOptions) (info util.CommonEr
109112

110113
// AccountInfoSchema 客服详情
111114
type AccountInfoSchema struct {
112-
OpenKFID string `json:"open_kfid"` // 客服帐号ID
113-
Name string `json:"name"` // 客服帐号名称
114-
Avatar string `json:"avatar"` // 客服头像URL
115+
OpenKFID string `json:"open_kfid"` // 客服帐号ID
116+
Name string `json:"name"` // 客服帐号名称
117+
Avatar string `json:"avatar"` // 客服头像URL
118+
ManagePrivilege bool `json:"manage_privilege"` // 当前调用接口的应用身份,是否有该客服账号的管理权限(编辑客服账号信息、分配会话和收发消息)
115119
}
116120

117121
// AccountListSchema 获取客服账号列表响应内容
@@ -141,6 +145,31 @@ func (r *Client) AccountList() (info AccountListSchema, err error) {
141145
return info, nil
142146
}
143147

148+
// AccountPagingRequest 分页获取客服账号列表请求
149+
type AccountPagingRequest struct {
150+
Offset int `json:"offset"`
151+
Limit int `json:"limit"`
152+
}
153+
154+
// AccountPaging 分页获取客服账号列表
155+
// see https://developer.work.weixin.qq.com/document/path/94661
156+
func (r *Client) AccountPaging(req *AccountPagingRequest) (*AccountListSchema, error) {
157+
var (
158+
accessToken string
159+
err error
160+
)
161+
if accessToken, err = r.ctx.GetAccessToken(); err != nil {
162+
return nil, err
163+
}
164+
var response []byte
165+
if response, err = util.PostJSON(fmt.Sprintf(accountListAddr, accessToken), req); err != nil {
166+
return nil, err
167+
}
168+
result := &AccountListSchema{}
169+
err = util.DecodeWithError(response, result, "AccountPaging")
170+
return result, err
171+
}
172+
144173
// AddContactWayOptions 获取客服账号链接
145174
// 1.若scene非空,返回的客服链接开发者可拼接scene_param=SCENE_PARAM参数使用,用户进入会话事件会将SCENE_PARAM原样返回。其中SCENE_PARAM需要urlencode,且长度不能超过128字节。
146175
// 如 https://work.weixin.qq.com/kf/kfcbf8f8d07ac7215f?enc_scene=ENCGFSDF567DF&scene_param=a%3D1%26b%3D2
@@ -158,6 +187,7 @@ type AddContactWaySchema struct {
158187
}
159188

160189
// AddContactWay 获取客服账号链接
190+
// see https://developer.work.weixin.qq.com/document/path/94665
161191
func (r *Client) AddContactWay(options AddContactWayOptions) (info AddContactWaySchema, err error) {
162192
var (
163193
accessToken string

0 commit comments

Comments
 (0)