0
votes

I'm getting the following error: Fatal error: Call to a member function getBillingAddress() on a non-object in /data/web/public/app/code/core/Mage/Payment/Model/Method/Abstract.php on line 689

I'm on Magento 1.9.1.1. Also have this problem with a completely different magento installation on a different server. Both same versions 1.9.1.1.

This error happens, when from the Manage Customers page, you'll want to create an order for a specific customer. Happens with any registerd customer.

Could this be a core magento bug? And how to fix it?

All help very much appreciated!

Abstract.php

/**
* Payment method abstract model
*
* @author      Magento Core Team <[email protected]>
*/
abstract class Mage_Payment_Model_Method_Abstract extends Varien_Object
{
const ACTION_ORDER             = 'order';
const ACTION_AUTHORIZE         = 'authorize';
const ACTION_AUTHORIZE_CAPTURE = 'authorize_capture';

const STATUS_UNKNOWN    = 'UNKNOWN';
const STATUS_APPROVED   = 'APPROVED';
const STATUS_ERROR      = 'ERROR';
const STATUS_DECLINED   = 'DECLINED';
const STATUS_VOID       = 'VOID';
const STATUS_SUCCESS    = 'SUCCESS';

/**
 * Bit masks to specify different payment method checks.
 * @see Mage_Payment_Model_Method_Abstract::isApplicableToQuote
 */
const CHECK_USE_FOR_COUNTRY       = 1;
const CHECK_USE_FOR_CURRENCY      = 2;
const CHECK_USE_CHECKOUT          = 4;
const CHECK_USE_FOR_MULTISHIPPING = 8;
const CHECK_USE_INTERNAL          = 16;
const CHECK_ORDER_TOTAL_MIN_MAX   = 32;
const CHECK_RECURRING_PROFILES    = 64;
const CHECK_ZERO_TOTAL            = 128;

protected $_code;
protected $_formBlockType = 'payment/form';
protected $_infoBlockType = 'payment/info';

/**
 * Payment Method features
 * @var bool
 */
protected $_isGateway                   = false;
protected $_canOrder                    = false;
protected $_canAuthorize                = false;
protected $_canCapture                  = false;
protected $_canCapturePartial           = false;
protected $_canCaptureOnce              = false;
protected $_canRefund                   = false;
protected $_canRefundInvoicePartial     = false;
protected $_canVoid                     = false;
protected $_canUseInternal              = true;
protected $_canUseCheckout              = true;
protected $_canUseForMultishipping      = true;
protected $_isInitializeNeeded          = false;
protected $_canFetchTransactionInfo     = false;
protected $_canReviewPayment            = false;
protected $_canCreateBillingAgreement   = false;
protected $_canManageRecurringProfiles  = true;
/**
 * TODO: whether a captured transaction may be voided by this gateway
 * This may happen when amount is captured, but not settled
 * @var bool
 */
protected $_canCancelInvoice        = false;

/**
 * Fields that should be replaced in debug with '***'
 *
 * @var array
 */
protected $_debugReplacePrivateDataKeys = array();

public function __construct()
{

}

/**
 * Check order availability
 *
 * @return bool
 */
public function canOrder()
{
    return $this->_canOrder;
}

/**
 * Check authorise availability
 *
 * @return bool
 */
public function canAuthorize()
{
    return $this->_canAuthorize;
}

/**
 * Check capture availability
 *
 * @return bool
 */
public function canCapture()
{
    return $this->_canCapture;
}

/**
 * Check partial capture availability
 *
 * @return bool
 */
public function canCapturePartial()
{
    return $this->_canCapturePartial;
}

/**
 * Check whether capture can be performed once and no further capture possible
 *
 * @return bool
 */
public function canCaptureOnce()
{
    return $this->_canCaptureOnce;
}

/**
 * Check refund availability
 *
 * @return bool
 */
public function canRefund()
{
    return $this->_canRefund;
}

/**
 * Check partial refund availability for invoice
 *
 * @return bool
 */
public function canRefundPartialPerInvoice()
{
    return $this->_canRefundInvoicePartial;
}

/**
 * Check void availability
 *
 * @param   Varien_Object $payment
 * @return  bool
 */
public function canVoid(Varien_Object $payment)
{
    return $this->_canVoid;
}

/**
 * Using internal pages for input payment data
 * Can be used in admin
 *
 * @return bool
 */
public function canUseInternal()
{
    return $this->_canUseInternal;
}

/**
 * Can be used in regular checkout
 *
 * @return bool
 */
public function canUseCheckout()
{
    return $this->_canUseCheckout;
}

/**
 * Using for multiple shipping address
 *
 * @return bool
 */
public function canUseForMultishipping()
{
    return $this->_canUseForMultishipping;
}

/**
 * Can be edit order (renew order)
 *
 * @return bool
 */
public function canEdit()
{
    return true;
}

/**
 * Check fetch transaction info availability
 *
 * @return bool
 */
public function canFetchTransactionInfo()
{
    return $this->_canFetchTransactionInfo;
}

/**
 * Check whether payment method instance can create billing agreements
 *
 * @return bool
 */
public function canCreateBillingAgreement()
{
    return $this->_canCreateBillingAgreement;
}

/**
 * Fetch transaction info
 *
 * @param Mage_Payment_Model_Info $payment
 * @param string $transactionId
 * @return array
 */
public function fetchTransactionInfo(Mage_Payment_Model_Info $payment, $transactionId)
{
    return array();
}

/**
 * Retrieve payment system relation flag
 *
 * @return bool
 */
public function isGateway()
{
    return $this->_isGateway;
}

/**
 * flag if we need to run payment initialize while order place
 *
 * @return bool
 */
public function isInitializeNeeded()
{
    return $this->_isInitializeNeeded;
}

/**
 * To check billing country is allowed for the payment method
 *
 * @return bool
 */
public function canUseForCountry($country)
{
    /*
    for specific country, the flag will set up as 1
    */
    if($this->getConfigData('allowspecific')==1){
        $availableCountries = explode(',', $this->getConfigData('specificcountry'));
        if(!in_array($country, $availableCountries)){
            return false;
        }

    }
    return true;
}

/**
 * Check method for processing with base currency
 *
 * @param string $currencyCode
 * @return boolean
 */
public function canUseForCurrency($currencyCode)
{
    return true;
}

/**
 * Check manage billing agreements availability
 *
 * @return bool
 */
public function canManageBillingAgreements()
{
    return ($this instanceof Mage_Payment_Model_Billing_Agreement_MethodInterface);
}

/**
 * Whether can manage recurring profiles
 *
 * @return bool
 */
public function canManageRecurringProfiles()
{
    return $this->_canManageRecurringProfiles
           && ($this instanceof Mage_Payment_Model_Recurring_Profile_MethodInterface);
}

/**
 * Retrieve model helper
 *
 * @return Mage_Payment_Helper_Data
 */
protected function _getHelper()
{
    return Mage::helper('payment');
}

/**
 * Retrieve payment method code
 *
 * @return string
 */
public function getCode()
{
    if (empty($this->_code)) {
        Mage::throwException(Mage::helper('payment')->__('Cannot retrieve the payment method code.'));
    }
    return $this->_code;
}

/**
 * Retrieve block type for method form generation
 *
 * @return string
 */
public function getFormBlockType()
{
    return $this->_formBlockType;
}

/**
 * Retrieve block type for display method information
 *
 * @return string
 */
public function getInfoBlockType()
{
    return $this->_infoBlockType;
}

/**
 * Retrieve payment iformation model object
 *
 * @return Mage_Payment_Model_Info
 */
public function getInfoInstance()
{
    $instance = $this->getData('info_instance');
    if (!($instance instanceof Mage_Payment_Model_Info)) {
        Mage::throwException(Mage::helper('payment')->__('Cannot retrieve the payment information object instance.'));
    }
    return $instance;
}

/**
 * Validate payment method information object
 *
 * @return Mage_Payment_Model_Abstract
 */
public function validate()
{
     /**
      * to validate payment method is allowed for billing country or not
      */
     $paymentInfo = $this->getInfoInstance();
     if ($paymentInfo instanceof Mage_Sales_Model_Order_Payment) {
         $billingCountry = $paymentInfo->getOrder()->getBillingAddress()->getCountryId();
     } else {
         $billingCountry = $paymentInfo->getQuote()->getBillingAddress()->getCountryId();
     }
     if (!$this->canUseForCountry($billingCountry)) {
         Mage::throwException(Mage::helper('payment')->__('Selected payment type is not allowed for billing country.'));
     }
     return $this;
}

/**
 * Order payment abstract method
 *
 * @param Varien_Object $payment
 * @param float $amount
 *
 * @return Mage_Payment_Model_Abstract
 */
public function order(Varien_Object $payment, $amount)
{
    if (!$this->canOrder()) {
        Mage::throwException(Mage::helper('payment')->__('Order action is not available.'));
    }
    return $this;
}

/**
 * Authorize payment abstract method
 *
 * @param Varien_Object $payment
 * @param float $amount
 *
 * @return Mage_Payment_Model_Abstract
 */
public function authorize(Varien_Object $payment, $amount)
{
    if (!$this->canAuthorize()) {
        Mage::throwException(Mage::helper('payment')->__('Authorize action is not available.'));
    }
    return $this;
}

/**
 * Capture payment abstract method
 *
 * @param Varien_Object $payment
 * @param float $amount
 *
 * @return Mage_Payment_Model_Abstract
 */
public function capture(Varien_Object $payment, $amount)
{
    if (!$this->canCapture()) {
        Mage::throwException(Mage::helper('payment')->__('Capture action is not available.'));
    }

    return $this;
}

/**
 * Set capture transaction ID to invoice for informational purposes
 * @param Mage_Sales_Model_Order_Invoice $invoice
 * @param Mage_Sales_Model_Order_Payment $payment
 * @return Mage_Payment_Model_Method_Abstract
 */
public function processInvoice($invoice, $payment)
{
    $invoice->setTransactionId($payment->getLastTransId());
    return $this;
}

/**
 * Set refund transaction id to payment object for informational purposes
 * Candidate to be deprecated:
 * there can be multiple refunds per payment, thus payment.refund_transaction_id doesn't make big sense
 *
 * @param Mage_Sales_Model_Order_Invoice $invoice
 * @param Mage_Sales_Model_Order_Payment $payment
 * @return Mage_Payment_Model_Method_Abstract
 */
public function processBeforeRefund($invoice, $payment)
{
    $payment->setRefundTransactionId($invoice->getTransactionId());
    return $this;
}

/**
 * Refund specified amount for payment
 *
 * @param Varien_Object $payment
 * @param float $amount
 *
 * @return Mage_Payment_Model_Abstract
 */
public function refund(Varien_Object $payment, $amount)
{

    if (!$this->canRefund()) {
        Mage::throwException(Mage::helper('payment')->__('Refund action is not available.'));
    }


    return $this;
}

/**
 * Set transaction ID into creditmemo for informational purposes
 * @param Mage_Sales_Model_Order_Creditmemo $creditmemo
 * @param Mage_Sales_Model_Order_Payment $payment
 * @return Mage_Payment_Model_Method_Abstract
 */
public function processCreditmemo($creditmemo, $payment)
{
    $creditmemo->setTransactionId($payment->getLastTransId());
    return $this;
}

/**
 * Cancel payment abstract method
 *
 * @param Varien_Object $payment
 *
 * @return Mage_Payment_Model_Abstract
 */
public function cancel(Varien_Object $payment)
{
    return $this;
}

/**
 * @deprecated after 1.4.0.0-alpha3
 * this method doesn't make sense, because invoice must not void entire authorization
 * there should be method for invoice cancellation
 * @param Mage_Sales_Model_Order_Invoice $invoice
 * @param Mage_Sales_Model_Order_Payment $payment
 * @return Mage_Payment_Model_Method_Abstract
 */
public function processBeforeVoid($invoice, $payment)
{
    $payment->setVoidTransactionId($invoice->getTransactionId());
    return $this;
}

/**
 * Void payment abstract method
 *
 * @param Varien_Object $payment
 *
 * @return Mage_Payment_Model_Abstract
 */
public function void(Varien_Object $payment)
{
    if (!$this->canVoid($payment)) {
        Mage::throwException(Mage::helper('payment')->__('Void action is not available.'));
    }
    return $this;
}

/**
 * Whether this method can accept or deny payment
 *
 * @param Mage_Payment_Model_Info $payment
 *
 * @return bool
 */
public function canReviewPayment(Mage_Payment_Model_Info $payment)
{
    return $this->_canReviewPayment;
}

/**
 * Attempt to accept a payment that us under review
 *
 * @param Mage_Payment_Model_Info $payment
 * @return bool
 * @throws Mage_Core_Exception
 */
public function acceptPayment(Mage_Payment_Model_Info $payment)
{
    if (!$this->canReviewPayment($payment)) {
        Mage::throwException(Mage::helper('payment')->__('The payment review action is unavailable.'));
    }
    return false;
}

/**
 * Attempt to deny a payment that us under review
 *
 * @param Mage_Payment_Model_Info $payment
 * @return bool
 * @throws Mage_Core_Exception
 */
public function denyPayment(Mage_Payment_Model_Info $payment)
{
    if (!$this->canReviewPayment($payment)) {
        Mage::throwException(Mage::helper('payment')->__('The payment review action is unavailable.'));
    }
    return false;
}

/**
 * Retrieve payment method title
 *
 * @return string
 */
public function getTitle()
{
    return $this->getConfigData('title');
}

/**
 * Retrieve information from payment configuration
 *
 * @param string $field
 * @param int|string|null|Mage_Core_Model_Store $storeId
 *
 * @return mixed
 */
public function getConfigData($field, $storeId = null)
{
    if (null === $storeId) {
        $storeId = $this->getStore();
    }
    $path = 'payment/'.$this->getCode().'/'.$field;
    return Mage::getStoreConfig($path, $storeId);
}

/**
 * Assign data to info model instance
 *
 * @param   mixed $data
 * @return  Mage_Payment_Model_Info
 */
public function assignData($data)
{
    if (is_array($data)) {
        $this->getInfoInstance()->addData($data);
    }
    elseif ($data instanceof Varien_Object) {
        $this->getInfoInstance()->addData($data->getData());
    }
    return $this;
}

/**
 * Parepare info instance for save
 *
 * @return Mage_Payment_Model_Abstract
 */
public function prepareSave()
{
    return $this;
}

/**
 * Check whether payment method can be used
 *
 * TODO: payment method instance is not supposed to know about quote
 *
 * @param Mage_Sales_Model_Quote|null $quote
 *
 * @return bool
 */
public function isAvailable($quote = null)
{
    $checkResult = new StdClass;
    $isActive = (bool)(int)$this->getConfigData('active', $quote ? $quote->getStoreId() : null);
    $checkResult->isAvailable = $isActive;
    $checkResult->isDeniedInConfig = !$isActive; // for future use in observers
    Mage::dispatchEvent('payment_method_is_active', array(
        'result'          => $checkResult,
        'method_instance' => $this,
        'quote'           => $quote,
    ));

    if ($checkResult->isAvailable && $quote) {
        $checkResult->isAvailable = $this->isApplicableToQuote($quote, self::CHECK_RECURRING_PROFILES);
    }
    return $checkResult->isAvailable;
}

/**
 * Check whether payment method is applicable to quote
 * Purposed to allow use in controllers some logic that was implemented in blocks only before
 *
 * @param Mage_Sales_Model_Quote $quote
 * @param int|null $checksBitMask
 * @return bool
 */
public function isApplicableToQuote($quote, $checksBitMask)
{
    if ($checksBitMask & self::CHECK_USE_FOR_COUNTRY) {
        if (!$this->canUseForCountry($quote->getBillingAddress()->getCountry())) {
            return false;
        }
    }
    if ($checksBitMask & self::CHECK_USE_FOR_CURRENCY) {
        if (!$this->canUseForCurrency($quote->getStore()->getBaseCurrencyCode())) {
            return false;
        }
    }
    if ($checksBitMask & self::CHECK_USE_CHECKOUT) {
        if (!$this->canUseCheckout()) {
            return false;
        }
    }
    if ($checksBitMask & self::CHECK_USE_FOR_MULTISHIPPING) {
        if (!$this->canUseForMultishipping()) {
            return false;
        }
    }
    if ($checksBitMask & self::CHECK_USE_INTERNAL) {
        if (!$this->canUseInternal()) {
            return false;
        }
    }
    if ($checksBitMask & self::CHECK_ORDER_TOTAL_MIN_MAX) {
        $total = $quote->getBaseGrandTotal();
        $minTotal = $this->getConfigData('min_order_total');
        $maxTotal = $this->getConfigData('max_order_total');
        if (!empty($minTotal) && $total < $minTotal || !empty($maxTotal) && $total > $maxTotal) {
            return false;
        }
    }
    if ($checksBitMask & self::CHECK_RECURRING_PROFILES) {
        if (!$this->canManageRecurringProfiles() && $quote->hasRecurringItems()) {
            return false;
        }
    }
    if ($checksBitMask & self::CHECK_ZERO_TOTAL) {
        $total = $quote->getBaseSubtotal() + $quote->getShippingAddress()->getBaseShippingAmount();
        if ($total < 0.0001 && $this->getCode() != 'free'
            && !($this->canManageRecurringProfiles() && $quote->hasRecurringItems())
        ) {
            return false;
        }
    }
    return true;
}

/**
 * Method that will be executed instead of authorize or capture
 * if flag isInitializeNeeded set to true
 *
 * @param string $paymentAction
 * @param object $stateObject
 *
 * @return Mage_Payment_Model_Abstract
 */
public function initialize($paymentAction, $stateObject)
{
    return $this;
}

/**
 * Get config payment action url
 * Used to universalize payment actions when processing payment place
 *
 * @return string
 */
public function getConfigPaymentAction()
{
    return $this->getConfigData('payment_action');
}

/**
 * Log debug data to file
 *
 * @param mixed $debugData
 */
protected function _debug($debugData)
{
    if ($this->getDebugFlag()) {
        Mage::getModel('core/log_adapter', 'payment_' . $this->getCode() . '.log')
           ->setFilterDataKeys($this->_debugReplacePrivateDataKeys)
           ->log($debugData);
    }
}

/**
 * Define if debugging is enabled
 *
 * @return bool
 */
public function getDebugFlag()
{
    return $this->getConfigData('debug');
}

/**
 * Used to call debug method from not Payment Method context
 *
 * @param mixed $debugData
 */
public function debugData($debugData)
{
    $this->_debug($debugData);
}
}
1
looks like the payment model doesn't get instantiated, what did you change recently? This is not a core magento bug. - cleong
What payment method is used for this order? The core file you referenced is not the root cause. - Christoffer Bubach
We are using the bank transfer payment method. - Feggel

1 Answers

0
votes

I had similar issue in success page, so i load object by loadByIncrementId function, it worked for me

$orderId = '600008796';
$order = Mage::getModel('sales/order')->loadByIncrementId($orderId);

then you can access to billing/shipping address by object

$order->getBillingAddress()->getFirstname();
$order->getBillingAddress()->getEmail();
$order->getShippingAddress()->getFirstname();
$order->getShippingAddress()->getEmail();