事情并不简单
开发须要用到钉钉开放平台提供的接口,可是钉钉官方并无提供 Go 语言版本的 sdkgit
在 GitHub 逛了一圈后,找不到满意的开源版本,有些 repo 设计不太规范,有些 repo 只实现了部分功能github
因而,我决定亲手撸一个web
但很快,我就发现事情并不简单:钉钉开放平台提供了超过 200 个接口!c#
开发一个完整的 sdk 须要阅读每个接口的文档,理解各个参数的做用,处理各类异常和接口返回的结果,还有 access_token 管理、数据加解密等细节api
即便是资深开发工程师,在这脏活累活上,恐怕也得耗上半个月的时间服务器
太慢了,这不是我想要的微信
快就一个字
通过 30 分钟仔细阅读接口文档后,我发现了一些规律:架构
-
服务器地址都是 https://oapi.dingtalk.com/ -
HTTP 请求方法都是 POST 或 GET -
全部的请求都须要 access_token 参数 -
官方文档针对每个接口都详细列出了接口简介、接口地址、Query 参数、Body 参数 -
...
一个不太成熟的小想法就浮现出脑海:app
-
搞个爬虫抓取接口名称、接口简介、接口地址、Query 参数、Body 参数 等 API 元信息 -
一个 API 的规格由其元信息惟必定义 -
每一个 API 都由一个 func
表示 -
用 params url.Values
表示接口须要的Query 参数 -
用 payload []byte
表示接口须要的Body 参数 -
用 resp []byte
表示接口的返回内容 -
根据 API 分组状况,拆分 package -
全部 API 请求由统一的 Http Client 模块处理 -
access_token、错误处理和重试逻辑由 Http Client 模块处理 -
钉钉服务器发出回调由 Http Server 模块处理 -
...
至此,一个简洁但完整的架构呼之欲出:编辑器
咱们将打造这样一款 sdk : 介于业务逻辑 和 钉钉 之间,将业务的指令发送到钉钉,将钉钉的响应透传给业务
魔鬼在细节
按照上 part 咱们的构想,就能够开始搞了
先看看钉钉文档页面结构:
启动爬虫抓回来接口元信息:
Api{
Name: "获取用户userid",
Description: "经过免登受权码和access_token获取用户的userid。",
Request: "GET https://oapi.dingtalk.com/user/getuserinfo?access_token=access_token&code=code",
See: "https://ding-doc.dingtalk.com/doc#/serverapi2/clotub",
FuncName: "GetUserInfo",
GetParams: []Param{
{Name: `code`, Type: `string`},
},
}
格式化成 Go func
:
package auth
import ...
const apiGetUserInfo = "/user/getuserinfo"
/*
获取用户userid
经过免登受权码和access_token获取用户的userid。
See: https://ding-doc.dingtalk.com/doc#/serverapi2/clotub
GET https://oapi.dingtalk.com/user/getuserinfo?access_token=access_token&code=code
*/
func GetUserInfo(ctx *dingding.App, params url.Values) (resp []byte, err error) {
return ctx.Client.HTTPGet(apiGetUserInfo + "?" + params.Encode())
}
再搞个 test
和 example
的模板代码,当爬虫所有执行完后,咱们就能够获得:
├─ai
│ ai.go
│ ai_test.go
│ example_ai_test.go
│
├─alitrip
│ alitrip.go
│ alitrip_test.go
│ example_alitrip_test.go
│
├─attendance
│ attendance.go
│ attendance_test.go
│ example_attendance_test.go
│
......
Wow Amazing! 200 个接口已尽入吾彀中矣
不过,咱们时间很少了:
-
部分接口文档页面不规范,致使爬虫中断了 20 分钟 -
GET|POST 不一样类型的请求测试函数的差别比较大,耗费了 40 分钟 -
...
access_token 管理
全部接口调用最终都由统一的 Http Client 模块发起
因为每一个接口调用都须要鉴权,因此咱们把鉴权模块放在这里再好不过了
处理方式很是简单,拿到access_token
,加到请求地址后便可:
accessToken, _ := client.Ctx.AccessToken.GetAccessTokenHandler()
newUrl := url + "?access_token=" + accessToken
关键在 GetAccessTokenHandler
方法,这里定义了如何获取 access_token
试一试
再处理一下其余细节,包括错误处理、单元测试等,咱们的 sdk 就差很少搞定啦
如今到了 Eating your own dog food
环节:
go get github.com/fastwego/dingding
// 建立应用实例
app := dingding.NewApp(dingding.AppConfig{
AppKey: viper.GetString("AppKey"),
AppSecret: viper.GetString("AppSecret"),
})
// 调用 api
params := url.Values{}
params.Add("code", CODE)
resp, err := auth.GetUserInfo(app, params)
若是一切正常的话,接口能够正确响应咱们的请求
效果好极啦,调用简单,不只有 Example 引导,还有文档和连接:

果真仍是本身打造的工具最趁手
才刚刚开始
在一样的思路下,我又撸完了企业微信和飞书的 Go sdk
-
https://github.com/fastwego/wxwork -
https://github.com/fastwego/feishu
to be continue ...
本文分享自微信公众号 - 追马Linux(zhuima_k8s)。
若有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一块儿分享。