334 lines
14 KiB
PHP
334 lines
14 KiB
PHP
<?php
|
|
|
|
/**
|
|
* PHP Mikrotik Billing (https://github.com/hotspotbilling/phpnuxbill/)
|
|
* by https://t.me/ibnux
|
|
**/
|
|
|
|
use PHPMailer\PHPMailer\PHPMailer;
|
|
use PHPMailer\PHPMailer\Exception;
|
|
use PHPMailer\PHPMailer\SMTP;
|
|
require $root_path . 'system/autoload/mail/Exception.php';
|
|
require $root_path . 'system/autoload/mail/PHPMailer.php';
|
|
require $root_path . 'system/autoload/mail/SMTP.php';
|
|
|
|
class Message
|
|
{
|
|
|
|
public static function sendTelegram($txt)
|
|
{
|
|
global $config;
|
|
run_hook('send_telegram'); #HOOK
|
|
if (!empty($config['telegram_bot']) && !empty($config['telegram_target_id'])) {
|
|
return Http::getData('https://api.telegram.org/bot' . $config['telegram_bot'] . '/sendMessage?chat_id=' . $config['telegram_target_id'] . '&text=' . urlencode($txt));
|
|
}
|
|
}
|
|
|
|
|
|
public static function sendSMS($phone, $txt)
|
|
{
|
|
global $config;
|
|
if(empty($txt)){
|
|
return "";
|
|
}
|
|
run_hook('send_sms'); #HOOK
|
|
if (!empty($config['sms_url'])) {
|
|
if (strlen($config['sms_url']) > 4 && substr($config['sms_url'], 0, 4) != "http") {
|
|
if (strlen($txt) > 160) {
|
|
$txts = str_split($txt, 160);
|
|
try {
|
|
$mikrotik = Mikrotik::info($config['sms_url']);
|
|
$client = Mikrotik::getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']);
|
|
foreach ($txts as $txt) {
|
|
Mikrotik::sendSMS($client, $phone, $txt);
|
|
}
|
|
} catch (Exception $e) {
|
|
// ignore, add to logs
|
|
_log("Failed to send SMS using Mikrotik.\n" . $e->getMessage(), 'SMS', 0);
|
|
}
|
|
} else {
|
|
try {
|
|
$mikrotik = Mikrotik::info($config['sms_url']);
|
|
$client = Mikrotik::getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']);
|
|
Mikrotik::sendSMS($client, $phone, $txt);
|
|
} catch (Exception $e) {
|
|
// ignore, add to logs
|
|
_log("Failed to send SMS using Mikrotik.\n" . $e->getMessage(), 'SMS', 0);
|
|
}
|
|
}
|
|
} else {
|
|
$smsurl = str_replace('[number]', urlencode($phone), $config['sms_url']);
|
|
$smsurl = str_replace('[text]', urlencode($txt), $smsurl);
|
|
return Http::getData($smsurl);
|
|
}
|
|
}
|
|
}
|
|
|
|
public static function sendWhatsapp($phone, $txt)
|
|
{
|
|
global $config;
|
|
if(empty($txt)){
|
|
return "";
|
|
}
|
|
run_hook('send_whatsapp'); #HOOK
|
|
if (!empty($config['wa_url'])) {
|
|
$waurl = str_replace('[number]', urlencode(Lang::phoneFormat($phone)), $config['wa_url']);
|
|
$waurl = str_replace('[text]', urlencode($txt), $waurl);
|
|
return Http::getData($waurl);
|
|
}
|
|
}
|
|
|
|
public static function sendEmail($to, $subject, $body)
|
|
{
|
|
global $config;
|
|
if(empty($body)){
|
|
return "";
|
|
}
|
|
run_hook('send_email'); #HOOK
|
|
if (empty($config['smtp_host'])) {
|
|
$attr = "";
|
|
if (!empty($config['mail_from'])) {
|
|
$attr .= "From: " . $config['mail_from'] . "\r\n";
|
|
}
|
|
if (!empty($config['mail_reply_to'])) {
|
|
$attr .= "Reply-To: " . $config['mail_reply_to'] . "\r\n";
|
|
}
|
|
mail($to, $subject, $body, $attr);
|
|
} else {
|
|
$mail = new PHPMailer();
|
|
$mail->isSMTP();
|
|
$mail->SMTPDebug = SMTP::DEBUG_SERVER;
|
|
$mail->Host = $config['smtp_host'];
|
|
$mail->SMTPAuth = true;
|
|
$mail->Username = $config['smtp_user'];
|
|
$mail->Password = $config['smtp_pass'];
|
|
$mail->SMTPSecure = $config['smtp_ssltls'];
|
|
$mail->Port = $config['smtp_port'];
|
|
if (!empty($config['mail_from'])) {
|
|
$mail->setFrom($config['mail_from']);
|
|
}
|
|
if (!empty($config['mail_reply_to'])) {
|
|
$mail->addReplyTo($config['mail_reply_to']);
|
|
}
|
|
$mail->isHTML(false);
|
|
$mail->addAddress($to);
|
|
$mail->Subject = $subject;
|
|
$mail->Body = $body;
|
|
$mail->send();
|
|
}
|
|
}
|
|
|
|
public static function sendPackageNotification($customer, $package, $price, $message, $via, $plan_type = null)
|
|
{
|
|
global $ds;
|
|
if(empty($message)){
|
|
return "";
|
|
}
|
|
|
|
// Get plan-specific template if plan_type is provided
|
|
$template = self::getPlanSpecificTemplate($message, $plan_type);
|
|
|
|
$msg = str_replace('[[name]]', $customer['fullname'], $template);
|
|
$msg = str_replace('[[username]]', $customer['username'], $msg);
|
|
$msg = str_replace('[[plan]]', $package, $msg);
|
|
$msg = str_replace('[[package]]', $package, $msg);
|
|
$msg = str_replace('[[price]]', Lang::moneyFormat($price), $msg);
|
|
$msg = str_replace('[[plan_type]]', $plan_type ? ucfirst(strtolower($plan_type)) : 'Internet', $msg);
|
|
|
|
// Add service-specific variables
|
|
global $config;
|
|
$msg = str_replace('[[service_portal]]', !empty($config['hotspot_url']) ? $config['hotspot_url'] : APP_URL, $msg);
|
|
$msg = str_replace('[[support_contact]]', !empty($config['phone']) ? $config['phone'] : 'our support team', $msg);
|
|
|
|
list($bills, $add_cost) = User::getBills($customer['id']);
|
|
if($add_cost>0){
|
|
$note = "";
|
|
foreach ($bills as $k => $v) {
|
|
$note .= $k . " : " . Lang::moneyFormat($v) . "\n";
|
|
}
|
|
$note .= "Total : " . Lang::moneyFormat($add_cost+$price) . "\n";
|
|
$msg = str_replace('[[bills]]', $note, $msg);
|
|
}else{
|
|
$msg = str_replace('[[bills]]', '', $msg);
|
|
}
|
|
if ($ds) {
|
|
$msg = str_replace('[[expired_date]]', Lang::dateAndTimeFormat($ds['expiration'], $ds['time']), $msg);
|
|
}else{
|
|
$msg = str_replace('[[expired_date]]', "", $msg);
|
|
}
|
|
if (
|
|
!empty($customer['phonenumber']) && strlen($customer['phonenumber']) > 5
|
|
&& !empty($template) && in_array($via, ['sms', 'wa'])
|
|
) {
|
|
if ($via == 'sms') {
|
|
echo Message::sendSMS($customer['phonenumber'], $msg);
|
|
} else if ($via == 'wa') {
|
|
echo Message::sendWhatsapp($customer['phonenumber'], $msg);
|
|
}
|
|
}
|
|
return "$via: $msg";
|
|
}
|
|
|
|
public static function sendBalanceNotification($phone, $name, $balance, $balance_now, $message, $via)
|
|
{
|
|
$msg = str_replace('[[name]]', $name, $message);
|
|
$msg = str_replace('[[current_balance]]', Lang::moneyFormat($balance_now), $msg);
|
|
$msg = str_replace('[[balance]]', Lang::moneyFormat($balance), $msg);
|
|
if (
|
|
!empty($phone) && strlen($phone) > 5
|
|
&& !empty($message) && in_array($via, ['sms', 'wa'])
|
|
) {
|
|
if ($via == 'sms') {
|
|
Message::sendSMS($phone, $msg);
|
|
} else if ($via == 'wa') {
|
|
Message::sendWhatsapp($phone, $msg);
|
|
}
|
|
}
|
|
return "$via: $msg";
|
|
}
|
|
|
|
public static function sendInvoice($cust, $trx)
|
|
{
|
|
global $config;
|
|
$textInvoice = Lang::getNotifText('invoice_paid');
|
|
$textInvoice = str_replace('[[company_name]]', $config['CompanyName'], $textInvoice);
|
|
$textInvoice = str_replace('[[address]]', $config['address'], $textInvoice);
|
|
$textInvoice = str_replace('[[phone]]', $config['phone'], $textInvoice);
|
|
$textInvoice = str_replace('[[invoice]]', $trx['invoice'], $textInvoice);
|
|
$textInvoice = str_replace('[[date]]', Lang::dateAndTimeFormat($trx['recharged_on'], $trx['recharged_time']), $textInvoice);
|
|
if (!empty($trx['note'])) {
|
|
$textInvoice = str_replace('[[note]]', $trx['note'], $textInvoice);
|
|
}
|
|
$gc = explode("-", $trx['method']);
|
|
$textInvoice = str_replace('[[payment_gateway]]', trim($gc[0]), $textInvoice);
|
|
$textInvoice = str_replace('[[payment_channel]]', trim($gc[1]), $textInvoice);
|
|
$textInvoice = str_replace('[[type]]', $trx['type'], $textInvoice);
|
|
$textInvoice = str_replace('[[plan_name]]', $trx['plan_name'], $textInvoice);
|
|
$textInvoice = str_replace('[[plan_price]]', Lang::moneyFormat($trx['price']), $textInvoice);
|
|
$textInvoice = str_replace('[[name]]', $cust['fullname'], $textInvoice);
|
|
$textInvoice = str_replace('[[note]]', $cust['note'], $textInvoice);
|
|
$textInvoice = str_replace('[[user_name]]', $trx['username'], $textInvoice);
|
|
$textInvoice = str_replace('[[user_password]]', $cust['password'], $textInvoice);
|
|
$textInvoice = str_replace('[[username]]', $trx['username'], $textInvoice);
|
|
$textInvoice = str_replace('[[password]]', $cust['password'], $textInvoice);
|
|
$textInvoice = str_replace('[[expired_date]]', Lang::dateAndTimeFormat($trx['expiration'], $trx['time']), $textInvoice);
|
|
$textInvoice = str_replace('[[footer]]', $config['note'], $textInvoice);
|
|
|
|
if ($config['user_notification_payment'] == 'sms') {
|
|
Message::sendSMS($cust['phonenumber'], $textInvoice);
|
|
} else if ($config['user_notification_payment'] == 'wa') {
|
|
Message::sendWhatsapp($cust['phonenumber'], $textInvoice);
|
|
}
|
|
}
|
|
|
|
public static function sendRegistrationNotification($customer)
|
|
{
|
|
global $config;
|
|
|
|
if(empty($customer['phonenumber']) || strlen($customer['phonenumber']) < 5){
|
|
return "";
|
|
}
|
|
|
|
$textRegistration = Lang::getNotifText('user_registration');
|
|
if(empty($textRegistration)) {
|
|
return "";
|
|
}
|
|
|
|
$textRegistration = str_replace('[[company_name]]', $config['CompanyName'], $textRegistration);
|
|
$textRegistration = str_replace('[[name]]', $customer['fullname'], $textRegistration);
|
|
$textRegistration = str_replace('[[user_name]]', $customer['username'], $textRegistration);
|
|
$textRegistration = str_replace('[[username]]', $customer['username'], $textRegistration);
|
|
$textRegistration = str_replace('[[password]]', $customer['password'], $textRegistration);
|
|
$textRegistration = str_replace('[[service_type]]', $customer['service_type'], $textRegistration);
|
|
$textRegistration = str_replace('[[footer]]', $config['note'], $textRegistration);
|
|
|
|
// Use the same notification setting as recharge process
|
|
if ($config['user_notification_payment'] == 'sms') {
|
|
Message::sendSMS($customer['phonenumber'], $textRegistration);
|
|
} else if ($config['user_notification_payment'] == 'wa') {
|
|
Message::sendWhatsapp($customer['phonenumber'], $textRegistration);
|
|
}
|
|
|
|
return $textRegistration;
|
|
}
|
|
|
|
/**
|
|
* Get plan-specific template based on plan type
|
|
* @param string $message_key The message key (e.g., 'expired', 'reminder_7_day')
|
|
* @param string $plan_type The plan type ('Hotspot', 'PPPOE', etc.)
|
|
* @return string The appropriate template
|
|
*/
|
|
public static function getPlanSpecificTemplate($message_key, $plan_type = null)
|
|
{
|
|
global $config;
|
|
|
|
// Load notification templates
|
|
$notifications = self::loadNotificationTemplates();
|
|
|
|
// If no plan type provided or template doesn't exist, return original message
|
|
if (empty($plan_type) || !isset($notifications[$message_key])) {
|
|
return $message_key;
|
|
}
|
|
|
|
// Check if it's a new structure with plan-specific templates
|
|
if (is_array($notifications[$message_key])) {
|
|
$plan_type_lower = strtolower($plan_type);
|
|
|
|
// Try to get plan-specific template
|
|
if (isset($notifications[$message_key][$plan_type_lower])) {
|
|
return $notifications[$message_key][$plan_type_lower];
|
|
}
|
|
|
|
// Fallback to default template
|
|
if (isset($notifications[$message_key]['default'])) {
|
|
return $notifications[$message_key]['default'];
|
|
}
|
|
}
|
|
|
|
// Fallback to original message for backward compatibility
|
|
return $notifications[$message_key];
|
|
}
|
|
|
|
/**
|
|
* Load notification templates from file
|
|
* @return array Notification templates
|
|
*/
|
|
public static function loadNotificationTemplates()
|
|
{
|
|
global $root_path;
|
|
$notifications_file = $root_path . 'system/uploads/notifications.default.json';
|
|
|
|
if (file_exists($notifications_file)) {
|
|
$content = file_get_contents($notifications_file);
|
|
$notifications = json_decode($content, true);
|
|
return $notifications ?: [];
|
|
}
|
|
|
|
return [];
|
|
}
|
|
|
|
/**
|
|
* Detect plan type from customer and package information
|
|
* @param array $customer Customer information
|
|
* @param string $package Package name
|
|
* @return string|null Plan type
|
|
*/
|
|
public static function detectPlanType($customer, $package)
|
|
{
|
|
// Try to get plan type from customer's service_type
|
|
if (!empty($customer['service_type']) && in_array($customer['service_type'], ['Hotspot', 'PPPoE'])) {
|
|
return $customer['service_type'];
|
|
}
|
|
|
|
// Try to detect from package name (basic detection)
|
|
$package_lower = strtolower($package);
|
|
if (strpos($package_lower, 'hotspot') !== false) {
|
|
return 'Hotspot';
|
|
} elseif (strpos($package_lower, 'pppoe') !== false) {
|
|
return 'PPPOE';
|
|
}
|
|
|
|
return null;
|
|
}
|
|
}
|