skip to Main Content

I’m building a payment plugin. The way it works is on clicking the pay option on the checkout page, the user gets a link on their mobile phone where they can complete the payment which then triggers a webhook to the WooCommerce site and status gets updated as paid/failed according to the data received in the webhook.

The requirement is that the spinner that’s displayed after clicking the pay option stays on until the webhook data is received or is timed out after 2 minutes. Right now the webhook is doing it’s job, but the logic behind the spinner fails. Not sure what’s going wrong

This is the code which get’s triggered after the SMS with the link is sent to the user. The logic inside the do...while loop doesn’t work

WC()->cart->empty_cart();
$order->update_status('wc-pending', __('Awaiting payment.', 'txtdomain'));

$loop = 8;
$loopOrder = wc_get_order($order_id);
do {
    sleep(15);
    $loopOrder = wc_get_order($order_id);
    $loop--;
} while ($loopOrder->get_status() == "pending" && $loop >= 0);

if ($loopOrder->get_status() == "pending" || $loopOrder->get_status() == "failed") {
    $_SESSION["order_id"] = $order_id;
    $_SESSION["timeout"] = (time() + ($GLOBALS['retry_delay_in_minutes'] * 60));
    $error_message = 'Timed out. Please wait <span id="retry_timer">' . ($_SESSION["timeout"] - time()) . '</span> seconds before retrying';
    if($loopOrder->get_status() == "failed"){
        $error_message = 'Payment failed. Please wait <span id="retry_timer">' . ($_SESSION["timeout"] - time()) . '</span> seconds before retrying';
    }
    wc_add_notice($error_message, 'error');
    return array(
        'result' => 'failed',
    );
} else {
    return array(
        'result' => 'success',
        'redirect' => $order->get_checkout_order_received_url()
    );
}

and below is the code that’s triggered on receiving the webhook

$order = wc_get_order($request["OrderNumber"]);

if ($request["StatusID"] == 0) {
    $order->update_status('wc-failed');
} else {
    update_post_meta($request["OrderNumber"], 'invoiceid', $request["TransactionID"]);
    $shipping = false;
    foreach ($order->get_items() as $order_item) {
        $item = wc_get_product($order_item->get_product_id());
        if (!$item->is_virtual()) {
            $shipping = true;
        }
    }
    if ($shipping) {
        $order->update_status('wc-processing');
    } else {
        $order->update_status('wc-completed');
    }
}
return true;

2

Answers


  1. Chosen as BEST ANSWER

    After multiple trials and error I understood that $loopOrder = wc_get_order($order_id); doesn't load the order information from the database. So to fetch the updated information, adding an $loopOrder->save(); after fetching current information fixed the issue.


  2. Looks like your your do/while conditional checks the get_status() method’s return value against un-prefixed strings "pending" and "failed", while the update_status() method in the second block of code is presumably setting the class variable for order status to stings that all include a "wc-" prefix (wc-failed, wc-processing, wc-completed etc).

    Change $loopOrder->get_status() == "pending" to $loopOrder->get_status() == "wc-pending" and $loopOrder->get_status() == "failed" to $loopOrder->get_status() == "wc-failed" in your first block.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search