Django集成Stripe支付按钮点击无响应问题求助
Stripe购买按钮无响应问题排查与修复
问题背景
在127.0.0.1:8000/item/1/页面点击Buy按钮后无响应,无法触发Stripe结账跳转。F12调试确认按钮关联路径为/buy/1/,相关代码如下:
Views代码
class ProductLandingPageView(DetailView): model = Item template_name = 'items/items.html' context_object_name = 'item' class CreateCheckoutSessionView(View): def get(self, request, pk): item_id = self.kwargs["pk"] item = Item.objects.get(id=item_id) checkout_session = stripe.checkout.Session.create( success_url="https://morungexpress.com/uploads/2022/01/36931750_1642339369_cc2dfdf7494bfa9436aac0d4a882a653.jpg", cancel_url="https://englishlib.org/dictionary/img/wlibrary/c/5ffdb27d24e086.50388072.jpg", mode="payment", line_items=[ { 'price_data': { 'currency': 'usd', 'unit_amount': item.price, 'product_data': { 'name': item.name }, }, "quantity": 1, } ] ) return JsonResponse({ 'id': checkout_session.id })
URLs代码
from django.urls import path from .views import * urlpatterns = [ path('item/<int:pk>/', ProductLandingPageView.as_view(), name='item'), path('buy/<int:pk>/', CreateCheckoutSessionView.as_view(), name='buy') ]
HTML代码
<html> <head> <title>Buy {{ item.name }}</title> </head> <body> <h1>{{ item.name }}</h1> <p>{{ item.description }}</p> <p>{{ item.price }}</p> <button id="buy-button">Buy</button> <script type="text/javascript"> var stripe = Stripe('pk_test_a9nwZVa5O7b0xz3lxl318KSU00x1L9ZWsF'); var buyButton = document.getElementById(buy-button); buyButton.addEventListener('click', function() { fetch("{% url 'buy' item.id %}", { method: 'GET'}) .then(response => return response.json()) .then(session => stripe.redirectToCheckout({ sessionId: session.id })) }); </script> </body> </html>
核心问题与修复方案
1. JavaScript语法错误(直接导致按钮无响应)
- 元素获取错误:
document.getElementById(buy-button)缺少引号,正确写法为document.getElementById('buy-button'),否则JS会把buy-button当作变量而非字符串ID。 - 箭头函数语法错误:
then(response => return response.json())中,单行箭头函数不需要显式写return,正确写法为then(response => response.json()),或用花括号包裹并加return:then(response => { return response.json(); })。
2. 请求方式不符合Stripe规范
Stripe官方推荐使用POST请求创建结账会话,避免GET请求的缓存、幂等性问题。需修改:
- 视图类的
get方法改为post - JS中fetch请求的
method改为'POST',同时携带Django的CSRF令牌(POST请求必须验证CSRF)
3. Stripe金额单位问题
Stripe的unit_amount要求传入最小货币单位(如美元为分),如果item.price存储的是美元金额(如10.99),需乘以100转成整数,否则会因金额格式错误导致会话创建失败。
修复后的完整代码
修复后的HTML代码(含JS)
<html> <head> <title>Buy {{ item.name }}</title> </head> <body> {% csrf_token %} <!-- 加入CSRF令牌 --> <h1>{{ item.name }}</h1> <p>{{ item.description }}</p> <p>{{ item.price }}</p> <button id="buy-button">Buy</button> <script type="text/javascript"> var stripe = Stripe('pk_test_a9nwZVa5O7b0xz3lxl318KSU00x1L9ZWsF'); var buyButton = document.getElementById('buy-button'); // 修正引号问题 buyButton.addEventListener('click', function() { // 获取CSRF令牌 const csrfToken = document.querySelector('[name=csrfmiddlewaretoken]').value; fetch("{% url 'buy' item.id %}", { method: 'POST', // 改为POST请求 headers: { 'X-CSRFToken': csrfToken // 携带CSRF令牌 } }) .then(response => response.json()) // 修正箭头函数语法 .then(session => stripe.redirectToCheckout({ sessionId: session.id })) .catch(error => console.error('结账请求错误:', error)); // 加入错误捕获,便于调试 }); </script> </body> </html>
修复后的Views代码
class CreateCheckoutSessionView(View): # 替换get为post方法 def post(self, request, pk): item_id = self.kwargs["pk"] item = Item.objects.get(id=item_id) # 将美元金额转换为分(Stripe要求的最小单位) unit_amount = int(item.price * 100) checkout_session = stripe.checkout.Session.create( success_url="https://morungexpress.com/uploads/2022/01/36931750_1642339369_cc2dfdf7494bfa9436aac0d4a882a653.jpg", cancel_url="https://englishlib.org/dictionary/img/wlibrary/c/5ffdb27d24e086.50388072.jpg", mode="payment", line_items=[ { 'price_data': { 'currency': 'usd', 'unit_amount': unit_amount, 'product_data': { 'name': item.name }, }, "quantity": 1, } ] ) return JsonResponse({'id': checkout_session.id})
调试建议
修改后打开F12控制台,查看Network和Console标签:
- 检查请求是否成功发送到
/buy/1/ - 查看是否有报错信息,帮助定位剩余问题
内容的提问来源于stack exchange,提问作者LilyX
相关产品推荐
相关产品推荐

