Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Magento Custom Payment Gateway not firing 'authorize' or 'capture' methods

Tags:

php

magento

So, horray - I'm attempting to create a new custom Payment Gateway. It's designed to do auth/capture via a third-party API, but does NOT need to redirect to the third-party site.

From my understanding, when an order is placed/finalized in Magento, and the gateway is set to "Authorize and Capture", it should be firing off the 'capture' method from the gateway model. Currently, it's not doing this.

Of course, if I specifically capture from the Admin Order view, it'll attempt to capture, but this needs to happen immediately upon checkout (and again, it's my understanding that it already should).

In my gateway Model, I have the following (truncated for readability):

<?php
class Example_Gateway_Model_Payment extends Mage_Payment_Model_Method_Cc
{
    protected $_code = 'example';

    protected $_isGateway = true;
    protected $_canAuthorize = true;
    protected $_canCapture = true;
    protected $_canUseInternal = true;
    protected $_canUseCheckout = true;

    // This is an empty block class that extends Mage_Payment_Block_Form_Cc
    protected $_formBlockType = 'example/form_example';

    public function authorize(Varien_Object $payment, $amount)
    {
        Mage::log('Authorizing!');
    }

    public function capture(Varien_Object $payment, $amount)
    {
        Mage::log('** Capturing **');
        // Third-party API stuff would go here, with exceptions being thrown if the gateway determines they've provided an invalid card, etc.
    }

    public function assignData($data)
    {
        Mage::log('Assigning Data');
    }
}

This Payment model itself definitely works - I get logging output for assignData() and validate(), as well as __construct() if I add it. But no matter what I do, neither the capture or authorize methods fire when actually placing the order.

My config.xml reads somewhat like this:

<?xml version="1.0"?>
<config>
    <modules>
        <Example_Gateway>
            <version>0.0.5</version>
        </Example_Gateway>
    </modules>
    <global>
        <blocks>
            <gateway>
                <class>Example_Gateway_Block</class>
            </gateway>
        </blocks>
        <models>
            <gateway>
                <class>Example_Gateway_Model</class>
            </gateway>
        </models>
        <helpers>
            <gateway>
                <class>Example_Gateway_Helper</class>
            </gateway>
        </helpers>
    </global>
    <frontend>
      <!-- Snip.. Nothing special here -->
    </frontend>
    <default>
        <payment>
            <gateway>
                <sort_order>0</sort_order>
                <model>gateway/payment</model>
                <enabled>1</enabled>
                <order_staus>processing</order_status>
                <payment_action>authorize_capture</payment_action>
                <cctypes>VI,MC,AE,DI</cctypes>
                <useccv>1</useccv>
            </gateway>
        </payment>
    </default>
</config>

I don't believe there's a need for a resource model as I don't need any additional tables; my expectation is that it will simply use sales_flat_order_payment and related tables to store any gateway-related/-provided data (txn id, etc)

Similarly, I'm simply extending the default CC block to get the standard payment form.

What am I missing? It has to be something small and simple that I'm overlooking.

Thanks in advance!


UPDATE: So far, I have implemented a workaround that uses an observer to the checkout_type_onepage_save_order event that calls the capture() method manually - but I'm pretty sure this is not the right way to go.

I'm not wrong in thinking that Magento should automatically call capture() upon the initial order save, if the gateway is set to authorize_capture, right..?

like image 658
Morgon Avatar asked May 30 '12 18:05

Morgon


2 Answers

Solved! You need this:

protected $_isInitializeNeeded      = false;

I have NO IDEA why this is necessary, but at this point I've given up trying to figure out the why of magento in favor of actually getting things done. I had the exact same problem as you, and when I traced it through the source code I found that Payment.php was not calling _authorize when isInitializeNeeded returned true. So, stick that line in your model, and it will work.

like image 154
Benubird Avatar answered Oct 12 '22 04:10

Benubird


I think the method should be : "authorize_capture" and not "capture" as stated in the config

<payment_action>authorize_capture</payment_action>

like that:

public function authorize_capture(Varien_Object $payment, $amount)
{
    Mage::log('** Capturing **');
    // Third-party API stuff would go here, with exceptions being thrown if the gateway determines they've provided an invalid card, etc.
}

i had a similar problem that the "authorize" method was not fired at all because "authorize_action" was empty. I was able to solve this by hardcoding it in the method itself. "getConfigPaymentAction" is called to get the authorize method.

public function getConfigPaymentAction() {
    return 'authorize';
} 
like image 40
Dimitri L. Avatar answered Oct 12 '22 03:10

Dimitri L.