Modifying Phoenix_Worldpay For Testing in Magento

Worldpay offers an easy way to switch from live to test mode, however if your server is unreachable by them then after completing the test transaction you won’t be redirected back to your Magento store.

We can make the following temporary adaptions to the module which will allow us to manually pass the required data via a GET string:

Phoenix_Worldpay_ProcessingController

   protected function _checkReturnedPost()
    {
//        // check request type
//        if (!$this->getRequest()->isPost()) {
//            Mage::throwException('Wrong request type.');
//        }
//
//        // validate request ip coming from WorldPay/RBS subnet
//        $helper = Mage::helper('core/http');
//        if (method_exists($helper, 'getRemoteAddr')) {
//            $remoteAddr = $helper->getRemoteAddr();
//        } else {
//            $request = $this->getRequest()->getServer();
//            $remoteAddr = $request['REMOTE_ADDR'];
//        }
//        if (!preg_match('/\.worldpay\.com$/', gethostbyaddr($remoteAddr))) {
//            Mage::throwException('Domain can\'t be validated as WorldPay-Domain.');
//        }

        // get request variables
        $request = $this->getRequest()->getParams();
        if (empty($request)) {
            Mage::throwException('Request doesn\'t contain POST elements.');
        }

        // check order id
        if (empty($request['MC_orderid']) || strlen($request['MC_orderid']) > 50) {
            Mage::throwException('Missing or invalid order ID');
        }

        // load order for further validation
        $this->_order = Mage::getModel('sales/order')->loadByIncrementId($request['MC_orderid']);
        if (!$this->_order->getId()) {
            Mage::throwException('Order not found');
        }

        $this->_paymentInst = $this->_order->getPayment()->getMethodInstance();

        // check transaction password
        if ($this->_paymentInst->getConfigData('transaction_password') != $request['callbackPW']) {
            Mage::throwException('Transaction password wrong');
        }

        return $request;
    }

– We remove the remote address checks at the start of the method
– We change the getPost to a getParams, allowing us to provide GET parameters

Phoenix_Worldpay_Model_Cc

public function capture(Varien_Object $payment, $amount)
	{
        $payment->getOrder()->addStatusToHistory($payment->getOrder()->getStatus(), $this->_getHelper()->__('Worldpay transaction has been captured.'));
        return true;
        if (!$this->canCapture()) {
            return $this;
        }

        if (Mage::app()->getRequest()->getParam('transId')) {
            // Capture is called from response action
            $payment->setStatus(self::STATUS_APPROVED);
            return $this;
        }
        $transactionId = $payment->getLastTransId();
        $params = $this->_prepareAdminRequestParams();
        $params['transId']  = $transactionId;
        $params['authMode'] = '0';
        $params['op']       = 'postAuth-full';

        $responseBody = $this->processAdminRequest($params);
        $response = explode(',', $responseBody);

        if (count($response) <= 0 || $response[0] != 'A' || $response[1] != $transactionId) {
            $message = $this->_getHelper()->__('Error during capture online. Server response: %s', $responseBody);
            $this->_debug($message);
            Mage::throwException($message);
        } else {
            $payment->getOrder()->addStatusToHistory($payment->getOrder()->getStatus(), $this->_getHelper()->__('Worldpay transaction has been captured.'));
        }
    }

– If capturing is required, then this will need further modification, however for our needs we only needed to return true from this method.

It should now be possible to provide a GET string with all of the required parameters, E.g.

http://mydomain.local/worldpay/processing/response?MC_orderid=100012592&transStatus=Y&authAmount=158.00&authCurrency=GBP&authMode=A

Paypal Express – Skip Order Review Step in Magento 1

Magento has the option to skip the review step upon returning from Paypal (System > Configuration > Payment Methods > Paypal Express Checkout > Advanced Settings > Skip Order Review Step). There are a couple of caveats to the way this functionality works:

1. Using the Paypal button from the cart page

If the button from the checkout/cart page is used rather than following the flow through the one step checkout then the review step becomes compulsory.

We can see this by the URL which the buttons links to the paypal express controller, which has the parameter button/1 on it. In Mage_Paypal_Controller_Express_Abstract, the following is passed into the start method of the checkout (Mage_Paypal_Model_Express_Checkout) object:

<?php
$button = (bool)$this->getRequest()->getParam(Mage_Paypal_Model_Express_Checkout::PAYMENT_INFO_BUTTON);
$token = $this->_checkout->start(Mage::getUrl('*/*/return'), Mage::getUrl('*/*/cancel'), $button);

This is then set and saved on the payment object:

<?php
$this->_quote->getPayment()->setAdditionalInformation(self::PAYMENT_INFO_BUTTON, 1);

This option is used when the user returns from Paypal in Mage_Paypal_Controller_Express_Abstract‘s returnAction method:

<?php
if ($this->_checkout->canSkipOrderReviewStep()) {
    $this->_forward('placeOrder');
} else {
    $this->_redirect('*/*/review');
}

Where the canSkipOrderReviewStep() method uses the PAYMENT_INFO_BUTTON option which was set earlier to decide wither the user should be sent to the review page or have their order placed straight away.

2. Using Paypal’s Incontext Module

If this module from Magento Connect has been installed, then the function referenced above which sets the button parameter when starting the checkout process is commented out:

<?php
//$button = (bool)$this->getRequest()->getParam(Mage_Paypal_Model_Express_Checkout::PAYMENT_INFO_BUTTON);
...
$token = $this->_checkout->start(Mage::getUrl($type . '/return'), Mage::getUrl($type . '/cancel'), true);

This means that Magento will always assume the user came from clicking one of the cart buttons in this scenario, and never from the one page checkout. This line is found in Paypal_InContext_Controller_Express_Action‘s startAction method, which supersedes the one found in Core Magento’s Mage_Paypal_Controller_Express_Abstract.

The reason the InContext module requires the review step is for the user experience. When using the InContext module, the user is not redirected to Paypal on a device where it’s enabled, so would never get chance to review their order from the point they chose to pay either from the cart or checkout page.