| 
									
										
										
										
											2019-12-25 12:07:42 +05:30
										 |  |  | import datetime | 
					
						
							|  |  |  | import logging | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import stripe | 
					
						
							|  |  |  | # Create your views here. | 
					
						
							|  |  |  | from django.conf import settings | 
					
						
							|  |  |  | from django.http import HttpResponse | 
					
						
							|  |  |  | from django.views.decorators.csrf import csrf_exempt | 
					
						
							|  |  |  | from django.views.decorators.http import require_POST | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-01 00:01:44 +05:30
										 |  |  | from membership.models import StripeCustomer | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-25 12:07:42 +05:30
										 |  |  | from utils.models import BillingAddress, UserBillingAddress | 
					
						
							|  |  |  | from utils.tasks import send_plain_email_task | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | logger = logging.getLogger(__name__) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-25 12:36:47 +05:30
										 |  |  | # Things to do for webhooks feature | 
					
						
							|  |  |  | # 1. Uninstall old version and install a more recent version of stripe | 
					
						
							|  |  |  | #    ``` | 
					
						
							|  |  |  | #    source venv/bin/activate | 
					
						
							|  |  |  | #    ./manage.py shell | 
					
						
							|  |  |  | #    pip uninstall stripe | 
					
						
							|  |  |  | #    pip install stripe==2.24.1 | 
					
						
							|  |  |  | #    ``` | 
					
						
							|  |  |  | # 2. Create tax id updated webhook | 
					
						
							|  |  |  | #    ``` | 
					
						
							|  |  |  | #    ./manage.py webhook --create \ | 
					
						
							|  |  |  | #    --webhook_endpoint https://datacenterlight.ch/en-us/webhooks/ \ | 
					
						
							|  |  |  | #    --events_csv customer.tax_id.updated | 
					
						
							|  |  |  | #    ``` | 
					
						
							|  |  |  | # | 
					
						
							|  |  |  | # 3. From the secret obtained in 2, setup an environment variable | 
					
						
							|  |  |  | #    ``` | 
					
						
							|  |  |  | #    WEBHOOK_SECRET='whsec......' | 
					
						
							|  |  |  | #    ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-25 12:07:42 +05:30
										 |  |  | @require_POST | 
					
						
							|  |  |  | @csrf_exempt | 
					
						
							|  |  |  | def handle_webhook(request): | 
					
						
							|  |  |  |     payload = request.body | 
					
						
							|  |  |  |     event = None | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     try: | 
					
						
							|  |  |  |         if 'HTTP_STRIPE_SIGNATURE' in request.META: | 
					
						
							|  |  |  |             sig_header = request.META['HTTP_STRIPE_SIGNATURE'] | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             logger.error("No HTTP_STRIPE_SIGNATURE header") | 
					
						
							|  |  |  |             # Invalid payload | 
					
						
							|  |  |  |             return HttpResponse(status=400) | 
					
						
							|  |  |  |         event = stripe.Webhook.construct_event( | 
					
						
							|  |  |  |             payload, sig_header, settings.WEBHOOK_SECRET | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  |     except ValueError as e: | 
					
						
							|  |  |  |         # Invalid payload | 
					
						
							|  |  |  |         err_msg = "FAILURE handle_invoice_webhook: Invalid payload details" | 
					
						
							|  |  |  |         err_body = "Details %s" % str(e) | 
					
						
							|  |  |  |         return handle_error(err_msg, err_body) | 
					
						
							|  |  |  |     except stripe.error.SignatureVerificationError as e: | 
					
						
							|  |  |  |         # Invalid signature | 
					
						
							|  |  |  |         err_msg = "FAILURE handle_invoice_webhook: SignatureVerificationError" | 
					
						
							|  |  |  |         err_body = "Details %s" % str(e) | 
					
						
							|  |  |  |         return handle_error(err_msg, err_body) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Do something with event | 
					
						
							|  |  |  |     logger.debug("Passed signature verification") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if event.type == "customer.tax_id.updated": | 
					
						
							|  |  |  |         logger.debug("Webhook Event: customer.tax_id.updated") | 
					
						
							|  |  |  |         tax_id_obj = event.data.object | 
					
						
							| 
									
										
										
										
											2019-12-26 08:06:27 +05:30
										 |  |  |         logger.debug("Tax_id %s is %s" % (tax_id_obj.id, | 
					
						
							|  |  |  |                      tax_id_obj.verification.status)) | 
					
						
							| 
									
										
										
										
											2020-01-01 00:01:44 +05:30
										 |  |  |         stripe_customer = None | 
					
						
							|  |  |  |         try: | 
					
						
							| 
									
										
										
										
											2020-01-01 00:52:07 +05:30
										 |  |  |             stripe_customer = StripeCustomer.objects.get(stripe_id=tax_id_obj.customer) | 
					
						
							| 
									
										
										
										
											2020-01-01 00:01:44 +05:30
										 |  |  |         except StripeCustomer.DoesNotExist as dne: | 
					
						
							|  |  |  |             logger.debug( | 
					
						
							|  |  |  |                 "StripeCustomer %s does not exist" % tax_id_obj.customer) | 
					
						
							| 
									
										
										
										
											2019-12-25 12:07:42 +05:30
										 |  |  |         if tax_id_obj.verification.status == "verified": | 
					
						
							| 
									
										
										
										
											2019-12-26 11:54:54 +05:30
										 |  |  |             b_addresses = BillingAddress.objects.filter(stripe_tax_id=tax_id_obj.id) | 
					
						
							| 
									
										
										
										
											2019-12-25 12:07:42 +05:30
										 |  |  |             for b_address in b_addresses: | 
					
						
							| 
									
										
										
										
											2019-12-26 19:35:50 +05:30
										 |  |  |                 b_address.vat_validation_status = tax_id_obj.verification.status | 
					
						
							| 
									
										
										
										
											2019-12-25 12:07:42 +05:30
										 |  |  |                 b_address.vat_number_validated_on = datetime.datetime.now() | 
					
						
							| 
									
										
										
										
											2019-12-26 11:54:54 +05:30
										 |  |  |                 b_address.save() | 
					
						
							| 
									
										
										
										
											2019-12-25 12:07:42 +05:30
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-26 11:54:54 +05:30
										 |  |  |             ub_addresses = UserBillingAddress.objects.filter(stripe_tax_id=tax_id_obj.id) | 
					
						
							| 
									
										
										
										
											2019-12-25 12:07:42 +05:30
										 |  |  |             for ub_address in ub_addresses: | 
					
						
							| 
									
										
										
										
											2019-12-26 19:35:50 +05:30
										 |  |  |                 ub_address.vat_validation_status = tax_id_obj.verification.status | 
					
						
							| 
									
										
										
										
											2019-12-25 12:07:42 +05:30
										 |  |  |                 ub_address.vat_number_validated_on = datetime.datetime.now() | 
					
						
							| 
									
										
										
										
											2019-12-26 11:54:54 +05:30
										 |  |  |                 ub_address.save() | 
					
						
							| 
									
										
										
										
											2020-01-01 00:01:44 +05:30
										 |  |  |             email_data = { | 
					
						
							|  |  |  |                 'subject': "The VAT %s associated with %s was verified" % | 
					
						
							|  |  |  |                            (tax_id_obj.value,  stripe_customer.user.email if stripe_customer else "unknown"), | 
					
						
							|  |  |  |                 'from_email': settings.DCL_SUPPORT_FROM_ADDRESS, | 
					
						
							|  |  |  |                 'to': settings.DCL_ERROR_EMAILS_TO_LIST, | 
					
						
							| 
									
										
										
										
											2020-01-01 02:04:55 +05:30
										 |  |  |                 'body': "The following objects were modified:\n".join( | 
					
						
							|  |  |  |                     '\n'.join([str(b_address) for b_address in b_addresses]) | 
					
						
							|  |  |  |                 ).join( | 
					
						
							|  |  |  |                     '\n'.join([str(ub_address) for ub_address in ub_addresses]) | 
					
						
							|  |  |  |                 ), | 
					
						
							| 
									
										
										
										
											2020-01-01 00:01:44 +05:30
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2019-12-25 12:07:42 +05:30
										 |  |  |         else: | 
					
						
							| 
									
										
										
										
											2019-12-26 08:06:27 +05:30
										 |  |  |             logger.debug("Tax_id %s is %s" % (tax_id_obj.id, | 
					
						
							|  |  |  |                          tax_id_obj.verification.status)) | 
					
						
							| 
									
										
										
										
											2020-01-01 00:01:44 +05:30
										 |  |  |             email_data = { | 
					
						
							|  |  |  |                 'subject': "The VAT %s associated with %s was %s" % | 
					
						
							|  |  |  |                            (tax_id_obj.value,  stripe_customer.user.email if stripe_customer else "unknown", tax_id_obj.verification.status), | 
					
						
							|  |  |  |                 'from_email': settings.DCL_SUPPORT_FROM_ADDRESS, | 
					
						
							|  |  |  |                 'to': settings.DCL_ERROR_EMAILS_TO_LIST, | 
					
						
							|  |  |  |                 'body': "Response = %s" % str(tax_id_obj), | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         send_plain_email_task.delay(email_data) | 
					
						
							| 
									
										
										
										
											2019-12-25 12:07:42 +05:30
										 |  |  |     else: | 
					
						
							|  |  |  |         logger.error("Unhandled event : " + event.type) | 
					
						
							|  |  |  |     return HttpResponse(status=200) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def handle_error(error_msg, error_body): | 
					
						
							|  |  |  |     logger.error("%s -- %s" % (error_msg, error_body)) | 
					
						
							|  |  |  |     email_to_admin_data = { | 
					
						
							|  |  |  |         'subject': error_msg, | 
					
						
							|  |  |  |         'from_email': settings.DCL_SUPPORT_FROM_ADDRESS, | 
					
						
							|  |  |  |         'to': [settings.ADMIN_EMAIL], | 
					
						
							|  |  |  |         'body': error_body, | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     send_plain_email_task.delay(email_to_admin_data) | 
					
						
							|  |  |  |     return HttpResponse(status=400) |