Home > Software engineering >  Vue.js-Failed to load resource: the server responded with a status of 401 (Unauthorized)
Vue.js-Failed to load resource: the server responded with a status of 401 (Unauthorized)

Time:05-27

I'm currently working on a project that collects payment info(like the products the client wants to buy, and how much that product costs) and client details(client name, client address, client credit card info, etc.) and I need to access Stripe's online payment system for the purchase. However, during my trial run, every time I try to click all "Pay", I keep getting notifications that something went wrong. I checked the terminal and it keeps displaying this error:

Failed to load resource: the server responded with a status of 401 (Unauthorized)

I'm also using Django's rest framework for my backend development, and it keeps displaying this

 HTTP 401 Unauthorized
    Allow: POST, OPTIONS
    Content-Type: application/json
    Vary: Accept
    WWW-Authenticate: Token
    
    {
        "detail": "Authentication credentials were not provided."
    }

This is the code I think the problem is located in:

<template>
  <div >
    <div >
      <div >
        <h1 >Checkout</h1>
      </div>

      <div >
        <table >
          <thead>
            <tr>
              <th>Product</th>
              <th>Price</th>
              <th>Quantity</th>
              <th>Total</th>
            </tr>
          </thead>

          <tbody>
            <tr v-for="item in cart.items" v-bind:key="item.product.id">
              <td>{{ item.product.name }}</td>
              <td>{{ item.product.price }}</td>
              <td>{{ item.quantity }}</td>
              <td>₱{{ getItemTotal(item).toFixed(2) }}</td>
            </tr>
          </tbody>

          <tfoot>
            <tr>
              <td colspan="2">Total</td>
              <td>{{ cartTotalLength }}</td>
              <td>₱{{ cartTotalPrice.toFixed(2) }}</td>
            </tr>
          </tfoot>
        </table>
      </div>

      <div >
        <h2 >Shipping Details</h2>

        <p >* All fields required</p>

        <div >
          <div >
            <div >
              <label>First Name*</label>
              <div >
                <input type="text"  v-model="first_name">
              </div>
            </div>

            <div >
              <label>Last Name*</label>
              <div >
                <input type="text"  v-model="last_name">
              </div>
            </div>

            <div >
              <label>E-mail*</label>
              <div >
                <input type="email"  v-model="email">
              </div>
            </div>

            <div >
              <label>Phone*</label>
              <div >
                <input type="text"  v-model="phone">
              </div>
            </div>
          </div>

          <div >
            <div >
              <label>Address*</label>
              <div >
                <input type="text"  v-model="address">
              </div>
            </div>

            <div >
              <label>Zipcode*</label>
              <div >
                <input type="text"  v-model="zipcode">
              </div>
            </div>

            <div >
              <label>Place*</label>
              <div >
                <input type="email"  v-model="place">
              </div>
            </div>
          </div>
        </div>

        <div  v-if="errors.length">
          <p v-for="error in errors" v-bind:key="error">{{ error }}</p>
        </div>

        <hr>

        <div id="card-element" ></div>

        <template v-if="cartTotalLength">
          <hr>

          <button  @click="submitForm">Pay with Stripe</button>
        </template>
      </div>
    </div>
  </div>
</template>

<script>
import axios from 'axios'

export default {
  name: "Checkout",
  data() {
    return {
      cart: {
        items: []
      },
      stripe: {},
      card: {},
      first_name: '',
      last_name: '',
      email: '',
      phone: '',
      address: '',
      zipcode: '',
      place: '',
      errors: []
    }
  },
  mounted() {
    document.title = ' The "GO BUY IT" page | Bjackets '

    this.cart = this.$store.state.cart

    if (this.cartTotalLength > 0) {
      this.stripe = Stripe('pk_test_51L3bhzFMIo7cZ677WbW384hMgVFcLs9E0x4sLocwajtGbnZIlplXoWSlSKr1IM89tWOCFYIBOWPpcF8OzBWGCnZR00MN1fPAGW')
      const elements = this.stripe.elements();
      this.card = elements.create('card', { hidePostalCode: true })

      this.card.mount('#card-element')
    }
  },
  methods: {
    getItemTotal(item) {
      return item.quantity * item.product.price
    },
    submitForm() {
      this.errors = []

      if (this.first_name === '') {
        this.errors.push('The First Name feild is empty. Please fill-out the space with your first name. For example, "Gaylord"')
      }

      if (this.last_name === '') {
        this.errors.push('The Last Name feild is empty. Please fill-out the space with your last name. For example, "Gaylord"')
      }

      if (this.email === '') {
        this.errors.push('The email feild is missing. Please fill-out the space with your email. For example, "[email protected]"')
      }

      if (this.phone === '') {
        this.errors.push('The phone feild is missing. Please fill-out the space with your contact number. For example, "123-456-7890"')
      }

      if (this.address === '') {
        this.errors.push('The address feild is missing. Please fill-out the space with your address. In other words, tell me where you live.')
      }

      if (this.zipcode === '') {
        this.errors.push('The zipcode feild is missing.')
      }

      if (this.place === '') {
        this.errors.push('Are you located in Lozun, Visayas, Mindanao?')
      }

      if (!this.errors.length) {
        this.$store.commit('setIsLoading', true)

        this.stripe.createToken(this.card).then(result => {
          if (result.error) {
            this.$store.commit('setIsLoading', false)

            this.errors.push('Something went wrong with Stripe. Please try again')

            console.log(result.error.message)
          } else {
            this.stripeTokenHandler(result.token)
          }
        })
      }
    },
    async stripeTokenHandler(token) {
      const items = []

      for (let i = 0; i < this.cart.items.length; i  ) {
        const item = this.cart.items[i]
        const obj = {
          product: item.product.id,
          quantity: item.quantity,
          price: item.product.price * item.quantity
        }

        items.push(obj)
      }

      const data = {
        'first_name': this.first_name,
        'last_name': this.last_name,
        'email': this.email,
        'address': this.address,
        'zipcode': this.zipcode,
        'place': this.place,
        'phone': this.phone,
        'items': items,
        'stripe_token': token.id
      }

      await axios
        .post('/api/v1/checkout/', data)
        .then(response => {
          this.$store.commit('clearCart')
          this.$router.push('/cart/success')
        })
        .catch(error => {
          this.errors.push('Something went wrong. Please try again')
          console.log(error)
        })
      this.$store.commit('setIsLoading', false)
    }
  },
  computed: {
    cartTotalPrice() {
      return this.cart.items.reduce((acc, curVal) => {
        return acc  = curVal.product.price * curVal.quantity
      }, 0)
    },
    cartTotalLength() {
      return this.cart.items.reduce((acc, curVal) => {
        return acc  = curVal.quantity
      }, 0)
    },
  }
}
</script>

This is the mani module that connects the orders from the client to the server(views.py),

import stripe

from django.conf import settings
from django.contrib.auth.models import User
from django.http import Http404
from django.shortcuts import render

from rest_framework import status, authentication, permissions
from rest_framework.decorators import api_view, authentication_classes, permission_classes
from rest_framework.views import APIView
from rest_framework.response import Response

from .models import Order, OrderItem
from .serializers import OrderSerializer

@api_view(['POST'])
@authentication_classes([authentication.TokenAuthentication])
@permission_classes([permissions.IsAuthenticated])

def checkout(request):
  serializer = OrderSerializer(data=request.POST)

  if serializer.is_valid():
    stripe.api_key = settings.STRIPE_SECRET_KEY
    paid_amount = sum(item.get('quantity') * item.get('product').price for item in serializer.validated_data['items'])

    try:
      charge = stripe.Charge.create(
        amount=int(paid_amount * 100),
        currency='USD',
        description='Charge from Bjackets',
        source=serializer.validated_data['stripe_token']
      )

      serializer.save(user=request.user, paid_amount=paid_amount)

      return Response(serializer.data, status=status.HTTP_201_CREATED)
    except Exception:
      return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

  return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)  

CodePudding user response:

I think you set the API permission as IsAuthenticated, but you didn't set the authentication header in the frontend.

Please add the authentication header or set the permission_classes as [permissions.AllowAny] in the api view.

  • Related