Skip to content

Commit cdf8b28

Browse files
authored
Merge branch 'v2' into kf-update
2 parents a5776bc + 3bd886d commit cdf8b28

File tree

10 files changed

+229
-15
lines changed

10 files changed

+229
-15
lines changed

Diff for: credential/default_access_token.go

+24-9
Original file line numberDiff line numberDiff line change
@@ -101,10 +101,11 @@ func (ak *DefaultAccessToken) GetAccessTokenContext(ctx context.Context) (access
101101
// 不强制更新access_token,可用于不同环境不同服务而不需要分布式锁以及公用缓存,避免access_token争抢
102102
// https://developers.weixin.qq.com/miniprogram/dev/OpenApiDoc/mp-access-token/getStableAccessToken.html
103103
type StableAccessToken struct {
104-
appID string
105-
appSecret string
106-
cacheKeyPrefix string
107-
cache cache.Cache
104+
appID string
105+
appSecret string
106+
cacheKeyPrefix string
107+
cache cache.Cache
108+
accessTokenLock *sync.Mutex
108109
}
109110

110111
// NewStableAccessToken new StableAccessToken
@@ -113,10 +114,11 @@ func NewStableAccessToken(appID, appSecret, cacheKeyPrefix string, cache cache.C
113114
panic("cache is need")
114115
}
115116
return &StableAccessToken{
116-
appID: appID,
117-
appSecret: appSecret,
118-
cache: cache,
119-
cacheKeyPrefix: cacheKeyPrefix,
117+
appID: appID,
118+
appSecret: appSecret,
119+
cache: cache,
120+
cacheKeyPrefix: cacheKeyPrefix,
121+
accessTokenLock: new(sync.Mutex),
120122
}
121123
}
122124

@@ -130,7 +132,20 @@ func (ak *StableAccessToken) GetAccessTokenContext(ctx context.Context) (accessT
130132
// 先从cache中取
131133
accessTokenCacheKey := fmt.Sprintf("%s_stable_access_token_%s", ak.cacheKeyPrefix, ak.appID)
132134
if val := ak.cache.Get(accessTokenCacheKey); val != nil {
133-
return val.(string), nil
135+
if accessToken = val.(string); accessToken != "" {
136+
return
137+
}
138+
}
139+
140+
// 加上lock,是为了防止在并发获取token时,cache刚好失效,导致从微信服务器上获取到不同token
141+
ak.accessTokenLock.Lock()
142+
defer ak.accessTokenLock.Unlock()
143+
144+
// 双检,防止重复从微信服务器获取
145+
if val := ak.cache.Get(accessTokenCacheKey); val != nil {
146+
if accessToken = val.(string); accessToken != "" {
147+
return
148+
}
134149
}
135150

136151
// cache失效,从微信服务器获取

Diff for: miniprogram/config/config.go

+1
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,5 @@ type Config struct {
1414
Token string `json:"token"` // token
1515
EncodingAESKey string `json:"encoding_aes_key"` // EncodingAESKey
1616
Cache cache.Cache
17+
UseStableAK bool // use the stable access_token
1718
}

Diff for: miniprogram/miniprogram.go

+7-1
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,13 @@ type MiniProgram struct {
3434

3535
// NewMiniProgram 实例化小程序 API
3636
func NewMiniProgram(cfg *config.Config) *MiniProgram {
37-
defaultAkHandle := credential.NewDefaultAccessToken(cfg.AppID, cfg.AppSecret, credential.CacheKeyMiniProgramPrefix, cfg.Cache)
37+
var defaultAkHandle credential.AccessTokenContextHandle
38+
const cacheKeyPrefix = credential.CacheKeyMiniProgramPrefix
39+
if cfg.UseStableAK {
40+
defaultAkHandle = credential.NewStableAccessToken(cfg.AppID, cfg.AppSecret, cacheKeyPrefix, cfg.Cache)
41+
} else {
42+
defaultAkHandle = credential.NewDefaultAccessToken(cfg.AppID, cfg.AppSecret, cacheKeyPrefix, cfg.Cache)
43+
}
3844
ctx := &context.Context{
3945
Config: cfg,
4046
AccessTokenHandle: defaultAkHandle,

Diff for: miniprogram/subscribe/subscribe.go

+35
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package subscribe
22

33
import (
4+
"encoding/json"
45
"fmt"
56

67
"github.com/silenceper/wechat/v2/miniprogram/context"
@@ -70,6 +71,13 @@ type TemplateList struct {
7071
Data []TemplateItem `json:"data"`
7172
}
7273

74+
// resTemplateSend 发送获取 msg id
75+
type resTemplateSend struct {
76+
util.CommonError
77+
78+
MsgID int64 `json:"msgid"`
79+
}
80+
7381
// Send 发送订阅消息
7482
func (s *Subscribe) Send(msg *Message) (err error) {
7583
var accessToken string
@@ -85,6 +93,33 @@ func (s *Subscribe) Send(msg *Message) (err error) {
8593
return util.DecodeWithCommonError(response, "Send")
8694
}
8795

96+
// SendGetMsgID 发送订阅消息返回 msgid
97+
func (s *Subscribe) SendGetMsgID(msg *Message) (msgID int64, err error) {
98+
var accessToken string
99+
accessToken, err = s.GetAccessToken()
100+
if err != nil {
101+
return
102+
}
103+
uri := fmt.Sprintf("%s?access_token=%s", subscribeSendURL, accessToken)
104+
response, err := util.PostJSON(uri, msg)
105+
if err != nil {
106+
return
107+
}
108+
109+
var result resTemplateSend
110+
if err = json.Unmarshal(response, &result); err != nil {
111+
return
112+
}
113+
if result.ErrCode != 0 {
114+
err = fmt.Errorf("template msg send error : errcode=%v , errmsg=%v", result.ErrCode, result.ErrMsg)
115+
return
116+
}
117+
118+
msgID = result.MsgID
119+
120+
return
121+
}
122+
88123
// ListTemplates 获取当前帐号下的个人模板列表
89124
// https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/subscribe-message/subscribeMessage.getTemplateList.html
90125
func (s *Subscribe) ListTemplates() (*TemplateList, error) {

Diff for: officialaccount/config/config.go

+1
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,5 @@ type Config struct {
1111
Token string `json:"token"` // token
1212
EncodingAESKey string `json:"encoding_aes_key"` // EncodingAESKey
1313
Cache cache.Cache
14+
UseStableAK bool // use the stable access_token
1415
}

Diff for: officialaccount/officialaccount.go

+7-1
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,13 @@ type OfficialAccount struct {
4949

5050
// NewOfficialAccount 实例化公众号API
5151
func NewOfficialAccount(cfg *config.Config) *OfficialAccount {
52-
defaultAkHandle := credential.NewDefaultAccessToken(cfg.AppID, cfg.AppSecret, credential.CacheKeyOfficialAccountPrefix, cfg.Cache)
52+
var defaultAkHandle credential.AccessTokenContextHandle
53+
const cacheKeyPrefix = credential.CacheKeyOfficialAccountPrefix
54+
if cfg.UseStableAK {
55+
defaultAkHandle = credential.NewStableAccessToken(cfg.AppID, cfg.AppSecret, cacheKeyPrefix, cfg.Cache)
56+
} else {
57+
defaultAkHandle = credential.NewDefaultAccessToken(cfg.AppID, cfg.AppSecret, cacheKeyPrefix, cfg.Cache)
58+
}
5359
ctx := &context.Context{
5460
Config: cfg,
5561
AccessTokenHandle: defaultAkHandle,

Diff for: work/addresslist/department.go

+48-1
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,16 @@ import (
99
const (
1010
// departmentCreateURL 创建部门
1111
departmentCreateURL = "https://qyapi.weixin.qq.com/cgi-bin/department/create?access_token=%s"
12+
// departmentUpdateURL 更新部门
13+
departmentUpdateURL = "https://qyapi.weixin.qq.com/cgi-bin/department/update?access_token=%s"
14+
// departmentDeleteURL 删除部门
15+
departmentDeleteURL = "https://qyapi.weixin.qq.com/cgi-bin/department/delete?access_token=%s&id=%d"
1216
// departmentSimpleListURL 获取子部门ID列表
1317
departmentSimpleListURL = "https://qyapi.weixin.qq.com/cgi-bin/department/simplelist?access_token=%s&id=%d"
1418
// departmentListURL 获取部门列表
1519
departmentListURL = "https://qyapi.weixin.qq.com/cgi-bin/department/list?access_token=%s"
1620
departmentListByIDURL = "https://qyapi.weixin.qq.com/cgi-bin/department/list?access_token=%s&id=%d"
17-
// departmentGetURL 获取单个部门详情 https://qyapi.weixin.qq.com/cgi-bin/department/get?access_token=ACCESS_TOKEN&id=ID
21+
// departmentGetURL 获取单个部门详情
1822
departmentGetURL = "https://qyapi.weixin.qq.com/cgi-bin/department/get?access_token=%s&id=%d"
1923
)
2024

@@ -85,6 +89,49 @@ func (r *Client) DepartmentCreate(req *DepartmentCreateRequest) (*DepartmentCrea
8589
return result, err
8690
}
8791

92+
// DepartmentUpdateRequest 更新部门请求
93+
type DepartmentUpdateRequest struct {
94+
ID int `json:"id"`
95+
Name string `json:"name,omitempty"`
96+
NameEn string `json:"name_en,omitempty"`
97+
ParentID int `json:"parentid,omitempty"`
98+
Order int `json:"order,omitempty"`
99+
}
100+
101+
// DepartmentUpdate 更新部门
102+
// see https://developer.work.weixin.qq.com/document/path/90206
103+
func (r *Client) DepartmentUpdate(req *DepartmentUpdateRequest) error {
104+
var (
105+
accessToken string
106+
err error
107+
)
108+
if accessToken, err = r.GetAccessToken(); err != nil {
109+
return err
110+
}
111+
var response []byte
112+
if response, err = util.PostJSON(fmt.Sprintf(departmentUpdateURL, accessToken), req); err != nil {
113+
return err
114+
}
115+
return util.DecodeWithCommonError(response, "DepartmentUpdate")
116+
}
117+
118+
// DepartmentDelete 删除部门
119+
// @see https://developer.work.weixin.qq.com/document/path/90207
120+
func (r *Client) DepartmentDelete(departmentID int) error {
121+
var (
122+
accessToken string
123+
err error
124+
)
125+
if accessToken, err = r.GetAccessToken(); err != nil {
126+
return err
127+
}
128+
var response []byte
129+
if response, err = util.HTTPGet(fmt.Sprintf(departmentDeleteURL, accessToken, departmentID)); err != nil {
130+
return err
131+
}
132+
return util.DecodeWithCommonError(response, "DepartmentDelete")
133+
}
134+
88135
// DepartmentSimpleList 获取子部门ID列表
89136
// see https://developer.work.weixin.qq.com/document/path/95350
90137
func (r *Client) DepartmentSimpleList(departmentID int) ([]*DepartmentID, error) {

Diff for: work/addresslist/user.go

+47
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ const (
1212
userSimpleListURL = "https://qyapi.weixin.qq.com/cgi-bin/user/simplelist"
1313
// userCreateURL 创建成员
1414
userCreateURL = "https://qyapi.weixin.qq.com/cgi-bin/user/create?access_token=%s"
15+
// userUpdateURL 更新成员
16+
userUpdateURL = "https://qyapi.weixin.qq.com/cgi-bin/user/update?access_token=%s"
1517
// userGetURL 读取成员
1618
userGetURL = "https://qyapi.weixin.qq.com/cgi-bin/user/get"
1719
// userDeleteURL 删除成员
@@ -154,6 +156,51 @@ func (r *Client) UserCreate(req *UserCreateRequest) (*UserCreateResponse, error)
154156
return result, err
155157
}
156158

159+
// UserUpdateRequest 更新成员请求
160+
type UserUpdateRequest struct {
161+
UserID string `json:"userid"`
162+
NewUserID string `json:"new_userid"`
163+
Name string `json:"name"`
164+
Alias string `json:"alias"`
165+
Mobile string `json:"mobile"`
166+
Department []int `json:"department"`
167+
Order []int `json:"order"`
168+
Position string `json:"position"`
169+
Gender int `json:"gender"`
170+
Email string `json:"email"`
171+
BizMail string `json:"biz_mail"`
172+
IsLeaderInDept []int `json:"is_leader_in_dept"`
173+
DirectLeader []string `json:"direct_leader"`
174+
Enable int `json:"enable"`
175+
AvatarMediaid string `json:"avatar_mediaid"`
176+
Telephone string `json:"telephone"`
177+
Address string `json:"address"`
178+
MainDepartment int `json:"main_department"`
179+
Extattr struct {
180+
Attrs []ExtraAttr `json:"attrs"`
181+
} `json:"extattr"`
182+
ToInvite bool `json:"to_invite"`
183+
ExternalPosition string `json:"external_position"`
184+
ExternalProfile ExternalProfile `json:"external_profile"`
185+
}
186+
187+
// UserUpdate 更新成员
188+
// see https://developer.work.weixin.qq.com/document/path/90197
189+
func (r *Client) UserUpdate(req *UserUpdateRequest) error {
190+
var (
191+
accessToken string
192+
err error
193+
)
194+
if accessToken, err = r.GetAccessToken(); err != nil {
195+
return err
196+
}
197+
var response []byte
198+
if response, err = util.PostJSON(fmt.Sprintf(userUpdateURL, accessToken), req); err != nil {
199+
return err
200+
}
201+
return util.DecodeWithCommonError(response, "UserUpdate")
202+
}
203+
157204
// UserGetResponse 获取部门成员响应
158205
type UserGetResponse struct {
159206
util.CommonError

Diff for: work/kf/servicer.go

+7-3
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ type ReceptionistSchema struct {
3434
}
3535

3636
// ReceptionistAdd 添加接待人员
37+
// @see https://developer.work.weixin.qq.com/document/path/94646
3738
func (r *Client) ReceptionistAdd(options ReceptionistOptions) (info ReceptionistSchema, err error) {
3839
var (
3940
accessToken string
@@ -51,10 +52,11 @@ func (r *Client) ReceptionistAdd(options ReceptionistOptions) (info Receptionist
5152
if info.ErrCode != 0 {
5253
return info, NewSDKErr(info.ErrCode, info.ErrMsg)
5354
}
54-
return info, nil
55+
return
5556
}
5657

5758
// ReceptionistDel 删除接待人员
59+
// @see https://developer.work.weixin.qq.com/document/path/94647
5860
func (r *Client) ReceptionistDel(options ReceptionistOptions) (info ReceptionistSchema, err error) {
5961
var (
6062
accessToken string
@@ -74,7 +76,7 @@ func (r *Client) ReceptionistDel(options ReceptionistOptions) (info Receptionist
7476
if info.ErrCode != 0 {
7577
return info, NewSDKErr(info.ErrCode, info.ErrMsg)
7678
}
77-
return info, nil
79+
return
7880
}
7981

8082
// ReceptionistListSchema 获取接待人员列表响应内容
@@ -84,10 +86,12 @@ type ReceptionistListSchema struct {
8486
UserID string `json:"userid"` // 接待人员的userid。第三方应用获取到的为密文userid,即open_userid
8587
Status int `json:"status"` // 接待人员的接待状态。0:接待中,1:停止接待。第三方应用需具有“管理帐号、分配会话和收发消息”权限才可获取
8688
DepartmentID int `json:"department_id"` // 接待人员部门的id
89+
StopType int `json:"stop_type"` // 接待人员的接待状态为「停止接待」的子类型。0:停止接待,1:暂时挂起
8790
} `json:"servicer_list"`
8891
}
8992

9093
// ReceptionistList 获取接待人员列表
94+
// @see https://developer.work.weixin.qq.com/document/path/94645
9195
func (r *Client) ReceptionistList(kfID string) (info ReceptionistListSchema, err error) {
9296
var (
9397
accessToken string
@@ -107,5 +111,5 @@ func (r *Client) ReceptionistList(kfID string) (info ReceptionistListSchema, err
107111
if info.ErrCode != 0 {
108112
return info, NewSDKErr(info.ErrCode, info.ErrMsg)
109113
}
110-
return info, nil
114+
return
111115
}

0 commit comments

Comments
 (0)