Skip to content

Commit

Permalink
add common subscription methods
Browse files Browse the repository at this point in the history
  • Loading branch information
PetrDlouhy committed Oct 25, 2021
1 parent 463f137 commit 6bd1ef1
Show file tree
Hide file tree
Showing 2 changed files with 99 additions and 0 deletions.
16 changes: 16 additions & 0 deletions payments/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,22 @@ def get_return_url(self, payment, extra_data=None):
return url + "?" + qs
return url

def autocomplete_with_subscription(self, payment):
"""
Complete the payment with subscription
Used by providers, that use server initiated subscription workflow
Throws RedirectNeeded if there is problem with the payment that needs to be solved by user
"""
raise NotImplementedError()

def cancel_subscription(self, subscription):
"""
Cancel subscription
Used by providers, that use provider initiated subscription workflow
"""
raise NotImplementedError()

def capture(self, payment, amount=None):
raise NotImplementedError()

Expand Down
83 changes: 83 additions & 0 deletions payments/models.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import enum
import json
from typing import Iterable
from typing import Optional
from typing import Union
from uuid import uuid4

Expand Down Expand Up @@ -36,6 +38,60 @@ def __setattr__(self, key, value):
self._payment.extra_data = json.dumps(data)


class BaseSubscription(models.Model):
token = models.CharField(
_("subscription token/id"),
help_text=_("Token/id used to identify subscription by provider"),
max_length=255,
default=None,
null=True,
blank=True,
)
payment_provider = models.CharField(
_('payment provider'),
help_text=_('Provider variant, that will be used for payment renewal'),
max_length=255,
default=None,
null=True,
blank=True,
)

class TimeUnit(enum.Enum):
year = "year"
month = "month"
day = "day"

def get_token(self) -> str:
return self.token

def set_recurrence(self, token: str, **kwargs):
"""
Sets token and other values associated with subscription recurrence
Kwargs can contain provider-specific values
"""
self.token = token

def get_period(self) -> int:
raise NotImplementedError()

def get_unit(self) -> TimeUnit:
raise NotImplementedError()

def cancel(self):
"""
Cancel the subscription by provider
Used by providers, that use provider initiated subscription workflow
Implementer is responsible for cancelling the subscription model
Raises PaymentError if the cancellation didn't pass through
"""
provider = provider_factory(self.variant)
provider.cancel_subscription(self)

class Meta:
abstract = True


class BasePayment(models.Model):
"""
Represents a single transaction. Each instance has one or more PaymentItem.
Expand Down Expand Up @@ -144,6 +200,33 @@ def get_success_url(self) -> str:
def get_process_url(self) -> str:
return reverse("process_payment", kwargs={"token": self.token})

def get_payment_url(self) -> str:
"""
Get the url the view that handles the payment (payment_details() in documentation)
For now used only by PayU provider to redirect users back to CVV2 form
"""
raise NotImplementedError()

def get_subscription(self) -> Optional[BaseSubscription]:
"""
Returns subscription object associated with this payment
or None if the payment is not recurring
"""
return None

def is_recurring(self) -> bool:
return self.get_subscription() is not None

def autocomplete_with_subscription(self):
"""
Complete the payment with subscription
Used by providers, that use server initiated subscription workflow
Throws RedirectNeeded if there is problem with the payment that needs to be solved by user
"""
provider = provider_factory(self.variant)
provider.autocomplete_with_subscription(self)

def capture(self, amount=None):
if self.status != PaymentStatus.PREAUTH:
raise ValueError("Only pre-authorized payments can be captured.")
Expand Down

0 comments on commit 6bd1ef1

Please sign in to comment.