部署时的 django stripe 验证 webhook 签名时出错

问题描述 投票:0回答:1

我有 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
django stripe-payments payment
1个回答
0
投票

好吧,我发现了问题所在,我希望这会对某人有所帮助,我认为我的 Secret_webhook_key 位于右上角,但不是,需要单击才能显示,只有在那之后才会出现您的 Secret_webhook_key :p

https://i.sstatic.net/4aiAjX7L.png

© www.soinside.com 2019 - 2024. All rights reserved.