1+ from django .shortcuts import get_object_or_404
2+ from django .core .exceptions import ObjectDoesNotExist
3+ from django .conf import settings
4+ from django .utils .encoding import smart_str
5+
6+ from rest_framework import status , generics
7+ from rest_framework .views import APIView
8+ from rest_framework .response import Response
9+ from rest_framework .permissions import IsAuthenticated
10+
11+ from .. import settings as app_settings
12+
13+ from .serializers import (
14+ CurrentSubscriptionSerializer ,
15+ CurrentCustomerSerializer ,
16+ SubscriptionSerializer ,
17+ CardSerializer ,
18+ CancelSerializer ,
19+ ChargeSerializer ,
20+ InvoiceSerializer ,
21+ EventSerializer ,
22+ WebhookSerializer ,
23+ EventProcessingExceptionSerializer
24+ )
25+
26+ from ..models import (
27+ Event ,
28+ Customer ,
29+ CurrentSubscription ,
30+ EventProcessingException
31+ )
32+
33+ import stripe
34+
35+ stripe .api_key = app_settings .get_api_key ()
36+
37+
38+ class StripeView (APIView ):
39+ """ Generic API StripeView """
40+ permission_classes = (IsAuthenticated , )
41+
42+ def get_current_subscription (self ):
43+ try :
44+ return self .request .user .customer .current_subscription
45+ except CurrentSubscription .DoesNotExist :
46+ return None
47+
48+ def get_customer (self ):
49+ try :
50+ return self .request .user .customer
51+ except ObjectDoesNotExist :
52+ return Customer .create (self .request .user )
53+
54+
55+ class CurrentCustomerDetailView (StripeView , generics .RetrieveAPIView ):
56+ """ See the current customer/user payment details """
57+
58+ serializer_class = CurrentCustomerSerializer
59+
60+ def get_object (self ):
61+ return self .get_customer ()
62+
63+
64+ class SubscriptionView (StripeView ):
65+ """ See, change/set the current customer/user subscription plan """
66+ serializer_class = SubscriptionSerializer
67+
68+ def get (self , request , * args , ** kwargs ):
69+ current_subscription = self .get_current_subscription ()
70+ serializer = CurrentSubscriptionSerializer (current_subscription )
71+ return Response (serializer .data , status = status .HTTP_200_OK )
72+
73+ def post (self , request , * args , ** kwargs ):
74+ try :
75+ serializer = self .serializer_class (data = request .data )
76+
77+ if serializer .is_valid ():
78+ validated_data = serializer .validated_data
79+ stripe_plan = validated_data .get ('stripe_plan' , None )
80+ customer = self .get_customer ()
81+ subscription = customer .subscribe (stripe_plan )
82+
83+ return Response (subscription , status = status .HTTP_201_CREATED )
84+ else :
85+ return Response (serializer .errors )
86+ except stripe .StripeError as e :
87+ from django .utils .encoding import smart_str
88+
89+ error_data = {u'error' : smart_str (e ) or u'Unknown error' }
90+ return Response (error_data , status = status .HTTP_400_BAD_REQUEST )
91+
92+
93+ class ChangeCardView (StripeView ):
94+ """ Add or update customer card details """
95+ serializer_class = CardSerializer
96+
97+ def post (self , request , * args , ** kwargs ):
98+ try :
99+ serializer = self .serializer_class (data = request .data )
100+
101+ if serializer .is_valid ():
102+ validated_data = serializer .validated_data
103+
104+ customer = self .get_customer ()
105+ card_token_response = customer .create_card_token (validated_data )
106+ token = card_token_response [0 ].get ('id' , None )
107+ customer .update_card (token )
108+ send_invoice = customer .card_fingerprint == ""
109+
110+ if send_invoice :
111+ customer .send_invoice ()
112+ customer .retry_unpaid_invoices ()
113+
114+ return Response (validated_data , status = status .HTTP_201_CREATED )
115+ else :
116+ return Response (serializer .errors )
117+
118+ except stripe .CardError as e :
119+ error_data = {u'error' : smart_str (e ) or u'Unknown error' }
120+ return Response (error_data , status = status .HTTP_400_BAD_REQUEST )
121+
122+
123+ class CancelView (StripeView ):
124+ """ Cancel customer subscription """
125+ serializer_class = CancelSerializer
126+
127+ def post (self , request , * args , ** kwargs ):
128+ try :
129+ serializer = self .serializer_class (data = request .data )
130+ if serializer .is_valid ():
131+ customer = self .get_customer ()
132+ customer .cancel ()
133+ return Response ({'success' : True }, status = status .HTTP_202_ACCEPTED )
134+ else :
135+ return Response (serializer .errors )
136+ except stripe .StripeError as e :
137+ error_data = {u'error' : smart_str (e ) or u'Unknown error' }
138+ return Response (error_data , status = status .HTTP_400_BAD_REQUEST )
139+
140+
141+ class PlanListView (StripeView ):
142+ """ List all current plans """
143+
144+ def get (self , request , * args , ** kwargs ):
145+ return Response (settings .PAYMENTS_PLANS , status = status .HTTP_200_OK )
146+
147+
148+ class ChargeListView (StripeView , generics .ListAPIView ):
149+ """ List customer charges """
150+ serializer_class = ChargeSerializer
151+
152+ def get_queryset (self ):
153+ customer = self .get_customer ()
154+ charges = customer .charges .all ()
155+ return charges
156+
157+
158+ class InvoiceListView (StripeView , generics .ListAPIView ):
159+ """ List customer invoices """
160+ serializer_class = InvoiceSerializer
161+
162+ def get_queryset (self ):
163+ customer = self .get_customer ()
164+ invoices = customer .invoices .all ()
165+ return invoices
166+
167+
168+ class EventListView (StripeView , generics .ListAPIView ):
169+ """ List customer events """
170+ serializer_class = EventSerializer
171+
172+ def get_queryset (self ):
173+ customer = self .get_customer ()
174+ events = customer .event_set .all ()
175+ return events
176+
177+
178+ class WebhookView (StripeView ):
179+ serializer_class = WebhookSerializer
180+
181+ def validate_webhook (self , webhook_data ):
182+ webhook_id = webhook_data .get ('id' , None )
183+ webhook_type = webhook_data .get ('type' , None )
184+ webhook_livemode = webhook_data .get ('livemode' , None )
185+ is_valid = False
186+
187+ if webhook_id and webhook_type and webhook_livemode :
188+ is_valid = True
189+ return is_valid , webhook_id , webhook_type , webhook_livemode
190+
191+ def post (self , request , * args , ** kwargs ):
192+ try :
193+ serializer = self .serializer_class (data = request .data )
194+
195+ if serializer .is_valid ():
196+ validated_data = serializer .validated_data
197+ webhook_data = validated_data .get ('data' , None )
198+
199+ is_webhook_valid , webhook_id , webhook_type , webhook_livemode = self .validate_webhook (webhook_data )
200+
201+ if is_webhook_valid :
202+ if Event .objects .filter (stripe_id = webhook_id ).exists ():
203+ obj = EventProcessingException .objects .create (
204+ data = validated_data ,
205+ message = "Duplicate event record" ,
206+ traceback = ""
207+ )
208+
209+ event_processing_exception_serializer = EventProcessingExceptionSerializer (obj )
210+ return Response (event_processing_exception_serializer .data , status = status .HTTP_200_OK )
211+ else :
212+ event = Event .objects .create (
213+ stripe_id = webhook_id ,
214+ kind = webhook_type ,
215+ livemode = webhook_livemode ,
216+ webhook_message = validated_data
217+ )
218+ event .validate ()
219+ event .process ()
220+ event_serializer = EventSerializer (event )
221+ return Response (event_serializer .data , status = status .HTTP_200_OK )
222+ else :
223+ error_data = {u'error' : u'Webhook must contain id, type and livemode.' }
224+ return Response (error_data , status = status .HTTP_400_BAD_REQUEST )
225+ else :
226+ return Response (serializer .errors )
227+ except stripe .StripeError as e :
228+ error_data = {u'error' : smart_str (e ) or u'Unknown error' }
229+ return Response (error_data , status = status .HTTP_400_BAD_REQUEST )
0 commit comments