import base64 from rest_framework import serializers from apps.jqr.tasks import save_add_contact, delete_add_contact, edit_add_contact from libs.weworkapi.callback.WXBizMsgCrypt3 import WXBizMsgCrypt, Prpcrypt from utils.tools import sha1_encoder, get_attribute, camel_to_snake import xml.etree.cElementTree as ET class WechatPublicTokenSerializer(serializers.Serializer): msg_signature = serializers.CharField() echostr = serializers.CharField() timestamp = serializers.CharField() nonce = serializers.CharField() def validate(self, attrs): corp = self.context.get('corp') token = corp.token corpid = corp.corpid encoding_aes_key = corp.encodingaeskey msg_signature = attrs.get('msg_signature') echostr = attrs.get('echostr') timestamp = attrs.get('timestamp') nonce = attrs.get('nonce') # # 1)将token、timestamp、nonce, echostr四个参数进行字典序排序 # arr = [token, timestamp, nonce, echostr] # arr.sort() # # 2)将三个参数字符串拼接成一个字符串进行sha1加密 # data = "".join(arr) # # 3)开发者获得加密后的字符串可与 signature 对比,标识该请求来源于微信 # encode_str = sha1_encoder(data) wxcpt = WXBizMsgCrypt(token, encoding_aes_key, corpid) ret, echostr = wxcpt.VerifyURL(msg_signature, timestamp, nonce, echostr) if ret != 0: return {} attrs['echostr'] = echostr.decode() return attrs class WechatEncryptSerializer(serializers.Serializer): ToUserName = serializers.CharField(write_only=True) Encrypt = serializers.CharField(write_only=True) AgentID = serializers.CharField(write_only=True) def create(self, data): corp = self.context.get('corp') encoding_aes_key = corp.encodingaeskey encrypt = data.get('Encrypt') xmltext = self.decrypt(encrypt, encoding_aes_key) data = self.parse_xml(xmltext) print(data) event = data.get('event') changetype = data.get('changetype') event_handler = getattr(self, f'handle_{event}_{changetype}', None) print(f'handle_{event}_{changetype}') if event_handler: event_handler(data) return {} def decrypt(self, encrypt, encoding_key): try: key = base64.b64decode(encoding_key + "=") prpcrypt = Prpcrypt(key) corpid = '' res, decrypt = prpcrypt.decrypt(encrypt, corpid) if res != 0: return decrypt = decrypt.decode() return decrypt except Exception as e: print(e) def parse_xml(self, xmltext): xml_tree = ET.fromstring(xmltext) data = {} for child in xml_tree: tag = child.tag key = camel_to_snake(tag) key = ''.join(key.split('_')) data[key] = get_attribute(xml_tree.find(tag), 'text') return data def handle_change_external_contact_add_external_contact(self, data): """ 处理添加企业客户事件 """ print('添加客户事件') corp = self.context.get('corp') data.pop('tousername') data['corpid'] = corp.corpid data['agentid'] = corp.agentid data['uid'] = corp.uid print(data) save_add_contact.delay(data, corp.to_dict(['corpid', 'appsecret'])) def handle_change_external_contact_edit_external_contact(self, data): """ 处理编辑企业客户事件 """ print('编辑客户事件') corp = self.context.get('corp') data.pop('tousername') data['corpid'] = corp.corpid data['agentid'] = corp.agentid data['uid'] = corp.uid print(data) edit_add_contact.delay(data, corp.to_dict(['corpid', 'appsecret'])) def handle_change_external_contact_add_half_external_contact(self, data): """ 处理外部联系人免验证添加成员事件 """ print('外部联系人免验证添加成员事件') corp = self.context.get('corp') data.pop('tousername') data['corpid'] = corp.corpid data['agentid'] = corp.agentid data['uid'] = corp.uid print(data) save_add_contact.delay(data, corp.to_dict(['corpid', 'appsecret'])) def handle_change_external_contact_del_follow_user(self, data): """ 处理删除跟进成员事件 (客户删我们) """ print('删除跟进成员事件') corp = self.context.get('corp') data.pop('tousername') data['corpid'] = corp.corpid data['agentid'] = corp.agentid data['uid'] = corp.uid print(data) delete_add_contact.delay(data, corp.to_dict(['corpid', 'appsecret'])) def handle_change_external_chat_create(self, data): """ 处理客户群创建事件 """ print('客户群创建事件') print(data) def handle_change_external_chat_update(self, data): """ 处理客户群更新事件 """ print('客户群更新事件') print(data) def handle_change_external_chat_dismiss(self, data): """ 处理客户群解散事件 """ print('客户群解散事件') print(data)