Django+Stripe项目支付成功页面无法跳转问题排查
Django+Stripe支付成功后无法跳转至成功页面的问题排查与解决
我正在开发首个Django+Stripe测试项目,但目前遇到支付成功后无法跳转至成功页面的问题。以下是我的相关代码:
views.py 文件
import stripe from django.conf import settings from django.http import HttpResponse from django.shortcuts import get_object_or_404 from django.views import View from django.views.generic import TemplateView from .models import Item stripe.api_key = settings.STRIPE_SECRET_KEY class ProductLandingPageView(TemplateView): template_name = 'landing.html' def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) item_id = self.kwargs["id"] item = get_object_or_404(Item, id=item_id) context['item'] = item return context class CreateCheckoutSessionView(View): def get(self, request, *args, **kwargs): item_id = self.kwargs["id"] DOMAIN: str = 'http://127.0.0.1:8000' item = Item.objects.get(id=item_id) session = stripe.checkout.Session.create( payment_method_types=['card'], line_items=[ { 'price_data': { 'currency': 'usd', 'unit_amount': item.price * 100, 'product_data': { 'name': item.name, }, }, 'quantity': 1, }, ], payment_intent_data={ 'metadata': { 'item_id': item.id, }, }, mode='payment', success_url=DOMAIN + '/success/', cancel_url=DOMAIN + '/cancel/', ) return HttpResponse(session.id) class SuccessView(TemplateView): template_name = "success.html" class CancelView(TemplateView): template_name = "cancel.html"
模板文件(landing.html)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Homepage</title> <script src="https://js.stripe.com/v3/"></script> </head> <body> <div class="description"> <h3>{{ item.name }}</h3> <h5>{{ item.display_price }} USD.</h5> </div> <button id="buy-button" data-item-id="{{ item.id }}">Buy</button> <script> document.getElementById('buy-button').addEventListener('click', function() { var itemId = this.getAttribute('data-item-id'); fetch('/buy/' + itemId) .then(function(response) { return response.json(); }) .then(function(data) { var stripe = Stripe(data.stripe_public_key); stripe.redirectToCheckout({ sessionId: data.session_id }); }) .catch(function(error) { console.error('Ошибка:', error); }); }); </script> </body> </html>
settings.py 相关配置
STRIPE_PUBLISHABLE_KEY = os.getenv('STRIPE_PUBLISHABLE_KEY') STRIPE_SECRET_KEY = os.getenv('STRIPE_SECRET_KEY')
urls.py 配置
from api.views import CancelView, SuccessView, CreateCheckoutSessionView, ProductLandingPageView from django.contrib import admin from django.urls import path urlpatterns = [ path('admin/', admin.site.urls), path('item/<int:id>', ProductLandingPageView.as_view(), name='item'), path('buy/<int:id>', CreateCheckoutSessionView.as_view(), name='buy'), path('cancel/', CancelView.as_view(), name='cancel'), path('success/', SuccessView.as_view(), name='success'),]
问题解决方法(更新)
通过修改前端JS代码,已解决支付成功后无法跳转的问题,修正后的代码如下:
<script> document.getElementById('buy-button').addEventListener('click', function() { var itemId = this.getAttribute('data-item-id'); var stripe = Stripe("{{ STRIPE_PUBLIC_KEY }}"); fetch('/buy/' + itemId) .then(function(response) { return response.json(); }) .then(function (session) { return stripe.redirectToCheckout({ sessionId: session.id }); }) .catch(function(error) { console.error('Ошибка:', error); }); }); </script>
额外优化建议
- 修正视图返回格式:原
CreateCheckoutSessionView返回纯文本session.id,但前端用response.json()解析会报错,需改为返回JSON格式:
from django.http import JsonResponse class CreateCheckoutSessionView(View): def get(self, request, *args, **kwargs): # 原有逻辑不变 return JsonResponse({'id': session.id})
- 模板传递公钥:在
ProductLandingPageView的get_context_data中添加Stripe公钥到上下文,避免模板硬编码:
def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) # 原有逻辑不变 context['STRIPE_PUBLIC_KEY'] = settings.STRIPE_PUBLISHABLE_KEY return context
- 添加异常捕获:在创建Stripe Session的视图中捕获API调用异常,返回错误响应:
from stripe.error import StripeError class CreateCheckoutSessionView(View): def get(self, request, *args, **kwargs): try: # 原有创建session的逻辑 return JsonResponse({'id': session.id}) except StripeError as e: return JsonResponse({'error': str(e)}, status=400)
- 改用POST请求创建Session:Stripe官方推荐用POST请求创建Checkout Session,避免GET请求的缓存或参数泄露问题,同时需添加Django CSRF Token验证。
内容的提问来源于stack exchange,提问作者Alan Dzheliev
相关产品推荐
相关产品推荐

