我有 Django React 应用程序,我向 Django 添加了 Stripe,在静态 Django 上设置了 React 构建文件 我已经在本地主机上使用 stripe cli 进行了测试,工作正常,但是在我在 vercel 上部署 django 项目并在 https://dashboard.stripe.com/test/webhooks 上创建端点以处理 stripe webhooks 事件后,我收到错误 https: //i.sstatic.net/51zS8MrH.png,(在创建新的 webhook 端点后,我设置了新的 webhook_secret_key,所以问题不在 webhook_secret_key 中) 我在网上搜索了如何修复它,他们建议设置在payload上
request.body.decode('utf-8)
或
request.data
但没有任何帮助
我的代码(本地主机上的此代码工作正常,但在部署的服务器上我收到错误,对于部署的服务器,我将 webhook_secret_key 更改为新的 Secret_webhook_key 从 https://dashboard.stripe.com/test/webhooks 并将 site_url 更改为部署的服务器)
from django.conf import settings
from django.http import HttpResponse
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from .models import DepositHistory
from django.views.decorators.csrf import csrf_exempt
from decimal import Decimal
import stripe
from rest_framework.decorators import api_view
from usersAuth.models import AppUser
stripe.api_key = settings.STRIPE_SECRET_KEY
class StripeCheckoutView(APIView):
def post(self, request):
if self.request.user.is_authenticated:
try:
checkout_session = stripe.checkout.Session.create(
line_items=[
{
'price': 'price_1PY4d6GKlfpQfnx9EFKpod75',
'quantity': 1,
},
],
metadata={"user": f'{self.request.user}'},
mode='payment',
success_url=settings.SITE_URL + '/?success=true&session_id={CHECKOUT_SESSION_ID}',
cancel_url=settings.SITE_URL + '/?canceled=true',
)
return Response({"url": checkout_session.url})
except:
return Response(
{'error': 'Something went wrong when creating stripe checkout session'},
status=status.HTTP_500_INTERNAL_SERVER_ERROR
)
return Response({'error': 'You must be logged in to pay'}, status=status.HTTP_401_UNAUTHORIZED)
@csrf_exempt
@api_view(['POST'])
def stripe_webhook_view(request):
payload = request.body
sig_header = request.META['HTTP_STRIPE_SIGNATURE']
event = None
try:
event = stripe.Webhook.construct_event(
payload,
sig_header,
settings.STRIPE_SECRET_WEBHOOK
)
except ValueError as e:
# Invalid payload
#print('Error parsing payload: {}'.format(str(e)))
return HttpResponse({'Error parsing payload'},status=400)
except stripe.error.SignatureVerificationError as e:
# Invalid signature
#print('Error verifying webhook signature: {}'.format(str(e)))
return HttpResponse({'Error verifying webhook signature'},status=400)
if event['type'] == 'checkout.session.completed':
print('we are in checkout.session.completed')
session = event['data']['object']
user = session.metadata.user
amount = Decimal(session.amount_total / 100)
appuser = AppUser.objects.get(email=user)
DepositHistory.objects.create(user=appuser, amount=amount)
appuser.balance += amount
appuser.save()
if event.type == 'payment_intent.succeeded':
payment_intent = event.data.object # contains a stripe.PaymentIntent
print('PaymentIntent was successful!')
elif event.type == 'payment_method.attached':
payment_method = event.data.object # contains a stripe.PaymentMethod
print('PaymentMethod was attached to a Customer!')
# ... handle other event types
else:
print('Unhandled event type {}'.format(event.type))
return HttpResponse(status=200)
我在 webhook 端点面板上收到此错误响应 https://i.sstatic.net/A2XYnrq8.png 并要求
{
"id": "evt_1PaIDNGKlfpQfnx92DWXRjHv",
"object": "event",
"api_version": "2024-06-20",
"created": 1720447609,
"data": {
"object": {
"id": "cs_test_a1RF6rCujYP6HqWdSmm3iZGxtdRNlpoSUlzvw09krFzU0UPgwWOyhwoIk7",
"object": "checkout.session",
"after_expiration": null,
"allow_promotion_codes": null,
"amount_subtotal": 500,
"amount_total": 500,
"automatic_tax": {
"enabled": false,
"liability": null,
"status": null
},
"billing_address_collection": null,
"cancel_url": "{url_website}/?canceled=true",
"client_reference_id": null,
"client_secret": null,
"consent": null,
"consent_collection": null,
"created": 1720447585,
"currency": "usd",
"currency_conversion": null,
"custom_fields": [
],
"custom_text": {
"after_submit": null,
"shipping_address": null,
"submit": null,
"terms_of_service_acceptance": null
},
"customer": null,
"customer_creation": "if_required",
"customer_details": {
"address": {
"city": null,
"country": "PN",
"line1": null,
"line2": null,
"postal_code": null,
"state": null
},
"email": "email",
"name": "name",
"phone": null,
"tax_exempt": "none",
"tax_ids": [
]
},
"customer_email": null,
"expires_at": 1720533984,
"invoice": null,
"invoice_creation": {
"enabled": false,
"invoice_data": {
"account_tax_ids": null,
"custom_fields": null,
"description": null,
"footer": null,
"issuer": null,
"metadata": {
},
"rendering_options": null
}
},
"livemode": false,
"locale": null,
"metadata": {
"user": "user_who_loged"
},
"mode": "payment",
"payment_intent": "pi_3PaIDLGKlfpQfnx918HiVozd",
"payment_link": null,
"payment_method_collection": "if_required",
"payment_method_configuration_details": {
"id": "pmc_1PY9NLGKlfpQfnx9LdBoV5BK",
"parent": null
},
"payment_method_options": {
"card": {
"request_three_d_secure": "automatic"
}
},
"payment_method_types": [
"card",
"link"
],
"payment_status": "paid",
"phone_number_collection": {
"enabled": false
},
"recovered_from": null,
"saved_payment_method_options": null,
"setup_intent": null,
"shipping_address_collection": null,
"shipping_cost": null,
"shipping_details": null,
"shipping_options": [
],
"status": "complete",
"submit_type": null,
"subscription": null,
"success_url": "{url_website}/?success=true&session_id={CHECKOUT_SESSION_ID}",
"total_details": {
"amount_discount": 0,
"amount_shipping": 0,
"amount_tax": 0
},
"ui_mode": "hosted",
"url": null
}
},
"livemode": false,
"pending_webhooks": 1,
"request": {
"id": null,
"idempotency_key": null
},
"type": "checkout.session.completed"
}
我在尝试之前打印了有效负载和sig_header,除了,这是我从网络服务器日志中得到的,这是用于有效负载的
b'{\n "id": "evt_1PaLctGKlfpQfnx9CVEMf0LE",\n "object": "event",\n "api_version": "2024-06-20",\n "created": 1720460723,\n "data": {\n "object": {\n "id": "cs_test_a1W2LUKRDeLyo3fwTaoVpxA1oaBbQ8Bdwe4KKPTX0F7gGg4LSCg9BoAxJk",\n "object": "checkout.session",\n "after_expiration": null,\n "allow_promotion_codes": null,\n "amount_subtotal": 500,\n "amount_total": 500,\n "automatic_tax": {\n "enabled": false,\n "liability": null,\n "status": null\n },\n "billing_address_collection": null,\n "cancel_url": "{url_server}/?canceled=true",\n "client_reference_id": null,\n "client_secret": null,\n "consent": null,\n "consent_collection": null,\n "created": 1720460707,\n "currency": "usd",\n "currency_conversion": null,\n "custom_fields": [\n\n ],\n "custom_text": {\n "after_submit": null,\n "shipping_address": null,\n "submit": null,\n "terms_of_service_acceptance": null\n },\n "customer": null,\n "customer_creation": "if_required",\n "customer_details": {\n "address": {\n "city": null,\n "country": "QA",\n "line1": null,\n "line2": null,\n "postal_code": null,\n "state": null\n },\n "email": "email",\n "name": "name",\n "phone": null,\n "tax_exempt": "none",\n "tax_ids": [\n\n ]\n },\n "customer_email": null,\n "expires_at": 1720547107,\n "invoice": null,\n "invoice_creation": {\n "enabled": false,\n "invoice_data": {\n "account_tax_ids": null,\n "custom_fields": null,\n "description": null,\n "footer": null,\n "issuer": null,\n "metadata": {\n },\n "rendering_options": null\n }\n },\n "livemode": false,\n "locale": null,\n "metadata": {\n "user": "user_who_logged"\n },\n "mode": "payment",\n "payment_intent": "pi_3PaLcrGKlfpQfnx91DXMhSXB",\n "payment_link": null,\n "payment_method_collection": "if_required",\n "payment_method_configuration_details": {\n "id": "pmc_1PY9NLGKlfpQfnx9LdBoV5BK",\n "parent": null\n },\n "payment_method_options": {\n "card": {\n "request_three_d_secure": "automatic"\n }\n },\n "payment_method_types": [\n "card",\n "link"\n ],\n "payment_status": "paid",\n "phone_number_collection": {\n "enabled": false\n },\n "recovered_from": null,\n "saved_payment_method_options": null,\n "setup_intent": null,\n "shipping_address_collection": null,\n "shipping_cost": null,\n "shipping_details": null,\n "shipping_options": [\n\n ],\n "status": "complete",\n "submit_type": null,\n "subscription": null,\n "success_url": "{web_server}/?success=true\\u0026session_id={CHECKOUT_SESSION_ID}",\n "total_details": {\n "amount_discount": 0,\n "amount_shipping": 0,\n "amount_tax": 0\n },\n "ui_mode": "hosted",\n "url": null\n }\n },\n "livemode": false,\n "pending_webhooks": 3,\n "request": {\n "id": null,\n "idempotency_key": null\n },\n "type": "checkout.session.completed"\n}'
这是用于 sig_header 的
t=1720460723,v1=633e50ecd694f51fc6ee2b38586304cd3d73575b2958a1863c5e4ca0854b00b8,v0=a82427ef23faaf0a8d6e5b6b6e466263379fe6f835e8bcd99bd6cde4d4bcb138
好吧,我发现了问题所在,我希望这会对某人有所帮助,我认为我的 Secret_webhook_key 位于右上角,但不是,需要单击才能显示,只有在那之后才会出现您的 Secret_webhook_key :p