mirror of
https://github.com/silenceper/wechat.git
synced 2026-02-05 21:22:27 +08:00
Compare commits
6 Commits
v2.1.5-rc.
...
v2.1.5
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9df943df69 | ||
|
|
0a37184c2f | ||
|
|
b4f243ab13 | ||
|
|
d92cd35533 | ||
|
|
58621cd79d | ||
|
|
8821a3856d |
@@ -12,9 +12,11 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
// AccessTokenURL 获取access_token的接口
|
||||
// accessTokenURL 获取access_token的接口
|
||||
accessTokenURL = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s"
|
||||
// AccessTokenURL 企业微信获取access_token的接口
|
||||
// stableAccessTokenURL 获取稳定版access_token的接口
|
||||
stableAccessTokenURL = "https://api.weixin.qq.com/cgi-bin/stable_token"
|
||||
// workAccessTokenURL 企业微信获取access_token的接口
|
||||
workAccessTokenURL = "https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid=%s&corpsecret=%s"
|
||||
// CacheKeyOfficialAccountPrefix 微信公众号cache key前缀
|
||||
CacheKeyOfficialAccountPrefix = "gowechat_officialaccount_"
|
||||
@@ -79,17 +81,87 @@ func (ak *DefaultAccessToken) GetAccessTokenContext(ctx context.Context) (access
|
||||
|
||||
// cache失效,从微信服务器获取
|
||||
var resAccessToken ResAccessToken
|
||||
resAccessToken, err = GetTokenFromServerContext(ctx, fmt.Sprintf(accessTokenURL, ak.appID, ak.appSecret))
|
||||
if resAccessToken, err = GetTokenFromServerContext(ctx, fmt.Sprintf(accessTokenURL, ak.appID, ak.appSecret)); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if err = ak.cache.Set(accessTokenCacheKey, resAccessToken.AccessToken, time.Duration(resAccessToken.ExpiresIn-1500)*time.Second); err != nil {
|
||||
return
|
||||
}
|
||||
accessToken = resAccessToken.AccessToken
|
||||
return
|
||||
}
|
||||
|
||||
// StableAccessToken 获取稳定版接口调用凭据(与getAccessToken获取的调用凭证完全隔离,互不影响)
|
||||
// 不强制更新access_token,可用于不同环境不同服务而不需要分布式锁以及公用缓存,避免access_token争抢
|
||||
// https://developers.weixin.qq.com/miniprogram/dev/OpenApiDoc/mp-access-token/getStableAccessToken.html
|
||||
type StableAccessToken struct {
|
||||
appID string
|
||||
appSecret string
|
||||
cacheKeyPrefix string
|
||||
cache cache.Cache
|
||||
}
|
||||
|
||||
// NewStableAccessToken new StableAccessToken
|
||||
func NewStableAccessToken(appID, appSecret, cacheKeyPrefix string, cache cache.Cache) AccessTokenContextHandle {
|
||||
if cache == nil {
|
||||
panic("cache is need")
|
||||
}
|
||||
return &StableAccessToken{
|
||||
appID: appID,
|
||||
appSecret: appSecret,
|
||||
cache: cache,
|
||||
cacheKeyPrefix: cacheKeyPrefix,
|
||||
}
|
||||
}
|
||||
|
||||
// GetAccessToken 获取access_token,先从cache中获取,没有则从服务端获取
|
||||
func (ak *StableAccessToken) GetAccessToken() (accessToken string, err error) {
|
||||
return ak.GetAccessTokenContext(context.Background())
|
||||
}
|
||||
|
||||
// GetAccessTokenContext 获取access_token,先从cache中获取,没有则从服务端获取
|
||||
func (ak *StableAccessToken) GetAccessTokenContext(ctx context.Context) (accessToken string, err error) {
|
||||
// 先从cache中取
|
||||
accessTokenCacheKey := fmt.Sprintf("%s_stable_access_token_%s", ak.cacheKeyPrefix, ak.appID)
|
||||
if val := ak.cache.Get(accessTokenCacheKey); val != nil {
|
||||
return val.(string), nil
|
||||
}
|
||||
|
||||
// cache失效,从微信服务器获取
|
||||
var resAccessToken ResAccessToken
|
||||
resAccessToken, err = ak.GetAccessTokenDirectly(ctx, false)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
expires := resAccessToken.ExpiresIn - 1500
|
||||
err = ak.cache.Set(accessTokenCacheKey, resAccessToken.AccessToken, time.Duration(expires)*time.Second)
|
||||
expires := resAccessToken.ExpiresIn - 300
|
||||
_ = ak.cache.Set(accessTokenCacheKey, resAccessToken.AccessToken, time.Duration(expires)*time.Second)
|
||||
|
||||
accessToken = resAccessToken.AccessToken
|
||||
return
|
||||
}
|
||||
|
||||
// GetAccessTokenDirectly 从微信获取access_token
|
||||
func (ak *StableAccessToken) GetAccessTokenDirectly(ctx context.Context, forceRefresh bool) (resAccessToken ResAccessToken, err error) {
|
||||
b, err := util.PostJSONContext(ctx, stableAccessTokenURL, map[string]interface{}{
|
||||
"grant_type": "client_credential",
|
||||
"appid": ak.appID,
|
||||
"secret": ak.appSecret,
|
||||
"force_refresh": forceRefresh,
|
||||
})
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
accessToken = resAccessToken.AccessToken
|
||||
|
||||
if err = json.Unmarshal(b, &resAccessToken); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if resAccessToken.ErrCode != 0 {
|
||||
err = fmt.Errorf("get stable access_token error : errcode=%v , errormsg=%v", resAccessToken.ErrCode, resAccessToken.ErrMsg)
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@ type RegisterMiniProgramParam struct {
|
||||
func (component *Component) RegisterMiniProgram(param *RegisterMiniProgramParam) error {
|
||||
componentAK, err := component.GetComponentAccessToken()
|
||||
if err != nil {
|
||||
return nil
|
||||
return err
|
||||
}
|
||||
url := fmt.Sprintf(fastregisterweappURL+"?action=create&component_access_token=%s", componentAK)
|
||||
data, err := util.PostJSON(url, param)
|
||||
@@ -58,7 +58,7 @@ type GetRegistrationStatusParam struct {
|
||||
func (component *Component) GetRegistrationStatus(param *GetRegistrationStatusParam) error {
|
||||
componentAK, err := component.GetComponentAccessToken()
|
||||
if err != nil {
|
||||
return nil
|
||||
return err
|
||||
}
|
||||
url := fmt.Sprintf(fastregisterweappURL+"?action=search&component_access_token=%s", componentAK)
|
||||
data, err := util.PostJSON(url, param)
|
||||
|
||||
@@ -13,6 +13,14 @@ const (
|
||||
updateTagURL = "https://qyapi.weixin.qq.com/cgi-bin/tag/update?access_token=%s"
|
||||
// deleteTagURL 删除标签
|
||||
deleteTagURL = "https://qyapi.weixin.qq.com/cgi-bin/tag/delete?access_token=%s&tagid=%d"
|
||||
// getTagURL 获取标签成员
|
||||
getTagURL = "https://qyapi.weixin.qq.com/cgi-bin/tag/get?access_token=%s&tagid=%d"
|
||||
// addTagUsersURL 增加标签成员
|
||||
addTagUsersURL = "https://qyapi.weixin.qq.com/cgi-bin/tag/addtagusers?access_token=%s"
|
||||
// delTagUsersURL 删除标签成员
|
||||
delTagUsersURL = "https://qyapi.weixin.qq.com/cgi-bin/tag/deltagusers?access_token=%s"
|
||||
// listTagURL 获取标签列表
|
||||
listTagURL = "https://qyapi.weixin.qq.com/cgi-bin/tag/list?access_token=%s"
|
||||
)
|
||||
|
||||
type (
|
||||
@@ -90,3 +98,145 @@ func (r *Client) DeleteTag(tagID int) error {
|
||||
}
|
||||
return util.DecodeWithCommonError(response, "DeleteTag")
|
||||
}
|
||||
|
||||
type (
|
||||
// GetTagResponse 获取标签成员响应
|
||||
GetTagResponse struct {
|
||||
util.CommonError
|
||||
TagName string `json:"tagname"`
|
||||
UserList []GetTagUserList `json:"userlist"`
|
||||
PartyList []int `json:"partylist"`
|
||||
}
|
||||
// GetTagUserList 标签中包含的成员列表
|
||||
GetTagUserList struct {
|
||||
UserID string `json:"userid"`
|
||||
Name string `json:"name"`
|
||||
}
|
||||
)
|
||||
|
||||
// GetTag 获取标签成员
|
||||
// @see https://developer.work.weixin.qq.com/document/path/90213
|
||||
func (r *Client) GetTag(tagID int) (*GetTagResponse, error) {
|
||||
var (
|
||||
accessToken string
|
||||
err error
|
||||
)
|
||||
if accessToken, err = r.GetAccessToken(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var response []byte
|
||||
if response, err = util.HTTPGet(fmt.Sprintf(getTagURL, accessToken, tagID)); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
result := &GetTagResponse{}
|
||||
if err = util.DecodeWithError(response, result, "GetTag"); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
type (
|
||||
// AddTagUsersRequest 增加标签成员请求
|
||||
AddTagUsersRequest struct {
|
||||
TagID int `json:"tagid"`
|
||||
UserList []string `json:"userlist"`
|
||||
PartyList []int `json:"partylist"`
|
||||
}
|
||||
// AddTagUsersResponse 增加标签成员响应
|
||||
AddTagUsersResponse struct {
|
||||
util.CommonError
|
||||
InvalidList string `json:"invalidlist"`
|
||||
InvalidParty []int `json:"invalidparty"`
|
||||
}
|
||||
)
|
||||
|
||||
// AddTagUsers 增加标签成员
|
||||
// see https://developer.work.weixin.qq.com/document/path/90214
|
||||
func (r *Client) AddTagUsers(req *AddTagUsersRequest) (*AddTagUsersResponse, error) {
|
||||
var (
|
||||
accessToken string
|
||||
err error
|
||||
)
|
||||
if accessToken, err = r.GetAccessToken(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var response []byte
|
||||
if response, err = util.PostJSON(fmt.Sprintf(addTagUsersURL, accessToken), req); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
result := &AddTagUsersResponse{}
|
||||
if err = util.DecodeWithError(response, result, "AddTagUsers"); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
type (
|
||||
// DelTagUsersRequest 删除标签成员请求
|
||||
DelTagUsersRequest struct {
|
||||
TagID int `json:"tagid"`
|
||||
UserList []string `json:"userlist"`
|
||||
PartyList []int `json:"partylist"`
|
||||
}
|
||||
// DelTagUsersResponse 删除标签成员响应
|
||||
DelTagUsersResponse struct {
|
||||
util.CommonError
|
||||
InvalidList string `json:"invalidlist"`
|
||||
InvalidParty []int `json:"invalidparty"`
|
||||
}
|
||||
)
|
||||
|
||||
// DelTagUsers 删除标签成员
|
||||
// see https://developer.work.weixin.qq.com/document/path/90215
|
||||
func (r *Client) DelTagUsers(req *DelTagUsersRequest) (*DelTagUsersResponse, error) {
|
||||
var (
|
||||
accessToken string
|
||||
err error
|
||||
)
|
||||
if accessToken, err = r.GetAccessToken(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var response []byte
|
||||
if response, err = util.PostJSON(fmt.Sprintf(delTagUsersURL, accessToken), req); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
result := &DelTagUsersResponse{}
|
||||
if err = util.DecodeWithError(response, result, "DelTagUsers"); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
type (
|
||||
// ListTagResponse 获取标签列表响应
|
||||
ListTagResponse struct {
|
||||
util.CommonError
|
||||
TagList []Tag `json:"taglist"`
|
||||
}
|
||||
// Tag 标签
|
||||
Tag struct {
|
||||
TagID int `json:"tagid"`
|
||||
TagName string `json:"tagname"`
|
||||
}
|
||||
)
|
||||
|
||||
// ListTag 获取标签列表
|
||||
// @see https://developer.work.weixin.qq.com/document/path/90216
|
||||
func (r *Client) ListTag() (*ListTagResponse, error) {
|
||||
var (
|
||||
accessToken string
|
||||
err error
|
||||
)
|
||||
if accessToken, err = r.GetAccessToken(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var response []byte
|
||||
if response, err = util.HTTPGet(fmt.Sprintf(listTagURL, accessToken)); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
result := &ListTagResponse{}
|
||||
if err = util.DecodeWithError(response, result, "ListTag"); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
@@ -13,6 +13,10 @@ const (
|
||||
userGetURL = "https://qyapi.weixin.qq.com/cgi-bin/user/get?access_token=%s&userid=%s"
|
||||
// userListIDURL 获取成员ID列表
|
||||
userListIDURL = "https://qyapi.weixin.qq.com/cgi-bin/user/list_id?access_token=%s"
|
||||
// convertToOpenIDURL userID转openID
|
||||
convertToOpenIDURL = "https://qyapi.weixin.qq.com/cgi-bin/user/convert_to_openid?access_token=%s"
|
||||
// convertToUserIDURL openID转userID
|
||||
convertToUserIDURL = "https://qyapi.weixin.qq.com/cgi-bin/user/convert_to_userid?access_token=%s"
|
||||
)
|
||||
|
||||
type (
|
||||
@@ -175,3 +179,75 @@ func (r *Client) UserListID(req *UserListIDRequest) (*UserListIDResponse, error)
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
type (
|
||||
// convertToOpenIDRequest userID转openID请求
|
||||
convertToOpenIDRequest struct {
|
||||
UserID string `json:"userid"`
|
||||
}
|
||||
|
||||
// convertToOpenIDResponse userID转openID响应
|
||||
convertToOpenIDResponse struct {
|
||||
util.CommonError
|
||||
OpenID string `json:"openid"`
|
||||
}
|
||||
)
|
||||
|
||||
// ConvertToOpenID userID转openID
|
||||
// see https://developer.work.weixin.qq.com/document/path/90202
|
||||
func (r *Client) ConvertToOpenID(userID string) (string, error) {
|
||||
var (
|
||||
accessToken string
|
||||
err error
|
||||
)
|
||||
if accessToken, err = r.GetAccessToken(); err != nil {
|
||||
return "", err
|
||||
}
|
||||
var response []byte
|
||||
if response, err = util.PostJSON(fmt.Sprintf(convertToOpenIDURL, accessToken), &convertToOpenIDRequest{
|
||||
UserID: userID,
|
||||
}); err != nil {
|
||||
return "", err
|
||||
}
|
||||
result := &convertToOpenIDResponse{}
|
||||
if err = util.DecodeWithError(response, result, "ConvertToOpenID"); err != nil {
|
||||
return "", err
|
||||
}
|
||||
return result.OpenID, nil
|
||||
}
|
||||
|
||||
type (
|
||||
// convertToUserIDRequest openID转userID请求
|
||||
convertToUserIDRequest struct {
|
||||
OpenID string `json:"openid"`
|
||||
}
|
||||
|
||||
// convertToUserIDResponse openID转userID响应
|
||||
convertToUserIDResponse struct {
|
||||
util.CommonError
|
||||
UserID string `json:"userid"`
|
||||
}
|
||||
)
|
||||
|
||||
// ConvertToUserID openID转userID
|
||||
// see https://developer.work.weixin.qq.com/document/path/90202
|
||||
func (r *Client) ConvertToUserID(openID string) (string, error) {
|
||||
var (
|
||||
accessToken string
|
||||
err error
|
||||
)
|
||||
if accessToken, err = r.GetAccessToken(); err != nil {
|
||||
return "", err
|
||||
}
|
||||
var response []byte
|
||||
if response, err = util.PostJSON(fmt.Sprintf(convertToUserIDURL, accessToken), &convertToUserIDRequest{
|
||||
OpenID: openID,
|
||||
}); err != nil {
|
||||
return "", err
|
||||
}
|
||||
result := &convertToUserIDResponse{}
|
||||
if err = util.DecodeWithError(response, result, "ConvertToUserID"); err != nil {
|
||||
return "", err
|
||||
}
|
||||
return result.UserID, nil
|
||||
}
|
||||
|
||||
115
work/appchat/appchat.go
Normal file
115
work/appchat/appchat.go
Normal file
@@ -0,0 +1,115 @@
|
||||
package appchat
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"github.com/silenceper/wechat/v2/util"
|
||||
)
|
||||
|
||||
const (
|
||||
// 应用推送消息接口地址
|
||||
sendURL = "https://qyapi.weixin.qq.com/cgi-bin/appchat/send?access_token=%s"
|
||||
)
|
||||
|
||||
type (
|
||||
// SendRequestCommon 发送应用推送消息请求公共参数
|
||||
SendRequestCommon struct {
|
||||
// 群聊id
|
||||
ChatID string `json:"chatid"`
|
||||
// 消息类型
|
||||
MsgType string `json:"msgtype"`
|
||||
// 表示是否是保密消息,0表示否,1表示是,默认0
|
||||
Safe int `json:"safe"`
|
||||
}
|
||||
|
||||
// SendResponse 发送应用消息响应参数
|
||||
SendResponse struct {
|
||||
util.CommonError
|
||||
}
|
||||
|
||||
// SendTextRequest 发送文本消息的请求
|
||||
SendTextRequest struct {
|
||||
*SendRequestCommon
|
||||
Text TextField `json:"text"`
|
||||
}
|
||||
// TextField 文本消息参数
|
||||
TextField struct {
|
||||
// 消息内容,最长不超过2048个字节
|
||||
Content string `json:"content"`
|
||||
}
|
||||
|
||||
// SendImageRequest 发送图片消息的请求
|
||||
SendImageRequest struct {
|
||||
*SendRequestCommon
|
||||
Image ImageField `json:"image"`
|
||||
}
|
||||
// ImageField 图片消息参数
|
||||
ImageField struct {
|
||||
// 图片媒体文件id,可以调用上传临时素材接口获取
|
||||
MediaID string `json:"media_id"`
|
||||
}
|
||||
|
||||
// SendVoiceRequest 发送语音消息的请求
|
||||
SendVoiceRequest struct {
|
||||
*SendRequestCommon
|
||||
Voice VoiceField `json:"voice"`
|
||||
}
|
||||
// VoiceField 语音消息参数
|
||||
VoiceField struct {
|
||||
// 语音文件id,可以调用上传临时素材接口获取
|
||||
MediaID string `json:"media_id"`
|
||||
}
|
||||
)
|
||||
|
||||
// Send 发送应用消息
|
||||
// @desc 实现企业微信发送应用消息接口:https://developer.work.weixin.qq.com/document/path/90248
|
||||
func (r *Client) Send(apiName string, request interface{}) (*SendResponse, error) {
|
||||
// 获取accessToken
|
||||
accessToken, err := r.GetAccessToken()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// 请求参数转 JSON 格式
|
||||
jsonData, err := json.Marshal(request)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// 发起http请求
|
||||
response, err := util.HTTPPost(fmt.Sprintf(sendURL, accessToken), string(jsonData))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// 按照结构体解析返回值
|
||||
result := &SendResponse{}
|
||||
if err = util.DecodeWithError(response, result, apiName); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// 返回数据
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// SendText 发送文本消息
|
||||
func (r *Client) SendText(request SendTextRequest) (*SendResponse, error) {
|
||||
// 发送文本消息MsgType参数固定为:text
|
||||
request.MsgType = "text"
|
||||
return r.Send("MessageSendText", request)
|
||||
}
|
||||
|
||||
// SendImage 发送图片消息
|
||||
func (r *Client) SendImage(request SendImageRequest) (*SendResponse, error) {
|
||||
// 发送图片消息MsgType参数固定为:image
|
||||
request.MsgType = "image"
|
||||
return r.Send("MessageSendImage", request)
|
||||
}
|
||||
|
||||
// SendVoice 发送语音消息
|
||||
func (r *Client) SendVoice(request SendVoiceRequest) (*SendResponse, error) {
|
||||
// 发送语音消息MsgType参数固定为:voice
|
||||
request.MsgType = "voice"
|
||||
return r.Send("MessageSendVoice", request)
|
||||
}
|
||||
|
||||
// 以上实现了部分常用消息推送:SendText 发送文本消息、SendImage 发送图片消息、SendVoice 发送语音消息,
|
||||
// 如需扩展其他消息类型,建议按照以上格式,扩展对应消息类型的参数即可
|
||||
// 也可以直接使用Send方法,按照企业微信消息推送的接口文档传对应消息类型的参数来使用
|
||||
16
work/appchat/client.go
Normal file
16
work/appchat/client.go
Normal file
@@ -0,0 +1,16 @@
|
||||
// Package appchat 应用发送消息到群聊会话,企业微信接口:https://developer.work.weixin.qq.com/document/path/90248
|
||||
package appchat
|
||||
|
||||
import (
|
||||
"github.com/silenceper/wechat/v2/work/context"
|
||||
)
|
||||
|
||||
// Client 接口实例
|
||||
type Client struct {
|
||||
*context.Context
|
||||
}
|
||||
|
||||
// NewClient 初始化实例
|
||||
func NewClient(ctx *context.Context) *Client {
|
||||
return &Client{ctx}
|
||||
}
|
||||
@@ -52,12 +52,12 @@ type callbackOriginMessage struct {
|
||||
|
||||
// CallbackMessage 微信客服回调消息
|
||||
type CallbackMessage struct {
|
||||
ToUserName string `json:"to_user_name"` // 微信客服组件ID
|
||||
CreateTime int `json:"create_time"` // 消息创建时间,unix时间戳
|
||||
MsgType string `json:"msgtype"` // 消息的类型,此时固定为 event
|
||||
Event string `json:"event"` // 事件的类型,此时固定为 kf_msg_or_event
|
||||
Token string `json:"token"` // 调用拉取消息接口时,需要传此token,用于校验请求的合法性
|
||||
OpenKfID string `json:"open_kfid"` // 有新消息的客服帐号。可通过sync_msg接口指定open_kfid获取此客服帐号的消息
|
||||
ToUserName string `json:"to_user_name" xml:"ToUserName"` // 微信客服组件ID
|
||||
CreateTime int `json:"create_time" xml:"CreateTime"` // 消息创建时间,unix时间戳
|
||||
MsgType string `json:"msgtype" xml:"MsgType"` // 消息的类型,此时固定为 event
|
||||
Event string `json:"event" xml:"Event"` // 事件的类型,此时固定为 kf_msg_or_event
|
||||
Token string `json:"token" xml:"Token"` // 调用拉取消息接口时,需要传此token,用于校验请求的合法性
|
||||
OpenKfID string `json:"open_kfid" xml:"OpenKfId"` // 有新消息的客服帐号。可通过sync_msg接口指定open_kfid获取此客服帐号的消息
|
||||
}
|
||||
|
||||
// GetCallbackMessage 获取回调事件中的消息内容
|
||||
|
||||
@@ -16,11 +16,11 @@ const (
|
||||
|
||||
// SyncMsgOptions 获取消息查询参数
|
||||
type SyncMsgOptions struct {
|
||||
Cursor string `json:"cursor"` // 上一次调用时返回的next_cursor,第一次拉取可以不填, 不多于64字节
|
||||
Token string `json:"token"` // 回调事件返回的token字段,10分钟内有效;可不填,如果不填接口有严格的频率限制, 不多于128字节
|
||||
Limit uint `json:"limit"` // 期望请求的数据量,默认值和最大值都为1000, 注意:可能会出现返回条数少于limit的情况,需结合返回的has_more字段判断是否继续请求。
|
||||
VoiceFormat uint `json:"voice_format"` // 语音消息类型,0-Amr 1-Silk,默认0。可通过该参数控制返回的语音格式,开发者可按需选择自己程序支持的一种格式
|
||||
OpenKfID string `json:"open_kfid"` // 指定拉取某个客服帐号的消息,否则默认返回有权限的客服帐号的消息。当客服帐号较多,建议按open_kfid来拉取以获取更好的性能。
|
||||
Cursor string `json:"cursor"` // 上一次调用时返回的next_cursor,第一次拉取可以不填, 不多于64字节
|
||||
Token string `json:"token"` // 回调事件返回的token字段,10分钟内有效;可不填,如果不填接口有严格的频率限制, 不多于128字节
|
||||
Limit uint `json:"limit"` // 期望请求的数据量,默认值和最大值都为1000, 注意:可能会出现返回条数少于limit的情况,需结合返回的has_more字段判断是否继续请求。
|
||||
VoiceFormat uint `json:"voice_format,omitempty"` // 语音消息类型,0-Amr 1-Silk,默认0。可通过该参数控制返回的语音格式,开发者可按需选择自己程序支持的一种格式
|
||||
OpenKfID string `json:"open_kfid,omitempty"` // 指定拉取某个客服帐号的消息,否则默认返回有权限的客服帐号的消息。当客服帐号较多,建议按open_kfid来拉取以获取更好的性能。
|
||||
}
|
||||
|
||||
// SyncMsgSchema 获取消息查询响应内容
|
||||
|
||||
@@ -3,6 +3,7 @@ package work
|
||||
import (
|
||||
"github.com/silenceper/wechat/v2/credential"
|
||||
"github.com/silenceper/wechat/v2/work/addresslist"
|
||||
"github.com/silenceper/wechat/v2/work/appchat"
|
||||
"github.com/silenceper/wechat/v2/work/config"
|
||||
"github.com/silenceper/wechat/v2/work/context"
|
||||
"github.com/silenceper/wechat/v2/work/externalcontact"
|
||||
@@ -69,7 +70,12 @@ func (wk *Work) GetRobot() *robot.Client {
|
||||
return robot.NewClient(wk.ctx)
|
||||
}
|
||||
|
||||
// GetMessage get robot
|
||||
// GetMessage 获取发送应用消息接口实例
|
||||
func (wk *Work) GetMessage() *message.Client {
|
||||
return message.NewClient(wk.ctx)
|
||||
}
|
||||
|
||||
// GetAppChat 获取应用发送消息到群聊会话接口实例
|
||||
func (wk *Work) GetAppChat() *appchat.Client {
|
||||
return appchat.NewClient(wk.ctx)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user