|
# -*- coding: utf-8 -*-
from __future__ import division
import random
import re
from django.conf import settings
from django.db import transaction
from django_logit import logit
from django_response import response
from pywe_marketcode import tickettocode
from pywe_storage import RedisStorage
from account.models import UserInfo
from logs.models import MchInfoDecryptLogInfo, MchInfoEncryptLogInfo
from marketcode.models import MarketCodeInfo
from mch.models import ActivityInfo, BrandInfo, ConsumeShotUnbindingInfo, ModelInfo
from sales.models import LotteryCampaignInfo
from utils.algorithm.b64 import b64_decrypt, b64_encrypt
from utils.algorithm.caesar import caesar_decrypt, caesar_encrypt
from utils.algorithm.rsalg import rsa_decrypt, rsa_encrypt
from utils.error.errno_utils import CiphertextStatusCode, MarketCodeStatusCode, UserStatusCode
from utils.redis.connect import r
WECHAT = settings.WECHAT
# CIPHER_ALGORITHM = ('CAESAR', 'B64', 'RSA')
CIPHER_ALGORITHM = ('CAESAR', )
CIPHER_PREFIX = {
'CAESAR': '0',
'B64': '1',
'RSA': '2',
}
def get_ciphertext(plaintext, optor_id, marketcode):
# brand_id#model_id#distributor_id#sn#time
# AAAA#AAAAAA#AAAAA#AAAAAAAAAAAAAA#180224
brand_pk, model_pk, distributor_pk, sn, time = plaintext.split('#')
mieli, created_at = MchInfoEncryptLogInfo.objects.get_or_create(plaintext=plaintext)
if marketcode:
if created_at or not mieli.code:
with transaction.atomic():
marketcode = MarketCodeInfo.objects.select_for_update().filter(has_used=False).first()
if not marketcode:
return ''
marketcode.has_used = True
marketcode.save()
mieli.application_id = marketcode.application_id
mieli.code = marketcode.code
mieli.code_url = marketcode.code_url
mieli.brand_pk = brand_pk
mieli.model_pk = model_pk
mieli.distributor_pk = distributor_pk
mieli.sn = sn
mieli.operator_id = optor_id
mieli.save()
return mieli.code_url
if created_at:
alg = random.choice(CIPHER_ALGORITHM)
if alg == 'CAESAR':
ciphertext = caesar_encrypt(plaintext)
elif alg == 'B64':
ciphertext = b64_encrypt(plaintext)
elif alg == 'RSA':
ciphertext = rsa_encrypt(plaintext)
else:
ciphertext = plaintext
mieli.alg = alg
mieli.ciphertext = ciphertext
mieli.brand_pk = brand_pk
mieli.model_pk = model_pk
mieli.distributor_pk = distributor_pk
mieli.sn = sn
mieli.operator_id = optor_id
mieli.save()
return u'{prefix}+{cipherlen}+{ciphertext}'.format(
prefix=CIPHER_PREFIX.get(mieli.alg, ''),
cipherlen=len(mieli.ciphertext),
ciphertext=mieli.ciphertext,
)
@logit(res=True)
def encrypt(request):
plaintext = request.POST.get('plaintext', '')
optor_id = request.POST.get('optor_id', '')
marketcode = request.POST.get('marketcode', '')
return response(200, data={
'ciphertext': get_ciphertext(plaintext, optor_id, marketcode),
})
@logit(res=True)
def decrypt(request, v='v2'):
ciphertext = request.POST.get('ciphertext', '')
try:
prefix, cipherlen, ciphertext = ciphertext.split('+', 2)
except Exception:
return response(CiphertextStatusCode.CIPHERTEXT_INVALID)
ciphertext = ciphertext[:int(cipherlen)]
if prefix == CIPHER_PREFIX['CAESAR']:
plaintext = caesar_decrypt(ciphertext)
elif prefix == CIPHER_PREFIX['B64']:
plaintext = b64_decrypt(ciphertext)
elif prefix == CIPHER_PREFIX['RSA']:
plaintext = rsa_decrypt(ciphertext)
else:
plaintext = ciphertext
# brand_id#model_id#distributor_id#sn#time
# AAAA#AAAAAA#AAAAA#AAAAAAAAAAAAAA#180224
brand_pk, model_pk, distributor_pk, sn, time = plaintext.split('#')
try:
brand = BrandInfo.objects.get(pk=brand_pk)
except BrandInfo.DoesNotExist:
brand = None
try:
model = ModelInfo.objects.get(pk=model_pk)
except ModelInfo.DoesNotExist:
model = None
mdli, created_at = MchInfoDecryptLogInfo.objects.get_or_create(ciphertext=ciphertext, defaults={
'brand_pk': brand_pk,
'model_pk': model_pk,
'distributor_pk': distributor_pk,
'sn': sn,
'decrypt_count': 1,
})
if not created_at:
mdli.decrypt_count += 1
mdli.save()
unbound = ConsumeShotUnbindingInfo.objects.filter(model_id=model.model_id, sn=sn, status=True).exists()
# 弃用老版本的劵形式,和会员系统统一
if v == 'v1':
has_unexpired_activity = False
coupon_infos = {}
else:
activities = ActivityInfo.objects.filter(status=True).order_by('-pk')
coupon_infos = [act.coupon_info3 for act in activities if act and act.has_unexpired_activity(model.model_name)]
lotterys = LotteryCampaignInfo.objects.filter(status=True)
if lotterys.exists():
active_lotterys = [lottery.data for lottery in lotterys if lottery.is_active()]
else:
active_lotterys = None
return response(200, data={
'plaintext': plaintext,
'lotterys': active_lotterys,
'logo_url': brand.brand_logo_url if brand else '',
'model_imgs': model.images if model else [],
'code_version': 1,
'goodsInfo': {
'BrandID': brand_pk,
'Brand': brand.brand_name if brand else '',
'ModelID': model_pk,
'Model': (model.model_full_name or model.model_name) if model else '',
'DistributorID': distributor_pk,
'SerialNo': sn,
'img': model.imgdata1 if model else '',
'img2': model.imgdata if model else {},
},
'has_unexpired_activity': False,
'coupon_infos': coupon_infos,
'unbound': unbound,
})
@logit(res=True)
def decrypt2(request, v='v2'):
code_ticket = request.POST.get('code_ticket', '')
code = request.POST.get('code', '')
user_id = request.POST.get('user_id', '')
if code_ticket and user_id:
try:
user = UserInfo.objects.get(user_id=user_id)
except UserInfo.DoesNotExist:
return response(UserStatusCode.USER_NOT_FOUND)
wxcfg = WECHAT.get('JSAPI', {})
appid = wxcfg.get('appID')
secret = wxcfg.get('appsecret')
code_info = tickettocode(code_ticket=code_ticket, openid=user.openid_miniapp, appid=appid, secret=secret, token=None, storage=RedisStorage(r))
code = code_info.get('code', '')
try:
mieli = MchInfoEncryptLogInfo.objects.get(code=code)
except MchInfoEncryptLogInfo.DoesNotExist:
return response()
else:
code = re.sub(r'http://|https://', '', code)
try:
mieli = MchInfoEncryptLogInfo.objects.get(code_url=code)
except MchInfoEncryptLogInfo.DoesNotExist:
return response()
plaintext = mieli.plaintext
# brand_id#model_id#distributor_id#sn#time
# AAAA#AAAAAA#AAAAA#AAAAAAAAAAAAAA#180224
brand_pk, model_pk, distributor_pk, sn, time = plaintext.split('#')
try:
brand = BrandInfo.objects.get(pk=brand_pk)
except BrandInfo.DoesNotExist:
brand = None
try:
model = ModelInfo.objects.get(pk=model_pk)
except ModelInfo.DoesNotExist:
model = None
mdli, created_at = MchInfoDecryptLogInfo.objects.get_or_create(
application_id=mieli.application_id,
code=mieli.code,
code_url=mieli.code_url,
defaults={
'brand_pk': brand_pk,
'model_pk': model_pk,
'distributor_pk': distributor_pk,
'sn': sn,
'decrypt_count': 1,
}
)
if not created_at:
mdli.decrypt_count += 1
mdli.save()
unbound = ConsumeShotUnbindingInfo.objects.filter(model_id=model.model_id, sn=sn, status=True).exists()
if v == 'v1':
has_unexpired_activity = False
coupon_infos = {}
else:
activities = ActivityInfo.objects.filter(status=True).order_by('-pk')
coupon_infos = [act.coupon_info3 for act in activities if act.has_unexpired_activity(model.model_name)]
return response(200, data={
'plaintext': plaintext,
'logo_url': brand.brand_logo_url if brand else '',
'model_imgs': model.images if model else [],
'code_version': mieli.version,
'goodsInfo': {
'BrandID': brand_pk,
'Brand': brand.brand_name if brand else '',
'ModelID': model_pk,
'Model': (model.model_full_name or model.model_name) if model else '',
'DistributorID': distributor_pk,
'SerialNo': sn,
'img': model.imgdata1 if model else '',
'img2': model.imgdata if model else {},
},
'has_unexpired_activity': False,
'coupon_infos': coupon_infos,
'unbound': unbound,
})
|