You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
153 lines
4.8 KiB
153 lines
4.8 KiB
# -*- coding: utf-8 -*-
|
|
|
|
import logging
|
|
from datetime import datetime, date
|
|
|
|
from django.http import HttpResponse
|
|
from django.utils.decorators import method_decorator
|
|
from django.views.decorators.csrf import csrf_exempt
|
|
from django.views.generic import View
|
|
from django.conf import settings
|
|
from django.core.mail import mail_admins
|
|
from lxml import etree
|
|
from lxml.builder import E
|
|
|
|
from .forms import CheckForm
|
|
from .forms import NoticeForm
|
|
from .models import Payment
|
|
from customer.models import License
|
|
|
|
|
|
logger = logging.getLogger('yandex_money')
|
|
|
|
|
|
class YandexValidationError(Exception):
|
|
params = None
|
|
|
|
def __init__(self, params=None):
|
|
super(YandexValidationError, self).__init__()
|
|
self.params = params if params is not None else {}
|
|
|
|
|
|
class BaseView(View):
|
|
form_class = None
|
|
|
|
@method_decorator(csrf_exempt)
|
|
def dispatch(self, *args, **kwargs):
|
|
return super(BaseView, self).dispatch(*args, **kwargs)
|
|
|
|
def post(self, request, *args, **kwargs):
|
|
form = self.form_class(request.POST)
|
|
if form.is_valid():
|
|
cd = form.cleaned_data
|
|
if form.check_md5(cd):
|
|
payment = self.get_payment(cd)
|
|
if payment:
|
|
try:
|
|
self.validate(cd, payment)
|
|
except YandexValidationError as exc:
|
|
params = exc.params
|
|
else:
|
|
params = self.get_response_params(payment, cd)
|
|
self.mark_payment(payment, cd)
|
|
payment.send_signals()
|
|
else:
|
|
params = {'code': '1000'}
|
|
else:
|
|
params = {'code': '1'}
|
|
else:
|
|
params = {'code': '200'}
|
|
|
|
self.logging(request, params)
|
|
content = self.get_xml(params)
|
|
|
|
if (
|
|
getattr(settings, 'YANDEX_MONEY_MAIL_ADMINS_ON_PAYMENT_ERROR', True) and
|
|
params.get('code') != '0'
|
|
):
|
|
mail_admins('yandexmoney_django error', u'post data: {post_data}\n\nresponse:{response}'.format(
|
|
post_data=request.POST,
|
|
response=content,
|
|
))
|
|
|
|
return HttpResponse(content, content_type='application/xml')
|
|
|
|
def validate(self, data, payment):
|
|
pass
|
|
|
|
def get_payment(self, cd):
|
|
try:
|
|
payment = Payment.objects.get(
|
|
order_number=cd['orderNumber'], shop_id=cd['shopId'])
|
|
except Payment.DoesNotExist:
|
|
payment = None
|
|
return payment
|
|
|
|
def get_response_params(self, payment, cd):
|
|
if payment:
|
|
now = datetime.now()
|
|
|
|
payment.performed_datetime = now
|
|
payment.save()
|
|
|
|
return {'code': '0',
|
|
'shopId': str(cd['shopId']),
|
|
'invoiceId': str(cd['invoiceId']),
|
|
'performedDatetime': now.isoformat()}
|
|
return {'code': '100'}
|
|
|
|
def mark_payment(self, payment, cd):
|
|
pass
|
|
|
|
def get_xml(self, params):
|
|
element = self.get_xml_element(**params)
|
|
return etree.tostring(element,
|
|
pretty_print=True,
|
|
xml_declaration=True,
|
|
encoding='UTF-8')
|
|
|
|
def get_xml_element(self, **params):
|
|
raise NotImplementedError()
|
|
|
|
def logging(self, request, params):
|
|
message = 'Action %s has code %s for customerNumber "%s"' % (
|
|
request.POST.get('action', ''), params['code'],
|
|
request.POST.get('customerNumber', ''))
|
|
logger.info(message)
|
|
|
|
|
|
class CheckOrderFormView(BaseView):
|
|
form_class = CheckForm
|
|
|
|
def validate(self, data, payment):
|
|
if payment.order_amount != data['orderSumAmount']:
|
|
params = {
|
|
'code': '100',
|
|
'message': u'Неверно указана сумма платежа',
|
|
}
|
|
raise YandexValidationError(params=params)
|
|
|
|
def get_xml_element(self, **params):
|
|
return E.checkOrderResponse(**params)
|
|
|
|
|
|
class NoticeFormView(BaseView):
|
|
form_class = NoticeForm
|
|
|
|
def get_xml_element(self, **params):
|
|
return E.paymentAvisoResponse(**params)
|
|
|
|
def mark_payment(self, payment, cd):
|
|
payment.cps_email = cd.get('cps_email', '')
|
|
payment.cps_phone = cd.get('cps_phone', '')
|
|
payment.order_currency = cd.get('orderSumCurrencyPaycash')
|
|
payment.shop_amount = cd.get('shopSumAmount')
|
|
payment.shop_currency = cd.get('shopSumCurrencyPaycash')
|
|
payment.payer_code = cd.get('paymentPayerCode')
|
|
payment.payment_type = cd.get('paymentType')
|
|
payment.status = payment.STATUS.SUCCESS
|
|
payment.save()
|
|
license = License.objects.get(id=payment.order_number)
|
|
license.paid_date = date.today()
|
|
license.status = 1
|
|
license.save()
|
|
|