Jump to content

[Solved] Validate a payment


Croonical

Recommended Posts

Hello,

 

I really need your help. I've developed a payment module which uses a paygate (a redirection on an external website).

 

My order is created with :

 

$this->module->validateOrder((int)$cart->id, Configuration::get('MY_STATUS'), $total, $this->module->displayName, "Customer redirected", NULL, (int)$currency->id, false, $customer->secure_key); 

 

 

When the callback is done from the other website, i need my module to save the payment. I wrote a controllers to do this

 

 

<?php
include('../../../../config/config.inc.php');


$order = new Order(Tools::getValue($id_order));
if (!Validate::isLoadedObject($order))
throw new PrestaShopException('Can\'t load Order object');

 

Now i need to save the order as done like "ok now you're paid, save the transaction and so on.."

 

How can i do this ? I didn't find any example.

I was thinking using addOrderPayment but i think it's too far from what i want.

 

Any clues ?

 

Thanks !

Edited by Croonical (see edit history)
Link to comment
Share on other sites

Hi guys,

 

I'm still looking for that answer.

At the moment, i'm using this :

 

$order->addOrderPayment((float)$order->total_paid); 

 

but this isn't enough. I mean, the payment is now recorded, but some things are still missing. For example, the amount paid by the customer isn't increased.

 

I'm sure it's quite simple, but i don't find it. Please help me.

 

Thanks :)

Link to comment
Share on other sites

Hi,

Actually, as far as I know the order should be saved once you validate it. Then you can simply redirect. See bankwire in action here

 

Tools::redirect('index.php?controller=order-confirmation&id_cart='.$cart->id.'&id_module='.$this->module->id.'&id_order='.$this->module->currentOrder.'&key='.$customer->secure_key);

Link to comment
Share on other sites

Hi Nemo1, thanks for your answer.

 

Actually i've already wrote that line, but it is called when the customer validate his cart.

 

$this->module->validateOrder((int)$cart->id, Configuration::get('MY_STATUS'), $total, $this->module->displayName, "Customer redirected", NULL, (int)$currency->id, false, $customer->secure_key);
Tools::redirect('index.php?controller=order-confirmation&id_cart='.(int)$cart->id.'&id_module='.(int)$this->module->id.'&id_order='.$this->module->currentOrder.'&key='.$customer->secure_key);

 

My need is to set the order (or cart) as paid when the callback from the paygate occurs. I only know the $id_order.

Edited by Croonical (see edit history)
Link to comment
Share on other sites

Ok i found the solution ! (in ipn.php from paypal module)

 

As i was expecting it, it is really really simple. Here is the code :

 

$history = new OrderHistory();
$history->id_order = (int)$id_order;
$history->changeIdOrderState((int)Configuration::get('PS_OS_PAYMENT'), $history->id_order);
$history->addWithemail();
$history->save();

Link to comment
Share on other sites

  • 4 months later...

Ok i found the solution ! (in ipn.php from paypal module)

 

As i was expecting it, it is really really simple. Here is the code :

 

$history = new OrderHistory();
$history->id_order = (int)$id_order;
$history->changeIdOrderState((int)Configuration::get('PS_OS_PAYMENT'), $history->id_order);
$history->addWithemail();
$history->save();

This is exactly the scenario in my unfinished payment module. But how can I get $id_order for the above solution? Paypal's IPN has its own getIPNTransactionDetails method.

Link to comment
Share on other sites

Hi,

 

When the payment is done, the server must proceed to a "callback" on a controller of your module. This callback (or IPN, it's the same thing) is actually a HTTP push, and it must contains an identifier of the paid order. This identifier depends on the payment method you use : sometimes you can use the order_id from your prestashop website, but other times you'll have an independant identifier. In this case you have to retrieve the order_id by yourself (for example you can use a table for that).

 

Check the ipn.php example :

function getIPNTransactionDetails(){
$transaction_id = pSQL(Tools::getValue('txn_id'));  //Here the module gets the transaction ID stored in the callback as a parameter
return array(
'id_invoice' => null,
'id_transaction' => $transaction_id,
'transaction_id' => $transaction_id,
'currency' => pSQL(Tools::getValue('mc_currency')),
'total_paid' => (float)Tools::getValue('mc_gross'),
'shipping' => (float)Tools::getValue('mc_shipping'),
'payment_date' => pSQL(Tools::getValue('payment_date')),
'payment_status' => pSQL(Tools::getValue('payment_status')),
);
}


if (Tools::getValue('payment_status') !== false)
{
$details = getIPNTransactionDetails();
$id_order = PayPalOrder::getIdOrderByTransactionId($details['id_transaction']);
PayPalOrder::updateOrder($id_order, $details);


$history = new OrderHistory();
$history->id_order = (int)$id_order;
$history->changeIdOrderState((int)Configuration::get('PS_OS_PAYMENT'), $history->id_order);
$history->addWithemail();
$history->save();
}

The paypal callback returns the transaction id. From that id, the paypal module is able to retrieve the order_id (getIdOrderByTransactionId function).

 

I hope it's clear enough. Good luck !

Edited by Croonical (see edit history)
Link to comment
Share on other sites

To create the order at the validation.php, you need the validateOrder function. On the cheque module example :

$this->module->validateOrder((int)$cart->id, Configuration::get('PS_OS_CHEQUE'), $total, $this->module->displayName, NULL, $mailVars, (int)$currency->id, false, $customer->secure_key);
Tools::redirect('index.php?controller=order-confirmation&id_cart='.(int)$cart->id.'&id_module='.(int)$this->module->id.'&id_order='.$this->module->currentOrder.'&key='.$customer->secure_key);

This will call the hookPaymentReturn (in your [module].php). From that block, you can get the order_id

function hookPaymentReturn($params)
{
   [...]
   $my_order_id = $params['objOrder']->id;
}
Edited by Croonical (see edit history)
Link to comment
Share on other sites

Thanks. I still can't get orders validated from my payment gateway's "lone GET request" (meaning without returning to the store using the browser). Here is my main module php-file's hookPaymentReturn:

public function hookPaymentReturn($params)
    {
        if (!$this->active)
            return;

        $state = $params['objOrder']->getCurrentState();
        if ($state == Configuration::get('PS_OS_PAYMENT') || $state == Configuration::get('PS_OS_OUTOFSTOCK'))
        {
            $id_order = $params['objOrder']->id;
            $history = new OrderHistory();
            $history->id_order = (int)$id_order;
            $history->changeIdOrderState((int)Configuration::get('PS_OS_PAYMENT'), $history->id_order);
            $history->addWithemail();
            $history->save();
            $this->smarty->assign(array(
                'total_to_pay' => Tools::displayPrice($params['total_to_pay'], $params['currencyObj'], false),
                'status' => 'ok',
                'id_order' => $params['objOrder']->id
            ));
            if (isset($params['objOrder']->reference) && !empty($params['objOrder']->reference))
                $this->smarty->assign('reference', $params['objOrder']->reference);
        }
        else
            $this->smarty->assign('status', 'failed');
        return $this->display(__FILE__, 'payment_return.tpl');
    }

Here is my validation.php:

class checkoutfiValidationModuleFrontController extends ModuleFrontController
{
    /**
     * @see FrontController::postProcess()
     */
    public function postProcess()
    {

        $customer = new Customer($_GET['customerId']);

        $currency = $_GET['currency'];
        $total = $_GET['amountPaid'];
        $cartId = $_GET['cartId'];
        $co = new checkoutData(Configuration::get('CHECKOUTFI_MERCHANT'), Configuration::get('CHECKOUTFI_PASSWORD')); // merchantID and securitykey (normally about 80 chars)
        $md5 = md5(Configuration::get('CHECKOUTFI_PASSWORD')."&{$_GET['VERSION']}&{$_GET['STAMP']}&{$_GET['REFERENCE']}&{$_GET['PAYMENT']}&{$_GET['STATUS']}&{$_GET['ALGORITHM']}");
        if (strtoupper($md5) == $_GET['MAC'])
        {
            if ($_GET['STATUS'] == 2 || $_GET['STATUS'] == 3)
            {
                // 2 = maksu suoritettu / payment done
                // 3 = maksu viivästetty / payment delayed
// I commented out the below for testing with the gateway return, just to make sure it doesn't get stuck on any cookie mismatch
                /*if ($this->context->cookie->shopContext)
                {
                    $psStamp = md5($this->context->cookie->date_add . $_GET['STAMP'] . Configuration::get('CHECKOUTFI_PASSWORD'));

                    if ($psStamp != $_GET['psStamp']){
                        die("Tilauksen tunnisteesta '" . $_GET['STAMP'] . "' laskettu md5 '" . $psStamp . "' tilauksen md5:n '" . $_GET['psStamp'] . "' kanssa.");
                    }
                    
                }*/
                if ($_GET['STATUS'] == 2)
                    {
                        $this->module->validateOrder($cartId, Configuration::get('PS_OS_PAYMENT'), $total, $this->module->displayName, NULL, NULL, $currency, false, $customer->secure_key);                        
                        Tools::redirect('index.php?controller=order-confirmation&id_cart='.$cartId.'&id_module='.$this->module->id.'&id_order='.$this->module->currentOrder.'&key='.$customer->secure_key);
                    }
                    else
                    {
                        $this->module->validateOrder($cartId, Configuration::get('PS_OS_DELAYED'), $total, $this->module->displayName, NULL, NULL, $currency, false, $customer->secure_key);
                        Tools::redirect('index.php?controller=order-confirmation&id_cart='.$cartId.'&id_module='.$this->module->id.'&id_order='.$this->module->currentOrder.'&key='.$customer->secure_key);
                    }
            }
            else
            {
                die("Tilauksen tila väärä (arvot 2 ja 3 sallittuja): " . $_GET['STATUS']); // State of the order is invalid
            }
        }
        else
        {
            die("MAC-tarkiste ei täsmää: " . strtoupper($md5) . " vs. " . $_GET['MAC']); // MAC checksum doesn't match
        }
    }
}
Edited by Beluga (see edit history)
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...