# -*- coding: utf-8 -*- #!/usr/bin/env python """ web.ad.views ~~~~~~~~~ """ import datetime import itertools import logging import random import traceback import simplejson as json import xmltodict from bson.objectid import ObjectId from django.core.handlers.wsgi import WSGIRequest from django.views.decorators.http import require_POST, require_GET from mongoengine.errors import NotUniqueError from typing import List, Union, Optional, Iterable, cast, TYPE_CHECKING, Dict from apilib import utils_datetime from apilib.utils import flatten from apilib.utils_datetime import dt_to_timestamp, date_to_datetime_floor, date_to_datetime_ceiling from apilib.utils_json import JsonResponse from apps import serviceCache from apps.web.ad import OfflineTaskType, MyJsonOkResponse from apps.web.ad.models import Advertisement, AdRecord, Advertiser, AdWord, AliAdLog from apps.web.ad.utils import (get_available_ads_by_user) from apps.web.agent.models import Agent from apps.web.common.validation import PASSWORD_RE from apps.web.core import ROLE from apps.web.core.db import prepare_conditions, prepare_query from apps.web.core.exceptions import InvalidPermission from apps.web.core.models import OfflineTask from apps.web.core.utils import DefaultJsonErrorResponse, parse_json_payload from apps.web.core.utils import JsonErrorResponse, JsonOkResponse from apps.web.dealer.models import Dealer from apps.web.device.models import Device from apps.web.device.models import Group from apps.web.management.models import Manager from apps.web.user.models import MyUser, Redpack from apps.web.user.utils import RedpackBuilder from apps.web.utils import advertiser_login, \ is_advertiser, is_manager, is_advertisement from apps.web.utils import error_tolerate, permission_required from taskmanager.mediator import task_caller if TYPE_CHECKING: from apps.web.common.models import UserSearchable logger = logging.getLogger(__name__) @error_tolerate(nil = DefaultJsonErrorResponse) @require_POST @permission_required(ROLE.manager, ROLE.advertiser) def getAdPreAllocatedDevice(request): # type:(WSGIRequest)->JsonResponse """ 根据多种多样的查询条件获取供分配设备列表List[Dict] {"devCondition":[{"agentIdList":[],"dealerIdList":[],"groupIdList":[]}],"addressTypeList":[],"devTypeList":[]} get_devices query = dealerIdList => Device.objects(ownerId__in=dealerIdList) | agentIdList => Device.objects(Dealer.objects(agentId__=agentIdList) | groupIdList => Device.objects(groupId__in=groupIdList) devices.filter( _ => _.devType in devTypeList & _ => _.group.addressType in addressTypeList) return [ { 'logicalCode': x, 'devType': 'y' } ] TODO: 优化方向, 0. 优化解析过程 1. 建立query解析缓存 2. 运用mongodb pipeline 3. 本地化部分数据(将厂商ID绑定到设备端,解绑记得清除,将地址类型也绑定到设备,解绑记得清除) :param request: :return: :rtype: JsonResponse """ query = json.loads(request.body) currentUser = request.user #type: cast(Union[Manager, Advertiser]) if is_manager(currentUser): devCondition, addressTypeList, devTypeList = query['devCondition'], query['addressTypeList'], query['devTypeList'] elif is_advertiser(currentUser): devCondition, addressTypeList, devTypeList = currentUser.preAllocatedDeviceConditions, query['addressTypeList'], query['devTypeList'] else: raise InvalidPermission(u'只有广告主或厂商才能查询广告投放设备') hasDevCondition = bool(len(list(itertools.ifilter(lambda _ : _ != [], flatten(_.values() for _ in devCondition))))) hasAddressTypeList = bool(len(addressTypeList)) hasDevTypeList = bool(len(devTypeList)) def imerge_dicts(iterable): """ Given any number of dicts, shallow copy and merge into a new dict, precedence goes to key value pairs in latter dicts. """ result = {} for dictionary in iterable: result.update(dictionary) return result to_query = lambda _ : imerge_dicts( x.to_query(None) for x in prepare_conditions(_) ) def acc_or_append(q, data): """ :param q: [{}] :param data: :return: """ if not len(q): q.append(data) else: for item in q: if data == item: break elif item['field'] == data['field'] and item['operator'] == data['operator']: item['value'] = list(set(item['value'] + data['value'])) break else: q.append(data) break def parse_devCondition(conditions): """ :param conditions: [{..conditions}] :return: """ queries = { 'device': [], 'dealer': [], 'group': [] } for cond in conditions: # 优先级 groupIdList > dealerIdList > agentIdList if cond['groupIdList']: acc_or_append(queries['group'], {"field": "_id", "operator": "in", "value": [ ObjectId(_) for _ in cond['groupIdList']] }) continue elif cond['dealerIdList']: acc_or_append(queries['group'], {"field": "ownerId", "operator": "in", "value": map(str, cond['dealerIdList']) }) continue elif cond['agentIdList']: acc_or_append(queries['dealer'], {"field": "agentId", "operator": "in", "value": cond['agentIdList']}) continue return queries #: 生成,拼装请求,延迟请求Device到最后, 减少IO queries = parse_devCondition(devCondition) #: 默认只能选择某厂商下的所有设备 #acc_or_append(queries['device'],{"field": "managerId", "operator": "", "value": managerId}) #: 不选择的时候,选择所有组的设备 if not hasDevCondition: if is_manager(currentUser): agentIds = [ str(_['_id']) for _ in Agent.get_collection().find({'managerId': str(currentUser.id)})] acc_or_append(queries['dealer'], {"field": "agentId", "operator": "in", "value": agentIds}) elif is_advertiser(currentUser): agentIds = [ str(_.id) for _ in Agent.objects(managerId=currentUser.managerId) ] acc_or_append(queries['dealer'], {"field": "agentId", "operator": "in", "value": agentIds}) if hasDevTypeList: acc_or_append(queries['device'], {"field": "devType.id", "operator": "in", "value": devTypeList}) if hasAddressTypeList: acc_or_append(queries['group'], {"field": "addressType", "operator": "in", "value": addressTypeList}) if queries['dealer']: dealers = [ str(_['_id']) for _ in Dealer.get_collection().find(to_query(queries['dealer']), {'_id': 1}) ] acc_or_append(queries['group'], {"field": "ownerId", "operator": "in", "value": dealers}) if queries['group']: groups = [ str(_['_id']) for _ in Group.get_collection().find(to_query(queries['group']), {'_id': 1}) ] acc_or_append(queries['device'], {"field": "groupId", "operator": "in", "value": groups}) if queries['device']: dataList = [ {'logicalCode': _['logicalCode'], 'devTypeName' : _['devType'].get('name')} for _ in Device.get_collection() .find(to_query(queries['device']), {'logicalCode': 1, 'devType.name': 1})] return JsonResponse({'result': 1, 'payload': {'dataList': dataList}}) return JsonResponse({'result': 1, 'payload': {'dataList': []}}) ###: 广告增删查改 @require_GET @error_tolerate(nil = DefaultJsonErrorResponse) @permission_required(ROLE.manager, ROLE.advertisement, ROLE.advertiser) def getAdList(request): # type:(WSGIRequest)->JsonResponse """ 获取广告列表 :param request: :return: """ return JsonResponse({'result': 1, 'description': '', 'payload': {'total': 0, 'dataList': []}}) @require_GET @error_tolerate(nil=JsonErrorResponse(u'获取广告分配设备列表失败')) @permission_required(ROLE.manager, ROLE.advertiser) def getDevListByAd(request): # type:(WSGIRequest)->JsonResponse """ 为了加快广告加载速度,不默认返回设备列表,只有在用户点击广告的时候才会请求设备列表 :param request: :return: """ adId = request.GET.get('adId') devList = Advertisement.get_by_adId(adId=adId).devList return JsonResponse({'result': 1, 'description': '', 'payload': {'total': len(devList), 'dataList': devList }}) @require_POST @error_tolerate(nil = JsonErrorResponse(u'添加广告失败')) @permission_required(ROLE.manager, ROLE.advertiser) def addAd(request): # type:(WSGIRequest)->JsonResponse """ 添加广告 广告主和厂商都可以添加广告 广告主只可配置 publicAdAvailable的广告主 :param request: :return: """ return JsonResponse({'result': 1, 'description': '', 'payload': {}}) @require_POST @error_tolerate(nil = JsonErrorResponse(u'编辑广告失败')) @permission_required(ROLE.manager, ROLE.advertiser) def editAd(request): # type:(WSGIRequest)->JsonResponse """ 编辑广告 :param request: :return: """ return JsonResponse({'result': 1, 'description': '', 'payload': {}}) @require_POST @error_tolerate(nil = JsonErrorResponse(u'删除广告失败')) @permission_required(ROLE.manager, ROLE.advertiser) def deleteAd(request): # type:(WSGIRequest)->JsonResponse """ 删除广告 :param request: :return: """ return JsonResponse({'result': 1, 'description': '', 'payload': {}}) ###: 各种过滤器 @error_tolerate(nil = JsonErrorResponse(u'获取经销商列表失败')) @permission_required(ROLE.manager) def getDealerList(request): # type:(WSGIRequest)->JsonResponse """ 获取经销商列表 :param request: :return: """ agentId = request.GET.get('agentId', None) if agentId is None: return JsonResponse({'result': 0, 'description': u'请传入正确的参数', 'payload': {}}) dealers = [{'value': str(dealer.id), 'label': dealer.nickname} for dealer in Dealer.objects(agentId = str(agentId))] return JsonResponse({'result': 1, 'description': '', 'payload': dealers}) @error_tolerate(nil = JsonErrorResponse(u'获取地址列表失败')) @permission_required(ROLE.manager) def getAddressList(request): # type:(WSGIRequest)->JsonResponse """ dealer->group.address :param request: :return: """ dealerId = request.GET.get('id') groupIds = Group.get_group_ids_of_dealer(dealerId) groups = Group.get_groups_by_group_ids(groupIds) if groups is None: return JsonResponse({'result': 1, 'description': '', 'payload': []}) else: groupIdAddressPair = [{'value': k, 'label': v['address']} for k, v in groups.iteritems()] return JsonResponse({'result': 1, 'description': '', 'payload': groupIdAddressPair}) @error_tolerate(nil = JsonErrorResponse(u'获取设备列表失败')) @permission_required(ROLE.manager) def getDevList(request): # type:(WSGIRequest)->JsonResponse """ 广告系统获取设备列表 :param request: :return: """ groupId = request.GET.get('id') deviceNos = Device.get_devNos_by_group([groupId]) devs = Device.get_dev_by_nos(deviceNos) return JsonResponse( { 'result': 1, 'description': '', 'payload': [ {'value': deviceNo, 'label': dev['logicalCode']} for deviceNo, dev in devs.items() ] if deviceNos else [] } ) ### 查看设备被分配的广告列表 @error_tolerate(nil = JsonErrorResponse(u'查看设备广告列表失败')) @permission_required(ROLE.manager) def getDeviceAllocatedAds(request): # type:(WSGIRequest)->JsonResponse """ :param request: :return: """ logicalCode = request.GET.get('logicalCode') return JsonResponse({'result': 1, 'description': '', 'payload': {'total': 0, 'dataList': []}}) ### 广告数据报表 @error_tolerate(nil = JsonErrorResponse(u'获取趋势列表失败')) @permission_required(ROLE.manager, ROLE.advertisement, ROLE.advertiser) def getAdFansTrend(request): # type:(WSGIRequest)->JsonResponse """ 获取广告效果趋势 :param request: :return: """ currentUser = request.user # type: cast(Union[Advertisement, Advertiser, Manager]) query = prepare_query(request.GET) queryDict = query.raw delta = query.attrs['dateTimeAdded__lte'] - query.attrs['dateTimeAdded__gte'] # type: datetime.timedelta if delta.days > 90: return JsonErrorResponse(u'只支持查询最远至90天前的数据') #: TODO to refactor 引入校验schema if 'adId' in queryDict: queryDict['adId'] = int(queryDict['adId']) if is_manager(currentUser): queryDict['managerId'] = str(currentUser.id) elif is_advertiser(currentUser): queryDict['advertiserId'] = str(currentUser.id) elif is_advertisement(currentUser): queryDict['adId'] = int(currentUser.adId) matchStage = { 'createdDate': { '$gte': queryDict.pop('startTime'), '$lte': queryDict.pop('endTime') }, } matchStage.update(queryDict) projectStage = { '_id': 0, 'clicks': 1, 'createdDate': 1, 'fans': {'$cond': ['$converted', 1, 0]}, 'maleFans': '$features.sex.is_male', 'femaleFans': '$features.sex.is_female' } projectStage.update(dict.fromkeys(AdRecord.filter_fields(), 1)) groupStage = { '_id': '$createdDate', 'clicks': {'$sum': '$clicks'}, 'fans': {'$sum': '$fans'}, 'show': {'$sum': '$clicks'}, 'maleFans': {'$sum': '$maleFans'}, 'femaleFans': {'$sum': '$femaleFans'} } aggregates = AdRecord.get_collection().aggregate( [ {'$project': projectStage}, {'$match': matchStage}, {'$group': groupStage}, {'$addFields': {'time': '$_id'}}, {'$sort': {'time': 1}}, ] ) return JsonResponse({'result': 1, 'description': '', 'payload': list(aggregates)}) @permission_required(ROLE.manager) def getAdMoneyTrend(request): # type:(WSGIRequest)->JsonResponse """ 收益趋势 :param request: :return: """ # TODO 待讨论 return JsonResponse({'result': 1, 'description': '', 'payload': []}) @error_tolerate(nil = DefaultJsonErrorResponse) @permission_required(ROLE.manager, ROLE.advertisement, ROLE.advertiser) def getAdFansDetail(request): # type:(WSGIRequest)->JsonResponse """ 获取广告效果详情列表 :param request: :return: """ query = prepare_query(request.GET) currentUser = request.user # type: cast(Union[Advertisement, Advertiser, Manager]) if is_manager(currentUser): query.attrs['managerId'] = str(currentUser.id) elif is_advertiser(currentUser): query.attrs['advertiserId'] = str(currentUser.id) elif is_advertisement(currentUser): query.attrs['adId'] = int(currentUser.adId) cursor = AdRecord.objects(converted=True, **query.attrs) total = cursor.count() pagedRecords = cursor.order_by('-dateTimeAdded').paginate(pageIndex=query.pageIndex, pageSize=query.pageSize) # type: List[AdRecord] records = [ r.to_dict() for r in pagedRecords ] return JsonResponse({'result': 1, 'description': None, 'data': {'total': total, 'dataList': records}}) @error_tolerate(nil=DefaultJsonErrorResponse) def getPayAfterAd(request): # type:(WSGIRequest)->JsonResponse """ 获取支付后广告链接(蓝牙payAfter页面) :param request: :return: """ logicalCode = request.GET.get('logicalCode', None) if not logicalCode: logger.debug('no logical code.') return JsonOkResponse(description='no ads available') device = Device.get_dev_by_logicalCode(logicalCode) if not device: logger.debug('no device find.') return JsonOkResponse(description='no ads available') ua = request.META.get('HTTP_USER_AGENT', '') user = request.user # type: MyUser ad_dict = Advertisement.fetch_payafter_ad(ua, user, device.owner, device) logger.debug('ad dict is {}'.format(ad_dict)) if not ad_dict: return JsonOkResponse(description='no ads available') else: return JsonResponse({'result': 1, 'description': u'', 'payload': ad_dict}) def taskList(request): # type:(WSGIRequest)->JsonResponse """ 广告适配系统 :param request: :return: """ try: user = request.user # type: cast(MyUser) devNo = request.GET.get('devNo') if not devNo: return JsonResponse({'result': 0, 'description': u'请首先扫码', 'payload': {}}) device = Device.get_dev(devNo) if not device: return JsonResponse({'result': 0, 'description': u'设备不存在', 'payload': {}}) ads = get_available_ads_by_user(device, user) logger.debug('%s got ads(%s) on device(logicalCode=%s)' % (repr(user), ads, device['logicalCode'])) allocated_ads = [{'id': ad.adId, 'name': ad.name, 'word': ad.word, 'qrcode': ad.img} for ad in ads] random.shuffle(allocated_ads) return JsonResponse({'result': 1, 'description': None, 'payload': {'taskList': allocated_ads}}) except Exception as e: logger.exception(e) return JsonResponse({'result': 1, 'description': None, 'payload': {'taskList': []}}) ### 广告主 @error_tolerate(nil = JsonErrorResponse(u'注册失败')) def registerAdvertiser(request): # type:(WSGIRequest)->JsonResponse """ 注册成为广告主 :param request: :return: """ payload = json.loads(request.body) try: Advertiser.create_user(**payload) except NotUniqueError: return JsonErrorResponse(description = u'该手机号已注册') return JsonResponse({'result': 1, 'description': None, 'payload': {}}) @error_tolerate(nil = JsonErrorResponse(u'登录失败')) def advertiserLogin(request): # type:(WSGIRequest)->JsonResponse """ 广告主登录 :param request: :return: """ payload = json.loads(request.body) username, password = payload['username'], payload['password'] return advertiser_login(request, logger, username, password) @error_tolerate(nil = JsonErrorResponse(u'修改密码失败')) @permission_required(ROLE.advertiser) def changeAdvertiserPassword(request): # type: (WSGIRequest)->JsonResponse currentAdvertiser = request.user # type: cast(Advertiser) payload = json.loads(request.body) password = payload['password'] if PASSWORD_RE.match(password) is None: return JsonErrorResponse(description=u'密码必须大于8位,只能是数字或字母或常见特殊符号') currentAdvertiser.set_password(payload['password']) return JsonResponse({'result': 1}) @error_tolerate(nil = JsonErrorResponse(u'获取广告主信息失败')) @permission_required(ROLE.advertiser) def getAdvertiserInfo(request): # type:(WSGIRequest)->JsonResponse """ 获取广告主信息 :param request: :return: """ user = request.user # type: cast(Advertiser) return JsonResponse( { 'result': 1, 'description': '', 'payload': {'nickname': user.nickname, 'brandName': '', 'quota': user.quota, 'role': ROLE.advertiser } } ) ### others @error_tolerate(nil = JsonErrorResponse(u'生成报表失败')) @permission_required(ROLE.manager) def exportExcel(request): # type:(WSGIRequest)->JsonResponse """ 广告效果报表生成excel :param request: :return: """ manager = request.user # type: cast(Manager) def get_offline_task_name(task_type, user, **kwargs): # type: (basestring, UserSearchable, Dict)->basestring tmp_list = [task_type, user.username] if 'adId' in kwargs and kwargs['adId']: tmp_list.append(u'广告_%s' % (kwargs['adId'],)) elif 'devNo' in kwargs: logicalCode = Device.get_logicalCode_by_devNo(kwargs['devNo']) tmp_list.append(u'设备号_%s' % (logicalCode,)) elif 'groupId' in kwargs: address = Group.get_group(kwargs['groupId']).get('address', '') tmp_list.append(u'地址_%s' % (address,)) elif 'dealerId' in kwargs: dealerName = Dealer.objects(id = str(kwargs['dealerId'])).get().nickname tmp_list.append(u'经销商_%s' % (dealerName,)) elif 'agentId' in kwargs: agentName = Agent.objects(id = str(kwargs['agentId'])).get().nickname tmp_list.append(u'代理商_%s' % (agentName,)) tmp_list.append(u'%s至%s' % (kwargs['startTime'], kwargs['endTime'])) tmp_list.append(str(utils_datetime.generate_timestamp_ex())) return '-'.join(tmp_list).replace("/", "_") query = prepare_query(request.GET) offline_task_name = get_offline_task_name(task_type = OfflineTaskType.AD_REPORT, user = manager, **(query.raw)) file_path, offline_task = OfflineTask.issue_export_report(offline_task_name = offline_task_name, process_func_name = 'generate_ad_excel_report', task_type = OfflineTaskType.AD_REPORT, userid = str(manager.id), role = ROLE.manager) #: make queryAttrs serializable queryAttrs = query.attrs queryAttrs['dateTimeAdded__lte'] = dt_to_timestamp(queryAttrs['dateTimeAdded__lte']) queryAttrs['dateTimeAdded__gte'] = dt_to_timestamp(queryAttrs['dateTimeAdded__gte']) task_caller(func_name = offline_task.process_func_name, offline_task_id = str(offline_task.id), filepath = file_path, queryAttrs = queryAttrs) return JsonResponse({ 'result': 1, 'description': u"请前往离线任务查看任务处理情况", 'payload': str(offline_task.id)}) def getDialogAd(request): # type:(WSGIRequest)->JsonResponse # TODO 支付前广告,待补充 return JsonResponse({ 'result': 1, 'description': '', 'payload': {'dataList': []}}) def getBannerAd(request): # type:(WSGIRequest)->JsonResponse logicalCode = request.GET.get('logicalCode') dev = Device.get_dev_by_logicalCode(logicalCode) dealer = Dealer.objects(id=str(dev['ownerId'])).only('agentId').get() # type: Dealer agent = Agent.objects(id=str(dealer.agentId)).only('managerId').get() # type: Agent ad = Advertisement.filter_by_top_show(managerId=agent.managerId).first() # type: Optional[Advertisement] if not ad: return JsonOkResponse(payload={}) else: return JsonOkResponse(payload={'link': ad.link, 'img': ad.img}) @permission_required(ROLE.supermanager) @error_tolerate(nil = DefaultJsonErrorResponse) def getAdWords(request): # type:(WSGIRequest)->JsonResponse pageIndex = int(request.GET.get('pageIndex', 1)) pageSize = int(request.GET.get('pageSize', 10)) searchKey = request.GET.get('searchKey') startTime = request.GET.get('startTime') endTime = request.GET.get('endTime') query = {} if startTime is not None and endTime is not None: query['dateTimeAdded__lte'] = date_to_datetime_ceiling(endTime) query['dateTimeAdded__gte'] = date_to_datetime_floor(startTime) total = AdWord.objects(**query).search(searchKey).count() qs = AdWord.objects(**query).search(searchKey).paginate(pageIndex=pageIndex, pageSize=pageSize) # type: Iterable[AdWord] return JsonOkResponse(payload={'dataList': [ _.to_dict() for _ in qs ], 'total': total}) @permission_required(ROLE.supermanager) @error_tolerate(nil = DefaultJsonErrorResponse) def addAdWord(request): # type:(WSGIRequest)->JsonResponse payload = parse_json_payload(request.body) AdWord(**payload).save() return JsonOkResponse() @permission_required(ROLE.supermanager) @error_tolerate(nil = DefaultJsonErrorResponse) def editAdword(request): # type:(WSGIRequest)->JsonResponse payload = parse_json_payload(request.body) ad_word = AdWord.objects(id=payload['id']).get() updated = ad_word.update(**payload) if updated: return JsonOkResponse(payload={'description': u'更新成功'}) else: return JsonErrorResponse(payload={'description': u'更新失败'}) @permission_required(ROLE.supermanager) @error_tolerate(nil = DefaultJsonErrorResponse) def deleteAdword(request): # type:(WSGIRequest)->JsonResponse payload = json.loads(request.body) ids = payload.get('ids') if not ids: return JsonErrorResponse(description=u'') AdWord.objects(id__in=ids).delete() # type: AdWord return JsonOkResponse() @error_tolerate(nil = DefaultJsonErrorResponse) def userGetAdword(request): # type:(WSGIRequest)->JsonResponse try: user = request.user # type: cast(MyUser) ad_word = AdWord.get_random_one() # type: AdWord if ad_word is not None: ad_word.incr_count(1) title = ad_word.title if not ad_word.autoPass: return MyJsonOkResponse({'result': 1, 'description': '', 'payload': {'content': ad_word.promotionUrl}}) tbkCode = serviceCache.get('tbk_{}'.format(str(ad_word.id))) if not tbkCode: from library.aliopen.tbkapi import CreatTaokoulingReq request = CreatTaokoulingReq(appKey = '33175347', appSecret = 'c4e2d8426d1d08ec49ef00bc40ac94d5') request.setParams(url = ad_word.promotionUrl) rv = xmltodict.parse(request.getResponse().content) logger.debug('tbk code rv for {} is: {}'.format(str(ad_word.id), str(rv))) tokens = rv['tbk_tpwd_create_response']['data']['model'].split(' ') tbkCode = '{} {} {}'.format(tokens[0], tokens[1], title) logger.debug('new tbk code is: {}'.format(tbkCode)) serviceCache.set('tbk_{}'.format(str(ad_word.id)), tbkCode, 60 * 60 * 2) return MyJsonOkResponse({'result': 1, 'description': '', 'payload': {'content': tbkCode}}) else: logger.debug('cache tbk code is: {}'.format(tbkCode)) return MyJsonOkResponse({'result': 1, 'description': '', 'payload': {'content': tbkCode}}) except Exception as e: logger.error('exception = {}; id = {}'.format(traceback.format_exc(), str(ad_word.id))) return MyJsonOkResponse({'result': 1, 'description': '', 'payload': {'content': ''}}) @error_tolerate(nil = DefaultJsonErrorResponse) def alipayCallback(request, uidType): # type:(WSGIRequest, str)->JsonResponse try: uidType = uidType.upper() payload = json.loads(request.body) if uidType == 'CPM': # uid = payload.get('uid') # bid = payload.get('bid') # try: # AdLog.objects.get(openId=uid, bidid=bid, status__ne='finished').update(status='finished', finishedData=request.body, finishedTime=datetime.datetime.now()) # except: # logger.info(traceback.format_exc()) pass elif uidType == 'RH': uid = payload.get('uid') urlId = payload.get('ext', {}).get('id') redpack = Redpack.take_effect(openId = uid, urlId = urlId, **{'RHCallback': request.body}) if redpack: RedpackBuilder._set_alipay_key(uid, redpack.factoryCode, urlId, redpack.money.mongo_amount, showType = redpack.showType) return JsonResponse({"status": 1, "alipayOrderId": urlId}) elif uidType == 'LX': pass try: AliAdLog.objects(campaignId = payload.get('campaignId'), bid = payload.get('bid')).upsert_one( uid = payload.get('uid'), uidType = payload.get('uidtype'), campaignId = payload.get('campaignId'), bid = payload.get('bid'), tradeTS = payload.get('tradetimestamp'), commission = payload.get('commission')) except Exception as e: logger.error(e) finally: return JsonResponse({'success': True, 'errorMsg': '', 'result': True})