我正在尝试使用 stripe 在 nextjs 中创建一个支付页面。如果我 guendo 指南它工作正常,但我不想使用表单来调用
/create-checkout-session
端点,但我想在 div 上使用 onClick 函数来使用 axios 进行调用。
'use client';
import React, {useEffect, useState} from 'react';
import Container from "@/components/Container";
import axios from "axios";
const PagamentiPage = () => {
const data = {
product_id: 1,
price: 599,
name: "Test",
description: "lorem ipsum dolor sit amet consectetur adipisicing elit.",
}
return (
<Container>
<div className="product">
<img
src="https://i.imgur.com/EHyR2nP.png"
alt="The cover of Stubborn Attachments"
/>
<div className="description">
<h3>{data.name}</h3>
<h5>Price: {data.price/100} €</h5>
</div>
</div>
<form
action="http://127.0.0.1:8000/pagamenti/create-checkout-session"
method="POST"
>
<input type="hidden" name="product_id" value={1}/>
<input type="hidden" name="price" value={70000}/>
<input type="hidden" name="name" value={"Test"}/>
<input type="hidden" name="description" value={"Frf"}/>
<input
type="hidden"
name="username"
value={"Federiko98"}
/>
<button type={"submit"} className={"bg-red-300 p-2 rounded"}>
Checkout
</button>
</form>
</Container>
);
};
export default PagamentiPage;
class StripeCheckoutView(APIView):
def post(self, request, *args, **kwargs):
data = request.data
try:
checkout_session = stripe.checkout.Session.create(
line_items=[{
'price_data': {
'currency': 'eur',
'unit_amount': data.get("price"), # centesimi
'product_data': {
'name': data.get("name"),
'description': data.get("description"),
},
},
'quantity': 1,
}],
metadata={
'username': data.get("username"),
'product_id': data.get("product_id"),
},
mode='payment',
success_url=f'{YOUR_DOMAIN}?success=true',
cancel_url=f'{YOUR_DOMAIN}?canceled=true',
)
return redirect(checkout_session.url)
except Exception as e:
return Response(
{'error': f"Errore {e}"},
status=status.HTTP_500_INTERNAL_SERVER_ERROR
)
在这种情况下它有效,因为我正在使用表单向后端发出请求。
如果我尝试创建一个像这样的 onClick 函数。
const PagamentiPage = () => {
const data = {
product_id: 1,
price: 599,
name: "Test",
description: "lorem ipsum dolor sit amet consectetur adipisicing elit.",
}
const handleClick = async () => {
axios.post(`http://127.0.0.1:8000/pagamenti/create-checkout-session`, data).then((res) => {
console.log(res);
}).catch((err) => {
console.log(err);
})
}
return (
<Container>
<div className="product">
<img
src="https://i.imgur.com/EHyR2nP.png"
alt="The cover of Stubborn Attachments"
/>
<div className="description">
<h3>{data.name}</h3>
<h5>Price: {data.price / 100} €</h5>
</div>
</div>
<div onClick={handleClick}>
Checkout
</div>
</Container>
);
};
export default PagamentiPage;
我收到以下错误返回:
Blocked multi-origin request (cross-origin): the origin matching policy does not allow reading the remote resource from https://checkout.stripe.com/c/pay/cs_test_a1eRHeGL4xxJiduP9byAbmJkNpWxVSDnpJhpugqmVUsKvT0vDw74my6Mib6#fidkdWxOYHwnPyd1blpxYHZxWjA0SGc3MWBNPXNtdUZAclNDTXRJd2NcbEM2bmZVSVxJNE1idWZXcl9GbTFvRG0xQjBLbE9xQmN9f0BsT2dBTFF%2FTFE1SDZnT1x9Z1IyaGx2f2xzQ29%2FQTdfNTU0a2JBXGJsRCcpJ2N3amhWYHdzYHcnP3F3cGApJ2lkfGpwcVF8dWAnPyd2bGtiaWBabHFgaCcpJ2BrZGdpYFVpZGZgbWppYWB3dic%2FcXdwYHgl.
但是我的 django cors 配置允许访问所有内容,因为我正在使用:
CORS_ALLOW_ALL_ORIGINS = True
我想找到一种通过 onClick 函数进行此调用的方法,因为我需要通过表单请求不支持的标头在请求中发送身份验证令牌。
我还想在请求中发送自定义正文
看起来您正在使用 Django REST Framework (DRF) 作为后端。当您使用 DRF UI 时,
redirect(checkout_session.url)
方法有效,因为它的行为类似于服务器渲染的 Django 页面,具有服务器端重定向(返回 HTTP 状态 302 并告诉您的浏览器要去哪里)。但实际的 REST API 并不是这样工作的,它只是返回数据,并由您的 Next.js 代码决定如何处理该数据。
我使用 DRF 作为后端,使用 Nuxt.js 作为前端。创建结帐会话时,我从结帐会话返回 URL,然后在 JavScript 代码中执行重定向,如下所示:
后端
# apis.py
class CheckoutView(APIView):
...
try:
session = stripe.checkout.Session.create(**checkout_kwargs)
return Response(data={'url': session.url}, status=200)
except Exception as ex:
return Response(data={'error': str(ex)}, status=400)
前端
const {url, error} = await this.$axios.$post('/checkout_sessions/', payload)
if (error) {
console.error(error)
this.processing = false
} else {
window.location.replace(url)
}
这应该允许您执行重定向而不会遇到 CORS 错误。