Call-back icon  Sales: Call 877.832.5289 (N America)|310.295.4144 (International)

Magento

eCommerce Software for Online Growth

Magento Forum

   
Return from Payment Gateway validation - Interesting situation
 
srinigenie
Guru
 
Avatar
Total Posts:  398
Joined:  2008-02-04
 

Hi all,

I have integrated my magento cart with my payment gateway and the transactions are running through fine. But I need some help on redirecting the users to the success page and error page based on the payment gateway validation.

On returning from my payment gateway (say XYZPymnt) , my page controller method resultAction is called - code is as below

protected $_redirectBlockType 'XYZPymnt/processing';
    protected 
$_successBlockType 'XYZPymnt/success';
    protected 
$_failureBlockType 'XYZPymnt/failure';

...
..
.

    public function 
resultAction()
    
{
       $request 
$this->getRequest()->getPost();      
       
$Merchant_Id$request['Merchant_Id'];
       
$Amount$request['Amount'];
       
$Order_Id$request['Order_Id'];
       
$Merchant_Param$request['Merchant_Param'];
       
$paymentValid=$request['validPayment'];

       
$this->_order Mage::getModel('sales/order')->loadByIncrementId($Order_Id);
       
$this->_paymentInst $this->_order->getPayment()->getMethodInstance();       

       
$session $this->getCheckout();
           
$session->getMessages(true);        
       if(
$paymentValid == 'Y')
         
{
          
//echo "<br>Thank you for shopping with us. Your credit card has been charged and your transaction is successful. We will be shipping your order to you soon.";
        
          
$this->successAction();            
       
}
       
else 
       
{
          
//echo "<br>Thank you for shopping with us.However,the transaction has been declined.";        
        //Here you need to put in the routines for a failed
        //transaction such as sending an email to customer
        //setting database status etc etc

          
$this->failureAction();
        
}

    }

    
protected function successAction()
    
{
        $session 
$this->getCheckout();

        
$session->unsVcsRealOrderId();
        
$session->setQuoteId($session->getVcsQuoteId(true));
        
$session->getQuote()->setIsActive(false)->save();

        
$order Mage::getModel('sales/order');
        
$order->load($this->getCheckout()->getLastOrderId());
        if(
$order->getId() && $this->_sendNewOrderEmail)
            
$order->sendNewOrderEmail();

         
$this->loadLayout();
        
$this->_initLayoutMessages('checkout/session');        
        
$this->getResponse()->setBody(
                
$this->getLayout()
                    ->
createBlock($this->_successBlockType)
                    ->
setOrder($this->_order)
                    ->
toHtml()
            );        
        
$this->renderLayout();
    
}
    
    
/**
     * CCAvenue return action
     */
    
protected function failureAction()
    
{
        $session 
$this->getCheckout();
        
$session->getMessages(true);
        if (!
$this->getRequest()->isPost()) {
            $session
->addError'Wrong request type.' );
        
else {
            $request 
$this->getRequest()->getPost();

            
$this->_order Mage::getModel('sales/order')->loadByIncrementId($request['Order_Id']);

        
}

        $messages 
$session->getMessages();
        
$errors false;
        if (
$messages{
            
foreach( $messages->getErrors() as $msg {
                $errors[] 
$msg->toString();
            
}
        }

        
if (isset($request)) {
            $this
->_order->addStatusToHistory(
                
Mage_Sales_Model_Order::STATE_CANCELED,
                
"Failure from CCAvenue<br/>".
                    (
is_array($errors)?implode("<br/>",$errors):'No extra information'));
            
$this->_order->cancel();
        
}

        $this
->loadLayout();
        
$this->_initLayoutMessages('checkout/session');        
        
$this->getResponse()->setBody(
                
$this->getLayout()
                    ->
createBlock($this->_failureBlockType)
                    ->
setOrder($this->_order)
                    ->
toHtml()
            );        
        
$this->renderLayout();    
      
}

 
Magento Community Magento Community
Magento Community
Magento Community
 
srinigenie
Guru
 
Avatar
Total Posts:  398
Joined:  2008-02-04
 

My problem now is in the redirection once resultAction has been executed. I dont think my code for failureAction and successAction are correct. This is because right now with this code, I get the content of my failure.phtml and success.phtml on top of the Magento layout and am unable to get the contents for failure and success inside the magento content block.

Code for failure and success.phtml are here -

failure.phtml

<?php
/* Magento */
?>
<h3><?php echo $this->__('Payment Transaction Error Occured'?></h3>
<?php echo $this->getMessagesBlock()->getGroupedHtml() ?>
<p><?php echo $this->__('Please <a href="%s">continue shopping</a>.'$this->getContinueShoppingUrl()) ?></p>

success.phtml

<?php
/**
 * Magento
 */
?>

<div class="page-head">
    <
h3><?php echo $this->__('Your order has been received'?></h3>
</
div>
<
p><strong><?php echo $this->__('Thank you for your purchase!'?></strong></p>
<
p>
    
<?php echo $this->__('Your order # is: %s'$this->getOrderId()) ?>.<br/>
    
<?php echo $this->__('You will receive an order confirmation email with details of your order and a link to track its progress.'?><br/>
    
<?php if ($this->canPrint()) :?>
    <?php 
echo $this->__('Click <a href="%s" target="_blank">here to print</a> a copy of your order confirmation.'$this->getPrintUrl()) ?>
    <?php 
endif;?>
</p>
<
div class="button-set">
    <
button class="form-button" onclick="[removed]='<?php echo $this->getUrl() ?>'"><span><?php echo $this->__('Continue Shopping'?></span></button>
</
div>

Also the image of the page when payment gateway returns with an error is attached herewith to see where the problem is -

Image Attachments
failure.JPG
 
Magento Community Magento Community
Magento Community
Magento Community
 
willo
Jr. Member
 
Avatar
Total Posts:  8
Joined:  2008-06-06
Centurion, Gauteng
 

I think it might be

$this->getResponse()->setBody(
                
$this->getLayout()
                    ->
createBlock($this->_failureBlockType)
                    ->
setOrder($this->_order)
                    ->
toHtml()
            );

try

$this->loadLayout();
            
$this->renderLayout();

If the problem is that your blocks aren’t loading, then you need to look at your module’s layout xml file.

Willlo

 
Magento Community Magento Community
Magento Community
Magento Community
 
ebizmarts.com
Member
 
Avatar
Total Posts:  41
Joined:  2008-03-10
 

Hi,

The problem is you’re not redirecting properly, by example here:

if($paymentValid == 'Y')
         
{
          
//echo "<br>Thank you for shopping with us. Your credit card has been charged and your transaction is successful. We will be shipping your order to you soon.";
        
          
$this->successAction();            
       
}

So, the website is still in the same url, there is not redirection.

Currently, when you call SuccessAction or FailureAction is rendering first one of then and after Magento renders the template specified in the layout file by the current “action” (this action seems be “result"). I’m 99% sure about I’m telling you LOL

Here I paste some of code executed in the case of the screenshot that you posted:

$this->loadLayout();
        
$this->_initLayoutMessages('checkout/session');        
        
$this->getResponse()->setBody(
                
$this->getLayout()
                    ->
createBlock($this->_failureBlockType)
                    ->
setOrder($this->_order)
                    ->
toHtml()
            );        
        
$this->renderLayout();

You are rendering the error payment message directly, using the method setBody of the Response object.
But, you are rendering the template associated with the current action when you call renderLayout.
loadLayout and renderLayout uses the layout configuration and the block class specified there.

I suggest you setup the actions “success” and “failure” in the layout file in the same way than “result” action. Then, you can redirect the browser with this instruction:

// instead of $this->successAction();
$this->_redirect('*/*/sucess');

In theory, you can not call an Action method in the controller by hand. The method should be automatically invoked depending of the requested url (again, we need a confirmation of somebody of Magento team, but I’m 99% sure)

I hope it helps you

Regards,
Jorge Bejar

 Signature 

http://www.ebizmarts.com

 
Magento Community Magento Community
Magento Community
Magento Community
 
Core
Member
 
Total Posts:  68
Joined:  2008-03-09
 

This is a great start to a tutorial, however, I’m still confused by the Controller implementation.

Can someone please please please explain how the controllers actually work.

I need to do an identical thing to the above but I don’t understand how the blocks, layouts and controllers are connected together.
Some modules override different controllers like Mage_Core_Controller_Front_Action
and have actions named: callback3dAction

However, when I grep for callback3dAction it comes up empty.  How does does this get called? greping for this over the entire source tree turns up blank.

Also, how do I know which controller to override?

 
Magento Community Magento Community
Magento Community
Magento Community
 
nikefido
Guru
 
Avatar
Total Posts:  421
Joined:  2008-07-11
New Haven, CT
 

Well the URL tells which Controller to fire

http://yourstore.com/index.php/controller/actions/parameter1/parameter2/parameter3 (etc)

so for instance, to add a product to the cart, the URL is something like:  http://www.yourstore.com/index.php/cart/add/somenumbers/product/3
(this will add product ID = 3 to the cart via the “addAction” method in a cart controller class, found in the Checkout module

Anyway, my point is the URL almost follows the general naming structure which points to the file structure of Magento code -

Hopefully I’m not pointing out what you already know (I have a feeling I am) -

I want to point out also that you might not override a controller to get this to work...but might need to make a new one (assuming you are using a payment module that did not come with Magento...[of course now that I mention this, I do not see any controllers being used for other payment gateways that come with magento such as authorize.net])

edit: Looks like the auth.net payment module creates an alert when there is an error as stock functionality. Kinda lame, but functional.

 Signature 

@ My Magento Blog

- Handy tutorials on programming and designing Magento. A continual work in progress!
- Now with a new design, new hosting and a new domain! Check it out!

 
Magento Community Magento Community
Magento Community
Magento Community
 
Core
Member
 
Total Posts:  68
Joined:  2008-03-09
 

Thanks nikefido,

It’s starting to make a little more sense now. 

So what you’re saying is that if the URL is http://www.yourstore.com/checkout/onepage then the controller is the checkout controller. 
Looking through the directories I notice that there is a Mage_Checkout_OnepageController located under app/code/core/Mage/Checkout/controllers/OnepageController.php.

It sounds like that would be the onepage checkout controller right?

Although now it gets confusing.  By your definition onepage is the action, correct?  or does that mean there should be an action called onepageAction? 
which I can’t find.  Or is onepage another controller beneath checkout?

You said that: the URL almost follows the general naming structure which points to the file structure of Magento code.

Is that just by convention or does Magento calculate the function names based on the URL retrieved or is there some mapping file that does this?

I guess I’m just a bit confused about where to even begin.  It’s not clear to me how to override the controller correctly in order to provide a success & failure URL for my payment module and what actions get called.  Or how to provide some calculated content on those URL’s and so on.

Cheers.

 
Magento Community Magento Community
Magento Community
Magento Community
 
nikefido
Guru
 
Avatar
Total Posts:  421
Joined:  2008-07-11
New Haven, CT
 

It doesn’t necessarily have to be onepageAction, it could be indexAction (default method called) -

That’s how I understand it - I’m not too sure beyond that either as I never delved deeply into the Zend framework.

I’m sorry I can’t shed more light on it

 Signature 

@ My Magento Blog

- Handy tutorials on programming and designing Magento. A continual work in progress!
- Now with a new design, new hosting and a new domain! Check it out!

 
Magento Community Magento Community
Magento Community
Magento Community
 
Core
Member
 
Total Posts:  68
Joined:  2008-03-09
 

Thanks, thats really helpful.  I havn’t used PHP for a long time and this is the first I’ve heard of the Zend framework. 

Looking at the zend framework website is shedding light on the Magento design.

 
Magento Community Magento Community
Magento Community
Magento Community
 
Core
Member
 
Total Posts:  68
Joined:  2008-03-09
 

How do I override the onepage checkout controller?

I have a module named Mage_Pxpay.

It’s located in Mage\Pxpay

I assume you need something like the following in config.xml

<frontend>
        <
routers>
            <
pxpay>
                <use>
standard</use>
                <
args>
                    <
module>Mage_Pxpay</module>
                    <
frontName>pxpay</frontName>
                </
args>
            </
pxpay>
        </
routers>
    </
frontend>

I have created the controller in the controllers folder and called it PxpayController.php
The file currently contains:

class Mage_Pxpay_Controller extends Mage_Core_Controller_Front_Action
{
    
//protected $_redirectBlockType = 'Mage_Pxpay/processing';
    
protected $_successBlockType 'pxpay/form_success';
    protected 
$_failureBlockType 'pxpay/form_failure';
    
    
    protected function 
_expireAjax()
    
{
        
if (!Mage::getSingleton('checkout/session')->getQuote()->hasItems()) {
            $this
->getResponse()->setHeader('HTTP/1.1','403 Session Expired');
            exit;
        
}
    }

    
public function successAction()
    
{
        $session 
Mage::getSingleton('checkout/session');
        
$session->setQuoteId($session->getPaymateQuoteId(true));
        
        
// Set the quote as inactive after returning from Paymate
        
Mage::getSingleton('checkout/session')->getQuote()->setIsActive(false)->save();

        
// Send a confirmation email to customer
        
$order Mage::getModel('sales/order');
        
$order->load(Mage::getSingleton('checkout/session')->getLastOrderId());
        if(
$order->getId()){
            $order
->sendNewOrderEmail();
        
}

        Mage
::getSingleton('checkout/session')->unsQuoteId();

        
$this->_redirect('*/*/success');
    
}
    
    
public function failureAction()
    
{
        $session 
Mage::getSingleton('checkout/session');
        
        
$this->_redirect('*/*/failure');
    
}
}

But, after putting some debugging in there, the actions are definately not being called.

I assume I want to go to

http://myurl/checkout/onepage/failure
or
http://myurl/checkout/onepage/success

What am I doing wrong?  none of the other payments modules that I’ve looked set up url rewrites like the examples do.  Are they all wrong or do you sometimes not need to do that?

 
Magento Community Magento Community
Magento Community
Magento Community
 
Core
Member
 
Total Posts:  68
Joined:  2008-03-09
 

Hi, I’ve spent quite a few hours on this and still can’t manage to override the controller.

Even when I have the following config.xml file, it still doesn’t work.

<global>
         <
rewrite>
            <!-- 
This is an identifier for your rewrite that should be unique -->
            <
mage_pxpay_checkout_onepage>
                <
from><![CDATA[#^/checkout/onepage/$#]]></from>
              
<to>/pxpay/checkout_onepage</to>
            </
mage_pxpay_checkout_onepage>
        </
rewrite>
   </global>
   
   <
frontend>
        <
routers>
            <
mage_pxpay>
                <use>
standard</use>
                <
args>
                    <
module>Mage_Pxpay</module>
                    <
frontName>pxpay</frontName>
                </
args>
            </
mage_pxpay>
        </
routers>
    </
frontend>

All I want to do is catch
http://mywebsite/checkout/onepage/success
and
http://mywebsite/checkout/onepage/failure
URL’s.

It seems like there are lots of people who’ve had trouble with this.  Can someone please show me where I’m going wrong?

--- EDIT---
Actually, is it http://mywebsite/pxpay/pxpay/success
and
http://mywebsite/pxpay/pxpay/failure
that I want to use?  if this is the case then I would redirect to the normal /checkout/onepage/success or failure URL’s right?

I notice there is no failure URL by default on the checkout/onepage.

 
Magento Community Magento Community
Magento Community
Magento Community
 
Core
Member
 
Total Posts:  68
Joined:  2008-03-09
 

Got a bit further.

I discovered that by going to http://mywebsite/pxpay/pxpay came up with the error

There has been an error processing your request.

Controller file was loaded but class does not exist
Trace:
#0 C:\wamp\www\hairworks\app\code\core\Mage\Core\Controller\Varien\Router\Standard.php(136): Mage::exception(’Mage_Core’, ‘Controller file...’)
#1 C:\wamp\www\hairworks\app\code\core\Mage\Core\Controller\Varien\Front.php(146): Mage_Core_Controller_Varien_Router_Standard->match(Object(Mage_Core_Controller_Request_Http))
#2 C:\wamp\www\hairworks\app\Mage.php(427): Mage_Core_Controller_Varien_Front->dispatch()
#3 C:\wamp\www\hairworks\index.php(40): Mage::run()
#4 {main}

Thats when I figured out that the controller class should have been named

class Mage_Pxpay_PxpayController extends Mage_Core_Controller_Front_Action

However, still got a way to go, but looks like I’m slowely heading on the right track.  Any other hints people might have I’d really appreciate.

I still can’t see why some modules have a rewrite rule and others don’t?

 
Magento Community Magento Community
Magento Community
Magento Community
 
Stefanos Z
Jr. Member
 
Total Posts:  9
Joined:  2008-07-17
Athens,GR
 

Hello.

Can you please send me with PM or post here the entire code so I can check it out.

Maybe I can help you

 
Magento Community Magento Community
Magento Community
Magento Community