From 8a59c2da1e04fb216e8ab4993bf5f3a17bd368b0 Mon Sep 17 00:00:00 2001 From: PCoder Date: Sun, 14 Apr 2019 00:58:13 +0200 Subject: [PATCH] Implement handling invoice.payment_succeeded and invoice.payment_failed webhooks --- dynamicweb/settings/base.py | 1 + hosting/models.py | 13 +++++++ webhook/views.py | 71 +++++++++++++++++++++++++++++++++++++ 3 files changed, 85 insertions(+) diff --git a/dynamicweb/settings/base.py b/dynamicweb/settings/base.py index 45018f13..85cf1a86 100644 --- a/dynamicweb/settings/base.py +++ b/dynamicweb/settings/base.py @@ -650,6 +650,7 @@ CELERY_MAX_RETRIES = int_env('CELERY_MAX_RETRIES', 5) DCL_ERROR_EMAILS_TO = env('DCL_ERROR_EMAILS_TO') ADMIN_EMAIL = env('ADMIN_EMAIL') +WEBHOOK_EMAIL_TO = env('WEBHOOK_EMAIL_TO') DCL_ERROR_EMAILS_TO_LIST = [] if DCL_ERROR_EMAILS_TO is not None: diff --git a/hosting/models.py b/hosting/models.py index 550cf27f..ed6329b8 100644 --- a/hosting/models.py +++ b/hosting/models.py @@ -435,6 +435,19 @@ class HostingBillLineItem(AssignPermissionsMixin, models.Model): ('view_hostingbilllineitem', 'View Monthly Hosting Bill Line Item'), ) + def get_vm_id(self): + """ + If VM_ID is set in the metadata extract and return it as integer + other return -1 + + :return: + """ + if "VM_ID" in self.metadata: + data = json.loads(self.metadata) + return int(data["VM_ID"]) + else: + return None + class VMDetail(models.Model): user = models.ForeignKey(CustomUser) diff --git a/webhook/views.py b/webhook/views.py index 19587e69..cf1b0950 100644 --- a/webhook/views.py +++ b/webhook/views.py @@ -7,6 +7,9 @@ from django.http import HttpResponse from django.views.decorators.csrf import csrf_exempt from django.views.decorators.http import require_POST +from membership.models import StripeCustomer +from hosting.models import MonthlyHostingBill, HostingBillLineItem +from utils.tasks import send_plain_email_task logger = logging.getLogger(__name__) @@ -33,4 +36,72 @@ def handle_invoice_webhook(request): # Do something with event logger.debug("Passed invoice signature verification") + # Get the user from the invoice + invoice = event.data.object + stripe_customer = StripeCustomer.objects.get(stripe_id=invoice.customer) + + if event.type == "invoice.payment_succeeded": + logger.debug("Invoice payment succeeded") + + # Create a new invoice for the user + invoice_dict = { + 'created': invoice.created, + 'receipt_number': invoice.receipt_number, + 'invoice_number': invoice.number, + 'paid_at': invoice.status_transitions.paid_at if invoice.paid else 0, + 'period_start': invoice.period_start, + 'period_end': invoice.period_end, + 'billing_reason': invoice.billing_reason, + 'discount': invoice.discount.coupon.amount_off if invoice.discount else 0, + 'total': invoice.total, + # to see how many line items we have in this invoice and + # then later check if we have more than 1 + 'lines_data_count': len( + invoice.lines.data) if invoice.lines.data is not None else 0, + 'invoice_id': invoice.id, + 'lines_meta_data_csv': ','.join( + [line.metadata.VM_ID if hasattr(line.metadata, 'VM_ID') else '' + for line in invoice.lines.data] + ), + 'subscription_ids_csv': ','.join( + [line.id if line.type == 'subscription' else '' for line in + invoice.lines.data] + ), + 'line_items': invoice.lines.data, + 'customer': stripe_customer + } + mhb = MonthlyHostingBill.create(invoice_dict) + mbli = HostingBillLineItem.objects.filter(monthly_hosting_bill=mhb).first() + vm_id = mbli.get_vm_id() + + # Send an email to admin + admin_msg_sub = "Invoice payment success for user {} and VM {}".format( + stripe_customer.user.email, + vm_id if vm_id is not None else "Unknown" + ) + email_to_admin_data = { + 'subject': admin_msg_sub, + 'from_email': settings.DCL_SUPPORT_FROM_ADDRESS, + 'to': settings.WEBHOOK_EMAIL_TO.split(","), + 'body': "\n".join( + ["%s=%s" % (k, v) for (k, v) in invoice_dict.items()]), + } + send_plain_email_task.delay(email_to_admin_data) + + elif event.type == "invoice.payment_failed": + logger.error("Invoice payment failed") + + admin_msg_sub = "Invoice payment FAILED for user {} and ".format( + stripe_customer.user.email, + invoice.lines.data.metadata + ) + email_to_admin_data = { + 'subject': admin_msg_sub, + 'from_email': settings.DCL_SUPPORT_FROM_ADDRESS, + 'to': settings.WEBHOOK_EMAIL_TO.split(","), + 'body': "\n".join( + ["%s=%s" % (k, v) for (k, v) in invoice.__dict__.items()]), + } + send_plain_email_task.delay(email_to_admin_data) + return HttpResponse(status=200) \ No newline at end of file