News:

AbanteCart v1.4.4 is released.

Main Menu

Do you like AbanteCart? Please rate AbanteCart or share your experience with other eCommerce entrepreneurs. Go to Softaculous rating page to add your rating or write a review

Menu

Show posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.

Show posts Menu

Topics - RCodiaDavid

#1
AbanteCart version: 1.4.4
Extension: Paypal Commerce
Payment action: Capture (Sale)
File affected: extensions/paypal_commerce/storefront/controller/responses/extension/paypal_commerce.php

Background
After updating to 1.4.4, PayPal payments were being taken but orders were not appearing in the admin, and customers were being left on the checkout confirmation page with their cart still full. I want to stress that this may be specific to my own setup or update path. I'm not certain these are universal bugs, but I couldn't find any existing posts about it and wanted to share what I found in case it helps anyone else in the same situation.

Symptoms
Customer pays via PayPal successfully & money is taken
Order does not appear in AbanteCart admin (or appears under "Incomplete" status, which is filtered out of the default admin order view)
After payment, customer is left on the checkout confirmation page with their cart still full, no redirect to the order confirmation page
PayPal error log shows: Paypal webhook PAYMENT.CAPTURE.COMPLETED: order ID XXXXX / Paypal related OrderId: XXXXXXXXXXXXXXXXX but not found in the database

What I think was happening
After digging through the code I found three separate issues that combined to break the checkout flow. These may have been introduced during my update to 1.4.4 or may be specific to my configuration, I can't say for certain. I'm sharing them here in case anyone else hits the same problems.

Issue 1: array_merge null crash in captureOrder()

$this->session->data['fc'] appeared to be null in my checkout path, causing a fatal error that crashed the entire captureOrder() method:

array_merge(): Argument #2 must be of type array, null given

Issue 2: Possible race condition: orders stuck as "incomplete"

Even without Issue 1, captureOrder() doesn't confirm the AbanteCart order itself, it relies on the browser making a subsequent call to send() → processGenericOrder() to do that. In my case, PayPal's PAYMENT.CAPTURE.COMPLETED webhook was arriving before the browser's send() call ran. The webhook handler calls update() on the order, which appears to do nothing on an unconfirmed/incomplete order. The result was orders remaining in "Incomplete" status, hidden from the default admin filter. This timing may vary between setups.

Issue 3: Duplicate INSERT crashing processGenericOrder(), cart never clearing

Once I fixed Issue 2 by saving the PayPal order record in captureOrder(), the subsequent send() call reached processGenericOrder(), which unconditionally calls savePaypalOrder() again for the same order. Since savePaypalOrder() uses a plain INSERT with no duplicate handling, this threw a database error that silently killed the method, so the checkout/finalize redirect URL was never returned to the browser and the cart was never cleared.

What I did to fix it

Fix 1: array_merge null crash

In captureOrder(), find:

$this->session->data['fc'] = array_merge($order->data, $this->session->data['fc']);
Replace with:

$this->session->data['fc'] = array_merge((array)$order->data, (array)$this->session->data['fc']);
Fix 2: Confirm order and save PayPal record immediately in captureOrder()

In captureOrder(), find the closing of the if ($orderInfo) block followed by the catch:

          $order->buildOrderData($this->session->data['fc']);
                $order->saveOrder();
            }

        } catch (Exception|Error $e) {

Replace with:

          $order->buildOrderData($this->session->data['fc']);
                $order->saveOrder();
            }

            $confirmOrderId = (int)($orderId ?: $this->session->data['order_id']);
            if ($confirmOrderId && $result->getId()) {
                /** @var ModelCheckoutOrder $oMdl */
                $oMdl = $this->loadModel('checkout/order');
                $confirmedOrderInfo = $oMdl->getOrder($confirmOrderId);
                $incompleteStatusId = (int)$this->order_status->getStatusByTextId('incomplete');
                $currentStatusId    = (int)($confirmedOrderInfo['order_status_id'] ?? 0);
                if ($confirmedOrderInfo && (!$currentStatusId || $currentStatusId == $incompleteStatusId)) {
                    $settledStatusId = $this->config->get('paypal_commerce_transaction_type') == 'capture'
                        ? $this->config->get('paypal_commerce_status_success_settled')
                        : $this->config->get('paypal_commerce_status_success_unsettled');
                    $oMdl->confirm(
                        $confirmOrderId,
                        $settledStatusId ?: $this->order_status->getStatusByTextId('pending')
                    );
                }
                if (!$mdl->getPaypalOrder($confirmOrderId)) {
                    $mdl->savePaypalOrder($confirmOrderId, [
                        'id'             => $ppOrderId,
                        'transaction_id' => $result->getId(),
                    ]);
                }
            }

        } catch (Exception|Error $e) {

Fix 3: Guard duplicate savePaypalOrder in processGenericOrder()

In processGenericOrder(), find:

      $mdl->savePaypalCustomer($this->customer->getId(), $transactionDetails['payer']['payer_id']);
            $mdl->savePaypalOrder(
                $orderId,
                [
                    'id'             => $transactionDetails['id'],
                    'transaction_id' => $transactionDetails['id'],
                ]
            );

Replace with:

      $mdl->savePaypalCustomer($this->customer->getId(), $transactionDetails['payer']['payer_id']);
            if (!$mdl->getPaypalOrder($orderId)) {
                $mdl->savePaypalOrder(
                    $orderId,
                    [
                        'id'             => $transactionDetails['id'],
                        'transaction_id' => $transactionDetails['id'],
                    ]
                );
            }

Fix 4: Improve webhook fallback in processWebHook()

In processWebHook(), find:

  /** @var ModelCheckoutOrder $oMdl */
        $oMdl = $this->loadModel('checkout/order');
        $oMdl->update(
            $orderId,
            $this->data['order_status_id'],
            'Order updated by Paypal webhook request.'
        );
Replace with:

  /** @var ModelCheckoutOrder $oMdl */
        $oMdl = $this->loadModel('checkout/order');
        /** @var ModelExtensionPaypalCommerce $mdl */
        $mdl = $this->loadModel('extension/paypal_commerce');
        $webhookOrderInfo   = $oMdl->getOrder($orderId);
        $incompleteStatusId = (int)$this->order_status->getStatusByTextId('incomplete');
        $currentStatusId    = (int)($webhookOrderInfo['order_status_id'] ?? 0);
        if ($webhookOrderInfo && (!$currentStatusId || $currentStatusId == $incompleteStatusId)) {
            $oMdl->confirm($orderId, $this->data['order_status_id']);
            if (!$mdl->getPaypalOrder($orderId)) {
                $ppOrderId = $inData['parsed']['resource']['supplementary_data']['related_ids']['order_id'] ?? '';
                $mdl->savePaypalOrder($orderId, [
                    'id'             => $ppOrderId,
                    'transaction_id' => $inData['parsed']['resource']['id'] ?? '',
                ]);
            }
        } else {
            $oMdl->update(
                $orderId,
                $this->data['order_status_id'],
                'Order updated by Paypal webhook request.'
            );
        }

Bonus: Order numbers missing from PayPal transaction exports

I also noticed that the "Custom Number" column in PayPal's transaction export spreadsheet was blank for all orders placed after updating to 1.4.4 (or maybe earlier). In older versions this column showed the AbanteCart order number, which is useful for reconciliation. The custom_id field appears to have been removed from the PayPal purchase unit payload in 1.4.4, possibly intentionally since the webhook lookup mechanism changed to use reference_id instead. Adding it back as a plain order number restores the column in exports without affecting anything else.

In prepareOrderData(), find:

   $this->data['pp']['purchase_units'][0] = [
            'reference_id' => $ppOrderData['data']['reference_id'] ? : $this->session->data['reference_id'],
            'amount'       => [
Replace with:

   $this->data['pp']['purchase_units'][0] = [
            'reference_id' => $ppOrderData['data']['reference_id'] ? : $this->session->data['reference_id'],
            'custom_id'    => (string) $orderId,
            'amount'       => [

Note for existing incomplete orders

If you have orders already stuck in "Incomplete" status where payment was successfully taken, go to Sales → Orders, filter by "Incomplete" status, open each affected order, change the status to Processing (or your configured success status), and tick "Notify Customer" to send the confirmation email. I think this works, not fully tested yet.

I'm not a core developer so there may be good reasons some of this works differently by design, happy to be corrected. (Please don't flame me if I've gone overboard)

Posting in case it's useful to anyone else who updated to 1.4.4 and is seeing the same symptoms.
#2
Support / PayPal code is outputted to customer comments
February 27, 2024, 07:32:34 AM
Earlier this month I disabled "Fast Checkout" as whenever anyone pays using PayPal, we get a big block of code from PayPal webhook in the Status & Comments section of the order. Disabling fast checkout didn't fix this, but it did have the strange side-effect of not sending any purchase details for Google Ads so it looks like no purchases have been made through there.

My main worry is the block of text though, in the Customer's order comment we get this for every PayPal transaction:

Paypal webhook PAYMENT.CAPTURE.COMPLETED:

Parsed data:
array (
'id' => etc...

Any idea why this is happening and how to fix it?
#3
Support / cache.php and critical app errors
September 25, 2023, 09:32:23 AM
Hi, strange things happening all of a sudden today.

I have a huge error log all relating to cache.php

Also a customer order came through but no email received and it's not in orders or in customer history.
Speaking of which, there in NO customer order history at all, all gone! Orders are still in Sales/Orders but not this one.

Here is an example of the logs, it goes on for 6626 lines so best not paste it all here. I deleted the log and it came back again.

2::warning
Trying to access array offset on value of type null in /home/customer/www/ourstore.com/public_html/store/core/lib/cache.php on line 624
2::warning
Undefined array key "layout" in /home/customer/www/ourstore.com/public_html/store/core/lib/cache.php on line 598
2::warning
Trying to access array offset on value of type null in /home/customer/www/ourstore.com/public_html/store/core/lib/cache.php on line 598
2::warning
Undefined array key "layout" in /home/customer/www/ourstore.com/public_html/store/core/lib/cache.php on line 601
2::warning
Trying to access array offset on value of type null in /home/customer/www/ourstore.com/public_html/store/core/lib/cache.php on line 601
2::warning
Undefined array key "layout.block.template.12.3.store_0" in /home/customer/www/ourstore.com/public_html/store/core/lib/cache.php on line 616
2::warning
Undefined array key "layout" in /home/customer/www/ourstore.com/public_html/store/core/lib/cache.php on line 621


We also have a critical App Error:

App Error
Message status:
critical
Date:
09/22/2023 03:36:32 PM
Number of repetitions:
101
aMySQLi class error: Try to escape non-string value: array ( 0 => '830', ) (file: /home/customer/www/ourstore.com/public_html/store/core/lib/cart.php line 255) Trace: #0 /home/customer/www/ourstore.com/public_html/store/core/database/amysqli.php on line 154 #1 /home/customer/www/ourstore.com/public_html/store/core/lib/db.php on line 107 #2 /home/customer/www/ourstore.com/public_html/store/core/lib/cart.php on line 255 #3 /home/customer/www/ourstore.com/public_html/store/core/lib/cart.php on line 154 #4 /home/customer/www/ourstore.com/public_html/store/core/lib/cart.php on line 838


Can someone help?



#4
Hi,

The new GA4 has been a bit of a nightmare. It never seemed to migrate properly from UA and is still bugged so I thought that was the issue, but I've set up a new GA4 and we are still not getting the purchase and revenue data come through.

Have updated to 1.3.4 and everything else seems to be coming through okay but purchases are not showing which is the most vital bit.

We are UK based and using GBP.

Any suggestions?

Thanks in advance
#5
Hi,

Been trying to dig through the code now for a while to try and find a way that we can implement Google API's to have addresses autocomplete to reduce user input errors.

However, this seems like a much more complicated task than I envisioned.

I have a HTML test page working and it works (as far as the Google bit) in an HTML block. But I'm unable to find the file (or files) that need to be changed to integrate something like this in AbanteCart's account stuff. I suppose it would need to be in several places for when a user first signs up, and also when they add/change addresses.

Can anyone shed any light on how we might go about this?

Thanks
David
#6
Support / Error 500 - Mail & Backup
March 31, 2022, 10:30:51 AM
Hi,

I'm a bit confused,

I'm getting a 500 error when trying to back up, the log just says error 0
Step 1 - failed. (Connection error occurred. HTTP-status:500)
Step 2 - failed. (Connection error occurred. HTTP-status:500)
Step 3 - failed. (Connection error occurred. HTTP-status:500)


Also when trying to send mails to customers I get the same
Task Failed
0 messages have been sent.
Step 1 - failed. (Connection error occurred. HTTP-status:500)
#7
Support / Stripe not receiving OrderID
December 21, 2021, 10:31:40 AM
Hi,

We recently updated to 1.3.0 and then got the Stripe issue of it not capturing payments. So we updated default_stripe to 1.0.5 which helped with the capture issue.

Since then, however, we are no longer receiving OrderID's in Stripe.

Previously the description would say "Shop Name Order #xxxx - Customer Name"
but now just says "Guest Customer: Customer Name" or "Customer ID: xxxx" without any reference to the OrderID.

Could you please help as it's causing a few issues for us.

Many thanks

Forum Rules Code of conduct
AbanteCart.com 2010 -