python处理钉钉回调事件中的消息体加解密

钉钉的回调事件列表:

  • user_add_org : 通讯录用户增加

  • user_modify_org : 通讯录用户更改

  • user_leave_org : 通讯录用户离职

  • org_admin_add :通讯录用户被设为管理员

  • org_admin_remove :通讯录用户被取消设置管理员

  • org_dept_create : 通讯录企业部门创建

  • org_dept_modify : 通讯录企业部门修改

  • org_dept_remove : 通讯录企业部门删除

  • org_remove : 企业被解散

  • org_change : 企业信息发生变更

  • label_user_change :员工角色信息发生变更

  • label_conf_add:增加角色或者角色组

  • label_conf_del:删除角色或者角色组

  • label_conf_modify:修改角色或者角色组

另外,在开发第三方企业应用时,通过回调URL推送suite_ticket。

所有的回调事件发生的时候会向URL POST数据,数据需要解密,解密后为

{
  "SuiteKey": "suitexxxxxx",
  "EventType": "suite_ticket ",
  "TimeStamp": 1234456,
  "SuiteTicket": "adsadsad"
}

然后所有的回调都需要向服务器返回经过加密的字符串'seccess'的json数据,

{
  "msg_signature":"111108bb8e6dbce3c9671d6fdb69d15066227608",
  "timestamp":"1783610513",
  "nonce":"123456",
  "encrypt":"1ojQf0NSvw2WPvW7LijxS8UvISr8pdDP+rXpPbcLGOmIBNbWetRg7IP0vdhVgkVwSoZBJeQwY2zhROsJq/HJ+q6tp1qhl9L1+ccC9ZjKs1wV5bmA9NoAWQiZ+7MpzQVq+j74rJQljdVyBdI/dGOvsnBSCxCVW0ISWX0vn9lYTuuHSoaxwCGylH9xRhYHL9bRDskBc7bO0FseHQQasdfghjkl" // "Random"字段的加密数据
}

 下面介绍一下字符串的加解密。

https://open-doc.dingtalk.com/microapp/faquestions/ltr370,这个是文档给出的加解密的方法。

然后就是使用python将整个过程实现。

from base64 import b64encode, b64decode
from Crypto.Cipher import AES
from hashlib import sha1
import struct, random, 


class prpcrypt():
    def __init__(self, key):
        self.key = key
        self.mode = AES.MODE_CBC
        self.Aec_key = b64decode(self.key + '=')
    
    def encrypt(self, text, key):
        # 加密
        rand_txt = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890'
        txt = ''.join(random.sample(rand_txt, 16))
        text_len = struct.pack('!i', len(text)).decode()
        crypto = AES.new(self.Aec_key, self.mode, self.key[:16])
        text = txt + text_len + text + key
        text = text + (16-len(text) % 16)*chr(16-len(text)%16)
        ciphertext = crypto.encrypt(text)
        return b64encode(ciphertext).decode().strip()

    def decrypt(self, text):
        # 解密
        crypto = AES.new(self.Aec_key, self.mode, self.key[:16])
        plain_text = crypto.decrypt(b64decode(text))
        raw = plain_text.rstrip(b'\0')
        length = struct.unpack('!i', raw[16:20])[0]
        return raw[20:20+length].decode().strip()
    
    def gen_signature(self, token, timestamp, nonce, encrypt):
        # 获取签名
        sign = sha1(''.join(sorted([token, timestamp, nonce, encrypt])).encode())
        return sign.hexdigest()

然后就是拿到POST的数据然后返回'success'

@csrf_exempt
def callback(request):
    token = 'token'  # 加解密需要用到的token
    aes_key = 'aes_key'  # 数据加密的密钥
    suiteKey = 'suiteKey'
    suiteSecret = 'suiteSecret'
    crypt = prpcrypt(aes_key)
    signature = request.GET.get('signature')
    timestamp = request.GET.get('timestamp')
    nonce = request.GET.get('nonce')
    msg_encrypt = json.loads(request.body, encoding='utf-8').get('encrypt')
    msg_signature = crypt.gen_signature(token, timestamp, nonce, msg_encrypt)
    if signature == msg_signature:
        data = json.loads(crypt.decrypt(text=msg_encrypt))
        
        EventType = data.get('EventType')
        (根据EventType对事件作处理)...

        # encrypt = crypt.encrypt("success", suiteKey)  第三方企业应用
        encrypt = crypt.encrypt("success", corpId)    企业内部应用
        result = json.dumps(dict(
            encrypt=encrypt,
            msg_signature=crypt.gen_signature(token, timestamp, nonce, encrypt),
            nonce=nonce,
            timeStamp=timestamp,
        ))
        return HttpResponse(result)

  • 1
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 7
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值