Notification Mail Not Sent

Hi,

I'm having having with some mail notifications.

When someone places an order and pays with credit card, the order lands in CS-Cart as Paid (Status "P").

After that, neither me, or the customer gets a notification mail that a new order have been placed. When an order comes, with any other payment method, the order lands as open and mail notification sents normaly.

Any suggestions on what i should look at to solve my problem?

Bellow you can see the code the from payment method, in case you think that its related to my issue. Seems fine to me, and works without no errors

use Tygh\Http;
use Tygh\Registry;

if (!defined(‘BOOTSTRAP’)) { die(‘Access denied’); }

if (defined(‘PAYMENT_NOTIFICATION’)) {

if ($mode == 'notify') {
	
    $order_id = (strpos($_REQUEST['MerchantReference'], '_')) ? substr($_REQUEST['MerchantReference'], 0, strpos($_REQUEST['MerchantReference'], '_')) : $_REQUEST['MerchantReference'];
    $order_info = fn_get_order_info($order_id);
    $processor_data = fn_get_payment_method_data($order_info['payment_id']);

    $pp_response = array();
    $pp_response['transaction_id'] = $_REQUEST['TransactionId'];
    $pp_response['transaction_datetime'] = $_REQUEST['TransactionDateTime'];
    $pp_response['reason_text'] = $_REQUEST['ResponseDescription'];

    if ($_REQUEST['ResultCode'] == 0) {
        if ( $_REQUEST['StatusFlag'] == 'Success' && in_array($_REQUEST['ResponseCode'], array('00', '08', '10', '11', '16')) ) {

            $tran_ticket = db_get_field("SELECT data FROM ?:order_data WHERE type = 'E' AND order_id = ?i", $order_id);

            $cart_hashkey_str = $tran_ticket.';'.$processor_data['processor_params']['posid'].';'.$processor_data['processor_params']['acquirerid'].';'.$_REQUEST['MerchantReference'].';'.$_REQUEST['ApprovalCode'].';'.$_REQUEST['Parameters'].';'.$_REQUEST['ResponseCode'].';'.$_REQUEST['SupportReferenceID'].';'.$_REQUEST['AuthStatus'].';'.$_REQUEST['PackageNo'].';'.$_REQUEST['StatusFlag'];
			$cart_hashkey = strtoupper(hash_hmac('sha256', $cart_hashkey_str, $tran_ticket));

            if ($cart_hashkey == $_REQUEST['HashKey']) {
                $pp_response['order_status'] = 'P';

                db_query("DELETE FROM ?:order_data WHERE type = 'E' AND order_id = ?i", $order_id);

                if (!empty($_REQUEST['SupportReferenceID'])) {
                    $pp_response['reason_text'] .= '; SupportReferenceID: ' . $_REQUEST['SupportReferenceID'];
                }

                if (!empty($_REQUEST['ApprovalCode'])) {
                    $pp_response['reason_text'] .= '; ApprovalCode: ' . $_REQUEST['ApprovalCode'];
                }

            } else {
                $pp_response['order_status'] = 'F';
                $pp_response['reason_text'] .= 'Hash value is incorrect';
            }
        } elseif ($_REQUEST['StatusFlag'] == 'Failure') {
            $pp_response['order_status'] = 'F';

        } elseif ($_REQUEST['StatusFlag'] == 'Asynchronous') {
            $pp_response['order_status'] = 'O';
            $pp_response['reason_text'] .= '; Asynchronous';
        }

    } else {
        $pp_response['order_status'] = 'F';
    }

    if (fn_check_payment_script('winpay.php', $order_id)) {
        fn_finish_payment($order_id, $pp_response, false);
    }

    fn_order_placement_routines('route', $order_id);
} elseif ($mode == 'cancel') {

    if (!empty($_SESSION['stored_piraeus_orderid'])) {
        $order_id = $_SESSION['stored_piraeus_orderid'];
        unset($_SESSION['stored_piraeus_orderid']);
    } else {
        fn_order_placement_routines('checkout_redirect');
    }

    $pp_response['order_status'] = 'N';
    $pp_response["reason_text"] = __('text_transaction_cancelled');

    if (fn_check_payment_script('piraeus.php', $order_id)) {
        fn_finish_payment($order_id, $pp_response, false);
    }

    fn_order_placement_routines('route', $order_id);
}

} else {

if (!empty($payment_info['installments'])) {

    if (Registry::get('addons.winpay.show_all_installments') == 'Y') {
		$installment = db_get_row('SELECT * FROM ?:winpay_installments WHERE installment_id = ?i', $payment_info['installment_id']);
		$installment['installments'] = $payment_info['installments'];
	} else {
		$installment = db_get_row('SELECT * FROM ?:winpay_installments WHERE installment_id = ?i', $payment_info['installments']);
	}
	$ab_interest = $order_info['total'] * ($installment['p_interest']/100) + $installment['a_interest'];
	$ab_total = $order_info['total'] + $ab_interest;
	$ab_payment_surcharge = $ab_interest + $order_info['payment_surcharge'];
	db_query("UPDATE ?:orders SET ?u WHERE order_id = ?i", array('total' => $ab_total, 'payment_surcharge' => $ab_payment_surcharge), $order_info['order_id']);
	$order_info['total'] = $ab_total;
	$period = $installment['installments'];

	$_data = array (
		'order_id' => $order_id,
		'type' => 'P', //payment information
		'data' => fn_encrypt_text(serialize(array('installments' => $period))),
	);

	db_query("REPLACE INTO ?:order_data ?e", $_data);

} else {

	$period = 0;

}

$ticketing_data = Array (
    'AcquirerId' => $processor_data['processor_params']['acquirerid'],
    'MerchantId' => $processor_data['processor_params']['merchantid'],
    'PosId' => $processor_data['processor_params']['posid'],
    'Username' => $processor_data['processor_params']['username'],
    'Password' => md5($processor_data['processor_params']['password']),
    'RequestType' => $processor_data['processor_params']['requesttype'],
    'CurrencyCode' => $processor_data['processor_params']['currencycode'],
    'MerchantReference' => (($order_info['repaid']) ? ($order_id . '_' . $order_info['repaid']) : $order_id),
    'Amount' => $order_info['total'],
    'Installments' => $period,
    'Bnpl' => 0,
    'ExpirePreauth' => (($processor_data['processor_params']['requesttype'] == '00') ? $processor_data['processor_params']['expirepreauth'] : '0'),
    'Parameters' => '',
    'MyBank' => (isset($processor_data['processor_params']['mybank']) && $processor_data['processor_params']['mybank'] == 'Y') ? 'yes' : 'no',
);

$str = <<

http://www.w3.org/2001/XMLSchema-instance” xmlns:xsd=“XML Schema” xmlns:soap=“http://schemas.xmlsoap.org/soap/envelope/”>
soap:Body


EOT;
$str .= fn_array_to_xml($ticketing_data);
$str .= <<



EOT;
$str = str_replace(array(“\t”, “\n”, “\r”), ‘’, $str);

$response_data = Http::post("https://paycenter.piraeusbank.gr/services/tickets/issuer.asmx", $str, array(
    'headers' => array(
        'Content-type: text/xml; charset=utf-8',
        'SOAPAction: http://piraeusbank.gr/paycenter/redirection/IssueNewTicket'
    )
));

$resultcode = true;
$pp_response = array();

if (strpos($response_data, ']*>([^>]+)!', $response_data, $matches)) {
        $resultcode = $matches[1];
    }
}

if ($resultcode == "0") {

    if (strpos($response_data, ']*>([^>]+)!', $response_data, $matches)) {
            $data = array (
                'order_id' => $order_id,
                'type' => 'E',
                'data' => $matches[1],
            );
            db_query("REPLACE INTO ?:order_data ?e", $data);
        }
    }

    $post_url = 'https://paycenter.piraeusbank.gr/redirection/pay.aspx';

    $post_data = array (
        'AcquirerId' => $processor_data['processor_params']['acquirerid'],
        'MerchantId' => $processor_data['processor_params']['merchantid'],
        'PosId' => $processor_data['processor_params']['posid'],
        'User' => $processor_data['processor_params']['username'],
        'LanguageCode' => $processor_data['processor_params']['languagecode'],
        'MerchantReference' => (($order_info['repaid']) ? ($order_id . '_' . $order_info['repaid']) : $order_id),
        'ParamBackLink' => ""
    );

    $_SESSION['stored_piraeus_orderid'] = $order_id;

    fn_create_payment_form($post_url, $post_data, 'Piraeus server');
exit;

} else {
    $pp_response['order_status'] = 'F';
    $pp_response["ResultCode"] = $resultcode;

    if (strpos($response_data, ']*>([^>]+)!', $response_data, $matches)) {
            $pp_response["reason_text"] = $matches[1];
        }
    }
}

}

Try to replace (2 lines)

fn_order_placement_routines('route', $order_id);

with

fn_order_placement_routines('route', $order_id, true);

Try to replace (2 lines)

fn_order_placement_routines('route', $order_id);

with

fn_order_placement_routines('route', $order_id, true);

Thank you eComLabs. I'll give it a try and i'll let you know!

Well, that didn't solve my problem. I'm running CS-Cart 4.11.5. I was aware for a bug with cs-cart 4.9-4.11.4 that after the chrome upgrade the jQuery had to be updated, otherwise the old jQuery version was redirecting the customers after the payment to the log in page and not to the thank you page.

As log as i run 4.11.5 version thats not an issue for me because in the last cs-cart upgrade the jQuery version got updated too.

Any other suggestions?

Sounds obvious, but double check the settings for the "orders department" email address. Ensure it doesn't have any leading/trailing whitespace since cs-cart is not very good at trimming data.

Sounds obvious, but double check the settings for the "orders department" email address. Ensure it doesn't have any leading/trailing whitespace since cs-cart is not very good at trimming data.

Did that too and its fine. I just have to mention again, that the e-mail not get sent only when a customer makes payment by card. With any other payment method everything works fine.

Well, that didn't solve my problem

Did you change 2 lines? Additional parameter should force order notification

Yes i changed both lines and cleared cache too

Please also make sure that the following emails are enabled

Administration -> Notifications -> Customer notifications -> Order status changed to Paid

Administration -> Notifications -> Administrator notifications -> Order status changed to Paid

I would like to post an update for this problem.

I have done everthing you told me so far and nothing worked. Seems like i have a idea about what could cause the problem of mail not beeing sent and i would like to share it with you for.

After the payment is succesfully done on the bank's website, when the customer is redirecting back to the e-shop, insteand of landing to the "Thank you" page, is landing to the "Log in/Register" page and the URL seems like this:

/index.php?dispatch=auth.login_form&return_url=index.php%3Fdispatch%3Dcheckout.complete%26order_id%3D1110

I thinking that if the customer is not landing to "Thank you" page may cause the problem with mail notifications.

Right now i'm using a clean in build CS-Cart payment method the "Winbank (Piraeus) Redirection" on CS-Cart Version 4.11.5 (/app/payments/piraeus.php).

After the payment is succesfully done on the bank's website, when the customer is redirecting back to the e-shop, insteand of landing to the "Thank you" page, is landing to the "Log in/Register" page and the URL seems like this:

Several users here wrote about the same issue. Please make a post in the bug tracker

The problem is with cookie policy on Google Chrome after version 80.

Its about the cookies where the SameSite has no value so they are considered as SameSite=Lax. Cookies that are included in cross-site requests should be SameSite=None and Secure.

So when bank is running a cross-site request like POST request, after the payment towards the store in order to refresh the order status and get the order confirmation page

PHP 7.3 ships the feature natively. Before that you need a library liek https://github.com/delight-im/PHP-Cookie

Thanks Fotis... So much to keep up on! :-)

I have the same issue with no notifications being sent when an order is placed and paid with credit card.
using stock Virtual Merchant payment processor, order shows up as paid in admin but no notifications get sent, customer, supplier or admin.
If I enter admin and click "update" without making any changes, all notifications go out but nothing happens when the order is originally placed by customer

have checked all the mentioned issues in forum I could find but am pulling my hair out on this.

latest version of CS-Cart Ultimate 4.13.1.SP2, no 3rd party addons or themes

site does NOT redirect to log-in like poster above but successfully arrives at checkout success page

/index.php?dispatch=checkout.complete&order_id=102&ssl_partner_app_id=01

for reference here is the virtual_merchant.php file that comes with CS-Cart that I am using

if (!defined(‘BOOTSTRAP’)) { die(‘Access denied’); }

if (defined(‘PAYMENT_NOTIFICATION’)) {
$processor_error = array (
‘status’ => array(
‘APPROVAL’ => ‘P’,
‘APPROVED’ => ‘P’,
‘ACCEPTED’ => ‘O’,
‘BAL.: 99999999.99’ => ‘O’,
‘PICK UP CARD’ => ‘O’,
‘AMOUNT ERROR’ => ‘D’,
‘APPL TYPE ERROR’ => ‘O’,
‘DECLINED’ => ‘D’,
‘DECLINED-HELP 9999’ => ‘F’,
‘EXCEEDS BAL.’ => ‘D’,
‘EXPIRED CARD’ => ‘D’,
‘INVALID CARD’ => ‘D’,
‘INCORRECT PIN’ => ‘F’,
‘INVALID TERM ID’ => ‘F’,
‘INVLD TERM ID 1’ => ‘F’,
‘INVLD TERM ID 2’ => ‘F’,
‘INVLD VOID DATA’ => ‘F’,
‘MUST SETTLE MMDD’ => ‘F’,
‘ON FILE’ => ‘D’,
‘RECORD NOT FOUND’ => ‘F’,
‘FOUND SERV NOT ALLOWED’ => ‘F’,
‘SEQ ERR PLS CALL’ => ‘O’,
‘CALL AUTH.’ => ‘O’,
‘CENTER CALL REF.; 999999’ => ‘O’,
‘DECLINE CVV2’ => ‘D’
),
‘result’ => array(
‘APPROVAL’ => ‘Approved’,
‘APPROVED’ => ‘Approved’,
‘ACCEPTED’ => ‘Frequency Approval’,
‘BAL.: 99999999.99’ => ‘Debit Card Balance Inquiry Response’,
‘PICK UP CARD’ => ‘Pick up card’,
‘AMOUNT ERROR’ => ‘Tran Amount Error’,
‘APPL TYPE ERROR’ => ‘Call for Assistance’,
‘DECLINED’ => ‘Transaction Declined, Please check your billing address and credit card info and try again’,
‘DECLINED-HELP 9999’ => ‘System Error’,
‘EXCEEDS BAL.’ => ‘Req. exceeds balance’,
‘EXPIRED CARD’ => ‘Expired Card’,
‘INVALID CARD’ => ‘Invalid Card’,
‘INCORRECT PIN’ => ‘Invalid PIN’,
‘INVALID TERM ID’ => ‘Invalid Terminal ID’,
‘INVLD TERM ID 1’ => ‘Invalid Merchant Number’,
‘INVLD TERM ID 2’ => ‘Invalid SE Number’,
‘INVLD VOID DATA’ => ‘Invalid Data’,
‘MUST SETTLE MMDD’ => ‘Must settle POS Device, open batch is more than 7 days old.’,
‘ON FILE’ => ‘Cardholder not found’,
‘RECORD NOT FOUND’ => ‘Record not on Host’,
‘FOUND SERV NOT ALLOWED’ => ‘Invalid request’,
‘SEQ ERR PLS CALL’ => ‘Call for Assistance’,
‘CALL AUTH.’ => ‘Refer to Issuer’,
‘CENTER CALL REF.; 999999’ => ‘Refer to Issuer’,
‘DECLINE CVV2’ => ‘Do Not Honor; Declined due to CVV2 mismatch/failure’
),
‘avs’ => array(
‘A’ => ‘Address (Street) matches, ZIP does not’,
‘E’ => ‘AVS error’,
‘N’ => ‘No Match on Address (Street) or ZIP’,
‘P’ => ‘AVS not applicable for this transaction’,
‘R’ => ‘Retry. System unavailable or timed out’,
‘S’ => ‘Service not supported by issuer’,
‘U’ => ‘Address information is unavailable’,
‘W’ => ‘9 digit ZIP matches, Address (Street) does not’,
‘X’ => ‘Exact AVS Match’,
‘Y’ => ‘Address (Street) and 5 digit ZIP match’,
‘Z’ => ‘5 digit ZIP matches, Address (Street) does not’
),
‘cvv’ => array(
‘M’ => ‘Match’,
‘N’ => ‘No Match’,
‘P’ => ‘Not Processed’,
‘S’ => ‘Should have been present’,
‘U’ => ‘Issuer unable to process request’
)
);

$pp_response = array();

if ($mode == 'notify' && !empty($_REQUEST['order_id']) && !empty($_REQUEST['ssl_result_message']) && isset($_REQUEST['ssl_result'])) {

    $pp_response['order_status'] = $processor_error['status'][$_REQUEST['ssl_result_message']];
    $pp_response['reason_text'] = $processor_error['result'][$_REQUEST['ssl_result_message']];
    $pp_response['transaction_id'] = $_REQUEST['ssl_txn_id'];
    $pp_response['descr_avs'] = $processor_error['avs'][$_REQUEST['ssl_avs_response']];
    $pp_response['descr_cvv'] = $processor_error['cvv'][$_REQUEST['ssl_cvv2_response']];

} elseif ($mode == 'error' && !empty($_REQUEST['order_id'])) {

    $pp_response['order_status'] = 'F';
    $pp_response['errorCode'] = str_replace('?', '', $_REQUEST['?errorCode']);
    $pp_response['errorName'] = $_REQUEST['errorName'];
    $pp_response['reason_text'] = $_REQUEST['errorMsg'];

} else {
    $pp_response['order_status'] = 'F';
    $pp_response['reason_text'] =  __('error');;
}

if (fn_check_payment_script('virtual_merchant.php', $_REQUEST['order_id'])) {
    fn_finish_payment($_REQUEST['order_id'], $pp_response, false);
}

fn_order_placement_routines('route', $_REQUEST['order_id']);

} else {

$post_data['ssl_invoice_number'] = ($order_info['repaid']) ? ($order_id .'_'. $order_info['repaid']) : $order_id;
$post_data['ssl_merchant_id'] = $processor_data['processor_params']['merchant_id'];
$post_data['ssl_user_id'] = $processor_data['processor_params']['user_id'];
$post_data['ssl_pin'] = $processor_data['processor_params']['user_pin'];
$post_data['ssl_customer_code'] = $order_info['user_id'] ? $order_info['user_id'] : 'n/a';
$post_data['ssl_salestax'] = fn_format_price($order_info['tax_subtotal']);
$post_data['ssl_description'] = $processor_data['processor_params']['order_prefix'].$order_id;
$post_data['ssl_test_mode'] = $processor_data['processor_params']['mode'] == 'live' ? 'FALSE' : 'TRUE';
$post_data['ssl_receipt_link_url'] = fn_url("payment_notification.notify?payment=virtual_merchant&order_id=$order_id&", AREA, 'http');
$post_data['ssl_error_url'] = fn_url("payment_notification.error?payment=virtual_merchant&order_id=$order_id&", AREA, 'http');
$post_data['ssl_receipt_link_method'] = 'REDG';
$post_data['ssl_amount'] = $order_info['total'];
$post_data['ssl_transaction_type'] = 'ccSALE';
$post_data['ssl_card_number'] = $order_info['payment_info']['card_number'];
$post_data['ssl_exp_date'] = $order_info['payment_info']['expiry_month'] . '' . $order_info['payment_info']['expiry_year'];
$post_data['ssl_company'] = $order_info['company'];
$post_data['ssl_first_name'] = $order_info['b_firstname'];
$post_data['ssl_last_name'] = $order_info['b_lastname'];
$post_data['ssl_avs_address'] = $order_info['b_address'];
$post_data['ssl_city'] = $order_info['b_city'];
$post_data['ssl_state'] = $order_info['b_state'] ? $order_info['b_state'] : 'n/a';
$post_data['ssl_avs_zip'] = fn_vm_process_zip($order_info['b_zipcode']);
$post_data['ssl_country'] = $order_info['b_country'];
$post_data['ssl_phone'] = $order_info['phone'];
$post_data['ssl_email'] = $order_info['email'];
$post_data['ssl_ship_to_company'] = $order_info['company'];
$post_data['ssl_ship_to_first_name'] = $order_info['s_firstname'];
$post_data['ssl_ship_to_last_name'] = $order_info['s_lastname'];
$post_data['ssl_ship_to_address'] = $order_info['s_address'];
$post_data['ssl_ship_to_city'] = $order_info['s_city'];
$post_data['ssl_ship_to_state'] = $order_info['s_state'] ? $order_info['s_state'] : 'n/a';
$post_data['ssl_ship_to_country'] = $order_info['s_country'];
$post_data['ssl_ship_to_zip'] = fn_vm_process_zip($order_info['s_zipcode']);
$post_data['ssl_show_form'] = 'FALSE';

if ($processor_data['processor_params']['avs'] == 'Y') {
    $post_data['ssl_avs_address'] = $order_info['b_address'];
    $post_data['ssl_avs_zip'] = fn_vm_process_zip($order_info['b_zipcode']);
}
if ($processor_data['processor_params']['cvv2'] && !empty($order_info['payment_info']['cvv2'])) {
    $post_data['ssl_cvv2cvc2_indicator'] = '1';
    $post_data['ssl_cvv2cvc2'] = $order_info['payment_info']['cvv2'];
}

$post_url = ($processor_data['processor_params']['mode'] != 'demo')? "https://www.myvirtualmerchant.com/VirtualMerchant/process.do" : "https://demo.myvirtualmerchant.com/VirtualMerchantDemo/process.do";

fn_create_payment_form($post_url, $post_data, 'Virtual Merchant');
exit;

}

function fn_vm_process_zip($str)
{
if (!empty($str)) {
$str = preg_replace(‘/[^0-9]/’, ‘’, $str);
}

return $str;

}

Try to force notification. To do it, please replace

fn_order_placement_routines('route', $_REQUEST['order_id']);

with

fn_order_placement_routines('route', $_REQUEST['order_id'], true);

Try to force notification. To do it, please replace

fn_order_placement_routines('route', $_REQUEST['order_id']);

with

fn_order_placement_routines('route', $_REQUEST['order_id'], true);

sadly that made no difference.
no notifications sent when order placed by credit card.
order shows in admin as paid but not a single notification gets sent until I manually open the order and click save changes (without making any changes) and making sure the boxes are checked for admin, supplier and customer get notified

just a thought here, it seems that the system is set up to send notifications when status is "changed" to paid. but it appears that it does nothing when an order is 1st created with the status of "paid" as happens when using an online credit card processor.

stock install does not include a status of "processing" as I have seen mentioned in the documentation
again, using latest version of CS-Cart Ultimate 4.13.1.SP2, no 3rd party addons or themes
1st Installed 4.11.5 and upgraded as they became available

All order start out as N (incomplete). If not payment processing they generally go to O (open) and if payment processing either F, D or P (failed, declined, paid/processed). Don't confuse the language values for the text representations versus the actual status code.

All order start out as N (incomplete). If not payment processing they generally go to O (open) and if payment processing either F, D or P (failed, declined, paid/processed). Don't confuse the language values for the text representations versus the actual status code.

Here are the statuses available as per the page ?dispatch=statuses.manage

Paid - P
Shipped - E
Complete - C
Open - O
Failed - F
Declined - D
Backordered - B
Canceled - I
Awaiting call - Y
Fraud checking - A

There is no N anywhere I can see

That's because it is an internal and hidden status. I.e. the initial value. If the order has all it's component parts, then fn_change_order_status() will be called with the appropriate new status and that will (or may) generate notifications.