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

# -*- 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()