How to cancel orders using payment method in magen

2019-08-04 05:12发布

问题:

I am creating an Open Source Extension for Magento. Its in very early stages. I am struggling with cancel orders problem. I found some solution here

Magento - How can I run code when my order is canceled or refunded.

But whenever I cancel an order it calls neither void (in case of only Authorize payment action) nor refund (in case of authorize-capture payment action).

When I use capture-refund, It says the order cannot be cancelled.

When I use authorize-void, It say's the order have been cancelled. But the Void() function wasn't called at all. I kept some Mage::Log() functions inside. Which are not shown in Log file.

I don't understand what is wrong.

Here is the code. This is payment method model

<?php 
class Package_Cashondelivery_Model_Createorder extends Mage_Payment_Model_Method_Abstract
{
    protected $_code = 'cashondelivery';
    protected $_canCapture = true;
    protected $_canUseCheckout = true;
    protected $_canFetchTransactionInfo     = true;
    protected $_isGateway                   = true;
    protected $_canUseInternal = true;
    protected $_canVoid    = true;
    protected $_canRefund = true;

    public function validate()
    {

        $paymentInfo = $this->getInfoInstance();
         if ($paymentInfo instanceof Mage_Sales_Model_Order_Payment) {
             $postCode = $paymentInfo->getOrder()->getBillingAddress()->getPostcode();

         } 
         else {
             $postCode = $paymentInfo->getQuote()->getBillingAddress()->getPostcode();
         }
         $res=Api->validatePostCode($postCode);
         $r = $res=='false'? FALSE : TRUE; 
         if (!$r) {
             Mage::throwException($this->_getHelper()->__('Sorry ! Service is not available in your area'));
         }
         return $this;
    }

    public function authorize(Varien_Object $payment, $amount)
    {
        -------------------------------
        -------------------------------
        -------------------------------
        #This is working fine
        $transactionId = Api->someCall();
        $payment->setTransactionId();
       ------------------------------- 
       -------------------------------
       -------------------------------
       -------------------------------
       -------------------------------
       -------------------------------
        return $this;
    }

    public function void(Varien_Object $payment)
    {
        if (!$this->canVoid($payment)) {
            Mage::throwException($this->_getHelper()->__('Void action is not available.'));
        }
        -------------------------------
        -------------------------------
        -------------------------------
        -------------------------------
        Mage::Log('Starting Void here....');
        $transactionId = $Payment->getTransactionId();
        Api->cancelOrder($transactionId);
        return $this;
        -------------------------------
        -------------------------------
        -------------------------------
    }
}
?>

Here is config file.

<?xml version="1.0"?>
<config>
    <modules>
       <Package_Cashondelivery>
<!-- declare module's version information for database updates -->
          <version>0.1.0</version>
       </Package_Cashondelivery>
    </modules>
    <global>
<!-- declare model group for new module -->
        <models>
<!-- model group alias to be used in Mage::getModel('newmodule/...') -->
            <cashondelivery>
<!-- base class name for the model group -->
                <class>Package_Cashondelivery_Model</class>
            </cashondelivery>    
        </models>
        <helpers>
            <cashondelivery>
                <class>Package_Cashondelivery_Helper</class>
            </cashondelivery>
        </helpers> 
<!-- declare resource setup for new module -->
        <resources>
<!-- resource identifier -->
            <cashondelivery_setup>
<!-- specify that this resource is a setup resource and used for upgrades -->
                <setup>
<!-- which module to look for install/upgrade files in -->
                    <module>Package_Cashondelivery</module>
                </setup>
<!-- specify database connection for this resource -->
                <connection>
<!-- do not create new connection, use predefined core setup connection -->
                    <use>core_setup</use>
                </connection>
            </cashondelivery_setup>
            <cashondelivery_write>
                <connection>
                  <use>core_write</use>
                </connection>
            </cashondelivery_write>
            <cashondelivery_read>
               <connection>
                <use>core_read</use>
              </connection>
            </cashondelivery_read>
        </resources>
    </global>
<!-- declare default configuration values for this module -->
    <default>
        <payment>
            <cashondelivery>
                <active>1</active>
                <model>cashondelivery/createorder</model>
                <order_status>Processing</order_status>
                <payment_action>authorize</payment_action>
                <title>Cash On Delivery</title>
                <example_uri>services.example.com</example_uri>
            </cashondelivery>
         </payment>
    </default>
</config>

Anybody has any idea why this happens and how to resolve.

回答1:

Sadly I don't have enough "experience" to just comment, so I'll post this as an answer instead.

Can you verify the order is in the proper state before canceling? For example, some orders are auto processed, like software downloads. Credit card charging, and product distribution can all be done automatically, then I doubt it lets you cancel. Can you verify the order is still pending?



回答2:

You should only be able to 'Cancel' or 'Void' an order that has not been captured. i.e. an order that doesn't have an associated invoice.

If you want to refund a captured order, then this should be done by creating a creditmemo on the invoice.

For the issue of your payment method's void function not being called - you should set up an IDE like Netbeans, using X-Debug, and put a break point in the first line of the cancelAction and voidPaymentAction functions in Mage_Adminhtml_Sales_OrderController. This way you can step through the code and see where the issue is.

For example, the route to void should be something like...

Mage_Adminhtml_Sales_OrderController->voidPaymentAction:629
Mage_Sales_Model_Order_Payment->void:602
Mage_Sales_Model_Order_Payment->_void:1088
Package_Cashondelivery_Model_Createorder->void:

So if you don't want to get into using a proper debugging environment, then put your log statements along that path and check all the conditions are valid to call your payment method's void function.



回答3:

The problem is that Magento indeed does not call either Void, nor Refund when you press cancel. When you press void it runs the void method, and when you click on refund it calls the refund method. And guess what, when you press on cancel, it actually calls the cancel method.

I agree that when you press cancel you actually want to void the authorization, but it comes handy to have separate methods just in case you would like to do something else too. So you could do something like this:

/*
 * Your class stuff
 */

public function cancel(Varien_Object $payment){

    // void the order if canceled
    $this->void($payment);

    return $this;
}

public function void(Varien_Object $payment){

    /* Whatever you call to void a payment in your gateway */

}