from rest_framework.views import APIView from apps.lyTiktokUnion.models import DyOrderManage from utils.jsonResponse import SuccessResponse,ErrorResponse,DetailResponse from utils.common import get_parameter_dic,formatdatetime,float2dot,getminrandomodernum,ast_convert,getLyStateEncrypt,verifyLyStateEncript,ly_md5 from django.db.models import Q,F,Sum,Count from django.db import transaction from rest_framework import serializers from rest_framework_simplejwt.authentication import JWTAuthentication from rest_framework.permissions import IsAuthenticated from utils.pagination import CustomPagination from utils.douyin.doudian_utils import doudian import datetime import json from django.http import HttpResponse,HttpResponseRedirect from config import DOUYIN_OPENAPI_CLIENT_KEY,DOUYIN_OPENAPI_CLIENT_SECRET,DOUDIAN_DKFX_TOOL_APPKEY,DOUDIAN_DKFX_TOOL_APPSECRET from apps.lyTiktokUnion.tools.lyPublic import * import logging import hashlib import datetime logger = logging.getLogger(__name__) def convertString2Datetime(string): if not string: return None try: dt = datetime.datetime.strptime(string, '%Y-%m-%d %H:%M:%S') return dt except: return None def sha1_encrypt(content): sha1_obj = hashlib.sha1() sha1_obj.update(content.encode('utf-8')) return sha1_obj.hexdigest() #订阅达人的订单新增和更新消息 #{'event': 'alliance_daren_order', 'client_key': 'awai74ahekaxxx', 'from_user_id': '_000_LzNb0HBhiwF1coI9Li860_5g2m6xxx', 'content': '{"order_id":"692400803131648xxx","product_id":"36467746704155xxx","product_name":"商品名xxx","product_img":"https://p6-aio.ecombdimg.com/obj/ecom-shop-material/gkByqoQb_m_bc4e51af32bf950fcxxxx491d604_sx_320245_www800-800","author_account":"xxx说","author_openid":"_000_LzNb0HBhiwF1coI9Li860_5g2m6xxx","shop_name":"xx工厂店","total_pay_amount":1290,"commission_rate":2000,"estimated_commission":232,"real_commission":0,"flow_point":"PAY_SUCC","app":"抖音","update_time":"2023-11-22 17:41:47","pay_success_time":"2023-11-22 17:41:36","pay_goods_amount":1290,"settled_goods_amount":0,"shop_id":1315421xx,"estimated_tech_service_fee":26,"item_num":1,"estimated_total_commission":258,"pick_source_client_key":"awai74ahekaxxx","author_short_id":"185236xxx","pick_extra":"ly_F1sv3mtH97_cc","author_buyin_id":"6958644459006165xxx","media_type":"shop_list","app_id":1128,"is_stepped_plan":false,"product_activity_id":"0"}', 'log_id': '02170064610750500000000000000000000ffxxxx'} class DouyinAllianceDarenOrderWebhookView(APIView): ''' 订阅达人的订单新增和更新消息 post: ''' authentication_classes = [] permission_classes = [] def post(self, request): douyin_sign = request.META.get('X-Douyin-Signature') reqdata = get_parameter_dic(request) logger.info("获取达人订单webhook通知,头部信息:X-Douyin-Signature=%s,通知内容:%s"%(douyin_sign,reqdata)) event = reqdata.get('event') client_key = reqdata.get('client_key') content = reqdata.get('content') from_user_id = reqdata.get('from_user_id') log_id = reqdata.get('log_id') if event == "verify_webhook": challenge = content.get('challenge') return HttpResponse(json.dumps({'challenge':challenge}), content_type='application/json') elif event == "alliance_daren_order": if not douyin_sign and not sha1_encrypt(f'{DOUYIN_OPENAPI_CLIENT_SECRET}{reqdata}'): logger.error("【签名校验错误】获取达人订单webhook通知,头部信息:X-Douyin-Signature=%s,通知内容:%s" % ( douyin_sign, request.body)) return HttpResponse("非法请求") content = json.loads(content) content['update_time'] = content['update_time'] if content.get('update_time',None) else None content['settle_time'] = content['settle_time'] if content.get('settle_time',None) else None content['refund_time'] = content['refund_time'] if content.get('refund_time',None) else None pid_info = content.pop('pid_info',None) order_id = content.get('order_id') defaults = content if content.get('media_type') == 'shop_list' and defaults.get('pick_extra',None): defaults['from_user_id'] = from_user_id if pid_info: defaults['pid'] = pid_info.get('pid') defaults['external_info'] = pid_info.get('external_info') defaults['media_type_name'] = pid_info.get('media_type_name') defaults['order_type'] = 1 defaults['inner_user_id'] = get_cc_userid(defaults['pick_extra']) defaults.pop("app_id",None) defaults.pop("author_buyin_id",None) defaults.pop("estimated_tech_service_fee",None) defaults.pop("estimated_total_commission",None) defaults.pop("is_stepped_plan",None) defaults.pop("product_activity_id",None) instance,created = DyOrderManage.objects.get_or_create(order_id=order_id,defaults=defaults) if not created: instance.update_time = content['update_time'] instance.estimated_commission = content['estimated_commission'] instance.real_commission = content['real_commission'] instance.settled_goods_amount = content['settled_goods_amount'] instance.pay_goods_amount = content['pay_goods_amount'] instance.settle_time = content['settle_time'] instance.refund_time = content['refund_time'] instance.flow_point = content['flow_point'] instance.save() else: logger.info("获取达人订单webhook通知,order_id=%s,处理结果:忽略"%order_id) return HttpResponse("ok") #订阅抖客的订单新增和更新消息 #https://buyin.jinritemai.com/dashboard/service-provider/msg-center?docId=3084 #消息推送失败,可以再抖店开放平台【开发】-【应用中心】-选择应用-【查看详情】-【应用配置】-【消息推送】-【推送记录】中进行手动点击【重新推送】 class DouyinAllianceDouKeOrderWebhookView(APIView): ''' 订阅独立抖客的订单新增和更新消息 post: ''' authentication_classes = [] permission_classes = [] def post(self, request): app_key = request.META.get('HTTP_APP_ID') event_sign = request.META.get('HTTP_EVENT_SIGN') body = request.body.decode('UTF-8') reqdata = json.loads(body) #抖音测试消息 success_response = json.dumps({"code": 0, "msg": "success"}) if reqdata[0]['tag'] == '0' and reqdata[0]['msg_id'] == '0': return HttpResponse(success_response, content_type='application/json') #校验消息 new_event_sign = ly_md5(f'{DOUDIAN_DKFX_TOOL_APPKEY}{reqdata}') if not DOUDIAN_DKFX_TOOL_APPKEY == app_key and not event_sign==new_event_sign: logger.error("【签名校验错误】获取抖客订单webhook通知,头部信息requestMETA=%s:app-id=%s,event-sign=%s,通知内容:%s" % (request.META,app_key,event_sign,request.body)) return HttpResponse('非法请求') logger.info("获取抖客订单webhook通知,头部信息requestMETA=%s:app-id=%s,event-sign=%s,通知内容:%s" % (request.META, app_key, event_sign, reqdata)) for d in reqdata: if d.get('tag') == '418': data = json.loads(d.get('data')) data['update_time'] = data['update_time'] if data.get('update_time',None) else None data['settle_time'] = data['settle_time'] if data.get('settle_time',None) else None data['refund_time'] = data['refund_time'] if data.get('refund_time',None) else None pid_info = data.pop('pid_info') order_id = data.get('order_id') # defaults = data defaults = {'pid':'','external_info':'','media_type_name':'','order_type':0,'inner_user_id':'','flow_point':data.get('flow_point'),'product_id':data.get('product_id'),'product_name':data.get('product_name'),'product_img':data.get('product_img'),'item_num':int(data.get('item_num')),'app':'','author_account':data.get('author_account'),'author_openid':'','author_short_id':'','shop_id':data.get('shop_id'),'shop_name':data.get('shop_name'),'pick_source_client_key':'','pick_extra':'','media_type':data.get('media_type'),'total_pay_amount':int(data.get('total_pay_amount')),'commission_rate':0,'update_time':convertString2Datetime(data.get('update_time')),'pay_success_time':convertString2Datetime(data.get('pay_success_time')),'settle_time':convertString2Datetime(data.get('settle_time')),'refund_time':convertString2Datetime(data.get('refund_time')),'pay_goods_amount':int(data.get('pay_goods_amount')),'settled_goods_amount':int(data.get('settled_goods_amount')),'estimated_commission':int(data.get('ads_estimated_commission')),'real_commission':int(data.get('ads_real_commission')),'from_user_id':''} defaults['pid'] = pid_info.get('pid') defaults['external_info'] = pid_info.get('external_info') if defaults['external_info'] and 'ly_' in defaults['external_info']: defaults['media_type_name'] = pid_info.get('media_type_name') if get_product_share_userid(defaults['external_info']): defaults['order_type'] = 2 defaults['inner_user_id'] = get_product_share_userid(defaults['external_info']) elif get_product_0y_userid(defaults['external_info']): defaults['order_type'] = 3 defaults['inner_user_id'] = get_product_0y_userid(defaults['external_info']) elif get_product_df_userid(defaults['external_info']): defaults['order_type'] = 4 defaults['inner_user_id'] = get_product_df_userid(defaults['external_info']) logger.info("获取抖客订单webhook通知,order_id=%s,处理结果:此为垫付买样订单,暂时忽略"%order_id) continue else:#其他类型忽略 logger.info("获取抖客订单webhook通知,order_id=%s,处理结果:忽略"%order_id) continue instance, created = DyOrderManage.objects.get_or_create(order_id=order_id, defaults=defaults) if not created: instance.update_time = data['update_time'] instance.estimated_commission = data['ads_estimated_commission'] instance.real_commission = data['ads_real_commission'] instance.settled_goods_amount = data['settled_goods_amount'] instance.settle_time = data['settle_time'] instance.refund_time = data['refund_time'] instance.flow_point = data['flow_point'] instance.save() else: logger.info("获取抖客订单webhook通知,order_id=%s,处理结果:忽略"%order_id) continue return HttpResponse(success_response, content_type='application/json')