4
votes

For one of my Magento module I need to catch the event “any order is defined as paid”. So I found that the associated event is sales_order_payment_pay. Ok seems to fit perfectly with my needs.

I’m a Magento dev, not a merchant and, for the moment, I’ve never put a Magento instance online and in production. So the payment workflow is quite dark to me. I used to select “Check/Money Order” as payment method during my tests.

The problem is : I need to catch this event (sales_order_payment_pay) but it seems I can’t trigger it and never enter in my observer function. I have currently 2 payment method, check/money order and credit card. For the first one, the merchant needs to validate the payment in the backend and I red it’s the moment when he creates the invoice. So I tried it but the event is never triggered. For the second one, it’s more difficult : as I am in dev mode, I don’t know how to validate payment via credit card. I found a number for MasterCard online who allows tests in Magento, but in the back end, the total paid ammound is still equal to zero. So after order submission, no event triggered (seems quite logical) and when I create the invoice, still no event triggered.

Can you help me to understand a little more the payment process and to catch any order paid ? I can’t find any information or documentation about it.

PS : The aim of my module is to catch the event place order or payment paid and generate an XML file for data export. The first one with place order is already developed.

2

2 Answers

2
votes

This topic seems a little tricky, so I will share my vision of payment methods and order lifecycle.

Alan Storm's vision

First of all I invite you to see this topics by one of the most famous Magento blogger, Alan Storm.

Here is how I think it’s working :

Case 1 : Order with an online payment (Paypal, credit card, etc ...), payment accepted

Order validated by Client -> order created by Magento -> status pending_payment
Order payed online by Client -> payment validated by Payment Service -> payment OK -> invoice created by Magento -> status pending_payment (not sure about this point).
Order shipped by merchant -> shippig coupon created by Magento -> status complete

Case 2 : Order with an online payment (Paypal, credit card, etc ...), payment refused

Order validated by Client -> order created by Magento -> status pending_payment
Order payed online by Client -> payment refused by Payment Service -> Order cancelled by Magento -> status canceled

Case 3 : Order with an offline payment (check/money order, selling coupon, etc ...). The merchant invoices before shipping

Order validated by Client -> order created by Magento -> status pending
Order payed offline by Client -> payment received by Merchant -> order invoiced by Merchant -> invoice created by Magento -> status processing
Order shipped by Merchant -> shipping coupon created by Magento -> status complete

Case 4 : Order with an offline payment (check/money order, selling coupon, etc ...). The merchant ships before invoicing

Order validated by Client -> order created by Magento -> status pending
Order payed offline by Client -> order shipped by Merchant -> shipping coupon created by Magento -> status processing
Order invoiced by Merchant -> invoice created by Magento -> status processing

Hope this topic will help someone in the future.
Let me know if you need some more information after that.

0
votes

I use as follows:

1 - app/code/loca/Packagename/Modulename/etc/config.xml

<config>
<global>
    <models>
        <sales>
            <rewrite>
                <order>Packagename_Modulename_Model_Rewrite_Order</order>
            </rewrite>
        </sales>
        <sales_resource>
            <rewrite>
                <quote>Packagename_Modulename_Model_Rewrite_Resource_Sales_Quote</quote>
            </rewrite>
        </sales_resource>
        <modelrewrite>
            <class>Packagename_Modulename_Model_Rewrite</class>
        </modelrewrite>
    </models>        
    <events>
        <packagename_modulename_order_status_change>
            <observers>
                <packagename_modulename_model_rewrite>
                    <type>singleton</type>
                    <class>modelrewrite/observer</class>
                    <method>changeStateOrder</method>
                </packagename_modulename_model_rewrite>
            </observers>
        </packagename_modulename_order_status_change>
    </events>        
     <resources>
        <modulename_setup>
            <setup>
                <module>Packagename_Modulename</module>
                 <class>Mage_Sales_Model_Resource_Setup</class>
            </setup>
            <connection>
            <use>core_setup</use>
            </connection>
        </modulename_setup>
    </resources>        
</global>
  <crontab>
    <!-- here I am listing only major routines  -->
    <jobs>        
        <Packagename_Modulename_Model_Rewrite_SendOrderToERP>
            <schedule>
                <cron_expr>12 * * * *</cron_expr>
            </schedule>
            <run>
                <model>modelrewrite/observer::runSendOrderToERP</model>
            </run>
        </Packagename_Modulename_Model_Rewrite_SendOrderToERP>            
        <Packagename_Modulename_Model_Rewrite_ReceiveERPStatusOrder>
            <schedule>
                <cron_expr>*/5 * * * *</cron_expr>
            </schedule>
            <run>
                <model>modelrewrite/observer::runReceiveERPStatusOrder</model>
            </run>
        </Packagename_Modulename_Model_Rewrite_ReceiveERPStatusOrder>            
    </jobs>        
</crontab>

2 - app/code/loca/Packagename/Modulename/Model/Rewrite/Order.php

class Packagename_Modulename_Model_Rewrite_Order extends Mage_Sales_Model_Order{

public function _setState($state, $status = false, $comment = '', $isCustomerNotified = null, $shouldProtectState = false){
    // attempt to set the specified state
    // tenta definir o status especificado
    if ($shouldProtectState) {
        if ($this->isStateProtected($state)) {
            Mage::throwException(
                Mage::helper('sales')->__('The Order State "%s" must not be set manually.', $state)
            );
        }
    }
    $this->setData('state', $state);

    // add status history
    if ($status) {
        if ($status === true) {
            $status = $this->getConfig()->getStateDefaultStatus($state);
        }
        $this->setStatus($status);
        $history = $this->addStatusHistoryComment($comment, false); // no sense to set $status again
        $history->setIsCustomerNotified($isCustomerNotified); // for backwards compatibility
    }

    Mage::dispatchEvent('packagename_modulename_order_status_change', array('order' => $this, 'state' => $state, 'status' => $status, 'comment' => $comment, 'isCustomerNotified' => $isCustomerNotified));              
    Mage::log("Packagename_Modulename_Model_Rewrite_Order Changing order to STATE ".$state." STATUS ".$status);
    return $this;
}

}

3 - app/code/loca/Packagename/Modulename/Model/Rewrite/Observer.php

class Packagename_modulename_Model_Rewrite_Observer{

public function implementOrderStatus($event){
    $order = $event->getOrder();
    $state = $event->getState();
    $status = $event->getStatus();
    return $this;
} 

public function changeStateOrder($observer){
    Mage::log('changeStateOrder');
    $order = $observer->getEvent()->getOrder();       

    if($order->getStatus() == "processing_paid"){
        $this->autoInvoicing($order);
    }
    else if($order->getStatus() == "processing_shipped"){
        $this->autoShipment($order);
    }

    // use your necessary ifs
    $this->sendTransactionalEmail($order);

    return $this;
}


public function autoShipment(Mage_Sales_Model_Order $order){ 
    //...    
}

public function autoInvoicing(Mage_Sales_Model_Order $order){ 
    //...    
    //return $this;
}

public function sendTransactionalEmail(Mage_Sales_Model_Order $order){

    switch ($order->getStatus()) {            
        case "processing":
            $templateId = 1;                        
            break;
        case "pending_payment":
            $templateId = 0;                        
            break;            
    //...                    
        default:
            $templateId = 0;
            break;
    }        

//...
}


public function runSendOrderToERP($schedule){
     //...
}


public function runReceiveERPStatusOrder($schedule){        
    //...
}

//And much more another methods can be used after change state / status order: refund, calcel, etc