Ejemplo n.º 1
0
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'],
        country=billing_address_data['country'])
    billing_address.save()
    customer = StripeCustomer.objects.filter(id=stripe_customer_id).first()
    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'))

    # 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(price=final_price,
                                customer=customer,
                                billing_address=billing_address,
                                vm_pricing=vm_pricing)

    order_detail_obj, obj_created = OrderDetail.objects.get_or_create(
        vm_template=VMTemplate.objects.get(
            opennebula_vm_template_id=vm_template_id),
        cores=specs['cpu'],
        memory=specs['memory'],
        ssd_size=specs['disk_size'])
    order.order_detail = order_detail_obj
    order.save()

    # 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()

    # Associate the given stripe subscription with the order
    order.set_subscription_id(stripe_subscription_obj.id, card_details_dict)

    # Set order status approved
    order.set_approved()

    create_vm_task.delay(vm_template_id, user, specs, template, order.id)

    for session_var in [
            'specs', 'template', 'billing_address', 'billing_address_data',
            'card_id', 'token', 'customer'
    ]:
        if session_var in request.session:
            del request.session[session_var]
Ejemplo n.º 2
0
    def test_create_vm_task(self):
        """Tests the create vm task for monthly subscription

        This test is supposed to validate the proper execution
        of celery create_vm_task on production, as we have no
        other way to do this.
        """

        # We create a VM from the first template available to DCL
        vm_template = VMTemplate.objects.all().first()
        template_data = VMTemplateSerializer(vm_template).data

        # The specs of VM that we want to create
        specs = {'cpu': 1, 'memory': 2, 'disk_size': 10, 'price': 15}

        stripe_customer = StripeCustomer.get_or_create(
            email=self.customer_email, token=self.token)
        card_details = self.stripe_utils.get_card_details(
            stripe_customer.stripe_id)
        card_details_dict = card_details.get('error')
        self.assertEquals(card_details_dict, None)
        billing_address_data = {
            'cardholder_name': self.customer_name,
            'postal_code': '1231',
            'country': 'CH',
            'token': self.token,
            'street_address': 'Monty\'s Street',
            'city': 'Hollywood'
        }
        vm_template_id = template_data.get('id', 1)

        cpu = specs.get('cpu')
        memory = specs.get('memory')
        disk_size = specs.get('disk_size')
        amount_to_be_charged = get_vm_price(cpu=cpu,
                                            memory=memory,
                                            disk_size=disk_size)
        plan_name = StripeUtils.get_stripe_plan_name(cpu=cpu,
                                                     memory=memory,
                                                     disk_size=disk_size)
        stripe_plan_id = StripeUtils.get_stripe_plan_id(cpu=cpu,
                                                        ram=memory,
                                                        ssd=disk_size,
                                                        version=1,
                                                        app='dcl')
        stripe_plan = self.stripe_utils.get_or_create_stripe_plan(
            amount=amount_to_be_charged,
            name=plan_name,
            stripe_plan_id=stripe_plan_id)
        subscription_result = self.stripe_utils.subscribe_customer_to_plan(
            stripe_customer.stripe_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':
            msg = subscription_result.get('error')
            raise Exception("Creating subscription failed: {}".format(msg))

        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=specs['price'],
                                    vm_id=0,
                                    customer=stripe_customer,
                                    billing_address=billing_address)

        async_task = create_vm_task.delay(vm_template_id, self.user, specs,
                                          template_data, order.id)
        new_vm_id = 0
        res = None
        for i in range(0, 10):
            sleep(5)
            res = AsyncResult(async_task.task_id)
            if res.result is not None and res.result > 0:
                new_vm_id = res.result
                break

        # We expect a VM to be created within 50 seconds
        self.assertGreater(
            new_vm_id, 0,
            "VM could not be created. res._get_task_meta() = {}".format(
                res._get_task_meta()))
Ejemplo n.º 3
0
    def post(self, request, *args, **kwargs):
        template = request.session.get('template')
        specs = request.session.get('specs')
        user = request.session.get('user')
        stripe_customer_id = request.session.get('customer')
        customer = StripeCustomer.objects.filter(id=stripe_customer_id).first()
        billing_address_data = request.session.get('billing_address_data')
        billing_address_id = request.session.get('billing_address')
        billing_address = BillingAddress.objects.filter(
            id=billing_address_id).first()
        vm_template_id = template.get('id', 1)
        final_price = specs.get('price')

        # Make stripe charge to a customer
        stripe_utils = StripeUtils()
        charge_response = stripe_utils.make_charge(amount=final_price,
                                                   customer=customer.stripe_id)
        charge = charge_response.get('response_object')

        # Check if the payment was approved
        if not charge:
            context = {}
            context.update({'paymentError': charge_response.get('error')})
            return render(request, self.payment_template_name, context)

        charge = charge_response.get('response_object')

        # Create OpenNebulaManager
        manager = OpenNebulaManager(email=settings.OPENNEBULA_USERNAME,
                                    password=settings.OPENNEBULA_PASSWORD)

        # Create a vm using oneadmin, also specify the name
        vm_id = manager.create_vm(
            template_id=vm_template_id,
            specs=specs,
            vm_name="{email}-{template_name}-{date}".format(
                email=user.get('email'),
                template_name=template.get('name'),
                date=int(datetime.now().strftime("%s"))))

        # Create a Hosting Order
        order = HostingOrder.create(price=final_price,
                                    vm_id=vm_id,
                                    customer=customer,
                                    billing_address=billing_address)

        # 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()

        # Associate an order with a stripe payment
        order.set_stripe_charge(charge)

        # If the Stripe payment was successed, set order status approved
        order.set_approved()

        vm = VirtualMachineSerializer(manager.get_vm(vm_id)).data

        context = {
            'name': user.get('name'),
            'email': user.get('email'),
            'cores': specs.get('cpu'),
            'memory': specs.get('memory'),
            'storage': specs.get('disk_size'),
            'price': specs.get('price'),
            'template': template.get('name'),
            'vm.name': vm['name'],
            'vm.id': vm['vm_id'],
            'order.id': order.id
        }
        email_data = {
            'subject': settings.DCL_TEXT + " Order from %s" % context['email'],
            'from_email': settings.DCL_SUPPORT_FROM_ADDRESS,
            'to': ['*****@*****.**'],
            'body':
            "\n".join(["%s=%s" % (k, v) for (k, v) in context.items()]),
            'reply_to': [context['email']],
        }
        email = EmailMessage(**email_data)
        email.send()
        request.session['order_confirmation'] = True
        return HttpResponseRedirect(reverse('datacenterlight:order_success'))
Ejemplo n.º 4
0
    def post(self, request, *args, **kwargs):
        user = request.session.get('user')
        stripe_api_cus_id = request.session.get('customer')
        stripe_utils = StripeUtils()

        if 'token' in request.session:
            card_details = stripe_utils.get_cards_details_from_token(
                request.session.get('token'))
            if not card_details.get('response_object'):
                msg = card_details.get('error')
                messages.add_message(self.request,
                                     messages.ERROR,
                                     msg,
                                     extra_tags='failed_payment')
                response = {
                    'status':
                    False,
                    'redirect':
                    "{url}#{section}".format(
                        url=(reverse(
                            'show_product',
                            kwargs={
                                'product_slug':
                                request.session['generic_payment_details']
                                ['product_slug']
                            }) if 'generic_payment_details' in request.session
                             else 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)
            card_details_response = card_details['response_object']
            card_details_dict = {
                'last4': card_details_response['last4'],
                'brand': card_details_response['brand'],
                'card_id': card_details_response['card_id']
            }
            stripe_customer_obj = StripeCustomer.objects.filter(
                stripe_id=stripe_api_cus_id).first()
            if stripe_customer_obj:
                ucd = UserCardDetail.get_user_card_details(
                    stripe_customer_obj, card_details_response)
                if not ucd:
                    acc_result = stripe_utils.associate_customer_card(
                        stripe_api_cus_id,
                        request.session['token'],
                        set_as_default=True)
                    if acc_result['response_object'] is None:
                        msg = _('An error occurred while associating the card.'
                                ' Details: {details}'.format(
                                    details=acc_result['error']))
                        messages.add_message(self.request,
                                             messages.ERROR,
                                             msg,
                                             extra_tags='failed_payment')
                        response = {
                            'status':
                            False,
                            'redirect':
                            "{url}#{section}".
                            format(url=(reverse(
                                'show_product',
                                kwargs={
                                    'product_slug':
                                    request.session['generic_payment_details']
                                    ['product_slug']
                                }) if 'generic_payment_details'
                                        in request.session else
                                        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)
        elif 'card_id' in request.session:
            card_id = request.session.get('card_id')
            user_card_detail = UserCardDetail.objects.get(id=card_id)
            card_details_dict = {
                'last4': user_card_detail.last4,
                'brand': user_card_detail.brand,
                'card_id': user_card_detail.card_id
            }
        else:
            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)

        if ('generic_payment_type' in request.session
                and self.request.session['generic_payment_type'] == 'generic'):
            gp_details = self.request.session['generic_payment_details']
            if gp_details['recurring']:
                # generic recurring payment
                logger.debug("Commencing a generic recurring payment")
            else:
                # generic one time payment
                logger.debug("Commencing a one time payment")
                charge_response = stripe_utils.make_charge(
                    amount=gp_details['amount'], customer=stripe_api_cus_id)
                stripe_onetime_charge = charge_response.get('response_object')

                # Check if the payment was approved
                if not stripe_onetime_charge:
                    msg = charge_response.get('error')
                    messages.add_message(self.request,
                                         messages.ERROR,
                                         msg,
                                         extra_tags='failed_payment')
                    response = {
                        'status':
                        False,
                        'redirect':
                        "{url}#{section}".format(
                            url=(reverse('show_product',
                                         kwargs={
                                             'product_slug':
                                             gp_details['product_slug']
                                         }) if 'generic_payment_details'
                                 in request.session else
                                 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)

        if ('generic_payment_type' not in request.session
                or (request.session['generic_payment_details']['recurring'])):
            if 'generic_payment_details' in request.session:
                amount_to_be_charged = (round(
                    request.session['generic_payment_details']['amount'], 2))
                plan_name = "generic-{0}-{1:.2f}".format(
                    request.session['generic_payment_details']['product_id'],
                    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(
                            'show_product',
                            kwargs={
                                'product_slug':
                                request.session['generic_payment_details']
                                ['product_slug']
                            }) if 'generic_payment_details' in request.session
                             else 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
        # registered
        if not request.user.is_authenticated():
            try:
                custom_user = CustomUser.objects.get(email=user.get('email'))
                stripe_customer = StripeCustomer.objects.filter(
                    user_id=custom_user.id).first()
                if stripe_customer is None:
                    stripe_customer = StripeCustomer.objects.create(
                        user=custom_user, stripe_id=stripe_api_cus_id)
                stripe_customer_id = stripe_customer.id
            except CustomUser.DoesNotExist:
                logger.debug("Customer {} does not exist.".format(
                    user.get('email')))
                password = CustomUser.get_random_password()
                base_url = "{0}://{1}".format(self.request.scheme,
                                              self.request.get_host())
                custom_user = CustomUser.register(user.get('name'),
                                                  password,
                                                  user.get('email'),
                                                  app='dcl',
                                                  base_url=base_url,
                                                  send_email=True,
                                                  account_details=password)
                logger.debug("Created user {}.".format(user.get('email')))
                stripe_customer = StripeCustomer.objects. \
                    create(user=custom_user, stripe_id=stripe_api_cus_id)
                stripe_customer_id = stripe_customer.id
                new_user = authenticate(username=custom_user.email,
                                        password=password)
                login(request, new_user)
        else:
            # We assume that if the user is here, his/her StripeCustomer
            # object already exists
            stripe_customer_id = request.user.stripecustomer.id
            custom_user = request.user

        if 'token' in request.session:
            ucd = UserCardDetail.get_or_create_user_card_detail(
                stripe_customer=self.request.user.stripecustomer,
                card_details=card_details_response)
            UserCardDetail.save_default_card_local(
                self.request.user.stripecustomer.stripe_id, ucd.card_id)
        else:
            card_id = request.session.get('card_id')
            user_card_detail = UserCardDetail.objects.get(id=card_id)
            card_details_dict = {
                'last4': user_card_detail.last4,
                'brand': user_card_detail.brand,
                'card_id': user_card_detail.card_id
            }
            if not user_card_detail.preferred:
                UserCardDetail.set_default_card(
                    stripe_api_cus_id=stripe_api_cus_id,
                    stripe_source_id=user_card_detail.card_id)

        # Save billing address
        billing_address_data = request.session.get('billing_address_data')
        logger.debug('billing_address_data is {}'.format(billing_address_data))
        billing_address_data.update({'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_description = gp_details["description"]
            order.generic_product_id = gp_details["product_id"]
            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'],
                'product_name': gp_details['product_name'],
                'product_id': gp_details['product_id'],
                'order_id': order.id
            }

            email_data = {
                'subject': (settings.DCL_TEXT +
                            " Payment received from %s" % context['email']),
                'from_email':
                settings.DCL_SUPPORT_FROM_ADDRESS,
                'to': ['*****@*****.**'],
                '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':
                _("Confirmation of your payment"),
                'from_email':
                settings.DCL_SUPPORT_FROM_ADDRESS,
                'to': [user.get('email')],
                'body':
                _("Hi {name},\n\n"
                  "thank you for your order!\n"
                  "We have just received a payment of CHF {amount:.2f}"
                  " from you.{recurring}\n\n"
                  "Cheers,\nYour Data Center Light team".format(
                      name=user.get('name'),
                      amount=gp_details['amount'],
                      recurring=(_(' This is a monthly recurring plan.')
                                 if gp_details['recurring'] else ''))),
                'reply_to': ['*****@*****.**'],
            }
            send_plain_email_task.delay(email_data)

            response = {
                'status':
                True,
                'redirect':
                (reverse('hosting:orders') 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 '
                      '[email protected] for any question that you may have.'))
            }
            clear_all_session_vars(request)

            return JsonResponse(response)

        user = {
            'name': custom_user.name,
            'email': custom_user.email,
            'pass': custom_user.password,
            'request_scheme': request.scheme,
            'request_host': request.get_host(),
            'language': get_language(),
        }

        create_vm(billing_address_data, stripe_customer_id, specs,
                  stripe_subscription_obj, card_details_dict, request,
                  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)