时间:2021-05-22
钉钉SDK
对接sdk还是遇到不少问题的
钉钉python版SDK文档地址:https://dingtalk-sdk.readthedocs.io/zh_CN/latest/
钉钉官方服务端文档:https://open-doc.dingtalk.com/microapp/serverapi2
为了避免调试出现不必要的参数错误,前期钉钉配置要做好,血和泪的教训😭
准备好下面几个参数
DINGTALK_CORP_ID = "重点:企业应用ID"# 钉钉微应用DINGTALK_APP_KEY = "微应用APP_KEY"DINGTALK_CORP_SECRET = "微应用SERCRET"# 钉钉移动应用(扫码登录),在移动应用接入菜单里配置DINGTALK_APP_ID = "移动应用APP_ID"DINGTALK_APP_SECRET = "移动应用APP_SECRET"# 钉钉aes加密(随机)DINGTALK_AES_TOKEN = "43位字符串 a-zA-Z0-9中生成"DINGTALK_TOKEN = "字符串随便填"一. 第三方web网站扫码登录1. 流程
钉钉扫码—>判断是否公司员工—>登录
关于web系统的两种接入方式,都只能获取到用户的钉钉身份,并不能获取到用户是否在企业中
解决方法:
批量同步钉钉人员信息到数据库,登录后匹配数据库,新进员工通过钉钉回调同步到数据库,回调未生效人工审核后手动更新数据库
由于钉钉开发文档读的不够仔细导致调试频繁出错,所以开发流程我简单说,把细节放大
前端导入钉钉scrpit文件开发扫码页面
<script src="//g.alicdn.com/dingding/dinglogin/0.0.5/ddLogin.js"></script><script>var url="http://erp.vaiwan.com/api/v1.0/ding_test";var goto = encodeURIComponent('https://oapi.dingtalk.com/connect/oauth2/sns_authorize?appid=dingoadwjj1iszubeh9rnf&response_type=code&scope=snsapi_login&state=STATE&redirect_uri='+url);var obj = DDLogin({ id:"login_container", goto: goto, style: "border:none;background-color:#FFFFFF;", width : "365", height: "400" });var hanndleMessage = function (event) { var origin = event.origin; console.log("origin", event.origin); //判断是否来自ddLogin扫码事件。 if( origin == "https://login.dingtalk.com" ) { //拿到loginTmpCode后就可以在这里构造跳转链接进行跳转了 var loginTmpCode = event.data; console.log("loginTmpCode", loginTmpCode); if(loginTmpCode){ let uri="https://oapi.dingtalk.com/connect/oauth2/sns_authorize?appid=dingoadwjj1iszubeh9rnf&response_type=code&scope=snsapi_login&state=STATE&redirect_uri="+url+"&loginTmpCode="+loginTmpCode; // 跳转 location.href = uri; } }};if (typeof window.addEventListener != 'undefined') { window.addEventListener('message', hanndleMessage, false);} else if (typeof window.attachEvent != 'undefined') { window.attachEvent('onmessage', hanndleMessage);}</script>配置扫码后跳转页面(就是第一步goto参数里的url),钉钉会自动在跳转页面路由后添加code和state参数
拿到code请求后端接口
<script src="https://cdn.bootcss.com/jquery/3.1.0/jquery.min.js"></script><script> // location.search: "?code=bb42ec66ed5...&state=STATE" let code = location.search.split("&")[0].split("=")[1]; $.ajax({ type:"post", url:'http://erp.vaiwan.com.cn/api/v1.0/getinfo', data:{ "code":code }, success:function(data){ console.log(data) } })</script>后端用appid和appsecret获取access_token
import requestsfrom dingtalk.client import SecretClientclass GetInfoByCode(object): def __init__(self): self.url = "https://oapi.dingtalk.com/sns" def get_access_token(self): resp = requests.get( url=self.url + "/gettoken", params=dict(appid=DINGTALK_APP_ID, appsecret=DINGTALK_APP_SECRET) ) resp = resp.json() return resp["access_token"]用access_token和code获取用户unionid
def get_persistent_code(self, code, token): resp = requests.post( url="%s/get_persistent_code?access_token=%s" % (self.url, token), json=dict(tmp_auth_code=code), ) resp = resp.json() return resp["unionid"]用unionid换取userid
ding_client = SecretClient(corp_id=DINGTALK_CORP_ID, corp_secret=DINGTALK_CORP_SECRET)# 这块提醒下一定要做缓存,由于我之前没做缓存,超过钉钉使用频率而被限制了,修改下上面那句代码import redisfrom dingtalk.storage.kvstorage import KvStorage# redis做缓存redis_ding = redis.StrictRedis(REDIS_HOST, REDIS_PORT, db=0)# 划重点,因为我是第三方web网站,没有使用E应用,所以我的corp_id填的是微应用的id,而不是企业应用ID(corp_id)ding_client = SecretClient( corp_id=DINGTALK_APP_KEY, corp_secret=DINGTALK_CORP_SECRET, storage=KvStorage(redis_ding))userid = ding_client.user.get_userid_by_unionid(unionid)userid换取user详情
user = ding_client.user.get(userid["userid"])二. 加解密
应用场景: 钉钉回调
事件流程:注册回调事件—>处理事件内容(新增员工、更新部门等),返回钉钉加密json
就是说你调用注册事件API,钉钉会给你需要注册的url发送一个post请求,你得按要求返回success,否则注册失败
1.注册事件
再看看什么是success的加密json数据
如果你没有看懂的话,很巧 我也看不懂…
json数据包含这些参数
时间戳和nonce容易拿,问题在于encrypt和msg_signature的生成
因为钉钉没有提供python的加解密库,所以看到这块我有点懵
钉钉的文档看不太懂…
百度搜了下 发现有人自己封装了这个库,我看了下名字XXXcrypto,crypto这个单词好像在sdk里边见过。
看了sdk目录,果然,虽然钉钉sdk虽然没写关于加解密的内容,但是它其实已经封装了这个库
使用
from dingtalk.crypto import DingTalkCryptoclass Crypto(object): def __init__(self): # 随便填的字符串 self.token = DINGTALK_TOKEN # 自己生成的43位随机字符串 self.aes_key = DINGTALK_AES_TOKEN # 钉钉企业ID self.corpid = DINGTALK_APP_ID self.crypto = DingTalkCrypto( token=self.token, encoding_aes_key=self.aes_key, corpid_or_suitekey=self.corpid )说明
原本是不需要自己封装的。看dingtalk的源码
在开始定义ding_client的时候,只需要填参数就可以,经过我反复的调试,发现因为我开发的是企业内部应用-微应用,而不是E应用,所以这里填的corp_id其实是微应用app_key,参数不正确导致后边调试一直返回文本非success错误,为了不与上边填的参数冲突,所以自己封装Crypto类,填写的corp_id是企业应用id
封装好Crypto这个类,就可以调用啦, 先测试返回给钉钉的结果是否正确
from ... import Cryptoclass EventCallBack(Resource): def __init__(self): self.crypto = Crypto().crypto def post(self): # 返回加密success result = self.crypto.encrypt_message( msg="success", nonce="123456", timestamp=int(time.time()*1000) ) return result事情没这么容易结束…
这个post方法你需要对回调事件作出处理而不是仅仅返回success,所以最终需要这样, 对结果进行处理
def post(self): po = request.json["encrypt"] data = request.values # 返回加密success result = self.crypto.encrypt_message( msg="success", nonce="123456", timestamp=int(time.time()*1000) ) # 获取到事件及其他信息 callback = self.crypto.decrypt_encrypt_str( encrypt_str=po, nonce=data["nonce"], timestamp=data["timestamp"], signature=data["signature"] ) # demjson可以把字符串转为字典,否则取值失败 # 安装 pip install demjson callback = demjson.decode(callback) # 判断事件类型,作出相应回调 if callback["EventType"] == "user_add_org": # 添加员工 ... elif callback["EventType"] == "org_dept_create": # 添加部门 ... return result三. 调试
# 钉钉内网穿透工具,主要作用是方便本地调试需要回调域名的接口# 地址: https://open-doc.dingtalk.com/microapp/debug/ucof2g可以后台启动以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
声明:本页内容来源网络,仅供用户参考;我单位不保证亦不表示资料全面及准确无误,也不保证亦不表示这些资料为最新信息,如因任何原因,本网内容或者用户因倚赖本网内容造成任何损失或损害,我单位将不会负任何法律责任。如涉及版权问题,请提交至online#300.cn邮箱联系删除。
前言:由于公司使用钉钉,之前告警都是使用邮箱,但是这种协同效率比较低,所以调用钉钉机器人来实现实时告警。创建机器人:创建钉钉群,然后添加群机器人。python代
背景偶然发现一个python实现的按照农历/阴历推送消息提醒的程序,钉钉群消息推送。此处总结并对其可推送的消息做。DingtalkNotice环境:python
本文实例讲述了C#实现推送钉钉消息的方法。分享给大家供大家参考,具体如下:利用钉钉提供的API可以推送消息到用户的钉钉app。根据钉钉的官方文档,调用钉钉的ap
一、钉钉群自定义机器人介绍钉钉群机器人是钉钉群的一个高级扩展功能,然而使用起来却非常简单,只有注册一个钉钉账号即可,就可以将第三方服务的信息聚合到钉钉群中,实现
1,需要在项目种引入钉钉官方的js或者npm也可以的2,钉钉自带的api,有写是需要鉴权的,所以在使用之前一定要先鉴权获取钉钉接口的鉴权dd.config({a