mirror of
https://github.com/silenceper/wechat.git
synced 2026-02-12 08:42:28 +08:00
improve comment ,参考:https://github.com/huacnlee/autocorrect
This commit is contained in:
@@ -53,3 +53,68 @@ linters-settings:
|
|||||||
lines: 66
|
lines: 66
|
||||||
statements: 50
|
statements: 50
|
||||||
|
|
||||||
|
errcheck:
|
||||||
|
# Report about not checking of errors in type assertions: `a := b.(MyStruct)`.
|
||||||
|
# Such cases aren't reported by default.
|
||||||
|
# Default: false
|
||||||
|
check-type-assertions: true
|
||||||
|
# report about assignment of errors to blank identifier: `num, _ := strconv.Atoi(numStr)`.
|
||||||
|
# Such cases aren't reported by default.
|
||||||
|
# Default: false
|
||||||
|
check-blank: true
|
||||||
|
# To disable the errcheck built-in exclude list.
|
||||||
|
# See `-excludeonly` option in https://github.com/kisielk/errcheck#excluding-functions for details.
|
||||||
|
# Default: false
|
||||||
|
disable-default-exclusions: true
|
||||||
|
# List of functions to exclude from checking, where each entry is a single function to exclude.
|
||||||
|
# See https://github.com/kisielk/errcheck#excluding-functions for details.
|
||||||
|
exclude-functions:
|
||||||
|
- io/ioutil.ReadFile
|
||||||
|
- io.Copy(*bytes.Buffer)
|
||||||
|
- io.Copy(os.Stdout)
|
||||||
|
- (*bytes.Buffer).WriteString
|
||||||
|
- (*bytes.Buffer).Write
|
||||||
|
- url.Parse
|
||||||
|
- (*strings.Builder).WriteString
|
||||||
|
- io.WriteString
|
||||||
|
- (*bytes.Buffer).WriteByte
|
||||||
|
- (*hmac.New).Write
|
||||||
|
- (*int)
|
||||||
|
- (*string)
|
||||||
|
- (hash.Hash).Write
|
||||||
|
|
||||||
|
depguard:
|
||||||
|
# Rules to apply.
|
||||||
|
#
|
||||||
|
# Variables:
|
||||||
|
# - File Variables
|
||||||
|
# you can still use and exclamation mark ! in front of a variable to say not to use it.
|
||||||
|
# Example !$test will match any file that is not a go test file.
|
||||||
|
#
|
||||||
|
# `$all` - matches all go files
|
||||||
|
# `$test` - matches all go test files
|
||||||
|
#
|
||||||
|
# - Package Variables
|
||||||
|
#
|
||||||
|
# `$gostd` - matches all of go's standard library (Pulled from `GOROOT`)
|
||||||
|
#
|
||||||
|
# Default: Only allow $gostd in all files.
|
||||||
|
rules:
|
||||||
|
# Name of a rule.
|
||||||
|
main:
|
||||||
|
# Used to determine the package matching priority.
|
||||||
|
# There are three different modes: `original`, `strict`, and `lax`.
|
||||||
|
# Default: "original"
|
||||||
|
list-mode: lax
|
||||||
|
# List of file globs that will match this list of settings to compare against.
|
||||||
|
# Default: $all
|
||||||
|
files:
|
||||||
|
- "!**/*_a _file.go"
|
||||||
|
# List of allowed packages.
|
||||||
|
allow:
|
||||||
|
- $gostd
|
||||||
|
- github.com/OpenPeeDeeP
|
||||||
|
# Packages that are not allowed where the value is a suggestion.
|
||||||
|
deny:
|
||||||
|
- pkg: "github.com/pkg/errors"
|
||||||
|
desc: Should be replaced by standard lib errors package
|
||||||
6
cache/memcache_test.go
vendored
6
cache/memcache_test.go
vendored
@@ -22,12 +22,16 @@ func TestMemcache(t *testing.T) {
|
|||||||
exists := mem.IsExist("unknown-key")
|
exists := mem.IsExist("unknown-key")
|
||||||
assert.Equal(t, false, exists)
|
assert.Equal(t, false, exists)
|
||||||
|
|
||||||
name := mem.Get("username").(string)
|
name, ok := mem.Get("username").(string)
|
||||||
|
if !ok {
|
||||||
|
t.Error("get Error")
|
||||||
|
}
|
||||||
if name != "" {
|
if name != "" {
|
||||||
if name != "silenceper" {
|
if name != "silenceper" {
|
||||||
t.Error("get Error")
|
t.Error("get Error")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
data := mem.Get("unknown-key")
|
data := mem.Get("unknown-key")
|
||||||
assert.Nil(t, data)
|
assert.Nil(t, data)
|
||||||
|
|
||||||
|
|||||||
6
cache/redis.go
vendored
6
cache/redis.go
vendored
@@ -76,8 +76,10 @@ func (r *Redis) IsExist(key string) bool {
|
|||||||
|
|
||||||
// IsExistContext 判断 key 是否存在
|
// IsExistContext 判断 key 是否存在
|
||||||
func (r *Redis) IsExistContext(ctx context.Context, key string) bool {
|
func (r *Redis) IsExistContext(ctx context.Context, key string) bool {
|
||||||
result, _ := r.conn.Exists(ctx, key).Result()
|
result, err := r.conn.Exists(ctx, key).Result()
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
return result > 0
|
return result > 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
5
cache/redis_test.go
vendored
5
cache/redis_test.go
vendored
@@ -35,7 +35,10 @@ func TestRedis(t *testing.T) {
|
|||||||
t.Error("IsExist Error")
|
t.Error("IsExist Error")
|
||||||
}
|
}
|
||||||
|
|
||||||
name := redis.Get(key).(string)
|
name, ok := redis.Get(key).(string)
|
||||||
|
if !ok {
|
||||||
|
t.Error("get Error")
|
||||||
|
}
|
||||||
if name != val {
|
if name != val {
|
||||||
t.Error("get Error")
|
t.Error("get Error")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -57,18 +57,19 @@ type ResAccessToken struct {
|
|||||||
ExpiresIn int64 `json:"expires_in"`
|
ExpiresIn int64 `json:"expires_in"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetAccessToken 获取access_token,先从cache中获取,没有则从服务端获取
|
// GetAccessToken 获取 access_token,先从 cache 中获取,没有则从服务端获取
|
||||||
func (ak *DefaultAccessToken) GetAccessToken() (accessToken string, err error) {
|
func (ak *DefaultAccessToken) GetAccessToken() (accessToken string, err error) {
|
||||||
return ak.GetAccessTokenContext(context.Background())
|
return ak.GetAccessTokenContext(context.Background())
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetAccessTokenContext 获取access_token,先从cache中获取,没有则从服务端获取
|
// GetAccessTokenContext 获取 access_token,先从 cache 中获取,没有则从服务端获取
|
||||||
func (ak *DefaultAccessToken) GetAccessTokenContext(ctx context.Context) (accessToken string, err error) {
|
func (ak *DefaultAccessToken) GetAccessTokenContext(ctx context.Context) (accessToken string, err error) {
|
||||||
// 先从 cache 中取
|
// 先从 cache 中取
|
||||||
accessTokenCacheKey := fmt.Sprintf("%s_access_token_%s", ak.cacheKeyPrefix, ak.appID)
|
accessTokenCacheKey := fmt.Sprintf("%s_access_token_%s", ak.cacheKeyPrefix, ak.appID)
|
||||||
|
|
||||||
if val := ak.cache.Get(accessTokenCacheKey); val != nil {
|
if val := ak.cache.Get(accessTokenCacheKey); val != nil {
|
||||||
if accessToken = val.(string); accessToken != "" {
|
var ok bool
|
||||||
|
if accessToken, ok = val.(string); ok && accessToken != "" {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -79,7 +80,8 @@ func (ak *DefaultAccessToken) GetAccessTokenContext(ctx context.Context) (access
|
|||||||
|
|
||||||
// 双检,防止重复从微信服务器获取
|
// 双检,防止重复从微信服务器获取
|
||||||
if val := ak.cache.Get(accessTokenCacheKey); val != nil {
|
if val := ak.cache.Get(accessTokenCacheKey); val != nil {
|
||||||
if accessToken = val.(string); accessToken != "" {
|
var ok bool
|
||||||
|
if accessToken, ok = val.(string); ok && accessToken != "" {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -98,7 +100,7 @@ func (ak *DefaultAccessToken) GetAccessTokenContext(ctx context.Context) (access
|
|||||||
}
|
}
|
||||||
|
|
||||||
// StableAccessToken 获取稳定版接口调用凭据 (与 getAccessToken 获取的调用凭证完全隔离,互不影响)
|
// StableAccessToken 获取稳定版接口调用凭据 (与 getAccessToken 获取的调用凭证完全隔离,互不影响)
|
||||||
// 不强制更新access_token,可用于不同环境不同服务而不需要分布式锁以及公用缓存,避免access_token争抢
|
// 不强制更新 access_token,可用于不同环境不同服务而不需要分布式锁以及公用缓存,避免 access_token 争抢
|
||||||
// https://developers.weixin.qq.com/miniprogram/dev/OpenApiDoc/mp-access-token/getStableAccessToken.html
|
// https://developers.weixin.qq.com/miniprogram/dev/OpenApiDoc/mp-access-token/getStableAccessToken.html
|
||||||
type StableAccessToken struct {
|
type StableAccessToken struct {
|
||||||
appID string
|
appID string
|
||||||
@@ -120,12 +122,12 @@ func NewStableAccessToken(appID, appSecret, cacheKeyPrefix string, cache cache.C
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetAccessToken 获取access_token,先从cache中获取,没有则从服务端获取
|
// GetAccessToken 获取 access_token,先从 cache 中获取,没有则从服务端获取
|
||||||
func (ak *StableAccessToken) GetAccessToken() (accessToken string, err error) {
|
func (ak *StableAccessToken) GetAccessToken() (accessToken string, err error) {
|
||||||
return ak.GetAccessTokenContext(context.Background())
|
return ak.GetAccessTokenContext(context.Background())
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetAccessTokenContext 获取access_token,先从cache中获取,没有则从服务端获取
|
// GetAccessTokenContext 获取 access_token,先从 cache 中获取,没有则从服务端获取
|
||||||
func (ak *StableAccessToken) GetAccessTokenContext(ctx context.Context) (accessToken string, err error) {
|
func (ak *StableAccessToken) GetAccessTokenContext(ctx context.Context) (accessToken string, err error) {
|
||||||
// 先从 cache 中取
|
// 先从 cache 中取
|
||||||
accessTokenCacheKey := fmt.Sprintf("%s_stable_access_token_%s", ak.cacheKeyPrefix, ak.appID)
|
accessTokenCacheKey := fmt.Sprintf("%s_stable_access_token_%s", ak.cacheKeyPrefix, ak.appID)
|
||||||
@@ -193,12 +195,12 @@ func NewWorkAccessToken(corpID, corpSecret, cacheKeyPrefix string, cache cache.C
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetAccessToken 企业微信获取access_token,先从cache中获取,没有则从服务端获取
|
// GetAccessToken 企业微信获取 access_token,先从 cache 中获取,没有则从服务端获取
|
||||||
func (ak *WorkAccessToken) GetAccessToken() (accessToken string, err error) {
|
func (ak *WorkAccessToken) GetAccessToken() (accessToken string, err error) {
|
||||||
return ak.GetAccessTokenContext(context.Background())
|
return ak.GetAccessTokenContext(context.Background())
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetAccessTokenContext 企业微信获取access_token,先从cache中获取,没有则从服务端获取
|
// GetAccessTokenContext 企业微信获取 access_token,先从 cache 中获取,没有则从服务端获取
|
||||||
func (ak *WorkAccessToken) GetAccessTokenContext(ctx context.Context) (accessToken string, err error) {
|
func (ak *WorkAccessToken) GetAccessTokenContext(ctx context.Context) (accessToken string, err error) {
|
||||||
// 加上 lock,是为了防止在并发获取 token 时,cache 刚好失效,导致从微信服务器上获取到不同 token
|
// 加上 lock,是为了防止在并发获取 token 时,cache 刚好失效,导致从微信服务器上获取到不同 token
|
||||||
ak.accessTokenLock.Lock()
|
ak.accessTokenLock.Lock()
|
||||||
@@ -206,7 +208,10 @@ func (ak *WorkAccessToken) GetAccessTokenContext(ctx context.Context) (accessTok
|
|||||||
accessTokenCacheKey := fmt.Sprintf("%s_access_token_%s", ak.cacheKeyPrefix, ak.CorpID)
|
accessTokenCacheKey := fmt.Sprintf("%s_access_token_%s", ak.cacheKeyPrefix, ak.CorpID)
|
||||||
val := ak.cache.Get(accessTokenCacheKey)
|
val := ak.cache.Get(accessTokenCacheKey)
|
||||||
if val != nil {
|
if val != nil {
|
||||||
accessToken = val.(string)
|
var ok bool
|
||||||
|
if accessToken, ok = val.(string); !ok {
|
||||||
|
accessToken = ""
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -93,10 +93,16 @@ func (o *OpenAPI) ClearQuotaByAppSecret() error {
|
|||||||
func (o *OpenAPI) getAppIDAndSecret() (string, string, error) {
|
func (o *OpenAPI) getAppIDAndSecret() (string, string, error) {
|
||||||
switch o.ctx.(type) {
|
switch o.ctx.(type) {
|
||||||
case *mpContext.Context:
|
case *mpContext.Context:
|
||||||
c := o.ctx.(*mpContext.Context)
|
c, ok := o.ctx.(*mpContext.Context)
|
||||||
|
if !ok {
|
||||||
|
return "", "", errors.New("invalid context type")
|
||||||
|
}
|
||||||
return c.AppID, c.AppSecret, nil
|
return c.AppID, c.AppSecret, nil
|
||||||
case *ocContext.Context:
|
case *ocContext.Context:
|
||||||
c := o.ctx.(*ocContext.Context)
|
c, ok := o.ctx.(*ocContext.Context)
|
||||||
|
if !ok {
|
||||||
|
return "", "", errors.New("invalid context type")
|
||||||
|
}
|
||||||
return c.AppID, c.AppSecret, nil
|
return c.AppID, c.AppSecret, nil
|
||||||
default:
|
default:
|
||||||
return "", "", errors.New("invalid context type")
|
return "", "", errors.New("invalid context type")
|
||||||
|
|||||||
@@ -183,7 +183,7 @@ type GetShippingOrderRequest struct {
|
|||||||
|
|
||||||
// ShippingItem 物流信息
|
// ShippingItem 物流信息
|
||||||
type ShippingItem struct {
|
type ShippingItem struct {
|
||||||
TrackingNo string `json:"tracking_no"` // 物流单号,示例值: "323244567777
|
TrackingNo string `json:"tracking_no"` // 物流单号,示例值:"323244567777
|
||||||
ExpressCompany string `json:"express_company"` // 物流公司编码,快递公司 ID,物流快递发货时必填;参见「查询物流公司编码列表」
|
ExpressCompany string `json:"express_company"` // 物流公司编码,快递公司 ID,物流快递发货时必填;参见「查询物流公司编码列表」
|
||||||
UploadTime int64 `json:"upload_time"` // 上传物流信息时间,时间戳形式
|
UploadTime int64 `json:"upload_time"` // 上传物流信息时间,时间戳形式
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ type Color struct {
|
|||||||
|
|
||||||
// QRCoder 小程序码参数
|
// QRCoder 小程序码参数
|
||||||
type QRCoder struct {
|
type QRCoder struct {
|
||||||
// page 必须是已经发布的小程序存在的页面,根路径前不要填加 /,不能携带参数(参数请放在scene字段里),如果不填写这个字段,默认跳主页面
|
// page 必须是已经发布的小程序存在的页面,根路径前不要填加 /,不能携带参数(参数请放在 scene 字段里),如果不填写这个字段,默认跳主页面
|
||||||
Page string `json:"page,omitempty"`
|
Page string `json:"page,omitempty"`
|
||||||
// path 扫码进入的小程序页面路径
|
// path 扫码进入的小程序页面路径
|
||||||
Path string `json:"path,omitempty"`
|
Path string `json:"path,omitempty"`
|
||||||
|
|||||||
@@ -43,8 +43,8 @@ func NewSubscribe(ctx *context.Context) *Subscribe {
|
|||||||
type Message struct {
|
type Message struct {
|
||||||
ToUser string `json:"touser"` // 必选,接收者(用户)的 openid
|
ToUser string `json:"touser"` // 必选,接收者(用户)的 openid
|
||||||
TemplateID string `json:"template_id"` // 必选,所需下发的订阅模板 id
|
TemplateID string `json:"template_id"` // 必选,所需下发的订阅模板 id
|
||||||
Page string `json:"page"` // 可选,点击模板卡片后的跳转页面,仅限本小程序内的页面。支持带参数,(示例index?foo=bar)。该字段不填则模板无跳转。
|
Page string `json:"page"` // 可选,点击模板卡片后的跳转页面,仅限本小程序内的页面。支持带参数,(示例 index?foo=bar)。该字段不填则模板无跳转。
|
||||||
Data map[string]*DataItem `json:"data"` // 必选, 模板内容
|
Data map[string]*DataItem `json:"data"` // 必选,模板内容
|
||||||
MiniprogramState string `json:"miniprogram_state"` // 可选,跳转小程序类型:developer 为开发版;trial 为体验版;formal 为正式版;默认为正式版
|
MiniprogramState string `json:"miniprogram_state"` // 可选,跳转小程序类型:developer 为开发版;trial 为体验版;formal 为正式版;默认为正式版
|
||||||
Lang string `json:"lang"` // 入小程序查看”的语言类型,支持 zh_CN(简体中文)、en_US(英文)、zh_HK(繁体中文)、zh_TW(繁体中文),默认为 zh_CN
|
Lang string `json:"lang"` // 入小程序查看”的语言类型,支持 zh_CN(简体中文)、en_US(英文)、zh_HK(繁体中文)、zh_TW(繁体中文),默认为 zh_CN
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -77,19 +77,27 @@ func ShowQRCode(tk *Ticket) string {
|
|||||||
|
|
||||||
// NewTmpQrRequest 新建临时二维码请求实例
|
// NewTmpQrRequest 新建临时二维码请求实例
|
||||||
func NewTmpQrRequest(exp time.Duration, scene interface{}) *Request {
|
func NewTmpQrRequest(exp time.Duration, scene interface{}) *Request {
|
||||||
tq := &Request{
|
var (
|
||||||
|
tq = &Request{
|
||||||
ExpireSeconds: int64(exp.Seconds()),
|
ExpireSeconds: int64(exp.Seconds()),
|
||||||
}
|
}
|
||||||
|
ok bool
|
||||||
|
)
|
||||||
switch reflect.ValueOf(scene).Kind() {
|
switch reflect.ValueOf(scene).Kind() {
|
||||||
case reflect.String:
|
case reflect.String:
|
||||||
tq.ActionName = actionStr
|
tq.ActionName = actionStr
|
||||||
tq.ActionInfo.Scene.SceneStr = scene.(string)
|
if tq.ActionInfo.Scene.SceneStr, ok = scene.(string); !ok {
|
||||||
|
panic("scene must be string")
|
||||||
|
}
|
||||||
case reflect.Int, reflect.Int8, reflect.Int16,
|
case reflect.Int, reflect.Int8, reflect.Int16,
|
||||||
reflect.Int32, reflect.Int64,
|
reflect.Int32, reflect.Int64,
|
||||||
reflect.Uint, reflect.Uint8, reflect.Uint16,
|
reflect.Uint, reflect.Uint8, reflect.Uint16,
|
||||||
reflect.Uint32, reflect.Uint64:
|
reflect.Uint32, reflect.Uint64:
|
||||||
tq.ActionName = actionID
|
tq.ActionName = actionID
|
||||||
tq.ActionInfo.Scene.SceneID = scene.(int)
|
if tq.ActionInfo.Scene.SceneID, ok = scene.(int); !ok {
|
||||||
|
panic("scene must be int")
|
||||||
|
}
|
||||||
|
default:
|
||||||
}
|
}
|
||||||
|
|
||||||
return tq
|
return tq
|
||||||
@@ -97,17 +105,25 @@ func NewTmpQrRequest(exp time.Duration, scene interface{}) *Request {
|
|||||||
|
|
||||||
// NewLimitQrRequest 新建永久二维码请求实例
|
// NewLimitQrRequest 新建永久二维码请求实例
|
||||||
func NewLimitQrRequest(scene interface{}) *Request {
|
func NewLimitQrRequest(scene interface{}) *Request {
|
||||||
tq := &Request{}
|
var (
|
||||||
|
tq = &Request{}
|
||||||
|
ok bool
|
||||||
|
)
|
||||||
switch reflect.ValueOf(scene).Kind() {
|
switch reflect.ValueOf(scene).Kind() {
|
||||||
case reflect.String:
|
case reflect.String:
|
||||||
tq.ActionName = actionLimitStr
|
tq.ActionName = actionLimitStr
|
||||||
tq.ActionInfo.Scene.SceneStr = scene.(string)
|
if tq.ActionInfo.Scene.SceneStr, ok = scene.(string); !ok {
|
||||||
|
panic("scene must be string")
|
||||||
|
}
|
||||||
case reflect.Int, reflect.Int8, reflect.Int16,
|
case reflect.Int, reflect.Int8, reflect.Int16,
|
||||||
reflect.Int32, reflect.Int64,
|
reflect.Int32, reflect.Int64,
|
||||||
reflect.Uint, reflect.Uint8, reflect.Uint16,
|
reflect.Uint, reflect.Uint8, reflect.Uint16,
|
||||||
reflect.Uint32, reflect.Uint64:
|
reflect.Uint32, reflect.Uint64:
|
||||||
tq.ActionName = actionLimitID
|
tq.ActionName = actionLimitID
|
||||||
tq.ActionInfo.Scene.SceneID = scene.(int)
|
if tq.ActionInfo.Scene.SceneID, ok = scene.(int); !ok {
|
||||||
|
panic("scene must be int")
|
||||||
|
}
|
||||||
|
default:
|
||||||
}
|
}
|
||||||
|
|
||||||
return tq
|
return tq
|
||||||
|
|||||||
@@ -11,13 +11,13 @@ import (
|
|||||||
type MediaType string
|
type MediaType string
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// MediaTypeImage 媒体文件:图片
|
// MediaTypeImage 媒体文件:图片
|
||||||
MediaTypeImage MediaType = "image"
|
MediaTypeImage MediaType = "image"
|
||||||
// MediaTypeVoice 媒体文件:声音
|
// MediaTypeVoice 媒体文件:声音
|
||||||
MediaTypeVoice MediaType = "voice"
|
MediaTypeVoice MediaType = "voice"
|
||||||
// MediaTypeVideo 媒体文件:视频
|
// MediaTypeVideo 媒体文件:视频
|
||||||
MediaTypeVideo MediaType = "video"
|
MediaTypeVideo MediaType = "video"
|
||||||
// MediaTypeThumb 媒体文件:缩略图
|
// MediaTypeThumb 媒体文件:缩略图
|
||||||
MediaTypeThumb MediaType = "thumb"
|
MediaTypeThumb MediaType = "thumb"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -31,14 +31,14 @@ func NewSubscribe(context *context.Context) *Subscribe {
|
|||||||
|
|
||||||
// SubscribeMessage 发送的订阅消息内容
|
// SubscribeMessage 发送的订阅消息内容
|
||||||
type SubscribeMessage struct {
|
type SubscribeMessage struct {
|
||||||
ToUser string `json:"touser"` // 必须, 接受者OpenID
|
ToUser string `json:"touser"` // 必须,接受者 OpenID
|
||||||
TemplateID string `json:"template_id"` // 必须, 模版ID
|
TemplateID string `json:"template_id"` // 必须,模版 ID
|
||||||
Page string `json:"page,omitempty"` // 可选, 跳转网页时填写
|
Page string `json:"page,omitempty"` // 可选,跳转网页时填写
|
||||||
Data map[string]*SubscribeDataItem `json:"data"` // 必须, 模板数据
|
Data map[string]*SubscribeDataItem `json:"data"` // 必须,模板数据
|
||||||
MiniProgram struct {
|
MiniProgram struct {
|
||||||
AppID string `json:"appid"` // 所需跳转到的小程序 appid(该小程序 appid 必须与发模板消息的公众号是绑定关联关系)
|
AppID string `json:"appid"` // 所需跳转到的小程序 appid(该小程序 appid 必须与发模板消息的公众号是绑定关联关系)
|
||||||
PagePath string `json:"pagepath"` // 所需跳转到小程序的具体页面路径,支持带参数,(示例index?foo=bar)
|
PagePath string `json:"pagepath"` // 所需跳转到小程序的具体页面路径,支持带参数,(示例 index?foo=bar)
|
||||||
} `json:"miniprogram"` // 可选,跳转至小程序地址
|
} `json:"miniprogram"` // 可选,跳转至小程序地址
|
||||||
}
|
}
|
||||||
|
|
||||||
// SubscribeDataItem 模版内某个 .DATA 的值
|
// SubscribeDataItem 模版内某个 .DATA 的值
|
||||||
|
|||||||
@@ -29,17 +29,17 @@ func NewTemplate(context *context.Context) *Template {
|
|||||||
|
|
||||||
// TemplateMessage 发送的模板消息内容
|
// TemplateMessage 发送的模板消息内容
|
||||||
type TemplateMessage struct {
|
type TemplateMessage struct {
|
||||||
ToUser string `json:"touser"` // 必须, 接受者OpenID
|
ToUser string `json:"touser"` // 必须,接受者 OpenID
|
||||||
TemplateID string `json:"template_id"` // 必须, 模版ID
|
TemplateID string `json:"template_id"` // 必须,模版 ID
|
||||||
URL string `json:"url,omitempty"` // 可选, 用户点击后跳转的URL, 该URL必须处于开发者在公众平台网站中设置的域中
|
URL string `json:"url,omitempty"` // 可选,用户点击后跳转的 URL, 该 URL 必须处于开发者在公众平台网站中设置的域中
|
||||||
Color string `json:"color,omitempty"` // 可选, 整个消息的颜色, 可以不设置
|
Color string `json:"color,omitempty"` // 可选,整个消息的颜色,可以不设置
|
||||||
Data map[string]*TemplateDataItem `json:"data"` // 必须, 模板数据
|
Data map[string]*TemplateDataItem `json:"data"` // 必须,模板数据
|
||||||
ClientMsgID string `json:"client_msg_id,omitempty"` // 可选, 防重入ID
|
ClientMsgID string `json:"client_msg_id,omitempty"` // 可选,防重入 ID
|
||||||
|
|
||||||
MiniProgram struct {
|
MiniProgram struct {
|
||||||
AppID string `json:"appid"` // 所需跳转到的小程序 appid(该小程序 appid 必须与发模板消息的公众号是绑定关联关系)
|
AppID string `json:"appid"` // 所需跳转到的小程序 appid(该小程序 appid 必须与发模板消息的公众号是绑定关联关系)
|
||||||
PagePath string `json:"pagepath"` // 所需跳转到小程序的具体页面路径,支持带参数,(示例index?foo=bar)
|
PagePath string `json:"pagepath"` // 所需跳转到小程序的具体页面路径,支持带参数,(示例 index?foo=bar)
|
||||||
} `json:"miniprogram"` // 可选,跳转至小程序地址
|
} `json:"miniprogram"` // 可选,跳转至小程序地址
|
||||||
}
|
}
|
||||||
|
|
||||||
// TemplateDataItem 模版内某个 .DATA 的值
|
// TemplateDataItem 模版内某个 .DATA 的值
|
||||||
@@ -80,7 +80,7 @@ func (tpl *Template) Send(msg *TemplateMessage) (msgID int64, err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// TemplateItem 模板消息.
|
// TemplateItem 模板消息。
|
||||||
type TemplateItem struct {
|
type TemplateItem struct {
|
||||||
TemplateID string `json:"template_id"`
|
TemplateID string `json:"template_id"`
|
||||||
Title string `json:"title"`
|
Title string `json:"title"`
|
||||||
@@ -121,7 +121,7 @@ type resTemplateAdd struct {
|
|||||||
TemplateID string `json:"template_id"`
|
TemplateID string `json:"template_id"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add 添加模板.
|
// Add 添加模板。
|
||||||
func (tpl *Template) Add(shortID string, keyNameList []string) (templateID string, err error) {
|
func (tpl *Template) Add(shortID string, keyNameList []string) (templateID string, err error) {
|
||||||
var accessToken string
|
var accessToken string
|
||||||
accessToken, err = tpl.GetAccessToken()
|
accessToken, err = tpl.GetAccessToken()
|
||||||
@@ -144,7 +144,7 @@ func (tpl *Template) Add(shortID string, keyNameList []string) (templateID strin
|
|||||||
return result.TemplateID, err
|
return result.TemplateID, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete 删除私有模板.
|
// Delete 删除私有模板。
|
||||||
func (tpl *Template) Delete(templateID string) (err error) {
|
func (tpl *Template) Delete(templateID string) (err error) {
|
||||||
var accessToken string
|
var accessToken string
|
||||||
accessToken, err = tpl.GetAccessToken()
|
accessToken, err = tpl.GetAccessToken()
|
||||||
|
|||||||
@@ -161,7 +161,10 @@ func (user *User) ListUserOpenIDs(nextOpenid ...string) (*OpenidList, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
uri, _ := url.Parse(userListURL)
|
uri, err := url.Parse(userListURL)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
q := uri.Query()
|
q := uri.Query()
|
||||||
q.Set("access_token", accessToken)
|
q.Set("access_token", accessToken)
|
||||||
if len(nextOpenid) > 0 && nextOpenid[0] != "" {
|
if len(nextOpenid) > 0 && nextOpenid[0] != "" {
|
||||||
|
|||||||
@@ -221,7 +221,7 @@ func (basic *Basic) SetHeadImage(imgMediaID string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// SetHeadImageFull 修改小程序头像
|
// SetHeadImageFull 修改小程序头像
|
||||||
// 新增临时素材: https://developers.weixin.qq.com/doc/offiaccount/Asset_Management/New_temporary_materials.html
|
// 新增临时素材:https://developers.weixin.qq.com/doc/offiaccount/Asset_Management/New_temporary_materials.html
|
||||||
// ref: https://developers.weixin.qq.com/doc/oplatform/openApi/OpenApiDoc/miniprogram-management/basic-info-management/setHeadImage.html
|
// ref: https://developers.weixin.qq.com/doc/oplatform/openApi/OpenApiDoc/miniprogram-management/basic-info-management/setHeadImage.html
|
||||||
func (basic *Basic) SetHeadImageFull(param *SetHeadImageParam) error {
|
func (basic *Basic) SetHeadImageFull(param *SetHeadImageParam) error {
|
||||||
ak, err := basic.GetAuthrAccessToken(basic.AppID)
|
ak, err := basic.GetAuthrAccessToken(basic.AppID)
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ type GetRegistrationStatusParam struct {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetRegistrationStatus 查询创建任务状态.
|
// GetRegistrationStatus 查询创建任务状态。
|
||||||
func (component *Component) GetRegistrationStatus(param *GetRegistrationStatusParam) error {
|
func (component *Component) GetRegistrationStatus(param *GetRegistrationStatusParam) error {
|
||||||
componentAK, err := component.GetComponentAccessToken()
|
componentAK, err := component.GetComponentAccessToken()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ func EncryptMsg(random, rawXMLMsg []byte, appID, aesKey string) (encrtptMsg []by
|
|||||||
func AESEncryptMsg(random, rawXMLMsg []byte, appID string, aesKey []byte) (ciphertext []byte) {
|
func AESEncryptMsg(random, rawXMLMsg []byte, appID string, aesKey []byte) (ciphertext []byte) {
|
||||||
const (
|
const (
|
||||||
BlockSize = 32 // PKCS#7
|
BlockSize = 32 // PKCS#7
|
||||||
BlockMask = BlockSize - 1 // BLOCK_SIZE 为 2^n 时, 可以用 mask 获取针对 BLOCK_SIZE 的余数
|
BlockMask = BlockSize - 1 // BLOCK_SIZE 为 2^n 时,可以用 mask 获取针对 BLOCK_SIZE 的余数
|
||||||
)
|
)
|
||||||
|
|
||||||
appIDOffset := 20 + len(rawXMLMsg)
|
appIDOffset := 20 + len(rawXMLMsg)
|
||||||
@@ -127,7 +127,7 @@ func aesKeyDecode(encodedAESKey string) (key []byte, err error) {
|
|||||||
func AESDecryptMsg(ciphertext []byte, aesKey []byte) (random, rawXMLMsg, appID []byte, err error) {
|
func AESDecryptMsg(ciphertext []byte, aesKey []byte) (random, rawXMLMsg, appID []byte, err error) {
|
||||||
const (
|
const (
|
||||||
BlockSize = 32 // PKCS#7
|
BlockSize = 32 // PKCS#7
|
||||||
BlockMask = BlockSize - 1 // BLOCK_SIZE 为 2^n 时, 可以用 mask 获取针对 BLOCK_SIZE 的余数
|
BlockMask = BlockSize - 1 // BLOCK_SIZE 为 2^n 时,可以用 mask 获取针对 BLOCK_SIZE 的余数
|
||||||
)
|
)
|
||||||
|
|
||||||
if len(ciphertext) < BlockSize {
|
if len(ciphertext) < BlockSize {
|
||||||
|
|||||||
@@ -25,7 +25,10 @@ func RSADecrypt(privateKey string, ciphertext []byte) ([]byte, error) {
|
|||||||
}
|
}
|
||||||
switch t := key.(type) {
|
switch t := key.(type) {
|
||||||
case *rsa.PrivateKey:
|
case *rsa.PrivateKey:
|
||||||
priv = key.(*rsa.PrivateKey)
|
var ok bool
|
||||||
|
if priv, ok = key.(*rsa.PrivateKey); !ok {
|
||||||
|
return nil, fmt.Errorf(" ParsePKCS8PrivateKey error: Not supported privatekey format, should be *rsa.PrivateKey, got %T", t)
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
return nil, fmt.Errorf("ParsePKCS1PrivateKey error: %s, ParsePKCS8PrivateKey error: Not supported privatekey format, should be *rsa.PrivateKey, got %T", oldErr.Error(), t)
|
return nil, fmt.Errorf("ParsePKCS1PrivateKey error: %s, ParsePKCS8PrivateKey error: Not supported privatekey format, should be *rsa.PrivateKey, got %T", oldErr.Error(), t)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Template 对字符串中的和map的key相同的字符串进行模板替换 仅支持 形如: {name}
|
// Template 对字符串中的和 map 的 key 相同的字符串进行模板替换 仅支持 形如:{name}
|
||||||
func Template(source string, data map[string]interface{}) string {
|
func Template(source string, data map[string]interface{}) string {
|
||||||
sourceCopy := &source
|
sourceCopy := &source
|
||||||
for k, val := range data {
|
for k, val := range data {
|
||||||
|
|||||||
@@ -188,7 +188,7 @@ type UserGetResponse struct {
|
|||||||
} `json:"web,omitempty"`
|
} `json:"web,omitempty"`
|
||||||
} `json:"attrs"`
|
} `json:"attrs"`
|
||||||
} `json:"extattr"` // 扩展属性,代开发自建应用需要管理员授权才返回;第三方仅通讯录应用可获取;对于非第三方创建的成员,第三方通讯录应用也不可获取;上游企业不可获取下游企业成员该字段
|
} `json:"extattr"` // 扩展属性,代开发自建应用需要管理员授权才返回;第三方仅通讯录应用可获取;对于非第三方创建的成员,第三方通讯录应用也不可获取;上游企业不可获取下游企业成员该字段
|
||||||
Status int `json:"status"` // 激活状态: 1=已激活,2=已禁用,4=未激活,5=退出企业。 已激活代表已激活企业微信或已关注微信插件(原企业号)。未激活代表既未激活企业微信又未关注微信插件(原企业号)。
|
Status int `json:"status"` // 激活状态:1=已激活,2=已禁用,4=未激活,5=退出企业。已激活代表已激活企业微信或已关注微信插件(原企业号)。未激活代表既未激活企业微信又未关注微信插件(原企业号)。
|
||||||
QrCode string `json:"qr_code"` // 员工个人二维码,扫描可添加为外部联系人 (注意返回的是一个 url,可在浏览器上打开该 url 以展示二维码);代开发自建应用需要管理员授权且成员 oauth2 授权获取;第三方仅通讯录应用可获取;对于非第三方创建的成员,第三方通讯录应用也不可获取;上游企业不可获取下游企业成员该字段
|
QrCode string `json:"qr_code"` // 员工个人二维码,扫描可添加为外部联系人 (注意返回的是一个 url,可在浏览器上打开该 url 以展示二维码);代开发自建应用需要管理员授权且成员 oauth2 授权获取;第三方仅通讯录应用可获取;对于非第三方创建的成员,第三方通讯录应用也不可获取;上游企业不可获取下游企业成员该字段
|
||||||
ExternalPosition string `json:"external_position"` // 对外职务,如果设置了该值,则以此作为对外展示的职务,否则以 position 来展示。代开发自建应用需要管理员授权才返回;第三方仅通讯录应用可获取;对于非第三方创建的成员,第三方通讯录应用也不可获取;上游企业不可获取下游企业成员该字段
|
ExternalPosition string `json:"external_position"` // 对外职务,如果设置了该值,则以此作为对外展示的职务,否则以 position 来展示。代开发自建应用需要管理员授权才返回;第三方仅通讯录应用可获取;对于非第三方创建的成员,第三方通讯录应用也不可获取;上游企业不可获取下游企业成员该字段
|
||||||
ExternalProfile struct {
|
ExternalProfile struct {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Package appchat 应用发送消息到群聊会话,企业微信接口:https://developer.work.weixin.qq.com/document/path/90248
|
// Package appchat 应用发送消息到群聊会话,企业微信接口:https://developer.work.weixin.qq.com/document/path/90248
|
||||||
package appchat
|
package appchat
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import (
|
|||||||
// Config for 企业微信
|
// Config for 企业微信
|
||||||
type Config struct {
|
type Config struct {
|
||||||
CorpID string `json:"corp_id"` // corp_id
|
CorpID string `json:"corp_id"` // corp_id
|
||||||
CorpSecret string `json:"corp_secret"` // corp_secret,如果需要获取会话存档实例,当前参数请填写聊天内容存档的Secret,可以在企业微信管理端--管理工具--聊天内容存档查看
|
CorpSecret string `json:"corp_secret"` // corp_secret,如果需要获取会话存档实例,当前参数请填写聊天内容存档的 Secret,可以在企业微信管理端--管理工具--聊天内容存档查看
|
||||||
AgentID string `json:"agent_id"` // agent_id
|
AgentID string `json:"agent_id"` // agent_id
|
||||||
Cache cache.Cache
|
Cache cache.Cache
|
||||||
RasPrivateKey string // 消息加密私钥,可以在企业微信管理端--管理工具--消息加密公钥查看对用公钥,私钥一般由自己保存
|
RasPrivateKey string // 消息加密私钥,可以在企业微信管理端--管理工具--消息加密公钥查看对用公钥,私钥一般由自己保存
|
||||||
|
|||||||
@@ -104,7 +104,7 @@ type WechatChannel struct {
|
|||||||
Source int `json:"source"`
|
Source int `json:"source"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// ExternalProfile 外部联系人的自定义展示信息,可以有多个字段和多种类型,包括文本,网页和小程序
|
// ExternalProfile 外部联系人的自定义展示信息,可以有多个字段和多种类型,包括文本,网页和小程序
|
||||||
type ExternalProfile struct {
|
type ExternalProfile struct {
|
||||||
ExternalCorpName string `json:"external_corp_name"`
|
ExternalCorpName string `json:"external_corp_name"`
|
||||||
WechatChannels WechatChannels `json:"wechat_channels"`
|
WechatChannels WechatChannels `json:"wechat_channels"`
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ const groupChatURL = "https://qyapi.weixin.qq.com/cgi-bin/externalcontact/groupc
|
|||||||
type (
|
type (
|
||||||
// AddJoinWayRequest 添加群配置请求参数
|
// AddJoinWayRequest 添加群配置请求参数
|
||||||
AddJoinWayRequest struct {
|
AddJoinWayRequest struct {
|
||||||
Scene int `json:"scene"` // 必填 1 - 群的小程序插件,2 - 群的二维码插件
|
Scene int `json:"scene"` // 必填 1 - 群的小程序插件,2 - 群的二维码插件
|
||||||
Remark string `json:"remark"` //非必填 联系方式的备注信息,用于助记,超过 30 个字符将被截断
|
Remark string `json:"remark"` //非必填 联系方式的备注信息,用于助记,超过 30 个字符将被截断
|
||||||
AutoCreateRoom int `json:"auto_create_room"` //非必填 当群满了后,是否自动新建群。0-否;1-是。默认为 1
|
AutoCreateRoom int `json:"auto_create_room"` //非必填 当群满了后,是否自动新建群。0-否;1-是。默认为 1
|
||||||
RoomBaseName string `json:"room_base_name"` //非必填 自动建群的群名前缀,当 auto_create_room 为 1 时有效。最长 40 个 utf8 字符
|
RoomBaseName string `json:"room_base_name"` //非必填 自动建群的群名前缀,当 auto_create_room 为 1 时有效。最长 40 个 utf8 字符
|
||||||
@@ -96,7 +96,7 @@ func (r *Client) GetJoinWay(req *JoinWayConfigRequest) (*GetJoinWayResponse, err
|
|||||||
// UpdateJoinWayRequest 更新群配置的请求参数
|
// UpdateJoinWayRequest 更新群配置的请求参数
|
||||||
type UpdateJoinWayRequest struct {
|
type UpdateJoinWayRequest struct {
|
||||||
ConfigID string `json:"config_id"`
|
ConfigID string `json:"config_id"`
|
||||||
Scene int `json:"scene"` // 必填 1 - 群的小程序插件,2 - 群的二维码插件
|
Scene int `json:"scene"` // 必填 1 - 群的小程序插件,2 - 群的二维码插件
|
||||||
Remark string `json:"remark"` //非必填 联系方式的备注信息,用于助记,超过 30 个字符将被截断
|
Remark string `json:"remark"` //非必填 联系方式的备注信息,用于助记,超过 30 个字符将被截断
|
||||||
AutoCreateRoom int `json:"auto_create_room"` //非必填 当群满了后,是否自动新建群。0-否;1-是。默认为 1
|
AutoCreateRoom int `json:"auto_create_room"` //非必填 当群满了后,是否自动新建群。0-否;1-是。默认为 1
|
||||||
RoomBaseName string `json:"room_base_name"` //非必填 自动建群的群名前缀,当 auto_create_room 为 1 时有效。最长 40 个 utf8 字符
|
RoomBaseName string `json:"room_base_name"` //非必填 自动建群的群名前缀,当 auto_create_room 为 1 时有效。最长 40 个 utf8 字符
|
||||||
|
|||||||
@@ -22,8 +22,8 @@ const (
|
|||||||
|
|
||||||
// AccountAddOptions 添加客服账号请求参数
|
// AccountAddOptions 添加客服账号请求参数
|
||||||
type AccountAddOptions struct {
|
type AccountAddOptions struct {
|
||||||
Name string `json:"name"` // 客服帐号名称, 不多于16个字符
|
Name string `json:"name"` // 客服帐号名称,不多于 16 个字符
|
||||||
MediaID string `json:"media_id"` // 客服头像临时素材。可以调用上传临时素材接口获取, 不多于128个字节
|
MediaID string `json:"media_id"` // 客服头像临时素材。可以调用上传临时素材接口获取,不多于 128 个字节
|
||||||
}
|
}
|
||||||
|
|
||||||
// AccountAddSchema 添加客服账号响应内容
|
// AccountAddSchema 添加客服账号响应内容
|
||||||
@@ -82,8 +82,8 @@ func (r *Client) AccountDel(options AccountDelOptions) (info util.CommonError, e
|
|||||||
// AccountUpdateOptions 修改客服账号请求参数
|
// AccountUpdateOptions 修改客服账号请求参数
|
||||||
type AccountUpdateOptions struct {
|
type AccountUpdateOptions struct {
|
||||||
OpenKFID string `json:"open_kfid"` // 客服帐号 ID, 不多于 64 字节
|
OpenKFID string `json:"open_kfid"` // 客服帐号 ID, 不多于 64 字节
|
||||||
Name string `json:"name"` // 客服帐号名称, 不多于16个字符
|
Name string `json:"name"` // 客服帐号名称,不多于 16 个字符
|
||||||
MediaID string `json:"media_id"` // 客服头像临时素材。可以调用上传临时素材接口获取, 不多于128个字节
|
MediaID string `json:"media_id"` // 客服头像临时素材。可以调用上传临时素材接口获取,不多于 128 个字节
|
||||||
}
|
}
|
||||||
|
|
||||||
// AccountUpdate 修复客服账号
|
// AccountUpdate 修复客服账号
|
||||||
@@ -148,7 +148,7 @@ func (r *Client) AccountList() (info AccountListSchema, err error) {
|
|||||||
// 3.返回的客服链接,不能修改或复制参数到其他链接使用。否则进入会话事件参数校验不通过,导致无法回调。
|
// 3.返回的客服链接,不能修改或复制参数到其他链接使用。否则进入会话事件参数校验不通过,导致无法回调。
|
||||||
type AddContactWayOptions struct {
|
type AddContactWayOptions struct {
|
||||||
OpenKFID string `json:"open_kfid"` // 客服帐号 ID, 不多于 64 字节
|
OpenKFID string `json:"open_kfid"` // 客服帐号 ID, 不多于 64 字节
|
||||||
Scene string `json:"scene"` // 场景值,字符串类型,由开发者自定义, 不多于32字节, 字符串取值范围(正则表达式):[0-9a-zA-Z_-]*
|
Scene string `json:"scene"` // 场景值,字符串类型,由开发者自定义,不多于 32 字节,字符串取值范围 (正则表达式):[0-9a-zA-Z_-]*
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddContactWaySchema 获取客服账号链接响应内容
|
// AddContactWaySchema 获取客服账号链接响应内容
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ type CustomerSchema struct {
|
|||||||
NickName string `json:"nickname"` // 微信昵称
|
NickName string `json:"nickname"` // 微信昵称
|
||||||
Avatar string `json:"avatar"` // 微信头像。第三方不可获取
|
Avatar string `json:"avatar"` // 微信头像。第三方不可获取
|
||||||
Gender int `json:"gender"` // 性别
|
Gender int `json:"gender"` // 性别
|
||||||
UnionID string `json:"unionid"` // unionid,需要绑定微信开发者帐号才能获取到,查看绑定方法: https://open.work.weixin.qq.com/kf/doc/92512/93143/94769#%E5%A6%82%E4%BD%95%E8%8E%B7%E5%8F%96%E5%BE%AE%E4%BF%A1%E5%AE%A2%E6%88%B7%E7%9A%84unionid
|
UnionID string `json:"unionid"` // unionid,需要绑定微信开发者帐号才能获取到,查看绑定方法:https://open.work.weixin.qq.com/kf/doc/92512/93143/94769#%E5%A6%82%E4%BD%95%E8%8E%B7%E5%8F%96%E5%BE%AE%E4%BF%A1%E5%AE%A2%E6%88%B7%E7%9A%84unionid
|
||||||
}
|
}
|
||||||
|
|
||||||
// CustomerBatchGetSchema 获取客户基本信息响应内容
|
// CustomerBatchGetSchema 获取客户基本信息响应内容
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ const (
|
|||||||
// SDKDecryptMSGFailed 错误码:40016
|
// SDKDecryptMSGFailed 错误码:40016
|
||||||
SDKDecryptMSGFailed Error = "消息解密失败"
|
SDKDecryptMSGFailed Error = "消息解密失败"
|
||||||
// SDKMediaIDExceedMinLength 错误码:40058
|
// SDKMediaIDExceedMinLength 错误码:40058
|
||||||
SDKMediaIDExceedMinLength Error = "不合法的参数, 请参照具体 API 接口说明进行传参"
|
SDKMediaIDExceedMinLength Error = "不合法的参数,请参照具体 API 接口说明进行传参"
|
||||||
// SDKContentContainsSensitiveInformation 错误码:40201
|
// SDKContentContainsSensitiveInformation 错误码:40201
|
||||||
SDKContentContainsSensitiveInformation Error = "当前客服账号由于涉及敏感信息,已被封禁,请联系企业微信客服处理"
|
SDKContentContainsSensitiveInformation Error = "当前客服账号由于涉及敏感信息,已被封禁,请联系企业微信客服处理"
|
||||||
// SDKAccessTokenMissing 错误码:41001
|
// SDKAccessTokenMissing 错误码:41001
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ const (
|
|||||||
// SendMsgSchema 发送消息响应内容
|
// SendMsgSchema 发送消息响应内容
|
||||||
type SendMsgSchema struct {
|
type SendMsgSchema struct {
|
||||||
util.CommonError
|
util.CommonError
|
||||||
MsgID string `json:"msgid"` // 消息ID。如果请求参数指定了msgid,则原样返回,否则系统自动生成并返回。不多于32字节, 字符串取值范围(正则表达式):[0-9a-zA-Z_-]*
|
MsgID string `json:"msgid"` // 消息 ID。如果请求参数指定了 msgid,则原样返回,否则系统自动生成并返回。不多于 32 字节,字符串取值范围 (正则表达式):[0-9a-zA-Z_-]*
|
||||||
}
|
}
|
||||||
|
|
||||||
// SendMsg 发送消息
|
// SendMsg 发送消息
|
||||||
|
|||||||
@@ -83,35 +83,35 @@ type Menu struct {
|
|||||||
MsgMenu struct {
|
MsgMenu struct {
|
||||||
HeadContent string `json:"head_content"` // 消息内容,不多于 1024 字节
|
HeadContent string `json:"head_content"` // 消息内容,不多于 1024 字节
|
||||||
List []interface{} `json:"list"` // 菜单项配置,不能多余 10 个
|
List []interface{} `json:"list"` // 菜单项配置,不能多余 10 个
|
||||||
TailContent string `json:"tail_content"` // 结束文本, 不多于1024字
|
TailContent string `json:"tail_content"` // 结束文本,不多于 1024 字
|
||||||
} `json:"msgmenu"`
|
} `json:"msgmenu"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// MenuClick 回复菜单
|
// MenuClick 回复菜单
|
||||||
type MenuClick struct {
|
type MenuClick struct {
|
||||||
Type string `json:"type"` // 菜单类型: click 回复菜单
|
Type string `json:"type"` // 菜单类型:click 回复菜单
|
||||||
Click struct {
|
Click struct {
|
||||||
ID string `json:"id"` // 菜单ID, 不少于1字节, 不多于64字节
|
ID string `json:"id"` // 菜单 ID, 不少于 1 字节,不多于 64 字节
|
||||||
Content string `json:"content"` // 菜单显示内容, 不少于1字节, 不多于128字节
|
Content string `json:"content"` // 菜单显示内容,不少于 1 字节,不多于 128 字节
|
||||||
} `json:"click"`
|
} `json:"click"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// MenuView 超链接菜单
|
// MenuView 超链接菜单
|
||||||
type MenuView struct {
|
type MenuView struct {
|
||||||
Type string `json:"type"` // 菜单类型: view 超链接菜单
|
Type string `json:"type"` // 菜单类型:view 超链接菜单
|
||||||
View struct {
|
View struct {
|
||||||
URL string `json:"url"` // 点击后跳转的链接, 不少于1字节, 不多于2048字节
|
URL string `json:"url"` // 点击后跳转的链接,不少于 1 字节,不多于 2048 字节
|
||||||
Content string `json:"content"` // 菜单显示内容, 不少于1字节, 不多于1024字节
|
Content string `json:"content"` // 菜单显示内容,不少于 1 字节,不多于 1024 字节
|
||||||
} `json:"view"`
|
} `json:"view"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// MenuMiniProgram 小程序菜单
|
// MenuMiniProgram 小程序菜单
|
||||||
type MenuMiniProgram struct {
|
type MenuMiniProgram struct {
|
||||||
Type string `json:"type"` // 菜单类型: miniprogram 小程序菜单
|
Type string `json:"type"` // 菜单类型:miniprogram 小程序菜单
|
||||||
MiniProgram struct {
|
MiniProgram struct {
|
||||||
AppID string `json:"appid"` // 小程序appid, 不少于1字节, 不多于32字节
|
AppID string `json:"appid"` // 小程序 appid, 不少于 1 字节,不多于 32 字节
|
||||||
PagePath string `json:"pagepath"` // 点击后进入的小程序页面, 不少于1字节, 不多于1024字节
|
PagePath string `json:"pagepath"` // 点击后进入的小程序页面,不少于 1 字节,不多于 1024 字节
|
||||||
Content string `json:"content"` // 菜单显示内容, 不少于1字节, 不多于1024字节
|
Content string `json:"content"` // 菜单显示内容,不少于 1 字节,不多于 1024 字节
|
||||||
} `json:"miniprogram"`
|
} `json:"miniprogram"`
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -120,8 +120,8 @@ type Location struct {
|
|||||||
Message
|
Message
|
||||||
MsgType string `json:"msgtype"` // 消息类型,此时固定为:location
|
MsgType string `json:"msgtype"` // 消息类型,此时固定为:location
|
||||||
Location struct {
|
Location struct {
|
||||||
Latitude float32 `json:"latitude"` // 纬度, 浮点数,范围为90 ~ -90
|
Latitude float32 `json:"latitude"` // 纬度,浮点数,范围为 90 ~ -90
|
||||||
Longitude float32 `json:"longitude"` // 经度, 浮点数,范围为180 ~ -180
|
Longitude float32 `json:"longitude"` // 经度,浮点数,范围为 180 ~ -180
|
||||||
Name string `json:"name"` // 位置名
|
Name string `json:"name"` // 位置名
|
||||||
Address string `json:"address"` // 地址详情说明
|
Address string `json:"address"` // 地址详情说明
|
||||||
} `json:"location"`
|
} `json:"location"`
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ const (
|
|||||||
// SendMsgOnEventSchema 发送事件响应消息
|
// SendMsgOnEventSchema 发送事件响应消息
|
||||||
type SendMsgOnEventSchema struct {
|
type SendMsgOnEventSchema struct {
|
||||||
util.CommonError
|
util.CommonError
|
||||||
MsgID string `json:"msgid"` // 消息ID。如果请求参数指定了msgid,则原样返回,否则系统自动生成并返回。不多于32字节, 字符串取值范围(正则表达式):[0-9a-zA-Z_-]*
|
MsgID string `json:"msgid"` // 消息 ID。如果请求参数指定了 msgid,则原样返回,否则系统自动生成并返回。不多于 32 字节,字符串取值范围 (正则表达式):[0-9a-zA-Z_-]*
|
||||||
}
|
}
|
||||||
|
|
||||||
// SendMsgOnEvent 发送事件响应消息
|
// SendMsgOnEvent 发送事件响应消息
|
||||||
|
|||||||
@@ -22,34 +22,34 @@ type Menu struct {
|
|||||||
MsgMenu struct {
|
MsgMenu struct {
|
||||||
HeadContent string `json:"head_content"` // 消息内容,不多于 1024 字节
|
HeadContent string `json:"head_content"` // 消息内容,不多于 1024 字节
|
||||||
List []interface{} `json:"list"` // 菜单项配置,不能多余 10 个
|
List []interface{} `json:"list"` // 菜单项配置,不能多余 10 个
|
||||||
TailContent string `json:"tail_content"` // 结束文本, 不多于1024字
|
TailContent string `json:"tail_content"` // 结束文本,不多于 1024 字
|
||||||
} `json:"msgmenu"`
|
} `json:"msgmenu"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// MenuClick 回复菜单
|
// MenuClick 回复菜单
|
||||||
type MenuClick struct {
|
type MenuClick struct {
|
||||||
Type string `json:"type"` // 菜单类型: click 回复菜单
|
Type string `json:"type"` // 菜单类型:click 回复菜单
|
||||||
Click struct {
|
Click struct {
|
||||||
ID string `json:"id"` // 菜单ID, 不少于1字节, 不多于64字节
|
ID string `json:"id"` // 菜单 ID, 不少于 1 字节,不多于 64 字节
|
||||||
Content string `json:"content"` // 菜单显示内容, 不少于1字节, 不多于128字节
|
Content string `json:"content"` // 菜单显示内容,不少于 1 字节,不多于 128 字节
|
||||||
} `json:"click"`
|
} `json:"click"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// MenuView 超链接菜单
|
// MenuView 超链接菜单
|
||||||
type MenuView struct {
|
type MenuView struct {
|
||||||
Type string `json:"type"` // 菜单类型: view 超链接菜单
|
Type string `json:"type"` // 菜单类型:view 超链接菜单
|
||||||
View struct {
|
View struct {
|
||||||
URL string `json:"url"` // 点击后跳转的链接, 不少于1字节, 不多于2048字节
|
URL string `json:"url"` // 点击后跳转的链接,不少于 1 字节,不多于 2048 字节
|
||||||
Content string `json:"content"` // 菜单显示内容, 不少于1字节, 不多于1024字节
|
Content string `json:"content"` // 菜单显示内容,不少于 1 字节,不多于 1024 字节
|
||||||
} `json:"view"`
|
} `json:"view"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// MenuMiniProgram 小程序菜单
|
// MenuMiniProgram 小程序菜单
|
||||||
type MenuMiniProgram struct {
|
type MenuMiniProgram struct {
|
||||||
Type string `json:"type"` // 菜单类型: miniprogram 小程序菜单
|
Type string `json:"type"` // 菜单类型:miniprogram 小程序菜单
|
||||||
MiniProgram struct {
|
MiniProgram struct {
|
||||||
AppID string `json:"appid"` // 小程序appid, 不少于1字节, 不多于32字节
|
AppID string `json:"appid"` // 小程序 appid, 不少于 1 字节,不多于 32 字节
|
||||||
PagePath string `json:"pagepath"` // 点击后进入的小程序页面, 不少于1字节, 不多于1024字节
|
PagePath string `json:"pagepath"` // 点击后进入的小程序页面,不少于 1 字节,不多于 1024 字节
|
||||||
Content string `json:"content"` // 菜单显示内容, 不少于1字节, 不多于1024字节
|
Content string `json:"content"` // 菜单显示内容,不少于 1 字节,不多于 1024 字节
|
||||||
} `json:"miniprogram"`
|
} `json:"miniprogram"`
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -80,7 +80,7 @@ type ReceptionistListSchema struct {
|
|||||||
util.CommonError
|
util.CommonError
|
||||||
ReceptionistList []struct {
|
ReceptionistList []struct {
|
||||||
UserID string `json:"userid"` // 接待人员的 userid。第三方应用获取到的为密文 userid,即 open_userid
|
UserID string `json:"userid"` // 接待人员的 userid。第三方应用获取到的为密文 userid,即 open_userid
|
||||||
Status int `json:"status"` // 接待人员的接待状态。0:接待中,1:停止接待。第三方应用需具有“管理帐号、分配会话和收发消息”权限才可获取
|
Status int `json:"status"` // 接待人员的接待状态。0:接待中,1:停止接待。第三方应用需具有“管理帐号、分配会话和收发消息”权限才可获取
|
||||||
} `json:"servicer_list"`
|
} `json:"servicer_list"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -16,8 +16,8 @@ const (
|
|||||||
|
|
||||||
// SyncMsgOptions 获取消息查询参数
|
// SyncMsgOptions 获取消息查询参数
|
||||||
type SyncMsgOptions struct {
|
type SyncMsgOptions struct {
|
||||||
Cursor string `json:"cursor"` // 上一次调用时返回的next_cursor,第一次拉取可以不填, 不多于64字节
|
Cursor string `json:"cursor"` // 上一次调用时返回的 next_cursor,第一次拉取可以不填,不多于 64 字节
|
||||||
Token string `json:"token"` // 回调事件返回的token字段,10分钟内有效;可不填,如果不填接口有严格的频率限制, 不多于128字节
|
Token string `json:"token"` // 回调事件返回的 token 字段,10 分钟内有效;可不填,如果不填接口有严格的频率限制,不多于 128 字节
|
||||||
Limit uint `json:"limit"` // 期望请求的数据量,默认值和最大值都为 1000, 注意:可能会出现返回条数少于 limit 的情况,需结合返回的 has_more 字段判断是否继续请求。
|
Limit uint `json:"limit"` // 期望请求的数据量,默认值和最大值都为 1000, 注意:可能会出现返回条数少于 limit 的情况,需结合返回的 has_more 字段判断是否继续请求。
|
||||||
VoiceFormat uint `json:"voice_format,omitempty"` // 语音消息类型,0-Amr 1-Silk,默认 0。可通过该参数控制返回的语音格式,开发者可按需选择自己程序支持的一种格式
|
VoiceFormat uint `json:"voice_format,omitempty"` // 语音消息类型,0-Amr 1-Silk,默认 0。可通过该参数控制返回的语音格式,开发者可按需选择自己程序支持的一种格式
|
||||||
OpenKfID string `json:"open_kfid,omitempty"` // 指定拉取某个客服帐号的消息,否则默认返回有权限的客服帐号的消息。当客服帐号较多,建议按 open_kfid 来拉取以获取更好的性能。
|
OpenKfID string `json:"open_kfid,omitempty"` // 指定拉取某个客服帐号的消息,否则默认返回有权限的客服帐号的消息。当客服帐号较多,建议按 open_kfid 来拉取以获取更好的性能。
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Package message 消息推送,实现企业微信消息推送相关接口:https://developer.work.weixin.qq.com/document/path/90235
|
// Package message 消息推送,实现企业微信消息推送相关接口:https://developer.work.weixin.qq.com/document/path/90235
|
||||||
package message
|
package message
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ type ChatData struct {
|
|||||||
MsgID string `json:"msgid,omitempty"` // 消息 id,消息的唯一标识,企业可以使用此字段进行消息去重。
|
MsgID string `json:"msgid,omitempty"` // 消息 id,消息的唯一标识,企业可以使用此字段进行消息去重。
|
||||||
PublickeyVer uint32 `json:"publickey_ver,omitempty"` // 加密此条消息使用的公钥版本号。
|
PublickeyVer uint32 `json:"publickey_ver,omitempty"` // 加密此条消息使用的公钥版本号。
|
||||||
EncryptRandomKey string `json:"encrypt_random_key,omitempty"` // 使用 publickey_ver 指定版本的公钥进行非对称加密后 base64 加密的内容,需要业务方先 base64 decode 处理后,再使用指定版本的私钥进行解密,得出内容。
|
EncryptRandomKey string `json:"encrypt_random_key,omitempty"` // 使用 publickey_ver 指定版本的公钥进行非对称加密后 base64 加密的内容,需要业务方先 base64 decode 处理后,再使用指定版本的私钥进行解密,得出内容。
|
||||||
EncryptChatMsg string `json:"encrypt_chat_msg,omitempty"` // 消息密文。需要业务方使用将encrypt_random_key解密得到的内容,与encrypt_chat_msg,传入sdk接口DecryptData,得到消息明文。
|
EncryptChatMsg string `json:"encrypt_chat_msg,omitempty"` // 消息密文。需要业务方使用将 encrypt_random_key 解密得到的内容,与 encrypt_chat_msg,传入 sdk 接口 DecryptData,得到消息明文。
|
||||||
}
|
}
|
||||||
|
|
||||||
// ChatMessage 会话存档消息
|
// ChatMessage 会话存档消息
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ func (s *Client) Free() {
|
|||||||
* @param [in] proxy 使用代理的请求,需要传入代理的链接。如:socks5://10.0.0.1:8081 或者 http://10.0.0.1:8081
|
* @param [in] proxy 使用代理的请求,需要传入代理的链接。如:socks5://10.0.0.1:8081 或者 http://10.0.0.1:8081
|
||||||
* @param [in] passwd 代理账号密码,需要传入代理的账号密码。如 user_name:passwd_123
|
* @param [in] passwd 代理账号密码,需要传入代理的账号密码。如 user_name:passwd_123
|
||||||
* @param [in] timeout 超时时间,单位秒
|
* @param [in] timeout 超时时间,单位秒
|
||||||
* @return chatDatas 返回本次拉取消息的数据,slice结构体.内容包括errcode/errmsg,以及每条消息内容。示例如下:
|
* @return chatDatas 返回本次拉取消息的数据,slice 结构体。内容包括 errcode/errmsg,以及每条消息内容。示例如下:
|
||||||
|
|
||||||
{"errcode":0,"errmsg":"ok","chatdata":[{"seq":196,"msgid":"CAQQ2fbb4QUY0On2rYSAgAMgip/yzgs=","publickey_ver":3,"encrypt_random_key":"ftJ+uz3n/z1DsxlkwxNgE+mL38H42/KCvN8T60gbbtPD+Rta1hKTuQPzUzO6Hzne97MgKs7FfdDxDck/v8cDT6gUVjA2tZ/M7euSD0L66opJ/IUeBtpAtvgVSD5qhlaQjvfKJc/zPMGNK2xCLFYqwmQBZXbNT7uA69Fflm512nZKW/piK2RKdYJhRyvQnA1ISxK097sp9WlEgDg250fM5tgwMjujdzr7ehK6gtVBUFldNSJS7ndtIf6aSBfaLktZgwHZ57ONewWq8GJe7WwQf1hwcDbCh7YMG8nsweEwhDfUz+u8rz9an+0lgrYMZFRHnmzjgmLwrR7B/32Qxqd79A==","encrypt_chat_msg":"898WSfGMnIeytTsea7Rc0WsOocs0bIAerF6de0v2cFwqo9uOxrW9wYe5rCjCHHH5bDrNvLxBE/xOoFfcwOTYX0HQxTJaH0ES9OHDZ61p8gcbfGdJKnq2UU4tAEgGb8H+Q9n8syRXIjaI3KuVCqGIi4QGHFmxWenPFfjF/vRuPd0EpzUNwmqfUxLBWLpGhv+dLnqiEOBW41Zdc0OO0St6E+JeIeHlRZAR+E13Isv9eS09xNbF0qQXWIyNUi+ucLr5VuZnPGXBrSfvwX8f0QebTwpy1tT2zvQiMM2MBugKH6NuMzzuvEsXeD+6+3VRqL"}]}
|
{"errcode":0,"errmsg":"ok","chatdata":[{"seq":196,"msgid":"CAQQ2fbb4QUY0On2rYSAgAMgip/yzgs=","publickey_ver":3,"encrypt_random_key":"ftJ+uz3n/z1DsxlkwxNgE+mL38H42/KCvN8T60gbbtPD+Rta1hKTuQPzUzO6Hzne97MgKs7FfdDxDck/v8cDT6gUVjA2tZ/M7euSD0L66opJ/IUeBtpAtvgVSD5qhlaQjvfKJc/zPMGNK2xCLFYqwmQBZXbNT7uA69Fflm512nZKW/piK2RKdYJhRyvQnA1ISxK097sp9WlEgDg250fM5tgwMjujdzr7ehK6gtVBUFldNSJS7ndtIf6aSBfaLktZgwHZ57ONewWq8GJe7WwQf1hwcDbCh7YMG8nsweEwhDfUz+u8rz9an+0lgrYMZFRHnmzjgmLwrR7B/32Qxqd79A==","encrypt_chat_msg":"898WSfGMnIeytTsea7Rc0WsOocs0bIAerF6de0v2cFwqo9uOxrW9wYe5rCjCHHH5bDrNvLxBE/xOoFfcwOTYX0HQxTJaH0ES9OHDZ61p8gcbfGdJKnq2UU4tAEgGb8H+Q9n8syRXIjaI3KuVCqGIi4QGHFmxWenPFfjF/vRuPd0EpzUNwmqfUxLBWLpGhv+dLnqiEOBW41Zdc0OO0St6E+JeIeHlRZAR+E13Isv9eS09xNbF0qQXWIyNUi+ucLr5VuZnPGXBrSfvwX8f0QebTwpy1tT2zvQiMM2MBugKH6NuMzzuvEsXeD+6+3VRqL"}]}
|
||||||
*/
|
*/
|
||||||
@@ -122,7 +122,7 @@ func (s *Client) GetChatData(seq uint64, limit uint64, proxy string, passwd stri
|
|||||||
* @param [in] proxy 使用代理的请求,需要传入代理的链接。如:socks5://10.0.0.1:8081 或者 http://10.0.0.1:8081
|
* @param [in] proxy 使用代理的请求,需要传入代理的链接。如:socks5://10.0.0.1:8081 或者 http://10.0.0.1:8081
|
||||||
* @param [in] passwd 代理账号密码,需要传入代理的账号密码。如 user_name:passwd_123
|
* @param [in] passwd 代理账号密码,需要传入代理的账号密码。如 user_name:passwd_123
|
||||||
* @param [in] timeout 超时时间,单位秒
|
* @param [in] timeout 超时时间,单位秒
|
||||||
* @return chatDatas 返回本次拉取消息的数据,slice结构体.内容包括errcode/errmsg,以及每条消息内容。示例如下:
|
* @return chatDatas 返回本次拉取消息的数据,slice 结构体。内容包括 errcode/errmsg,以及每条消息内容。示例如下:
|
||||||
|
|
||||||
{"errcode":0,"errmsg":"ok","chatdata":[{"seq":196,"msgid":"CAQQ2fbb4QUY0On2rYSAgAMgip/yzgs=","publickey_ver":3,"encrypt_random_key":"ftJ+uz3n/z1DsxlkwxNgE+mL38H42/KCvN8T60gbbtPD+Rta1hKTuQPzUzO6Hzne97MgKs7FfdDxDck/v8cDT6gUVjA2tZ/M7euSD0L66opJ/IUeBtpAtvgVSD5qhlaQjvfKJc/zPMGNK2xCLFYqwmQBZXbNT7uA69Fflm512nZKW/piK2RKdYJhRyvQnA1ISxK097sp9WlEgDg250fM5tgwMjujdzr7ehK6gtVBUFldNSJS7ndtIf6aSBfaLktZgwHZ57ONewWq8GJe7WwQf1hwcDbCh7YMG8nsweEwhDfUz+u8rz9an+0lgrYMZFRHnmzjgmLwrR7B/32Qxqd79A==","encrypt_chat_msg":"898WSfGMnIeytTsea7Rc0WsOocs0bIAerF6de0v2cFwqo9uOxrW9wYe5rCjCHHH5bDrNvLxBE/xOoFfcwOTYX0HQxTJaH0ES9OHDZ61p8gcbfGdJKnq2UU4tAEgGb8H+Q9n8syRXIjaI3KuVCqGIi4QGHFmxWenPFfjF/vRuPd0EpzUNwmqfUxLBWLpGhv+dLnqiEOBW41Zdc0OO0St6E+JeIeHlRZAR+E13Isv9eS09xNbF0qQXWIyNUi+ucLr5VuZnPGXBrSfvwX8f0QebTwpy1tT2zvQiMM2MBugKH6NuMzzuvEsXeD+6+3VRqL"}]}
|
{"errcode":0,"errmsg":"ok","chatdata":[{"seq":196,"msgid":"CAQQ2fbb4QUY0On2rYSAgAMgip/yzgs=","publickey_ver":3,"encrypt_random_key":"ftJ+uz3n/z1DsxlkwxNgE+mL38H42/KCvN8T60gbbtPD+Rta1hKTuQPzUzO6Hzne97MgKs7FfdDxDck/v8cDT6gUVjA2tZ/M7euSD0L66opJ/IUeBtpAtvgVSD5qhlaQjvfKJc/zPMGNK2xCLFYqwmQBZXbNT7uA69Fflm512nZKW/piK2RKdYJhRyvQnA1ISxK097sp9WlEgDg250fM5tgwMjujdzr7ehK6gtVBUFldNSJS7ndtIf6aSBfaLktZgwHZ57ONewWq8GJe7WwQf1hwcDbCh7YMG8nsweEwhDfUz+u8rz9an+0lgrYMZFRHnmzjgmLwrR7B/32Qxqd79A==","encrypt_chat_msg":"898WSfGMnIeytTsea7Rc0WsOocs0bIAerF6de0v2cFwqo9uOxrW9wYe5rCjCHHH5bDrNvLxBE/xOoFfcwOTYX0HQxTJaH0ES9OHDZ61p8gcbfGdJKnq2UU4tAEgGb8H+Q9n8syRXIjaI3KuVCqGIi4QGHFmxWenPFfjF/vRuPd0EpzUNwmqfUxLBWLpGhv+dLnqiEOBW41Zdc0OO0St6E+JeIeHlRZAR+E13Isv9eS09xNbF0qQXWIyNUi+ucLr5VuZnPGXBrSfvwX8f0QebTwpy1tT2zvQiMM2MBugKH6NuMzzuvEsXeD+6+3VRqL"}]}
|
||||||
*/
|
*/
|
||||||
@@ -152,10 +152,10 @@ func (s *Client) GetRawChatData(seq uint64, limit uint64, proxy string, passwd s
|
|||||||
return data, err
|
return data, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// DecryptData 解析密文.企业微信自有解密内容
|
// DecryptData 解析密文。企业微信自有解密内容
|
||||||
/**
|
/**
|
||||||
* @brief 解析密文.企业微信自有解密内容
|
* @brief 解析密文。企业微信自有解密内容
|
||||||
* @param [in] encrypt_key, getchatdata返回的encrypt_random_key,使用企业自持对应版本秘钥RSA解密后的内容
|
* @param [in] encrypt_key, getchatdata 返回的 encrypt_random_key,使用企业自持对应版本秘钥 RSA 解密后的内容
|
||||||
* @param [in] encrypt_msg, getchatdata 返回的 encrypt_chat_msg
|
* @param [in] encrypt_msg, getchatdata 返回的 encrypt_chat_msg
|
||||||
* @param [out] msg, 解密的消息明文
|
* @param [out] msg, 解密的消息明文
|
||||||
* @return 返回是否调用成功
|
* @return 返回是否调用成功
|
||||||
@@ -219,7 +219,7 @@ func (s *Client) DecryptData(encryptRandomKey string, encryptMsg string) (msg Ch
|
|||||||
* @param [in] passwd 代理账号密码,需要传入代理的账号密码。如 user_name:passwd_123
|
* @param [in] passwd 代理账号密码,需要传入代理的账号密码。如 user_name:passwd_123
|
||||||
* @param [in] indexbuf 媒体消息分片拉取,需要填入每次拉取的索引信息。首次不需要填写,默认拉取 512k,后续每次调用只需要将上次调用返回的 outindexbuf 填入即可。
|
* @param [in] indexbuf 媒体消息分片拉取,需要填入每次拉取的索引信息。首次不需要填写,默认拉取 512k,后续每次调用只需要将上次调用返回的 outindexbuf 填入即可。
|
||||||
* @param [in] timeout 超时时间,单位秒
|
* @param [in] timeout 超时时间,单位秒
|
||||||
* @param [out] media_data 返回本次拉取的媒体数据.MediaData结构体.内容包括data(数据内容)/outindexbuf(下次索引)/is_finish(拉取完成标记)
|
* @param [out] media_data 返回本次拉取的媒体数据.MediaData 结构体。内容包括 data(数据内容)/outindexbuf(下次索引)/is_finish(拉取完成标记)
|
||||||
|
|
||||||
*
|
*
|
||||||
* @return 返回是否调用成功
|
* @return 返回是否调用成功
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ type WebhookSendResponse struct {
|
|||||||
|
|
||||||
// WebhookSendTextOption 机器人发送文本消息请求参数
|
// WebhookSendTextOption 机器人发送文本消息请求参数
|
||||||
type WebhookSendTextOption struct {
|
type WebhookSendTextOption struct {
|
||||||
MsgType string `json:"msgtype"` // 消息类型,此时固定为text
|
MsgType string `json:"msgtype"` // 消息类型,此时固定为 text
|
||||||
Text struct {
|
Text struct {
|
||||||
Content string `json:"content"` // 文本内容,最长不超过 2048 个字节,必须是 utf8 编码
|
Content string `json:"content"` // 文本内容,最长不超过 2048 个字节,必须是 utf8 编码
|
||||||
MentionedList []string `json:"mentioned_list"` // userid 的列表,提醒群中的指定成员 (@某个成员),@all 表示提醒所有人,如果开发者获取不到 userid,可以使用 mentioned_mobile_list
|
MentionedList []string `json:"mentioned_list"` // userid 的列表,提醒群中的指定成员 (@某个成员),@all 表示提醒所有人,如果开发者获取不到 userid,可以使用 mentioned_mobile_list
|
||||||
@@ -20,7 +20,7 @@ type WebhookSendTextOption struct {
|
|||||||
// WebhookSendMarkdownOption 机器人发送 markdown 消息请求参数
|
// WebhookSendMarkdownOption 机器人发送 markdown 消息请求参数
|
||||||
// 支持语法参考 https://developer.work.weixin.qq.com/document/path/91770
|
// 支持语法参考 https://developer.work.weixin.qq.com/document/path/91770
|
||||||
type WebhookSendMarkdownOption struct {
|
type WebhookSendMarkdownOption struct {
|
||||||
MsgType string `json:"msgtype"` // 消息类型,此时固定为markdown
|
MsgType string `json:"msgtype"` // 消息类型,此时固定为 markdown
|
||||||
Markdown struct {
|
Markdown struct {
|
||||||
Content string `json:"content"` // markdown 内容,最长不超过 4096 个字节,必须是 utf8 编码
|
Content string `json:"content"` // markdown 内容,最长不超过 4096 个字节,必须是 utf8 编码
|
||||||
} `json:"markdown"` // markdown 消息内容
|
} `json:"markdown"` // markdown 消息内容
|
||||||
@@ -28,7 +28,7 @@ type WebhookSendMarkdownOption struct {
|
|||||||
|
|
||||||
// WebhookSendImageOption 机器人发送图片消息请求参数
|
// WebhookSendImageOption 机器人发送图片消息请求参数
|
||||||
type WebhookSendImageOption struct {
|
type WebhookSendImageOption struct {
|
||||||
MsgType string `json:"msgtype"` // 消息类型,此时固定为image
|
MsgType string `json:"msgtype"` // 消息类型,此时固定为 image
|
||||||
Image struct {
|
Image struct {
|
||||||
Base64 string `json:"base64"` // 图片内容的 base64 编码
|
Base64 string `json:"base64"` // 图片内容的 base64 编码
|
||||||
MD5 string `json:"md5"` // 图片内容(base64 编码前)的 md5 值
|
MD5 string `json:"md5"` // 图片内容(base64 编码前)的 md5 值
|
||||||
@@ -37,7 +37,7 @@ type WebhookSendImageOption struct {
|
|||||||
|
|
||||||
// WebhookSendNewsOption 机器人发送图文消息请求参数
|
// WebhookSendNewsOption 机器人发送图文消息请求参数
|
||||||
type WebhookSendNewsOption struct {
|
type WebhookSendNewsOption struct {
|
||||||
MsgType string `json:"msgtype"` // 消息类型,此时固定为news
|
MsgType string `json:"msgtype"` // 消息类型,此时固定为 news
|
||||||
News struct {
|
News struct {
|
||||||
Articles []struct {
|
Articles []struct {
|
||||||
Title string `json:"title"` // 标题,不超过 128 个字节,超过会自动截断
|
Title string `json:"title"` // 标题,不超过 128 个字节,超过会自动截断
|
||||||
|
|||||||
Reference in New Issue
Block a user