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]
。
我目前正在从事一个收集付款信息(例如客户想要购买的产品,以及该产品的价格)和客户详细信息(客户名称、客户地址、客户信用卡信息等)的项目.) 而且我需要访问 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]
。