序幕
之前实现了钉钉三方扫码登陆,不得不说,钉钉还是一款很不错的办公软件。在最近的疫情期间,打游戏都不怎么坑了(因为钉钉的存在)。不过钉钉的群发机器人还是挺不错,可以自定义发送的信息。个人感觉比图灵好用,前期的微信公众号添加机器人使用的就是图灵机器人。
不过关于钉钉机器人网上的一些攻略年代都比较久远,代码很多都基于python2,那我们尝试用python3.7来开发配置钉钉自定义机器人。
解决问题
quote_plus与quote的区别
1 2 3 4
| quote = urllib.parse.quote('a&b/c') print('a&b/c:',quote) plus = urllib.parse.quote_plus('a&b/c') print('a&b/c:',plus)
|
结果(一个不编译/,一个编译)
1 2
| a&b/c: a%26b/c a&b/c: a%26b%2Fc
|
创建机器人
在创建机器人之前,我们需要有自己的钉钉号,和创建一个钉钉群聊,而且创建机器人不支持手机端,所以请在电脑端进行创建
进入创建好的群,群成员可根据个人喜好添加,找到智能群组手

进入之后,下拉找到添加机器人

之后添加机器人
,选择自定义


机器人名称
自己修改(密钥保存)

需要注意的是,在安全设置一栏里,我们选择加签的方式来验证,在此说明一下,钉钉机器人的安全策略有三种,第一种是使用关键字,就是说你推送的消息里必须包含你创建机器人时定义的关键字,如果不包含就推送不了消息,第二种就是使用加密签名,第三种是定义几个ip源,非这些源的请求会被拒绝,综合来看还是第二种又安全又灵活。
点击完成
,ok,群发机器人已创建好(webhoot保存)

值得一提的是,钉钉的机器人基于webhook协议,webhook呢是一个api概念,是微服务api的使用范式之一,也被成为反向api,即前端不主动发送请求。
编写后端请求接口
钉钉开发文档
开发文档中居然出现了python3.8的代码,很遗憾我们用的是3.7的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
| import time import hmac import hashlib import base64 import urllib.parse
timestamp = str(round(time.time() * 1000)) secret = 'this is secret' secret_enc = secret.encode('utf-8') string_to_sign = '{}\n{}'.format(timestamp, secret) string_to_sign_enc = string_to_sign.encode('utf-8') hmac_code = hmac.new(secret_enc, string_to_sign_enc, digestmod=hashlib.sha256).digest() sign = urllib.parse.quote_plus(base64.b64encode(hmac_code))
import requests,json headers={'Content-Type': 'application/json'} webhook = '"this is webhoot"×tamp='+timestamp+"&sign="+sign
data = { "msgtype": "text", "text": {"content": '群发消息'}, "isAtAll": True }
{ "msgtype": "text", "text": { "content": "群发消息" }, "at": { "atMobiles": [ "156xxxx8827", "189xxxx8325" ], "isAtAll": False } } res = requests.post(webhook, data=json.dumps(data), headers=headers)
print(res.text)
|
推送效果

校验不通过的消息将会发送失败,错误如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| { "errcode":310000, "errmsg":"keywords not in content" }
{ "errcode":310000, "errmsg":"invalid timestamp" }
{ "errcode":310000, "errmsg":"sign not match" }
{ "errcode":310000, "errmsg":"ip X.X.X.X not in whitelist" }
|