123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465 |
- # coding=utf-8
- import time
- import logging
- import xmltodict
- from django.http import HttpResponse
- from typing import TYPE_CHECKING
- from apps.web.user.models import MoniUser
- from apps.web.utils import concat_user_center_entry_url, concat_user_login_entry_url
- if TYPE_CHECKING:
- from apps.web.dealer.models import Dealer
- from apps.web.agent.models import MoniApp
- logger = logging.getLogger(__name__)
- class UserConsumeFilter(object):
- """
- 用户端的消费信息显示过滤器
- 用于过滤掉某些 用户的敏感信息
- """
- _DEFAULT_DATA = [
- 'deviceStatTime',
- 'reason',
- 'deviceFinishedTime',
- 'elec',
- 'power',
- 'orderStatus',
- 'consumeType',
- 'coins',
- 'amount',
- 'spendMoney',
- 'refundedMoney',
- 'cardOrderNo',
- 'vCardOrderNo',
- 'cardNo',
- 'errorDesc',
- 'feeType',
- 'cardDeduct',
- 'vCardDeduct',
- 'billTime',
- 'batteryType',
- 'voltage',
- 'oldBatteryImei',
- 'newBatteryImei',
- 'pw',
- ]
- def __init__(self, dealer, consumeDict): # type:(Dealer, dict) -> None
- self._supportFields = dealer.supportedConsumptionShow or UserConsumeFilter._DEFAULT_DATA
- self._consumeDict = consumeDict.copy()
- @classmethod
- def default_filter(cls):
- return cls._DEFAULT_DATA
- def filter(self):
- """
- 重新赋值 并过滤掉显示为空的部分
- """
- # 默认不显示
- self._consumeDict["needTime"] = self.needTime
- self._consumeDict["usedTime"] = self.usedTime
- self._consumeDict["leftTime"] = self.leftTime
- self._consumeDict["needElec"] = self.needElec
- self._consumeDict["elec"] = self.usedElec
- self._consumeDict["leftElec"] = self.leftElec
- # 默认需要显示
- self._consumeDict['deviceStatTime'] = self.deviceStatTime
- self._consumeDict['reason'] = self.reason
- self._consumeDict['deviceFinishedTime'] = self.deviceFinishedTime
- self._consumeDict['elec'] = self.elec
- self._consumeDict['orderStatus'] = self.orderStatus
- self._consumeDict['consumeType'] = self.consumeType
- self._consumeDict['coins'] = self.coins
- self._consumeDict['amount'] = self.amount
- self._consumeDict['spendMoney'] = self.spendMoney
- self._consumeDict['refundedMoney'] = self.refundedMoney
- self._consumeDict['cardOrderNo'] = self.cardOrderNo
- self._consumeDict['vCardOrderNo'] = self.vCardOrderNo
- self._consumeDict['cardNo'] = self.cardNo
- self._consumeDict['errorDesc'] = self.errorDesc
- self._consumeDict['feeType'] = self.feeType
- self._consumeDict['cardDeduct'] = self.cardDeduct
- self._consumeDict['vCardDeduct'] = self.vCardDeduct
- self._consumeDict['billTime'] = self.billTime
- self._consumeDict['batteryType'] = self.batteryType
- self._consumeDict['voltage'] = self.voltage
- self._consumeDict['oldBatteryImei'] = self.oldBatteryImei
- self._consumeDict['newBatteryImei'] = self.newBatteryImei
- self._consumeDict['pw'] = self.pw
- consumeDict = dict()
- for _k, _v in self._consumeDict.items():
- if _v is None:
- continue
- consumeDict[_k] = _v
- return consumeDict
- @property
- def needTime(self):
- if "needTime" in self._supportFields and "needTime" in self._consumeDict:
- return self._consumeDict["needTime"]
- @property
- def usedTime(self):
- if "usedTime" in self._consumeDict:
- usedTime = self._consumeDict["usedTime"]
- elif "duration" in self._consumeDict:
- usedTime = self._consumeDict["duration"]
- else:
- usedTime = None
- if "usedTime" in self._supportFields:
- return usedTime
- @property
- def leftTime(self):
- if "leftTime" in self._supportFields and "leftTime" in self._consumeDict:
- return self._consumeDict["leftTime"]
- @property
- def needElec(self):
- if "needElec" in self._supportFields and "needElec" in self._consumeDict:
- return self._consumeDict["needElec"]
- @property
- def usedElec(self):
- if "usedElec" in self._consumeDict:
- usedElec = self._consumeDict["usedElec"]
- elif "elec" in self._consumeDict:
- usedElec = self._consumeDict["elec"]
- else:
- usedElec = None
- if "usedElec" in self._supportFields:
- return usedElec
- @property
- def leftElec(self):
- if "leftElec" in self._supportFields and "leftElec" in self._consumeDict:
- return self._consumeDict["leftElec"]
- @property
- def deviceStatTime(self):
- if 'deviceStatTime' in self._supportFields and 'deviceStatTime' in self._consumeDict:
- return self._consumeDict['deviceStatTime']
- @property
- def reason(self):
- if 'reason' in self._supportFields and 'reason' in self._consumeDict:
- return self._consumeDict['reason']
- @property
- def deviceFinishedTime(self):
- if 'deviceFinishedTime' in self._supportFields and 'deviceFinishedTime' in self._consumeDict:
- return self._consumeDict['deviceFinishedTime']
- @property
- def elec(self):
- if 'elec' in self._supportFields and 'elec' in self._consumeDict:
- return self._consumeDict['elec']
- @property
- def orderStatus(self):
- """
- 订单状态必须返回, 不在判断模板
- :return:
- """
- if 'orderStatus' in self._consumeDict:
- return self._consumeDict['orderStatus']
- @property
- def consumeType(self):
- if 'consumeType' in self._supportFields and 'consumeType' in self._consumeDict:
- return self._consumeDict['consumeType']
- @property
- def coins(self):
- if 'coins' in self._supportFields and 'coins' in self._consumeDict:
- return self._consumeDict['coins']
- @property
- def amount(self):
- if 'amount' in self._supportFields and 'amount' in self._consumeDict:
- return self._consumeDict['amount']
- @property
- def spendMoney(self):
- if 'spendMoney' in self._supportFields and 'spendMoney' in self._consumeDict:
- return self._consumeDict['spendMoney']
- @property
- def refundedMoney(self):
- if 'refundedMoney' in self._supportFields and 'refundedMoney' in self._consumeDict:
- return self._consumeDict['refundedMoney']
- @property
- def cardOrderNo(self):
- if 'cardOrderNo' in self._supportFields and 'cardOrderNo' in self._consumeDict:
- return self._consumeDict['cardOrderNo']
- @property
- def vCardOrderNo(self):
- if 'vCardOrderNo' in self._supportFields and 'vCardOrderNo' in self._consumeDict:
- return self._consumeDict['vCardOrderNo']
- @property
- def cardNo(self):
- if 'cardNo' in self._supportFields and 'cardNo' in self._consumeDict:
- return self._consumeDict['cardNo']
- @property
- def errorDesc(self):
- if 'errorDesc' in self._supportFields and 'errorDesc' in self._consumeDict:
- return self._consumeDict['errorDesc']
- @property
- def feeType(self):
- if 'feeType' in self._supportFields and 'feeType' in self._consumeDict:
- return self._consumeDict['feeType']
- @property
- def cardDeduct(self):
- if 'cardDeduct' in self._supportFields and 'cardDeduct' in self._consumeDict:
- return self._consumeDict['cardDeduct']
- @property
- def vCardDeduct(self):
- if 'vCardDeduct' in self._supportFields and 'vCardDeduct' in self._consumeDict:
- return self._consumeDict['vCardDeduct']
- @property
- def billTime(self):
- if 'billTime' in self._supportFields and 'billTime' in self._consumeDict:
- return self._consumeDict['billTime']
- @property
- def batteryType(self):
- if 'batteryType' in self._supportFields and 'batteryType' in self._consumeDict:
- return self._consumeDict['batteryType']
- @property
- def voltage(self):
- if 'voltage' in self._supportFields and 'voltage' in self._consumeDict:
- return self._consumeDict['voltage']
- @property
- def oldBatteryImei(self):
- if 'oldBatteryImei' in self._supportFields and 'oldBatteryImei' in self._consumeDict:
- return self._consumeDict['oldBatteryImei']
- @property
- def newBatteryImei(self):
- if 'newBatteryImei' in self._supportFields and 'newBatteryImei' in self._consumeDict:
- return self._consumeDict['newBatteryImei']
- @property
- def pw(self):
- if 'pw' in self._supportFields and 'pw' in self._consumeDict:
- return self._consumeDict['pw']
- @property
- def power(self):
- if 'power' in self._supportFields and 'power' in self._consumeDict:
- return self._consumeDict['power']
- class WechatMessage(object):
- """
- 微信消息总成
- """
- def __init__(self, source):
- self._source = source
- self._data = self.parse_xml(xmlData=source)
- self._successor = None
- def __str__(self):
- return self._data.__str__()
- @property
- def isEvent(self):
- return self._data["MsgType"] == "event"
- @property
- def isSubscribeEvent(self):
- return self._data["Event"] == "subscribe"
- @property
- def isUnSubscribeEvent(self):
- return self._data["Event"] == "unsubscribe"
- @property
- def isMenuEvent(self):
- return self._data["Event"] == "VIEW"
- @property
- def isScanEvent(self):
- return self._data["Event"] == "SCAN"
- @property
- def isText(self):
- return self._data["MsgType"] == "text"
- @property
- def eventKey(self):
- if self.isEvent and self._data["EventKey"]:
- return self._data["EventKey"].replace("qrscene_", "")
- return ""
- @staticmethod
- def parse_xml(xmlData):
- payload = xmltodict.parse(xmlData)['xml']
- return payload
- @staticmethod
- def un_parse_xml(xmlDict):
- return xmltodict.unparse(xmlDict)
- @property
- def fromUser(self):
- return self._data["FromUserName"]
- @property
- def toUser(self):
- return self._data["ToUserName"]
- @property
- def receiveTime(self):
- return self._data["CreateTime"]
- def get_text_response(self, context):
- xmlDict = {
- "xml" : {
- "ToUserName": self.fromUser,
- "FromUserName": self.toUser,
- "CreateTime": int(time.time()),
- "MsgType": "text",
- "Content": context
- }
- }
- return HttpResponse(self.un_parse_xml(xmlDict))
- class MessageHandler(object):
- def __init__(self, message, app): # type:(WechatMessage, MoniApp) -> None
- self._message = message
- self._app = app
- @classmethod
- def defaultResponse(cls):
- return HttpResponse()
- def handle(self):
- return self.defaultResponse()
- def get_text_response(self, content):
- xmlDict = {
- "xml" : {
- "ToUserName": self._message.fromUser,
- "FromUserName": self._message.toUser,
- "CreateTime": int(time.time()),
- "MsgType": "text",
- "Content": content
- }
- }
- return HttpResponse(self._message.un_parse_xml(xmlDict))
- def get_news_response(self, linkUrl, imageUrl, content=None, title=None):
- content = content or u"🔋🔋🔋点击开始使用"
- title = title or u"点击使用"
- xmlDict = {
- "xml" : {
- "ToUserName": self._message.fromUser,
- "FromUserName": self._message.toUser,
- "CreateTime": int(time.time()),
- "MsgType": "news",
- "ArticleCount": 1,
- "Articles": {
- "item": {
- "Title": title,
- "Description": content,
- "PicUrl": imageUrl,
- "Url": linkUrl
- }
- }
- }
- }
- return HttpResponse(self._message.un_parse_xml(xmlDict))
- class WechatText(MessageHandler):
- """
- 文本类消息
- # TODO 智能机器人待添加
- """
- def handle(self):
- logger.info("{} handle event, event = {}".format(self.__class__.__name__, self._message))
- return self.defaultResponse()
- class WechatMenu(MessageHandler):
- pass
- class WechatSubscribe(MessageHandler):
- """
- 微信关注事件
- """
- def handle(self):
- """
- 微信关注一共分为两种 第一种 是扫描带参数二维码的 第二种是不带参数二维码的
- """
- eventKey = self._message.eventKey
- if not eventKey or not isinstance(eventKey, (str, unicode)):
- content = "您好,欢迎关注{}".format(self._app.appName)
- openId, logicalCode, productAgentId, chargeIndex = "", "", "", ""
- response = self.get_text_response(content)
- else:
- productAgentId, openId, logicalCode, chargeIndex = eventKey.split(":")
- title = "您好,欢迎关注 {}".format(self._app.appName)
- if logicalCode:
- url = concat_user_login_entry_url(l=logicalCode, chargeIndex=chargeIndex)
- else:
- url = concat_user_center_entry_url(productAgentId)
- response = self.get_news_response(linkUrl=url, imageUrl="", title=title)
- # 创建一条关联记录
- MoniUser.get_or_create(
- moniOpenId=self._message.fromUser, moniAppId=self._app.appid,
- openId=openId, subLogicalCode=logicalCode, subAgentId=productAgentId, isSubscribe=True
- )
-
- self._app.__class__.subscribe(self._app)
- return response
- class WechatUnSubscribe(MessageHandler):
- """
- 微信取关事件
- """
- def handle(self):
- moniOpenId, moniAppId = self._message.fromUser, self._app.appid
- MoniUser.get_or_delete(moniAppId=moniAppId, moniOpenId=moniOpenId)
- self._app.__class__.unSubscribe(self._app)
- return super(WechatUnSubscribe, self).handle()
- class WechatScanEvent(WechatSubscribe):
- """
- 扫码消息
- """
- pass
|