mollie / mollie-api-php

Mollie API client for PHP
http://www.mollie.com
BSD 2-Clause "Simplified" License
552 stars 191 forks source link

Webhook call after refund #532

Closed TheoHuitema closed 3 years ago

TheoHuitema commented 3 years ago

Specifications

Describe the issue

I don't know if this is an issue or a support question, but I'm having a hard time getting the actual refund status via the webhook after a refund is made.

If I understand correctly, when a refund is made, the webhook is called. And when there's a refund status change, the webhook is called also. But I can't find out with what. Is it the payment id or the refund id? I presume the webhook is called with the payment id. But how can I find the actual refund status then? Is it correct that the payment object contains an '_embedded' property with a property 'refund' that contains all refunds? And if so, do I have to find the most recent refund status in the refund property?

A lot of questions, I know... But I hope you can set me on the right track with this, so I have a better understanding of the refund webhook flow. It is mentioned briefly in the docs, but not how the refund call to the webhook works. Or am I missing something?

Thanks,

Theo

sandervanhooft commented 3 years ago

Hi @TheoHuitema ,

Mollie will indeed call your webhook using the payment id the refund belongs to. You can then fetch the payment and (optionally) the related refunds.

$payment = $mollie->payments->get($idFromWebhookRequest);

// Retrieve a paginated collection of refunds for the payment
$refunds = $payment->refunds();

// Total amount refunded (NULL if there are nothing has been refunded)
$payment->amountRefunded;

Depending on your implementation you can check what happened either using the refund collection or the total amountRefunded.

TheoHuitema commented 3 years ago

Hi Sander

Thank you for your quick reply!

Okay, if I want to check for refunds, on every payment webhook call where te payment has the status 'paid' I have to check if refunds for that payment exist and if so, check the $refunds object for the latest refund? Sounds logical. At first I missed refund as a payment status, but this is actually a better way, I think.

If I understand correctly, depending on the status:

pending (the initial status after the refund is initiated) -> the webhook isn't called. queued -> the webhook is called processing -> the webhook is called failed -> the webhook is called refunded -> the webhook is called. The $payment->hasRefunds() has is populated with the current refund

Love the Mollie API by the way ;-)

Regards,

Theo

sandervanhooft commented 3 years ago

:+1: That's it!

TheoHuitema commented 3 years ago

Sorry Sander, closed this one too soon.

When checking the webhook with Postman I do not get the reponse I expected.

$refunds->count works (in the output I see it as such), but I can't get the refunds.

I expected that the refunds data was accessable via $refunds->_embedded->refunds, so I can loop the object, but instead I get this (see below). Getting the refund via the refund ID works fine, but in my use case I haven't got this ID yet. I therefor have to use the suggested Refund List method. Do you know what is happening?


 [count] => 1
    [_links] => stdClass Object
        (
            [documentation] => stdClass Object
                (
                    [href] => https://docs.mollie.com/reference/v2/refunds-api/list-refunds
                    [type] => text/html
                )

            [self] => stdClass Object
                (
                    [href] => https://api.mollie.com/v2/payments/tr_bDdmK72HwW/refunds?limit=50
                    [type] => application/hal+json
                )

            [previous] => 
            [next] => 
        )

    [storage:ArrayObject:private] => Array
        (
            [0] => Mollie\Api\Resources\Refund Object
                (
                    [resource] => refund
                    [id] => re_t5Hvjq9Q6n
                    [amount] => stdClass Object
                        (
                            [value] => 4.99
                            [currency] => EUR
                        )

                    [createdAt] => 2021-02-17T13:18:25+00:00
                    [description] => Coulance
                    [paymentId] => tr_bDdmK72HwW
                    [orderId] => 
                    [lines] => 
                    [settlementAmount] => stdClass Object
                        (
                            [value] => -4.99
                            [currency] => EUR
                        )

                    [status] => refunded
                    [_links] => stdClass Object
                        (
                            [self] => stdClass Object
                                (
                                    [href] => https://api.mollie.com/v2/payments/tr_bDdmK72HwW/refunds/re_t5Hvjq9Q6n
                                    [type] => application/hal+json
                                )

                            [payment] => stdClass Object
                                (
                                    [href] => https://api.mollie.com/v2/payments/tr_bDdmK72HwW
                                    [type] => application/hal+json
                                )

                        )
sandervanhooft commented 3 years ago

Yes that's raw data not processed by the client. How about $payment->refunds()?

TheoHuitema commented 3 years ago

When I print the $payment object the ouput is formatted as expected, but when I print $payment->refunds() at the same place the raw data shows up. In both cases I use ( print_r( ) ). Formatting as e.g. JSON has no effect on the result.

sandervanhooft commented 3 years ago

Despite output formatting, can you double check that it is in fact returning the right classes?

$payment = mollie()->payments()->get("tr_kxUGTsztNd");
$refunds = $payment->refunds();

echo get_class($refunds) . ' | ' . get_class($refunds[0]);
// Output: "Mollie\Api\Resources\RefundCollection | Mollie\Api\Resources\Refund"
TheoHuitema commented 3 years ago

Hi Sander,

Instead of $payment = mollie()->payments()->get("tr_bDdmK72HwW"); I used $payment = $mollie->payments->get("tr_bDdmK72HwW");. The first throws an error ( Call to undefined function mollie() ).

When I echo it, the ouptut is indeed "Mollie\Api\Resources\RefundCollection | Mollie\Api\Resources\Refund".

sandervanhooft commented 3 years ago

Great, that means it's not raw data you're receiving, but Refund objects. Not sure what's going on with your formatting though.

TheoHuitema commented 3 years ago

Oké. Any idea how to get the refund data then, given the output formatting I have? Something similar occurs when getting subscriptions. Although I can get the most relevant data directly , nextPaymentDate e.g. is somewhere in the data, but I can't get it via $subcriptions->nextPaymentDate .

FYI: I didn't install the Mollie library via Composer, but dowloaded it as a zip-file.

sandervanhooft commented 3 years ago

As php recognizes the output as valid objects, it doesn't seem to be related to this package. So can't help you there, sorry.

TheoHuitema commented 3 years ago

I will look into it.

Thank you for your time and effort, Sander!

sandervanhooft commented 3 years ago

No problem, hope you get it solved!