Call to a member function on a non-object

Permalink Browser Info Environment
We're seeing an error on our server logs, "PHP Fatal error: Call to a member function getAddress2() on a non-object in /Users/domain/Sites/Packages/core_commerce/models/payment/methods/authorize_net_aim/controller.php on line 87"

From what I can gather, this has been happening sporadically, but at least once a week. Our client is getting duplicate orders. We suspect there is an error after the order is placed and payment is processed, but the customer never sees the confirmation page. (This may be totally wrong.)

The other scenario is a customer tries to place an order, get the fatal error message and never places an order.

Both situations result in lost time and revenue as the duplicate charges have to be reversed or the order is never placed.

Line 87 is:
$addr2 = $o->getAttribute('billing_address')->getAddress2();

What I'm wondering is if something is returning a null value and throwing the error. Is it possible to put that statement is a try/catch block?

Also, the address2 calls are the only ones assigned to a variable ($addr2) which is never initially declared. All the other calls are put directly into the $fields array.

$addr2 = $o->getAttribute('billing_address')->getAddress2();
        if (!empty($addr2)) {
            $fields['x_company'] = $o->getAttribute('billing_address')->getAddress1();
            $fields['x_address'] = $addr2;
        } else {
            $fields['x_address'] = $o->getAttribute('billing_address')->getAddress1();
        }


The same type of code (for shipping address) is on line 103.

Type: Discussion
Status: In Progress
thehawkeye
View Replies:
thehawkeye replied on at Permalink Reply
thehawkeye
This is the same problem from an older version of eCommerce (2.8.10) which apparently hasn't been addressed. See:https://www.concrete5.org/marketplace/addons/ecommerce/support/error... from April 28, 2014 at 11:32 AM.
Korvin replied on at Permalink Reply
Korvin
Hi Thehawkeye,
This is tricky because this does not happen with any other ecommerce install that we know of and it doesn't make much sense that the attribute would be conditionally available.

The only way I can see that this could happen is if your session is being lost. It sounds like - from the old thread - this is exacerbated by server load, that sounds to me like your server is not retaining the session files for whatever reason. That said, it'd be nice if we failed with a "Uh oh, your order looks lost" message instead of a fatal error.

To potentially fix this, I would suggest moving your session to the database.
https://www.concrete5.org/documentation/how-tos/developers/handle-se...
thehawkeye replied on at Permalink Reply
thehawkeye
We've been concerned about server load too, so we cut down on the server logs and disabled ssh except for our internal IP address. (We noticed IP addresses we didn't recognize trying to continually ssh which was consuming bursts up to 80% of server cpu.)
thehawkeye replied on at Permalink Reply
thehawkeye
So far two days without any duplicate orders or php errors.
thehawkeye replied on at Permalink Reply
thehawkeye
We had an error this morning @ 10:12:28am. I modified the controller.php and set it up as an override. If we get another error, it will give me an idea of where the code is failing. (If we get no orders, I can just delete the override to go back to default code.)
thehawkeye replied on at Permalink Reply
thehawkeye
Last night we had an error on ->getAddress1(). This is mixed news. The process got through the ->getAddress2() patch which is processed first. I made added some more code to check for a null on ->getAddress1(). Instead of assigning address1 to an empty string like address2 (which is optional) I assigned it to an error message. We'll keep monitoring...
frz replied on at Permalink Reply
frz
I'm not sure there's really much more we can do in an add-on support capacity at this point.
thehawkeye replied on at Permalink Reply
thehawkeye
Authorized.net is making a change in the authentication URL, and now offering three.

"Using Akamai network technology will help decrease latency and improve the reliability of our payment gateway."

Search for "authorized.net akamai"

h t t p s ://community.developer.authorize.net/t5/The-Authorize-Net-Developer-Blog/Important-Authorize-Net-Networking-Change/ba-p/51272
thehawkeye replied on at Permalink Reply
thehawkeye
If we get no more errors, it could be the change to Akamai or the changes in code. I will share the code if we've had no failures after a week. (I don't want to share what doesn't work.)
thehawkeye replied on at Permalink Reply
thehawkeye
We had another error on getCity() for billing. I've now isolated all the ->get() functions within a null check for both billing_address and shipping_address.
thehawkeye replied on at Permalink Reply
thehawkeye
No errors over the weekend after putting in the null check...
thehawkeye replied on at Permalink Reply
thehawkeye
The problem appears to be caused when $o->getAttribute('billing_address'); or $o->getAttribute('shipping_address'); return null.

I've made the following changes in packages/core_commerce/models/payment/methods/authorize_net_aim/controller.php

Replace all code after:
$fields['x_first_name'] = $o->getAttribute('billing_first_name');
$fields['x_last_name'] = $o->getAttribute('billing_last_name');

and before:
$post_data = "";
foreach($fields as $key => $value) {
$post_data .= "$key=" . urlencode($value) . "&";
}// end foreach
$post_data = rtrim($post_data, "& ");

With:
/* below added to test for null billing_address /dka */
        $addr_test = $o->getAttribute('billing_address');
        if (!is_null($addr_test)) {
             $addr1 = $o->getAttribute('billing_address')->getAddress1();
             $addr2 = $o->getAttribute('billing_address')->getAddress2();
            $fields['x_city'] = $o->getAttribute('billing_address')->getCity();
            $fields['x_state'] = $o->getAttribute('billing_address')->getStateProvince();
            $fields['x_zip'] = $o->getAttribute('billing_address')->getPostalCode();
            $fields['x_country'] = $o->getAttribute('billing_address')->getCountry();
        } else {
             $addr1 = "Error: Billing address Not Found";
             $addr2 = "";
            $fields['x_city'] = "Error: Billing address Not Found";
            $fields['x_state'] = "Error: Billing address Not Found";
            $fields['x_zip'] = "Error: Billing address Not Found";

------------------------------------------------------------------------------------------

I've made the following changes in packages/core_commerce/controllers/checkout/shipping/address.php

Replace:
if ($o->getAttribute('shipping_first_name') == $o->getAttribute('billing_first_name')
&& $o->getAttribute('shipping_last_name') == $o->getAttribute('billing_last_name')
&& $o->getAttribute('shipping_address')->__toString() == $o->getAttribute('billing_address')->__toString()
&& $o->getAttribute('shipping_phone') == $o->getAttribute('billing_phone')
) {
$this->set('useBillingAddressForShipping', true);
}

With:
/* below added to test for null shipping_address & billing_address /dka */
     $shipping_addr_test = $o->getAttribute('shipping_address');
     $billing_addr_test = $o->getAttribute('billing_address');
     if ( (!is_null($shipping_addr_test)) && (!is_null($billing_addr_test)) ) {
         if ($o->getAttribute('shipping_first_name') == $o->getAttribute('billing_first_name')
            && $o->getAttribute('shipping_last_name') == $o->getAttribute('billing_last_name')
            && $o->getAttribute('shipping_address')->__toString() == $o->getAttribute('billing_address')->__toString()
            && $o->getAttribute('shipping_phone') == $o->getAttribute('billing_phone')
         ) {
            $this->set('useBillingAddressForShipping', true);
         }
      }
    /* above added to test for null shipping_address & billing_address /dka */
pixo replied on at Permalink Reply
pixo
Did this fix your problem with the fatal error? I've run into this exact same problem and couldn't figure out if it was a coding issue or payment gateway issue. I've got dozens of ecommerce installs, but for some reason this issue only seems to be happening on just one site.
Korvin replied on at Permalink Reply
Korvin
Any clue what you guys are doing that'd cause the shipping attribute or the billing attribute to return null?

Thanks,
Korvin
pixo replied on at Permalink Reply
pixo
The strange thing for this is that the error popped up randomly. A user could submit the order and get the error, hit the back button on their browser and resubmit again and the order would go through. Exact same data submitted both times. I never found an obvious pattern for when the error would come up, because not everyone would get the error.
Korvin replied on at Permalink Reply
Korvin
The fix that hawkeye offers seems a little bit sketchy if that is the case. I'd recommend playing around with disabling mysql query cache and any aggressive PHP opcode cache and see if that helps.

concrete5 Environment Information

# concrete5 Version
5.6.3.1

# concrete5 Packages
Destyle (1.1), eCommerce (2.8.12), eCommerce - UPS Shipping (1.5.8), eCommerce - USPS Shipping (1.4.6), Flat Shipping with Free Shipping by Product Set (1.1), PHP block by ND (1.0), Table-Based Shipping (1.1.0), Whitespace Theme (1.2).

# concrete5 Overrides
controllers/dashboard, elements/checkout, elements/orders, libraries/payment, models/attribute, models/core_commerce, models/events, models/order, single_pages/checkout, single_pages/dashboard

# concrete5 Cache Settings
Block Cache - On
Overrides Cache - On
Full Page Caching - On - If blocks on the particular page allow it.
Full Page Cache Lifetime - Every 6 hours (default setting).

# Server Software
Apache/2.2.29 (Unix) mod_ssl/2.2.29 OpenSSL/1.0.1k DAV/2

# Server API
apache2handler

# PHP Version
5.3.29

# PHP Extensions
apache2handler, bcmath, bz2, Core, ctype, curl, date, dom, ereg, fileinfo, filter, gd, hash, iconv, json, libxml, mhash, mysql, mysqli, mysqlnd, pcre, PDO, pdo_mysql, Phar, Reflection, session, SimpleXML, SPL, standard, tokenizer, xml, xmlreader, xmlwriter, zlib.

# PHP Settings
max_execution_time - 30
log_errors_max_len - 1024
max_file_uploads - 20
max_input_nesting_level - 64
max_input_time - 60
max_input_vars - 1000
memory_limit - 128M
post_max_size - 15M
safe_mode - Off
safe_mode_exec_dir - <i>no value</i>
safe_mode_gid - Off
safe_mode_include_dir - <i>no value</i>
sql.safe_mode - Off
upload_max_filesize - 15M
mysql.max_links - Unlimited
mysql.max_persistent - Unlimited
mysqli.max_links - Unlimited
mysqli.max_persistent - Unlimited
pcre.backtrack_limit - 1000000
pcre.recursion_limit - 100000
session.cache_limiter - nocache
session.gc_maxlifetime - 7200
safe_mode_allowed_env_vars - PHP_
safe_mode_protected_env_vars - LD_LIBRARY_PATH

Browser User-Agent String

Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:39.0) Gecko/20100101 Firefox/39.0

Hide Post Content

This will replace the post content with the message: "Content has been removed by an Administrator"

Hide Content

Request Refund

You may not request a refund that is not currently owned by you.