stripe / stripe-php

PHP library for the Stripe API.
https://stripe.com
MIT License
3.74k stars 849 forks source link

Charge failure returns no decline code #1707

Closed that-guy-iain closed 4 months ago

that-guy-iain commented 4 months ago

Describe the bug

I see that in CardException that it's looking for decline_code but I see in the response output from a charge to a card on file returns the code in failure_code and that is in the openapi spec as well.

To Reproduce

Create a charge to a card that fails and catch the CardException and call getDeclineCode.

Expected behavior

getDeclineCode returns the reason the charge failed

Code snippets

No response

OS

all

PHP version

all

Library version

v7.128.0

API version

2024-04-10

Additional context

No response

remi-stripe commented 4 months ago

@that-guy-iain I'm not entirely sure I grasp what you are describing here. It seems you say you got a Charge ch_123 that was declined but it has no decline_code or failure_code set, is that correct? This is more likely to be something you should debug directly with our support team if that's the case so that they can investigate what caused this but it wouldn't be a bug with the stripe-php SDK. I'd recommend you reach out to our support team at https://support.stripe.com/contact and share all the details of what you noticed so they can help you further!

that-guy-iain commented 4 months ago

I'm sorry I thought I wrote I was trying to get the decline code from CardException that is a class provided by this SDK, no?

That exception looks for decline_code however the API is returning it under failure_code. This means when you call the getDeclineCode method on the CardException provided by this SDK it returns null.

I'm very confused about what you're not understanding. Please re-read this issue.

that-guy-iain commented 4 months ago

I've created a POC so you can read the code and understand.

remi-stripe commented 4 months ago

failure_code is a property on the Charge object. It's completely separate/unrelated to what is returned on an API error where that describes our Error object and that one has decline_code and not failure_code.

Right now my read is that you are mixing up the two concepts and the change you made is not something we'd merge as is since it can't happen.

that-guy-iain commented 4 months ago

I'm just dealing with the CardException that is flung by this SDK. I'm not using the API directly so if there is a mixup in the concepts it would have to be by the maintainers of this library.

remi-stripe commented 4 months ago

@that-guy-iain Can you give a concrete example request that you caught that way? If you can share the exact request id req_123 from your account, it would help to make sure we are talking about the same thing.

that-guy-iain commented 4 months ago

I can give you the exact code https://github.com/getparthenon/obol/blob/main/src/Provider/Stripe/PaymentService.php#L292

that-guy-iain commented 4 months ago

And evt_3POTl0IfxpuZtqIz1ocN0aLE is an event id

that-guy-iain commented 4 months ago

Just realised I did some workarounds in that repo https://github.com/getparthenon/obol/blob/c2c0b41a54f6cb91023856a1e8e1bf5e66dff495/src/Provider/Stripe/PaymentService.php#L293 is an old original version

remi-stripe commented 4 months ago

The id you shared is an Event id which is quite different. This describes a Charge and it has failure_code which is what I explained above. It's a property on the Charge object.

You need to look at the API Request itself since that will have the real error. You can see it in your Dashboard here for your account for example. I'll share a redacted version here

{
  error: {
    charge: "ch_12345",
    code: "expired_card",
    doc_url: "https://stripe.com/docs/error-codes/expired-card",
    message: "Your card has expired.",
    param: "exp_month",
    request_log_url: "https://dashboard.stripe.com/test/logs/req_12345",
    type: "card_error",
  },
}

That is the Error object that maps to the relevant exception class in stripe-php. You can see that response/JSON does not have failure_code and adding your change wouldn't really help/make sense in this case. And the code property already exists on the exception you are catching and you an access it directly with getCode()

With that said, this error should return decline_code: 'expired_card' too to make it easier for developers so I'll flag this internally so we can fix it.

that-guy-iain commented 4 months ago

Thanks