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

Display Shipping Methods For A Product

This will display appropriate shipping methods on the product detail page

The Block Class

class Namespace_Module_Block_Catalog_Product_Delivery extends Mage_Core_Block_Template{

    protected $_product;

    public function _construct(){
       parent::_construct();
       $this->setTemplate('catalog/product/delivery.phtml');
    }

    public function setProductId($productId){
        $this->_product = Mage::getModel('catalog/product')->load($productId);
    }

    public function getDeliveryMethods(){
        $quote = Mage::getModel('sales/quote');
        $existingQuote = Mage::getSingleton('checkout/session')->getQuote();

        if($countryId = $existingQuote->getShippingAddress()->getCountryId()){
            $quote->getShippingAddress()->setCountryId($countryId);
        }else{
            $quote->getShippingAddress()->setCountryId(Mage::getStoreconfig('general/country/default'));
        }

        $quote->addProduct($this->_product);
        $quote->getShippingAddress()->collectTotals();
        $quote->getShippingAddress()->setCollectShippingRates(true);
        $quote->getShippingAddress()->collectShippingRates();
        $rates = $quote->getShippingAddress()->getShippingRatesCollection();

       return $rates;
    }

}
  • Load a new quote object and populate its address with the country of the existing quote or the default config country.
  • Add the product to the quote
  • return the rates

The Template

<?php
$_rates = $this->getDeliveryMethods();
?>

<p><?php echo $this->__("DELIVERY OPTIONS");?></p>
<?php if(count($_rates)):?>
    <ul class="product-rates">
    <?php foreach($_rates as $_rate):?>
        <li><?php echo $this->escapeHtml($_rate->getMethodTitle());?></li>
    <?php endforeach; ?>
    </ul>
<?php endif;?>