From 64eec635dad80a1a765e273ff4a281ca0295a181 Mon Sep 17 00:00:00 2001 From: Ganesh R Date: Thu, 23 Apr 2026 20:05:27 +0530 Subject: [PATCH 1/7] Added Retry Card option when payment failed. --- src/cc.inc.php | 111 ++++++++++++++++++++++++------------------------- 1 file changed, 54 insertions(+), 57 deletions(-) diff --git a/src/cc.inc.php b/src/cc.inc.php index 6aa9ee9..61a25ab 100644 --- a/src/cc.inc.php +++ b/src/cc.inc.php @@ -243,61 +243,6 @@ function format_cc_exp() return $value; } -/** -* generates a cc decline email body -* -* @param int $custid the customer id # -* @param int $invoice_id the invoice id # -* @return array array w/ the information needed to send an email or display the cc decline -* @throws \Exception -* @throws \SmartyException -*/ -function make_cc_decline($custid, $invoice_id) -{ - $admin_dir = INSTALL_ROOT; - $data = $GLOBALS['tf']->accounts->read($custid); - $domain = $GLOBALS['tf']->accounts->cross_reference($custid); - $groupinfo = get_groupinfo($domain); - if ($groupinfo['email'] != '') { - $emailfrom = $groupinfo['email']; - } else { - $emailfrom = EMAIL_FROM; - } - $smarty = new TFSmarty(); - $smarty->assign('invoice_id', $invoice_id); - $smarty->assign('customer_domain', $domain); - $smarty->assign('customer_id', $custid); - $smarty->assign('customer_name', $data['name']); - $smarty->assign('company_name', $groupinfo['account_lid']); - $invoice_data = get_invoice($invoice_id); - $smarty->assign('customer_balance', $invoice_data['invoices_amount']); - if (DOMAIN == 'interserver.net' || trim(DOMAIN) == '') { - $smarty->assign('url', 'my.interserver.net'); - } else { - $smarty->assign('url', DOMAIN.URLDIR); - } - $ret_invoice['invoice'] = $smarty->fetch('email/client/ccdecline.tpl'); - $ret_invoice['toname'] = $data['name']; - $ret_invoice['toemail'] = get_invoices_email($data); - $ret_invoice['subject'] = 'Problem With Account '.$domain; - $ret_invoice['fromname'] = $groupinfo['account_lid'].' Billing Department'; - $ret_invoice['fromemail'] = $emailfrom; - return $ret_invoice; -} - -/** -* sends a cc decline email -* -* @param int $custid -* @param mixed $invoice_id -* @return void -*/ -function email_cc_decline($custid, $invoice_id) -{ - $email = make_cc_decline($custid, $invoice_id); - myadmin_log('billing', 'debug', ' Emailing CC Decline Message To '.$email['toname'], __LINE__, __FILE__); - (new \MyAdmin\Mail())->multiMail($email['subject'], '
'.$email['invoice'].'
', $email['toemail'], 'client/ccdecline.tpl'); -} /** * given the account data array, it parses out and returns an array of ccs @@ -569,7 +514,6 @@ function charge_card($custid, $amount = false, $invoice = false, $module = 'defa return $retval; } //$data['status'] = 'pending-fixcc'; - $GLOBALS['tf']->accounts->update($custid, ['payment_method' => 'paypal']); $subject = $settings['TITLE'].' Credit Card Payment Declined'; $smarty = new TFSmarty(); $smarty->assign('amount', $amount); @@ -620,7 +564,25 @@ function charge_card($custid, $amount = false, $invoice = false, $module = 'defa $smarty->assign('invoices', $rows); $email = $smarty->fetch('email/client/payment_failed.tpl'); (new \MyAdmin\Mail())->multiMail($subject, $email, get_invoice_email($data), 'client/payment_failed.tpl'); - //email_cc_decline($custid, $invoice); + + //"ot_cc" is added because it came from pay_balance where they try specific card so no retry for that. + if ( + count($ccs) > 1 && //more than 1 cc present then proceed + RETRY_CC == 1 && //When CC Retry is enabled from config + ( + !isset($GLOBALS['tf']->variables->request['ot_cc']) || //This confirms that it is not from cart/paybalance page + isset($GLOBALS['tf']->variables->request['retry_cc']) // This confirms its from retry + ) + ) { + $cc_encrypted = $GLOBALS['tf']->encrypt(trim(str_replace([' ', '_', '-'], ['', '', ''], $cc))); + $GLOBALS['tf']->history->add('users', 'carddecline', $cc_encrypted, $cc_exp, $custid); + retry_charge_card($custid, $amount, $invoice, $module, $returnURL, $useHandlePayment, $queue); + } + $new_data = [ + 'payment_method' => 'paypal', + 'cc_auto' => '0' + ]; + App::accounts()->update($custid, $new_data); //$GLOBALS['tf']->history->add('users', 'carddecline', $data['cc'], $data['cc_exp'], $custid); break; } @@ -752,6 +714,41 @@ function auth_charge_card($custid, $cc, $cc_exp, $amount, $module = 'default', $ return $retval; } +/** + * Gets next available verified CC number to charge + * + */ +function get_next_cc($custid) +{ + function_requirements('parse_ccs'); + $data = App::accounts()->read($custid); + $db = get_module_db('default'); + $db->query("SELECT * FROM user_log WHERE history_owner = {$custid} AND history_type = 'carddecline'", __LINE__, __FILE__); + if ($db->num_rows() > 0) { + while ($db->next_record(MYSQL_ASSOC)) { + $dec_ccs[] = $GLOBALS['tf']->decrypt($db->Record['history_new_value']); + } + } + foreach ($ccs as $cc_id => $cc_det) { + $cc_num = $GLOBALS['tf']->decrypt($cc_det['cc']); + if (!in_array($cc_num, $dec_ccs) && can_use_cc($data, $cc_det, false)) { + return $cc_id; + } + } + return false; +} + +function retry_charge_card($custid, $amount = false, $invoice = false, $module = 'default', $returnURL = false, $useHandlePayment = true, $queue = false) +{ + $next_cc = get_next_cc($custid); + if ($next_cc !=== false) { + $GLOBALS['tf']->variables->request['ot_cc'] = $cc_id; + $GLOBALS['tf']->variables->request['retry_cc'] = 1; + charge_card($custid, $amount, $invoice, $module, $returnURL, $useHandlePayment, $queue); + } + return false; +} + /** * gets the cc bank number / bin for the given encrypted cc * From 474f47cb5638ece36c5fc6698594c66c4a14f6d5 Mon Sep 17 00:00:00 2001 From: Ganesh R Date: Thu, 23 Apr 2026 20:17:13 +0530 Subject: [PATCH 2/7] Minor syntax err - fixes --- src/cc.inc.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cc.inc.php b/src/cc.inc.php index 61a25ab..0b90241 100644 --- a/src/cc.inc.php +++ b/src/cc.inc.php @@ -741,7 +741,7 @@ function_requirements('parse_ccs'); function retry_charge_card($custid, $amount = false, $invoice = false, $module = 'default', $returnURL = false, $useHandlePayment = true, $queue = false) { $next_cc = get_next_cc($custid); - if ($next_cc !=== false) { + if ($next_cc !== false) { $GLOBALS['tf']->variables->request['ot_cc'] = $cc_id; $GLOBALS['tf']->variables->request['retry_cc'] = 1; charge_card($custid, $amount, $invoice, $module, $returnURL, $useHandlePayment, $queue); From 402575bccd50dc4af53c891bc2a02b3c8d995c04 Mon Sep 17 00:00:00 2001 From: Ganesh R Date: Thu, 23 Apr 2026 20:30:28 +0530 Subject: [PATCH 3/7] App class usage issue fix --- src/cc.inc.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/cc.inc.php b/src/cc.inc.php index 0b90241..6e6cc52 100644 --- a/src/cc.inc.php +++ b/src/cc.inc.php @@ -582,7 +582,8 @@ function charge_card($custid, $amount = false, $invoice = false, $module = 'defa 'payment_method' => 'paypal', 'cc_auto' => '0' ]; - App::accounts()->update($custid, $new_data); + //App::accounts()->update($custid, $new_data); + $GLOBALS['tf']->accounts->update($custid, $new_data); //$GLOBALS['tf']->history->add('users', 'carddecline', $data['cc'], $data['cc_exp'], $custid); break; } @@ -721,7 +722,8 @@ function auth_charge_card($custid, $cc, $cc_exp, $amount, $module = 'default', $ function get_next_cc($custid) { function_requirements('parse_ccs'); - $data = App::accounts()->read($custid); + //$data = App::accounts()->read($custid); + $data = $GLOBALS['tf']->accounts->read($custid); $db = get_module_db('default'); $db->query("SELECT * FROM user_log WHERE history_owner = {$custid} AND history_type = 'carddecline'", __LINE__, __FILE__); if ($db->num_rows() > 0) { From 3a03279e1760a54658c2802aaf74f3f2d9c3a284 Mon Sep 17 00:00:00 2001 From: Ganesh R Date: Thu, 23 Apr 2026 22:28:26 +0530 Subject: [PATCH 4/7] Few updates --- src/cc.inc.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/cc.inc.php b/src/cc.inc.php index 6e6cc52..851086a 100644 --- a/src/cc.inc.php +++ b/src/cc.inc.php @@ -10,6 +10,7 @@ use Punic\Currency; use Brick\Money\Money; use Brick\Math\RoundingMode; +use MyAdmin/App; /** * @param $cc @@ -582,8 +583,7 @@ function charge_card($custid, $amount = false, $invoice = false, $module = 'defa 'payment_method' => 'paypal', 'cc_auto' => '0' ]; - //App::accounts()->update($custid, $new_data); - $GLOBALS['tf']->accounts->update($custid, $new_data); + App::accounts()->update($custid, $new_data); //$GLOBALS['tf']->history->add('users', 'carddecline', $data['cc'], $data['cc_exp'], $custid); break; } @@ -722,8 +722,7 @@ function auth_charge_card($custid, $cc, $cc_exp, $amount, $module = 'default', $ function get_next_cc($custid) { function_requirements('parse_ccs'); - //$data = App::accounts()->read($custid); - $data = $GLOBALS['tf']->accounts->read($custid); + $data = App::accounts()->read($custid); $db = get_module_db('default'); $db->query("SELECT * FROM user_log WHERE history_owner = {$custid} AND history_type = 'carddecline'", __LINE__, __FILE__); if ($db->num_rows() > 0) { @@ -731,6 +730,7 @@ function_requirements('parse_ccs'); $dec_ccs[] = $GLOBALS['tf']->decrypt($db->Record['history_new_value']); } } + $ccs = parse_ccs($data); foreach ($ccs as $cc_id => $cc_det) { $cc_num = $GLOBALS['tf']->decrypt($cc_det['cc']); if (!in_array($cc_num, $dec_ccs) && can_use_cc($data, $cc_det, false)) { From b8f9fa3c2d006a08e336cef1c4eba611c03f7f54 Mon Sep 17 00:00:00 2001 From: Ganesh R Date: Thu, 23 Apr 2026 22:45:49 +0530 Subject: [PATCH 5/7] Added logs for tracking and other updates --- src/cc.inc.php | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/src/cc.inc.php b/src/cc.inc.php index 851086a..4fa90e6 100644 --- a/src/cc.inc.php +++ b/src/cc.inc.php @@ -10,7 +10,7 @@ use Punic\Currency; use Brick\Money\Money; use Brick\Math\RoundingMode; -use MyAdmin/App; +use MyAdmin\App; /** * @param $cc @@ -570,13 +570,19 @@ function charge_card($custid, $amount = false, $invoice = false, $module = 'defa if ( count($ccs) > 1 && //more than 1 cc present then proceed RETRY_CC == 1 && //When CC Retry is enabled from config - ( - !isset($GLOBALS['tf']->variables->request['ot_cc']) || //This confirms that it is not from cart/paybalance page - isset($GLOBALS['tf']->variables->request['retry_cc']) // This confirms its from retry - ) + (!isset(App::variables()->request['ot_cc']) || isset(App::variables()->request['retry_cc'])) ) { $cc_encrypted = $GLOBALS['tf']->encrypt(trim(str_replace([' ', '_', '-'], ['', '', ''], $cc))); - $GLOBALS['tf']->history->add('users', 'carddecline', $cc_encrypted, $cc_exp, $custid); + $dec_ccs = []; + $db->query("SELECT * FROM user_log WHERE history_owner = {$custid} AND history_type = 'carddecline'", __LINE__, __FILE__); + if ($db->num_rows() > 0) { + while ($db->next_record(MYSQL_ASSOC)) { + $dec_ccs[] = $GLOBALS['tf']->decrypt($db->Record['history_new_value']); + } + } + if (!in_array($cc, $dec_ccs)) { + $GLOBALS['tf']->history->add('users', 'carddecline', $cc_encrypted, $cc_exp, $custid); + } retry_charge_card($custid, $amount, $invoice, $module, $returnURL, $useHandlePayment, $queue); } $new_data = [ @@ -723,6 +729,7 @@ function get_next_cc($custid) { function_requirements('parse_ccs'); $data = App::accounts()->read($custid); + $dec_ccs = []; $db = get_module_db('default'); $db->query("SELECT * FROM user_log WHERE history_owner = {$custid} AND history_type = 'carddecline'", __LINE__, __FILE__); if ($db->num_rows() > 0) { @@ -734,18 +741,21 @@ function_requirements('parse_ccs'); foreach ($ccs as $cc_id => $cc_det) { $cc_num = $GLOBALS['tf']->decrypt($cc_det['cc']); if (!in_array($cc_num, $dec_ccs) && can_use_cc($data, $cc_det, false)) { + myadmin_log('billing', 'info', "Backup cc - found $custid ".mask_cc($cc_num), __LINE__, __FILE__); return $cc_id; } } + myadmin_log('billing', 'info', "Backup cc - not found for $custid", __LINE__, __FILE__); return false; } function retry_charge_card($custid, $amount = false, $invoice = false, $module = 'default', $returnURL = false, $useHandlePayment = true, $queue = false) { + myadmin_log('billing', 'info', "Retrying backupcc: $custid $amount", __LINE__, __FILE__); $next_cc = get_next_cc($custid); if ($next_cc !== false) { - $GLOBALS['tf']->variables->request['ot_cc'] = $cc_id; - $GLOBALS['tf']->variables->request['retry_cc'] = 1; + App::variables()->request['ot_cc'] = $cc_id; + App::variables()->request['retry_cc'] = 1; charge_card($custid, $amount, $invoice, $module, $returnURL, $useHandlePayment, $queue); } return false; From 5c5fad53ca8bf704125d4c36353d9be35aa1fcd9 Mon Sep 17 00:00:00 2001 From: Ganesh R Date: Fri, 24 Apr 2026 02:10:15 +0530 Subject: [PATCH 6/7] var cc_id undefined error and other updates - considering few other scenarios --- src/cc.inc.php | 36 ++++++++++++++++++++++++------------ 1 file changed, 24 insertions(+), 12 deletions(-) diff --git a/src/cc.inc.php b/src/cc.inc.php index 4fa90e6..064f022 100644 --- a/src/cc.inc.php +++ b/src/cc.inc.php @@ -521,6 +521,7 @@ function charge_card($custid, $amount = false, $invoice = false, $module = 'defa $smarty->assign('service_name', $settings['TBLNAME']); $smarty->assign('company', $settings['TITLE']); $smarty->assign('name', $data['name']); + $smarty->assign('cc_num', mask_cc($cc, true)); if (!defined(DOMAIN) || in_array(DOMAIN, ['interserver.net', 'misha.interserver.net', 'mymisha.interserver.net']) || trim(DOMAIN) == '') { $smarty->assign('domain', 'my.interserver.net'); } else { @@ -564,7 +565,7 @@ function charge_card($custid, $amount = false, $invoice = false, $module = 'defa } $smarty->assign('invoices', $rows); $email = $smarty->fetch('email/client/payment_failed.tpl'); - (new \MyAdmin\Mail())->multiMail($subject, $email, get_invoice_email($data), 'client/payment_failed.tpl'); + //"ot_cc" is added because it came from pay_balance where they try specific card so no retry for that. if ( @@ -583,13 +584,14 @@ function charge_card($custid, $amount = false, $invoice = false, $module = 'defa if (!in_array($cc, $dec_ccs)) { $GLOBALS['tf']->history->add('users', 'carddecline', $cc_encrypted, $cc_exp, $custid); } - retry_charge_card($custid, $amount, $invoice, $module, $returnURL, $useHandlePayment, $queue); + $retval = retry_charge_card($custid, $amount, $invoice, $module, $returnURL, $useHandlePayment, $queue); + } else { + $new_data = [ + 'payment_method' => 'paypal', + 'cc_auto' => '0' + ]; + App::accounts()->update($custid, $new_data); } - $new_data = [ - 'payment_method' => 'paypal', - 'cc_auto' => '0' - ]; - App::accounts()->update($custid, $new_data); //$GLOBALS['tf']->history->add('users', 'carddecline', $data['cc'], $data['cc_exp'], $custid); break; } @@ -741,22 +743,32 @@ function_requirements('parse_ccs'); foreach ($ccs as $cc_id => $cc_det) { $cc_num = $GLOBALS['tf']->decrypt($cc_det['cc']); if (!in_array($cc_num, $dec_ccs) && can_use_cc($data, $cc_det, false)) { - myadmin_log('billing', 'info', "Backup cc - found $custid ".mask_cc($cc_num), __LINE__, __FILE__); + myadmin_log('billing', 'info', "Backup CC - found for customer $custid ".mask_cc($cc_num), __LINE__, __FILE__); return $cc_id; } } - myadmin_log('billing', 'info', "Backup cc - not found for $custid", __LINE__, __FILE__); + myadmin_log('billing', 'info', "Backup CC - not found for customer $custid", __LINE__, __FILE__); + //Here Primary & Backup both CCs failed so updating payment method paypal. + $new_data = [ + 'payment_method' => 'paypal', + 'cc_auto' => '0' + ]; + App::accounts()->update($custid, $new_data); return false; } function retry_charge_card($custid, $amount = false, $invoice = false, $module = 'default', $returnURL = false, $useHandlePayment = true, $queue = false) { - myadmin_log('billing', 'info', "Retrying backupcc: $custid $amount", __LINE__, __FILE__); + myadmin_log('billing', 'info', "Retrying BackupCC - Custid: $custid, Amount: $amount", __LINE__, __FILE__); $next_cc = get_next_cc($custid); if ($next_cc !== false) { - App::variables()->request['ot_cc'] = $cc_id; + App::variables()->request['ot_cc'] = $next_cc; App::variables()->request['retry_cc'] = 1; - charge_card($custid, $amount, $invoice, $module, $returnURL, $useHandlePayment, $queue); + $success = charge_card($custid, $amount, $invoice, $module, $returnURL, $useHandlePayment, $queue); + if ($success) { + myadmin_log('billing', 'info', "Retrying BackupCC - Success for $custid, Amount: $amount, CC ID - $next_cc", __LINE__, __FILE__); + return true; + } } return false; } From a597ae9b450c8da520d24bbef77250ec4de06773 Mon Sep 17 00:00:00 2001 From: Ganesh R Date: Fri, 24 Apr 2026 02:47:45 +0530 Subject: [PATCH 7/7] Payment failed email sending line missed - added back --- src/cc.inc.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cc.inc.php b/src/cc.inc.php index 064f022..f081484 100644 --- a/src/cc.inc.php +++ b/src/cc.inc.php @@ -565,7 +565,7 @@ function charge_card($custid, $amount = false, $invoice = false, $module = 'defa } $smarty->assign('invoices', $rows); $email = $smarty->fetch('email/client/payment_failed.tpl'); - + (new \MyAdmin\Mail())->multiMail($subject, $email, get_invoice_email($data), 'client/payment_failed.tpl'); //"ot_cc" is added because it came from pay_balance where they try specific card so no retry for that. if (