yzk_wechat_event/apps/jqr/serializers.py

269 lines
9.8 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import base64
import json
from datetime import datetime
from rest_framework import serializers
from apps.jqr.models import JqrHookUser
from apps.jqr.pubsub import JQREventNewUserCallbackPubSub, JQREventCallbackPubSub
from apps.jqr.tasks import save_add_contact, delete_add_contact, edit_add_contact, save_add_contact_by_channel, \
edit_add_contact_by_channel, delete_add_contact_by_channel
from apps.msg.models import TbMessage
from apps.msg.pubsub import JQRMSGPubSub
from apps.qc.choices import QcCorpInfoCallbackStatusChoices
from apps.qc.models import QcQrcodes
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
from utils.base_serializer import BaseSerializer, CurrentIpDefault
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 {}
corp.callbackstatus = QcCorpInfoCallbackStatusChoices.VALIDATED
corp.callback_validate_time = datetime.now()
corp.save()
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')
print(data)
state = data.get('state')
data['corpid'] = corp.corpid
if state and state.startswith('mg') and '_' in state:
[_, uid, qrcodeid] = state.split('_')
data['qrcodeid'] = qrcodeid
data['agentid'] = corp.agentid
data['uid'] = uid
qrcode = QcQrcodes.objects.filter(id=qrcodeid, uid=uid).first()
if not qrcode:
return
data['qrcodeid'] = qrcodeid
data['agentid'] = qrcode.agentid
data['uid'] = uid
data['corpid'] = qrcode.corpid
# save_add_contact.delay(data, corp.to_dict(['corpid', 'appsecret']))
JQREventNewUserCallbackPubSub.publish({
'handler': f'{save_add_contact_by_channel.__module__}.{save_add_contact_by_channel.__name__}',
'data': json.dumps(data),
'corpinfo': corp.to_dict(['corpid', 'appsecret']),
})
def handle_change_external_contact_edit_external_contact(self, data):
"""
处理编辑企业客户事件
"""
print('编辑客户事件')
corp = self.context.get('corp')
data.pop('tousername')
print(data)
state = data.get('state')
data['corpid'] = corp.corpid
if state and state.startswith('mg') and '_' in state:
[_, uid, qrcodeid] = state.split('_')
data['qrcodeid'] = qrcodeid
data['agentid'] = corp.agentid
data['uid'] = uid
qrcode = QcQrcodes.objects.filter(id=qrcodeid, uid=uid).first()
if not qrcode:
return
data['qrcodeid'] = qrcodeid
data['agentid'] = qrcode.agentid
data['uid'] = uid
data['corpid'] = qrcode.corpid
# edit_add_contact.delay(data, corp.to_dict(['corpid', 'appsecret']))
JQREventCallbackPubSub.publish({
'handler': f'{edit_add_contact_by_channel.__module__}.{edit_add_contact_by_channel.__name__}',
'data': json.dumps(data),
'corpinfo': 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')
print(data)
state = data.get('state')
data['corpid'] = corp.corpid
if state and state.startswith('mg') and '_' in state:
[_, uid, qrcodeid] = state.split('_')
data['qrcodeid'] = qrcodeid
data['agentid'] = corp.agentid
data['uid'] = uid
qrcode = QcQrcodes.objects.filter(id=qrcodeid, uid=uid).first()
if not qrcode:
return
data['qrcodeid'] = qrcodeid
data['agentid'] = qrcode.agentid
data['uid'] = uid
data['corpid'] = qrcode.corpid
# save_add_contact.delay(data, corp.to_dict(['corpid', 'appsecret']))
JQREventNewUserCallbackPubSub.publish({
'handler': f'{save_add_contact_by_channel.__module__}.{save_add_contact_by_channel.__name__}',
'data': json.dumps(data),
'corpinfo': corp.to_dict(['corpid', 'appsecret']),
})
def handle_change_external_contact_del_follow_user(self, data):
"""
处理删除跟进成员事件 (客户删我们)
"""
print('删除跟进成员事件')
corp = self.context.get('corp')
data.pop('tousername')
print(data)
state = data.get('state')
data['corpid'] = corp.corpid
if state and state.startswith('mg') and '_' in state:
[_, uid, qrcodeid] = state.split('_')
data['qrcodeid'] = qrcodeid
data['agentid'] = corp.agentid
data['uid'] = uid
qrcode = QcQrcodes.objects.filter(id=qrcodeid, uid=uid).first()
if not qrcode:
return
data['qrcodeid'] = qrcodeid
data['agentid'] = qrcode.agentid
data['uid'] = uid
data['corpid'] = qrcode.corpid
# delete_add_contact.delay(data, corp.to_dict(['corpid', 'appsecret']))
JQREventCallbackPubSub.publish({
'handler': f'{delete_add_contact_by_channel.__module__}.{delete_add_contact_by_channel.__name__}',
'data': json.dumps(data),
'corpinfo': corp.to_dict(['corpid', 'appsecret']),
})
def handle_change_external_chat_create(self, data):
"""
处理客户群创建事件
"""
print('客户群创建事件')
print(data)
corp = self.context.get('corp')
data['chat_id'] = data.pop('chatid')
def handle_change_external_chat_update(self, data):
"""
处理客户群更新事件
"""
print('客户群更新事件')
print(data)
def handle_change_external_chat_dismiss(self, data):
"""
处理客户群解散事件
"""
print('客户群解散事件')
print(data)
class HeartBeatSerializer(BaseSerializer):
ip = serializers.HiddenField(default=CurrentIpDefault())
class Meta:
validators = []
model = JqrHookUser
fields = '__all__'
def create(self, validated_data):
corpid = validated_data.get('corpid')
userid = validated_data.get('userid')
obj, _ = JqrHookUser.objects.update_or_create(
defaults=validated_data,
corpid=corpid,
userid=userid,
)
return obj
class TbMessageModelSerializer(BaseSerializer):
class Meta:
model = TbMessage
fields = '__all__'
def create(self, validated_data):
JQRMSGPubSub.publish({
**self.context.get('request').data,
'corpid': validated_data.get('corpid'),
'userid': validated_data.get('userid'),
})
return TbMessage(**validated_data)