Open EvgeniyHablak opened 4 years ago
Thanks @EvgeniyHablak for reporting this. I have fixed the inconsistency in the develop
branch.
Can you help me understand what's going on with the second part of your question?
ah found it
Dropped the 'temp_' prefix in the controller:
https://github.com/laravel/cashier-mollie/pull/113/commits/dda412f0ad1e0a6672730ad2358c3e2dff2725e9
We are almost there BUT now my mollie_payment_status is not updated to 'paid' I've tried to debug it but unsuccessful
Could you check:
Could you check:
- the Mollie dashboard for the response they're getting when calling your webhookUrl?
- your logs for any errors?
I've tried to debug library a little bit. when the lib version was 1.6 mollie made 2 requests and thats because our first response was with status code 500 (because we've tried to get mollie_payment_id from empty order object). after your fixes we are able to find order record in the database by temp payment id BUT I've Log that object we have found and it doesn't look like the order in my db. But how is that possible? Why for the first request from mollie we can't find the order but for the second one it works?
Here is one of response example
Here is example of webhooks i received
Mollie's webhook call is crazy fast. It's probably a concurrency issue. We'll have to look into it.
What cashier-mollie version are you at?
@sandervanhooft The debugging above is on version 1.6 And i'm currently on version 1.6 (because at least second webhook from mollie works fine)
Can you give 1.7
a try?
I have just checked it. I received one webhook from mollie and my response code was 200 BUT in my db molllie_payment_status is open
Also interesting thing is that i've tried to log the order in webhook Here is what ive got
But even if i die the script and would try to find such order with that temp id I couldn't
Maybe i'm testing incorrectly This is how my flow looks like:
order_items.process_at
from (for example) 2020-12-12
to 2019-12-12
php artisan cashier:run
Hi @EvgeniyHablak,
$order
is resolved just fine?_link
embedded on the payment specifically for this reason. I usually grab it using mollie()->payments()->get("the_payment_id")->_links;
Hi @sandervanhooft ! Thanks! I'll check it out asap
Closing this for now, let me know if it should be reopened @EvgeniyHablak .
I don't want to hijack this issue, but I also have some issues with the default Webhook callback. The getOrder function returns always null (can't find by mollie_payment_id). Could it be that the Webhook is called before the Order actually exists in the database.....? In this case the webhook is called after swapping a plan.
@Paulsky what version are you using?
I'm using v1.10.3
Just to make things clear (maybe I'm doing something wrong):
I'm using the swap() function on an existing subscription. The webhook is called correctly, and the data in the Mollie dashboard looks also correct. When I manually check the database, the mollie_payments_status is 'open' and the 'mollie_payment_id' is filled. The Order before the swap, created with the newSubscription, is 'paid'. The given payment ID with the request is set and looks correct. But as I said, maybe the Order doesn't exists at the time of the webhook call? Because Order::where('mollie_payment_id', $id)->first(); returns null.
So I did a lot of debugging. The Order is found in the webhook function, if I remove the DB::transaction() wrapper in the Subscription restartCycleWithModifications() function.
This way, the handlePaymentPaid() is called in the webhook and the OrderPaymentPaid event is fired. So that's great (for sending a new invoice).
But, somehow, the order status is still 'open', even though $this->update(['mollie_payment_status' => 'paid']);
is called.
Hope this helps you understand my issue a little bit!
I know you are very busy @sandervanhooft , and I don't want to push you. But maybe you can re-open this issue...?
I have been thinking about this...
The transaction is there for a reason. It's good to disable it to understand the problem, but I think we should keep it there.
As I've discussed here, there are essentially two alternatives we can try:
when the webhook is called, return a 404 if the payment is not found. Mollie will retry the webhook a second later, and then again using increasing intervals.
keep on returning a 200 response, but handle the webhook call in a queued Job, effectively enforcing a retry scheme within the app.
For simplicity and ease of debugging, I'm leaning towards option 1. What do you think, @Paulsky et al?
Hmm, I'm not sure. I'm also leaning towards option 1.
But, the problem I have is that I don't understand the reason why this is happening. Why is the Order not found (while it really seems to exists in the db)? Maybe if I understand the reason, I can give a better suggestion. Do you know what the problem is and could you explain it to me?
Thank you @sandervanhooft 🙏
Edit: I thought I have read somewhere that you wrote that the Mollie webhook is too fast. But I'm not sure about that myself; why would the Order be found if the DB:transaction wrapper is removed? This shouldn't speed up the webhook code would it? Or am I wrong about this?
It's a race condition issue.
Mollie's webhook call is so crazy fast it calls the webhook before the transaction is finished (meaning the Order is not stored yet). This all happens in a fraction of a second. So to the human eye it seems like the Order already is in the database table. But in fact, it's not stored yet.
Alright, incredible! If that's the case and if the DB::transaction wrapper can't be removed (I don't know if this is even the problem) I also recommend option 1; return a 404 because the Order really does not exists right? It feels less hacky and a lighter solution (instead of forcing users to use queues right?)
Exactly @Paulsky , thanks!
@Paulsky is this is issue occurring in test or live mode?
This occurs in test mode. But live I'm not sure, because I just saw I have some 'paid' 'mollie_payment_status' in the live database.
Ok, any of them not marked as paid
that should be?
No, it looks correct at live!
I've got an error while testing the webhooks
Undefined property: stdClass::$temporary_payment_id {"exception":"[object] (ErrorException(code: 0): Undefined property: stdClass::$temporary_payment_id at /var/www/wordproof/vendor/laravel/cashier-mollie/src/Http/Controllers/WebhookController.php:52)
And it seems like this is because of different properties in this places
But when i've set the same properties the order is not found by findByPaymentId using uuid. And thats why order status can't be updated.
This is how fixed version look but it works not as expected.