X-Git-Url: https://git.mdrn.pl/wolnelektury.git/blobdiff_plain/d527b63f5320d32e5c598354fd60ebc00d88d7bb..9a0ea819fa5bfd8bce2e2500fbfc0cfcc75eff08:/src/club/payu/models.py?ds=sidebyside diff --git a/src/club/payu/models.py b/src/club/payu/models.py index 1a49dd707..d50ee8b75 100644 --- a/src/club/payu/models.py +++ b/src/club/payu/models.py @@ -1,5 +1,5 @@ -# This file is part of Wolnelektury, licensed under GNU Affero GPLv3 or later. -# Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information. +# This file is part of Wolne Lektury, licensed under GNU Affero GPLv3 or later. +# Copyright © Fundacja Wolne Lektury. See NOTICE for more information. # import json from urllib.parse import urlencode @@ -7,40 +7,44 @@ from urllib.request import HTTPError from django.contrib.sites.models import Site from django.db import models from django.urls import reverse -from django.utils.translation import ugettext_lazy as _ +from django.utils.timezone import now from . import POSS class CardToken(models.Model): """ This should be attached to a payment schedule. """ - pos_id = models.CharField(_('POS id'), max_length=255) - disposable_token = models.CharField(_('disposable token'), max_length=255) - reusable_token = models.CharField(_('reusable token'), max_length=255, null=True, blank=True) - created_at = models.DateTimeField(_('created_at'), auto_now_add=True) + pos_id = models.CharField('POS id', max_length=255) + disposable_token = models.CharField('token jednorazowy', max_length=255) + reusable_token = models.CharField('token wielokrotnego użytku', max_length=255, null=True, blank=True) + created_at = models.DateTimeField('utworzony', auto_now_add=True) class Meta: abstract = True - verbose_name = _('PayU card token') - verbose_name_plural = _('PayU card tokens') + verbose_name = 'token PayU karty płatniczej' + verbose_name_plural = 'tokeny PayU kart płatniczych' class Order(models.Model): - pos_id = models.CharField(_('POS id'), max_length=255) # TODO: redundant? - customer_ip = models.GenericIPAddressField(_('customer IP')) - order_id = models.CharField(_('order ID'), max_length=255, blank=True) + pos_id = models.CharField('POS id', max_length=255) # TODO: redundant? + customer_ip = models.GenericIPAddressField('adres IP klienta') + order_id = models.CharField('ID zamówienia', max_length=255, blank=True) status = models.CharField(max_length=128, blank=True, choices=[ - ('PENDING', _('Pending')), - ('WAITING_FOR_CONFIRMATION', _('Waiting for confirmation')), - ('COMPLETED', _('Completed')), - ('CANCELED', _('Canceled')), - ('REJECTED', _('Rejected')), + ('PENDING', 'Czeka'), + ('WAITING_FOR_CONFIRMATION', 'Czeka na potwierdzenie'), + ('COMPLETED', 'Ukończone'), + ('CANCELED', 'Anulowane'), + ('REJECTED', 'Odrzucone'), + + ('ERR-INVALID_TOKEN', 'Błędny token'), ]) + created_at = models.DateTimeField(null=True, blank=True, auto_now_add=True) + completed_at = models.DateTimeField(null=True, blank=True) class Meta: abstract = True - verbose_name = _('PayU order') - verbose_name_plural = _('PayU orders') + verbose_name = 'Zamówienie PayU' + verbose_name_plural = 'Zamówienia PayU' # These need to be provided in a subclass. @@ -72,6 +76,9 @@ class Order(models.Model): def get_notify_url(self): raise NotImplementedError + def get_thanks_url(self): + raise NotImplementedError + def status_updated(self): pass @@ -80,6 +87,11 @@ class Order(models.Model): def get_pos(self): return POSS[self.pos_id] + def get_continue_url(self): + return "https://{}{}".format( + Site.objects.get_current().domain, + self.get_thanks_url()) + def get_representation(self, token=None): rep = { "notifyUrl": self.get_notify_url(), @@ -87,7 +99,7 @@ class Order(models.Model): "merchantPosId": self.pos_id, "currencyCode": self.get_pos().currency_code, "totalAmount": str(int(self.get_amount() * 100)), - "extOrderId": "wolne-lektury-rcz-%d" % self.pk, + "extOrderId": "wolne-lektury-%d" % self.pk, "buyer": self.get_buyer() or {}, "continueUrl": self.get_continue_url(), @@ -124,22 +136,30 @@ class Order(models.Model): token.save() # else? - self.order_id = response['orderId'] - self.save() + if 'orderId' not in response: + code = response.get('status', {}).get('codeLiteral', '') + if code: + self.status = 'ERR-' + str(code) + self.save() + self.status_updated() + else: + raise ValueError("Expecting dict with `orderId` key, got: %s" % response) + else: + self.order_id = response['orderId'] + self.save() - - return response.get('redirectUri', self.schedule.get_thanks_url()) + return response.get('redirectUri', self.get_thanks_url()) class Notification(models.Model): """ Add `order` FK to real Order model. """ - body = models.TextField(_('body')) - received_at = models.DateTimeField(_('received_at'), auto_now_add=True) + body = models.TextField('treść') + received_at = models.DateTimeField('odebrana', auto_now_add=True) class Meta: abstract = True - verbose_name = _('PayU notification') - verbose_name_plural = _('PayU notifications') + verbose_name = 'notyfikacja PayU' + verbose_name_plural = 'notyfikacje PayU' def get_status(self): return json.loads(self.body)['order']['status'] @@ -148,5 +168,7 @@ class Notification(models.Model): status = self.get_status() if self.order.status not in (status, 'COMPLETED'): self.order.status = status + if status == 'COMPLETED': + self.order.completed_at = now() self.order.save() self.order.status_updated()