0

I have a current script that uses a mishmash of pure Magento methods and the API. I'm trying to convert it all to straight Magento methods, but I'm having an issue to get the payment method to stay. Some of the processing is done in one script, which then passes the quote ID to a class.

The first part:

$paymentMethod =    array(
    'method' => 'verisign',
    'cc_cid' => $_REQUEST['cc_verify'],
    'cc_owner' => $_REQUEST['cc_name'],
    'cc_number' => $_REQUEST['cc_number'],
    'cc_type' => $_REQUEST['cc_type'],
    'cc_exp_year' => $_REQUEST['expire_year'],
    'cc_exp_month' => $_REQUEST['expire_month']
);

try {
    $payment = $quote->getPayment();
    $payment->importData($paymentMethod);
    $quote->getBillingAddress()->setPaymentMethod($payment->getMethod());
    $quote->getShippingAddress()->setPaymentMethod($payment->getMethod());
    $quote->setPayment($payment);
    $quote->collectTotals()->save();

    $err = $OTOrder->completeOrder($shopping_cart_id,$paymentMethod);

..... }

and the relevant part of the OTOrder->completeOrder function:

$quote = Mage::getModel('sales/quote')->load($shopping_cart_id); // shopping_cart_id is the quote ID
// setting the shipping methods and other order-specific settings here

$payment=$quote->getPayment();
Mage::log('1');
$convertQuote = Mage::getSingleton('sales/convert_quote');
Mage::log('2');
$order = $convertQuote->addressToOrder($quote->getShippingAddress());
Mage::log('3');
$order->setPayment($convertQuote->paymentToOrderPayment($payment));
Mage::log('4');

The script stops at addressToOrder with the error Uncaught exception 'Mage_Core_Exception' with message 'The requested Payment Method is not available.' Am I perhaps doing something in the wrong order somewhere, or missing a crucial setp?

1

Instead of re-loading the quote inside of OTOrder, I just created the quote as a variable of OTOrder, and just referenced it wherever I needed it. This also allowed me to bring more of the checkout methods directly into the class.

| improve this answer | |
1

There's two places in the Magento source code that use that exception.

$ ack 'The requested Payment Method is not available'
app/code/core/Mage/Payment/Model/Info.php
82:            Mage::throwException(Mage::helper('payment')->__('The requested Payment Method is not available.'));

app/code/core/Mage/Sales/Model/Quote/Payment.php
151:            Mage::throwException(Mage::helper('sales')->__('The requested Payment Method is not available.'));

I'm going to guess yours is the later (although this advice will apply to the former). If you look at where the exception is thrown

$method = $this->getMethodInstance();
//...
if (!$method->isAvailable($this->getQuote())) {
    Mage::throwException(Mage::helper('sales')->__('The requested Payment Method is not available.'));
}

You can see the payment method model's isAvailable return false when passed the quote object. This is what causes your exception to be thrown

Assuming you have a standard configuration, the verisign payment model is a paypal/payflowpro model.

<!-- File: app/code/core/Mage/Paypal/etc/config.xml -->
<verisign>
    <model>paypal/payflowpro</model>
    <title>Payflow Pro</title>
    <payment_action>Authorization</payment_action>
    ...

This resolves to (again, assuming standard configuration), the model class Mage_Paypal_Model_Payflowpro. Looking at the isAvailable method

#File: app/code/core/Mage/Paypal/Model/Payflowpro.php
public function isAvailable($quote = null)
{
    $storeId = Mage::app()->getStore($this->getStore())->getId();
    $config = Mage::getModel('paypal/config')->setStoreId($storeId);
    if (parent::isAvailable($quote) && $config->isMethodAvailable($this->getCode())) {
        return true;
    }
    return false;
}

You can immediatly see one reason this method may return false is the payment is configured as unavaiabled in the backend. You'll also want to checkout the parent class method definitions

#File: app/code/core/Mage/Payment/Model/Method/Cc.php
public function isAvailable($quote = null)
{
    return $this->getConfigData('cctypes', ($quote ? $quote->getStoreId() : null))
        && parent::isAvailable($quote);
}

#File: app/code/core/Mage/Payment/Model/Method/Abstract.php
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,
    ));

    // disable method if it cannot implement recurring profiles management and there are recurring items in quote
    if ($checkResult->isAvailable) {
        $implementsRecurring = $this->canManageRecurringProfiles();
        // the $quote->hasRecurringItems() causes big performance impact, thus it has to be called last
        if ($quote && !$implementsRecurring && $quote->hasRecurringItems()) {
            $checkResult->isAvailable = false;
        }
    }
    return $checkResult->isAvailable;
}

Somewhre in here your code in your system is triggering a return false. Find that code, and you'll find the reason.

| improve this answer | |
  • 1
    Actually, I found that the method was not saving to the quote. I could tell by logging $payment->getData() inside of the OTOrder, and it only gave me the quote ID. getMethod() was empty. – aynber Aug 13 '13 at 17:44
0

write

$payment->setMethod($payment->getMethod());

instead of these two lines

$quote->getBillingAddress()->setPaymentMethod($payment->getMethod());
$quote->getShippingAddress()->setPaymentMethod($payment->getMethod());
| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.