简体   繁体   中英

Django - AttributeError: 'tuple' object has no attribute 'get' [ DRF, Stripe, Python ]

I constantly get an error whenever I make a POST request to /api/tickets/:

Internal Server Error: /payment-stripe/
Traceback (most recent call last):
  File "/ENV/lib/python3.8/site-packages/django/core/handlers/exception.py", line 34, in inner
    response = get_response(request)
  File "/ENV/lib/python3.8/site-packages/django/utils/deprecation.py", line 96, in __call__
    response = self.process_response(request, response)
  File "/ENV/lib/python3.8/site-packages/django/middleware/clickjacking.py", line 26, in process_response
    if response.get('X-Frame-Options') is not None:
AttributeError: 'tuple' object has no attribute 'get'
[03/Jan/2020 03:17:09] "POST /payment-stripe/ HTTP/1.1" 500 58576

Here is my stripe payment handling view that I think is causing the problem, but I can't find out why:

@require_http_methods(["POST"])
@csrf_exempt
def stripe_payment_handling(request):
    """
    The following code is copied from Stripe Docs.

    Everything inside the IF statements is how the ticket gets handled.
    """
    payload = request.body
    # Checks for the signature of stripe.
    sig_header = request.headers['Stripe-Signature']
    event = None

    try:

        # Tests if it can create a connection with Stripe.
        event = stripe.Webhook.construct_event(
            payload, sig_header, endpoint_secret
        )

    except ValueError as e:

        # invalid payload: If it doesn't pass it gives back a 400
        return "Invalid payload", 400

    except stripe.error.SignatureVerificationError as e:

        # invalid signature: If the Stripe Signature is not there it wont accept it.
        return "Invalid signature", 400

    # Create the a dictionary with the data
    event_dict = event.to_dict()
    print(event_dict)

    if event_dict['type'] == "payment_intent.created":

        # If someone redirects to the bank to pay it will create a payment intent
        # Now it will use that value to validate the payment 
        intent = event_dict['data']['object']
        ticket = Ticket.objects.get(
            stripe_payment_intent=intent["id"]
        )
        ticket.status = "Created"
        ticket.save()

    elif event_dict['type'] == "payment_intent.succeeded":

        # If the payment Succeeded:
        intent = event_dict['data']['object']

        # get the ticket with the intent id that was created from payment_intent.created
        ticket = Ticket.objects.get(stripe_payment_intent=intent["id"])

        # Change status to Completed
        ticket.status = "Completed"
        ticket.save()

        # Reduce the amount of stock for the selected parking location
        ticket.stock_type.quantity -= 1
        ticket.stock_type.save()

        # Send the email to the client
        # The .send_ticket_email() function is part of the Ticket Model
        ticket.send_ticket_email()


    elif event_dict['type'] == "payment_intent.payment_failed":

        # If the payment has failed:
        intent = event_dict['data']['object']

        # Get the error message
        error_message = intent['last_payment_error']['message']
        print("Failed: ", intent['id'], error_message)

        # Notify the customer that payment failed
        try:
            # Find the ticket based on the intent id
            ticket = Ticket.objects.get(stripe_payment_intent=intent["id"])

            # Change its status to Failed
            ticket.status = "Failed"
            ticket.save()

            # Send Failed email
            # the .send_failed_email() function is part of the Ticket model
            ticket.send_failed_email()

        except Exception as e:
            # if the payment intent wasn't found send an email to contact support:
            print("Payment intent not found! => {0}".format(e))

    elif event_dict['type'] == "payment_intent.canceled":
        print("PAYMENT INTENT CANCELED")

    elif event_dict['type'] == "payment_intent.amount_capturable_updated":
        print("PAYMENT INTENT UPDATED")

    else:
        print("INTENT = {NONE}")

    return HttpResponse(status=200)

(extra) Here is my api/views.py:


class TicketInitialize(generics.GenericAPIView):
    queryset = Ticket.objects.all()
    serializer_class = TicketSerializer
    permission_classes = (permissions.AllowAny,)

    def post(self, request, *args, **kwargs):
        ticket_price = int(float(request.data["price"])) * 100
        print(ticket_price)
        stripe.api_key = 'my_stripe_api_key'
        intent = stripe.PaymentIntent.create(
            amount=ticket_price,
            currency='eur',
            payment_method_types=['card', 'ideal']
        )
        request.data["stripe_payment_intent"] = intent["id"]
        stock = Stock.objects.get(id=request.data["stock_type"])
        event = Event.objects.get(id=request.data["event"])
        new_ticket = Ticket.objects.create(
            first_name=request.data["first_name"],
            last_name=request.data["last_name"],
            quantity=request.data["quantity"],
            cell_phone=request.data["cell_phone"],
            email=request.data["email"],
            price=request.data["price"],
            service_fee=request.data["service_fee"],
            stock_type=stock,
            event=event,
            stripe_payment_intent=request.data["stripe_payment_intent"]
        )

        return Response(intent)

my urls.py:

urlpatterns = [
    path('payment-stripe/', views.stripe_payment_handling, name="stripe-endpoint"),
]

I don't understand why it keeps giving me the Attribute Error. It won't allow me to handle any webhooks from stripe or complete orders.

Thank you for taking a look, and I'm looking forward to your suggestions and answers!

Change return "Invalid signature", 400 to

 return HttpResponse(status=400, content="Invalid signature")

and return "Invalid payload", 400 to

 return HttpResponse(status=400, content="Invalid payload")

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM