New Payment Method Doesn't Send Email Notifications

Hi,

We added a new Credit Card payment method and when a user buys something, the status of the order changes properly, but the admin notification email nor client notification email aren't send.

For the other payment method, the emails are sent properly.

The company that takes care of the Credit Card payment changed some of the files and added others, so I guess they didn't include this feature when they changed the files.

Can someone please advise what can I do to make the application send emails when the status of the order changes through this payment method?

Is there a function that sends those email and that we could add into our files?

Thanks for your help!

It is required to examine new payment method files. Please try to find something similar to

fn_finish_payment($order_id, $pp_response);

and replace with

fn_finish_payment($order_id, $pp_response, true);

Also please make sure that the Notify customer and Notify orders department settings are enabled for the order status

http://prntscr.com/94tf9e

It is required to examine new payment method files. Please try to find something similar to

fn_finish_payment($order_id, $pp_response);

and replace with

fn_finish_payment($order_id, $pp_response, true);

Also please make sure that the Notify customer and Notify orders department settings are enabled for the order status

http://prntscr.com/94tf9e

Thanks for your mesage!

I made the change you suggested, but the email is still not sent.

I changed

fn_finish_payment($order_id, "C", false);

to

fn_finish_payment($order_id, "C", true);

Here is the complete code snippet:

if($zcrsp['fp_hash']===$fp_hash)    {
        if($zcrsp['action']=="0") {
            fn_change_order_status($orderid, 'C');
            fn_finish_payment($order_id, "C", true);
            fn_order_placement_routines($order_id);
            echo "Successfully completed";
            update_stock($order_info);
        }
        else {        
            fn_finish_payment($order_id, "F", true);
            echo "Tranzaction failed" . $zcrsp['message'];
        }
    }
    else {
        echo "Invalid signature";
    }

Can you please advise if there is anything wrong with it?

Thanks!

I guess this line:

if($zcrsp['action']=="0") {

is the brach for successfull payment. And it does not include the 'status_to' parameter. In this case the previous order status is taken. And if the 'status_from' is equal to 'status_to', the notification will not be sent.

Try to replace:

fn_finish_payment($order_id, "C", true);

with:

$pp_response = array(
    'order_status' => 'C'
);
fn_finish_payment($order_id, $pp_response, true);

Try to replace:

fn_finish_payment($order_id, "C", true);

with:

$pp_response = array(
    'order_status' => 'C'
);
fn_finish_payment($order_id, $pp_response, true);

Thanks for your reply!

I tried your suggestion but nothing changed :(

I guess this line:

if($zcrsp['action']=="0") {

is the brach for successfull payment. And it does not include the 'status_to' parameter. In this case the previous order status is taken. And if the 'status_from' is equal to 'status_to', the notification will not be sent.

Indeed,

'action'     => addslashes(trim(@$_POST['action'])), // if action ==0 transaction ok

Can you please advise what I should change on our code in oder to make the application send the notification emails?

Thanks!

Thanks for your reply!

I tried your suggestion but nothing changed :(

Are you sure that this part of code is executed when the order is successfully paid?

What version of CS-Cart do you use? The code does not seem to be for version 4, but it does not matter, we can find a solution for any version

What version of CS-Cart do you use? The code does not seem to be for version 4, but it does not matter, we can find a solution for any version

Hello,

We are using version 4.2.4:

https://sedussa.ro/?version

Thanks for your help!

Are you sure that this part of code is executed when the order is successfully paid?

Hi,

Yes, I think so - this section is the only place where I can find "fn_finish_payment" defined from the files the payment company added/edited. So this should be it.

Thanks for your time!

Hello,

We are using version 4.2.4:

https://sedussa.ro/?version

Thanks for your help!

Then I should say your payment module is not adapted to be used ib CS-Cart version 4.2.4

You can find these 2 functions in the app/functions/fn.cart.php file. And please pay your attention to its declaration:

function fn_order_placement_routines($action = '', $order_id = 0, $force_notification = array(), $clear_cart = true, $area = AREA)

and

function fn_finish_payment($order_id, $pp_response, $force_notification = array())

First parameter in the fn_finish_payment calling is order_id, which is right. The second one should be the $pp_response array. This array should include at least the 'order_status' item for successfull order placing.

As for the fn_order_placement_routines the first parameter is expected to be the action ('route' or 'save, or another). But it sends $order_id.

Also you can see that the first fn_change_order_status calling receives $orderid, but other functions - $order_id

Try to replace these functions calling with this code:

            fn_change_order_status($order_id, 'C');
            fn_finish_payment($order_id, array('order_status' => "C"), true);
            fn_order_placement_routines('route', $order_id, true);

Then I should say your payment module is not adapted to be used ib CS-Cart version 4.2.4

You can find these 2 functions in the app/functions/fn.cart.php file. And please pay your attention to its declaration:

function fn_order_placement_routines($action = '', $order_id = 0, $force_notification = array(), $clear_cart = true, $area = AREA)

and

function fn_finish_payment($order_id, $pp_response, $force_notification = array())

First parameter in the fn_finish_payment calling is order_id, which is right. The second one should be the $pp_response array. This array should include at least the 'order_status' item for successfull order placing.

As for the fn_order_placement_routines the first parameter is expected to be the action ('route' or 'save, or another). But it sends $order_id.

Also you can see that the first fn_change_order_status calling receives $orderid, but other functions - $order_id

Try to replace these functions calling with this code:

            fn_change_order_status($order_id, 'C');
            fn_finish_payment($order_id, array('order_status' => "C"), true);
            fn_order_placement_routines('route', $order_id, true);

Hi,

Thanks for your suggestions. I changed those 3 functions as you advised but nothing changed.

So, when I test this as a customer, I use a dummy card which generates a "Failed Payment" message - I receive an email about this from the company which takes care of the payment. Anyway, this is fine for now. But, I suppose I also should receive an email from CS Cart about the failing order since the order appears on the admin area as "Failed". Is that correct?

The problem we get is that we don't receive the email about the failed order, as admin neither as client (when we test this as a client).

This happens only when a new order is placed and the new payment method is used. For the other payment method, everything works fine. Also if we change the status of any order, the customer and the admin are notified properly.

Thanks!

Try to replace these functions calling with this code:

            fn_change_order_status($order_id, 'C');
            fn_finish_payment($order_id, array('order_status' => "C"), true);

This code is not correct as it will send 3 notifications if the notifications are enabled for the order status.

fn_change_order_status function is called within the fn_finish_payment function, also true parameter is used to send the notifications in the fn_finish_payment and fn_order_placement_routines functions

For failed orders you should change the following part of code:

else {        
            fn_finish_payment($order_id, "F", true);
            echo "Tranzaction failed" . $zcrsp['message'];
        }

for example:

else {        
            fn_finish_payment($order_id, array('order_status' => "F"), true);
            echo "Tranzaction failed" . $zcrsp['message'];
        }

Please try and keep us updated. And pay attention to the $orderid / $order_id issue. Use correct value

This code is not correct as it will send 3 notifications if the notifications are enabled for the order status.

fn_change_order_status function is called within the fn_finish_payment function, also true parameter is used to send the notifications in the fn_finish_payment and fn_order_placement_routines functions

For failed orders you should change the following part of code:

else {        
            fn_finish_payment($order_id, "F", true);
            echo "Tranzaction failed" . $zcrsp['message'];
        }

for example:

else {        
            fn_finish_payment($order_id, array('order_status' => "F"), true);
            echo "Tranzaction failed" . $zcrsp['message'];
        }

Please try and keep us updated. And pay attention to the $orderid / $order_id issue. Use correct value

I updated the

fn_finish_payment($order_id, "F", true);

line, but I still don't receive an email about the failed order.

Also there is no $orderid mentioned on our files anymore. Any other suggestions please?

Thanks!

Can you PM me temporary FTP access to your server? Our specialists will check the issue

Could you provide the full content of this file?

Could you provide the full content of this file?

This is full content of the file:

use Tygh\Bootstrap;
use Tygh\Debugger;
use Tygh\Exceptions\DatabaseException;
use Tygh\Registry;

define('AREA', 'C');

function update_stock($order_info) {
$ids = array();
if (!empty($order_info[‘products’])) {
foreach ($order_info[‘products’] as $k => $v) {
$id = $v[‘product_id’];
$qty = $v[‘amount’];
if($id && $qty) {
$sql = “UPDATE cscart_products SET amount = amount - “.$qty.” WHERE product_id=” . $id . " AND amount >= " . $qty;
db_query($sql);

            $sql = "UPDATE cscart_product_options_inventory SET amount = amount - ".$qty." WHERE product_id=" . $id . " AND amount >= " . $qty;
            db_query($sql);
        }
    }
}

}

try {

    // Register autoloader
    $this_dir = dirname(__FILE__);
    $classLoader = require($this_dir . '/app/lib/vendor/autoload.php');
    $classLoader->add('Tygh', $this_dir . '/app');

    // Prepare environment and process request vars
    list($_REQUEST, $_SERVER) = Bootstrap::initEnv($_GET, $_POST, $_SERVER, $this_dir);
    
    // Get config data
    $config = require(DIR_ROOT . '/config.php');

    if (isset($_REQUEST['version'])) {
        $product_name = (PRODUCT_EDITION == 'ULTIMATE' ? PRODUCT_NAME : 'Multi-Vendor');
        die($product_name . ' ' . PRODUCT_VERSION . ' ' . (PRODUCT_STATUS != '' ? (' (' . PRODUCT_STATUS . ')') : '') . (PRODUCT_BUILD != '' ? (' ' . PRODUCT_BUILD) : '') . '');
    }

    Debugger::init();

    // Start debugger log
    Debugger::checkpoint('Before init');
    
    // Check if software is installed
    if ($config['db_host'] == '%DB_HOST%') {
        $product_name = (PRODUCT_EDITION == 'ULTIMATE' ? PRODUCT_NAME : 'Multi-Vendor');
        die($product_name . ' is not installed. Please click here to start the installation process: [install]');
    }

    // Load core functions
    $fn_list = array(
        'fn.database.php',
        'fn.users.php',
        'fn.catalog.php',
        'fn.cms.php',
        'fn.cart.php',
        'fn.locations.php',
        'fn.common.php',
        'fn.fs.php',
        'fn.images.php',
        'fn.init.php',
        'fn.control.php',
        'fn.search.php',
        'fn.promotions.php',
        'fn.log.php',
        'fn.companies.php',
        'fn.addons.php'
    );

    $fn_list[] = 'fn.' . strtolower(PRODUCT_EDITION) . '.php';

    foreach ($fn_list as $file) {
        require($config['dir']['functions'] . $file);
    }

    Registry::set('class_loader', $classLoader);
    Registry::set('config', $config);
    unset($config);

    // Connect to database
    if (!db_initiate(Registry::get('config.db_host'), Registry::get('config.db_user'), Registry::get('config.db_password'), Registry::get('config.db_name'))) {
        throw new DatabaseException('Cannot connect to the database server');
    }

    register_shutdown_function(array('\\Tygh\\Registry', 'save'));
    
    // define lifetime for the cache data
    date_default_timezone_set('UTC'); // setting temporary timezone to avoid php warnings

    if (defined('API')) {
        fn_init_stack(
            array('fn_init_api')
        );
    }

    fn_init_stack(
        array('fn_init_storage'),
        array('fn_init_ua')
    );

    if (fn_allowed_for('ULTIMATE')) {
        fn_init_stack(array('fn_init_store_params_by_host', &$_REQUEST));
    }

    fn_init_stack(
        array(array('\\Tygh\\Session', 'init'), &$_REQUEST),
        array('fn_init_ajax'),
        array('fn_init_company_id', &$_REQUEST),
        array('fn_check_cache', $_REQUEST),
        array('fn_init_settings'),
        array('fn_init_addons'),
        array('fn_get_route', &$_REQUEST),
        array('fn_simple_ultimate', &$_REQUEST)
    );
    
    if (!fn_allowed_for('ULTIMATE:FREE')) {
        fn_init_stack(array('fn_init_localization', &$_REQUEST));
    }

    fn_init_stack(array('fn_init_language', &$_REQUEST),
        array('fn_init_currency', &$_REQUEST),
        array('fn_init_company_data', $_REQUEST),
        array('fn_init_full_path', $_REQUEST),
        array('fn_init_layout', &$_REQUEST),
        array('fn_init_user'),
        array('fn_init_templater')
    );

} catch (Tygh\Exceptions\AException $e) {
    $e->output();
}

$order_id = $_POST['invoice_id'];
$order_info = fn_get_order_info($order_id);
//print_r($_POST); exit;
// TODO

//print_r($order_info); exit;    
//$key=$processor_data['processor_params']['secret_word'];
$key="8D822SWER2345234530F768B7B1WE2349149";
$zcrsp =  array (
    'amount'     => addslashes(trim(@$_POST['amount'])),  //original amount
    'curr'       => addslashes(trim(@$_POST['curr'])),    //original currency
    'invoice_id' => addslashes(trim(@$_POST['invoice_id'])),//original invoice id
    'ep_id'      => addslashes(trim(@$_POST['ep_id'])), //Euplatesc.ro unique id
    'merch_id'   => addslashes(trim(@$_POST['merch_id'])), //your merchant id
    'action'     => addslashes(trim(@$_POST['action'])), // if action ==0 transaction ok
    'message'    => addslashes(trim(@$_POST['message'])),// transaction responce message
    'approval'   => addslashes(trim(@$_POST['approval'])),// if action!=0 empty
    'timestamp'  => addslashes(trim(@$_POST['timestamp'])),// meesage timestamp
    'nonce'      => addslashes(trim(@$_POST['nonce'])),
    );
    
    $zcrsp['fp_hash'] = strtoupper(euplatesc_mac($zcrsp, $key));

    $fp_hash=addslashes(trim(@$_POST['fp_hash']));
if($zcrsp['fp_hash']===$fp_hash)    {
// start facem update in baza de date
    if($zcrsp['action']=="0") {
        fn_change_order_status($order_id, 'C');
        //fn_finish_payment($order_id, "C", true);
        fn_finish_payment($order_id, array('order_status' => "C"), true);
        fn_order_placement_routines('route', $order_id, true);
        //fn_order_placement_routines_euplatesc($order_id);
        //include "ep_succes.php";
        echo "Successfully completed";
        
        update_stock($order_info);
    }
    else {        
    //include "ep_esec.php";
        fn_finish_payment($order_id, array('order_status' => "F"), true);
        echo "Tranzaction failed" . $zcrsp['message'];
    }
// end facem update in baza de date
}
else {
    echo "Invalid signature";
}

function hmacsha1($key,$data) {
$blocksize = 64;
$hashfunc = ‘md5’;

if(strlen($key) > $blocksize)
$key = pack(‘H*’, $hashfunc($key));

$key = str_pad($key, $blocksize, chr(0x00));
$ipad = str_repeat(chr(0x36), $blocksize);
$opad = str_repeat(chr(0x5c), $blocksize);

$hmac = pack(‘H*’, $hashfunc(($key ^ $opad) . pack(‘H*’, $hashfunc(($key ^ $ipad) . $data))));
return bin2hex($hmac);
}
// ===========================================================================================
function euplatesc_mac($data, $key = NULL)
{
$str = NULL;

foreach($data as $d)
{
if($d === NULL || strlen($d) == 0)
$str .= ‘-’; // valorile nule sunt inlocuite cu -
else
$str .= strlen($d) . $d;
}

$key = pack(‘H*’, $key);

return hmacsha1($key, $str);
}

?>

Thanks for looking into this!

Can you PM me temporary FTP access to your server? Our specialists will check the issue

Our offer is still open. From the first view, I see that the payment method is not integrated according to CS-Cart standards and the code should be reworked.

And where this file is located? What file makes the request to payment gateway? (because this code only receives the data from payment gateway).

All lines from the beginning to $order_id = $_POST['invoice_id']; can be replaced with the only:

define('AREA', 'C');
require(dirname(__FILE__) . '/init.php');

More than that, not $_POST['invoice_id'], but $_REQUEST['invoice_id'] at least. And it will be better to print the parameters which came to this file, using this:

fn_print_die($_REQUEST);

just after require(dirname(__FILE__) . '/init.php');

Or you can print it to a file (if it is backgroun request), with the help of the following:

$f = fopen(DIR_ROOT . '/var/debug.log', 'w');
if ($f) {
    fwrite($f, var_export($_REQUEST, true) . "\n"));
    fclose($f);
}