• Resolved Saif

    (@babylon1999)


    Hi there!

    I’m having a problem with the plugin in “Live” mode, specifically ACH payments.

    For some reason, the order status is not being switched to processing/complete when the payment success intent is sent to the website.

    I was able to track down the issue to this exact function: https://gist.github.com/Babylon1999/53d76745785eff3a894db0747d9cbd5b

    The function is stopped at if ( ! $order ) and throws the related error, however, the $intent->metadata->order_id returns the true order ID and is thrown in the error.

    2024-02-13T21:18:16+00:00 INFO Webhook notification received: Event: payment_intent.succeeded 2024-02-13T21:18:16+00:00 INFO Could not complete payment_intent.succeeded event for payment_intent pi_TEST. No order ID 14924 was found in your WordPress database. This typically happens when you have multiple webhooks setup for the same Stripe account. This order most likely originated from a different site.

    I thought this might have to do with HPOS, but no, the behavior is consistent. What’s driving me crazy is when I log the $order value in test mode I get the correct data, also the order status is changed correctly.

    Here’s the response from the server: https://i.imgur.com/U3tOkLp.png

    As you can see, there are no errors whatsoever, only an empty array response.

    I would really appreciate any assistance on how to solve this. ??

    Here’s a copy of the site’s system status (had to redact some data as it’s a client website).

Viewing 13 replies - 1 through 13 (of 13 total)
  • Plugin Author Payment Plugins

    (@mrclayton)

    Hi @babylon1999,

    Since you’re using HPOS, did you confirm that the order ID in the payment_intent’s metadata corresponds to an entry in the orders table?

    Do you have multiple webhooks setup for this Stripe account that point to different websites?

    Are you using the filter wc_stripe_filter_order_id at all?

    When fetching an order via the wc_get_order function, WooCommerce attempts to find the order in the cache first. Perhaps you have a caching issue with live orders?

    Kind Regards

    Thread Starter Saif

    (@babylon1999)

    Thank you so much for the fast reply!

    Since you’re using HPOS, did you confirm that the order ID in the payment_intent’s metadata corresponds to an entry in the orders table?

    The site is actually using the post table, but I did test with both storage modes, same result.

    Are you using the filter wc_stripe_filter_order_id at all?

    I was just given access to the website today, but I disabled all plugins and switched themes in case there was something in the functions.php file, so no, it’s not possible.

    When fetching an order via the wc_get_order function, WooCommerce attempts to find the order in the cache first. Perhaps you have a caching issue with live orders?

    Hmm, I didn’t know this. The website is hosted on WP Engine which has many caching features. I’ll try to disable all the options they allow and let you know.

    EDIT:

    Do you have multiple webhooks setup for this Stripe account that point to different websites?

    There are only two webhooks, one for test and one for live mode.

    Thread Starter Saif

    (@babylon1999)

    All caching features that can be disabled already are, any other suggestions, @mrclayton?

    Plugin Author Payment Plugins

    (@mrclayton)

    You have the ability to re-send webhook events. So I would write some logging code in the plugin so you can track everything. The plugin provides the wc_stripe_log_info function which you can use to log info from the request.

    Log the payment_intent’s metadata before the wc_get_order request. This wouldn’t be a Stripe plugin issue from what I can see. It’s the wc_get_order function that’s failing to return the order based on the order ID which is weird.

    Also, in the WC_Stripe_Utils::get_order_from_payment_intent function, modify line 265 the following code:

    $order = wc_get_order( wc_stripe_filter_order_id( absint($payment_intent->metadata->order_id), $payment_intent ) );

    Notice the use of absint. See if that makes a difference.

    In WC_Stripe_Utils::get_order_from_payment_intent, the plugin makes sure the _payment_intent_id metakey exists and it’s value matches the ID of the payment_intent from the webhook. You can view that code here. See if your order is missing the _payment_intent_id metakey or value.

    Kind Regards

    Thread Starter Saif

    (@babylon1999)

    I tried logging every step of the way.

    The culprit isn’t wc_get_order, the value of the $order variable is correct when logged.

    It’s only when passed to wc_stripe_process_payment_intent_succeeded , the value is NULL even though the $intent is valid.

    In WC_Stripe_Utils::get_order_from_payment_intent, the plugin makes sure the _payment_intent_id metakey exists and it’s value matches the ID of the payment_intent from the webhook. You can view that code here. See if your order is missing the _payment_intent_id metakey or value.

    Both the key and value are there. Also, wrapping it with absint made no difference.

    I don’t get why would this happen only in Live mode.

    Look forward to your reply.

    Plugin Author Payment Plugins

    (@mrclayton)

    Your logging statements are a bit confusing because you used The order: twice. It’s best to make unique statements per log entry so there’s not confusion about what line it came from.

    Please add additional log statements in the following locations (where all the return statements are for the method get_order_from_payment_intent):

    WC_Stripe_Utils::get_order_from_payment_intent LINE 267
    
    WC_Stripe_Utils::get_order_from_payment_intent LINE 283
    
    WC_Stripe_Utils::get_order_from_payment_intent LINE 293
    
    WC_Stripe_Utils::get_order_from_payment_intent LINE 297

    This will help determine which line of that method is returning the order result.

    Kind Regards

    Thread Starter Saif

    (@babylon1999)

    Your logging statements are a bit confusing because you used The order: twice. It’s best to make unique statements per log entry so there’s not confusion about what line it came from.

    I’m only keeping it one at a time, so I know where it’s coming from. Sorry, I should’ve mentioned that.

    I did your way, and it’s the one from line 293, which is expected the site is using the post table.

    What do you think is the problem?

    Thread Starter Saif

    (@babylon1999)

    Ok, I think I know what’s going on. The payment intent ID in Stripe is different than the one in the order meta.

    In the order meta, it’s: pi_{same_value}cqjzqE5

    In Stripe: pi_{same_value}8JEWzNQ

    How did this happen? :\

    Plugin Author Payment Plugins

    (@mrclayton)

    How did this happen??

    Lookup both of those payment intents and review their metadata. Is the order_id metadata property the same for each one?

    Which payment intent is the older of the two?

    What is your Stripe account ID? You can find that on the API Settings page of the plugin.

    It’s the same code base for live and test mode, nothing is different so that’s very odd.

    Thread Starter Saif

    (@babylon1999)

    What is your Stripe account ID? You can find that on the API Settings page of the plugin.

    The account ID in the plugins setting’s match the one in Stripe.

    Here’s what I found.

    At 2-Feb an order was started with ID 14930 (Live Mode).

    When the ACH payment cleared on the 8th, the payment in Stripe was completed but at the same time, a new payment was started in test mode for the same order ID with incomplete status. Its intent ID is the one I found in the order meta is the one from the test mode payment.

    I will be asking my client if they’re ok with uninstalling the plugin and reconfiguring everything from scratch.


    Before I ask them to place a new livemode order, do you know how something like this would happen?

    Plugin Author Payment Plugins

    (@mrclayton)

    Before I ask them to place a new livemode order, do you know how something like this would happen?

    The mode is set on the WooCommerce order’s metadata when it’s processed via the checkout page. Is it possible someone changed the order’s status to pending and tried to process a payment again with test mode enabled?

    Based on your description, this order was originally a live mode order but then got switched to a test mode order.

    There are quite a few merchants using the ACH integration and I’ve never heard of this issue before.

    Kind Regards

    Thread Starter Saif

    (@babylon1999)

    The mode is set on the WooCommerce order’s metadata when it’s processed via the checkout page. Is it possible someone changed the order’s status to pending and tried to process a payment again with test mode enabled?

    The behavior is consistent with all ACH order so far.

    Here’s the timeline:

    • Payment started in Live mode (Feb 2, 2024, 11:20 AM)
    • After 6 days, Payment succeeded was triggered in Live mode (Feb 8, 2024, 6:42 AM)
    • After one minute a new payment started in Test mode for the same Woo order ID (Feb 8, 2024, 6:43 AM)
    • The _payment_intent order meta data in Woo now belongs to the new Test mode payment.
    • Because of this, the webhook process function fails to change the order status.

    There are quite a few merchants using the ACH integration and I’ve never heard of this issue before.

    Yes, that’s why I’m still not convinced it’s a reproducible issue. I’m still waiting to hear back from my client. I’ll let you know if uninstalling/reconfiguring everything doesn’t help.

    Thank you so much for the continuous support!

    Thread Starter Saif

    (@babylon1999)

    Just want to let you know after reconfiguring everything from scratch, the issue is no longer reproducible, feel free to switch the thread to “solved”.

    Thank you so much for the amazing support! EZ 5 start review!

Viewing 13 replies - 1 through 13 (of 13 total)
  • The topic ‘$order is null when incoming webhook is in Live mode’ is closed to new replies.