diff --git a/bd_api/apps/payment/signals.py b/bd_api/apps/payment/signals.py index 1ba2c50f..e69de29b 100644 --- a/bd_api/apps/payment/signals.py +++ b/bd_api/apps/payment/signals.py @@ -1,15 +0,0 @@ -# -*- coding: utf-8 -*- -from django.db.models.signals import post_save -from django.dispatch import receiver -from djstripe.models import Customer as DJStripeCustomer - -from bd_api.apps.account.models import Account -from bd_api.utils import is_prod - - -@receiver(post_save, sender=Account) -def create_stripe_customer(sender, instance, created, **kwargs): - """Create stripe customer from after registration""" - - if created and is_prod(): - DJStripeCustomer.create(subscriber=instance) diff --git a/bd_api/apps/payment/tests.py b/bd_api/apps/payment/tests.py index 00664ef6..e69de29b 100644 --- a/bd_api/apps/payment/tests.py +++ b/bd_api/apps/payment/tests.py @@ -1,17 +0,0 @@ -# -*- coding: utf-8 -*- -from unittest.mock import MagicMock, patch - -import pytest - -from bd_api.apps.account.models import Account - - -@pytest.mark.django_db -@patch("bd_api.apps.payment.signals.DJStripeCustomer") -@patch("bd_api.apps.payment.signals.is_prod", new=lambda: True) -def test_create_stripe_customer_signal(mock: MagicMock): - Account.objects.create( - username="john.doe", - email="john.doe@email.com", - ) - assert mock.create.called diff --git a/bd_api/apps/payment/urls.py b/bd_api/apps/payment/urls.py index e14bfad1..abedb198 100644 --- a/bd_api/apps/payment/urls.py +++ b/bd_api/apps/payment/urls.py @@ -1,12 +1,34 @@ # -*- coding: utf-8 -*- from django.urls import include, path -from bd_api.apps.payment.views import StripeCustomerView, StripeSubscriptionView +from bd_api.apps.payment.views import ( + StripeCustomerSubscriptionView, + StripeCustomerView, + StripeSubscriptionView, +) urlpatterns = [ path("", include("djstripe.urls", namespace="payment")), - path("customer//", StripeCustomerView, name="payment_customer"), + path("customer/", StripeCustomerView.as_view(), name="payment_customer"), + path("customer//", StripeCustomerView.as_view(), name="payment_customer"), path( - "subscription///", StripeSubscriptionView, name="payment_subscription" + "customer//subscription/", + StripeCustomerSubscriptionView.as_view(), + name="payment_subscription", + ), + path( + "customer//subscription/", + StripeCustomerSubscriptionView.as_view(), + name="payment_subscription", + ), + path( + "subscription/", + StripeSubscriptionView.as_view(), + name="payment_subscription", + ), + path( + "subscription//", + StripeSubscriptionView.as_view(), + name="payment_subscription", ), ] diff --git a/bd_api/apps/payment/views.py b/bd_api/apps/payment/views.py index 0353695c..7d069d5b 100644 --- a/bd_api/apps/payment/views.py +++ b/bd_api/apps/payment/views.py @@ -1,7 +1,8 @@ # -*- coding: utf-8 -*- from json import JSONDecodeError, loads -from django.http import JsonResponse +from django.contrib.auth.decorators import login_required +from django.http import HttpRequest, JsonResponse from django.views import View from django.views.decorators.csrf import csrf_exempt from djstripe.models import Customer as DJStripeCustomer @@ -12,20 +13,51 @@ from bd_api.apps.account.models import Account -@csrf_exempt class StripeCustomerView(View): - """Update stripe customer fields: - - name - - email - - address - - line1: "Rua Augusta, 100" - - city: "São Paulo" - - state: "SP" - - country: "BR" - - postal_code: "01304-000" - """ - - def put(self, request, account_id): + @csrf_exempt + @login_required + def post(self, request: HttpRequest): + """Create a stripe customer + - name + - email + - address + - line1: "Rua Augusta, 100" + - city: "São Paulo" + - state: "SP" + - country: "BR" + - postal_code: "01304-000" + """ + try: + body = loads(request.body) + assert "name" in body + assert "email" in body + assert "address" in body + + account = Account.objects.get(id=body.account_id) + customer = DJStripeCustomer.create(account) + customer = StripeCustomer.modify(customer.id, **body) + + return JsonResponse(customer.values()) + except (JSONDecodeError, KeyError) as e: + logger.error(e) + return JsonResponse({}, status=400) + except Exception as e: + logger.error(e) + return JsonResponse({"error": str(e)}, status=422) + + @csrf_exempt + @login_required + def put(self, request: HttpRequest, account_id: str): + """Update a stripe customer + - name + - email + - address + - line1: "Rua Augusta, 100" + - city: "São Paulo" + - state: "SP" + - country: "BR" + - postal_code: "01304-000" + """ try: body = loads(request.body) assert "name" in body @@ -45,16 +77,17 @@ def put(self, request, account_id): return JsonResponse({"error": str(e)}, status=422) -@csrf_exempt class StripeSubscriptionView(View): - """Create a stripe subscription""" - - def post(self, request, account_id, price_id): + @csrf_exempt + @login_required + def post(self, request: HttpRequest): + """Create a stripe subscription""" try: - account = Account.objects.get(id=account_id) + body = loads(request.body) + account = Account.objects.get(id=body.account_id) customer: DJStripeCustomer = account.djstripe_customers[0] subscription: DJStripeSubscription = customer.subscribe( - price=price_id, + price=body.price_id, payment_behaviour="default_incomplete", payment_settings={"save_default_payment_method": "on_subscription"}, ) @@ -71,6 +104,33 @@ def post(self, request, account_id, price_id): logger.error(e) return JsonResponse({"error": str(e)}, status=422) + @csrf_exempt + @login_required + def delete(self, request: HttpRequest, subscription_id: str): + """Delete a stripe subscription""" + + try: + subscription = DJStripeSubscription.objects.get(id=subscription_id) + subscription = subscription.cancel() + return JsonResponse({}) + except Exception as e: + logger.error(e) + return JsonResponse({"error": str(e)}, status=422) + + +class StripeCustomerSubscriptionView(View): + @csrf_exempt + @login_required + def post(self, request: HttpRequest, account_id: str, subscription_id: str): + """Add a customer to a stripe subscription""" + ... + + @csrf_exempt + @login_required + def delete(self, request: HttpRequest, account_id: str, subscription_id: str): + """Remove a customer from a stripe subscription""" + ... + # Reference # https://stripe.com/docs/billing/subscriptions/build-subscriptions?ui=elementsf