Implement provisioning of VM on invoice.paid webhook

This commit is contained in:
PCoder 2020-12-20 02:41:30 +05:30
parent 3389e69af1
commit cb7a1ed4f4
2 changed files with 247 additions and 204 deletions

View file

@ -710,6 +710,7 @@ class OrderConfirmationView(DetailView, FormView):
stripe_api_cus_id = request.session.get('customer') stripe_api_cus_id = request.session.get('customer')
stripe_utils = StripeUtils() stripe_utils = StripeUtils()
logger.debug("user=%s stripe_api_cus_id=%s" % (user, stripe_api_cus_id)) logger.debug("user=%s stripe_api_cus_id=%s" % (user, stripe_api_cus_id))
card_details_response = None
if 'token' in request.session: if 'token' in request.session:
card_details = stripe_utils.get_cards_details_from_token( card_details = stripe_utils.get_cards_details_from_token(
@ -954,10 +955,40 @@ class OrderConfirmationView(DetailView, FormView):
} }
return JsonResponse(context) return JsonResponse(context)
else: else:
logger.debug("Handle this case") logger.debug(
"Handle this case when "
"stripe.subscription_status is incomplete but "
"pi.status is neither requires_attention nor "
"requires_source_action")
msg = subscription_result.get('error') msg = subscription_result.get('error')
return show_error(msg, self.request) return show_error(msg, self.request)
do_create_vm(self.request, user, stripe_api_cus_id,
card_details_response, stripe_subscription_obj,
stripe_onetime_charge, gp_details, specs, vm_template_id,
template
)
response = {
'status': True,
'redirect': (
reverse('hosting:virtual_machines')
if request.user.is_authenticated()
else reverse('datacenterlight:index')
),
'msg_title': str(_('Thank you for the order.')),
'msg_body': str(
_('Your VM will be up and running in a few moments.'
' We will send you a confirmation email as soon as'
' it is ready.'))
}
return JsonResponse(response)
def do_create_vm(request, user, stripe_api_cus_id, card_details_response,
stripe_subscription_obj, stripe_onetime_charge, gp_details,
specs, vm_template_id, template):
# Create user if the user is not logged in and if he is not already # Create user if the user is not logged in and if he is not already
# registered # registered
if not request.user.is_authenticated(): if not request.user.is_authenticated():
@ -975,8 +1006,8 @@ class OrderConfirmationView(DetailView, FormView):
logger.debug( logger.debug(
"Customer {} does not exist.".format(user.get('email'))) "Customer {} does not exist.".format(user.get('email')))
password = CustomUser.get_random_password() password = CustomUser.get_random_password()
base_url = "{0}://{1}".format(self.request.scheme, base_url = "{0}://{1}".format(request.scheme,
self.request.get_host()) request.get_host())
custom_user = CustomUser.register( custom_user = CustomUser.register(
user.get('name'), password, user.get('name'), password,
user.get('email'), user.get('email'),
@ -990,8 +1021,9 @@ class OrderConfirmationView(DetailView, FormView):
new_user = authenticate(username=custom_user.email, new_user = authenticate(username=custom_user.email,
password=password) password=password)
login(request, new_user) login(request, new_user)
if 'new_user_hosting_key_id' in self.request.session: if 'new_user_hosting_key_id' in request.session:
user_hosting_key = UserHostingKey.objects.get(id=self.request.session['new_user_hosting_key_id']) user_hosting_key = UserHostingKey.objects.get(
id=request.session['new_user_hosting_key_id'])
user_hosting_key.user = new_user user_hosting_key.user = new_user
user_hosting_key.save() user_hosting_key.save()
else: else:
@ -1002,11 +1034,11 @@ class OrderConfirmationView(DetailView, FormView):
if 'token' in request.session: if 'token' in request.session:
ucd = UserCardDetail.get_or_create_user_card_detail( ucd = UserCardDetail.get_or_create_user_card_detail(
stripe_customer=self.request.user.stripecustomer, stripe_customer=request.user.stripecustomer,
card_details=card_details_response card_details=card_details_response
) )
UserCardDetail.save_default_card_local( UserCardDetail.save_default_card_local(
self.request.user.stripecustomer.stripe_id, request.user.stripecustomer.stripe_id,
ucd.card_id ucd.card_id
) )
else: else:
@ -1045,8 +1077,7 @@ class OrderConfirmationView(DetailView, FormView):
billing_address.save() billing_address.save()
order = HostingOrder.create( order = HostingOrder.create(
price=self.request price=request.session['generic_payment_details']['amount'],
.session['generic_payment_details']['amount'],
customer=stripe_cus, customer=stripe_cus,
billing_address=billing_address, billing_address=billing_address,
vm_pricing=VMPricing.get_default_pricing() vm_pricing=VMPricing.get_default_pricing()
@ -1067,7 +1098,7 @@ class OrderConfirmationView(DetailView, FormView):
billing_address_user_form.is_valid() billing_address_user_form.is_valid()
billing_address_user_form.save() billing_address_user_form.save()
if self.request.session['generic_payment_details']['recurring']: if request.session['generic_payment_details']['recurring']:
# Associate the given stripe subscription with the order # Associate the given stripe subscription with the order
order.set_subscription_id( order.set_subscription_id(
stripe_subscription_obj.id, card_details_dict stripe_subscription_obj.id, card_details_dict
@ -1162,23 +1193,6 @@ class OrderConfirmationView(DetailView, FormView):
vm_template_id, template, user vm_template_id, template, user
) )
response = {
'status': True,
'redirect': (
reverse('hosting:virtual_machines')
if request.user.is_authenticated()
else reverse('datacenterlight:index')
),
'msg_title': str(_('Thank you for the order.')),
'msg_body': str(
_('Your VM will be up and running in a few moments.'
' We will send you a confirmation email as soon as'
' it is ready.'))
}
return JsonResponse(response)
def show_error(msg, request): def show_error(msg, request):
messages.add_message(request, messages.ERROR, msg, messages.add_message(request, messages.ERROR, msg,
extra_tags='failed_payment') extra_tags='failed_payment')

View file

@ -8,7 +8,9 @@ from django.http import HttpResponse
from django.views.decorators.csrf import csrf_exempt from django.views.decorators.csrf import csrf_exempt
from django.views.decorators.http import require_POST from django.views.decorators.http import require_POST
from datacenterlight.views import do_create_vm
from membership.models import StripeCustomer from membership.models import StripeCustomer
from hosting.models import HostingOrder
from utils.models import BillingAddress, UserBillingAddress from utils.models import BillingAddress, UserBillingAddress
from utils.tasks import send_plain_email_task from utils.tasks import send_plain_email_task
@ -117,8 +119,35 @@ def handle_webhook(request):
invoice_obj = event.data.object invoice_obj = event.data.object
logger.debug("Webhook Event: invoice.paid") logger.debug("Webhook Event: invoice.paid")
logger.debug("invoice_obj %s " % str(invoice_obj)) logger.debug("invoice_obj %s " % str(invoice_obj))
if invoice_obj.paid and invoice_obj.billing_reason == "subscription_create": logger.debug("invoice_obj.paid = %s %s" % (invoice_obj.paid, type(invoice_obj.paid)))
logger.debug("invoice_obj.billing_reason = %s %s" % (invoice_obj.billing_reason, type(invoice_obj.billing_reason)))
# We should check for billing_reason == "subscription_create" but we check for "subscription_update"
# because we are using older api. See https://stripe.com/docs/upgrades?since=2015-07-13
# The billing_reason attribute of the invoice object now can take the
# value of subscription_create, indicating that it is the first
# invoice of a subscription. For older API versions,
# billing_reason=subscription_create is represented as
# subscription_update.
if invoice_obj.paid and invoice_obj.billing_reason == "subscription_update":
logger.debug("Start provisioning") logger.debug("Start provisioning")
# get subscription id, order_id
ho = None
try:
ho = HostingOrder.objects.get(subscription_id=invoice_obj.subscription)
except Exception as ex:
logger.error(str(ex))
if ho:
logger.debug("Create a VM for order %s" % str(ho))
# TODO: fix the error below
do_create_vm(request, user, stripe_api_cus_id,
card_details_response, stripe_subscription_obj,
stripe_onetime_charge, gp_details, specs,
vm_template_id,
template
)
else: else:
logger.error("Unhandled event : " + event.type) logger.error("Unhandled event : " + event.type)