Giter Site home page Giter Site logo

xen0n / go-workwx Goto Github PK

View Code? Open in Web Editor NEW
612.0 9.0 159.0 962 KB

a sensible WeCom (企业微信, Wechat Work, Work Weixin) SDK for Go

Home Page: https://godoc.org/github.com/xen0n/go-workwx

License: MIT License

Go 99.90% Shell 0.10%
sdk-go weixin weixin-sdk wechat-sdk work-weixin chinese wechat wechat-work golang golang-sdk

go-workwx's Introduction

go-workwx

GitHub go.mod Go version GitHub tag (latest by date) GitHub Workflow Status (develop branch) GitHub license info Go Report Card Go Reference GitHub Repo stars

本项目需要您的帮助!

import (
    "github.com/xen0n/go-workwx" // package workwx
)

A Work Weixin (a.k.a. Wechat Work) client SDK for Golang, that happens to be battle-tested and pretty serious about its types.

In production since late 2018, pushing all kinds of notifications and alerts in at least 2 of Qiniu's internal systems.

一个 Golang 企业微信客户端 SDK;碰巧在生产环境试炼过,还对类型很严肃。

自 2018 年末以来,在七牛至少 2 个内部系统运转至今,推送各种通知、告警。

English translation TODO for now, as the service covered here is not available outside of China (AFAIK).

Why another wheel?

工作中需要用 Go 实现一个简单的消息推送,想着找个开源库算了,然而现有唯一的开源企业微信 Golang SDK 代码质量不佳。只好自己写一个。

Update: 自从这个库写出来,已经过了很久;现在(2019.08)已经有三四个同类项目了。 不过看了看这些“竞品”,发现自己这个库的类型设计、公开接口、access token 处理等方面还不赖。 为什么人们总是喜欢写死请求 Host、用全局量、为拆包而拆包甚至不惜公开内部方法呢?

Supported Go versions

本库的 v1.x 分支最低支持到 go1.17

CI 会在 go1.17 和 Go 的当前稳定版本、上一个稳定版本上跑测试,只有测试全部通过才可能合并 PR。

Features

  • 包名短
  • 支持覆盖 API Host,用于自己拦一层网关、临时调试等等奇葩需求
  • 支持使用自定义 http.Client
  • access token 处理靠谱
    • 你可以直接就做 API 调用,会自动请求 access token
    • 你也可以一行代码起一个后台 access token 刷新 goroutine
    • 自带指数退避重试
  • 严肃对待类型、公开接口
    • 公开暴露接口最小化,两步构造出 WorkwxApp 对象,然后直接用
    • 刻意不暴露企业微信原始接口请求、响应类型
    • 后续可能会做一个 lowlevel 包暴露裸的 API 接口,但很可能不做
    • 不为多态而多态,宁可 SDK 内部重复代码,也保证一个接口一类动作,下游用户 static dispatch
    • 个别数据模型做了调整甚至重做(如 UserInfoRecipient),以鼓励 idiomatic Go 风格
    • 几乎不会越俎代庖,一言不合 panic现存的少数一些情况都是要修掉的。
  • 自带一个 workwxctl 命令行小工具帮助调试
    • 用起来不爽提 issue 让我知道你在想啥

详情看 godoc 文档,还提供 Examples 小段代码可以参考。

Supported APIs

  • 通讯录管理 (部分支持,见下)
  • 客户联系 (大部分支持,见下)
  • 微信客服 (部分支持,见下)
  • 应用管理
  • 消息发送 (全部支持)
  • 消息接收
  • 素材管理 (支持上传, 见下)
  • OA (大部分支持,见下)
  • 会话内容存档 (大部分支持,见下)
  • 企业微信登录接口 (code2Session)
  • 获取访问用户身份 (code2UserInfo)
通讯录管理 API
  • 成员管理
    • 创建成员
    • 读取成员 NOTE: 成员对外信息暂未实现
    • 更新成员
    • 删除成员
    • 批量删除成员
    • 获取部门成员
    • 获取部门成员详情
    • userid与openid互换
    • 二次验证
    • 邀请成员
    • 获取加入企业二维码
    • 手机号获取userid
    • 邮箱获取userid
    • 获取成员ID列表
  • 部门管理
    • 创建部门
    • 更新部门
    • 删除部门
    • 获取部门列表
    • 获取子部门ID列表
  • 标签管理
    • 创建标签
    • 更新标签名字
    • 删除标签
    • 获取标签成员
    • 增加标签成员
    • 删除标签成员
    • 获取标签列表
  • 异步批量接口
    • 增量更新成员
    • 全量覆盖成员
    • 全量覆盖部门
    • 获取异步任务结果
  • 通讯录回调通知
    • 成员变更通知
    • 部门变更通知
    • 标签变更通知
    • 异步任务完成通知
客户联系 API
  • 成员对外信息
  • 企业服务人员管理
    • 获取配置了客户联系功能的成员列表
    • 客户联系「联系我」管理
    • 客户群「加入群聊」管理
  • 客户管理
    • 获取客户列表
    • 获取客户详情
    • 批量获取客户详情
    • 修改客户备注信息
  • 客户群管理
    • 获取客户群列表
    • 获取客户群详情
    • 客户群opengid转换
  • 在职继承
    • 分配在职成员的客户
    • 查询客户接替状态
    • 分配在职成员的客户群
  • 离职继承
    • 获取待分配的离职成员列表
    • 分配离职成员的客户
    • 查询客户接替状态
    • 分配离职成员的客户群
  • 客户标签管理
    • 管理企业标签
    • 编辑客户企业标签
  • 客户分配
    • 获取离职成员列表
    • 分配在职或离职成员的客户
    • 查询客户接替结果
    • 分配离职成员的客户群
  • 变更回调通知
    • 添加企业客户事件
    • 编辑企业客户事件
    • 外部联系人免验证添加成员事件
    • 删除企业客户事件
    • 删除跟进成员事件
    • 客户接替失败事件
    • 客户群变更事件
  • 消息推送
    • 创建企业群发
    • 获取企业的全部群发记录
    • 发送新客户欢迎语
    • 入群欢迎语素材管理
微信客服 API
  • 客服账号管理
    • 添加客服账号
    • 删除客服账号
    • 修改客服账号
    • 获取客服账号列表
    • 获取客服账号链接
  • 接待人员管理
    • 添加接待人员
    • 删除接待人员
    • 获取接待人员列表
  • 会话分配与消息收发
    • 分配客服会话
    • 接收消息和事件
    • 发送消息
    • 发送欢迎语等事件响应消息
  • 「升级服务」配置
  • 其他基础信息获取
    • 获取客户基础信息
  • 统计管理
    • 获取「客户数据统计」企业汇总数据
    • 获取「客户数据统计」接待人员明细数据
  • 机器人管理
    • 知识库分组管理
    • 知识库问答管理
身份验证 API
  • 获取访问用户身份
应用管理 API
  • 获取应用
  • 设置应用
  • 自定义菜单
    • 创建菜单
    • 获取菜单
    • 删除菜单
消息发送 API
  • 发送应用消息
  • 接收消息
  • 发送消息到群聊会话
    • 创建群聊会话
    • 修改群聊会话
    • 获取群聊会话
    • 应用推送消息

消息类型

  • 文本消息
  • 图片消息
  • 语音消息
  • 视频消息
  • 文件消息
  • 文本卡片消息
  • 图文消息
  • 图文消息(mpnews)
  • markdown消息
  • 任务卡片消息
素材管理 API
  • 上传临时素材
  • 上传永久图片
  • 获取临时素材
  • 获取高清语音素材
OA API
  • 审批
    • 获取审批模板详情
    • 提交审批申请
    • 审批申请状态变化回调通知
    • 批量获取审批单号
    • 获取审批申请详情
    • 获取企业假期管理配置
    • 修改成员假期余额
会话内容存档 API
  • 获取会话内容存档开启成员列表
  • 获取会话同意情况
  • 客户同意进行聊天内容存档事件回调
  • 获取会话内容存档内部群信息

Notes

关于保密消息发送

Markdown 等类型消息目前不支持作为保密消息发送,强行发送会报错。 那么为何发送消息的方法还全部带着 isSafe 参数呢?

一方面,企业微信服务方完全可能在未来支持更多消息类型的保密发送,到时候不希望客户端代码重新编译; 另一方面,反正响应会报错,你也不会留着这种逻辑。因此不改了。

License

Stargazers over time

Stargazers over time

go-workwx's People

Contributors

autodeploy-doc avatar bioshrek avatar bors[bot] avatar ch3rub1m avatar dependabot[bot] avatar eryajf avatar kanzihuang avatar nottwoc avatar qinhf3-l avatar rainzm avatar rudy-tao avatar tiger1103 avatar w3xse7en avatar xen0n avatar yoogoc avatar zhaikangqi avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

go-workwx's Issues

backoff包升级带来的问题

github.com/cenkalti/backoff/v4 v4.2.0 用的是go的1.18版本,里面用到了泛型。

我这边项目用的go版本是1.17,直接引用最新版的go-workwx是会报错的。

我看go-workwx用的也是1.17。

想问下 升级mod到4.2.0是因为什么呢?

SendTextCardMessage resp 疑问

建议优化下sendMessage的resp返回,目前是忽略的。在某些情况下会导致开发者无法获悉消息是否已经成功发出。比如:超出消息发送频率限制

`rx_message`里的rx是啥意思呀?

rx是啥的缩写呢,这个消息只是企业微信APP的消息吗?

我想复用这个结构实现处理 群机器人Webhook的回调消息。

// RxMessage 一条接收到的消息
type RxMessage struct {
	// FromUserID 发送者的 UserID
	FromUserID string
	// SendTime 消息发送时间
	SendTime time.Time
	// MsgType 消息类型
	MsgType MessageType
	// AgentID 企业应用 ID,可在应用的设置页面查看
	AgentID int64
	// Event 事件类型 MsgType为event存在
	Event EventType
	// ChangeType 变更类型 Event为change_external_contact存在
	ChangeType ChangeType
	extras messageKind
// --------- 类型变更  ---------------
	// MsgID 消息 ID, int64 --> string
	MsgID string
// ---------- 新增字段 ---------------
	// WebhookUrl 是否是webhook推送的消息
	WebhookUrl string
	// ChatType 消息类型
	ChatType ChatType
	// ChatID 消息 ID
	ChatID string

}

调研打赏(sponsor)方案

本项目是开源项目,作者业余时间维护,但作者公司内的使用场景只有这么多,近一年都没有动力去认真开发了。这可能影响到下游用户,毕竟不是所有公司的需求都一样。

调研一个可行的打赏方案。

可否支持在外部调用 token

例如提供一个 GetAccessToken 方法,因为有些接口包里面还没有支持,业务又急着要用,有点不太方便。感谢!

用户id 从哪里来的。

// send to user(s)
to1 := workwx.Recipient{
UserIDs: []string{"testuser"},
}

testuser 这个词 从哪里来的。用户id是要从企业微信的用户列表里取得的,go-workwx目前应该还没有这样的接口

支持发送消息到微信吗?

比如微信添加了我的企业微信机器人,那么机器人可以直接在微信回复消息吗?

企业微信机器人可以被邀请到微信群里吗?

问个问题

在企业微信后台创建的群聊,然后微信用户加入了,那么在这个群推送的消息,微信用户能接收到马?

需求收集

每层楼回复一个现在不支持的功能,想要就赞

不一定做

发企微消息提示: access_token missing

老哥,麻烦看下这个问题哈,采用自建应用发企微消息,过几天就自动出现: Code: 41001, Msg: "access_token missing, 这个提示了。
当前有三个自建应用,都是不同的企业,都是在http请求到了之后,在实例化weworkApp ,然后调用的

client := workwx.New(wk.CorpId)
app := client.WithApp(wk.Secret, wk.AgentId)
app.SpawnAccessTokenRefresherWithContext(ctx)

//下面开始发消息,

这样会有问题么? 麻烦老哥看到了,帮忙看下哈

没有使用文档

看来下文档,都是一些类的声明,函数的声明,请问应该怎么使用呢?从哪里开始呢?很迷茫

E2E tests

做了消息接收之后可以开工 E2E 集测,先记下来

允许自由替换Token生成逻辑

企业微信有内部应用与第三方应用两种,内部接口差不多一致,只是Token生成方式不一致,希望能把Token定义为interface,允许自由替换Token生成逻辑

Originally posted by @sssxxxzzz in #25 (comment)

如何获取应用菜单事件?

回调后端有收到消息,callback handler OnIncomingMessage没有解析到event message;
EventKey是应用菜单里用户自定义的值

能否提供debug的思路
还有扩展解析workwx.RxMessage新类型的方法

希望引入.gitattributes文件

Windows克隆下载之后.md文件的换行符是CRLF,导致用blackfriday解析表格(Table)变成了段落(Paragraph)

T<Document<0>>{ T=[T<Heading<1>>{ tC=[C<Text>] C=[C<Paragraph>{ tC=[C<Text>]}] T=[T<Heading<2>>{ tC=[C<Text>] C=[C<Paragraph>{ tC=[C<Text>]}] T=[T<Heading<3>>{ tC=[C<Code> C<Text>] C=[C<Paragraph>{ tC=[C<Text> C<Code> C<Text> C<Code> C<Text> C<Code> C<Text> C<Code> C<Text> C<Code> C<Text> C<Code> C<Text> C<Code> C<Text> C<Code> C<Text>]}]} T<Heading<3>>{ tC=[C<Code> C<Text>] C=[C<Paragraph>{ tC=[C<Text> C<Code> C<Text> C<Code> C<Text> C<Code> C<Text> C<Code> C<Text> C<Code> C<Text> C<Code> C<Text> C<Code> C<Text> C<Code> C<Text>]}]}]} T<Heading<2>>{ tC=[C<Text>] C=[C<Paragraph>{ tC=[C<Text> C<Code> C<Text> C<Code> C<Text> C<Code> C<Text> C<Code> C<Text> C<Code> C<Text> C<Code> C<Text> C<Code> C<Text> C<Code> C<Text>]}]}]}]}

image
将.md的换行符改成LF之后才能正常运行

T<Document<0>>{ T=[T<Heading<1>>{ tC=[C<Text>] T=[T<Heading<2>>{ tC=[C<Text>] T=[T<Heading<3>>{ tC=[C<Code> C<Text>] C=[C<Table>{ tC=[C<TableHead>{ tC=[C<TableRow>{ tC=[C<TableCell>{ tC=[C<Text>]} C<TableCell>{ tC=[C<Text>]} C<TableCell>{ tC=[C<Text>]}]}]} C<TableBody>{ tC=[C<TableRow>{ tC=[C<TableCell>{ tC=[C<Code>]} C<TableCell>{ tC=[C<Code>]} C<TableCell>{ tC=[C<Text>]}]} C<TableRow>{ tC=[C<TableCell>{ tC=[C<Code>]} C<TableCell>{ tC=[C<Code>]} C<TableCell>{ tC=[C<Text>]}]} C<TableRow>{ tC=[C<TableCell>{ tC=[C<Code>]} C<TableCell>{ tC=[C<Code>]} C<TableCell>{ tC=[C<Text>]}]} C<TableRow>{ tC=[C<TableCell>{ tC=[C<Code>]} C<TableCell>{ tC=[C<Code>]} C<TableCell>{ tC=[C<Text>]}]}]}]}]} T<Heading<3>>{ tC=[C<Code> C<Text>] C=[C<Table>{ tC=[C<TableHead>{ tC=[C<TableRow>{ tC=[C<TableCell>{ tC=[C<Text>]} C<TableCell>{ tC=[C<Text>]} C<TableCell>{ tC=[C<Text>]} C<TableCell>{ tC=[C<Text>]}]}]} C<TableBody>{ tC=[C<TableRow>{ tC=[C<TableCell>{ tC=[C<Code>]} C<TableCell>{ tC=[C<Code>]} C<TableCell>{ tC=[C<Text>]} C<TableCell>{ tC=[C<Code>]}]} C<TableRow>{ tC=[C<TableCell>{ tC=[C<Code>]} C<TableCell>{ tC=[C<Code>]} C<TableCell>{ tC=[C<Text>]} C<TableCell>{ tC=[C<Code>]}]}]}]} C<CodeBlock> C<CodeBlock>]}]} T<Heading<2>>{ tC=[C<Text>] C=[C<Table>{ tC=[C<TableHead>{ tC=[C<TableRow>{ tC=[C<TableCell>{ tC=[C<Text>]} C<TableCell>{ tC=[C<Text>]} C<TableCell>{ tC=[C<Text>]} C<TableCell>{ tC=[C<Text>]} C<TableCell>{ tC=[C<Text>]}]}]} C<TableBody>{ tC=[C<TableRow>{ tC=[C<TableCell>{ tC=[C<Code>]} C<TableCell>{ tC=[C<Code>]} C<TableCell>{ tC=[C<Code>]} C<TableCell>{ tC=[C<Text>]} C<TableCell>{ tC=[C<Code>]}]} C<TableRow>{ tC=[C<TableCell>{ tC=[C<Code>]} C<TableCell>{ tC=[C<Code>]} C<TableCell>{ tC=[C<Code>]} C<TableCell>{ tC=[C<Text>]} C<TableCell>{ tC=[C<Code>]}]}]}]}]}]}]}

image

针对我大Windows (-_-#)

Roadmap to v2

  • 切出 v2 分支
  • 提升最低 Go 版本要求,提升一些期待已久的依赖库版本
  • 开始引入 API-breaking changes #133
  • Tag RC
  • 等下游正面反馈
  • Release

在 tag 出 v2.0.0 之前不预期出现任何问题。如果有,及时过来冒泡

can not run example

./main.go:15:7: undefined: workwx.RxMessageHandler
./main.go:18:53: undefined: workwx.RxMessage
./main.go:31:13: undefined: workwx.NewHTTPHandler

支持企业微信私有化部署版本

企业微信同时也支持私有化部署版本:https://work.weixin.qq.com/server
从文档这里看代码大部分和企业微信都兼容,但是有一些不兼容的,也有一些是比较特有的接口。

请问这里如果提PR的话,是单独维护一个分支好呢,还是在现有代码上做一些兼容逻辑好呢?

希望能返回微信接口的响应

现在需要统计有哪些用户发送成功了,有哪些发送失败了,企业微信resp中给出了错误码和错误信息,但是框架没有做处理
go-workwx/message.go 235行:
// TODO: what to do with resp?
_ = resp

更新tag

现在 go get -u github.com/xen0n/go-workwxv0.1.1

少了一些方法:如 GetUserInfoByCode

send message to workwx response no error, but message did not deliver

in message.go

func (c *WorkwxApp) sendMessage(
recipient *Recipient,
msgtype string,
content map[string]interface{},
isSafe bool,
) error {
//...

if err != nil {
return err
}

    //return errmsg it not succeed
if resp.ErrCode != 0 {
	return fmt.Errorf("errcode:%d, errmsg:%s", resp.ErrCode, resp.ErrMsg)
}
return nil

}

素材上传报错44001

调用UploadTempFileMedia()接口上传素材,一直报44001的错误,empty media data。

	mediaFile, err := workwx.NewMediaFromFile(f)
	if err != nil {
		return
	}
	
	mediaUploadResp, err := client.UploadTempFileMedia(mediaFile)
	if err != nil {
		return
	}

如何自助保活goroutine

我在文档中发现了多个标记「该 goroutine 本身没有 keep-alive 逻辑,需要自助保活」的 API。请问对于这样的 API,应当如何进行自助保活呢?希望可以有更具体的解释。如果可以有代码片段的话就更好了。谢谢。

[PSA] 需要协同维护人手 / Co-maintainer needed

大家好,我是 go-workwx 作者,虽然经过一段时间的拖延(Sorry for that!),但现在总算想起向大家说明本项目的维护情况的时候了。

长懒看:本项目需要协同维护者,请有兴趣的贡献者在 issue 下自主评论。

本项目最初是为七牛的内部推送消息需求而写作。但之后的**互联网行业,私域运营风生水起,企业微信成为私域打法的重要一环;因此我相信,本项目的下游用户中,这些高级场景的占比甚至可能早已超过本项目的原始目标场景了。

正常而言,对于一个有公司参与成分的开源项目,贡献的主要来源应该是公司需求和个人用爱发电。但从这个项目的近两年发展来看,原作者的公司需求已经完全满足;原作者的“用爱发电”兴趣点早已不在业务。现实生活中认识本人的、以及偷窥过本人 GitHub 时间线的人应该都了解,本人近两年用来写代码的业余时间绝大部分都在做编译器、Linux 等项目的龙芯生态适配。作为“开源贡献者”的本人,早已不是合格的“业务系统开发者”了。

然而,对本项目的需求不可能停止,近一年的一些 issues 本人都无暇处理(忙着在各种上游写英语小作文),客观上我应该造成了本项目的开发停滞,这对下游而言是不负责任的。因此我认为,是时候交出适当的维护责任给适格的开发者了。

关于之后,可能整体上我仍然会关注项目的发展,负责打 tag,乃至干预极个别无法达成共识的技术决策;大部分日常工作应该都会交给新的维护者。有关接下来要做的工作,近期会写一个文档贴在某处(Wiki or ROADMAP.md)。

感兴趣的开发者在下面留言即可;已有贡献记录会是一个加分项,但主要您应该能使我相信本项目在您的维护下,会得到它应有的迭代和发展。

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.