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 from membership.models import StripeCustomer from hosting.models import MonthlyHostingBill, HostingBillLineItem from utils.tasks import send_plain_email_task logger = logging.getLogger(__name__) @require_POST @csrf_exempt def handle_invoice_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.INVOICE_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 invoice signature verification") # Get the user from the invoice invoice = event.data.object logger.debug("Checking whether StripeCustomer %s exists" % invoice.customer) try: stripe_customer = StripeCustomer.objects.get(stripe_id=invoice.customer) except StripeCustomer.DoesNotExist as dne: # StripeCustomer does not exist err_msg = "FAILURE handle_invoice_webhook: StripeCustomer %s doesn't exist" % invoice.customer err_body = "Details %s" % str(dne) return handle_error(err_msg, err_body) 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) 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.WEBHOOK_EMAIL_TO.split(","), 'body': error_body, } send_plain_email_task.delay(email_to_admin_data) return HttpResponse(status=400)