def test_product_detail_view(self):
     new_user = User.objects.create_user('testuser', '*****@*****.**',
                                         'password')
     self.client.login(username='******', password='******')
     product1 = Product.objects.create(name='test1',
                                       description='p1',
                                       price=1)
     product1.save()
     order = Order.objects.create(full_name='John Doe',
                                  phone_number='123456789',
                                  country='Netherlands',
                                  postcode='1234',
                                  town_or_city='Amsterdam',
                                  street_address1='Street',
                                  street_address2='22',
                                  county='North',
                                  date='2020-06-09')
     order_line_item1 = OrderLineItem(user=new_user,
                                      order=order,
                                      product=product1,
                                      quantity=1)
     order_line_item1.save()
     response = self.client.get('/products/1',
                                content_type="html/text",
                                follow=True)
     check_product = Product.objects.get(pk=1)
     self.assertEqual(check_product.view_count, 1)
     self.assertEqual(get_user_purchases(new_user), ['test1'])
Esempio n. 2
0
    def handle_payment_intent_succeeded(self, event):
        """
        Handle payment_intent.succeeded webhook
        """
        intent = event.data.object
        payment_intent_id = intent.id
        basket = intent.metadata.basket
        username = intent.metadata.user

        order_exists = False
        attempt = 1
        while attempt <= 5:
            try:
                order = Order.objects.get(
                    stripe_id=payment_intent_id,
                    original_basket=basket,
                )
                order_exists = True
                break
            except Order.DoesNotExist:
                attempt += 1
                time.sleep(1)
        if order_exists:
            self._send_confirmation_email(order)
            return HttpResponse(
                content=f'Webhook received: {event["type"]} | SUCCESS: \
                              Order already in database',
                status=200)
        else:
            order = None
            try:
                user = get_object_or_404(User, username=username)
                profile = get_object_or_404(UserProfile, user=user)
                order = Order.objects.create(
                    profile=profile,
                    stripe_id=payment_intent_id,
                    original_basket=basket,
                    full_name=(
                        intent.charges.data[0]['billing_details']['name']),
                    email=intent.charges.data[0]['billing_details']['email'],
                )
                for lesson_id, value in json.loads(basket).items():
                    lesson = get_object_or_404(Lesson, lesson_id=lesson_id)
                    order_line_item = OrderLineItem(
                        order=order,
                        lesson=lesson,
                        profile=profile,
                    )
                    order_line_item.save()
            except Exception as e:
                if order:
                    order.delete()
                return HttpResponse(
                    content=f'Webhook received: {event["type"]} | \
                                Error: {e}',
                    status=500)
        self._send_confirmation_email(order)
        return HttpResponse(content=f'Webhook received: {event["type"]} | \
                                  Success: Created order in webhook',
                            status=200)
Esempio n. 3
0
 def test_can_create_a_order_line_item(self):
     orderlineitem = OrderLineItem(order_id=3,
                                   product_id=1,
                                   quantity=2,
                                   size='Large')
     orderlineitem.save()
     self.assertEqual(orderlineitem.order_id, 3)
     self.assertEqual(orderlineitem.product_id, 1)
     self.assertEqual(orderlineitem.quantity, 2)
     self.assertEqual(orderlineitem.size, 'Large')
Esempio n. 4
0
def save_order_items(userid, order, cart):
    for id, quantity in cart.items():
        print(userid)
        print(f"Typeis: {type(userid)}")
        product = get_object_or_404(BaseProduct, pk=id)
        shopper = get_object_or_404(User, pk=userid)
        order_line_item = OrderLineItem(order=order,
                                        product=product,
                                        quantity=quantity,
                                        shopper=shopper)
        order_line_item.save()
Esempio n. 5
0
def checkout(request):
    if request.method == 'POST':
        order_form = OrderForm(request.POST)
        payment_form = MakePaymentForm(request.POST)

        if order_form.is_valid() and payment_form.is_valid():
            order = order_form.save(commit=False)
            order.date = timezone.now()
            order.save()

            cart = request.session.get('cart', {})
            total = 0
            for id, quantity in cart.items():
                product = get_object_or_404(Product, pk=id)
                total += quantity * product.price
                order_line_item = OrderLineItem(order=order,
                                                product=product,
                                                quantity=quantity)
                order_line_item.save()

            try:
                customer = stripe.Charge.create(
                    amount=int(total * 100),  # as it is in pence
                    currency="gbp",
                    description=request.user.email,
                    card=payment_form.cleaned_data['stripe_id'],
                )
            except:
                messages.error(request, "Your card was declined")

            if customer.paid:
                messages.error(request, "You have successfully paid")
                request.session['cart'] = {}
                return redirect(reverse('products'))
            else:
                messages.error(request, "Unable to take payment at this time")
        else:
            print(payment_form.errors)
            messages.error(request,
                           "We are unable to take a payment with that card")
    else:
        payment_form = MakePaymentForm()
        order_form = OrderForm()

    return render(
        request, "checkout.html", {
            'order_form': order_form,
            'payment_form': payment_form,
            'publishable': settings.STRIPE_PUBLISHABLE
        })
    def test_get_all_products_as_logged_in_user(self):
        product1 = Product.objects.create(name='test1',
                                          description='p1',
                                          price=1)
        product2 = Product.objects.create(name='test2',
                                          description='p2',
                                          price=2)
        product3 = Product.objects.create(name='test3',
                                          description='p3',
                                          price=3)
        product4 = Product.objects.create(name='test4',
                                          description='p4',
                                          price=4)
        new_user = User.objects.create_user('testuser', '*****@*****.**',
                                            'password')
        self.client.login(username='******', password='******')
        order = Order.objects.create(full_name='John Doe',
                                     phone_number='123456789',
                                     country='Netherlands',
                                     postcode='1234',
                                     town_or_city='Amsterdam',
                                     street_address1='Street',
                                     street_address2='22',
                                     county='North',
                                     date='2020-06-09')

        order_line_item1 = OrderLineItem(user=new_user,
                                         order=order,
                                         product=product1,
                                         quantity=1)

        order_line_item2 = OrderLineItem(user=new_user,
                                         order=order,
                                         product=product2,
                                         quantity=2)

        order_line_item3 = OrderLineItem(user=new_user,
                                         order=order,
                                         product=product3,
                                         quantity=3)

        response = self.client.get("/products/",
                                   content_type="html/text",
                                   follow=True)
        self.assertEqual(response.status_code, 200)
        self.assertIn(b'test1', response.content)
        self.assertIn(b'test2', response.content)
        self.assertIn(b'test3', response.content)
        self.assertIn(b'test4', response.content)
Esempio n. 7
0
def confirm_pre_order(request, order_number):
    """ view upgrading preorder and creating a corresponding order """
    if not request.user.is_superuser:
        messages.error(request, 'Sorry, only store owners can see that.')
        return redirect(reverse('home'))
    pre_order = get_object_or_404(PreOrder, order_number=order_number)
    pp_transaction_id = request.POST['pp_transaction_id']
    order = Order(user_profile=pre_order.user_profile,
                  full_name=pre_order.full_name,
                  email=pre_order.email,
                  phone_number=pre_order.phone_number,
                  country=pre_order.country,
                  postcode=pre_order.postcode,
                  town_or_city=pre_order.town_or_city,
                  street_address1=pre_order.street_address1,
                  street_address2=pre_order.street_address2,
                  county=pre_order.county,
                  delivery_cost=pre_order.delivery_cost,
                  order_total=pre_order.order_total,
                  grand_total=pre_order.grand_total,
                  pp_transaction_id=pp_transaction_id)
    # save order
    order.save()
    # copy line items from preorder to order
    for li in pre_order.lineitems.all():
        order_line_item = OrderLineItem(
            order=order,
            product=li.product,
            quantity=li.quantity,
        )
        order_line_item.save()
        # update product reserved, sold
        product = li.product
        quantity = li.quantity
        product.sold = product.sold + quantity
        product.reserved = product.reserved - quantity
        product.save()
    # update preorder
    pre_order.upgraded_order = order
    pre_order.status = "UPG"
    pre_order.save()
    # success message
    messages.success(request, (f'Preorder {pre_order.order_number} upgraded.'
                               f'New order {order.order_number} confirmed.'))
    return redirect(reverse('products_management'))
Esempio n. 8
0
class OrderTests(TestCase):
    """
    Testing order line item total calculation
    """
    def test_subtotal_calculation(self):
        self.product = Product(name='test_name',
                               price=11,
                               description='test_description',
                               )
        self.product.save()
        self.order = Order(
            full_name="Test User",
            email="*****@*****.**",
            phone_number="12345",
            country="gb",
            postcode="e114dr",
            town_or_city="london",
            street_address1="40 test road",
            original_bag="",
            stripe_pid="",
        )
        self.order.save()
        self.order_line_item = OrderLineItem(
            order=self.order,
            product=self.product,
            quantity=2,

        )
        self.order_line_item.save()
        '''
        Testing product and order is created
        '''
        self.assertEqual(str(self.product.name), 'test_name')
        self.assertEqual(str(self.order.full_name), 'Test User')
        '''
        Testing order line item
        '''
        self.assertEqual(str(self.order_line_item.lineitem_total), '22')
        '''
        Testing order total
        '''
        self.assertEqual(str(self.order.order_total), '22')
Esempio n. 9
0
 def test_total_contributions(self):
     user = User.objects.create_user(username='******', password='******')
     feature = Feature(title="Test Post", author=user, content="Test Content")
     feature.save()
     order = Order(full_name = "Patrick Doherty",
                 phone_number = "02871774646",
                 country = "Ireland",
                 postcode = "BT829DE",
                 town_or_city = "Strabane",
                 street_address1 = "5 Lasts Lane",
                 street_address2 = "Urney Road",
                 county = "Tyrone",
                 date = timezone.now())
     order.save()
     contribution = OrderLineItem(order=order, feature=feature, user=user, contribution =50)
     contribution.save()
     page = self.client.get("/features/{0}/{1}/".format(feature.id, feature.slug))
     self.assertEqual(page.status_code, 200)
     self.assertTemplateUsed(page, "features/feature_detail.html")
     self.assertEqual(page.context["total_contributions"], 50)
     self.assertContains(page, 'Test Content')
     self.assertEqual(str(order), "{0}-{1}-{2}".format(order.id, order.date, order.full_name))
     self.assertEqual(str(contribution), "{0}-{1}-{2}".format(contribution.contribution, feature.title, user.username))
Esempio n. 10
0
def submit_payment(request):
    
    cart = request.session.get('cart', {})
    cart_items_and_total = get_cart_items_and_total(cart)
    
    payment_form = MakePaymentForm(request.POST)
    order_form = OrderForm(request.POST)
    
    if order_form.is_valid() and payment_form.is_valid():
        
        # save the order to the database
        order = order_form.save()
        cart = request.session.get('cart', {})
        for product_id, quantity in cart.items():
            line_item = OrderLineItem()
            line_item.product_id = product_id
            line_item.quantity = quantity
            line_item.order = order
            line_item.save()
        
        #Grab the money and run!
        total = cart_items_and_total['cart_total']
        stripe_token=payment_form.cleaned_data['stripe_id']

        try:

            total_in_cent = int(total*100)
            customer = stripe.Charge.create(
                amount=total_in_cent,
                currency="EUR",
                description="Dummy Transaction",
                card=stripe_token,
            )

        except stripe.error.CardError:
            print("Declined")
            messages.error(request, "Your card was declined!")

        if customer.paid:
            print("Paid")
            messages.error(request, "You have successfully paid")
        

            
            
    # clear the cart    
    del request.session['cart']
    #redirect to home
    return redirect("/")    
Esempio n. 11
0
def checkout(request):
    stripe_public_key = settings.STRIPE_PUBLIC_KEY
    stripe_secret_key = settings.STRIPE_SECRET_KEY

    if request.method == 'POST':
        cart = request.session.get('cart', {})
        form_data = {
            'full_name': request.POST['full_name'],
            'email': request.POST['email'],
            'phone_number': request.POST['phone_number'],
            'country': request.POST['country'],
            'postcode': request.POST['postcode'],
            'town_or_city': request.POST['town_or_city'],
            'street_address1': request.POST['street_address1'],
            'street_address2': request.POST['street_address2'],
            'county': request.POST['county'],
        }
        order_form = OrderForm(form_data)
        if order_form.is_valid():
            order = order_form.save(commit=False)
            pid = request.POST.get('client_secret').split('_secret')[0]
            order.stripe_pid = pid
            order.original_cart = json.dumps(cart)
            order.save()
            for item_id, quantity in cart.items():
                try:
                    product = Album.objects.get(id=item_id)
                    order_line_item = OrderLineItem(order=order,
                                                    product=product,
                                                    quantity=quantity)
                    order_line_item.save()
                except Album.DoesNotExist:
                    messages.error(
                        request,
                        (f'Album with title {product.title} could'
                         ' not be processed. Please contact us for details.'))
                    order.delete()
                    return redirect(reverse('view_cart'))

            request.session['save_info'] = 'save-info' in request.POST
            return redirect(
                reverse('checkout_success', args=[order.order_number]))

    else:
        cart = request.session.get('cart', {})
        if not cart:
            messages.error(request, 'Your cart is empty')
            return redirect(reverse('products'))

        current_cart = cart_contents(request)
        total = current_cart['grand_total']
        stripe_total = round(total * 100)
        stripe.api_key = stripe_secret_key
        intent = stripe.PaymentIntent.create(
            amount=stripe_total,
            currency=settings.STRIPE_CURRENCY,
        )

        if request.user.is_authenticated:
            try:
                profile = UserProfile.objects.get(user=request.user)
                order_form = OrderForm(
                    initial={
                        'full_name': profile.default_full_name,
                        'email': profile.user.email,
                        'phone_number': profile.default_phone_number,
                        'country': profile.default_country,
                        'postcode': profile.default_postcode,
                        'town_or_city': profile.default_town_or_city,
                        'street_address1': profile.default_street_address1,
                        'street_address2': profile.default_street_address2,
                        'county': profile.default_county,
                    })
            except UserProfile.DoesNotExist:
                order_form = OrderForm()
        else:
            order_form = OrderForm()

    template = 'checkout/checkout.html'
    context = {
        'order_form': order_form,
        'stripe_public_key': stripe_public_key,
        'client_secret': intent.client_secret
    }

    return render(request, template, context)
Esempio n. 12
0
    def handle_payment_intent_succeeded(self, event):
        """
        Handle the payment_intent.succeeded webhook from Stripe
        """
        intent = event.data.object
        pid = intent.id
        customer = intent.get('customer')

        # Bypass if subscription purchase
        if customer:
            return HttpResponse(
                    content=f'Webhook received: {event["type"]} | SUCCESS: \
                        Stripe Subscription Customer',
                    status=200)

        else:
            basket = intent.metadata.basket
            save_info = intent.metadata.save_info
            billing_details = intent.charges.data[0].billing_details
            shipping_details = intent.shipping
            grand_total = round(intent.charges.data[0].amount / 100, 2)

            # Set empty strings to null
            for field, value in shipping_details.address.items():
                if value == "":
                    shipping_details.address[field] = None

            # Update profile information if save_info was checked
            profile = None
            username = intent.metadata.username
            if username != 'AnonymousUser':
                profile = UserProfile.objects.get(user__username=username)
                if save_info:
                    profile.default_phone_number = shipping_details.phone
                    profile.default_street_address1 = shipping_details.address.line1
                    profile.default_street_address2 = shipping_details.address.line2
                    profile.default_town_or_city = shipping_details.address.city
                    profile.default_county = shipping_details.address.state
                    profile.default_country = shipping_details.address.country
                    profile.default_postcode = shipping_details.address.postal_code
                    profile.save()

            order_exists = False
            attempt = 1
            while attempt <= 5:
                try:
                    order = Order.objects.get(
                        full_name__iexact=shipping_details.name,
                        email__iexact=billing_details.email,
                        phone_number__iexact=shipping_details.phone,
                        street_address1__iexact=shipping_details.address.line1,
                        street_address2__iexact=shipping_details.address.line2,
                        town_or_city__iexact=shipping_details.address.city,
                        county__iexact=shipping_details.address.state,
                        country__iexact=shipping_details.address.country,
                        postcode__iexact=shipping_details.address.postal_code,
                        grand_total=grand_total,
                        original_basket=basket,
                        stripe_pid=pid,
                    )
                    order_exists = True
                    break
                except Order.DoesNotExist:
                    attempt += 1
                    time.sleep(1)
            if order_exists:
                self._send_confirmation_email(order)
                return HttpResponse(
                    content=f'Webhook received: {event["type"]} | SUCCESS: \
                        Verified order already in database',
                    status=200)
            else:
                order = None
                try:
                    order = Order.objects.create(
                        full_name=shipping_details.name,
                        user_profile=profile,
                        email=billing_details.email,
                        phone_number=shipping_details.phone,
                        street_address1=shipping_details.address.line1,
                        street_address2=shipping_details.address.line2,
                        town_or_city=shipping_details.address.city,
                        county=shipping_details.address.state,
                        country=shipping_details.address.country,
                        postcode=shipping_details.address.postal_code,
                        original_basket=basket,
                        stripe_pid=pid,
                    )

                    for item_id, item_data in json.loads(basket).items():
                        product = get_object_or_404(Product, id=item_id)

                        order_line_item = OrderLineItem(
                                order=order,
                                product=product,
                                quantity=item_data,
                            )
                        order_line_item.save()

                        if not product.inventory_updated:
                            product.remove_items_from_inventory(
                                count=item_data, save=True)

                except Exception as e:
                    if order:
                        order.delete()
                    return HttpResponse(
                        content=f'Webhook received: {event["type"]} \
                            | ERROR: {e}',
                        status=500)

                self._send_confirmation_email(order)
                return HttpResponse(
                    content=f'Webhook received: {event["type"]} | SUCCESS: \
                        Created order in webhook',
                    status=200)
Esempio n. 13
0
def checkout(request):
    """ A view to render checkout page """

    public_key = settings.STRIPE_PUBLIC_KEY
    secret_key = settings.STRIPE_SECRET_KEY
    if request.method == 'POST':
        bag = request.session.get('bag', {})

        form_data = {
            'full_name': request.POST['full_name'],
            'email': request.POST['email'],
            'phone_number': request.POST['phone_number'],
            'country': request.POST['country'],
            'postcode': request.POST['postcode'],
            'town_or_city': request.POST['town_or_city'],
            'street_address1': request.POST['street_address1'],
            'street_address2': request.POST['street_address2'],
            'county': request.POST['county'],
        }

        order_form = OrderForm(form_data)
        if order_form.is_valid():
            order = order_form.save(commit=False)
            pid = request.POST.get('client_secret').split('_secret')[0]
            order.stripe_pid = pid
            order.original_bag = json.dumps(bag)
            order.save()
            for workshop_id, quantity in bag.items():
                try:
                    workshop = Workshop.objects.get(id=workshop_id)
                    if isinstance(quantity, int):
                        order_line_item = OrderLineItem(
                            order=order,
                            workshop=workshop,
                            quantity=quantity,
                        )
                        order_line_item.save()
                except Workshop.DoesNotExist:
                    messages.error(request, (
                        "One of the products in your bag wasn't"
                        "found in our database."
                        "Please message us for assistance!")
                    )
                    order.delete()
                    return redirect(reverse('booking'))

            request.session['save_info'] = 'save-info' in request.POST
            return redirect(reverse('checkout_success',
                                    args=[order.order_number]))
        else:
            messages.error(request, "There was an error with your form. \
                Check your information, please.")
    else:
        bag = request.session.get('bag', {})
        if not bag:
            messages.info(request, "Your booking is empty")
            return redirect(reverse('workshops'))

        current_bag = booking_contents(request)
        total = current_bag['grand_total']
        stripe_total = round(total * 100)
        stripe.api_key = secret_key
        intent = stripe.PaymentIntent.create(
            amount=stripe_total,
            currency=settings.STRIPE_CURRENCY,
        )

        if request.user.is_authenticated:
            try:
                profile = UserProfile.objects.get(user=request.user)
                order_form = OrderForm(initial={
                    'full_name': profile.full_name,
                    'email': profile.email_address,
                    'phone_number': profile.phone_number,
                    'street_address1': profile.street_address1,
                    'street_address2': profile.street_address2,
                    'postcode': profile.postcode,
                    'town_or_city': profile.town_or_city,
                    'county': profile.county,
                    'country': profile.country,
                })
            except UserProfile.DoesNotExist:
                order_form = OrderForm()
        else:
            order_form = OrderForm()

    if not public_key:
        messages.warning(request, 'Stripe public key is missing. \
                Check your environment, maybe it is there sleeping.')

    template = 'checkout/checkout.html'

    context = {
        'order_form': order_form,
        'stripe_public_key': public_key,
        'client_secret': intent.client_secret,
    }

    return render(request, template, context)
Esempio n. 14
0
    def handle_payment_intent_succeeded(self, event):
        """
        Handle the payment_intent.succeeded webhook from Stripe
        """
        intent = event.data.object
        pid = intent.id
        bag = intent.metadata.bag

        billing_details = intent.charges.data[0].billing_details
        grand_total = round(intent.charges.data[0].amount / 100, 2)

        order_exists = False
        attempt = 1
        while attempt <= 5:
            try:
                order = Order.objects.get(
                    full_name__iexact=billing_details.name,
                    email__iexact=billing_details.email,
                    phone_number__iexact=billing_details.phone,
                    street_address1__iexact=(
                        billing_details.address.line1),
                    street_address2__iexact=(
                        billing_details.address.line2),
                    town_or_city__iexact=billing_details.address.city,
                    county__iexact=billing_details.address.state,
                    country__iexact=billing_details.address.country,
                    grand_total=grand_total,
                    original_bag=bag,
                    stripe_pid=pid,
                )
                order_exists = True
                break
            except Order.DoesNotExist:
                attempt += 1
                time.sleep(1)

        if order_exists:
            return HttpResponse(
                content=f'Webhook received: ({event["type"]}'
                '| SUCCESS: Verified order already in database',
                status=200)
        else:
            order = None
            try:
                order = Order.objects.create(
                    full_name=billing_details.name,
                    email=billing_details.email,
                    phone_number=billing_details.phone,
                    street_address1=billing_details.address.line1,
                    street_address2=billing_details.address.line2,
                    town_or_city=billing_details.address.city,
                    county=billing_details.state,
                    country=billing_details.country,
                    original_bag=bag,
                    stripe_pid=pid,
                )
                for workshop_id, quantity in json.loads(bag).items():
                    workshop = Workshop.objects.get(id=workshop_id)
                    if isinstance(quantity, int):
                        order_line_item = OrderLineItem(
                            order=order,
                            workshop=workshop,
                            quantity=quantity,
                        )
                        order_line_item.save()
            except Exception as e:
                if order:
                    order.delete()
                return HttpResponse(
                    content=f'Webhook received: {event["type"]} | ERROR: {e}',
                    status=500)
        return HttpResponse(
            content=f'Webhook received: {event["type"]}'
            '| SUCCESS: Created order in webhook',
            status=200)
 def test_get_user_purchases(self):
     new_user = User.objects.create_user('testuser', '*****@*****.**',
                                         'password')
     self.client.login(username='******', password='******')
     product1 = Product.objects.create(name='test1',
                                       description='p1',
                                       price=1)
     product2 = Product.objects.create(name='test2',
                                       description='p2',
                                       price=2)
     product3 = Product.objects.create(name='test3',
                                       description='p3',
                                       price=3)
     product1.save()
     product2.save()
     product3.save()
     order = Order.objects.create(full_name='John Doe',
                                  phone_number='123456789',
                                  country='Netherlands',
                                  postcode='1234',
                                  town_or_city='Amsterdam',
                                  street_address1='Street',
                                  street_address2='22',
                                  county='North',
                                  date='2020-06-09')
     order_line_item1 = OrderLineItem(user=new_user,
                                      order=order,
                                      product=product1,
                                      quantity=1)
     order_line_item1.save()
     order_line_item2 = OrderLineItem(user=new_user,
                                      order=order,
                                      product=product2,
                                      quantity=2)
     order_line_item2.save()
     order_line_item3 = OrderLineItem(user=new_user,
                                      order=order,
                                      product=product3,
                                      quantity=3)
     order_line_item3.save()
     self.assertEqual(get_user_purchases(new_user),
                      ['test1', 'test2', 'test3'])
Esempio n. 16
0
 def test_place_order_products(self):
     order_line_item = OrderLineItem()
     self.assertFalse(order_line_item.quantity)
Esempio n. 17
0
def checkout(request):
    """Renders checkout page with form for user to purchase prodcuts using Stripe API"""
    cart = request.session.get('cart', {})
    total = 0
    for id, quantity in cart.items():
        product = get_object_or_404(Product, pk=id)
        total += quantity * product.price
    delivery = 0
    if total > 30:
        delivery = 0
    else:
        delivery = 3.95
    new_total = round(float(total) + delivery, 2)

    if request.method == "POST":
        order_form = OrderForm(request.POST)
        payment_form = MakePaymentForm(request.POST)

        if order_form.is_valid() and payment_form.is_valid():
            order = order_form.save(commit=False)
            order.purchased_by = request.user
            order.date = timezone.now()
            order.save()

            cart = request.session.get('cart', {})
            total = 0
            for id, quantity in cart.items():
                product = get_object_or_404(Product, pk=id)
                total += quantity * product.price
                order_line_item = OrderLineItem(order=order,
                                                product=product,
                                                quantity=quantity)
                order_line_item.save()
            try:
                customer = stripe.Charge.create(
                    amount=int(new_total * 100),
                    currency="GBP",
                    description=request.user.email,
                    card=payment_form.cleaned_data['stripe_id'],
                )
            except stripe.error.CardError:
                messages.error(request, "Your card was declined!")

            if customer.paid:
                messages.error(request, "You have successfully paid!")
                request.session['cart'] = {}
                return redirect(reverse('confirmation', args=(order.id, )))
            else:
                messages.error(request, "Unable to take payment")
        else:
            print(payment_form.errors)
            messages.error(request,
                           "We were unable to take a payment with that card!")
    else:
        payment_form = MakePaymentForm()
        order_form = OrderForm()

    return render(
        request, "checkout.html", {
            "order_form": order_form,
            "payment_form": payment_form,
            "delivery": delivery,
            "new_total": new_total,
            "publishable": settings.STRIPE_PUBLISHABLE
        })
    def handle_payment_intent_succeeded(self, event):
        # Get order data from payment intent
        intent = event.data.object
        payment_intent_id = intent.id
        bag = json.loads(intent.metadata.bag
                         ) if intent.metadata and intent.metadata.bag else None
        billing_details = intent.charges.data[
            0].billing_details if intent.charges.data[
                0].billing_details else None
        shipping_details = intent.shipping if intent.shipping else None
        grand_total = round(intent.charges.data[0].amount / 100, 2)

        # If no bag in metadata
        if not bag:
            return HttpResponse(
                content='No bag or items associated with this order | {}'.
                format(intent),
                status=400)

        # If no billing details
        if not billing_details:
            return HttpResponse(
                content='No billing details associated with this order | {}'.
                format(intent),
                status=400)

        # If no shipping details
        if not shipping_details:
            return HttpResponse(
                content='No shipping details associated with this order | {}'.
                format(intent),
                status=400)

        # Replace empty strings with Null for db compatibility
        for field, value in shipping_details.address.items():
            if value == '':
                shipping_details.address[field] = None

        order_exists = False
        attempt = 1

        # Attempt to find order in database 5 times
        while attempt <= 5:
            # Check if order already exists in database
            try:
                order = get_object_or_404(
                    Order,
                    stripe_payment_id=payment_intent_id,
                )
                order_exists = True
                break
            # Increase attempt, sleep 1 second
            except Order.DoesNotExist:
                attempt += 1
                time.sleep(1)

        if order_exists:
            # Send confirmation email
            self._send_confirmation_email(order)
            return HttpResponse(
                content=
                'Webhook received: {} | SUCCESS: Verified order already in database'
                .format(event.type),
                status=200,
            )
        else:
            order = None
            try:
                # Create order
                order = Order.objects.create(
                    Order,
                    full_name=shipping_details.name,
                    address_1=shipping_details.line1,
                    address_2=shipping_details.line2,
                    city=shipping_details.city,
                    postcode=shipping_details.postcode,
                    email=billing_details.email,
                    phone_number=billing_details.phone_number,
                    grand_total=grand_total,
                    original_bag=bag,
                    stripe_payment_id=payment_intent_id,
                )
                # Create line items (taken from contexts.py)
                if bag:
                    forloop_count = 0
                    for restaurant, food_items in bag.items():
                        list_of_food_keys_in_bag = list(food_items.keys())
                        food_id = list_of_food_keys_in_bag[forloop_count]
                        food_object = get_object_or_404(FoodItem, pk=food_id)
                        quantity = bag[restaurant][food_id]['quantity']
                        for food in bag[restaurant]:
                            order_line_item = OrderLineItem(
                                order=order,
                                food_item=food_object,
                                quantity=bag[restaurant][food_id]['quantity'],
                            )
                            order_line_item.save()
                            forloop_count += 1
                else:
                    return HttpResponse(content='Bag does not exist',
                                        status=400)
            except Exception as e:
                if order:
                    order.delete()
                return HttpResponse(
                    content='Webhook received: {} | ERROR: {}'.format(
                        event.type, e),
                    status=500)

        # Send confirmation email
        self._send_confirmation_email(order)
        return HttpResponse(
            content=
            'Webhook received: {} | SUCCESS: Created order via Webhook handler'
            .format(event.type),
            status=200,
        )
    def handle_payment_intent_succeeded(self, event):
        """
        Handle the "payment_intent.succeeded" webhook from Stripe
        """

        # Get the payment intent and metadata
        intent = event.data.object
        pid = intent.id
        bag = intent.metadata.bag
        save_info = intent.metadata.save_info

        billing_details = intent.charges.data[0].billing_details
        shipping_details = intent.shipping
        grand_total = round(intent.charges.data[0].amount / 100, 2)

        # Clean/strip form data and set empty values to None
        for field, value in shipping_details.address.items():
            if value == "":
                shipping_details.address[field] = None

        # Update profile information if save_info was checked
        profile = None
        username = intent.metadata.username
        if username != "AnonymousUser":
            profile = UserProfile.objects.get(user__username=username)
            if save_info:
                profile.default_phone_number = shipping_details.phone
                profile.default_country = shipping_details.address.country
                profile.default_postcode = shipping_details.address.postal_code
                profile.default_town_or_city = shipping_details.address.city
                profile.default_street_address1 = shipping_details.address.line1
                profile.default_street_address2 = shipping_details.address.line2
                profile.default_county = shipping_details.address.state
                profile.save()

        # Try to get the order in the database using the form data
        attempt = 1
        order_exists = False
        while attempt <= 5:
            try:
                order = Order.objects.get(
                    full_name__iexact=shipping_details.name,
                    email__iexact=billing_details.email,
                    phone_number__iexact=shipping_details.phone,
                    country__iexact=shipping_details.address.country,
                    postcode__iexact=shipping_details.address.postal_code,
                    town_or_city__iexact=shipping_details.address.city,
                    street_address1__iexact=shipping_details.address.line1,
                    street_address2__iexact=shipping_details.address.line2,
                    county__iexact=shipping_details.address.state,
                    grand_total=grand_total,
                    original_bag=bag,
                    stripe_pid=pid,
                )
                order_exists = True  # Nothing else to do if order is already created
                break
            except Order.DoesNotExist:
                attempt += 1
                time.sleep(1)  # Sleep for a second and then try again
        if order_exists:
            # Send a confirmation email
            self._send_confirmation_email(order)
            return HttpResponse(
                content=f'Webhook received: {event["type"]} | SUCCESS: Verified order already in database',
                status=200)
        else:
            order = None
            # If somehow the form didn't create the order, try to create it here
            try:
                order = Order.objects.create(
                    full_name=shipping_details.name,
                    user_profile=profile,
                    email=billing_details.email,
                    phone_number=shipping_details.phone,
                    country=shipping_details.address.country,
                    postcode=shipping_details.address.postal_code,
                    town_or_city=shipping_details.address.city,
                    street_address1=shipping_details.address.line1,
                    street_address2=shipping_details.address.line2,
                    county=shipping_details.address.state,
                    original_bag=bag,
                    stripe_pid=pid,
                )
                for item_id, item_data in json.loads(bag).items():
                    product = Product.objects.get(id=item_id)
                    # If we're working w/ an item with no sizes, item_data will be the quantity
                    if isinstance(item_data, int):
                        order_line_item = OrderLineItem(
                            order=order,
                            product=product,
                            quantity=item_data
                        )
                        order_line_item.save()
                    # Otherwise we need to add order lineitems for each size
                    else:
                        for size, quantity in item_data['items_by_size'].items():
                            order_line_item = OrderLineItem(
                                order=order,
                                product=product,
                                quantity=quantity,
                                product_size=size
                            )
                            order_line_item.save()
            except Exception as e:
                if order:
                    order.delete()  # Delete it if anything went wrong. Stripe will try again later.
                return HttpResponse(
                    content=f'Webhook received: {event["type"]} | ERROR: {e}',
                    status=500)
        # Send a confirmation email
        self._send_confirmation_email(order)
        return HttpResponse(
                content=f'Webhook received: {event["type"]} | SUCCESS: Created order in webhook',
                status=200)