Vue.js-加载资源失败:服务器响应状态为 401(未授权)

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

我目前正在从事一个收集付款信息(例如客户想要购买的产品,以及该产品的价格)和客户详细信息(客户名称、客户地址、客户信用卡信息等)的项目.) 而且我需要访问 Stripe 的在线支付系统才能进行购买。然而,在我试用 运行 期间,每次我尝试点击所有“支付”时,我都会不断收到出错的通知。我检查了终端,它一直显示此错误:

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

我后端开发也是用的Django的rest framework,一直显示这个

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

这是我认为问题所在的代码:

<template>
  <div class="page-checkout">
    <div class="columns is-multiline">
      <div class="column is-12">
        <h1 class="title">Checkout</h1>
      </div>

      <div class="column is-12 box">
        <table class="table is-fullwidth">
          <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 class="column is-12 box">
        <h2 class="subtitle">Shipping Details</h2>

        <p class="has-text-grey mb-4">* All fields required</p>

        <div class="columns is-multiline">
          <div class="column is-6">
            <div class="field">
              <label>First Name*</label>
              <div class="control">
                <input type="text" class="input" v-model="first_name">
              </div>
            </div>

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

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

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

          <div class="column is-6">
            <div class="field">
              <label>Address*</label>
              <div class="control">
                <input type="text" class="input" v-model="address">
              </div>
            </div>

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

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

        <div class="notification is-danger mt-4" v-if="errors.length">
          <p v-for="error in errors" v-bind:key="error">{{ error }}</p>
        </div>

        <hr>

        <div id="card-element" class="mb-5"></div>

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

          <button class="button is-dark" @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, "ThisExample@gmail.com"')
      }

      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>

这是将订单从客户端连接到服务器的mani模块(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)  

我认为您将 API 权限设置为 IsAuthenticated,但您没有在前端设置身份验证 header。

请添加身份验证 header 或在 api 视图中将 permission_classes 设置为 [permissions.AllowAny]