2019-12-25 14:41:15 +00:00
|
|
|
import datetime
|
2018-08-21 21:24:40 +00:00
|
|
|
import logging
|
2019-07-01 15:00:35 +00:00
|
|
|
|
2019-05-13 01:34:54 +00:00
|
|
|
import pyotp
|
|
|
|
import requests
|
2019-12-25 14:41:15 +00:00
|
|
|
import stripe
|
2019-05-13 07:44:09 +00:00
|
|
|
from django.conf import settings
|
2019-07-01 15:00:35 +00:00
|
|
|
from django.contrib.sites.models import Site
|
2018-04-03 17:11:29 +00:00
|
|
|
|
2018-04-20 14:55:24 +00:00
|
|
|
from datacenterlight.tasks import create_vm_task
|
2018-07-01 20:30:23 +00:00
|
|
|
from hosting.models import HostingOrder, HostingBill, OrderDetail
|
2018-04-20 14:55:24 +00:00
|
|
|
from membership.models import StripeCustomer
|
|
|
|
from utils.forms import UserBillingAddressForm
|
2019-12-25 14:41:15 +00:00
|
|
|
from utils.models import BillingAddress, UserBillingAddress
|
2019-12-25 15:32:43 +00:00
|
|
|
from utils.stripe_utils import StripeUtils
|
2018-04-03 17:11:29 +00:00
|
|
|
from .cms_models import CMSIntegration
|
2018-07-01 16:33:10 +00:00
|
|
|
from .models import VMPricing, VMTemplate
|
2018-04-03 17:11:29 +00:00
|
|
|
|
2018-08-21 21:24:40 +00:00
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
2019-12-31 11:58:11 +00:00
|
|
|
eu_countries = ['at', 'be', 'bg', 'ch', 'cy', 'cz', 'hr', 'dk',
|
|
|
|
'ee', 'fi', 'fr', 'mc', 'de', 'gr', 'hu', 'ie', 'it',
|
|
|
|
'lv', 'lu', 'mt', 'nl', 'po', 'pt', 'ro','sk', 'si', 'es',
|
|
|
|
'se', 'gb']
|
|
|
|
|
2019-12-25 14:41:15 +00:00
|
|
|
|
2018-04-03 17:11:29 +00:00
|
|
|
def get_cms_integration(name):
|
|
|
|
current_site = Site.objects.get_current()
|
|
|
|
try:
|
|
|
|
cms_integration = CMSIntegration.objects.get(
|
|
|
|
name=name, domain=current_site
|
|
|
|
)
|
|
|
|
except CMSIntegration.DoesNotExist:
|
|
|
|
cms_integration = CMSIntegration.objects.get(name=name, domain=None)
|
|
|
|
return cms_integration
|
2018-04-20 14:55:24 +00:00
|
|
|
|
|
|
|
|
|
|
|
def create_vm(billing_address_data, stripe_customer_id, specs,
|
|
|
|
stripe_subscription_obj, card_details_dict, request,
|
|
|
|
vm_template_id, template, user):
|
|
|
|
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'],
|
2019-12-25 05:02:37 +00:00
|
|
|
country=billing_address_data['country'],
|
|
|
|
vat_number=billing_address_data['vat_number'],
|
2018-04-20 14:55:24 +00:00
|
|
|
)
|
|
|
|
billing_address.save()
|
|
|
|
customer = StripeCustomer.objects.filter(id=stripe_customer_id).first()
|
2018-04-21 15:31:42 +00:00
|
|
|
vm_pricing = (
|
|
|
|
VMPricing.get_vm_pricing_by_name(name=specs['pricing_name'])
|
|
|
|
if 'pricing_name' in specs else
|
|
|
|
VMPricing.get_default_pricing()
|
|
|
|
)
|
|
|
|
|
|
|
|
final_price = (
|
|
|
|
specs.get('total_price')
|
|
|
|
if 'total_price' in specs
|
|
|
|
else specs.get('price')
|
|
|
|
)
|
2018-04-20 14:55:24 +00:00
|
|
|
|
|
|
|
# Create a Hosting Order with vm_id = 0, we shall set it later in
|
|
|
|
# celery task once the VM instance is up and running
|
|
|
|
order = HostingOrder.create(
|
2018-04-21 15:31:42 +00:00
|
|
|
price=final_price,
|
2018-04-20 14:55:24 +00:00
|
|
|
customer=customer,
|
2018-04-21 15:31:42 +00:00
|
|
|
billing_address=billing_address,
|
|
|
|
vm_pricing=vm_pricing
|
2018-04-20 14:55:24 +00:00
|
|
|
)
|
|
|
|
|
2018-07-01 20:30:23 +00:00
|
|
|
order_detail_obj, obj_created = OrderDetail.objects.get_or_create(
|
2018-07-01 16:42:11 +00:00
|
|
|
vm_template=VMTemplate.objects.get(
|
|
|
|
opennebula_vm_template_id=vm_template_id
|
|
|
|
),
|
2018-07-01 16:33:10 +00:00
|
|
|
cores=specs['cpu'], memory=specs['memory'], ssd_size=specs['disk_size']
|
|
|
|
)
|
2018-07-01 20:30:23 +00:00
|
|
|
order.order_detail = order_detail_obj
|
2018-07-01 16:33:10 +00:00
|
|
|
order.save()
|
|
|
|
|
2018-04-20 14:55:24 +00:00
|
|
|
# Create a Hosting Bill
|
|
|
|
HostingBill.create(customer=customer, billing_address=billing_address)
|
|
|
|
|
|
|
|
# Create Billing Address for User if he does not have one
|
|
|
|
if not customer.user.billing_addresses.count():
|
|
|
|
billing_address_data.update({
|
|
|
|
'user': customer.user.id
|
|
|
|
})
|
|
|
|
billing_address_user_form = UserBillingAddressForm(
|
|
|
|
billing_address_data
|
|
|
|
)
|
|
|
|
billing_address_user_form.is_valid()
|
|
|
|
billing_address_user_form.save()
|
|
|
|
|
2018-06-27 10:24:53 +00:00
|
|
|
# Associate the given stripe subscription with the order
|
2018-04-20 14:55:24 +00:00
|
|
|
order.set_subscription_id(
|
|
|
|
stripe_subscription_obj.id, card_details_dict
|
|
|
|
)
|
|
|
|
|
2018-06-27 10:24:53 +00:00
|
|
|
# Set order status approved
|
2018-04-20 14:55:24 +00:00
|
|
|
order.set_approved()
|
|
|
|
|
|
|
|
create_vm_task.delay(vm_template_id, user, specs, template, order.id)
|
|
|
|
|
2018-10-05 08:36:13 +00:00
|
|
|
clear_all_session_vars(request)
|
|
|
|
|
|
|
|
|
|
|
|
def clear_all_session_vars(request):
|
|
|
|
if request.session is not None:
|
|
|
|
for session_var in ['specs', 'template', 'billing_address',
|
|
|
|
'billing_address_data', 'card_id',
|
2018-10-06 05:47:40 +00:00
|
|
|
'token', 'customer', 'generic_payment_type',
|
2019-07-01 15:00:35 +00:00
|
|
|
'generic_payment_details', 'product_id',
|
2019-12-25 17:18:57 +00:00
|
|
|
'order_confirm_url', 'new_user_hosting_key_id',
|
2019-12-26 05:19:45 +00:00
|
|
|
'vat_validation_status', 'billing_address_id']:
|
2018-10-05 08:36:13 +00:00
|
|
|
if session_var in request.session:
|
2018-10-06 05:47:40 +00:00
|
|
|
del request.session[session_var]
|
2019-05-13 01:34:54 +00:00
|
|
|
|
|
|
|
|
|
|
|
def check_otp(name, realm, token):
|
|
|
|
data = {
|
2019-05-13 07:44:09 +00:00
|
|
|
"auth_name": settings.AUTH_NAME,
|
|
|
|
"auth_token": pyotp.TOTP(settings.AUTH_SEED).now(),
|
|
|
|
"auth_realm": settings.AUTH_REALM,
|
2019-05-13 01:34:54 +00:00
|
|
|
"name": name,
|
|
|
|
"realm": realm,
|
|
|
|
"token": token
|
|
|
|
}
|
|
|
|
response = requests.post(
|
|
|
|
"https://{OTP_SERVER}{OTP_VERIFY_ENDPOINT}".format(
|
2019-05-13 07:44:09 +00:00
|
|
|
OTP_SERVER=settings.OTP_SERVER,
|
|
|
|
OTP_VERIFY_ENDPOINT=settings.OTP_VERIFY_ENDPOINT
|
2019-05-13 01:34:54 +00:00
|
|
|
),
|
|
|
|
data=data
|
|
|
|
)
|
|
|
|
return response.status_code
|
2019-12-25 14:41:15 +00:00
|
|
|
|
|
|
|
|
2019-12-26 08:01:15 +00:00
|
|
|
def validate_vat_number(stripe_customer_id, billing_address_id,
|
|
|
|
is_user_ba=False):
|
|
|
|
if is_user_ba:
|
|
|
|
try:
|
|
|
|
billing_address = UserBillingAddress.objects.get(
|
|
|
|
id=billing_address_id)
|
|
|
|
except UserBillingAddress.DoesNotExist as dne:
|
|
|
|
billing_address = None
|
|
|
|
logger.debug(
|
|
|
|
"UserBillingAddress does not exist for %s" % billing_address_id)
|
|
|
|
except UserBillingAddress.MultipleObjectsReturned as mor:
|
|
|
|
logger.debug(
|
|
|
|
"Multiple UserBillingAddress exist for %s" % billing_address_id)
|
|
|
|
billing_address = UserBillingAddress.objects.filter(
|
|
|
|
id=billing_address_id).order_by('-id').first()
|
|
|
|
else:
|
|
|
|
try:
|
|
|
|
billing_address = BillingAddress.objects.get(id=billing_address_id)
|
|
|
|
except BillingAddress.DoesNotExist as dne:
|
|
|
|
billing_address = None
|
|
|
|
logger.debug("BillingAddress does not exist for %s" % billing_address_id)
|
|
|
|
except BillingAddress.MultipleObjectsReturned as mor:
|
|
|
|
logger.debug("Multiple BillingAddress exist for %s" % billing_address_id)
|
|
|
|
billing_address = BillingAddress.objects.filter(id=billing_address_id).order_by('-id').first()
|
2019-12-25 14:41:15 +00:00
|
|
|
if billing_address is not None:
|
2019-12-26 12:52:08 +00:00
|
|
|
logger.debug("BillingAddress found: %s %s type=%s" % (
|
|
|
|
billing_address_id, str(billing_address), type(billing_address)))
|
2019-12-31 11:58:11 +00:00
|
|
|
if billing_address.country.lower().strip() not in eu_countries:
|
|
|
|
return {
|
|
|
|
"validated_on": "",
|
|
|
|
"status": "not_needed"
|
|
|
|
}
|
2019-12-25 14:41:15 +00:00
|
|
|
if billing_address.vat_number_validated_on:
|
2019-12-26 12:52:08 +00:00
|
|
|
logger.debug("billing_address verified on %s" %
|
|
|
|
billing_address.vat_number_validated_on)
|
2019-12-25 14:41:15 +00:00
|
|
|
return {
|
|
|
|
"validated_on": billing_address.vat_number_validated_on,
|
|
|
|
"status": "verified"
|
|
|
|
}
|
|
|
|
else:
|
2019-12-26 12:52:08 +00:00
|
|
|
logger.debug("billing_address not yet verified, "
|
|
|
|
"Checking if we already have a tax id")
|
2019-12-25 14:41:15 +00:00
|
|
|
if billing_address.stripe_tax_id:
|
2019-12-26 12:52:08 +00:00
|
|
|
logger.debug("We have a tax id %s" % billing_address.stripe_tax_id)
|
2019-12-25 14:41:15 +00:00
|
|
|
tax_id_obj = stripe.Customer.retrieve_tax_id(
|
|
|
|
stripe_customer_id,
|
|
|
|
billing_address.stripe_tax_id,
|
|
|
|
)
|
|
|
|
if tax_id_obj.verification.status == "verified":
|
2019-12-26 12:52:08 +00:00
|
|
|
logger.debug("Latest status on Stripe=%s. Updating" %
|
|
|
|
tax_id_obj.verification.status)
|
2019-12-26 05:20:53 +00:00
|
|
|
# update billing address
|
|
|
|
billing_address.vat_number_validated_on = datetime.datetime.now()
|
2019-12-26 14:07:57 +00:00
|
|
|
billing_address.vat_validation_status = tax_id_obj.verification.status
|
2019-12-26 05:20:53 +00:00
|
|
|
billing_address.save()
|
2019-12-25 14:41:15 +00:00
|
|
|
return {
|
|
|
|
"status": "verified",
|
|
|
|
"validated_on": billing_address.vat_number_validated_on
|
|
|
|
}
|
|
|
|
else:
|
2019-12-26 14:07:57 +00:00
|
|
|
billing_address.vat_validation_status = tax_id_obj.verification.status
|
|
|
|
billing_address.save()
|
2019-12-26 12:52:08 +00:00
|
|
|
logger.debug(
|
|
|
|
"Latest status on Stripe=%s" % str(tax_id_obj)
|
|
|
|
)
|
2019-12-25 14:41:15 +00:00
|
|
|
return {
|
2019-12-26 12:52:08 +00:00
|
|
|
"status": tax_id_obj.verification.status if tax_id_obj
|
|
|
|
else "unknown",
|
2019-12-25 14:41:15 +00:00
|
|
|
"validated_on": ""
|
|
|
|
}
|
|
|
|
else:
|
2019-12-26 12:52:08 +00:00
|
|
|
logger.debug("Creating a tax id")
|
2019-12-31 12:38:09 +00:00
|
|
|
logger.debug("Billing address = %s" % str(billing_address))
|
2019-12-25 17:40:18 +00:00
|
|
|
tax_id_obj = create_tax_id(
|
2019-12-26 06:00:01 +00:00
|
|
|
stripe_customer_id, billing_address_id,
|
2019-12-26 08:51:18 +00:00
|
|
|
"ch_vat" if billing_address.country.lower() == "ch" else "eu_vat",
|
|
|
|
is_user_ba=is_user_ba
|
|
|
|
)
|
2019-12-26 12:56:30 +00:00
|
|
|
logger.debug("tax_id_obj = %s" % str(tax_id_obj))
|
2019-12-25 14:41:15 +00:00
|
|
|
else:
|
2019-12-26 12:52:08 +00:00
|
|
|
logger.debug("invalid billing address")
|
2019-12-26 05:20:53 +00:00
|
|
|
return {
|
|
|
|
"status": "invalid billing address",
|
|
|
|
"validated_on": ""
|
|
|
|
}
|
2019-12-25 14:41:15 +00:00
|
|
|
|
2019-12-25 15:32:43 +00:00
|
|
|
if 'response_object' in tax_id_obj:
|
|
|
|
return tax_id_obj
|
|
|
|
|
2019-12-25 14:41:15 +00:00
|
|
|
return {
|
|
|
|
"status": tax_id_obj.verification.status,
|
|
|
|
"validated_on": datetime.datetime.now() if tax_id_obj.verification.status == "verified" else ""
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-12-26 08:49:07 +00:00
|
|
|
def create_tax_id(stripe_customer_id, billing_address_id, type,
|
|
|
|
is_user_ba=False):
|
|
|
|
if is_user_ba:
|
|
|
|
try:
|
|
|
|
billing_address = UserBillingAddress.objects.get(
|
|
|
|
id=billing_address_id)
|
|
|
|
except UserBillingAddress.DoesNotExist as dne:
|
|
|
|
billing_address = None
|
|
|
|
logger.debug(
|
|
|
|
"UserBillingAddress does not exist for %s" % billing_address_id)
|
|
|
|
except UserBillingAddress.MultipleObjectsReturned as mor:
|
|
|
|
logger.debug(
|
|
|
|
"Multiple UserBillingAddress exist for %s" % billing_address_id)
|
|
|
|
billing_address = UserBillingAddress.objects.filter(
|
|
|
|
id=billing_address_id).order_by('-id').first()
|
|
|
|
else:
|
|
|
|
try:
|
|
|
|
billing_address = BillingAddress.objects.get(id=billing_address_id)
|
|
|
|
except BillingAddress.DoesNotExist as dne:
|
|
|
|
billing_address = None
|
|
|
|
logger.debug("BillingAddress does not exist for %s" % billing_address_id)
|
|
|
|
except BillingAddress.MultipleObjectsReturned as mor:
|
|
|
|
logger.debug("Multiple BillingAddress exist for %s" % billing_address_id)
|
|
|
|
billing_address = BillingAddress.objects.filter(billing_address_id).order_by('-id').first()
|
2019-12-25 15:32:43 +00:00
|
|
|
stripe_utils = StripeUtils()
|
2019-12-26 12:36:22 +00:00
|
|
|
tax_id_response = stripe_utils.get_or_create_tax_id_for_user(
|
2019-12-25 14:41:15 +00:00
|
|
|
stripe_customer_id,
|
2019-12-26 06:00:01 +00:00
|
|
|
vat_number=billing_address.vat_number,
|
2019-12-25 17:40:18 +00:00
|
|
|
type=type
|
2019-12-25 14:41:15 +00:00
|
|
|
)
|
2019-12-25 15:32:43 +00:00
|
|
|
|
|
|
|
tax_id_obj = tax_id_response.get('response_object')
|
|
|
|
|
|
|
|
if not tax_id_obj:
|
2019-12-26 13:04:26 +00:00
|
|
|
logger.debug("Received none in tax_id_obj")
|
2019-12-25 15:32:43 +00:00
|
|
|
return tax_id_response
|
|
|
|
|
2019-12-26 06:00:01 +00:00
|
|
|
try:
|
|
|
|
stripe_customer = StripeCustomer.objects.get(stripe_id=stripe_customer_id)
|
|
|
|
billing_address_set = set()
|
2019-12-26 13:04:26 +00:00
|
|
|
logger.debug("Updating billing address")
|
2019-12-26 06:00:01 +00:00
|
|
|
for ho in stripe_customer.hostingorder_set.all():
|
|
|
|
if ho.billing_address.vat_number == billing_address.vat_number:
|
|
|
|
billing_address_set.add(ho.billing_address)
|
|
|
|
for b_address in billing_address_set:
|
|
|
|
b_address.stripe_tax_id = tax_id_obj.id
|
2019-12-26 14:25:28 +00:00
|
|
|
b_address.vat_validation_status = tax_id_obj.verification.status
|
2019-12-26 08:57:16 +00:00
|
|
|
b_address.save()
|
2019-12-26 13:04:26 +00:00
|
|
|
logger.debug("Updated billing_address %s" % str(b_address))
|
2019-12-26 06:00:01 +00:00
|
|
|
|
|
|
|
ub_addresses = stripe_customer.user.billing_addresses.filter(
|
|
|
|
vat_number=billing_address.vat_number)
|
|
|
|
for ub_address in ub_addresses:
|
|
|
|
ub_address.stripe_tax_id = tax_id_obj.id
|
2019-12-26 14:25:28 +00:00
|
|
|
ub_address.vat_validation_status = tax_id_obj.verification.status
|
2019-12-26 08:57:16 +00:00
|
|
|
ub_address.save()
|
2019-12-26 13:04:26 +00:00
|
|
|
logger.debug("Updated user_billing_address %s" % str(ub_address))
|
2019-12-26 06:00:01 +00:00
|
|
|
except StripeCustomer.DoesNotExist as dne:
|
|
|
|
logger.debug("StripeCustomer %s does not exist" % stripe_customer_id)
|
|
|
|
billing_address.stripe_tax_id = tax_id_obj.id
|
2019-12-26 14:25:28 +00:00
|
|
|
billing_address.vat_validation_status = tax_id_obj.verification.status
|
2019-12-26 06:00:01 +00:00
|
|
|
billing_address.save()
|
2019-12-25 14:41:15 +00:00
|
|
|
return tax_id_obj
|