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 Apr 17, 2024
1 parent d5a3404 commit c8a78d1
Show file tree
Hide file tree
Showing 2 changed files with 100 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 @@ -143,6 +143,22 @@ def get_return_url(
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 cancellation workflow
"""
raise NotImplementedError()

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

Expand Down
84 changes: 84 additions & 0 deletions payments/models.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
from __future__ import annotations

import json
import enum
from typing import Iterable
from typing import Optional
from typing import Union
from uuid import uuid4

from django.db import models
Expand Down Expand Up @@ -39,6 +42,60 @@ def __setattr__(self, key, value):
return None


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 @@ -185,6 +242,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):
"""Capture a pre-authorized payment.
Expand Down

0 comments on commit c8a78d1

Please sign in to comment.