123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089 |
- # -*- coding: utf-8 -*-
- # !/usr/bin/env python
- import datetime
- import hashlib
- import logging
- import re
- import ssl
- import subprocess
- import time
- import urllib2
- import simplejson as json
- import xmltodict
- from django.http import HttpResponse, JsonResponse, HttpResponseBadRequest
- from django.views.generic.base import View
- from pymongo.results import UpdateResult
- from typing import TYPE_CHECKING, Iterable, Dict
- from voluptuous import MultipleInvalid
- from apilib.monetary import RMB
- from apilib.utils import generate_RSA_key_pairs
- from apilib.utils_datetime import to_datetime
- from apilib.utils_string import cn
- from apps import serviceCache
- from apps.web import district
- from apps.web.ad.models import Advertisement, AdStatistics
- from apps.web.agent.models import MoniApp
- from apps.web.common import ALIPAY_NOTIFY_URL
- from apps.web.common.models import AddressType, WithdrawRecord, WithdrawBanks, WithdrawDistrict, \
- WithdrawBranchBanks, WithdrawBankCard
- from apps.web.common.models import FrontendLog, FAQ
- from apps.web.common.transaction.pay.alipay import AliPayWithdrawNotifier
- from apps.web.common.utils import WechatMessage, WechatText, WechatMenu, WechatSubscribe, WechatUnSubscribe, \
- WechatScanEvent, MessageHandler
- from apps.web.constant import Const, AppPlatformType, AdSpace
- from apps.web.core import ROLE
- from apps.web.core.exceptions import InvalidFileSize, InvalidFileName
- from apps.web.core.file import AliOssFileUploader, WechatSubscriptionAccountVerifyFileUploader
- from apps.web.core.models import WechatPayApp, AliApp, AliUserAgreementSign, AliFundAccountBookApp
- from apps.web.core.utils import DefaultJsonErrorResponse, JsonOkResponse, JsonErrorResponse
- from apps.web.dealer.models import Dealer
- from apps.web.device.models import Device
- from apps.web.device.timescale import PowerManager
- from apps.web.helpers import PlatformPayGatewayUtil
- from apps.web.user.models import MoniUser, AskRobot
- from apps.web.user.models import MyUser
- from apps.web.user.utils import get_consume_order
- from apps.web.utils import error_tolerate, permission_required, concat_dealer_main_page_url, \
- concat_front_end_url, concat_user_center_url, concat_user_login_entry_url
- from apps.web.validation import SaveWithdrawBankCardSchema, SaveWithdrawAlipaySchema, SaveWithdrawWechatSchema
- from library.misc import BankAPI
- if TYPE_CHECKING:
- from apps.web.core.db import RoleBaseDocument
- from django.core.handlers.wsgi import WSGIRequest
- from apps.web.device.models import DeviceDict
- from apps.web.core.adapter.bolai_gateway import ChargingGatewayBox
- from apps.web.core.payment.ali import AliPayGateway
- logger = logging.getLogger(__name__)
- @permission_required(ROLE.dealer, ROLE.agent, ROLE.supermanager)
- def loadDistrictData(request):
- return JsonResponse({'result': 1, 'description': None, 'payload': district.DISTRICT})
- @error_tolerate(nil = lambda: JsonResponse({'result': 0, 'description': u'系统错误'}), logger = logger)
- def logFrontend(request):
- """
- 收集来自前端的日志
- :param request:
- :return:
- """
- if not request.body:
- return JsonResponse({'result': 1, 'description': u'BODY为空'})
- payload = json.loads(request.body)
- if 'onlyLog' in payload and payload['onlyLog']:
- logger.debug('--[BLUETOOTH]onlyLog--' + str(payload) + '--eof onlyLog--')
- else:
- FrontendLog(**payload).save()
- return JsonResponse({'result': 1, 'description': u'记录成功'})
- def getFAQ(request):
- """
- 使用的常见说明
- :param request:
- :return:
- """
- current_user = request.user # type: RoleBaseDocument
- faqs = FAQ.get_by_role(current_user.role)
- return JsonResponse({
- "result": 1,
- "description": None,
- "payload": {'dataList': [faq.to_dict() for faq in faqs], 'total': len(faqs)}
- })
- def getNotifications(request):
- """
- 做一个临时的用户通知 如果可以使用京东引流 就通知经销商
- :param request:
- :return:
- """
- return JsonResponse(
- {
- "result": 1,
- "description": None,
- "payload": {
- "total": 0,
- "dataList": []
- }
- }
- )
- # @trace_call()
- # def wx_biz_dispatch(request):
- # def response_xml(payload):
- # xmlData = dicttoxml.dicttoxml(payload, attr_type = False, custom_root = 'xml', cdata = True)
- # return HttpResponse(xmlData)
- #
- # logger.info('has receive wechat dispatch message')
- #
- # def check_signature(signature, timestamp, nonce, token):
- # args = [token, timestamp, nonce]
- # args.sort()
- # return hashlib.sha1(''.join(args).encode('utf-8')).hexdigest() == signature
- #
- # if request.method == 'GET':
- # signature = request.GET['signature']
- # timestamp = request.GET['timestamp']
- # nonce = request.GET['nonce']
- # echostr = request.GET['echostr']
- # if check_signature(signature, timestamp, nonce, settings.MY_WECHAT_USER_TOKEN):
- # return HttpResponse(str(echostr))
- # else:
- # return HttpResponse('')
- # else:
- # replyData = event_reply(request)
- # logger.info('calc replaydata = %s' % replyData)
- # if replyData:
- # return response_xml(replyData)
- #
- # return HttpResponse('success')
- @error_tolerate(nil = lambda: JsonResponse({'result': 0, 'description': u'文件操作有误'}), logger = logger)
- @permission_required(ROLE.dealer, ROLE.manager, ROLE.myuser, ROLE.advertiser, ROLE.supermanager, ROLE.subaccount)
- def uploadFile(request):
- """
- 公共的文件上传接口
- TODO 需要注意安全选项!!
- ..added 2018/03/21 添加参数判断安全路径
- :param request:
- :return:
- """
- UPLOADER_MAP = {
- 'wechatValidate': WechatSubscriptionAccountVerifyFileUploader,
- 'public': AliOssFileUploader
- }
- Uploader = UPLOADER_MAP.get(request.GET.get('category', 'public'))
- uploader = Uploader(inputFile = request.FILES.getlist('file')[0], uploadType = request.GET.get('type', 'others'))
- logger.info('[upload] %s is being used' % (repr(uploader),))
- try:
- outputUrl = uploader.upload()
- return JsonResponse({'result': 1, 'description': '', 'payload': outputUrl})
- except InvalidFileSize, e:
- logger.info(
- '%s(id=%s)\'s uploaded file reached limit' % (request.user.__class__.__name__, str(request.user.id),))
- return JsonResponse({'result': 0, 'description': e.message, 'payload': {}})
- except InvalidFileName, e:
- logger.info(
- '%s(id=%s)\'s uploaded file name is not legal' % (request.user.__class__.__name__, str(request.user.id),))
- return JsonResponse({'result': 0, 'description': e.message, 'payload': {}})
- @error_tolerate(nil = DefaultJsonErrorResponse, logger = logger)
- @permission_required(ROLE.manager, ROLE.advertisement, ROLE.advertiser, ROLE.dealer, ROLE.agent, ROLE.subaccount)
- def getAddressType(request):
- # type: (WSGIRequest)->JsonResponse
- """
- 获取地址类型
- :param request:
- :return:
- """
- addressTypes = AddressType.objects.all().order_by('-showWeight') # type: Iterable[AddressType]
- dataList = [{'value': addressType.value, 'label': addressType.label} for addressType in addressTypes]
- return JsonResponse(
- {
- 'result': 1,
- 'description': '',
- 'payload':
- {
- 'dataList': dataList,
- 'total': len(dataList)
- }
- }
- )
- @error_tolerate(nil = DefaultJsonErrorResponse, logger = logger)
- def getVersion(request):
- version = subprocess.check_output(["git", "log", "-1", "--format=%cd"]).strip()
- return JsonOkResponse(payload = {'version': version})
- @error_tolerate(nil = DefaultJsonErrorResponse, logger = logger)
- @permission_required(ROLE.supermanager, ROLE.manager)
- def generateNewAppKeyPair(request):
- # type: (WSGIRequest)->JsonResponse
- """
- 生成新的应用私钥公匙对, 返回给前台私钥的地址和公钥的内容 (方便前台去粘贴给支付宝)
- :param request:
- :return:
- """
- payload = json.loads(request.body)
- appid = payload.get('appid')
- if not appid:
- return JsonErrorResponse(description = u'appid未传入')
- key = 'alipay_app_private_{appid}_{timestamp}'.format(appid = appid, timestamp = int(time.time() * 1000))
- pair = generate_RSA_key_pairs()
- serviceCache.set(key, pair.private, 3600)
- appPublicKeyContent = re.sub(r'-.*', '', pair.public)
- return JsonOkResponse(description = u'生成成功', payload = {'path': key, 'appPublicKeyContent': appPublicKeyContent})
- @error_tolerate(nil = DefaultJsonErrorResponse, logger = logger)
- @permission_required(ROLE.supermanager, ROLE.manager)
- def verifyAppKeyPairs(request):
- # type: (WSGIRequest)->JsonResponse
- """
- :param request:
- :return:
- """
- return JsonErrorResponse(description = u'暂不开放')
- @error_tolerate(nil = DefaultJsonErrorResponse)
- @permission_required(ROLE.supermanager)
- def getAliAppList(request):
- # type: (WSGIRequest)->JsonResponse
- """
- 获取阿里APP列表
- :param request:
- :return:
- """
- page_index = int(request.GET.get('pageIndex', 1))
- page_size = int(request.GET.get('pageSize', 10))
- search_key = request.GET.get('searchKey', None)
- total, items = AliApp.list(page_index = page_index, page_size = page_size, search_key = search_key)
- return JsonResponse({'result': 1,
- 'description': None,
- 'payload': {
- 'total': total,
- 'dataList': items
- }
- })
- @error_tolerate(nil = DefaultJsonErrorResponse)
- @permission_required(ROLE.supermanager)
- def editAliApp(request):
- # type: (WSGIRequest)->JsonResponse
- """
- 编辑阿里APP
- :param request:
- :return:
- """
- payload = json.loads(request.body) # type: dict
- id = payload.pop('id', None)
- update = payload
- if id:
- query = {'_id': id}
- else:
- query = {'appid': payload.get('appid')}
- result = AliApp.get_collection().update_one(query, update, upsert = True) # type: UpdateResult
- return JsonResponse({
- 'result': 1 if (result.modified_count == 1 or result.upserted_id) else 0,
- 'description': u'修改成功' if (result.modified_count == 1 or result.upserted_id) else u'修改失败',
- 'payload': {
- 'id': str(result.upserted_id) if result.upserted_id else id
- }})
- @error_tolerate(nil = DefaultJsonErrorResponse, logger = logger)
- @permission_required(ROLE.supermanager, ROLE.manager)
- def getWechatFundApp(request):
- # type: (WSGIRequest)->JsonResponse
- """
- 更改微信资金平台APP信息
- :param request:
- :return:
- """
- appid = request.GET.get('appid')
- mchid = request.GET.get('mchid')
- app = WechatPayApp.objects(appid = appid, mchid = mchid).first() # type: WechatPayApp
- if not app:
- return JsonOkResponse(payload = {})
- else:
- return JsonOkResponse(payload = app.to_dict())
- @error_tolerate(nil = DefaultJsonErrorResponse)
- @permission_required(ROLE.supermanager, ROLE.manager)
- def editWechatFundApp(request):
- # type: (WSGIRequest)->JsonResponse
- """
- 编辑阿里APP
- :param request:
- :return:
- """
- payload = json.loads(request.body) # type: dict
- id = payload.pop('id', None)
- update = payload
- if id:
- query = {'_id': id}
- else:
- query = {'appid': payload.get('appid')}
- result = WechatPayApp.get_collection().update_one(query, update, upsert = True) # type: UpdateResult
- return JsonResponse({
- 'result': 1 if (result.modified_count == 1 or result.upserted_id) else 0,
- 'description': u'修改成功' if (result.modified_count == 1 or result.upserted_id) else u'修改失败',
- 'payload': {
- 'id': str(result.upserted_id) if result.upserted_id else id
- }})
- @error_tolerate(nil = DefaultJsonErrorResponse)
- @permission_required(ROLE.supermanager, ROLE.manager)
- def getWechatAppList(request):
- # type: (WSGIRequest)->JsonResponse
- """
- 获取微信支付APP列表
- :param request:
- :return:
- """
- page_index = int(request.GET.get('pageIndex', 1))
- page_size = int(request.GET.get('pageSize', 10))
- search_key = request.GET.get('searchKey', None)
- total, items = WechatPayApp.list(page_index = page_index, page_size = page_size, search_key = search_key)
- return JsonResponse({'result': 1,
- 'description': None,
- 'payload': {
- 'total': total,
- 'dataList': items
- }
- })
- def event_reply(request):
- logger.info('has receive event_reply dispatch message = %s' % request.body)
- raw = xmltodict.parse(request.body)['xml']
- msgType = raw.get('MsgType', '')
- event = raw.get('Event', '')
- if msgType == 'event' and event in ['subscribe', 'unsubscribe']:
- moniOpenId = raw['FromUserName']
- rawAppId = raw['ToUserName']
- try:
- moniApp = MoniApp.objects.get(rawAppId = rawAppId)
- except Exception, e:
- return ''
- try:
- moniUser = MoniUser.objects.filter(moniAppId = moniApp.appId, moniOpenId = moniOpenId).first()
- if moniUser:
- if event == 'subscribe':
- moniUser.subTime = datetime.datetime.now()
- moniUser.isSubscribe = True
- AskRobot.reply(event, moniOpenId, '', moniApp.appId, moniApp.secret, openId = moniUser.openId)
- else:
- moniUser.unsubTime = datetime.datetime.now()
- moniUser.isSubscribe = False
- moniUser.save()
- else:
- user = MyUser.objects.filter(managerialOpenId = raw['FromUserName']).first()
- if user is None:
- newUser = MoniUser(moniAppId = moniApp.appId, moniOpenId = moniOpenId,
- subTime = datetime.datetime.now(), isSubscribe = True)
- newUser.save()
- else:
- AskRobot.reply(event, moniOpenId, '', moniApp.appId, moniApp.secret, openId = user.openId,
- agentId = user.agentId)
- except Exception, e:
- logger.exception('event_reply error=%s' % e)
- return ''
- elif msgType == 'text':
- try:
- # 如果是监督号,就直接回复。如果不是监督号,可能是用户的管理app,这个时候,需要走另外的流程。用户付费后关注
- moniApp = MoniApp.objects.filter(rawAppId = raw['ToUserName']).first()
- if moniApp:
- try:
- logger.info('111')
- moniUser = MoniUser.objects.filter(moniAppId = moniApp.appId,
- moniOpenId = raw['FromUserName']).first()
- if moniUser and moniUser.openId and moniUser.subAgentId:
- logger.info('222')
- logger.info('content = %s,openId=%s' % (raw['Content'], moniUser.openId))
- AskRobot.reply(event, raw['FromUserName'], raw['Content'], moniApp.appId, moniApp.secret,
- openId = moniUser.openId, agentId = moniUser.subAgentId)
- else:
- logger.info('333')
- user = MyUser.objects.filter(managerialOpenId = raw['FromUserName']).first()
- if user is None:
- logger.info('444')
- return {'MsgType': 'text', 'FromUserName': raw['ToUserName'],
- 'ToUserName': raw['FromUserName'], 'Content': u'没有找到您在平台扫码使用设备的任何信息',
- 'CreateTime': int(time.time())}
- AskRobot.reply(event, raw['FromUserName'], raw['Content'], moniApp.appId, moniApp.secret,
- openId = user.openId, agentId = user.agentId)
- except Exception, e:
- logger.exception('event_reply error=%s' % e)
- return ''
- logger.info('555')
- return ''
- except Exception, e:
- return ''
- return ''
- @error_tolerate(logger = logger, nil = JsonErrorResponse(u'故障部件图片存储失败,请重新上传'))
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def uploadFaultPartPic(request):
- # type: (WSGIRequest)->JsonResponse
- files = request.FILES.getlist('file')
- if not len(files):
- return JsonResponse({'result': 0, 'description': u'故障部件图片存储失败,请重新上传', 'payload': ''})
- uploader = AliOssFileUploader(inputFile = request.FILES.getlist('file')[0], uploadType = 'fault')
- logger.info('[uploadFaultPartPic] %s is being used' % (repr(uploader),))
- try:
- outputUrl = uploader.upload()
- return JsonResponse({'result': 1, 'description': '', 'payload': outputUrl})
- except InvalidFileSize, e:
- logger.info(
- '%s(id=%s)\'s uploaded file reached limit' % (request.user.__class__.__name__, str(request.user.id),))
- return JsonResponse({'result': 0, 'description': e.message, 'payload': {}})
- except InvalidFileName, e:
- logger.info(
- '%s(id=%s)\'s uploaded file name is not legal' % (request.user.__class__.__name__, str(request.user.id),))
- return JsonResponse({'result': 0, 'description': e.message, 'payload': {}})
- def queryExpressInfo(request):
- orderNo = request.GET.get('orderNo')
- bodys = {}
- url = 'https://kuaidid.market.alicloudapi.com/danhao'
- bodys['com'] = ''
- bodys['src'] = orderNo
- from six.moves.urllib import parse
- post_data = parse.urlencode(bodys)
- request = urllib2.Request(url, post_data)
- request.add_header('Authorization', 'APPCODE ' + Const.KUAIDI_API_APPCODE)
- request.add_header('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8')
- ctx = ssl.create_default_context()
- ctx.check_hostname = False
- ctx.verify_mode = ssl.CERT_NONE
- response = urllib2.urlopen(request, timeout = 15, context = ctx)
- content = response.read()
- if (content):
- result = json.loads(content)
- if result['status'] == 200:
- resultList = []
- for info in result['msg']['context']:
- resultList.append({'time': datetime.datetime.fromtimestamp(info['time']).strftime(Const.DATETIME_FMT),
- 'desc': info['desc']})
- return JsonOkResponse(payload = {'dataList': resultList})
- else:
- return JsonErrorResponse(description = u'无法获取到订单详细信息')
- else:
- return JsonErrorResponse(description = u'无法获取到订单详细信息')
- @error_tolerate(logger = logger)
- def aliNotify(request):
- payload = request.POST.dict() # type: Dict
- logger.info('ali common notify: %s' % str(payload))
- if 'service' in payload and payload['service'] == 'alipay.service.check':
- biz_content = xmltodict.parse(payload['biz_content'])['XML']
- app = AliApp.objects(appid = biz_content['AppId']).first() # type: AliApp
- gateway = app.new_gateway(app_platform_type = AppPlatformType.ALIPAY) # type: AliPayGateway
- if gateway.check(data = payload, pop_sign_type = False):
- sign = gateway.client._sign('<success>true</success>')
- return HttpResponse(
- '<?xml version="1.0" encoding="GBK"?><alipay><response><success>true</success></response><app_cert_sn>{}</app_cert_sn><sign>{}</sign><sign_type>RSA2</sign_type></alipay>'.format(
- gateway.client.app_cert_sn, sign))
- if 'msg_method' in payload and payload['msg_method'] == 'alipay.fund.trans.order.changed':
- payload['biz_content'] = json.loads(payload['biz_content'])
- order_no = payload['biz_content']['out_biz_no']
- if WithdrawRecord.is_my(order_no):
- return AliPayWithdrawNotifier(record_cls = WithdrawRecord).do(payload)
- else:
- logger.warn('not support this order. orderNo = {}'.format(order_no))
- return HttpResponse('success')
- elif 'notify_type' in payload and payload['notify_type'] == 'dut_user_sign':
- external_agreement_no = payload['external_agreement_no']
- sign_model = AliUserAgreementSign.objects(externalAgreementNo = external_agreement_no).first()
- if sign_model:
- if payload['status'] == 'NORMAL' and sign_model.attachParas['action'] == 'make_fund_account_book':
- sign_model.agreementNo = payload['agreement_no']
- sign_model.signTime = datetime.datetime.strptime(payload['sign_time'], "%Y-%m-%d %H:%M:%S")
- sign_model.save()
- agreementNo = sign_model.agreementNo
- certNo = sign_model.attachParas['certNo']
- if not AliFundAccountBookApp.objects(agreementNo = agreementNo, certNo = certNo).first():
- bookModel = AliFundAccountBookApp.apply(sign_model)
- create_rv = PlatformPayGatewayUtil.get_ali_isv_pay_gateway().create_fund_accountbook(bookModel)
- if create_rv['code'] == '10000':
- bookModel.appid = create_rv['account_book_id']
- card_info = create_rv['ext_card_info']
- card_info.pop('status')
- bookModel.cardInfo = card_info
- bookModel.save()
- return HttpResponse('success')
- else:
- logger.warn('not support this method = {}'.format(payload['msg_method']))
- return HttpResponse('success')
- @error_tolerate(logger=logger, nil=JsonErrorResponse(description=u"获取订单失败,请刷新"))
- def getReceipt(request): # type: (WSGIRequest)->JsonResponse
- """
- 获取支付结果
- 消费单的结果直接跳转回去
- """
- user = request.user # type: RoleBaseDocument
- order_type = request.GET.get('order_type', 'recharge')
- out_trade_no = request.GET.get('out_trade_no')
- check_code = request.GET.get('check_code', None)
- from apps.web.user.models import RechargeRecord, ConsumeRecord
- if order_type == 'consume':
- record = get_consume_order(out_trade_no) # type: ConsumeRecord
- payload = record.receiptDesc
- else:
- record = RechargeRecord.objects(__raw__={
- '$or': [
- {
- 'wxOrderNo': out_trade_no
- },
- {
- 'orderNo': out_trade_no
- }
- ]}).first() # type: RechargeRecord
- if not record:
- from apps.web.dealer.models import DealerRechargeRecord
- record = DealerRechargeRecord.objects(__raw__={
- '$or': [
- {
- 'wxOrderNo': out_trade_no
- },
- {
- 'orderNo': out_trade_no
- }
- ]}).first() # type: DealerRechargeRecord
- if not record:
- return JsonErrorResponse(description = u'订单获取失败,请重新获取')
- else:
- payload = {
- 'itemName': record.subject,
- 'orderNo': record.orderNo,
- 'payment': RMB.fen_to_yuan(record.totalFee),
- 'homeLink': concat_dealer_main_page_url(),
- 'finishedTime': record.finishedTime,
- 'adInfo': {
- 'adShow': 'noshow'
- }
- }
- if record.product == DealerRechargeRecord.ProductType.SimCard:
- payload.update(
- {'detailLink': concat_front_end_url(
- uri = '/app/payOrderDetail.html?orderNo={}'.format(record.orderNo))})
- return JsonOkResponse(payload = payload)
- else:
- if record.result != RechargeRecord.PayResult.SUCCESS:
- return JsonErrorResponse(description = u'订单回调还未调用')
- payload = {
- 'orderNo': record.orderNo,
- 'payment': record.money,
- 'finishedTime': record.finished_time
- }
- from apps.web.device.models import Device
- # 是否是启动设备的
- start_key = record.startKey
- if start_key:
- payload.update({
- 'startKey': start_key,
- 'devNo': record.devNo,
- 'logicalCode': record.logicalCode,
- 'homeLink': concat_user_login_entry_url(l = record.logicalCode),
- 'serviceLink': concat_user_center_url(l = record.logicalCode)
- })
- else:
- payload.update({
- 'serviceLink': concat_user_center_url(),
- 'homeLink': concat_user_center_url(),
- 'detailLink': concat_front_end_url(
- uri = '/user/index.html#/user/chargeRecordDetail?ownerId={}&id={}'.format(record.ownerId,
- str(record.id)))
- })
- if isinstance(record, RechargeRecord):
- payload['itemName'] = record.subject
- if record.devNo:
- device = Device.get_dev(record.devNo)
- else:
- device = None
- else:
- device = Device.get_dev(record.devNo)
- if record.port:
- payload['itemName'] = cn(u'{major_type}/{logicalCode}-端口{port}'.format(
- major_type = device.majorDeviceType[0:8], logicalCode = record.logicalCode,
- port = record.port))
- else:
- payload['itemName'] = cn(u'{major_type}/{logicalCode}'.format(
- major_type = device.majorDeviceType[0:8], logicalCode = record.logicalCode))
- if not check_code:
- owner = Dealer.objects(id=record.ownerId).first() # type: Dealer
- ad_dict = Advertisement.fetch_payafter_ad(
- ua=request.META.get('HTTP_USER_AGENT', ''), user=request.user, dealer=owner, device=device)
- logger.debug('ad dict is {}'.format(ad_dict))
- payload.update({'adInfo': ad_dict})
- else:
- AdStatistics.inc_make_count(adSpace=AdSpace.PAYAFTER, showType='payAfter_dianjin', gateway='wechat')
- return JsonOkResponse(payload=payload)
- def bolaiEvent(request):
- payload = json.loads(request.body)
- logger.debug('received bolai event: {}'.format(payload))
- gateId = payload.get('gateway_id')
- gateway_dev = Device.get_dev(gateId) # type: DeviceDict
- if gateway_dev is None: # 可能是一体化设备
- rcds = Device.get_collection().find({'gateImei': gateId})
- if rcds.count() == 0:
- return JsonOkResponse()
- gateway_dev = Device.get_dev(rcds[0]['devNo'])
- logger.info('this is gatewayplug device')
- if gateway_dev is None:
- return JsonOkResponse()
- if 'data' in payload and 'node_index' in payload['data']:
- if payload['data']['node_index'] != 0:
- logger.info('this is nodeplug device')
- gateway_adapter = gateway_dev.deviceAdapter # type: ChargingGatewayBox
- node_devno = gateway_adapter.get_node_devNo(str(payload['data']['node_index']))
- node_dev = Device.get_dev(node_devno) # type: DeviceDict
- if not node_dev:
- return JsonOkResponse()
- payload.update({
- 'nodeType': 'node'
- })
- event = node_dev.eventer.getEvent(payload)
- event.do()
- else:
- logger.info('this is gateway device')
- payload.update({
- 'nodeType': 'node'
- })
- event = gateway_dev.eventer.getEvent(payload)
- event.do()
- else:
- payload.update({
- 'nodeType': 'gateway'
- })
- event = gateway_dev.eventer.getEvent(payload)
- event.do()
- return JsonOkResponse()
- def bolaitenEvent(request):
- payload = json.loads(request.body)
- logger.debug('received bolai event: {}'.format(payload))
- devNo = payload.get('gateway_id')
- dev = Device.get_dev(devNo)
- if dev is None:
- return JsonOkResponse()
- if 'data' in payload:
- event = dev.eventer.getEvent(payload)
- event.do()
- return JsonOkResponse()
- @error_tolerate(nil = DefaultJsonErrorResponse)
- @permission_required(ROLE.dealer, ROLE.supermanager, ROLE.myuser)
- def getPowerGraphByDevice(request):
- startTime = to_datetime(request.GET.get('startTime'))
- endTime = to_datetime(request.GET.get('endTime'))
- port = str(request.GET.get('port', '1'))
- device = Device.get_dev_by_logicalCode(request.GET.get('logicalCode')) # type: DeviceDict
- if device.devTypeCode in [Const.DEVICE_TYPE_CODE_CHANGING_YUEWANGTONG]:
- interval = 600
- else:
- interval = device.cycle
- items = PowerManager.instence().get(devNo = device.devNo, port = port, sTime = startTime, eTime = endTime,
- interval = interval)
- return JsonOkResponse(payload = {'dataList': items})
- class WechatFollowView(View):
- def __init__(self, **kwargs):
- super(WechatFollowView, self).__init__(**kwargs)
- self.app = None
- @staticmethod
- def auth_request(request, app): # type:(WSGIRequest, MoniApp) -> bool
- """
- 对微信的请求进行验签
- """
- token = app.appToken
- signature = request.GET.get('signature')
- timestamp = request.GET.get('timestamp')
- nonce = request.GET.get('nonce')
- params = [token, timestamp, nonce]
- params.sort()
- return hashlib.sha1("".join(params)).hexdigest() == signature
- @staticmethod
- def get_followed_app(rawAppId):
- return MoniApp.get_app_by_raw(rawAppId)
- def dispatch(self, request, *args, **kwargs):
- rawAppId = kwargs.pop("rawAppId", "")
- app = self.get_followed_app(rawAppId)
- # 查找是否是入库的app
- if not app:
- logger.warning("[WechatFollowView dispatch], not find app! rawAppId = {}".format(rawAppId))
- return HttpResponseBadRequest()
- # 查找是否通过校验
- if not self.auth_request(request, app):
- logger.warning("[WechatFollowView dispatch], verify server error! params = {}".format(request.GET))
- return HttpResponseBadRequest()
- self.app = app
- return super(WechatFollowView, self).dispatch(request)
- def get(self, request):
- """
- 微信公众号服务器验证token使用 配置的时候只会访问一次
- """
- logger.info("[WechatFollowView GET], verify server success! params = {}, app = {}".format(request.GET, self.app))
- echoStr = request.GET["echostr"]
- return HttpResponse(echoStr)
- def post(self, request):
- """
- 业务请求都在这里
- 大致分为两类
- 1.业务事件(关注、订阅、点击菜单)
- 2.用户互动文字
- """
- logger.info("[WechatFollowView POST], payload = {}, app = {}".format(request.body, self.app))
- message = WechatMessage(request.body)
- if message.isText:
- response = WechatText(message, self.app).handle()
- elif message.isEvent:
- if message.isScanEvent:
- response = WechatScanEvent(message, self.app).handle()
- elif message.isSubscribeEvent:
- response = WechatSubscribe(message, self.app).handle()
- elif message.isUnSubscribeEvent:
- response = WechatUnSubscribe(message, self.app).handle()
- elif message.isMenuEvent:
- response = WechatMenu(message, self.app).handle()
- else:
- response = MessageHandler.defaultResponse()
- else:
- response = MessageHandler.defaultResponse()
- return response
- @permission_required(ROLE.dealer, ROLE.agent, ROLE.supermanager)
- def loadWithdrawArea(request):
- province = request.GET.get("province", None)
- return JsonOkResponse(payload = {'dataList': WithdrawDistrict.get_area(province)})
- @error_tolerate(logger = logger, nil = JsonErrorResponse(description = u"获取数据失败,请刷新"))
- @permission_required(ROLE.dealer, ROLE.agent, ROLE.supermanager)
- def supportedWithdrawBanks(request):
- # type: (WSGIRequest)->JsonResponse
- keyWord = request.GET.get('keyWord', None)
- chooseRange = 'all' # request.GET.get('range', 'wechat')
- if chooseRange == 'all':
- return JsonOkResponse(payload = {'dataList': WithdrawBanks.get_all_banks(keyWord)})
- elif chooseRange == 'wechat':
- return JsonOkResponse(payload = {'dataList': WithdrawBanks.get_wechat_support_banks(keyWord)})
- else:
- return JsonErrorResponse(description = u'参数错误')
- @error_tolerate(logger = logger, nil = JsonErrorResponse(description = u"获取数据失败,请刷新"))
- @permission_required(ROLE.dealer, ROLE.agent, ROLE.supermanager)
- def getWithdrawBankByAccount(request):
- # type: (WSGIRequest)->JsonResponse
- accountCode = request.GET.get('accountCode', None)
- if not accountCode:
- return JsonResponse({'result': 2, 'description': u'银行账号不能为空', 'payload': {}})
- bank_info = BankAPI().get_bank_card_info(card_no = accountCode)
- if bank_info:
- rv = WithdrawBanks.get_by_bank_abbrev_code(bank_info['bankAbbrevCode'])
- if rv:
- return JsonOkResponse(payload = rv)
- else:
- logger.warning('not find this bank: {}'.format(bank_info))
- return JsonResponse({'result': 2, 'description': u'该银行卡不支持', 'payload': {}})
- else:
- return JsonResponse({'result': 2, 'description': u'没有查到该银行账号信息', 'payload': {}})
- @error_tolerate(logger = logger, nil = JsonErrorResponse(description = u"获取数据失败,请刷新"))
- @permission_required(ROLE.dealer, ROLE.agent, ROLE.supermanager)
- def withdrawBranchBankList(request):
- # type: (WSGIRequest)->JsonResponse
- provinceCode = request.GET.get('provinceCode')
- cityCode = request.GET.get('cityCode')
- bankCode = request.GET.get('bankCode')
- keyWord = request.GET.get('keyWord')
- queryset = WithdrawBranchBanks.objects(**{
- 'provinceCode': provinceCode,
- 'cityCode': cityCode,
- 'bankCode': bankCode
- }).search(keyWord)
- rv = [
- {
- 'code': item.code,
- 'name': item.name
- } for item in queryset
- ]
- return JsonOkResponse(payload = {'dataList': rv})
- @error_tolerate(nil = DefaultJsonErrorResponse)
- @permission_required(ROLE.dealer, ROLE.agent)
- def saveWithdrawBankCard(request):
- # type: (WSGIRequest)->JsonResponse
- """
- 添加银行卡
- """
- ownerId = str(request.user.id)
- if WithdrawBankCard.objects.filter(ownerId = ownerId, role = request.user.role).count() > 5:
- return JsonResponse({"result": 2, "description": u"银行卡数量已添加至上限(5),不允许继续添加"})
- try:
- payload = SaveWithdrawBankCardSchema(json.loads(request.body))
- except MultipleInvalid as e:
- logger.exception(e)
- return JsonErrorResponse(description = u"信息不完整")
- if WithdrawBankCard.objects(ownerId = ownerId, role = request.user.role,
- accountCode = payload['accountCode']).first():
- return JsonResponse({"result": 2, "description": u"请勿重复添加"})
- accountType = payload.pop('accountType')
- if accountType == WithdrawBankCard.AccountType.PERSONAL:
- item = WithdrawBankCard.new_personal_withdraw_bank_card(ownerId = ownerId, role = request.user.role, **payload)
- return JsonOkResponse(payload = {"id": str(item.id)})
- else:
- return JsonErrorResponse(description = u"不支持添加对公提现银行卡,请您开通商户。")
- @error_tolerate(nil = DefaultJsonErrorResponse)
- @permission_required(ROLE.dealer, ROLE.agent)
- def unbindWithdrawBankCard(request):
- # type: (WSGIRequest)->JsonResponse
- ownerId = str(request.user.id)
- payload = json.loads(request.body)
- accountCode = payload.get('accountCode')
- if not accountCode:
- return JsonResponse({"result": 2, "description": u"参数错误,请刷新后重试"})
- try:
- card = WithdrawBankCard.objects.get(ownerId = ownerId, role = request.user.role, accountCode = accountCode)
- except Exception as e:
- logger.exception(e)
- return JsonResponse({"result": 2, "description": u"解绑定失败,请联系客服解决。"})
- else:
- card.delete()
- return JsonOkResponse()
- @error_tolerate(nil = DefaultJsonErrorResponse)
- @permission_required(ROLE.dealer, ROLE.agent)
- def getWithdrawBankCards(request):
- # type: (WSGIRequest)->JsonResponse
- ownerId = str(request.user.id)
- bankCards = WithdrawBankCard.objects.filter(ownerId = ownerId, role = request.user.role)
- dataList = list()
- for bankCard in bankCards:
- dataList.append(bankCard.to_dict())
- return JsonOkResponse(payload = {'dataList': dataList})
- @error_tolerate(nil = DefaultJsonErrorResponse)
- @permission_required(ROLE.dealer, ROLE.agent)
- def saveAlipayWithdrawInfo(request):
- # type: (WSGIRequest)->JsonResponse
- try:
- payload = SaveWithdrawAlipaySchema(json.loads(request.body))
- except MultipleInvalid as e:
- logger.exception(e)
- return JsonErrorResponse(description = u"参数错误")
- else:
- request.user.set_withdraw_alipay(**payload)
- return JsonOkResponse()
- @error_tolerate(nil = DefaultJsonErrorResponse)
- @permission_required(ROLE.dealer, ROLE.agent)
- def saveWechatWithdrawInfo(request):
- # type: (WSGIRequest)->JsonResponse
- try:
- payload = SaveWithdrawWechatSchema(json.loads(request.body))
- except MultipleInvalid as e:
- logger.exception(e)
- return JsonErrorResponse(description = u"参数错误")
- else:
- request.user.set_withdraw_wechat(**payload)
- return JsonOkResponse()
- @error_tolerate(nil = DefaultJsonErrorResponse)
- def makeAliUserAgreementSign(request):
- companyName = request.GET.get('companyName')
- certNo = request.GET.get('certNo')
- gateway = PlatformPayGatewayUtil.get_ali_isv_pay_gateway()
- signModel = AliUserAgreementSign.objects(
- externalLogonId = companyName,
- attachParas__action = 'make_fund_account_book',
- attachParas__certNo = certNo).first()
- if not signModel:
- signModel = AliUserAgreementSign.issue(
- cooperAppId = gateway.appid,
- external_agreement_no = AliUserAgreementSign.makeNo(companyName),
- external_logon_id = companyName,
- attach = {
- 'action': 'make_fund_account_book',
- 'certNo': certNo
- })
- url = gateway.create_transfer_agreement_sign(signModel, notify_url = ALIPAY_NOTIFY_URL)
- return JsonOkResponse(payload = {
- 'signUrl': url
- })
- @error_tolerate(nil = DefaultJsonErrorResponse)
- def queryAliUserAgreementSign(request):
- externalAgreementNo = request.GET.get('externalAgreementNo')
- isvGateway = PlatformPayGatewayUtil.get_ali_isv_pay_gateway()
- signModel = AliUserAgreementSign.objects(
- external_agreement_no = externalAgreementNo).first() # type: AliUserAgreementSign
- if not signModel:
- return JsonErrorResponse(description = u'该协议号不存在')
- result = isvGateway.query_transfer_agreement(signModel)
- if result['status'] == 'NORMAL' and signModel.attachParas['action'] == 'make_fund_account_book':
- signModel.agreementNo = result['agreement_no']
- signModel.save()
- agreementNo = signModel.agreementNo
- certNo = signModel.attachParas['certNo']
- if not AliFundAccountBookApp.objects(agreementNo = agreementNo, certNo = certNo).first():
- bookModel = AliFundAccountBookApp.apply(signModel)
- create_rv = PlatformPayGatewayUtil.get_ali_isv_pay_gateway().create_fund_accountbook(bookModel)
- bookModel.appid = create_rv['account_book_id']
- card_info = create_rv['ext_card_info']
- card_info.pop('status')
- bookModel.cardInfo = card_info
- bookModel.save()
- return JsonOkResponse(payload = result)
|