Modify datacenterlight/views.py to includes various cases of generic payment
This commit is contained in:
parent
9ec05e7df4
commit
d23624c525
1 changed files with 266 additions and 60 deletions
|
@ -1,4 +1,5 @@
|
||||||
import logging
|
import logging
|
||||||
|
import uuid
|
||||||
|
|
||||||
from django import forms
|
from django import forms
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
@ -13,10 +14,13 @@ from django.views.decorators.cache import cache_control
|
||||||
from django.views.generic import FormView, CreateView, DetailView
|
from django.views.generic import FormView, CreateView, DetailView
|
||||||
|
|
||||||
from hosting.forms import HostingUserLoginForm, GenericPaymentForm
|
from hosting.forms import HostingUserLoginForm, GenericPaymentForm
|
||||||
from hosting.models import HostingOrder, UserCardDetail
|
from hosting.models import HostingBill, HostingOrder, UserCardDetail
|
||||||
from membership.models import CustomUser, StripeCustomer
|
from membership.models import CustomUser, StripeCustomer
|
||||||
from opennebula_api.serializers import VMTemplateSerializer
|
from opennebula_api.serializers import VMTemplateSerializer
|
||||||
from utils.forms import BillingAddressForm, BillingAddressFormSignup
|
from utils.forms import (
|
||||||
|
BillingAddressForm, BillingAddressFormSignup, UserBillingAddressForm,
|
||||||
|
BillingAddress
|
||||||
|
)
|
||||||
from utils.hosting_utils import get_vm_price_with_vat
|
from utils.hosting_utils import get_vm_price_with_vat
|
||||||
from utils.stripe_utils import StripeUtils
|
from utils.stripe_utils import StripeUtils
|
||||||
from utils.tasks import send_plain_email_task
|
from utils.tasks import send_plain_email_task
|
||||||
|
@ -244,7 +248,8 @@ class PaymentOrderView(FormView):
|
||||||
'cms_integration': get_cms_integration('default'),
|
'cms_integration': get_cms_integration('default'),
|
||||||
})
|
})
|
||||||
|
|
||||||
if self.request.session['generic_payment_type'] == 'generic':
|
if ('generic_payment_type' in self.request.session and
|
||||||
|
self.request.session['generic_payment_type'] == 'generic'):
|
||||||
context.update({'generic_payment_form': GenericPaymentForm(
|
context.update({'generic_payment_form': GenericPaymentForm(
|
||||||
prefix='generic_payment_form'
|
prefix='generic_payment_form'
|
||||||
), })
|
), })
|
||||||
|
@ -261,6 +266,8 @@ class PaymentOrderView(FormView):
|
||||||
def get(self, request, *args, **kwargs):
|
def get(self, request, *args, **kwargs):
|
||||||
if 'type' in request.GET and request.GET['type'] == 'generic':
|
if 'type' in request.GET and request.GET['type'] == 'generic':
|
||||||
request.session['generic_payment_type'] = request.GET['type']
|
request.session['generic_payment_type'] = request.GET['type']
|
||||||
|
if 'generic_payment_details' in request.session:
|
||||||
|
request.session.pop('generic_payment_details')
|
||||||
elif 'specs' not in request.session:
|
elif 'specs' not in request.session:
|
||||||
return HttpResponseRedirect(reverse('datacenterlight:index'))
|
return HttpResponseRedirect(reverse('datacenterlight:index'))
|
||||||
return self.render_to_response(self.get_context_data())
|
return self.render_to_response(self.get_context_data())
|
||||||
|
@ -285,13 +292,42 @@ class PaymentOrderView(FormView):
|
||||||
return self.render_to_response(context)
|
return self.render_to_response(context)
|
||||||
if request.user.is_authenticated():
|
if request.user.is_authenticated():
|
||||||
address_form = BillingAddressForm(
|
address_form = BillingAddressForm(
|
||||||
data=request.POST,
|
data=request.GET,
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
address_form = BillingAddressFormSignup(
|
address_form = BillingAddressFormSignup(
|
||||||
data=request.POST,
|
data=request.GET,
|
||||||
)
|
)
|
||||||
if address_form.is_valid():
|
if address_form.is_valid():
|
||||||
|
# Check if we are in a generic payment case and handle the generic
|
||||||
|
# payment details form before we go on to verify payment
|
||||||
|
if ('generic_payment_type' in request.session and
|
||||||
|
self.request.session['generic_payment_type'] == 'generic'):
|
||||||
|
generic_payment_form = GenericPaymentForm(
|
||||||
|
data=request.GET, prefix='generic_payment_form'
|
||||||
|
)
|
||||||
|
if generic_payment_form.is_valid():
|
||||||
|
logger.debug("Generic payment form is valid.")
|
||||||
|
generic_payment_details = {
|
||||||
|
"amount": generic_payment_form.cleaned_data.get(
|
||||||
|
'amount'
|
||||||
|
),
|
||||||
|
"recurring": generic_payment_form.cleaned_data.get(
|
||||||
|
'recurring'
|
||||||
|
),
|
||||||
|
"description": generic_payment_form.cleaned_data.get(
|
||||||
|
'description'
|
||||||
|
),
|
||||||
|
}
|
||||||
|
request.session["generic_payment_details"] = (
|
||||||
|
generic_payment_details
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
logger.debug("Generic payment form invalid")
|
||||||
|
context = self.get_context_data()
|
||||||
|
context['generic_payment_form'] = generic_payment_form
|
||||||
|
context['billing_address_form'] = address_form
|
||||||
|
return self.render_to_response(context)
|
||||||
token = address_form.cleaned_data.get('token')
|
token = address_form.cleaned_data.get('token')
|
||||||
if token is '':
|
if token is '':
|
||||||
card_id = address_form.cleaned_data.get('card')
|
card_id = address_form.cleaned_data.get('card')
|
||||||
|
@ -397,7 +433,8 @@ class OrderConfirmationView(DetailView):
|
||||||
@cache_control(no_cache=True, must_revalidate=True, no_store=True)
|
@cache_control(no_cache=True, must_revalidate=True, no_store=True)
|
||||||
def get(self, request, *args, **kwargs):
|
def get(self, request, *args, **kwargs):
|
||||||
context = {}
|
context = {}
|
||||||
if 'specs' not in request.session or 'user' not in request.session:
|
if (('specs' not in request.session or 'user' not in request.session)
|
||||||
|
and 'generic_payment_type' not in request.session):
|
||||||
return HttpResponseRedirect(reverse('datacenterlight:index'))
|
return HttpResponseRedirect(reverse('datacenterlight:index'))
|
||||||
if 'token' in self.request.session:
|
if 'token' in self.request.session:
|
||||||
token = self.request.session['token']
|
token = self.request.session['token']
|
||||||
|
@ -415,9 +452,19 @@ class OrderConfirmationView(DetailView):
|
||||||
card_detail = UserCardDetail.objects.get(id=card_id)
|
card_detail = UserCardDetail.objects.get(id=card_id)
|
||||||
context['cc_last4'] = card_detail.last4
|
context['cc_last4'] = card_detail.last4
|
||||||
context['cc_brand'] = card_detail.brand
|
context['cc_brand'] = card_detail.brand
|
||||||
|
|
||||||
|
if ('generic_payment_type' in request.session and
|
||||||
|
self.request.session['generic_payment_type'] == 'generic'):
|
||||||
|
context.update({
|
||||||
|
'generic_payment_details':
|
||||||
|
request.session['generic_payment_details'],
|
||||||
|
})
|
||||||
|
else:
|
||||||
|
context.update({
|
||||||
|
'vm': request.session.get('specs'),
|
||||||
|
})
|
||||||
context.update({
|
context.update({
|
||||||
'site_url': reverse('datacenterlight:index'),
|
'site_url': reverse('datacenterlight:index'),
|
||||||
'vm': request.session.get('specs'),
|
|
||||||
'page_header_text': _('Confirm Order'),
|
'page_header_text': _('Confirm Order'),
|
||||||
'billing_address_data': (
|
'billing_address_data': (
|
||||||
request.session.get('billing_address_data')
|
request.session.get('billing_address_data')
|
||||||
|
@ -427,11 +474,8 @@ class OrderConfirmationView(DetailView):
|
||||||
return render(request, self.template_name, context)
|
return render(request, self.template_name, context)
|
||||||
|
|
||||||
def post(self, request, *args, **kwargs):
|
def post(self, request, *args, **kwargs):
|
||||||
template = request.session.get('template')
|
|
||||||
specs = request.session.get('specs')
|
|
||||||
user = request.session.get('user')
|
user = request.session.get('user')
|
||||||
stripe_api_cus_id = request.session.get('customer')
|
stripe_api_cus_id = request.session.get('customer')
|
||||||
vm_template_id = template.get('id', 1)
|
|
||||||
stripe_utils = StripeUtils()
|
stripe_utils = StripeUtils()
|
||||||
|
|
||||||
if 'token' in request.session:
|
if 'token' in request.session:
|
||||||
|
@ -516,57 +560,107 @@ class OrderConfirmationView(DetailView):
|
||||||
}
|
}
|
||||||
return JsonResponse(response)
|
return JsonResponse(response)
|
||||||
|
|
||||||
cpu = specs.get('cpu')
|
if ('generic_payment_type' in request.session and
|
||||||
memory = specs.get('memory')
|
self.request.session['generic_payment_type'] == 'generic'):
|
||||||
disk_size = specs.get('disk_size')
|
gp_details = self.request.session['generic_payment_details']
|
||||||
amount_to_be_charged = specs.get('total_price')
|
if gp_details['recurring']:
|
||||||
plan_name = StripeUtils.get_stripe_plan_name(
|
# generic recurring payment
|
||||||
cpu=cpu,
|
logger.debug("Commencing a generic recurring payment")
|
||||||
memory=memory,
|
else:
|
||||||
disk_size=disk_size,
|
# generic one time payment
|
||||||
price=amount_to_be_charged
|
logger.debug("Commencing a one time payment")
|
||||||
)
|
charge_response = stripe_utils.make_charge(
|
||||||
stripe_plan_id = StripeUtils.get_stripe_plan_id(
|
amount=gp_details['amount'],
|
||||||
cpu=cpu,
|
customer=stripe_api_cus_id
|
||||||
ram=memory,
|
)
|
||||||
ssd=disk_size,
|
stripe_onetime_charge = charge_response.get('response_object')
|
||||||
version=1,
|
|
||||||
app='dcl',
|
|
||||||
price=amount_to_be_charged
|
|
||||||
)
|
|
||||||
stripe_plan = stripe_utils.get_or_create_stripe_plan(
|
|
||||||
amount=amount_to_be_charged,
|
|
||||||
name=plan_name,
|
|
||||||
stripe_plan_id=stripe_plan_id)
|
|
||||||
subscription_result = stripe_utils.subscribe_customer_to_plan(
|
|
||||||
stripe_api_cus_id,
|
|
||||||
[{"plan": stripe_plan.get(
|
|
||||||
'response_object').stripe_plan_id}])
|
|
||||||
stripe_subscription_obj = subscription_result.get('response_object')
|
|
||||||
# Check if the subscription was approved and is active
|
|
||||||
if (stripe_subscription_obj is None
|
|
||||||
or stripe_subscription_obj.status != 'active'):
|
|
||||||
# At this point, we have created a Stripe API card and
|
|
||||||
# associated it with the customer; but the transaction failed
|
|
||||||
# due to some reason. So, we would want to dissociate this card
|
|
||||||
# here.
|
|
||||||
# ...
|
|
||||||
|
|
||||||
msg = subscription_result.get('error')
|
# Check if the payment was approved
|
||||||
messages.add_message(self.request, messages.ERROR, msg,
|
if not stripe_onetime_charge:
|
||||||
extra_tags='failed_payment')
|
msg = charge_response.get('error')
|
||||||
response = {
|
messages.add_message(self.request, messages.ERROR, msg,
|
||||||
'status': False,
|
extra_tags='failed_payment')
|
||||||
'redirect': "{url}#{section}".format(
|
response = {
|
||||||
url=reverse('datacenterlight:payment'),
|
'status': False,
|
||||||
section='payment_error'),
|
'redirect': "{url}#{section}".format(
|
||||||
'msg_title': str(_('Error.')),
|
url=(reverse('datacenterlight:payment') +
|
||||||
'msg_body': str(
|
"?type=generic"),
|
||||||
_('There was a payment related error.'
|
section='payment_error'),
|
||||||
' On close of this popup, you will be redirected back to'
|
'msg_title': str(_('Error.')),
|
||||||
' the payment page.'))
|
'msg_body': str(
|
||||||
}
|
_('There was a payment related error.'
|
||||||
return JsonResponse(response)
|
' On close of this popup, you will be redirected'
|
||||||
|
' back to the payment page.'))
|
||||||
|
}
|
||||||
|
return JsonResponse(response)
|
||||||
|
|
||||||
|
if ('generic_payment_type' not in request.session or
|
||||||
|
(request.session['generic_payment_details']['recurring'])):
|
||||||
|
if request.session['generic_payment_details']['recurring']:
|
||||||
|
amount_to_be_charged = (
|
||||||
|
round(
|
||||||
|
request.session['generic_payment_details']['amount'],
|
||||||
|
2
|
||||||
|
)
|
||||||
|
)
|
||||||
|
plan_name = "generic-{0:.2f}".format(amount_to_be_charged)
|
||||||
|
stripe_plan_id = plan_name
|
||||||
|
else:
|
||||||
|
template = request.session.get('template')
|
||||||
|
specs = request.session.get('specs')
|
||||||
|
vm_template_id = template.get('id', 1)
|
||||||
|
|
||||||
|
cpu = specs.get('cpu')
|
||||||
|
memory = specs.get('memory')
|
||||||
|
disk_size = specs.get('disk_size')
|
||||||
|
amount_to_be_charged = specs.get('total_price')
|
||||||
|
plan_name = StripeUtils.get_stripe_plan_name(
|
||||||
|
cpu=cpu,
|
||||||
|
memory=memory,
|
||||||
|
disk_size=disk_size,
|
||||||
|
price=amount_to_be_charged
|
||||||
|
)
|
||||||
|
stripe_plan_id = StripeUtils.get_stripe_plan_id(
|
||||||
|
cpu=cpu,
|
||||||
|
ram=memory,
|
||||||
|
ssd=disk_size,
|
||||||
|
version=1,
|
||||||
|
app='dcl',
|
||||||
|
price=amount_to_be_charged
|
||||||
|
)
|
||||||
|
stripe_plan = stripe_utils.get_or_create_stripe_plan(
|
||||||
|
amount=amount_to_be_charged,
|
||||||
|
name=plan_name,
|
||||||
|
stripe_plan_id=stripe_plan_id)
|
||||||
|
subscription_result = stripe_utils.subscribe_customer_to_plan(
|
||||||
|
stripe_api_cus_id,
|
||||||
|
[{"plan": stripe_plan.get(
|
||||||
|
'response_object').stripe_plan_id}])
|
||||||
|
stripe_subscription_obj = subscription_result.get('response_object')
|
||||||
|
# Check if the subscription was approved and is active
|
||||||
|
if (stripe_subscription_obj is None
|
||||||
|
or stripe_subscription_obj.status != 'active'):
|
||||||
|
# At this point, we have created a Stripe API card and
|
||||||
|
# associated it with the customer; but the transaction failed
|
||||||
|
# due to some reason. So, we would want to dissociate this card
|
||||||
|
# here.
|
||||||
|
# ...
|
||||||
|
|
||||||
|
msg = subscription_result.get('error')
|
||||||
|
messages.add_message(self.request, messages.ERROR, msg,
|
||||||
|
extra_tags='failed_payment')
|
||||||
|
response = {
|
||||||
|
'status': False,
|
||||||
|
'redirect': "{url}#{section}".format(
|
||||||
|
url=reverse('datacenterlight:payment'),
|
||||||
|
section='payment_error'),
|
||||||
|
'msg_title': str(_('Error.')),
|
||||||
|
'msg_body': str(
|
||||||
|
_('There was a payment related error.'
|
||||||
|
' On close of this popup, you will be redirected back to'
|
||||||
|
' the payment page.'))
|
||||||
|
}
|
||||||
|
return JsonResponse(response)
|
||||||
|
|
||||||
# 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
|
||||||
|
@ -636,6 +730,118 @@ class OrderConfirmationView(DetailView):
|
||||||
'user': custom_user.id
|
'user': custom_user.id
|
||||||
})
|
})
|
||||||
|
|
||||||
|
if 'generic_payment_type' in request.session:
|
||||||
|
|
||||||
|
stripe_cus = StripeCustomer.objects.filter(
|
||||||
|
stripe_id=stripe_api_cus_id
|
||||||
|
).first()
|
||||||
|
billing_address = BillingAddress(
|
||||||
|
cardholder_name=billing_address_data['cardholder_name'],
|
||||||
|
street_address=billing_address_data['street_address'],
|
||||||
|
city=billing_address_data['city'],
|
||||||
|
postal_code=billing_address_data['postal_code'],
|
||||||
|
country=billing_address_data['country']
|
||||||
|
)
|
||||||
|
billing_address.save()
|
||||||
|
|
||||||
|
order = HostingOrder.create(
|
||||||
|
price=self.request
|
||||||
|
.session['generic_payment_details']['amount'],
|
||||||
|
customer=stripe_cus,
|
||||||
|
billing_address=billing_address,
|
||||||
|
vm_pricing=VMPricing.get_default_pricing()
|
||||||
|
)
|
||||||
|
|
||||||
|
# Create a Hosting Bill
|
||||||
|
HostingBill.create(customer=stripe_cus,
|
||||||
|
billing_address=billing_address)
|
||||||
|
|
||||||
|
# Create Billing Address for User if he does not have one
|
||||||
|
if not stripe_cus.user.billing_addresses.count():
|
||||||
|
billing_address_data.update({
|
||||||
|
'user': stripe_cus.user.id
|
||||||
|
})
|
||||||
|
billing_address_user_form = UserBillingAddressForm(
|
||||||
|
billing_address_data
|
||||||
|
)
|
||||||
|
billing_address_user_form.is_valid()
|
||||||
|
billing_address_user_form.save()
|
||||||
|
|
||||||
|
if self.request.session['generic_payment_details']['recurring']:
|
||||||
|
# Associate the given stripe subscription with the order
|
||||||
|
order.set_subscription_id(
|
||||||
|
stripe_subscription_obj.id, card_details_dict
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
# Associate the given stripe charge id with the order
|
||||||
|
order.set_stripe_charge(stripe_onetime_charge)
|
||||||
|
|
||||||
|
# Set order status approved
|
||||||
|
order.set_approved()
|
||||||
|
|
||||||
|
order.generic_payment_id = str(uuid.uuid4())
|
||||||
|
order.save()
|
||||||
|
# send emails
|
||||||
|
context = {
|
||||||
|
'name': user.get('name'),
|
||||||
|
'email': user.get('email'),
|
||||||
|
'amount': gp_details['amount'],
|
||||||
|
'description': gp_details['description'],
|
||||||
|
'recurring': gp_details['recurring'],
|
||||||
|
'order_id': order.id
|
||||||
|
}
|
||||||
|
|
||||||
|
email_data = {
|
||||||
|
'subject': settings.DCL_TEXT + " Payment received from %s" % context[
|
||||||
|
'email'],
|
||||||
|
'from_email': settings.DCL_SUPPORT_FROM_ADDRESS,
|
||||||
|
'to': ['info@ungleich.ch'],
|
||||||
|
'body': "\n".join(
|
||||||
|
["%s=%s" % (k, v) for (k, v) in context.items()]),
|
||||||
|
'reply_to': [context['email']],
|
||||||
|
}
|
||||||
|
send_plain_email_task.delay(email_data)
|
||||||
|
|
||||||
|
email_data = {
|
||||||
|
'subject': (settings.DCL_TEXT +
|
||||||
|
" Payment received from %s" % context['email']),
|
||||||
|
'from_email': settings.DCL_SUPPORT_FROM_ADDRESS,
|
||||||
|
'to': [user.get('email')],
|
||||||
|
'body': ("Hi {name},\n\n"
|
||||||
|
"We just received a payment of {amount}{recurring} "
|
||||||
|
"from you. We will get back to you on this soon.\n\n"
|
||||||
|
"Your DataCenterLight Team".format(
|
||||||
|
name=user.get('name'),
|
||||||
|
amount=gp_details['amount'],
|
||||||
|
recurring=gp_details['recurring']
|
||||||
|
)
|
||||||
|
),
|
||||||
|
'reply_to': ['info@ungleich.ch'],
|
||||||
|
}
|
||||||
|
send_plain_email_task.delay(email_data)
|
||||||
|
|
||||||
|
response = {
|
||||||
|
'status': True,
|
||||||
|
'redirect': (
|
||||||
|
reverse('hosting:virtual_machines')
|
||||||
|
if request.user.is_authenticated()
|
||||||
|
else reverse('datacenterlight:index')
|
||||||
|
),
|
||||||
|
'msg_title': str(_('Thank you for the payment.')),
|
||||||
|
'msg_body': str(
|
||||||
|
_('You will soon receive a confirmation email of the '
|
||||||
|
'payment. You can always contact us at '
|
||||||
|
'info@ungleich.ch for any question that you may have.')
|
||||||
|
)
|
||||||
|
}
|
||||||
|
for session_var in ['specs', 'template', 'billing_address',
|
||||||
|
'billing_address_data', 'card_id',
|
||||||
|
'token', 'customer', 'generic_payment_type', 'generic_payment_details']:
|
||||||
|
if session_var in request.session:
|
||||||
|
del request.session[session_var]
|
||||||
|
|
||||||
|
return JsonResponse(response)
|
||||||
|
|
||||||
user = {
|
user = {
|
||||||
'name': custom_user.name,
|
'name': custom_user.name,
|
||||||
'email': custom_user.email,
|
'email': custom_user.email,
|
||||||
|
|
Loading…
Reference in a new issue