1

I am using magento CE 1.9.3.1 and I would like to disable auto invoicing of orders placed by paypal. Tax point purposes I would like to invoice them manually in the magento backend myself like I do for the Purchase order orders.

Doing some research (Googling!) I found this:

stop auto-invoice of paypal orders

Now, this is nearly three years old from 2014 so is this still a viable solution for 1.9.3.1 ?

Or is there a more reliable solution ?

Update

I went and amended the registerCaptureNotification function in payment.php from prasantas answser below to the following:

 $status = true;
$letsEmail = false;
if ($this->getIsTransactionPending()) {
    $message = Mage::helper('sales')->__('Capturing amount of %s is pending approval on gateway.', $this->_formatPrice($amount));
    $state = Mage_Sales_Model_Order::STATE_PAYMENT_REVIEW;
    $letsEmail = true;
    if ($this->getIsFraudDetected()) {
        $message = Mage::helper('sales')->__('Order is suspended as its capture amount %s is suspected to be fraudulent.', $this->_formatPrice($amount, $this->getCurrencyCode()));
        $status = Mage_Sales_Model_Order::STATUS_FRAUD;
        $letsEmail = false;
    }
} else {
    $message = Mage::helper('sales')->__('Registered notification about captured amount of %s.', $this->_formatPrice($amount));
    $state = Mage_Sales_Model_Order::STATE_NEW;
    $letsEmail = true;
    if ($this->getIsFraudDetected()) {
        $state = Mage_Sales_Model_Order::STATE_PAYMENT_REVIEW;
        $message = Mage::helper('sales')->__('Order is suspended as its capture amount %s is suspected to be fraudulent.', $this->_formatPrice($amount, $this->getCurrencyCode()));
        $status = Mage_Sales_Model_Order::STATUS_FRAUD;
        $letsEmail = false;
    }
}

$transaction = $this->_addTransaction(Mage_Sales_Model_Order_Payment_Transaction::TYPE_CAPTURE, $invoice, true);
$message = $this->_prependMessage($message);
$message = $this->_appendTransactionToMessage($transaction, $message);
$order->setState($state, $status, $message);
if ($letsEmail === true && !$order->getEmailSent()){
     $order->queueNewOrderEmail()->addStatusHistoryComment(
            Mage::helper('paypal')->__('Notified Customer')
        )
        ->setIsCustomerNotified(true)
        ->save();
}

This is now sending order confirmation emails.

Update 2

I now have an order where customer paid via paypal and then it showed pending-payment, which changed to cancelled and back to pending.

I cannot cancel the order, ship, invoice or nothing. only options we have are to edit,hold or delete order.

Update 3

I have also noticed that paypal orders at random get cancelled.

Below is a screenshot of an orders status history and as it illustrates an order goes to pending payment first then to pending. From here 3 seconds later it is set to cancelled. Why is this ?

I enabled debug but nothing at all was recorded in the /var/log location. Looking at transaction history and and ipn history on paypal I can see that the payment has come through successfully and ipn was confirmed/completed.

Order being cancelled

I would now just like to know why sporadically (1 in 4 or so) the paypal orders get cancelled even though paypal order was successfully placed and paid for and payment information passed back to magento?

1

Create a file Wfh_DisableAutoInvoice.xml in app/etc/modules/ and put the following code.

<?xml version="1.0"?>
<config>
<modules>
    <Wfh_DisableAutoInvoice>
        <active>true</active>
        <codePool>local</codePool>
    </Wfh_DisableAutoInvoice>
</modules>
</config>

Create a file config.xml in app/code/local/Wfh/DisableAutoInvoice/etc/ and put the following code.

<?xml version="1.0"?>
<config>
<modules>
    <Wfh_DisableAutoInvoice>
        <version>0.1.0</version>
    </Wfh_DisableAutoInvoice>
</modules>
<global>
    <models>
        <disableautoinvoice>
            <class>Wfh_DisableAutoInvoice_Model</class>
            <resourceModel>disableautoinvoice_mysql4</resourceModel>
        </disableautoinvoice>
        <sales>
            <rewrite>
        <order_payment>Wfh_DisableAutoInvoice_Model_Sales_Order_Payment</order_payment>
            </rewrite>
        </sales>
    </models>
</global>
</config> 

Create a file Payment.php in app/code/local/Wfh/DisableAutoInvoice/Model/Sales/Order/ and put the following code.

class Wfh_DisableAutoInvoice_Model_Sales_Order_Payment extends     Mage_Sales_Model_Order_Payment
{   

/**
 * Authorize or authorize and capture payment on gateway, if applicable
 * This method is supposed to be called only when order is placed
 *
 * @return Mage_Sales_Model_Order_Payment
 */
public function place()
{
    Mage::dispatchEvent('sales_order_payment_place_start', array('payment' => $this));
    $order = $this->getOrder();

    $this->setAmountOrdered($order->getTotalDue());
    $this->setBaseAmountOrdered($order->getBaseTotalDue());
    $this->setShippingAmount($order->getShippingAmount());
    $this->setBaseShippingAmount($order->getBaseShippingAmount());

    $methodInstance = $this->getMethodInstance();
    $methodInstance->setStore($order->getStoreId());
    $orderState = Mage_Sales_Model_Order::STATE_NEW;
    $stateObject = new Varien_Object();

    /**
     * Do order payment validation on payment method level
     */
    $methodInstance->validate();
    $action = $methodInstance->getConfigPaymentAction();
    if ($action) {
        if ($methodInstance->isInitializeNeeded()) {
            /**
             * For method initialization we have to use original config value for payment action
             */
            $methodInstance->initialize($methodInstance->getConfigData('payment_action'), $stateObject);
        } else {
            $orderState = Mage_Sales_Model_Order::STATE_NEW;
            switch ($action) {
                case Mage_Payment_Model_Method_Abstract::ACTION_ORDER:
                    $this->_order($order->getBaseTotalDue());
                    break;
                case Mage_Payment_Model_Method_Abstract::ACTION_AUTHORIZE:
                    $this->_authorize(true, $order->getBaseTotalDue()); // base amount will be set inside
                    $this->setAmountAuthorized($order->getTotalDue());
                    break;
                case Mage_Payment_Model_Method_Abstract::ACTION_AUTHORIZE_CAPTURE:
                    $this->setAmountAuthorized($order->getTotalDue());
                    $this->setBaseAmountAuthorized($order->getBaseTotalDue());
                    $this->capture(null);
                    break;
                default:
                    break;
            }
        }
    }

    $this->_createBillingAgreement();

    $orderIsNotified = null;
    if ($stateObject->getState() && $stateObject->getStatus()) {
        $orderState      = $stateObject->getState();
        $orderStatus     = $stateObject->getStatus();
        $orderIsNotified = $stateObject->getIsNotified();
    } else {
        $orderStatus = $methodInstance->getConfigData('order_status');
        if (!$orderStatus) {
            $orderStatus = $order->getConfig()->getStateDefaultStatus($orderState);
        } else {
            // check if $orderStatus has assigned a state
            $states = $order->getConfig()->getStatusStates($orderStatus);
            if (count($states) == 0) {
                $orderStatus = $order->getConfig()->getStateDefaultStatus($orderState);
            }
        }
    }
    $isCustomerNotified = (null !== $orderIsNotified) ? $orderIsNotified : $order->getCustomerNoteNotify();

    $message = $order->getCustomerNote();
    // add message if order was put into review during authorization or capture
    if ($order->getState() == Mage_Sales_Model_Order::STATE_PAYMENT_REVIEW) {
        if ($message) {
            $order->addStatusToHistory($order->getStatus(), $message, $isCustomerNotified);
        }
    } elseif ($order->getState() && ($orderStatus !== $order->getStatus() || $message)) {
        // add message to history if order state already declared
        $order->setState($orderState, $orderStatus, $message, $isCustomerNotified);
    } elseif (($order->getState() != $orderState) || ($order->getStatus() != $orderStatus) || $message) {
        // set order state
        $order->setState($orderState, $orderStatus, $message, $isCustomerNotified);
    }

    Mage::dispatchEvent('sales_order_payment_place_end', array('payment' => $this));

    return $this;
}


/**
 * Capture the payment online
 * Does not create invoice automatically for order
 * Updates transactions hierarchy, if required
 * Updates payment totals, updates order status and adds proper comments
 *
 * TODO: eliminate logic duplication with registerCaptureNotification()
 *
 * @return Mage_Sales_Model_Order_Payment
 * @throws Mage_Core_Exception
 */
public function capture($invoice)
{

    $invoice = null;
    $order = $this->getOrder();

    $amountToCapture = $this->_formatAmount($order->getBaseGrandTotal());

    $paidWorkaround = (float)$amountToCapture;
    $this->_isCaptureFinal($paidWorkaround);

    $this->_generateTransactionId(
        Mage_Sales_Model_Order_Payment_Transaction::TYPE_CAPTURE,
        $this->getAuthorizationTransaction()
    );

    Mage::dispatchEvent('sales_order_payment_capture', array('payment' => $this, 'invoice' => $invoice));

    $status = true;
    if (!$this->getIsTransactionPending()) {
        // attempt to capture: this can trigger "is_transaction_pending"
        $this->getMethodInstance()->setStore($order->getStoreId())->capture($this, $amountToCapture);

        $transaction = $this->_addTransaction(
            Mage_Sales_Model_Order_Payment_Transaction::TYPE_CAPTURE,
            $invoice,
            true
        );

        if ($this->getIsTransactionPending()) {
            $message = Mage::helper('sales')->__('Capturing amount of %s is pending approval on gateway.', $this->_formatPrice($amountToCapture));
            $state = Mage_Sales_Model_Order::STATE_PAYMENT_REVIEW;
            if ($this->getIsFraudDetected()) {
                $status = Mage_Sales_Model_Order::STATUS_FRAUD;
            }
        } else { // normal online capture: invoice is marked as "paid"
            $message = Mage::helper('sales')->__('Captured amount of %s online.', $this->_formatPrice($amountToCapture));
            $state = Mage_Sales_Model_Order::STATE_NEW;
            $this->_updateTotals(array('base_amount_paid_online' => $amountToCapture));
        }
        if ($order->isNominal()) {
            $message = $this->_prependMessage(Mage::helper('sales')->__('Nominal order registered.'));
        } else {
            $message = $this->_prependMessage($message);
            $message = $this->_appendTransactionToMessage($transaction, $message);
        }
        $order->setState($state, $status, $message);

        return $this;
    }
    Mage::throwException(
        Mage::helper('sales')->__('The transaction "%s" cannot be captured yet.', $amountToCapture)
    );
}

/**
 * Process a capture notification from a payment gateway for specified amount
 * Does not create an invoice automatically if the amount if the amount covers the order base grand total completely
 * Updates transactions hierarchy, if required
 * Prevents transaction double processing
 * Updates payment totals, updates order status and adds proper comments
 *
 * TODO: eliminate logic duplication with capture()
 *
 * @param float $amount
 * @param bool $skipFraudDetection
 * @return Mage_Sales_Model_Order_Payment
 */
public function registerCaptureNotification($amount, $skipFraudDetection = false)
{

    $this->_generateTransactionId(Mage_Sales_Model_Order_Payment_Transaction::TYPE_CAPTURE,
        $this->getAuthorizationTransaction()
    );

    $order   = $this->getOrder();
    $amount  = (float)$amount;
    $invoice = null;

    // register new capture
    if (!$invoice) {
        $isSameCurrency = $this->_isSameCurrency();
        if (!$isSameCurrency && !$this->_isCaptureFinal($amount)) {
            if (!$skipFraudDetection || !$isSameCurrency) {
                $this->setIsFraudDetected(true);
            }
            $this->_updateTotals(array('base_amount_paid_online' => $amount));
        }
    }

    $status = true;
    if ($this->getIsTransactionPending()) {
        $message = Mage::helper('sales')->__('Capturing amount of %s is pending approval on gateway.', $this->_formatPrice($amount));
        $state = Mage_Sales_Model_Order::STATE_PAYMENT_REVIEW;
        if ($this->getIsFraudDetected()) {
            $message = Mage::helper('sales')->__('Order is suspended as its capture amount %s is suspected to be fraudulent.', $this->_formatPrice($amount, $this->getCurrencyCode()));
            $status = Mage_Sales_Model_Order::STATUS_FRAUD;
        }
    } else {
        $message = Mage::helper('sales')->__('Registered notification about captured amount of %s.', $this->_formatPrice($amount));
        $state = Mage_Sales_Model_Order::STATE_NEW;
        if ($this->getIsFraudDetected()) {
            $state = Mage_Sales_Model_Order::STATE_PAYMENT_REVIEW;
            $message = Mage::helper('sales')->__('Order is suspended as its capture amount %s is suspected to be fraudulent.', $this->_formatPrice($amount, $this->getCurrencyCode()));
            $status = Mage_Sales_Model_Order::STATUS_FRAUD;
        }
    }

    $transaction = $this->_addTransaction(Mage_Sales_Model_Order_Payment_Transaction::TYPE_CAPTURE, $invoice, true);
    $message = $this->_prependMessage($message);
    $message = $this->_appendTransactionToMessage($transaction, $message);
    $order->setState($state, $status, $message);
    return $this;
}
}
  • Sorry how would I rewrite the that model ? – Vaishal Patel Jan 24 '17 at 10:22
  • I have edited the answer please check – Prasanta Hatui Jan 24 '17 at 10:56
  • Wouldn't this overwrite entire payment model ? I just need for paypal payments – Vaishal Patel Jan 24 '17 at 13:17
  • You can restrict according to payment method by payment method code in order. ex :- if( $order->getPayment()->getMethodInstance()->getCode()!="payment_method_code_here"){ return parent::place(); } if( $order->getPayment()->getMethodInstance()->getCode()!="payment_method_code_here"){ return parent::capture($invoice); } if( $order->getPayment()->getMethodInstance()->getCode()!="payment_method_code_here"){ return parent::registerCaptureNotification($amount, $skipFraudDetection ); } – Prasanta Hatui Jan 24 '17 at 13:56
  • there should be some error coming. Check that. – Prasanta Hatui Mar 10 '17 at 12:43

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.