Upload files to "system/autoload"
Signed-off-by: kevin <kevin@codelab.nestict.africa>
This commit is contained in:
61
system/autoload/Admin.php
Normal file
61
system/autoload/Admin.php
Normal file
@@ -0,0 +1,61 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* PHP Mikrotik Billing (https://github.com/hotspotbilling/phpnuxbill/)
|
||||
* by https://t.me/ibnux
|
||||
**/
|
||||
|
||||
|
||||
class Admin
|
||||
{
|
||||
|
||||
public static function getID()
|
||||
{
|
||||
global $db_password;
|
||||
if (isset($_SESSION['aid'])) {
|
||||
return $_SESSION['aid'];
|
||||
} else if (isset($_COOKIE['aid'])) {
|
||||
// id.time.sha1
|
||||
$tmp = explode('.', $_COOKIE['aid']);
|
||||
if (sha1($tmp[0] . '.' . $tmp[1] . '.' . $db_password) == $tmp[2]) {
|
||||
if (time() - $tmp[1] < 86400 * 7) {
|
||||
$_SESSION['aid'] = $tmp[0];
|
||||
return $tmp[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static function setCookie($aid)
|
||||
{
|
||||
global $db_password;
|
||||
if (isset($aid)) {
|
||||
$time = time();
|
||||
$token = $aid . '.' . $time . '.' . sha1($aid . '.' . $time . '.' . $db_password);
|
||||
setcookie('aid', $token, time() + 86400 * 7);
|
||||
return $token;
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
|
||||
public static function removeCookie()
|
||||
{
|
||||
if (isset($_COOKIE['aid'])) {
|
||||
setcookie('aid', '', time() - 86400);
|
||||
}
|
||||
}
|
||||
|
||||
public static function _info($id = 0)
|
||||
{
|
||||
if (empty($id) && $id == 0) {
|
||||
$id = Admin::getID();
|
||||
}
|
||||
if ($id) {
|
||||
return ORM::for_table('tbl_users')->find_one($id);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
29
system/autoload/App.php
Normal file
29
system/autoload/App.php
Normal file
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
/**
|
||||
* PHP Mikrotik Billing (https://github.com/hotspotbilling/phpnuxbill/)
|
||||
* by https://t.me/ibnux
|
||||
**/
|
||||
|
||||
|
||||
class App{
|
||||
public static function _run(){
|
||||
return true;
|
||||
}
|
||||
|
||||
public static function getToken(){
|
||||
return md5(microtime());
|
||||
}
|
||||
|
||||
public static function setToken($token, $value){
|
||||
$_SESSION[$token] = $value;
|
||||
}
|
||||
|
||||
public static function getTokenValue($key){
|
||||
if(isset($_SESSION[$key])){
|
||||
return $_SESSION[$key];
|
||||
}else{
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
64
system/autoload/Balance.php
Normal file
64
system/autoload/Balance.php
Normal file
@@ -0,0 +1,64 @@
|
||||
<?php
|
||||
/**
|
||||
* PHP Mikrotik Billing (https://github.com/hotspotbilling/phpnuxbill/)
|
||||
* by https://t.me/ibnux
|
||||
**/
|
||||
/**
|
||||
* This script is for managing user balance
|
||||
**/
|
||||
|
||||
class Balance
|
||||
{
|
||||
|
||||
public static function plus($id_customer, $amount)
|
||||
{
|
||||
$c = ORM::for_table('tbl_customers')->where('id', $id_customer)->find_one();
|
||||
$c->balance = $amount + $c['balance'];
|
||||
$c->save();
|
||||
}
|
||||
|
||||
public static function transfer($id_customer, $phoneTarget, $amount)
|
||||
{
|
||||
global $config;
|
||||
if (Balance::min($id_customer, $amount)) {
|
||||
return Balance::plusByPhone($phoneTarget, $amount);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static function min($id_customer, $amount)
|
||||
{
|
||||
$c = ORM::for_table('tbl_customers')->where('id', $id_customer)->find_one();
|
||||
if ($c && $c['balance'] >= $amount) {
|
||||
$c->balance = $c['balance'] - $amount;
|
||||
$c->save();
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static function plusByPhone($phone_customer, $amount)
|
||||
{
|
||||
$c = ORM::for_table('tbl_customers')->where('username', $phone_customer)->find_one();
|
||||
if ($c) {
|
||||
$c->balance = $amount + $c['balance'];
|
||||
$c->save();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static function minByPhone($phone_customer, $amount)
|
||||
{
|
||||
$c = ORM::for_table('tbl_customers')->where('username', $phone_customer)->find_one();
|
||||
if ($c && $c['balance'] >= $amount) {
|
||||
$c->balance = $c['balance'] - $amount;
|
||||
$c->save();
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
283
system/autoload/CronLog.php
Normal file
283
system/autoload/CronLog.php
Normal file
@@ -0,0 +1,283 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Cron Logging System
|
||||
* Tracks cron job execution and performance
|
||||
*/
|
||||
|
||||
class CronLog
|
||||
{
|
||||
private static $logId = null;
|
||||
private static $startTime = null;
|
||||
private static $startMemory = null;
|
||||
|
||||
/**
|
||||
* Start logging a cron job
|
||||
* @param string $cronType Type of cron job (main, reminder, etc.)
|
||||
* @return int Log ID
|
||||
*/
|
||||
public static function start($cronType = 'main')
|
||||
{
|
||||
self::$startTime = microtime(true);
|
||||
self::$startMemory = memory_get_usage();
|
||||
|
||||
$log = ORM::for_table('tbl_cron_logs')->create();
|
||||
$log->cron_type = $cronType;
|
||||
$log->started_at = date('Y-m-d H:i:s');
|
||||
$log->status = 'running';
|
||||
$log->save();
|
||||
|
||||
self::$logId = $log->id();
|
||||
return self::$logId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update log with current statistics
|
||||
* @param array $stats Statistics array
|
||||
*/
|
||||
public static function updateStats($stats = [])
|
||||
{
|
||||
if (!self::$logId) return;
|
||||
|
||||
$log = ORM::for_table('tbl_cron_logs')->find_one(self::$logId);
|
||||
if (!$log) return;
|
||||
|
||||
foreach ($stats as $key => $value) {
|
||||
if (property_exists($log, $key)) {
|
||||
$log->$key = $value;
|
||||
}
|
||||
}
|
||||
|
||||
$log->save();
|
||||
}
|
||||
|
||||
/**
|
||||
* Increment a counter
|
||||
* @param string $field Field to increment
|
||||
* @param int $amount Amount to increment by
|
||||
*/
|
||||
public static function increment($field, $amount = 1)
|
||||
{
|
||||
if (!self::$logId) return;
|
||||
|
||||
$log = ORM::for_table('tbl_cron_logs')->find_one(self::$logId);
|
||||
if (!$log) return;
|
||||
|
||||
if (property_exists($log, $field)) {
|
||||
$log->$field = $log->$field + $amount;
|
||||
$log->save();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Complete the cron job successfully
|
||||
* @param array $finalStats Final statistics
|
||||
*/
|
||||
public static function complete($finalStats = [])
|
||||
{
|
||||
if (!self::$logId) return;
|
||||
|
||||
$log = ORM::for_table('tbl_cron_logs')->find_one(self::$logId);
|
||||
if (!$log) return;
|
||||
|
||||
$log->finished_at = date('Y-m-d H:i:s');
|
||||
$log->status = 'completed';
|
||||
|
||||
// Calculate execution time
|
||||
if (self::$startTime) {
|
||||
$log->execution_time = round(microtime(true) - self::$startTime, 3);
|
||||
}
|
||||
|
||||
// Calculate memory usage
|
||||
if (self::$startMemory) {
|
||||
$currentMemory = memory_get_usage();
|
||||
$peakMemory = memory_get_peak_usage();
|
||||
$log->memory_usage = self::formatBytes($peakMemory - self::$startMemory);
|
||||
}
|
||||
|
||||
// Update final stats
|
||||
foreach ($finalStats as $key => $value) {
|
||||
if (property_exists($log, $key)) {
|
||||
$log->$key = $value;
|
||||
}
|
||||
}
|
||||
|
||||
$log->save();
|
||||
|
||||
// Clean up old logs (keep last 1000 records)
|
||||
self::cleanup();
|
||||
}
|
||||
|
||||
/**
|
||||
* Mark cron job as failed
|
||||
* @param string $errorMessage Error message
|
||||
* @param array $finalStats Final statistics
|
||||
*/
|
||||
public static function fail($errorMessage, $finalStats = [])
|
||||
{
|
||||
if (!self::$logId) return;
|
||||
|
||||
$log = ORM::for_table('tbl_cron_logs')->find_one(self::$logId);
|
||||
if (!$log) return;
|
||||
|
||||
$log->finished_at = date('Y-m-d H:i:s');
|
||||
$log->status = 'failed';
|
||||
$log->error_message = $errorMessage;
|
||||
|
||||
// Calculate execution time
|
||||
if (self::$startTime) {
|
||||
$log->execution_time = round(microtime(true) - self::$startTime, 3);
|
||||
}
|
||||
|
||||
// Update final stats
|
||||
foreach ($finalStats as $key => $value) {
|
||||
if (property_exists($log, $key)) {
|
||||
$log->$key = $value;
|
||||
}
|
||||
}
|
||||
|
||||
$log->save();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get recent cron logs
|
||||
* @param int $limit Number of records to return
|
||||
* @param string $cronType Filter by cron type
|
||||
* @return array
|
||||
*/
|
||||
public static function getRecent($limit = 50, $cronType = null)
|
||||
{
|
||||
$query = ORM::for_table('tbl_cron_logs');
|
||||
|
||||
if ($cronType) {
|
||||
$query->where('cron_type', $cronType);
|
||||
}
|
||||
|
||||
return $query->order_by_desc('started_at')
|
||||
->limit($limit)
|
||||
->find_many();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get cron job statistics
|
||||
* @param int $days Number of days to look back
|
||||
* @return array
|
||||
*/
|
||||
public static function getStats($days = 7)
|
||||
{
|
||||
$since = date('Y-m-d H:i:s', strtotime("-$days days"));
|
||||
|
||||
$stats = ORM::for_table('tbl_cron_logs')
|
||||
->where_gte('started_at', $since)
|
||||
->find_many();
|
||||
|
||||
$result = [
|
||||
'total_runs' => count($stats),
|
||||
'successful_runs' => 0,
|
||||
'failed_runs' => 0,
|
||||
'total_expired_users' => 0,
|
||||
'total_notifications_sent' => 0,
|
||||
'total_auto_renewals' => 0,
|
||||
'avg_execution_time' => 0,
|
||||
'last_run' => null,
|
||||
'last_success' => null,
|
||||
'last_failure' => null
|
||||
];
|
||||
|
||||
$totalExecutionTime = 0;
|
||||
$executionCount = 0;
|
||||
|
||||
foreach ($stats as $log) {
|
||||
if ($log->status == 'completed') {
|
||||
$result['successful_runs']++;
|
||||
$result['last_success'] = $log->finished_at;
|
||||
} elseif ($log->status == 'failed') {
|
||||
$result['failed_runs']++;
|
||||
$result['last_failure'] = $log->finished_at;
|
||||
}
|
||||
|
||||
$result['total_expired_users'] += $log->expired_users_processed;
|
||||
$result['total_notifications_sent'] += $log->notifications_sent;
|
||||
$result['total_auto_renewals'] += $log->auto_renewals_successful;
|
||||
|
||||
if ($log->execution_time) {
|
||||
$totalExecutionTime += $log->execution_time;
|
||||
$executionCount++;
|
||||
}
|
||||
|
||||
if (!$result['last_run'] || $log->started_at > $result['last_run']) {
|
||||
$result['last_run'] = $log->started_at;
|
||||
}
|
||||
}
|
||||
|
||||
if ($executionCount > 0) {
|
||||
$result['avg_execution_time'] = round($totalExecutionTime / $executionCount, 3);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clean up old logs (keep last 1000 records)
|
||||
*/
|
||||
private static function cleanup()
|
||||
{
|
||||
$count = ORM::for_table('tbl_cron_logs')->count();
|
||||
|
||||
if ($count > 1000) {
|
||||
$logsToDelete = ORM::for_table('tbl_cron_logs')
|
||||
->order_by_asc('started_at')
|
||||
->limit($count - 1000)
|
||||
->find_many();
|
||||
|
||||
foreach ($logsToDelete as $log) {
|
||||
$log->delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Format bytes to human readable format
|
||||
* @param int $bytes
|
||||
* @return string
|
||||
*/
|
||||
private static function formatBytes($bytes)
|
||||
{
|
||||
$units = ['B', 'KB', 'MB', 'GB'];
|
||||
$bytes = max($bytes, 0);
|
||||
$pow = floor(($bytes ? log($bytes) : 0) / log(1024));
|
||||
$pow = min($pow, count($units) - 1);
|
||||
|
||||
$bytes /= pow(1024, $pow);
|
||||
|
||||
return round($bytes, 2) . ' ' . $units[$pow];
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if cron is running (has a running log in last 5 minutes)
|
||||
* @return bool
|
||||
*/
|
||||
public static function isRunning()
|
||||
{
|
||||
$fiveMinutesAgo = date('Y-m-d H:i:s', strtotime('-5 minutes'));
|
||||
|
||||
$runningLog = ORM::for_table('tbl_cron_logs')
|
||||
->where('status', 'running')
|
||||
->where_gte('started_at', $fiveMinutesAgo)
|
||||
->find_one();
|
||||
|
||||
return $runningLog ? true : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the last successful cron run
|
||||
* @return object|null
|
||||
*/
|
||||
public static function getLastSuccess()
|
||||
{
|
||||
return ORM::for_table('tbl_cron_logs')
|
||||
->where('status', 'completed')
|
||||
->order_by_desc('finished_at')
|
||||
->find_one();
|
||||
}
|
||||
}
|
||||
55
system/autoload/Csrf.php
Normal file
55
system/autoload/Csrf.php
Normal file
@@ -0,0 +1,55 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* PHP Mikrotik Billing (https://github.com/hotspotbilling/phpnuxbill/)
|
||||
* by https://t.me/ibnux
|
||||
**/
|
||||
|
||||
|
||||
class Csrf
|
||||
{
|
||||
private static $tokenExpiration = 1800; // 30 minutes
|
||||
|
||||
public static function generateToken($length = 16)
|
||||
{
|
||||
return bin2hex(random_bytes($length));
|
||||
}
|
||||
|
||||
public static function validateToken($token, $storedToken)
|
||||
{
|
||||
return hash_equals($token, $storedToken);
|
||||
}
|
||||
|
||||
public static function check($token)
|
||||
{
|
||||
global $config;
|
||||
if($config['csrf_enabled'] == 'yes') {
|
||||
if (isset($_SESSION['csrf_token'], $_SESSION['csrf_token_time'], $token)) {
|
||||
$storedToken = $_SESSION['csrf_token'];
|
||||
$tokenTime = $_SESSION['csrf_token_time'];
|
||||
|
||||
if (time() - $tokenTime > self::$tokenExpiration) {
|
||||
self::clearToken();
|
||||
return false;
|
||||
}
|
||||
|
||||
return self::validateToken($token, $storedToken);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static function generateAndStoreToken()
|
||||
{
|
||||
$token = self::generateToken();
|
||||
$_SESSION['csrf_token'] = $token;
|
||||
$_SESSION['csrf_token_time'] = time();
|
||||
return $token;
|
||||
}
|
||||
|
||||
public static function clearToken()
|
||||
{
|
||||
unset($_SESSION['csrf_token'], $_SESSION['csrf_token_time']);
|
||||
}
|
||||
}
|
||||
108
system/autoload/File.php
Normal file
108
system/autoload/File.php
Normal file
@@ -0,0 +1,108 @@
|
||||
<?php
|
||||
/**
|
||||
* PHP Mikrotik Billing (https://github.com/hotspotbilling/phpnuxbill/)
|
||||
* by https://t.me/ibnux
|
||||
**/
|
||||
class File
|
||||
{
|
||||
|
||||
public static function copyFolder($from, $to, $exclude = [])
|
||||
{
|
||||
$files = scandir($from);
|
||||
foreach ($files as $file) {
|
||||
if (is_file($from . $file) && !in_array($file, $exclude)) {
|
||||
if (file_exists($to . $file)) unlink($to . $file);
|
||||
rename($from . $file, $to . $file);
|
||||
} else if (is_dir($from . $file) && !in_array($file, ['.', '..'])) {
|
||||
if (!file_exists($to . $file)) {
|
||||
mkdir($to . $file);
|
||||
}
|
||||
File::copyFolder($from . $file . DIRECTORY_SEPARATOR, $to . $file . DIRECTORY_SEPARATOR, $exclude);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static function deleteFolder($path)
|
||||
{
|
||||
$files = scandir($path);
|
||||
foreach ($files as $file) {
|
||||
if (is_file($path . $file)) {
|
||||
unlink($path . $file);
|
||||
} else if (is_dir($path . $file) && !in_array($file, ['.', '..'])) {
|
||||
File::deleteFolder($path . $file . DIRECTORY_SEPARATOR);
|
||||
rmdir($path . $file);
|
||||
}
|
||||
}
|
||||
rmdir($path);
|
||||
}
|
||||
|
||||
public static function resizeCropImage($source_file, $dst_dir, $max_width, $max_height, $quality = 80)
|
||||
{
|
||||
$imgsize = getimagesize($source_file);
|
||||
$width = $imgsize[0];
|
||||
$height = $imgsize[1];
|
||||
$mime = $imgsize['mime'];
|
||||
|
||||
switch ($mime) {
|
||||
case 'image/gif':
|
||||
$image_create = "imagecreatefromgif";
|
||||
$image = "imagegif";
|
||||
break;
|
||||
|
||||
case 'image/png':
|
||||
$image_create = "imagecreatefrompng";
|
||||
$image = "imagepng";
|
||||
$quality = 7;
|
||||
break;
|
||||
|
||||
case 'image/jpeg':
|
||||
$image_create = "imagecreatefromjpeg";
|
||||
$image = "imagejpeg";
|
||||
$quality = 80;
|
||||
break;
|
||||
|
||||
default:
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
|
||||
if ($max_width == 0) {
|
||||
$max_width = $width;
|
||||
}
|
||||
|
||||
if ($max_height == 0) {
|
||||
$max_height = $height;
|
||||
}
|
||||
|
||||
$widthRatio = $max_width / $width;
|
||||
$heightRatio = $max_height / $height;
|
||||
$ratio = min($widthRatio, $heightRatio);
|
||||
$nwidth = (int)$width * $ratio;
|
||||
$nheight = (int)$height * $ratio;
|
||||
|
||||
$dst_img = imagecreatetruecolor($nwidth, $nheight);
|
||||
$white = imagecolorallocate($dst_img, 255, 255, 255);
|
||||
imagefill($dst_img, 0, 0, $white);
|
||||
$src_img = $image_create($source_file);
|
||||
imagecopyresampled($dst_img, $src_img, 0, 0, 0, 0, $nwidth, $nheight, $width, $height);
|
||||
|
||||
$image($dst_img, $dst_dir, $quality);
|
||||
|
||||
if ($dst_img) imagedestroy($dst_img);
|
||||
if ($src_img) imagedestroy($src_img);
|
||||
return file_exists($dst_dir);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* file path fixer
|
||||
*
|
||||
* @access public
|
||||
* @param string $path
|
||||
* @return string
|
||||
*/
|
||||
public static function pathFixer($path)
|
||||
{
|
||||
return str_replace("/", DIRECTORY_SEPARATOR, $path);
|
||||
}
|
||||
}
|
||||
57
system/autoload/Hookers.php
Normal file
57
system/autoload/Hookers.php
Normal file
@@ -0,0 +1,57 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* PHP Mikrotik Billing (https://github.com/hotspotbilling/phpnuxbill/)
|
||||
* by https://t.me/ibnux
|
||||
**/
|
||||
|
||||
$menu_registered = array();
|
||||
|
||||
/**
|
||||
* Register for global menu
|
||||
* @param string name Name of the menu
|
||||
* @param bool admin true if for admin and false for customer
|
||||
* @param string function function to run after menu clicks
|
||||
* @param string position position of menu, use AFTER_ for root menu |
|
||||
* Admin/Sales menu: AFTER_DASHBOARD, CUSTOMERS, PREPAID, SERVICES, REPORTS, VOUCHER, AFTER_ORDER, NETWORK, SETTINGS, AFTER_PAYMENTGATEWAY
|
||||
* | Customer menu: AFTER_DASHBOARD, ORDER, HISTORY, ACCOUNTS
|
||||
* @param string icon from ion icon, ion-person, only for AFTER_
|
||||
* @param string label for showing label or number of notification or update
|
||||
* @param string color Label color
|
||||
* @param string auth authorization ['SuperAdmin', 'Admin', 'Report', 'Agent', 'Sales'] will only show in this user, empty array for all users
|
||||
*/
|
||||
function register_menu($name, $admin, $function, $position, $icon = '', $label = '', $color = 'success', $auth = [])
|
||||
{
|
||||
global $menu_registered;
|
||||
$menu_registered[] = [
|
||||
"name" => $name,
|
||||
"admin" => $admin,
|
||||
"position" => $position,
|
||||
"icon" => $icon,
|
||||
"function" => $function,
|
||||
"label" => $label,
|
||||
"color" => $color,
|
||||
"auth" => $auth
|
||||
];
|
||||
}
|
||||
|
||||
$hook_registered = array();
|
||||
|
||||
function register_hook($action, $function){
|
||||
global $hook_registered;
|
||||
$hook_registered[] = [
|
||||
'action' => $action,
|
||||
'function' => $function
|
||||
];
|
||||
}
|
||||
|
||||
function run_hook($action){
|
||||
global $hook_registered;
|
||||
foreach($hook_registered as $hook){
|
||||
if($hook['action'] == $action){
|
||||
if(function_exists($hook['function'])){
|
||||
call_user_func($hook['function']);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
117
system/autoload/Http.php
Normal file
117
system/autoload/Http.php
Normal file
@@ -0,0 +1,117 @@
|
||||
<?php
|
||||
/**
|
||||
* PHP Mikrotik Billing (https://github.com/hotspotbilling/phpnuxbill/)
|
||||
* by https://t.me/ibnux
|
||||
**/
|
||||
|
||||
/**
|
||||
* using proxy, add this variable in config.php
|
||||
* $http_proxy = '127.0.0.1:3128';
|
||||
* if proxy using authentication, use this parameter
|
||||
* $http_proxyauth = 'user:password';
|
||||
**/
|
||||
|
||||
class Http
|
||||
{
|
||||
public static function getData($url, $headers = [])
|
||||
{
|
||||
global $http_proxy, $http_proxyauth, $admin;
|
||||
$ch = curl_init();
|
||||
curl_setopt($ch, CURLOPT_URL, $url);
|
||||
curl_setopt($ch, CURLOPT_POST, 0);
|
||||
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 15);
|
||||
curl_setopt($ch, CURLOPT_TIMEOUT, 15);
|
||||
if(is_array($headers) && count($headers)>0){
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
|
||||
}
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
if (!empty($http_proxy)) {
|
||||
curl_setopt($ch, CURLOPT_PROXY, $http_proxy);
|
||||
if (!empty($http_proxyauth)) {
|
||||
curl_setopt($ch, CURLOPT_PROXYUSERPWD, $http_proxyauth);
|
||||
}
|
||||
}
|
||||
$server_output = curl_exec($ch);
|
||||
if (curl_errno($ch)) {
|
||||
$error_msg = curl_error($ch);
|
||||
}
|
||||
curl_close($ch);
|
||||
if($admin && $error_msg){
|
||||
r2(U . 'dashboard', 'd', $error_msg);
|
||||
}
|
||||
return ($server_output) ? $server_output : $error_msg;
|
||||
}
|
||||
|
||||
public static function postJsonData($url, $array_post, $headers = [], $basic = null)
|
||||
{
|
||||
global $http_proxy, $http_proxyauth, $admin;
|
||||
$headers[] = 'Content-Type: application/json';
|
||||
$ch = curl_init();
|
||||
curl_setopt($ch, CURLOPT_URL, $url);
|
||||
curl_setopt($ch, CURLOPT_POST, 1);
|
||||
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 15);
|
||||
curl_setopt($ch, CURLOPT_TIMEOUT, 15);
|
||||
curl_setopt($ch, CURLOPT_VERBOSE, false);
|
||||
curl_setopt($ch, CURLINFO_HEADER_OUT, false);
|
||||
if (!empty($http_proxy)) {
|
||||
curl_setopt($ch, CURLOPT_PROXY, $http_proxy);
|
||||
if (!empty($http_proxyauth)) {
|
||||
curl_setopt($ch, CURLOPT_PROXYUSERPWD, $http_proxyauth);
|
||||
}
|
||||
}
|
||||
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($array_post));
|
||||
if(is_array($headers) && count($headers)>0){
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
|
||||
}
|
||||
if (!empty($basic)) {
|
||||
curl_setopt($ch, CURLOPT_USERPWD, $basic);
|
||||
}
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
$server_output = curl_exec($ch);
|
||||
if (curl_errno($ch)) {
|
||||
$error_msg = curl_error($ch);
|
||||
}
|
||||
curl_close($ch);
|
||||
if($admin && $error_msg){
|
||||
r2(U . 'dashboard', 'd', $error_msg);
|
||||
}
|
||||
return ($server_output) ? $server_output : $error_msg;
|
||||
}
|
||||
|
||||
|
||||
public static function postData($url, $array_post, $headers = [], $basic = null)
|
||||
{
|
||||
global $http_proxy, $http_proxyauth, $admin;
|
||||
$headers[] = 'Content-Type: application/x-www-form-urlencoded';
|
||||
$ch = curl_init();
|
||||
curl_setopt($ch, CURLOPT_URL, $url);
|
||||
curl_setopt($ch, CURLOPT_POST, 1);
|
||||
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 15);
|
||||
curl_setopt($ch, CURLOPT_TIMEOUT, 15);
|
||||
curl_setopt($ch, CURLOPT_VERBOSE, false);
|
||||
curl_setopt($ch, CURLINFO_HEADER_OUT, false);
|
||||
if (!empty($http_proxy)) {
|
||||
curl_setopt($ch, CURLOPT_PROXY, $http_proxy);
|
||||
if (!empty($http_proxyauth)) {
|
||||
curl_setopt($ch, CURLOPT_PROXYUSERPWD, $http_proxyauth);
|
||||
}
|
||||
}
|
||||
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($array_post));
|
||||
if(is_array($headers) && count($headers)>0){
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
|
||||
}
|
||||
if (!empty($basic)) {
|
||||
curl_setopt($ch, CURLOPT_USERPWD, $basic);
|
||||
}
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
$server_output = curl_exec($ch);
|
||||
if (curl_errno($ch)) {
|
||||
$error_msg = curl_error($ch);
|
||||
}
|
||||
curl_close($ch);
|
||||
if($admin && $error_msg){
|
||||
r2(U . 'dashboard', 'd', $error_msg);
|
||||
}
|
||||
return ($server_output) ? $server_output : $error_msg;
|
||||
}
|
||||
}
|
||||
262
system/autoload/Lang.php
Normal file
262
system/autoload/Lang.php
Normal file
@@ -0,0 +1,262 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* PHP Mikrotik Billing (https://github.com/hotspotbilling/phpnuxbill/)
|
||||
* by https://t.me/ibnux
|
||||
**/
|
||||
|
||||
|
||||
class Lang
|
||||
{
|
||||
public static function T($key)
|
||||
{
|
||||
global $_L, $lan_file, $config;
|
||||
if(is_array($_SESSION['Lang'])){
|
||||
$_L = array_merge($_L, $_SESSION['Lang']);
|
||||
}
|
||||
$key = preg_replace('/\s+/', ' ', $key);
|
||||
if (!empty($_L[$key])) {
|
||||
return $_L[$key];
|
||||
}
|
||||
$val = $key;
|
||||
$key = Lang::sanitize($key);
|
||||
if (isset($_L[$key])) {
|
||||
return $_L[$key];
|
||||
} else if (isset($_L[$key])) {
|
||||
return $_L[$key];
|
||||
} else {
|
||||
$iso = Lang::getIsoLang()[$config['language']];
|
||||
if (empty($iso)) {
|
||||
return $val;
|
||||
}
|
||||
if (!empty($iso) && !empty($val)) {
|
||||
$temp = Lang::translate($val, $iso);
|
||||
if (!empty($temp)) {
|
||||
$val = $temp;
|
||||
}
|
||||
}
|
||||
$_L[$key] = $val;
|
||||
$_SESSION['Lang'][$key] = $val;
|
||||
file_put_contents($lan_file, json_encode($_SESSION['Lang'], JSON_PRETTY_PRINT));
|
||||
return $val;
|
||||
}
|
||||
}
|
||||
|
||||
public static function sanitize($str)
|
||||
{
|
||||
return preg_replace("/[^A-Za-z0-9]/", '_', $str);;
|
||||
}
|
||||
|
||||
public static function getIsoLang()
|
||||
{
|
||||
global $isolang;
|
||||
if (empty($isolang) || count($isolang) == 0) {
|
||||
$isolang = json_decode(file_get_contents(File::pathFixer("system/lan/country.json")), true);
|
||||
}
|
||||
return $isolang;
|
||||
}
|
||||
|
||||
public static function htmlspecialchars($var)
|
||||
{
|
||||
return htmlspecialchars($var);
|
||||
}
|
||||
|
||||
public static function moneyFormat($var)
|
||||
{
|
||||
global $config;
|
||||
return $config['currency_code'] . ' ' . number_format($var, 0, $config['dec_point'], $config['thousands_sep']);
|
||||
}
|
||||
|
||||
public static function phoneFormat($phone)
|
||||
{
|
||||
global $config;
|
||||
if (Validator::UnsignedNumber($phone) && !empty($config['country_code_phone'])) {
|
||||
return preg_replace('/^0/', $config['country_code_phone'], $phone);
|
||||
} else {
|
||||
return $phone;
|
||||
}
|
||||
}
|
||||
|
||||
public static function dateFormat($date)
|
||||
{
|
||||
global $config;
|
||||
return date($config['date_format'], strtotime($date));
|
||||
}
|
||||
|
||||
public static function dateTimeFormat($date)
|
||||
{
|
||||
global $config;
|
||||
if (strtotime($date) < strtotime("2000-01-01 00:00:00")) {
|
||||
return "";
|
||||
} else {
|
||||
return date($config['date_format'] . ' H:i', strtotime($date));
|
||||
}
|
||||
}
|
||||
|
||||
public static function dateAndTimeFormat($date, $time)
|
||||
{
|
||||
global $config;
|
||||
return date($config['date_format'] . ' H:i', strtotime("$date $time"));
|
||||
}
|
||||
|
||||
public static function timeElapsed($datetime, $full = false)
|
||||
{
|
||||
$now = new DateTime;
|
||||
$ago = new DateTime($datetime);
|
||||
$diff = $now->diff($ago);
|
||||
|
||||
$diff->w = floor($diff->d / 7);
|
||||
$diff->d -= $diff->w * 7;
|
||||
|
||||
$string = array(
|
||||
'y' => Lang::T('year'),
|
||||
'm' => Lang::T('month'),
|
||||
'w' => Lang::T('week'),
|
||||
'd' => Lang::T('day'),
|
||||
'h' => Lang::T('hour'),
|
||||
'i' => Lang::T('minute'),
|
||||
's' => Lang::T('second'),
|
||||
);
|
||||
foreach ($string as $k => &$v) {
|
||||
if ($diff->$k) {
|
||||
$v = $diff->$k . ' ' . $v . ($diff->$k > 1 ? 's' : '');
|
||||
} else {
|
||||
unset($string[$k]);
|
||||
}
|
||||
}
|
||||
|
||||
if (!$full)
|
||||
$string = array_slice($string, 0, 1);
|
||||
return $string ? implode(', ', $string) .' '. Lang::T('ago') : Lang::T('just now');
|
||||
}
|
||||
|
||||
public static function nl2br($text)
|
||||
{
|
||||
return nl2br($text);
|
||||
}
|
||||
|
||||
public static function arrayCount($arr)
|
||||
{
|
||||
if (is_array($arr)) {
|
||||
return count($arr);
|
||||
} else if (is_object($arr)) {
|
||||
// Handle IdiormResultSet and other countable objects
|
||||
if (method_exists($arr, 'count')) {
|
||||
return $arr->count();
|
||||
} elseif (method_exists($arr, 'toArray')) {
|
||||
return count($arr->toArray());
|
||||
} elseif (is_countable($arr)) {
|
||||
return count($arr);
|
||||
} else {
|
||||
// Try to iterate and count
|
||||
$count = 0;
|
||||
foreach ($arr as $item) {
|
||||
$count++;
|
||||
}
|
||||
return $count;
|
||||
}
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
public static function getNotifText($key)
|
||||
{
|
||||
global $_notifmsg, $_notifmsg_default;
|
||||
if (isset($_notifmsg[$key])) {
|
||||
return $_notifmsg[$key];
|
||||
} else {
|
||||
return $_notifmsg_default[$key];
|
||||
}
|
||||
}
|
||||
|
||||
public static function ucWords($text)
|
||||
{
|
||||
return ucwords(str_replace('_', ' ', $text));
|
||||
}
|
||||
|
||||
public static function randomUpLowCase($text)
|
||||
{
|
||||
$jml = strlen($text);
|
||||
$result = '';
|
||||
for ($i = 0; $i < $jml; $i++) {
|
||||
if (rand(0, 99) % 2) {
|
||||
$result .= strtolower(substr($text, $i, 1));
|
||||
} else {
|
||||
$result .= substr($text, $i, 1);
|
||||
}
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* $pad_type
|
||||
* 0 Left
|
||||
* 1 right
|
||||
* 2 center
|
||||
* */
|
||||
public static function pad($text, $pad_string = ' ', $pad_type = 0)
|
||||
{
|
||||
global $config;
|
||||
$cols = 37;
|
||||
if ($config['printer_cols']) {
|
||||
$cols = $config['printer_cols'];
|
||||
}
|
||||
$text = trim($text);
|
||||
$texts = explode("\n", $text);
|
||||
if (count($texts) > 1) {
|
||||
$text = '';
|
||||
foreach ($texts as $t) {
|
||||
$text .= self::pad(trim($t), $pad_string, $pad_type) . "\n";
|
||||
}
|
||||
return $text;
|
||||
} else {
|
||||
return str_pad(trim($text), $cols, $pad_string, $pad_type);
|
||||
}
|
||||
}
|
||||
|
||||
public static function pads($textLeft, $textRight, $pad_string = ' ')
|
||||
{
|
||||
global $config;
|
||||
$cols = 37;
|
||||
if ($config['printer_cols']) {
|
||||
$cols = $config['printer_cols'];
|
||||
}
|
||||
return $textLeft . str_pad($textRight, $cols - strlen($textLeft), $pad_string, 0);
|
||||
}
|
||||
|
||||
public static function translate($txt, $to = 'id')
|
||||
{
|
||||
$ch = curl_init();
|
||||
curl_setopt($ch, CURLOPT_URL, "https://translate.google.com/m?hl=en&sl=en&tl=$to&ie=UTF-8&prev=_m&q=" . urlencode($txt));
|
||||
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
|
||||
curl_setopt($ch, CURLOPT_USERAGENT, "Mozilla/5.0 (iPhone; CPU OS 13_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) FxiOS/28.1 Mobile/15E148 Safari/605.1.15");
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
|
||||
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 2);
|
||||
curl_setopt($ch, CURLOPT_TIMEOUT, 5);
|
||||
curl_setopt($ch, CURLOPT_HEADER, 0);
|
||||
$hasil = curl_exec($ch);
|
||||
curl_close($ch);
|
||||
$temp = explode('<div class="result-container">', $hasil);
|
||||
if (count($temp) > 0) {
|
||||
$temp = explode("</div", $temp[1]);
|
||||
if (!empty($temp[0])) {
|
||||
return $temp[0];
|
||||
}
|
||||
}
|
||||
return $txt;
|
||||
}
|
||||
|
||||
public static function maskText($text){
|
||||
$len = strlen($text);
|
||||
if($len < 3){
|
||||
return "***";
|
||||
}else if($len<5){
|
||||
return substr($text,0,1)."***".substr($text,-1,1);
|
||||
}else if($len<8){
|
||||
return substr($text,0,2)."***".substr($text,-2,2);
|
||||
}else{
|
||||
return substr($text,0,4)."******".substr($text,-3,3);
|
||||
}
|
||||
}
|
||||
}
|
||||
32
system/autoload/Log.php
Normal file
32
system/autoload/Log.php
Normal file
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* PHP Mikrotik Billing (https://github.com/hotspotbilling/phpnuxbill/)
|
||||
* by https://t.me/ibnux
|
||||
**/
|
||||
|
||||
|
||||
class Log{
|
||||
public static function put($type, $description, $userid = '', $username = '')
|
||||
{
|
||||
$d = ORM::for_table('tbl_logs')->create();
|
||||
$d->date = date('Y-m-d H:i:s');
|
||||
$d->type = $type;
|
||||
$d->description = $description;
|
||||
$d->userid = $userid;
|
||||
$d->ip = (empty($username)) ? $_SERVER["REMOTE_ADDR"] : $username;
|
||||
$d->save();
|
||||
}
|
||||
|
||||
public static function arrayToText($array, $start = '', $result = '')
|
||||
{
|
||||
foreach ($array as $k => $v) {
|
||||
if (is_array($v)) {
|
||||
$result = Log::arrayToText($v, "$start$k.", $result);
|
||||
} else {
|
||||
$result .= $start.$k ." : ". strval($v) ."\n";
|
||||
}
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
333
system/autoload/Message.php
Normal file
333
system/autoload/Message.php
Normal file
@@ -0,0 +1,333 @@
|
||||
<?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;
|
||||
}
|
||||
}
|
||||
118
system/autoload/Meta.php
Normal file
118
system/autoload/Meta.php
Normal file
@@ -0,0 +1,118 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* PHP Mikrotik Billing (https://github.com/hotspotbilling/phpnuxbill/)
|
||||
* by https://t.me/ibnux
|
||||
*
|
||||
* Meta is for save adtional information in database for every existing table
|
||||
*
|
||||
* * Good for Plugin, so plugin don't need to modify existing tables
|
||||
*
|
||||
* Example to put data
|
||||
* if plan need to add point value for loyalty poin
|
||||
* Meta::for("tbl_plans")->set(1, 'point', '24');
|
||||
* it means tbl_plans with id 1 have point value 24, customer will get 24 point for loyalty if buy plan with id 1
|
||||
* You need to create the logic for that, Meta only hold the data
|
||||
*
|
||||
* Example to get data
|
||||
* $point = Meta::for("tbl_plans")->get(1, 'point');
|
||||
* this will return the point value of plan with id 1
|
||||
*
|
||||
* to get all key value
|
||||
* $metas = Meta::for("tbl_plans")->getAll(1);
|
||||
*
|
||||
* to delete 1 data
|
||||
* Meta::for("tbl_plans")->delete(1, 'point');
|
||||
*
|
||||
* to delete all data
|
||||
* Meta::for("tbl_plans")->deleteAll(1);
|
||||
**/
|
||||
|
||||
|
||||
class Meta
|
||||
{
|
||||
protected $table = '';
|
||||
|
||||
protected function __construct($table)
|
||||
{
|
||||
$this->table = $table;
|
||||
}
|
||||
|
||||
public static function for($table)
|
||||
{
|
||||
return new self($table);
|
||||
}
|
||||
|
||||
public function get($id, $key)
|
||||
{
|
||||
// get the Value
|
||||
return ORM::for_table('tbl_meta')
|
||||
->select('value')
|
||||
->where('tbl', $this->table)
|
||||
->where('tbl_id', $id)
|
||||
->where('name', $key)
|
||||
->find_one()['value'];
|
||||
}
|
||||
|
||||
public function getAll($id)
|
||||
{
|
||||
//get all key Value
|
||||
$metas = [];
|
||||
$result = ORM::for_table('tbl_meta')
|
||||
->select('name')
|
||||
->select('value')
|
||||
->where('tbl', $this->table)
|
||||
->where('tbl_id', $id)
|
||||
->find_array();
|
||||
foreach ($result as $value) {
|
||||
$metas[$value['name']] = $value['value'];
|
||||
}
|
||||
return $metas;
|
||||
}
|
||||
|
||||
public function set($id, $key, $value = '')
|
||||
{
|
||||
$meta = ORM::for_table('tbl_meta')
|
||||
->where('tbl', $this->table)
|
||||
->where('tbl_id', $id)
|
||||
->where('name', $key)
|
||||
->find_one();
|
||||
if (!$meta) {
|
||||
$meta = ORM::for_table('tbl_meta')->create();
|
||||
$meta->tbl = $this->table;
|
||||
$meta->tbl_id = $id;
|
||||
$meta->name = $key;
|
||||
$meta->value = $value;
|
||||
$meta->save();
|
||||
$result = $meta->id();
|
||||
if ($result) {
|
||||
return $result;
|
||||
}
|
||||
} else {
|
||||
$meta->value = $value;
|
||||
$meta->save();
|
||||
return $meta['id'];
|
||||
}
|
||||
}
|
||||
|
||||
public function delete($id, $key = '')
|
||||
{
|
||||
// get the Value
|
||||
return ORM::for_table('tbl_meta')
|
||||
->select('value')
|
||||
->where('tbl', $this->table)
|
||||
->where('tbl_id', $id)
|
||||
->where('name', $key)
|
||||
->delete();
|
||||
}
|
||||
|
||||
public function deleteAll($id)
|
||||
{
|
||||
//get all key Value
|
||||
return ORM::for_table('tbl_meta')
|
||||
->select('value')
|
||||
->where('tbl', $this->table)
|
||||
->where('tbl_id', $id)
|
||||
->delete_many();
|
||||
}
|
||||
}
|
||||
562
system/autoload/Mikrotik.php
Normal file
562
system/autoload/Mikrotik.php
Normal file
@@ -0,0 +1,562 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* PHP Mikrotik Billing (https://github.com/hotspotbilling/phpnuxbill/)
|
||||
* by https://t.me/ibnux
|
||||
**/
|
||||
|
||||
use PEAR2\Net\RouterOS;
|
||||
|
||||
class Mikrotik
|
||||
{
|
||||
public static function info($name)
|
||||
{
|
||||
return ORM::for_table('tbl_routers')->where('name', $name)->find_one();
|
||||
}
|
||||
|
||||
public static function getClient($ip, $user, $pass, $timeout = 10)
|
||||
{
|
||||
global $_app_stage;
|
||||
if ($_app_stage == 'demo') {
|
||||
return null;
|
||||
}
|
||||
$iport = explode(":", $ip);
|
||||
return new RouterOS\Client($iport[0], $user, $pass, ($iport[1]) ? $iport[1] : null, false, $timeout);
|
||||
}
|
||||
|
||||
public static function isUserLogin($client, $username)
|
||||
{
|
||||
global $_app_stage;
|
||||
if ($_app_stage == 'demo') {
|
||||
return null;
|
||||
}
|
||||
$printRequest = new RouterOS\Request(
|
||||
'/ip hotspot active print',
|
||||
RouterOS\Query::where('user', $username)
|
||||
);
|
||||
return $client->sendSync($printRequest)->getProperty('.id');
|
||||
}
|
||||
|
||||
public static function logMeIn($client, $user, $pass, $ip, $mac)
|
||||
{
|
||||
global $_app_stage;
|
||||
if ($_app_stage == 'demo') {
|
||||
return null;
|
||||
}
|
||||
$addRequest = new RouterOS\Request('/ip/hotspot/active/login');
|
||||
$client->sendSync(
|
||||
$addRequest
|
||||
->setArgument('user', $user)
|
||||
->setArgument('password', $pass)
|
||||
->setArgument('ip', $ip)
|
||||
->setArgument('mac-address', $mac)
|
||||
);
|
||||
}
|
||||
|
||||
public static function logMeOut($client, $user)
|
||||
{
|
||||
global $_app_stage;
|
||||
if ($_app_stage == 'demo') {
|
||||
return null;
|
||||
}
|
||||
$printRequest = new RouterOS\Request(
|
||||
'/ip hotspot active print',
|
||||
RouterOS\Query::where('user', $user)
|
||||
);
|
||||
$id = $client->sendSync($printRequest)->getProperty('.id');
|
||||
$removeRequest = new RouterOS\Request('/ip/hotspot/active/remove');
|
||||
$client->sendSync(
|
||||
$removeRequest
|
||||
->setArgument('numbers', $id)
|
||||
);
|
||||
}
|
||||
|
||||
public static function addHotspotPlan($client, $name, $sharedusers, $rate)
|
||||
{
|
||||
global $_app_stage;
|
||||
if ($_app_stage == 'demo') {
|
||||
return null;
|
||||
}
|
||||
$addRequest = new RouterOS\Request('/ip/hotspot/user/profile/add');
|
||||
$client->sendSync(
|
||||
$addRequest
|
||||
->setArgument('name', $name)
|
||||
->setArgument('shared-users', $sharedusers)
|
||||
->setArgument('rate-limit', $rate)
|
||||
);
|
||||
}
|
||||
|
||||
public static function setHotspotPlan($client, $name, $sharedusers, $rate)
|
||||
{
|
||||
global $_app_stage;
|
||||
if ($_app_stage == 'demo') {
|
||||
return null;
|
||||
}
|
||||
$printRequest = new RouterOS\Request(
|
||||
'/ip hotspot user profile print .proplist=.id',
|
||||
RouterOS\Query::where('name', $name)
|
||||
);
|
||||
$profileID = $client->sendSync($printRequest)->getProperty('.id');
|
||||
if (empty($profileID)) {
|
||||
Mikrotik::addHotspotPlan($client, $name, $sharedusers, $rate);
|
||||
} else {
|
||||
$setRequest = new RouterOS\Request('/ip/hotspot/user/profile/set');
|
||||
$client->sendSync(
|
||||
$setRequest
|
||||
->setArgument('numbers', $profileID)
|
||||
->setArgument('shared-users', $sharedusers)
|
||||
->setArgument('rate-limit', $rate)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public static function setHotspotExpiredPlan($client, $name, $pool)
|
||||
{
|
||||
global $_app_stage;
|
||||
if ($_app_stage == 'demo') {
|
||||
return null;
|
||||
}
|
||||
$printRequest = new RouterOS\Request(
|
||||
'/ip hotspot user profile print .proplist=.id',
|
||||
RouterOS\Query::where('name', $name)
|
||||
);
|
||||
$profileID = $client->sendSync($printRequest)->getProperty('.id');
|
||||
if (empty($profileID)) {
|
||||
$addRequest = new RouterOS\Request('/ip/hotspot/user/profile/add');
|
||||
$client->sendSync(
|
||||
$addRequest
|
||||
->setArgument('name', $name)
|
||||
->setArgument('shared-users', 3)
|
||||
->setArgument('address-pool', $pool)
|
||||
->setArgument('rate-limit', '512K/512K')
|
||||
);
|
||||
} else {
|
||||
$setRequest = new RouterOS\Request('/ip/hotspot/user/profile/set');
|
||||
$client->sendSync(
|
||||
$setRequest
|
||||
->setArgument('numbers', $profileID)
|
||||
->setArgument('shared-users', 3)
|
||||
->setArgument('address-pool', $pool)
|
||||
->setArgument('rate-limit', '512K/512K')
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public static function removeHotspotPlan($client, $name)
|
||||
{
|
||||
global $_app_stage;
|
||||
if ($_app_stage == 'demo') {
|
||||
return null;
|
||||
}
|
||||
$printRequest = new RouterOS\Request(
|
||||
'/ip hotspot user profile print .proplist=.id',
|
||||
RouterOS\Query::where('name', $name)
|
||||
);
|
||||
$profileID = $client->sendSync($printRequest)->getProperty('.id');
|
||||
|
||||
$removeRequest = new RouterOS\Request('/ip/hotspot/user/profile/remove');
|
||||
$client->sendSync(
|
||||
$removeRequest
|
||||
->setArgument('numbers', $profileID)
|
||||
);
|
||||
}
|
||||
|
||||
public static function removeHotspotUser($client, $username)
|
||||
{
|
||||
global $_app_stage;
|
||||
if ($_app_stage == 'demo') {
|
||||
return null;
|
||||
}
|
||||
$printRequest = new RouterOS\Request(
|
||||
'/ip hotspot user print .proplist=.id',
|
||||
RouterOS\Query::where('name', $username)
|
||||
);
|
||||
$userID = $client->sendSync($printRequest)->getProperty('.id');
|
||||
$removeRequest = new RouterOS\Request('/ip/hotspot/user/remove');
|
||||
$client->sendSync(
|
||||
$removeRequest
|
||||
->setArgument('numbers', $userID)
|
||||
);
|
||||
}
|
||||
|
||||
public static function addHotspotUser($client, $plan, $customer)
|
||||
{
|
||||
global $_app_stage;
|
||||
if ($_app_stage == 'demo') {
|
||||
return null;
|
||||
}
|
||||
$addRequest = new RouterOS\Request('/ip/hotspot/user/add');
|
||||
if ($plan['typebp'] == "Limited") {
|
||||
if ($plan['limit_type'] == "Time_Limit") {
|
||||
if ($plan['time_unit'] == 'Hrs')
|
||||
$timelimit = $plan['time_limit'] . ":00:00";
|
||||
else
|
||||
$timelimit = "00:" . $plan['time_limit'] . ":00";
|
||||
$client->sendSync(
|
||||
$addRequest
|
||||
->setArgument('name', $customer['username'])
|
||||
->setArgument('profile', $plan['name_plan'])
|
||||
->setArgument('password', $customer['password'])
|
||||
->setArgument('comment', $customer['fullname'])
|
||||
->setArgument('email', $customer['email'])
|
||||
->setArgument('limit-uptime', $timelimit)
|
||||
);
|
||||
} else if ($plan['limit_type'] == "Data_Limit") {
|
||||
if ($plan['data_unit'] == 'GB')
|
||||
$datalimit = $plan['data_limit'] . "000000000";
|
||||
else
|
||||
$datalimit = $plan['data_limit'] . "000000";
|
||||
$client->sendSync(
|
||||
$addRequest
|
||||
->setArgument('name', $customer['username'])
|
||||
->setArgument('profile', $plan['name_plan'])
|
||||
->setArgument('password', $customer['password'])
|
||||
->setArgument('comment', $customer['fullname'])
|
||||
->setArgument('email', $customer['email'])
|
||||
->setArgument('limit-bytes-total', $datalimit)
|
||||
);
|
||||
} else if ($plan['limit_type'] == "Both_Limit") {
|
||||
if ($plan['time_unit'] == 'Hrs')
|
||||
$timelimit = $plan['time_limit'] . ":00:00";
|
||||
else
|
||||
$timelimit = "00:" . $plan['time_limit'] . ":00";
|
||||
if ($plan['data_unit'] == 'GB')
|
||||
$datalimit = $plan['data_limit'] . "000000000";
|
||||
else
|
||||
$datalimit = $plan['data_limit'] . "000000";
|
||||
$client->sendSync(
|
||||
$addRequest
|
||||
->setArgument('name', $customer['username'])
|
||||
->setArgument('profile', $plan['name_plan'])
|
||||
->setArgument('password', $customer['password'])
|
||||
->setArgument('comment', $customer['fullname'])
|
||||
->setArgument('email', $customer['email'])
|
||||
->setArgument('limit-uptime', $timelimit)
|
||||
->setArgument('limit-bytes-total', $datalimit)
|
||||
);
|
||||
}
|
||||
} else {
|
||||
$client->sendSync(
|
||||
$addRequest
|
||||
->setArgument('name', $customer['username'])
|
||||
->setArgument('profile', $plan['name_plan'])
|
||||
->setArgument('comment', $customer['fullname'])
|
||||
->setArgument('email', $customer['email'])
|
||||
->setArgument('password', $customer['password'])
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public static function setHotspotUser($client, $user, $pass)
|
||||
{
|
||||
global $_app_stage;
|
||||
if ($_app_stage == 'demo') {
|
||||
return null;
|
||||
}
|
||||
$printRequest = new RouterOS\Request('/ip/hotspot/user/print');
|
||||
$printRequest->setArgument('.proplist', '.id');
|
||||
$printRequest->setQuery(RouterOS\Query::where('name', $user));
|
||||
$id = $client->sendSync($printRequest)->getProperty('.id');
|
||||
|
||||
$setRequest = new RouterOS\Request('/ip/hotspot/user/set');
|
||||
$setRequest->setArgument('numbers', $id);
|
||||
$setRequest->setArgument('password', $pass);
|
||||
$client->sendSync($setRequest);
|
||||
}
|
||||
|
||||
public static function setHotspotUserPackage($client, $user, $plan)
|
||||
{
|
||||
global $_app_stage;
|
||||
if ($_app_stage == 'demo') {
|
||||
return null;
|
||||
}
|
||||
$printRequest = new RouterOS\Request('/ip/hotspot/user/print');
|
||||
$printRequest->setArgument('.proplist', '.id');
|
||||
$printRequest->setQuery(RouterOS\Query::where('name', $user));
|
||||
$id = $client->sendSync($printRequest)->getProperty('.id');
|
||||
|
||||
$setRequest = new RouterOS\Request('/ip/hotspot/user/set');
|
||||
$setRequest->setArgument('numbers', $id);
|
||||
$setRequest->setArgument('profile', $plan);
|
||||
$client->sendSync($setRequest);
|
||||
}
|
||||
|
||||
public static function removeHotspotActiveUser($client, $username)
|
||||
{
|
||||
global $_app_stage;
|
||||
if ($_app_stage == 'demo') {
|
||||
return null;
|
||||
}
|
||||
$onlineRequest = new RouterOS\Request('/ip/hotspot/active/print');
|
||||
$onlineRequest->setArgument('.proplist', '.id');
|
||||
$onlineRequest->setQuery(RouterOS\Query::where('user', $username));
|
||||
$id = $client->sendSync($onlineRequest)->getProperty('.id');
|
||||
|
||||
$removeRequest = new RouterOS\Request('/ip/hotspot/active/remove');
|
||||
$removeRequest->setArgument('numbers', $id);
|
||||
$client->sendSync($removeRequest);
|
||||
}
|
||||
|
||||
public static function removePpoeUser($client, $username)
|
||||
{
|
||||
global $_app_stage;
|
||||
if ($_app_stage == 'demo') {
|
||||
return null;
|
||||
}
|
||||
$printRequest = new RouterOS\Request('/ppp/secret/print');
|
||||
//$printRequest->setArgument('.proplist', '.id');
|
||||
$printRequest->setQuery(RouterOS\Query::where('name', $username));
|
||||
$id = $client->sendSync($printRequest)->getProperty('.id');
|
||||
$removeRequest = new RouterOS\Request('/ppp/secret/remove');
|
||||
$removeRequest->setArgument('numbers', $id);
|
||||
$client->sendSync($removeRequest);
|
||||
}
|
||||
|
||||
public static function addPpoeUser($client, $plan, $customer)
|
||||
{
|
||||
global $_app_stage;
|
||||
if ($_app_stage == 'demo') {
|
||||
return null;
|
||||
}
|
||||
$addRequest = new RouterOS\Request('/ppp/secret/add');
|
||||
if (!empty($customer['pppoe_password'])) {
|
||||
$pass = $customer['pppoe_password'];
|
||||
} else {
|
||||
$pass = $customer['password'];
|
||||
}
|
||||
$client->sendSync(
|
||||
$addRequest
|
||||
->setArgument('name', $customer['username'])
|
||||
->setArgument('service', 'pppoe')
|
||||
->setArgument('profile', $plan['name_plan'])
|
||||
->setArgument('comment', $customer['fullname'] . ' | ' . $customer['email'])
|
||||
->setArgument('password', $pass)
|
||||
);
|
||||
}
|
||||
|
||||
public static function setPpoeUser($client, $user, $pass)
|
||||
{
|
||||
global $_app_stage;
|
||||
if ($_app_stage == 'demo') {
|
||||
return null;
|
||||
}
|
||||
$printRequest = new RouterOS\Request('/ppp/secret/print');
|
||||
$printRequest->setArgument('.proplist', '.id');
|
||||
$printRequest->setQuery(RouterOS\Query::where('name', $user));
|
||||
$id = $client->sendSync($printRequest)->getProperty('.id');
|
||||
|
||||
$setRequest = new RouterOS\Request('/ppp/secret/set');
|
||||
$setRequest->setArgument('numbers', $id);
|
||||
$setRequest->setArgument('password', $pass);
|
||||
$client->sendSync($setRequest);
|
||||
}
|
||||
|
||||
public static function setPpoeUserPlan($client, $user, $plan)
|
||||
{
|
||||
global $_app_stage;
|
||||
if ($_app_stage == 'demo') {
|
||||
return null;
|
||||
}
|
||||
$printRequest = new RouterOS\Request('/ppp/secret/print');
|
||||
$printRequest->setArgument('.proplist', '.id');
|
||||
$printRequest->setQuery(RouterOS\Query::where('name', $user));
|
||||
$id = $client->sendSync($printRequest)->getProperty('.id');
|
||||
|
||||
$setRequest = new RouterOS\Request('/ppp/secret/set');
|
||||
$setRequest->setArgument('numbers', $id);
|
||||
$setRequest->setArgument('profile', $plan);
|
||||
$client->sendSync($setRequest);
|
||||
}
|
||||
|
||||
public static function removePpoeActive($client, $username)
|
||||
{
|
||||
global $_app_stage;
|
||||
if ($_app_stage == 'demo') {
|
||||
return null;
|
||||
}
|
||||
$onlineRequest = new RouterOS\Request('/ppp/active/print');
|
||||
$onlineRequest->setArgument('.proplist', '.id');
|
||||
$onlineRequest->setQuery(RouterOS\Query::where('name', $username));
|
||||
$id = $client->sendSync($onlineRequest)->getProperty('.id');
|
||||
|
||||
$removeRequest = new RouterOS\Request('/ppp/active/remove');
|
||||
$removeRequest->setArgument('numbers', $id);
|
||||
$client->sendSync($removeRequest);
|
||||
}
|
||||
|
||||
public static function removePool($client, $name)
|
||||
{
|
||||
global $_app_stage;
|
||||
if ($_app_stage == 'demo') {
|
||||
return null;
|
||||
}
|
||||
$printRequest = new RouterOS\Request(
|
||||
'/ip pool print .proplist=.id',
|
||||
RouterOS\Query::where('name', $name)
|
||||
);
|
||||
$poolID = $client->sendSync($printRequest)->getProperty('.id');
|
||||
|
||||
$removeRequest = new RouterOS\Request('/ip/pool/remove');
|
||||
$client->sendSync(
|
||||
$removeRequest
|
||||
->setArgument('numbers', $poolID)
|
||||
);
|
||||
}
|
||||
|
||||
public static function addPool($client, $name, $ip_address)
|
||||
{
|
||||
global $_app_stage;
|
||||
if ($_app_stage == 'demo') {
|
||||
return null;
|
||||
}
|
||||
$addRequest = new RouterOS\Request('/ip/pool/add');
|
||||
$client->sendSync(
|
||||
$addRequest
|
||||
->setArgument('name', $name)
|
||||
->setArgument('ranges', $ip_address)
|
||||
);
|
||||
}
|
||||
|
||||
public static function setPool($client, $name, $ip_address)
|
||||
{
|
||||
global $_app_stage;
|
||||
if ($_app_stage == 'demo') {
|
||||
return null;
|
||||
}
|
||||
$printRequest = new RouterOS\Request(
|
||||
'/ip pool print .proplist=.id',
|
||||
RouterOS\Query::where('name', $name)
|
||||
);
|
||||
$poolID = $client->sendSync($printRequest)->getProperty('.id');
|
||||
|
||||
if (empty($poolID)) {
|
||||
self::addPool($client, $name, $ip_address);
|
||||
} else {
|
||||
$setRequest = new RouterOS\Request('/ip/pool/set');
|
||||
$client->sendSync(
|
||||
$setRequest
|
||||
->setArgument('numbers', $poolID)
|
||||
->setArgument('ranges', $ip_address)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static function addPpoePlan($client, $name, $pool, $rate)
|
||||
{
|
||||
global $_app_stage;
|
||||
if ($_app_stage == 'demo') {
|
||||
return null;
|
||||
}
|
||||
$addRequest = new RouterOS\Request('/ppp/profile/add');
|
||||
$client->sendSync(
|
||||
$addRequest
|
||||
->setArgument('name', $name)
|
||||
->setArgument('local-address', $pool)
|
||||
->setArgument('remote-address', $pool)
|
||||
->setArgument('rate-limit', $rate)
|
||||
);
|
||||
}
|
||||
|
||||
public static function setPpoePlan($client, $name, $pool, $rate)
|
||||
{
|
||||
global $_app_stage;
|
||||
if ($_app_stage == 'demo') {
|
||||
return null;
|
||||
}
|
||||
$printRequest = new RouterOS\Request(
|
||||
'/ppp profile print .proplist=.id',
|
||||
RouterOS\Query::where('name', $name)
|
||||
);
|
||||
$profileID = $client->sendSync($printRequest)->getProperty('.id');
|
||||
if (empty($profileID)) {
|
||||
self::addPpoePlan($client, $name, $pool, $rate);
|
||||
} else {
|
||||
$setRequest = new RouterOS\Request('/ppp/profile/set');
|
||||
$client->sendSync(
|
||||
$setRequest
|
||||
->setArgument('numbers', $profileID)
|
||||
->setArgument('local-address', $pool)
|
||||
->setArgument('remote-address', $pool)
|
||||
->setArgument('rate-limit', $rate)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public static function removePpoePlan($client, $name)
|
||||
{
|
||||
global $_app_stage;
|
||||
if ($_app_stage == 'demo') {
|
||||
return null;
|
||||
}
|
||||
$printRequest = new RouterOS\Request(
|
||||
'/ppp profile print .proplist=.id',
|
||||
RouterOS\Query::where('name', $name)
|
||||
);
|
||||
$profileID = $client->sendSync($printRequest)->getProperty('.id');
|
||||
|
||||
$removeRequest = new RouterOS\Request('/ppp/profile/remove');
|
||||
$client->sendSync(
|
||||
$removeRequest
|
||||
->setArgument('numbers', $profileID)
|
||||
);
|
||||
}
|
||||
|
||||
public static function sendSMS($client, $to, $message)
|
||||
{
|
||||
global $_app_stage;
|
||||
if ($_app_stage == 'demo') {
|
||||
return null;
|
||||
}
|
||||
$smsRequest = new RouterOS\Request('/tool sms send');
|
||||
$smsRequest
|
||||
->setArgument('phone-number', $to)
|
||||
->setArgument('message', $message);
|
||||
$client->sendSync($smsRequest);
|
||||
}
|
||||
|
||||
public static function getIpHotspotUser($client, $username){
|
||||
global $_app_stage;
|
||||
if ($_app_stage == 'demo') {
|
||||
return null;
|
||||
}
|
||||
$printRequest = new RouterOS\Request(
|
||||
'/ip hotspot active print',
|
||||
RouterOS\Query::where('user', $username)
|
||||
);
|
||||
return $client->sendSync($printRequest)->getProperty('address');
|
||||
}
|
||||
|
||||
public static function addIpToAddressList($client, $ip, $listName, $comment = '')
|
||||
{
|
||||
global $_app_stage;
|
||||
if ($_app_stage == 'demo') {
|
||||
return null;
|
||||
}
|
||||
$addRequest = new RouterOS\Request('/ip/firewall/address-list/add');
|
||||
$client->sendSync(
|
||||
$addRequest
|
||||
->setArgument('address', $ip)
|
||||
->setArgument('comment', $comment)
|
||||
->setArgument('list', $listName)
|
||||
);
|
||||
}
|
||||
|
||||
public static function removeIpFromAddressList($client, $ip)
|
||||
{
|
||||
global $_app_stage;
|
||||
if ($_app_stage == 'demo') {
|
||||
return null;
|
||||
}
|
||||
$printRequest = new RouterOS\Request(
|
||||
'/ip firewall address-list print .proplist=.id',
|
||||
RouterOS\Query::where('address', $ip)
|
||||
);
|
||||
$id = $client->sendSync($printRequest)->getProperty('.id');
|
||||
$removeRequest = new RouterOS\Request('/ip/firewall/address-list/remove');
|
||||
$client->sendSync(
|
||||
$removeRequest
|
||||
->setArgument('numbers', $id)
|
||||
);
|
||||
}
|
||||
}
|
||||
817
system/autoload/Package.php
Normal file
817
system/autoload/Package.php
Normal file
@@ -0,0 +1,817 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* PHP Mikrotik Billing (https://github.com/hotspotbilling/phpnuxbill/)
|
||||
* by https://t.me/ibnux
|
||||
**/
|
||||
|
||||
|
||||
|
||||
class Package
|
||||
{
|
||||
/**
|
||||
* @param int $id_customer String user identifier
|
||||
* @param string $router_name router name for this package
|
||||
* @param int $plan_id plan id for this package
|
||||
* @param string $gateway payment gateway name
|
||||
* @param string $channel channel payment gateway
|
||||
* @param array $pgids payment gateway ids
|
||||
* @return boolean
|
||||
*/
|
||||
public static function rechargeUser($id_customer, $router_name, $plan_id, $gateway, $channel, $note = '')
|
||||
{
|
||||
global $config, $admin, $c, $p, $b, $t, $d, $zero, $trx;
|
||||
$date_now = date("Y-m-d H:i:s");
|
||||
$date_only = date("Y-m-d");
|
||||
$time_only = date("H:i:s");
|
||||
$time = date("H:i:s");
|
||||
$inv = "";
|
||||
|
||||
if ($id_customer == '' or $router_name == '' or $plan_id == '') {
|
||||
return false;
|
||||
}
|
||||
|
||||
$c = ORM::for_table('tbl_customers')->where('id', $id_customer)->find_one();
|
||||
$p = ORM::for_table('tbl_plans')->where('id', $plan_id)->find_one();
|
||||
|
||||
if ($c['status'] != 'Active') {
|
||||
_alert(Lang::T('This account status') . ' : ' . Lang::T($c['status']), 'danger', "");
|
||||
}
|
||||
|
||||
$add_cost = 0;
|
||||
$bills = [];
|
||||
// Zero cost recharge
|
||||
if (isset($zero) && $zero == 1) {
|
||||
$p['price'] = 0;
|
||||
} else {
|
||||
// Additional cost
|
||||
list($bills, $add_cost) = User::getBills($id_customer);
|
||||
if ($add_cost > 0 && $router_name != 'balance') {
|
||||
foreach ($bills as $k => $v) {
|
||||
$note .= $k . " : " . Lang::moneyFormat($v) . "\n";
|
||||
}
|
||||
$note .= $p['name_plan'] . " : " . Lang::moneyFormat($p['price']) . "\n";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (!$p['enabled']) {
|
||||
if (!isset($admin) || !isset($admin['id']) || empty($admin['id'])) {
|
||||
r2(U . 'home', 'e', Lang::T('Plan Not found'));
|
||||
}
|
||||
if (!in_array($admin['user_type'], ['SuperAdmin', 'Admin'])) {
|
||||
r2(U . 'dashboard', 'e', Lang::T('Plan Not found'));
|
||||
}
|
||||
}
|
||||
|
||||
if ($p['validity_unit'] == 'Period') {
|
||||
$day_exp = User::getAttribute("Expired Date", $c['id']); //ORM::for_table('tbl_customers_fields')->where('field_name', 'Expired Date')->where('customer_id', $c['id'])->find_one();
|
||||
if (!$day_exp) {
|
||||
$day_exp = 20;
|
||||
// $day_exp = date('d', strtotime($c['created_at']));
|
||||
// if (empty($day_exp) || $day_exp > 28) {
|
||||
// $day_exp = 1;
|
||||
// }
|
||||
$f = ORM::for_table('tbl_customers_fields')->create();
|
||||
$f->customer_id = $c['id'];
|
||||
$f->field_name = 'Expired Date';
|
||||
$f->field_value = $day_exp;
|
||||
$f->save();
|
||||
}
|
||||
}
|
||||
|
||||
if ($router_name == 'balance') {
|
||||
// insert table transactions
|
||||
$t = ORM::for_table('tbl_transactions')->create();
|
||||
$t->invoice = $inv = "INV-" . Package::_raid();
|
||||
$t->username = $c['username'];
|
||||
$t->plan_name = $p['name_plan'];
|
||||
$t->price = $p['price'];
|
||||
$t->recharged_on = $date_only;
|
||||
$t->recharged_time = date("H:i:s");
|
||||
$t->expiration = $date_only;
|
||||
$t->time = $time;
|
||||
$t->method = "$gateway - $channel";
|
||||
$t->routers = $router_name;
|
||||
$t->type = "Balance";
|
||||
if ($admin) {
|
||||
$t->admin_id = ($admin['id']) ? $admin['id'] : '0';
|
||||
} else {
|
||||
$t->admin_id = '0';
|
||||
}
|
||||
$t->save();
|
||||
|
||||
$balance_before = $c['balance'];
|
||||
Balance::plus($id_customer, $p['price']);
|
||||
$balance = $c['balance'] + $p['price'];
|
||||
|
||||
$textInvoice = Lang::getNotifText('invoice_balance');
|
||||
$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]]', $inv, $textInvoice);
|
||||
$textInvoice = str_replace('[[date]]', Lang::dateTimeFormat($date_now), $textInvoice);
|
||||
$textInvoice = str_replace('[[payment_gateway]]', $gateway, $textInvoice);
|
||||
$textInvoice = str_replace('[[payment_channel]]', $channel, $textInvoice);
|
||||
$textInvoice = str_replace('[[type]]', 'Balance', $textInvoice);
|
||||
$textInvoice = str_replace('[[plan_name]]', $p['name_plan'], $textInvoice);
|
||||
$textInvoice = str_replace('[[plan_price]]', Lang::moneyFormat($p['price']), $textInvoice);
|
||||
$textInvoice = str_replace('[[name]]', $c['fullname'], $textInvoice);
|
||||
$textInvoice = str_replace('[[user_name]]', $c['username'], $textInvoice);
|
||||
$textInvoice = str_replace('[[user_password]]', $c['password'], $textInvoice);
|
||||
$textInvoice = str_replace('[[footer]]', $config['note'], $textInvoice);
|
||||
$textInvoice = str_replace('[[balance_before]]', Lang::moneyFormat($balance_before), $textInvoice);
|
||||
$textInvoice = str_replace('[[balance]]', Lang::moneyFormat($balance), $textInvoice);
|
||||
|
||||
if ($config['user_notification_payment'] == 'sms') {
|
||||
Message::sendSMS($c['phonenumber'], $textInvoice);
|
||||
} else if ($config['user_notification_payment'] == 'wa') {
|
||||
Message::sendWhatsapp($c['phonenumber'], $textInvoice);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1 Customer only can have 1 PPPOE and 1 Hotspot Plan, 1 prepaid and 1 postpaid
|
||||
*/
|
||||
$b = ORM::for_table('tbl_user_recharges')
|
||||
->select('tbl_user_recharges.id', 'id')
|
||||
->select('customer_id')
|
||||
->select('username')
|
||||
->select('plan_id')
|
||||
->select('namebp')
|
||||
->select('recharged_on')
|
||||
->select('recharged_time')
|
||||
->select('expiration')
|
||||
->select('time')
|
||||
->select('status')
|
||||
->select('method')
|
||||
->select('tbl_user_recharges.routers', 'routers')
|
||||
->select('tbl_user_recharges.type', 'type')
|
||||
->select('admin_id')
|
||||
->select('prepaid')
|
||||
->where('customer_id', $id_customer)
|
||||
->where('tbl_user_recharges.routers', $router_name)
|
||||
->where('tbl_user_recharges.Type', $p['type'])
|
||||
# PPPOE or Hotspot only can have 1 per customer prepaid or postpaid
|
||||
# because 1 customer can have 1 PPPOE and 1 Hotspot Plan in mikrotik
|
||||
//->where('prepaid', $p['prepaid'])
|
||||
->left_outer_join('tbl_plans', array('tbl_plans.id', '=', 'tbl_user_recharges.plan_id'))
|
||||
->find_one();
|
||||
|
||||
run_hook("recharge_user");
|
||||
|
||||
|
||||
$mikrotik = Mikrotik::info($router_name);
|
||||
if ($p['validity_unit'] == 'Months') {
|
||||
$date_exp = date("Y-m-d", strtotime('+' . $p['validity'] . ' month'));
|
||||
} else if ($p['validity_unit'] == 'Period') {
|
||||
$date_tmp = date("Y-m-$day_exp", strtotime('+' . $p['validity'] . ' month'));
|
||||
$dt1 = new DateTime("$date_only");
|
||||
$dt2 = new DateTime("$date_tmp");
|
||||
$diff = $dt2->diff($dt1);
|
||||
$sum = $diff->format("%a"); // => 453
|
||||
if ($sum >= 35 * $p['validity']) {
|
||||
$date_exp = date("Y-m-$day_exp", strtotime('+0 month'));
|
||||
} else {
|
||||
$date_exp = date("Y-m-$day_exp", strtotime('+' . $p['validity'] . ' month'));
|
||||
};
|
||||
$time = date("23:59:00");
|
||||
} else if ($p['validity_unit'] == 'Days') {
|
||||
$datetime = explode(' ', date("Y-m-d H:i:s", strtotime('+' . $p['validity'] . ' day')));
|
||||
$date_exp = $datetime[0];
|
||||
$time = $datetime[1];
|
||||
} else if ($p['validity_unit'] == 'Hrs') {
|
||||
$datetime = explode(' ', date("Y-m-d H:i:s", strtotime('+' . $p['validity'] . ' hour')));
|
||||
$date_exp = $datetime[0];
|
||||
$time = $datetime[1];
|
||||
} else if ($p['validity_unit'] == 'Mins') {
|
||||
$datetime = explode(' ', date("Y-m-d H:i:s", strtotime('+' . $p['validity'] . ' minute')));
|
||||
$date_exp = $datetime[0];
|
||||
$time = $datetime[1];
|
||||
}
|
||||
$isChangePlan = false;
|
||||
if ($p['type'] == 'Hotspot') {
|
||||
if ($b) {
|
||||
if ($plan_id != $b['plan_id']) {
|
||||
$isChangePlan = true;
|
||||
}
|
||||
if ($config['extend_expiry'] === 'yes') {
|
||||
if ($b['namebp'] == $p['name_plan'] && $b['status'] == 'on') {
|
||||
// if it same internet plan, expired will extend
|
||||
if ($p['validity_unit'] == 'Months') {
|
||||
$date_exp = date("Y-m-d", strtotime($b['expiration'] . ' +' . $p['validity'] . ' months'));
|
||||
$time = $b['time'];
|
||||
} else if ($p['validity_unit'] == 'Period') {
|
||||
$date_exp = date("Y-m-$day_exp", strtotime($b['expiration'] . ' +' . $p['validity'] . ' months'));
|
||||
$time = date("23:59:00");
|
||||
} else if ($p['validity_unit'] == 'Days') {
|
||||
$date_exp = date("Y-m-d", strtotime($b['expiration'] . ' +' . $p['validity'] . ' days'));
|
||||
$time = $b['time'];
|
||||
} else if ($p['validity_unit'] == 'Hrs') {
|
||||
$datetime = explode(' ', date("Y-m-d H:i:s", strtotime($b['expiration'] . ' ' . $b['time'] . ' +' . $p['validity'] . ' hours')));
|
||||
$date_exp = $datetime[0];
|
||||
$time = $datetime[1];
|
||||
} else if ($p['validity_unit'] == 'Mins') {
|
||||
$datetime = explode(' ', date("Y-m-d H:i:s", strtotime($b['expiration'] . ' ' . $b['time'] . ' +' . $p['validity'] . ' minutes')));
|
||||
$date_exp = $datetime[0];
|
||||
$time = $datetime[1];
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($isChangePlan || $b['status'] == 'off') {
|
||||
if ($p['is_radius']) {
|
||||
Radius::customerAddPlan($c, $p, "$date_exp $time");
|
||||
} else {
|
||||
$client = Mikrotik::getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']);
|
||||
Mikrotik::removeHotspotUser($client, $c['username']);
|
||||
Mikrotik::removeHotspotActiveUser($client, $c['username']);
|
||||
Mikrotik::addHotspotUser($client, $p, $c);
|
||||
}
|
||||
}
|
||||
|
||||
$b->customer_id = $id_customer;
|
||||
$b->username = $c['username'];
|
||||
$b->plan_id = $plan_id;
|
||||
$b->namebp = $p['name_plan'];
|
||||
$b->recharged_on = $date_only;
|
||||
$b->recharged_time = $time_only;
|
||||
$b->expiration = $date_exp;
|
||||
$b->time = $time;
|
||||
$b->status = "on";
|
||||
$b->method = "$gateway - $channel";
|
||||
$b->routers = $router_name;
|
||||
$b->type = "Hotspot";
|
||||
if ($admin) {
|
||||
$b->admin_id = ($admin['id']) ? $admin['id'] : '0';
|
||||
} else {
|
||||
$b->admin_id = '0';
|
||||
}
|
||||
$b->save();
|
||||
|
||||
// insert table transactions
|
||||
$t = ORM::for_table('tbl_transactions')->create();
|
||||
$t->invoice = $inv = "INV-" . Package::_raid();
|
||||
$t->username = $c['username'];
|
||||
$t->plan_name = $p['name_plan'];
|
||||
if ($p['validity_unit'] == 'Period') {
|
||||
// Postpaid price from field
|
||||
$add_inv = User::getAttribute("Invoice", $id_customer);
|
||||
if (empty($add_inv) or $add_inv == 0) {
|
||||
$t->price = $p['price'] + $add_cost;
|
||||
} else {
|
||||
$t->price = $add_inv + $add_cost;
|
||||
}
|
||||
} else {
|
||||
$t->price = $p['price'] + $add_cost;
|
||||
}
|
||||
$t->recharged_on = $date_only;
|
||||
$t->recharged_time = $time_only;
|
||||
$t->expiration = $date_exp;
|
||||
$t->time = $time;
|
||||
$t->method = "$gateway - $channel";
|
||||
$t->routers = $router_name;
|
||||
$t->note = $note;
|
||||
$t->type = "Hotspot";
|
||||
if ($admin) {
|
||||
$t->admin_id = ($admin['id']) ? $admin['id'] : '0';
|
||||
} else {
|
||||
$t->admin_id = '0';
|
||||
}
|
||||
$t->save();
|
||||
|
||||
if ($p['validity_unit'] == 'Period') {
|
||||
// insert price to fields for invoice next month
|
||||
$fl = ORM::for_table('tbl_customers_fields')->where('field_name', 'Invoice')->where('customer_id', $c['id'])->find_one();
|
||||
if (!$fl) {
|
||||
$fl = ORM::for_table('tbl_customers_fields')->create();
|
||||
$fl->customer_id = $c['id'];
|
||||
$fl->field_name = 'Invoice';
|
||||
$fl->field_value = $p['price'];
|
||||
$fl->save();
|
||||
} else {
|
||||
$fl->customer_id = $c['id'];
|
||||
$fl->field_value = $p['price'];
|
||||
$fl->save();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Message::sendTelegram("#u$c[username] $c[fullname] #recharge #Hotspot \n" . $p['name_plan'] .
|
||||
"\nRouter: " . $router_name .
|
||||
"\nGateway: " . $gateway .
|
||||
"\nChannel: " . $channel .
|
||||
"\nPrice: " . Lang::moneyFormat($p['price'] + $add_cost) .
|
||||
"\nNote:\n" . $note);
|
||||
} else {
|
||||
if ($p['is_radius']) {
|
||||
Radius::customerAddPlan($c, $p, "$date_exp $time");
|
||||
} else {
|
||||
$client = Mikrotik::getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']);
|
||||
Mikrotik::removeHotspotUser($client, $c['username']);
|
||||
Mikrotik::removeHotspotActiveUser($client, $c['username']);
|
||||
Mikrotik::addHotspotUser($client, $p, $c);
|
||||
}
|
||||
|
||||
$d = ORM::for_table('tbl_user_recharges')->create();
|
||||
$d->customer_id = $id_customer;
|
||||
$d->username = $c['username'];
|
||||
$d->plan_id = $plan_id;
|
||||
$d->namebp = $p['name_plan'];
|
||||
$d->recharged_on = $date_only;
|
||||
$d->recharged_time = $time_only;
|
||||
$d->expiration = $date_exp;
|
||||
$d->time = $time;
|
||||
$d->status = "on";
|
||||
$d->method = "$gateway - $channel";
|
||||
$d->routers = $router_name;
|
||||
$d->type = "Hotspot";
|
||||
if ($admin) {
|
||||
$d->admin_id = ($admin['id']) ? $admin['id'] : '0';
|
||||
} else {
|
||||
$d->admin_id = '0';
|
||||
}
|
||||
$d->save();
|
||||
|
||||
// insert table transactions
|
||||
$t = ORM::for_table('tbl_transactions')->create();
|
||||
$t->invoice = $inv = "INV-" . Package::_raid();
|
||||
$t->username = $c['username'];
|
||||
$t->plan_name = $p['name_plan'];
|
||||
if ($p['validity_unit'] == 'Period') {
|
||||
// Postpaid price always zero for first time
|
||||
$t->price = 0 + $add_cost;
|
||||
} else {
|
||||
$t->price = $p['price'] + $add_cost;
|
||||
}
|
||||
$t->recharged_on = $date_only;
|
||||
$t->recharged_time = $time_only;
|
||||
$t->expiration = $date_exp;
|
||||
$t->time = $time;
|
||||
$t->method = "$gateway - $channel";
|
||||
$t->routers = $router_name;
|
||||
$t->note = $note;
|
||||
$t->type = "Hotspot";
|
||||
if ($admin) {
|
||||
$t->admin_id = ($admin['id']) ? $admin['id'] : '0';
|
||||
} else {
|
||||
$t->admin_id = '0';
|
||||
}
|
||||
$t->save();
|
||||
|
||||
if ($p['validity_unit'] == 'Period' && $p['price'] != 0) {
|
||||
// insert price to fields for invoice next month
|
||||
$fl = ORM::for_table('tbl_customers_fields')->where('field_name', 'Invoice')->where('customer_id', $c['id'])->find_one();
|
||||
if (!$fl) {
|
||||
$fl = ORM::for_table('tbl_customers_fields')->create();
|
||||
$fl->customer_id = $c['id'];
|
||||
$fl->field_name = 'Invoice';
|
||||
// Calculating Price
|
||||
$sd = new DateTime("$date_only");
|
||||
$ed = new DateTime("$date_exp");
|
||||
$td = $ed->diff($sd);
|
||||
$fd = $td->format("%a");
|
||||
$gi = ($p['price'] / (30 * $p['validity'])) * $fd;
|
||||
if ($gi > $p['price']) {
|
||||
$fl->field_value = $p['price'];
|
||||
} else {
|
||||
$fl->field_value = $gi;
|
||||
}
|
||||
$fl->save();
|
||||
} else {
|
||||
$fl->customer_id = $c['id'];
|
||||
$fl->field_value = $p['price'];
|
||||
$fl->save();
|
||||
}
|
||||
}
|
||||
|
||||
Message::sendTelegram("#u$c[username] $c[fullname] #buy #Hotspot \n" . $p['name_plan'] .
|
||||
"\nRouter: " . $router_name .
|
||||
"\nGateway: " . $gateway .
|
||||
"\nChannel: " . $channel .
|
||||
"\nPrice: " . Lang::moneyFormat($p['price'] + $add_cost) .
|
||||
"\nNote:\n" . $note);
|
||||
}
|
||||
} else {
|
||||
|
||||
if ($b) {
|
||||
if ($plan_id != $b['plan_id']) {
|
||||
$isChangePlan = true;
|
||||
}
|
||||
if ($config['extend_expiry'] === 'yes') {
|
||||
if ($b['namebp'] == $p['name_plan'] && $b['status'] == 'on') {
|
||||
// if it same internet plan, expired will extend
|
||||
if ($p['validity_unit'] == 'Months') {
|
||||
$date_exp = date("Y-m-d", strtotime($b['expiration'] . ' +' . $p['validity'] . ' months'));
|
||||
$time = $b['time'];
|
||||
} else if ($p['validity_unit'] == 'Period') {
|
||||
$date_exp = date("Y-m-$day_exp", strtotime($b['expiration'] . ' +' . $p['validity'] . ' months'));
|
||||
$time = date("23:59:00");
|
||||
} else if ($p['validity_unit'] == 'Days') {
|
||||
$date_exp = date("Y-m-d", strtotime($b['expiration'] . ' +' . $p['validity'] . ' days'));
|
||||
$time = $b['time'];
|
||||
} else if ($p['validity_unit'] == 'Hrs') {
|
||||
$datetime = explode(' ', date("Y-m-d H:i:s", strtotime($b['expiration'] . ' ' . $b['time'] . ' +' . $p['validity'] . ' hours')));
|
||||
$date_exp = $datetime[0];
|
||||
$time = $datetime[1];
|
||||
} else if ($p['validity_unit'] == 'Mins') {
|
||||
$datetime = explode(' ', date("Y-m-d H:i:s", strtotime($b['expiration'] . ' ' . $b['time'] . ' +' . $p['validity'] . ' minutes')));
|
||||
$date_exp = $datetime[0];
|
||||
$time = $datetime[1];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($isChangePlan || $b['status'] == 'off') {
|
||||
if ($p['is_radius']) {
|
||||
Radius::customerAddPlan($c, $p, "$date_exp $time");
|
||||
} else {
|
||||
$client = Mikrotik::getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']);
|
||||
Mikrotik::removePpoeUser($client, $c['username']);
|
||||
Mikrotik::removePpoeActive($client, $c['username']);
|
||||
Mikrotik::addPpoeUser($client, $p, $c);
|
||||
}
|
||||
}
|
||||
|
||||
$b->customer_id = $id_customer;
|
||||
$b->username = $c['username'];
|
||||
$b->plan_id = $plan_id;
|
||||
$b->namebp = $p['name_plan'];
|
||||
$b->recharged_on = $date_only;
|
||||
$b->recharged_time = $time_only;
|
||||
$b->expiration = $date_exp;
|
||||
$b->time = $time;
|
||||
$b->status = "on";
|
||||
$b->method = "$gateway - $channel";
|
||||
$b->routers = $router_name;
|
||||
$b->type = "PPPOE";
|
||||
if ($admin) {
|
||||
$b->admin_id = ($admin['id']) ? $admin['id'] : '0';
|
||||
} else {
|
||||
$b->admin_id = '0';
|
||||
}
|
||||
$b->save();
|
||||
|
||||
// insert table transactions
|
||||
$t = ORM::for_table('tbl_transactions')->create();
|
||||
$t->invoice = $inv = "INV-" . Package::_raid();
|
||||
$t->username = $c['username'];
|
||||
$t->plan_name = $p['name_plan'];
|
||||
if ($p['validity_unit'] == 'Period') {
|
||||
// Postpaid price from field
|
||||
$add_inv = User::getAttribute("Invoice", $id_customer);
|
||||
if (empty($add_inv) or $add_inv == 0) {
|
||||
$t->price = $p['price'] + $add_cost;
|
||||
} else {
|
||||
$t->price = $add_inv + $add_cost;
|
||||
}
|
||||
} else {
|
||||
$t->price = $p['price'] + $add_cost;
|
||||
}
|
||||
$t->recharged_on = $date_only;
|
||||
$t->recharged_time = $time_only;
|
||||
$t->expiration = $date_exp;
|
||||
$t->time = $time;
|
||||
$t->method = "$gateway - $channel";
|
||||
$t->routers = $router_name;
|
||||
$t->note = $note;
|
||||
$t->type = "PPPOE";
|
||||
if ($admin) {
|
||||
$t->admin_id = ($admin['id']) ? $admin['id'] : '0';
|
||||
} else {
|
||||
$t->admin_id = '0';
|
||||
}
|
||||
$t->save();
|
||||
|
||||
if ($p['validity_unit'] == 'Period' && $p['price'] != 0) {
|
||||
// insert price to fields for invoice next month
|
||||
$fl = ORM::for_table('tbl_customers_fields')->where('field_name', 'Invoice')->where('customer_id', $c['id'])->find_one();
|
||||
if (!$fl) {
|
||||
$fl = ORM::for_table('tbl_customers_fields')->create();
|
||||
$fl->customer_id = $c['id'];
|
||||
$fl->field_name = 'Invoice';
|
||||
$fl->field_value = $p['price'];
|
||||
$fl->save();
|
||||
} else {
|
||||
$fl->customer_id = $c['id'];
|
||||
$fl->field_value = $p['price'];
|
||||
$fl->save();
|
||||
}
|
||||
}
|
||||
|
||||
Message::sendTelegram("#u$c[username] $c[fullname] #recharge #PPPOE \n" . $p['name_plan'] .
|
||||
"\nRouter: " . $router_name .
|
||||
"\nGateway: " . $gateway .
|
||||
"\nChannel: " . $channel .
|
||||
"\nPrice: " . Lang::moneyFormat($p['price'] + $add_cost) .
|
||||
"\nNote:\n" . $note);
|
||||
} else {
|
||||
if ($p['is_radius']) {
|
||||
Radius::customerAddPlan($c, $p, "$date_exp $time");
|
||||
} else {
|
||||
$client = Mikrotik::getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']);
|
||||
Mikrotik::removePpoeUser($client, $c['username']);
|
||||
Mikrotik::removePpoeActive($client, $c['username']);
|
||||
Mikrotik::addPpoeUser($client, $p, $c);
|
||||
}
|
||||
|
||||
$d = ORM::for_table('tbl_user_recharges')->create();
|
||||
$d->customer_id = $id_customer;
|
||||
$d->username = $c['username'];
|
||||
$d->plan_id = $plan_id;
|
||||
$d->namebp = $p['name_plan'];
|
||||
$d->recharged_on = $date_only;
|
||||
$d->recharged_time = $time_only;
|
||||
$d->expiration = $date_exp;
|
||||
$d->time = $time;
|
||||
$d->status = "on";
|
||||
$d->method = "$gateway - $channel";
|
||||
$d->routers = $router_name;
|
||||
$d->type = "PPPOE";
|
||||
if ($admin) {
|
||||
$d->admin_id = ($admin['id']) ? $admin['id'] : '0';
|
||||
} else {
|
||||
$d->admin_id = '0';
|
||||
}
|
||||
$d->save();
|
||||
|
||||
// insert table transactions
|
||||
$t = ORM::for_table('tbl_transactions')->create();
|
||||
$t->invoice = $inv = "INV-" . Package::_raid();
|
||||
$t->username = $c['username'];
|
||||
$t->plan_name = $p['name_plan'];
|
||||
if ($p['validity_unit'] == 'Period') {
|
||||
// Postpaid price always zero for first time
|
||||
$note = '';
|
||||
$bills = [];
|
||||
$t->price = 0;
|
||||
} else {
|
||||
$t->price = $p['price'] + $add_cost;
|
||||
}
|
||||
$t->recharged_on = $date_only;
|
||||
$t->recharged_time = $time_only;
|
||||
$t->expiration = $date_exp;
|
||||
$t->time = $time;
|
||||
$t->method = "$gateway - $channel";
|
||||
$t->note = $note;
|
||||
$t->routers = $router_name;
|
||||
if ($admin) {
|
||||
$t->admin_id = ($admin['id']) ? $admin['id'] : '0';
|
||||
} else {
|
||||
$t->admin_id = '0';
|
||||
}
|
||||
$t->type = "PPPOE";
|
||||
$t->save();
|
||||
|
||||
if ($p['validity_unit'] == 'Period' && $p['price'] != 0) {
|
||||
// insert price to fields for invoice next month
|
||||
$fl = ORM::for_table('tbl_customers_fields')->where('field_name', 'Invoice')->where('customer_id', $c['id'])->find_one();
|
||||
if (!$fl) {
|
||||
$fl = ORM::for_table('tbl_customers_fields')->create();
|
||||
$fl->customer_id = $c['id'];
|
||||
$fl->field_name = 'Invoice';
|
||||
// Calculating Price
|
||||
$sd = new DateTime("$date_only");
|
||||
$ed = new DateTime("$date_exp");
|
||||
$td = $ed->diff($sd);
|
||||
$fd = $td->format("%a");
|
||||
$gi = ($p['price'] / (30 * $p['validity'])) * $fd;
|
||||
if ($gi > $p['price']) {
|
||||
$fl->field_value = $p['price'];
|
||||
} else {
|
||||
$fl->field_value = $gi;
|
||||
}
|
||||
$fl->save();
|
||||
} else {
|
||||
$fl->customer_id = $c['id'];
|
||||
$fl->field_value = $p['price'];
|
||||
$fl->save();
|
||||
}
|
||||
}
|
||||
|
||||
Message::sendTelegram("#u$c[username] $c[fullname] #buy #PPPOE \n" . $p['name_plan'] .
|
||||
"\nRouter: " . $router_name .
|
||||
"\nGateway: " . $gateway .
|
||||
"\nChannel: " . $channel .
|
||||
"\nPrice: " . Lang::moneyFormat($p['price'] + $add_cost) .
|
||||
"\nNote:\n" . $note);
|
||||
}
|
||||
}
|
||||
if (is_array($bills) && count($bills) > 0) {
|
||||
User::billsPaid($bills, $id_customer);
|
||||
}
|
||||
run_hook("recharge_user_finish");
|
||||
Message::sendInvoice($c, $t);
|
||||
if ($trx) {
|
||||
$trx->trx_invoice = $inv;
|
||||
}
|
||||
return $inv;
|
||||
}
|
||||
|
||||
public static function changeTo($username, $plan_id, $from_id)
|
||||
{
|
||||
$c = ORM::for_table('tbl_customers')->where('username', $username)->find_one();
|
||||
$p = ORM::for_table('tbl_plans')->where('id', $plan_id)->find_one();
|
||||
$b = ORM::for_table('tbl_user_recharges')->find_one($from_id);
|
||||
if ($p['routers'] == $b['routers'] && $b['routers'] != 'radius') {
|
||||
$mikrotik = Mikrotik::info($p['routers']);
|
||||
} else {
|
||||
$mikrotik = Mikrotik::info($b['routers']);
|
||||
}
|
||||
// delete first
|
||||
if ($p['type'] == 'Hotspot') {
|
||||
if ($b) {
|
||||
if (!$p['is_radius']) {
|
||||
$client = Mikrotik::getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']);
|
||||
Mikrotik::removeHotspotUser($client, $c['username']);
|
||||
Mikrotik::removeHotspotActiveUser($client, $c['username']);
|
||||
}
|
||||
} else {
|
||||
if (!$p['is_radius']) {
|
||||
$client = Mikrotik::getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']);
|
||||
Mikrotik::removeHotspotUser($client, $c['username']);
|
||||
Mikrotik::removeHotspotActiveUser($client, $c['username']);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if ($b) {
|
||||
if (!$p['is_radius']) {
|
||||
$client = Mikrotik::getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']);
|
||||
Mikrotik::removePpoeUser($client, $c['username']);
|
||||
Mikrotik::removePpoeActive($client, $c['username']);
|
||||
}
|
||||
} else {
|
||||
if (!$p['is_radius']) {
|
||||
$client = Mikrotik::getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']);
|
||||
Mikrotik::removePpoeUser($client, $c['username']);
|
||||
Mikrotik::removePpoeActive($client, $c['username']);
|
||||
}
|
||||
}
|
||||
}
|
||||
// call the next mikrotik
|
||||
if ($p['routers'] != $b['routers'] && $p['routers'] != 'radius') {
|
||||
$mikrotik = Mikrotik::info($p['routers']);
|
||||
}
|
||||
if ($p['type'] == 'Hotspot') {
|
||||
if ($b) {
|
||||
if ($p['is_radius']) {
|
||||
Radius::customerAddPlan($c, $p, $b['expiration'] . '' . $b['time']);
|
||||
} else {
|
||||
$client = Mikrotik::getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']);
|
||||
Mikrotik::addHotspotUser($client, $p, $c);
|
||||
}
|
||||
} else {
|
||||
if ($p['is_radius']) {
|
||||
Radius::customerAddPlan($c, $p, $b['expiration'] . '' . $b['time']);
|
||||
} else {
|
||||
$client = Mikrotik::getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']);
|
||||
Mikrotik::addHotspotUser($client, $p, $c);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if ($b) {
|
||||
if ($p['is_radius']) {
|
||||
Radius::customerAddPlan($c, $p);
|
||||
} else {
|
||||
$client = Mikrotik::getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']);
|
||||
Mikrotik::addPpoeUser($client, $p, $c);
|
||||
}
|
||||
} else {
|
||||
if ($p['is_radius']) {
|
||||
Radius::customerAddPlan($c, $p);
|
||||
} else {
|
||||
$client = Mikrotik::getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']);
|
||||
Mikrotik::addPpoeUser($client, $p, $c);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static function _raid()
|
||||
{
|
||||
return ORM::for_table('tbl_transactions')->max('id') + 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param in tbl_transactions
|
||||
* @param string $router_name router name for this package
|
||||
* @param int $plan_id plan id for this package
|
||||
* @param string $gateway payment gateway name
|
||||
* @param string $channel channel payment gateway
|
||||
* @return boolean
|
||||
*/
|
||||
public static function createInvoice($in)
|
||||
{
|
||||
global $config, $admin, $ui;
|
||||
$date = Lang::dateAndTimeFormat($in['recharged_on'], $in['recharged_time']);
|
||||
if ($admin['id'] != $in['admin_id'] && $in['admin_id'] > 0) {
|
||||
$_admin = Admin::_info($in['admin_id']);
|
||||
// if admin not deleted
|
||||
if ($_admin) $admin = $_admin;
|
||||
} else {
|
||||
$admin['fullname'] = 'Customer';
|
||||
}
|
||||
$cust = ORM::for_table('tbl_customers')->where('username', $in['username'])->findOne();
|
||||
|
||||
$note = '';
|
||||
//print
|
||||
$invoice = Lang::pad($config['CompanyName'], ' ', 2) . "\n";
|
||||
$invoice .= Lang::pad($config['address'], ' ', 2) . "\n";
|
||||
$invoice .= Lang::pad($config['phone'], ' ', 2) . "\n";
|
||||
$invoice .= Lang::pad("", '=') . "\n";
|
||||
$invoice .= Lang::pads("Invoice", $in['invoice'], ' ') . "\n";
|
||||
$invoice .= Lang::pads(Lang::T('Date'), $date, ' ') . "\n";
|
||||
$invoice .= Lang::pads(Lang::T('Sales'), $admin['fullname'], ' ') . "\n";
|
||||
$invoice .= Lang::pad("", '=') . "\n";
|
||||
$invoice .= Lang::pads(Lang::T('Type'), $in['type'], ' ') . "\n";
|
||||
$invoice .= Lang::pads(Lang::T('Plan Name'), $in['plan_name'], ' ') . "\n";
|
||||
if (!empty($in['note'])) {
|
||||
$in['note'] = str_replace("\r", "", $in['note']);
|
||||
$tmp = explode("\n", $in['note']);
|
||||
foreach ($tmp as $t) {
|
||||
if (strpos($t, " : ") === false) {
|
||||
if (!empty($t)) {
|
||||
$note .= "$t\n";
|
||||
}
|
||||
} else {
|
||||
$tmp2 = explode(" : ", $t);
|
||||
$invoice .= Lang::pads($tmp2[0], $tmp2[1], ' ') . "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
$invoice .= Lang::pads(Lang::T('Total'), Lang::moneyFormat($in['price']), ' ') . "\n";
|
||||
$method = explode("-", $in['method']);
|
||||
$invoice .= Lang::pads($method[0], $method[1], ' ') . "\n";
|
||||
if (!empty($note)) {
|
||||
$invoice .= Lang::pad("", '=') . "\n";
|
||||
$invoice .= Lang::pad($note, ' ', 2) . "\n";
|
||||
}
|
||||
$invoice .= Lang::pad("", '=') . "\n";
|
||||
if ($cust) {
|
||||
$invoice .= Lang::pads(Lang::T('Full Name'), $cust['fullname'], ' ') . "\n";
|
||||
}
|
||||
$invoice .= Lang::pads(Lang::T('Username'), $in['username'], ' ') . "\n";
|
||||
$invoice .= Lang::pads(Lang::T('Password'), '**********', ' ') . "\n";
|
||||
if ($in['type'] != 'Balance') {
|
||||
$invoice .= Lang::pads(Lang::T('Created On'), Lang::dateAndTimeFormat($in['recharged_on'], $in['recharged_time']), ' ') . "\n";
|
||||
$invoice .= Lang::pads(Lang::T('Expires On'), Lang::dateAndTimeFormat($in['expiration'], $in['time']), ' ') . "\n";
|
||||
}
|
||||
$invoice .= Lang::pad("", '=') . "\n";
|
||||
$invoice .= Lang::pad($config['note'], ' ', 2) . "\n";
|
||||
$ui->assign('invoice', $invoice);
|
||||
$config['printer_cols'] = 30;
|
||||
//whatsapp
|
||||
$invoice = Lang::pad($config['CompanyName'], ' ', 2) . "\n";
|
||||
$invoice .= Lang::pad($config['address'], ' ', 2) . "\n";
|
||||
$invoice .= Lang::pad($config['phone'], ' ', 2) . "\n";
|
||||
$invoice .= Lang::pad("", '=') . "\n";
|
||||
$invoice .= Lang::pads("Invoice", $in['invoice'], ' ') . "\n";
|
||||
$invoice .= Lang::pads(Lang::T('Date'), $date, ' ') . "\n";
|
||||
$invoice .= Lang::pads(Lang::T('Sales'), $admin['fullname'], ' ') . "\n";
|
||||
$invoice .= Lang::pad("", '=') . "\n";
|
||||
$invoice .= Lang::pads(Lang::T('Type'), $in['type'], ' ') . "\n";
|
||||
$invoice .= Lang::pads(Lang::T('Plan Name'), $in['plan_name'], ' ') . "\n";
|
||||
if (!empty($in['note'])) {
|
||||
$invoice .= Lang::pad("", '=') . "\n";
|
||||
foreach ($tmp as $t) {
|
||||
if (strpos($t, " : ") === false) {
|
||||
if (!empty($t)) {
|
||||
$invoice .= Lang::pad($t, ' ', 2) . "\n";
|
||||
}
|
||||
} else {
|
||||
$tmp2 = explode(" : ", $t);
|
||||
$invoice .= Lang::pads($tmp2[0], $tmp2[1], ' ') . "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
$invoice .= Lang::pads(Lang::T('Total'), Lang::moneyFormat($in['price']), ' ') . "\n";
|
||||
$invoice .= Lang::pads($method[0], $method[1], ' ') . "\n";
|
||||
if (!empty($note)) {
|
||||
$invoice .= Lang::pad("", '=') . "\n";
|
||||
$invoice .= Lang::pad($note, ' ', 2) . "\n";
|
||||
}
|
||||
$invoice .= Lang::pad("", '=') . "\n";
|
||||
if ($cust) {
|
||||
$invoice .= Lang::pads(Lang::T('Full Name'), $cust['fullname'], ' ') . "\n";
|
||||
}
|
||||
$invoice .= Lang::pads(Lang::T('Username'), $in['username'], ' ') . "\n";
|
||||
$invoice .= Lang::pads(Lang::T('Password'), '**********', ' ') . "\n";
|
||||
if ($in['type'] != 'Balance') {
|
||||
$invoice .= Lang::pads(Lang::T('Created On'), Lang::dateAndTimeFormat($in['recharged_on'], $in['recharged_time']), ' ') . "\n";
|
||||
$invoice .= Lang::pads(Lang::T('Expires On'), Lang::dateAndTimeFormat($in['expiration'], $in['time']), ' ') . "\n";
|
||||
}
|
||||
$invoice .= Lang::pad("", '=') . "\n";
|
||||
$invoice .= Lang::pad($config['note'], ' ', 2) . "\n";
|
||||
$ui->assign('whatsapp', urlencode("```$invoice```"));
|
||||
$ui->assign('in', $in);
|
||||
}
|
||||
public static function tax($price, $tax_rate = 1)
|
||||
{
|
||||
// Convert tax rate to decimal
|
||||
$tax_rate_decimal = $tax_rate / 100;
|
||||
$tax = $price * $tax_rate_decimal;
|
||||
return $tax;
|
||||
}
|
||||
}
|
||||
366
system/autoload/Paginator.php
Normal file
366
system/autoload/Paginator.php
Normal file
@@ -0,0 +1,366 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* PHP Mikrotik Billing (https://github.com/SiberTech/)
|
||||
* by https://t.me/ibnux
|
||||
**/
|
||||
|
||||
|
||||
class Paginator
|
||||
{
|
||||
public static function findMany($query, $search = [], $per_page = '10')
|
||||
{
|
||||
global $routes, $ui;
|
||||
$adjacents = "2";
|
||||
$page = _get('p', 1);
|
||||
$page = (empty($page) ? 1 : $page);
|
||||
$url = U . implode('/', $routes);
|
||||
if (count($search) > 0) {
|
||||
$url .= '&' . http_build_query($search);
|
||||
}
|
||||
$url .= '&p=';
|
||||
$totalReq = $query->count();
|
||||
$lastpage = ceil($totalReq / $per_page);
|
||||
$lpm1 = $lastpage - 1;
|
||||
$limit = $per_page;
|
||||
$startpoint = ($page * $limit) - $limit;
|
||||
if ($lastpage >= 1) {
|
||||
$pages = [];
|
||||
if ($lastpage < 7 + ($adjacents * 2)) {
|
||||
for ($counter = 1; $counter <= $lastpage; $counter++) {
|
||||
$pages[] = $counter;
|
||||
}
|
||||
} elseif ($lastpage > 5 + ($adjacents * 2)) {
|
||||
if ($page < 1 + ($adjacents * 2)) {
|
||||
for ($counter = 1; $counter < 4 + ($adjacents * 2); $counter++) {
|
||||
$pages[] = $counter;
|
||||
}
|
||||
$pages[] = "...";
|
||||
$pages[] = $lpm1;
|
||||
$pages[] = $lastpage;
|
||||
} elseif ($lastpage - ($adjacents * 2) > $page && $page > ($adjacents * 2)) {
|
||||
$pages[] = "1";
|
||||
$pages[] = "2";
|
||||
$pages[] = "...";
|
||||
for ($counter = $page - $adjacents; $counter <= $page + $adjacents; $counter++) {
|
||||
$pages[] = $counter;
|
||||
}
|
||||
$pages[] = "...";
|
||||
$pages[] = $lpm1;
|
||||
$pages[] = $lastpage;
|
||||
} else {
|
||||
$pages[] = "1";
|
||||
$pages[] = "2";
|
||||
$pages[] = "...";
|
||||
for ($counter = $lastpage - (2 + ($adjacents * 2)); $counter <= $lastpage; $counter++) {
|
||||
$pages[] = $counter;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$result = [
|
||||
'count' => $lastpage,
|
||||
'limit' => $per_page,
|
||||
'startpoint' => $startpoint,
|
||||
'url' => $url,
|
||||
'page' => $page,
|
||||
'pages' => $pages,
|
||||
'prev' => ($page > 0) ? ($page - 1) : "0",
|
||||
'next' => ($page >= $lastpage) ? $lastpage : $page + 1
|
||||
];
|
||||
if ($ui) {
|
||||
$ui->assign('paginator', $result);
|
||||
}
|
||||
return $query->offset($startpoint)->limit($per_page)->find_many();
|
||||
}
|
||||
}
|
||||
|
||||
public static function build($table, $colVal = [], $query = '', $per_page = '10')
|
||||
{
|
||||
global $routes;
|
||||
global $_L;
|
||||
$url = U . implode('/', $routes);
|
||||
$query = urlencode($query);
|
||||
$adjacents = "2";
|
||||
$page = (int)(empty(_get('p')) ? 1 : _get('p'));
|
||||
$pagination = "";
|
||||
foreach ($colVal as $k => $v) {
|
||||
if (!is_array($v) && strpos($v, '%') === false) {
|
||||
$table = $table->where($k, $v);
|
||||
} else {
|
||||
if (is_array($v)) {
|
||||
$table = $table->where_in($k, $v);
|
||||
} else {
|
||||
$table = $table->where_like($k, $v);
|
||||
}
|
||||
}
|
||||
}
|
||||
$totalReq = $table->count();
|
||||
$page = ($page == 0 ? 1 : $page);
|
||||
$next = $page + 1;
|
||||
$lastpage = ceil($totalReq / $per_page);
|
||||
$lpm1 = $lastpage - 1;
|
||||
$limit = $per_page;
|
||||
$startpoint = ($page * $limit) - $limit;
|
||||
if ($lastpage >= 1) {
|
||||
$pagination .= '<ul class="pagination">';
|
||||
if ($lastpage < 7 + ($adjacents * 2)) {
|
||||
for ($counter = 1; $counter <= $lastpage; $counter++) {
|
||||
if ($counter == $page)
|
||||
$pagination .= "<li class='page-item active'><a class='page-link' href='javascript:void(0);'>$counter</a></li>";
|
||||
else
|
||||
$pagination .= "<li class='page-item'><a class='page-link' href='{$url}&p=$counter&q=$query'>$counter</a></li>";
|
||||
}
|
||||
} elseif ($lastpage > 5 + ($adjacents * 2)) {
|
||||
if ($page < 1 + ($adjacents * 2)) {
|
||||
for ($counter = 1; $counter < 4 + ($adjacents * 2); $counter++) {
|
||||
if ($counter == $page)
|
||||
$pagination .= "<li class='page-item active'><a class='page-link' href='javascript:void(0);'>$counter</a></li>";
|
||||
else
|
||||
$pagination .= "<li class='page-item'><a class='page-link' href='{$url}&p=$counter&q=$query'>$counter</a></li>";
|
||||
}
|
||||
$pagination .= "<li class='page-item disabled'><a class='page-link' href='#'>...</a></li>";
|
||||
$pagination .= "<li class='page-item'><a class='page-link' href='{$url}&p=$lpm1&q=$query'>$lpm1</a></li>";
|
||||
$pagination .= "<li class='page-item'><a class='page-link' href='{$url}&p=$lastpage&q=$query'>$lastpage</a></li>";
|
||||
} elseif ($lastpage - ($adjacents * 2) > $page && $page > ($adjacents * 2)) {
|
||||
$pagination .= "<li class='page-item'><a class='page-link' href='{$url}&p=1&q=$query'>1</a></li>";
|
||||
$pagination .= "<li class='page-item'><a class='page-link' href='{$url}&p=2&q=$query'>2</a></li>";
|
||||
$pagination .= "<li class='page-item disabled'><a class='page-link' href='#'>...</a></li>";
|
||||
for ($counter = $page - $adjacents; $counter <= $page + $adjacents; $counter++) {
|
||||
if ($counter == $page)
|
||||
$pagination .= "<li class='page-item active'><a class='page-link' href='javascript:void(0);'>$counter</a></li>";
|
||||
else
|
||||
$pagination .= "<li class='page-item'><a class='page-link' href='{$url}&p=$counter&q=$query'>$counter</a></li>";
|
||||
}
|
||||
$pagination .= "<li class='page-item disabled'><a class='page-link' href='#'>...</a></li>";
|
||||
$pagination .= "<li class='page-item'><a class='page-link' href='{$url}&p=$lpm1&q=$query'>$lpm1</a></li>";
|
||||
$pagination .= "<li class='page-item'><a class='page-link' href='{$url}&p=$lastpage&q=$query'>$lastpage</a></li>";
|
||||
} else {
|
||||
$pagination .= "<li class='page-item'><a class='page-link' href='{$url}&p=1&q=$query'>1</a></li>";
|
||||
$pagination .= "<li class='page-item'><a class='page-link' href='{$url}&p=2&q=$query'>2</a></li>";
|
||||
$pagination .= "<li class='page-item'><a class='page-link' href='#'>...</a></li>";
|
||||
for ($counter = $lastpage - (2 + ($adjacents * 2)); $counter <= $lastpage; $counter++) {
|
||||
if ($counter == $page)
|
||||
$pagination .= "<li class='page-item'><a class='page-link disabled'>$counter</a></li>";
|
||||
else
|
||||
$pagination .= "<li class='page-item'><a class='page-link' href='{$url}&p=$counter&q=$query'>$counter</a></li>";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($page < $counter - 1) {
|
||||
$pagination .= "<li class='page-item'><a class='page-link' href='{$url}&p=$next&q=$query'>" . Lang::T('Next') . "</a></li>";
|
||||
$pagination .= "<li class='page-item'><a class='page-link' href='{$url}&p=$lastpage&q=$query'>" . Lang::T('Last') . "</a></li>";
|
||||
} else {
|
||||
$pagination .= "<li class='page-item disabled'><a class='page-link disabled'>" . Lang::T('Next') . "</a></li>";
|
||||
$pagination .= "<li class='page-item disabled'><a class='page-link disabled'>" . Lang::T('Last') . "</a></li>";
|
||||
}
|
||||
$pagination .= "</ul>";
|
||||
$pagination = '<nav>' . $pagination . '</nav>';
|
||||
return array("startpoint" => $startpoint, "limit" => $limit, "found" => $totalReq, "page" => $page, "lastpage" => $lastpage, "contents" => $pagination);
|
||||
}
|
||||
}
|
||||
|
||||
public static function bootstrap($table, $w1 = '', $c1 = '', $w2 = '', $c2 = '', $w3 = '', $c3 = '', $w4 = '', $c4 = '', $per_page = '10')
|
||||
{
|
||||
global $routes;
|
||||
global $_L;
|
||||
$url = U . $routes['0'] . '/' . $routes['1'] . '/';
|
||||
$adjacents = "2";
|
||||
$page = (int)(!isset($routes['2']) ? 1 : $routes['2']);
|
||||
$pagination = "";
|
||||
|
||||
if (is_object($table)) {
|
||||
if ($w1 != '') {
|
||||
$totalReq = $table->where($w1, $c1)->count();
|
||||
} elseif ($w2 != '') {
|
||||
$totalReq = $table->where($w1, $c1)->where($w2, $c2)->count();
|
||||
} elseif ($w3 != '') {
|
||||
$totalReq = $table->where($w1, $c1)->where($w2, $c2)->where($w3, $c3)->count();
|
||||
} elseif ($w4 != '') {
|
||||
$totalReq = $table->where($w1, $c1)->where($w2, $c2)->where($w3, $c3)->where($w4, $c4)->count();
|
||||
} else {
|
||||
$totalReq = $table->count();
|
||||
}
|
||||
} else {
|
||||
if ($w1 != '') {
|
||||
$totalReq = ORM::for_table($table)->where($w1, $c1)->count();
|
||||
} elseif ($w2 != '') {
|
||||
$totalReq = ORM::for_table($table)->where($w1, $c1)->where($w2, $c2)->count();
|
||||
} elseif ($w3 != '') {
|
||||
$totalReq = ORM::for_table($table)->where($w1, $c1)->where($w2, $c2)->where($w3, $c3)->count();
|
||||
} elseif ($w4 != '') {
|
||||
$totalReq = ORM::for_table($table)->where($w1, $c1)->where($w2, $c2)->where($w3, $c3)->where($w4, $c4)->count();
|
||||
} else {
|
||||
$totalReq = ORM::for_table($table)->count();
|
||||
}
|
||||
}
|
||||
|
||||
$i = 0;
|
||||
$page = ($page == 0 ? 1 : $page);
|
||||
$start = ($page - 1) * $per_page;
|
||||
|
||||
$prev = $page - 1;
|
||||
$next = $page + 1;
|
||||
$lastpage = ceil($totalReq / $per_page);
|
||||
|
||||
$lpm1 = $lastpage - 1;
|
||||
$limit = $per_page;
|
||||
$startpoint = ($page * $limit) - $limit;
|
||||
|
||||
if ($lastpage >= 1) {
|
||||
$pagination .= '<ul class="pagination">';
|
||||
if ($lastpage < 7 + ($adjacents * 2)) {
|
||||
for ($counter = 1; $counter <= $lastpage; $counter++) {
|
||||
if ($counter == $page)
|
||||
$pagination .= "<li class='page-item active'><a class='page-link' href='javascript:void(0);'>$counter</a></li>";
|
||||
else
|
||||
$pagination .= "<li class='page-item'><a class='page-link' href='{$url}$counter'>$counter</a></li>";
|
||||
}
|
||||
} elseif ($lastpage > 5 + ($adjacents * 2)) {
|
||||
if ($page < 1 + ($adjacents * 2)) {
|
||||
for ($counter = 1; $counter < 4 + ($adjacents * 2); $counter++) {
|
||||
if ($counter == $page)
|
||||
$pagination .= "<li class='page-item active'><a class='page-link' href='javascript:void(0);'>$counter</a></li>";
|
||||
else
|
||||
$pagination .= "<li class='page-item'><a class='page-link' href='{$url}$counter'>$counter</a></li>";
|
||||
}
|
||||
$pagination .= "<li class='page-item disabled'><a class='page-link' href='#'>...</a></li>";
|
||||
$pagination .= "<li class='page-item'><a class='page-link' href='{$url}$lpm1'>$lpm1</a></li>";
|
||||
$pagination .= "<li class='page-item'><a class='page-link' href='{$url}$lastpage'>$lastpage</a></li>";
|
||||
} elseif ($lastpage - ($adjacents * 2) > $page && $page > ($adjacents * 2)) {
|
||||
$pagination .= "<li class='page-item'><a class='page-link' href='{$url}1'>1</a></li>";
|
||||
$pagination .= "<li class='page-item'><a class='page-link' href='{$url}2'>2</a></li>";
|
||||
$pagination .= "<li class='page-item disabled'><a class='page-link' href='#'>...</a></li>";
|
||||
for ($counter = $page - $adjacents; $counter <= $page + $adjacents; $counter++) {
|
||||
if ($counter == $page)
|
||||
$pagination .= "<li class='page-item active'><a class='page-link' href='javascript:void(0);'>$counter</a></li>";
|
||||
else
|
||||
$pagination .= "<li class='page-item'><a class='page-link' href='{$url}$counter'>$counter</a></li>";
|
||||
}
|
||||
$pagination .= "<li class='page-item disabled'><a class='page-link' href='#'>...</a></li>";
|
||||
$pagination .= "<li class='page-item'><a class='page-link' href='{$url}$lpm1'>$lpm1</a></li>";
|
||||
$pagination .= "<li class='page-item'><a class='page-link' href='{$url}$lastpage'>$lastpage</a></li>";
|
||||
} else {
|
||||
$pagination .= "<li class='page-item'><a class='page-link' href='{$url}1'>1</a></li>";
|
||||
$pagination .= "<li class='page-item'><a class='page-link' href='{$url}2'>2</a></li>";
|
||||
$pagination .= "<li class='page-item'><a class='page-link' href='#'>...</a></li>";
|
||||
for ($counter = $lastpage - (2 + ($adjacents * 2)); $counter <= $lastpage; $counter++) {
|
||||
if ($counter == $page)
|
||||
$pagination .= "<li class='page-item'><a class='page-link disabled'>$counter</a></li>";
|
||||
else
|
||||
$pagination .= "<li class='page-item'><a class='page-link' href='{$url}$counter'>$counter</a></li>";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($page < $counter - 1) {
|
||||
$pagination .= "<li class='page-item'><a class='page-link' href='{$url}$next'>" . Lang::T('Next') . "</a></li>";
|
||||
$pagination .= "<li class='page-item'><a class='page-link' href='{$url}$lastpage'>" . Lang::T('Last') . "</a></li>";
|
||||
} else {
|
||||
$pagination .= "<li class='page-item disabled'><a class='page-link disabled'>" . Lang::T('Next') . "</a></li>";
|
||||
$pagination .= "<li class='page-item disabled'><a class='page-link disabled'>" . Lang::T('Last') . "</a></li>";
|
||||
}
|
||||
$pagination .= "</ul>";
|
||||
$pagination = '<nav>' . $pagination . '</nav>';
|
||||
|
||||
$gen = array("startpoint" => $startpoint, "limit" => $limit, "found" => $totalReq, "page" => $page, "lastpage" => $lastpage, "contents" => $pagination);
|
||||
return $gen;
|
||||
}
|
||||
}
|
||||
|
||||
public static function bootstrapRaw($table, $w1 = '', $c1 = [], $per_page = '10')
|
||||
{
|
||||
global $routes;
|
||||
global $_L;
|
||||
$url = U . $routes['0'] . '/' . $routes['1'] . '/';
|
||||
$adjacents = "2";
|
||||
$page = (int)(!isset($routes['2']) ? 1 : $routes['2']);
|
||||
$pagination = "";
|
||||
if (is_object($table)) {
|
||||
if ($w1 != '') {
|
||||
$totalReq = $table->where_raw($w1, $c1)->count();
|
||||
} else {
|
||||
$totalReq = $table->count();
|
||||
}
|
||||
} else {
|
||||
if ($w1 != '') {
|
||||
$totalReq = ORM::for_table($table)->where_raw($w1, $c1)->count();
|
||||
} else {
|
||||
$totalReq = ORM::for_table($table)->count();
|
||||
}
|
||||
}
|
||||
|
||||
$i = 0;
|
||||
$page = ($page == 0 ? 1 : $page);
|
||||
$start = ($page - 1) * $per_page;
|
||||
|
||||
$prev = $page - 1;
|
||||
$next = $page + 1;
|
||||
$lastpage = ceil($totalReq / $per_page);
|
||||
|
||||
$lpm1 = $lastpage - 1;
|
||||
$limit = $per_page;
|
||||
$startpoint = ($page * $limit) - $limit;
|
||||
|
||||
if ($lastpage >= 1) {
|
||||
$pagination .= '<ul class="pagination">';
|
||||
if ($lastpage < 7 + ($adjacents * 2)) {
|
||||
for ($counter = 1; $counter <= $lastpage; $counter++) {
|
||||
if ($counter == $page)
|
||||
$pagination .= "<li class='page-item active'><a class='page-link' href='javascript:void(0);'>$counter</a></li>";
|
||||
else
|
||||
$pagination .= "<li class='page-item'><a class='page-link' href='{$url}$counter'>$counter</a></li>";
|
||||
}
|
||||
} elseif ($lastpage > 5 + ($adjacents * 2)) {
|
||||
if ($page < 1 + ($adjacents * 2)) {
|
||||
for ($counter = 1; $counter < 4 + ($adjacents * 2); $counter++) {
|
||||
if ($counter == $page)
|
||||
$pagination .= "<li class='page-item active'><a class='page-link' href='javascript:void(0);'>$counter</a></li>";
|
||||
else
|
||||
$pagination .= "<li class='page-item'><a class='page-link' href='{$url}$counter'>$counter</a></li>";
|
||||
}
|
||||
$pagination .= "<li class='page-item disabled'><a class='page-link' href='#'>...</a></li>";
|
||||
$pagination .= "<li class='page-item'><a class='page-link' href='{$url}$lpm1'>$lpm1</a></li>";
|
||||
$pagination .= "<li class='page-item'><a class='page-link' href='{$url}$lastpage'>$lastpage</a></li>";
|
||||
} elseif ($lastpage - ($adjacents * 2) > $page && $page > ($adjacents * 2)) {
|
||||
$pagination .= "<li class='page-item'><a class='page-link' href='{$url}1'>1</a></li>";
|
||||
$pagination .= "<li class='page-item'><a class='page-link' href='{$url}2'>2</a></li>";
|
||||
$pagination .= "<li class='page-item disabled'><a class='page-link' href='#'>...</a></li>";
|
||||
for ($counter = $page - $adjacents; $counter <= $page + $adjacents; $counter++) {
|
||||
if ($counter == $page)
|
||||
$pagination .= "<li class='page-item active'><a class='page-link' href='javascript:void(0);'>$counter</a></li>";
|
||||
else
|
||||
$pagination .= "<li class='page-item'><a class='page-link' href='{$url}$counter'>$counter</a></li>";
|
||||
}
|
||||
$pagination .= "<li class='page-item disabled'><a class='page-link' href='#'>...</a></li>";
|
||||
$pagination .= "<li class='page-item'><a class='page-link' href='{$url}$lpm1'>$lpm1</a></li>";
|
||||
$pagination .= "<li class='page-item'><a class='page-link' href='{$url}$lastpage'>$lastpage</a></li>";
|
||||
} else {
|
||||
$pagination .= "<li class='page-item'><a class='page-link' href='{$url}1'>1</a></li>";
|
||||
$pagination .= "<li class='page-item'><a class='page-link' href='{$url}2'>2</a></li>";
|
||||
$pagination .= "<li class='page-item'><a class='page-link' href='#'>...</a></li>";
|
||||
for ($counter = $lastpage - (2 + ($adjacents * 2)); $counter <= $lastpage; $counter++) {
|
||||
if ($counter == $page)
|
||||
$pagination .= "<li class='page-item active'><a class='page-item disabled'>$counter</a></li>";
|
||||
else
|
||||
$pagination .= "<li class='page-item'><a class='page-link' href='{$url}$counter'>$counter</a></li>";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($page < $counter - 1) {
|
||||
$pagination .= "<li class='page-item'><a class='page-link' href='{$url}$next'>" . Lang::T('Next') . "</a></li>";
|
||||
$pagination .= "<li class='page-item'><a class='page-link' href='{$url}$lastpage'>" . Lang::T('Last') . "</a></li>";
|
||||
} else {
|
||||
$pagination .= "<li class='page-item disabled'><a class='page-item disabled'>" . Lang::T('Next') . "</a></li>";
|
||||
$pagination .= "<li class='page-item disabled'><a class='page-item disabled'>" . Lang::T('Last') . "</a></li>";
|
||||
}
|
||||
$pagination .= "</ul>";
|
||||
$pagination = '<nav>' . $pagination . '</nav>';
|
||||
|
||||
$gen = array("startpoint" => $startpoint, "limit" => $limit, "found" => $totalReq, "page" => $page, "lastpage" => $lastpage, "contents" => $pagination);
|
||||
return $gen;
|
||||
}
|
||||
}
|
||||
}
|
||||
1994
system/autoload/Parsedown.php
Normal file
1994
system/autoload/Parsedown.php
Normal file
File diff suppressed because it is too large
Load Diff
35
system/autoload/Password.php
Normal file
35
system/autoload/Password.php
Normal file
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* PHP Mikrotik Billing (https://github.com/hotspotbilling/phpnuxbill/)
|
||||
* by https://t.me/ibnux
|
||||
**/
|
||||
|
||||
class Password
|
||||
{
|
||||
|
||||
public static function _crypt($password)
|
||||
{
|
||||
return sha1($password);
|
||||
}
|
||||
|
||||
public static function _verify($user_input, $hashed_password)
|
||||
{
|
||||
if (sha1($user_input) == $hashed_password) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
public static function _uverify($user_input, $hashed_password)
|
||||
{
|
||||
if ($user_input == $hashed_password) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
public static function _gen()
|
||||
{
|
||||
$pass = substr(str_shuffle(str_repeat('ABCDEFGHIJKLMNPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz@#!123456789', 8)), 0, 8);
|
||||
return $pass;
|
||||
}
|
||||
}
|
||||
349
system/autoload/Radius.php
Normal file
349
system/autoload/Radius.php
Normal file
@@ -0,0 +1,349 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* PHP Mikrotik Billing (https://github.com/hotspotbilling/phpnuxbill/)
|
||||
* by https://t.me/ibnux
|
||||
**/
|
||||
|
||||
/**
|
||||
* Radius Class
|
||||
* based https://gist.github.com/nasirhafeez/6669b24aab0bda545f60f9da5ed14f25
|
||||
*/
|
||||
class Radius
|
||||
{
|
||||
|
||||
public static function getClient()
|
||||
{
|
||||
global $config;
|
||||
if (empty($config['radius_client'])) {
|
||||
if (function_exists("shell_exec")) {
|
||||
shell_exec('which radclient');
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
} else {
|
||||
$config['radius_client'];
|
||||
}
|
||||
}
|
||||
|
||||
public static function getTableNas()
|
||||
{
|
||||
return ORM::for_table('nas', 'radius');
|
||||
}
|
||||
public static function getTableAcct()
|
||||
{
|
||||
return ORM::for_table('radacct', 'radius');
|
||||
}
|
||||
public static function getTableCustomer()
|
||||
{
|
||||
return ORM::for_table('radcheck', 'radius');
|
||||
}
|
||||
|
||||
public static function getTableCustomerAttr()
|
||||
{
|
||||
return ORM::for_table('radreply', 'radius');
|
||||
}
|
||||
|
||||
public static function getTablePackage()
|
||||
{
|
||||
return ORM::for_table('radgroupreply', 'radius');
|
||||
}
|
||||
|
||||
public static function getTableUserPackage()
|
||||
{
|
||||
return ORM::for_table('radusergroup', 'radius');
|
||||
}
|
||||
|
||||
public static function nasAdd($name, $ip, $ports, $secret, $routers = "", $description = "", $type = 'other', $server = null, $community = null)
|
||||
{
|
||||
$n = Radius::getTableNas()->create();
|
||||
$n->nasname = $ip;
|
||||
$n->shortname = $name;
|
||||
$n->type = $type;
|
||||
$n->ports = $ports;
|
||||
$n->secret = $secret;
|
||||
$n->description = $description;
|
||||
$n->server = $server;
|
||||
$n->community = $community;
|
||||
$n->routers = $routers;
|
||||
$n->save();
|
||||
return $n->id();
|
||||
}
|
||||
|
||||
public static function nasUpdate($id, $name, $ip, $ports, $secret, $routers = "", $description = "", $type = 'other', $server = null, $community = null)
|
||||
{
|
||||
$n = Radius::getTableNas()->find_one($id);
|
||||
if (empty($n)) {
|
||||
return false;
|
||||
}
|
||||
$n->nasname = $ip;
|
||||
$n->shortname = $name;
|
||||
$n->type = $type;
|
||||
$n->ports = $ports;
|
||||
$n->secret = $secret;
|
||||
$n->description = $description;
|
||||
$n->server = $server;
|
||||
$n->community = $community;
|
||||
$n->routers = $routers;
|
||||
return $n->save();
|
||||
}
|
||||
|
||||
public static function planUpSert($plan_id, $rate, $pool = null)
|
||||
{
|
||||
$rates = explode('/', $rate);
|
||||
##burst fixed
|
||||
if (strpos($rate, ' ')) {
|
||||
$ratos = $rates[0] . '/' . $rates[1] . ' ' . $rates[2] . '/' . $rates[3] . '/' . $rates[4] . '/' . $rates[5] . '/' . $rates[6];
|
||||
} else {
|
||||
$ratos = $rates[0] . '/' . $rates[1];
|
||||
}
|
||||
|
||||
Radius::upsertPackage($plan_id, 'Ascend-Data-Rate', $rates[1], ':=');
|
||||
Radius::upsertPackage($plan_id, 'Ascend-Xmit-Rate', $rates[0], ':=');
|
||||
Radius::upsertPackage($plan_id, 'Mikrotik-Rate-Limit', $ratos, ':=');
|
||||
// if ($pool != null) {
|
||||
// Radius::upsertPackage($plan_id, 'Framed-Pool', $pool, ':=');
|
||||
// }
|
||||
}
|
||||
|
||||
public static function planDelete($plan_id)
|
||||
{
|
||||
// Delete Plan
|
||||
Radius::getTablePackage()->where_equal('plan_id', "plan_" . $plan_id)->delete_many();
|
||||
// Reset User Plan
|
||||
$c = Radius::getTableUserPackage()->where_equal('groupname', "plan_" . $plan_id)->findMany();
|
||||
if ($c) {
|
||||
foreach ($c as $u) {
|
||||
$u->groupname = '';
|
||||
$u->save();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static function customerChangeUsername($from, $to)
|
||||
{
|
||||
$c = Radius::getTableCustomer()->where_equal('username', $from)->findMany();
|
||||
if ($c) {
|
||||
foreach ($c as $u) {
|
||||
$u->username = $to;
|
||||
$u->save();
|
||||
}
|
||||
}
|
||||
$c = Radius::getTableUserPackage()->where_equal('username', $from)->findMany();
|
||||
if ($c) {
|
||||
foreach ($c as $u) {
|
||||
$u->username = $to;
|
||||
$u->save();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static function customerDeactivate($username, $radiusDisconnect = true)
|
||||
{ {
|
||||
global $radius_pass;
|
||||
$r = Radius::getTableCustomer()->where_equal('username', $username)->whereEqual('attribute', 'Cleartext-Password')->findOne();
|
||||
if ($r) {
|
||||
// no need to delete, because it will make ID got higher
|
||||
// we just change the password
|
||||
$r->value = md5(time() . $username . $radius_pass);
|
||||
$r->save();
|
||||
if ($radiusDisconnect)
|
||||
return Radius::disconnectCustomer($username);
|
||||
}
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
public static function customerDelete($username)
|
||||
{
|
||||
Radius::getTableCustomer()->where_equal('username', $username)->delete_many();
|
||||
Radius::getTableUserPackage()->where_equal('username', $username)->delete_many();
|
||||
}
|
||||
|
||||
/**
|
||||
* When add a plan to Customer, use this
|
||||
*/
|
||||
public static function customerAddPlan($customer, $plan, $expired = null)
|
||||
{
|
||||
global $config;
|
||||
if (Radius::customerUpsert($customer, $plan)) {
|
||||
$p = Radius::getTableUserPackage()->where_equal('username', $customer['username'])->findOne();
|
||||
if ($p) {
|
||||
// if exists
|
||||
Radius::delAtribute(Radius::getTableCustomer(), 'Max-All-Session', 'username', $customer['username']);
|
||||
Radius::delAtribute(Radius::getTableCustomer(), 'Max-Volume', 'username', $customer['username']);
|
||||
$p->groupname = "plan_" . $plan['id'];
|
||||
$p->save();
|
||||
} else {
|
||||
$p = Radius::getTableUserPackage()->create();
|
||||
$p->username = $customer['username'];
|
||||
$p->groupname = "plan_" . $plan['id'];
|
||||
$p->priority = 1;
|
||||
$p->save();
|
||||
}
|
||||
if ($plan['type'] == 'Hotspot' && $plan['typebp'] == "Limited") {
|
||||
if ($plan['limit_type'] == "Time_Limit") {
|
||||
if ($plan['time_unit'] == 'Hrs')
|
||||
$timelimit = $plan['time_limit'] * 60 * 60;
|
||||
else
|
||||
$timelimit = $plan['time_limit'] * 60;
|
||||
Radius::upsertCustomer($customer['username'], 'Max-All-Session', $timelimit);
|
||||
//Radius::upsertCustomer($customer['username'], 'Expire-After', $timelimit);
|
||||
} else if ($plan['limit_type'] == "Data_Limit") {
|
||||
if ($plan['data_unit'] == 'GB')
|
||||
$datalimit = $plan['data_limit'] . "000000000";
|
||||
else
|
||||
$datalimit = $plan['data_limit'] . "000000";
|
||||
Radius::upsertCustomer($customer['username'], 'Max-Volume', $datalimit);
|
||||
// Mikrotik Spesific
|
||||
//Radius::upsertCustomer($customer['username'], 'Max-Data', $datalimit);
|
||||
//Radius::upsertCustomer($customer['username'], 'Mikrotik-Total-Limit', $datalimit);
|
||||
} else if ($plan['limit_type'] == "Both_Limit") {
|
||||
if ($plan['time_unit'] == 'Hrs')
|
||||
$timelimit = $plan['time_limit'] * 60 * 60;
|
||||
else
|
||||
$timelimit = $plan['time_limit'] * 60;
|
||||
if ($plan['data_unit'] == 'GB')
|
||||
$datalimit = $plan['data_limit'] . "000000000";
|
||||
else
|
||||
$datalimit = $plan['data_limit'] . "000000";
|
||||
Radius::upsertCustomer($customer['username'], 'Max-Volume', $datalimit);
|
||||
Radius::upsertCustomer($customer['username'], 'Max-All-Session', $timelimit);
|
||||
// Mikrotik Spesific
|
||||
//Radius::upsertCustomer($customer['username'], 'Max-Data', $datalimit);
|
||||
//Radius::upsertCustomer($customer['username'], 'Mikrotik-Total-Limit', $datalimit);
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
} else {
|
||||
Radius::delAtribute(Radius::getTableCustomer(), 'Max-Volume', 'username', $customer['username']);
|
||||
Radius::delAtribute(Radius::getTableCustomer(), 'Max-All-Session', 'username', $customer['username']);
|
||||
//Radius::delAtribute(Radius::getTableCustomer(), 'Max-Data', 'username', $customer['username']);
|
||||
}
|
||||
|
||||
Radius::disconnectCustomer($customer['username']);
|
||||
Radius::getTableAcct()->where_equal('username', $customer['username'])->delete_many();
|
||||
|
||||
|
||||
// expired user
|
||||
if ($expired != null) {
|
||||
//Radius::upsertCustomer($customer['username'], 'access-period', strtotime($expired) - time());
|
||||
Radius::upsertCustomer($customer['username'], 'Max-All-Session', strtotime($expired) - time());
|
||||
//Radius::upsertCustomer($customer['username'], 'expiration', date('d M Y H:i:s', strtotime($expired)));
|
||||
// Mikrotik Spesific
|
||||
Radius::upsertCustomer(
|
||||
$customer['username'],
|
||||
'WISPr-Session-Terminate-Time',
|
||||
date('Y-m-d', strtotime($expired)) . 'T' . date('H:i:s', strtotime($expired)) . Timezone::getTimeOffset($config['timezone'])
|
||||
);
|
||||
} else {
|
||||
Radius::delAtribute(Radius::getTableCustomer(), 'Max-All-Session', 'username', $customer['username']);
|
||||
//Radius::delAtribute(Radius::getTableCustomer(), 'access-period', 'username', $customer['username']);
|
||||
//Radius::delAtribute(Radius::getTableCustomer(), 'expiration', 'username', $customer['username']);
|
||||
}
|
||||
|
||||
if ($plan['type'] == 'PPPOE') {
|
||||
Radius::upsertCustomerAttr($customer['username'], 'Framed-Pool', $plan['pool'], ':=');
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static function customerUpsert($customer, $plan)
|
||||
{
|
||||
if ($plan['type'] == 'PPPOE') {
|
||||
Radius::upsertCustomer($customer['username'], 'Cleartext-Password', (empty($customer['pppoe_password'])) ? $customer['password'] : $customer['pppoe_password']);
|
||||
} else {
|
||||
Radius::upsertCustomer($customer['username'], 'Cleartext-Password', $customer['password']);
|
||||
}
|
||||
Radius::upsertCustomer($customer['username'], 'Simultaneous-Use', ($plan['type'] == 'PPPOE') ? 1 : $plan['shared_users']);
|
||||
// Mikrotik Spesific
|
||||
Radius::upsertCustomer($customer['username'], 'Port-Limit', ($plan['type'] == 'PPPOE') ? 1 : $plan['shared_users']);
|
||||
Radius::upsertCustomer($customer['username'], 'Mikrotik-Wireless-Comment', $customer['fullname']);
|
||||
return true;
|
||||
}
|
||||
|
||||
private static function delAtribute($tabel, $attribute, $key, $value)
|
||||
{
|
||||
$r = $tabel->where_equal($key, $value)->whereEqual('attribute', $attribute)->findOne();
|
||||
if ($r) $r->delete();
|
||||
}
|
||||
|
||||
/**
|
||||
* To insert or update existing plan
|
||||
*/
|
||||
private static function upsertPackage($plan_id, $attr, $value, $op = ':=')
|
||||
{
|
||||
$r = Radius::getTablePackage()->where_equal('plan_id', $plan_id)->whereEqual('attribute', $attr)->find_one();
|
||||
if (!$r) {
|
||||
$r = Radius::getTablePackage()->create();
|
||||
$r->groupname = "plan_" . $plan_id;
|
||||
$r->plan_id = $plan_id;
|
||||
}
|
||||
$r->attribute = $attr;
|
||||
$r->op = $op;
|
||||
$r->value = $value;
|
||||
return $r->save();
|
||||
}
|
||||
|
||||
/**
|
||||
* To insert or update existing customer
|
||||
*/
|
||||
public static function upsertCustomer($username, $attr, $value, $op = ':=')
|
||||
{
|
||||
$r = Radius::getTableCustomer()->where_equal('username', $username)->whereEqual('attribute', $attr)->find_one();
|
||||
if (!$r) {
|
||||
$r = Radius::getTableCustomer()->create();
|
||||
$r->username = $username;
|
||||
}
|
||||
$r->attribute = $attr;
|
||||
$r->op = $op;
|
||||
$r->value = $value;
|
||||
return $r->save();
|
||||
}
|
||||
/**
|
||||
* To insert or update existing customer Attribute
|
||||
*/
|
||||
public static function upsertCustomerAttr($username, $attr, $value, $op = ':=')
|
||||
{
|
||||
$r = Radius::getTableCustomerAttr()->where_equal('username', $username)->whereEqual('attribute', $attr)->find_one();
|
||||
if (!$r) {
|
||||
$r = Radius::getTableCustomerAttr()->create();
|
||||
$r->username = $username;
|
||||
}
|
||||
$r->attribute = $attr;
|
||||
$r->op = $op;
|
||||
$r->value = $value;
|
||||
return $r->save();
|
||||
}
|
||||
|
||||
public static function disconnectCustomer($username)
|
||||
{
|
||||
global $_app_stage;
|
||||
if ($_app_stage == 'demo') {
|
||||
return null;
|
||||
}
|
||||
/**
|
||||
* Fix loop to all Nas but still detecting Hotspot Multylogin from other Nas
|
||||
*/
|
||||
$act = ORM::for_table('radacct')->where_raw("acctstoptime IS NULL")->where('username', $username)->find_one();
|
||||
$nas = Radius::getTableNas()->where('nasname', $act['nasipaddress'])->find_many();
|
||||
$count = count($nas) * 15;
|
||||
set_time_limit($count);
|
||||
$result = [];
|
||||
foreach ($nas as $n) {
|
||||
$port = 3799;
|
||||
if (!empty($n['ports'])) {
|
||||
$port = $n['ports'];
|
||||
}
|
||||
$result[] = $n['nasname'] . ': ' . @shell_exec("echo 'User-Name = $username,Framed-IP-Address = " . $act['framedipaddress'] . "' | radclient -x " . trim($n['nasname']) . ":$port disconnect '" . $n['secret'] . "'");
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
64
system/autoload/Text.php
Normal file
64
system/autoload/Text.php
Normal file
@@ -0,0 +1,64 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* PHP Mikrotik Billing (https://github.com/hotspotbilling/phpnuxbill/)
|
||||
* by https://t.me/ibnux
|
||||
*
|
||||
* This file is for Text Transformation
|
||||
**/
|
||||
|
||||
class Text
|
||||
{
|
||||
|
||||
public static function toHex($string)
|
||||
{
|
||||
return "\x" . implode("\x", str_split(array_shift(unpack('H*', $string)), 2));
|
||||
}
|
||||
|
||||
public static function alphanumeric($str, $tambahan = "")
|
||||
{
|
||||
return preg_replace("/[^a-zA-Z0-9" . $tambahan . "]+/", "", $str);
|
||||
}
|
||||
|
||||
public static function numeric($str)
|
||||
{
|
||||
return preg_replace("/[^0-9]+/", "", $str);
|
||||
}
|
||||
|
||||
public static function ucWords($text)
|
||||
{
|
||||
return ucwords(str_replace('_', ' ', $text));
|
||||
}
|
||||
|
||||
public static function randomUpLowCase($text)
|
||||
{
|
||||
$jml = strlen($text);
|
||||
$result = '';
|
||||
for ($i = 0; $i < $jml; $i++) {
|
||||
if (rand(0, 99) % 2) {
|
||||
$result .= strtolower(substr($text, $i, 1));
|
||||
} else {
|
||||
$result .= substr($text, $i, 1);
|
||||
}
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
public static function maskText($text){
|
||||
$len = strlen($text);
|
||||
if($len < 3){
|
||||
return "***";
|
||||
}else if($len<5){
|
||||
return substr($text,0,1)."***".substr($text,-1,1);
|
||||
}else if($len<8){
|
||||
return substr($text,0,2)."***".substr($text,-2,2);
|
||||
}else{
|
||||
return substr($text,0,4)."******".substr($text,-3,3);
|
||||
}
|
||||
}
|
||||
|
||||
public static function sanitize($str)
|
||||
{
|
||||
return preg_replace("/[^A-Za-z0-9]/", '_', $str);;
|
||||
}
|
||||
}
|
||||
50
system/autoload/Timezone.php
Normal file
50
system/autoload/Timezone.php
Normal file
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
/**
|
||||
* PHP Mikrotik Billing (https://github.com/hotspotbilling/phpnuxbill/)
|
||||
* by https://t.me/ibnux
|
||||
**/
|
||||
|
||||
|
||||
class Timezone {
|
||||
public static function timezoneList()
|
||||
{
|
||||
$timezoneIdentifiers = DateTimeZone::listIdentifiers();
|
||||
$utcTime = new DateTime('now', new DateTimeZone('UTC'));
|
||||
|
||||
$tempTimezones = array();
|
||||
foreach ($timezoneIdentifiers as $timezoneIdentifier) {
|
||||
$currentTimezone = new DateTimeZone($timezoneIdentifier);
|
||||
|
||||
$tempTimezones[] = array(
|
||||
'offset' => (int)$currentTimezone->getOffset($utcTime),
|
||||
'identifier' => $timezoneIdentifier
|
||||
);
|
||||
}
|
||||
|
||||
// Sort the array by offset,identifier ascending
|
||||
usort($tempTimezones, function($a, $b) {
|
||||
return ($a['offset'] == $b['offset'])
|
||||
? strcmp($a['identifier'], $b['identifier'])
|
||||
: $a['offset'] - $b['offset'];
|
||||
});
|
||||
|
||||
$timezoneList = array();
|
||||
foreach ($tempTimezones as $tz) {
|
||||
$sign = ($tz['offset'] > 0) ? '+' : '-';
|
||||
$offset = gmdate('H:i', abs($tz['offset']));
|
||||
$timezoneList[$tz['identifier']] = '(UTC ' . $sign . $offset . ') ' .
|
||||
$tz['identifier'];
|
||||
}
|
||||
|
||||
return $timezoneList;
|
||||
}
|
||||
|
||||
public static function getTimeOffset($tz = 'Asia/Jakarta'){
|
||||
$utcTime = new DateTime('now', new DateTimeZone('UTC'));
|
||||
$currentTimezone = new DateTimeZone($tz);
|
||||
$offset = $currentTimezone->getOffset($utcTime);
|
||||
$sign = ($offset > 0) ? '+' : '-';
|
||||
$offset = gmdate('H:i', abs($offset));
|
||||
return $sign.$offset;
|
||||
}
|
||||
}
|
||||
202
system/autoload/User.php
Normal file
202
system/autoload/User.php
Normal file
@@ -0,0 +1,202 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* PHP Mikrotik Billing (https://github.com/hotspotbilling/phpnuxbill/)
|
||||
* by https://t.me/ibnux
|
||||
**/
|
||||
|
||||
|
||||
class User
|
||||
{
|
||||
public static function getID()
|
||||
{
|
||||
global $db_password;
|
||||
if (isset($_SESSION['uid']) && !empty($_SESSION['uid'])) {
|
||||
return $_SESSION['uid'];
|
||||
} else if (isset($_COOKIE['uid'])) {
|
||||
// id.time.sha1
|
||||
$tmp = explode('.', $_COOKIE['uid']);
|
||||
if (sha1($tmp[0] . '.' . $tmp[1] . '.' . $db_password) == $tmp[2]) {
|
||||
if (time() - $tmp[1] < 86400 * 30) {
|
||||
$_SESSION['uid'] = $tmp[0];
|
||||
return $tmp[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static function getBills($id = 0)
|
||||
{
|
||||
if (!$id) {
|
||||
$id = User::getID();
|
||||
if (!$id) {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
$addcost = 0;
|
||||
$bills = [];
|
||||
$attrs = User::getAttributes('Bill', $id);
|
||||
foreach ($attrs as $k => $v) {
|
||||
// if has : then its an installment
|
||||
if (strpos($v, ":") === false) {
|
||||
// Not installment
|
||||
$bills[$k] = $v;
|
||||
$addcost += $v;
|
||||
} else {
|
||||
// installment
|
||||
list($cost, $rem) = explode(":", $v);
|
||||
// :0 installment is done
|
||||
if (!empty($rem)) {
|
||||
$bills[$k] = $cost;
|
||||
$addcost += $cost;
|
||||
}
|
||||
}
|
||||
}
|
||||
return [$bills, $addcost];
|
||||
}
|
||||
|
||||
public static function billsPaid($bills, $id = 0)
|
||||
{
|
||||
if (!$id) {
|
||||
$id = User::getID();
|
||||
if (!$id) {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
foreach ($bills as $k => $v) {
|
||||
// if has : then its an installment
|
||||
$v = User::getAttribute($k, $id);
|
||||
if (strpos($v, ":") === false) {
|
||||
// Not installment, no need decrement
|
||||
} else {
|
||||
// installment
|
||||
list($cost, $rem) = explode(":", $v);
|
||||
// :0 installment is done
|
||||
if ($rem != 0) {
|
||||
User::setAttribute($k, "$cost:" . ($rem - 1), $id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static function setAttribute($name, $value, $id = 0)
|
||||
{
|
||||
if (!$id) {
|
||||
$id = User::getID();
|
||||
if (!$id) {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
$f = ORM::for_table('tbl_customers_fields')->where('field_name', $name)->where('customer_id', $id)->find_one();
|
||||
if (!$f) {
|
||||
$f = ORM::for_table('tbl_customers_fields')->create();
|
||||
$f->customer_id = $id;
|
||||
$f->field_name = $name;
|
||||
$f->field_value = $value;
|
||||
$f->save();
|
||||
$result = $f->id();
|
||||
if ($result) {
|
||||
return $result;
|
||||
}
|
||||
} else {
|
||||
$f->field_value = $value;
|
||||
$f->save();
|
||||
return $f['id'];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static function getAttribute($name, $id = 0)
|
||||
{
|
||||
if (!$id) {
|
||||
$id = User::getID();
|
||||
if (!$id) {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
$f = ORM::for_table('tbl_customers_fields')->where('field_name', $name)->where('customer_id', $id)->find_one();
|
||||
if ($f) {
|
||||
return $f['field_value'];
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
public static function getAttributes($endWith, $id = 0)
|
||||
{
|
||||
if (!$id) {
|
||||
$id = User::getID();
|
||||
if (!$id) {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
$attrs = [];
|
||||
$f = ORM::for_table('tbl_customers_fields')->where_like('field_name', "%$endWith")->where('customer_id', $id)->find_many();
|
||||
if ($f) {
|
||||
foreach ($f as $k) {
|
||||
$attrs[$k['field_name']] = $k['field_value'];
|
||||
}
|
||||
return $attrs;
|
||||
}
|
||||
return [];
|
||||
}
|
||||
|
||||
public static function setCookie($uid)
|
||||
{
|
||||
global $db_password;
|
||||
if (isset($uid)) {
|
||||
$time = time();
|
||||
setcookie('uid', $uid . '.' . $time . '.' . sha1($uid . '.' . $time . '.' . $db_password), time() + 86400 * 30);
|
||||
}
|
||||
}
|
||||
|
||||
public static function removeCookie()
|
||||
{
|
||||
if (isset($_COOKIE['uid'])) {
|
||||
setcookie('uid', '', time() - 86400);
|
||||
}
|
||||
}
|
||||
|
||||
public static function _info($id = 0)
|
||||
{
|
||||
global $config;
|
||||
if ($config['maintenance_mode'] == true) {
|
||||
if ($config['maintenance_mode_logout'] == true) {
|
||||
r2(U . 'logout', 'd', '');
|
||||
} else {
|
||||
displayMaintenanceMessage();
|
||||
}
|
||||
}
|
||||
if (!$id) {
|
||||
$id = User::getID();
|
||||
}
|
||||
$d = ORM::for_table('tbl_customers')->find_one($id);
|
||||
if ($d['status'] == 'Banned') {
|
||||
_alert(Lang::T('This account status') . ' : ' . Lang::T($d['status']), 'danger', "logout");
|
||||
}
|
||||
if (empty($d['username'])) {
|
||||
r2(U . 'logout', 'd', '');
|
||||
}
|
||||
return $d;
|
||||
}
|
||||
|
||||
public static function _billing($id = 0)
|
||||
{
|
||||
if (!$id) {
|
||||
$id = User::getID();
|
||||
}
|
||||
$d = ORM::for_table('tbl_user_recharges')
|
||||
->select('tbl_user_recharges.id', 'id')
|
||||
->selects([
|
||||
'customer_id', 'username', 'plan_id', 'namebp', 'recharged_on', 'recharged_time', 'expiration', 'time',
|
||||
'status', 'method', 'plan_type',
|
||||
['tbl_user_recharges.routers', 'routers'],
|
||||
['tbl_user_recharges.type', 'type'],
|
||||
'admin_id', 'prepaid'
|
||||
])
|
||||
->where('customer_id', $id)
|
||||
->left_outer_join('tbl_plans', array('tbl_plans.id', '=', 'tbl_user_recharges.plan_id'))
|
||||
->find_many();
|
||||
return $d;
|
||||
}
|
||||
}
|
||||
323
system/autoload/Validator.php
Normal file
323
system/autoload/Validator.php
Normal file
@@ -0,0 +1,323 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* PHP Mikrotik Billing (https://github.com/hotspotbilling/phpnuxbill/)
|
||||
* by https://t.me/ibnux
|
||||
**/
|
||||
|
||||
|
||||
/**
|
||||
* Validator class
|
||||
*/
|
||||
class Validator
|
||||
{
|
||||
|
||||
/**
|
||||
* String text finder
|
||||
*
|
||||
* @access private
|
||||
* @param string $string
|
||||
* @param array $hits
|
||||
* @return void
|
||||
*/
|
||||
public static function textHit($string, $exclude = "")
|
||||
{
|
||||
if (empty($exclude)) return false;
|
||||
if (is_array($exclude)) {
|
||||
foreach ($exclude as $text) {
|
||||
if (strstr($string, $text)) return true;
|
||||
}
|
||||
} else {
|
||||
if (strstr($string, $exclude)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Number compare
|
||||
*
|
||||
* @access private
|
||||
* @param int $integer
|
||||
* @param int $max
|
||||
* @param int $min
|
||||
* @return bool
|
||||
*/
|
||||
private static function numberBetween($integer, $max = null, $min = 0)
|
||||
{
|
||||
if (is_numeric($min) && $integer <= $min) return false;
|
||||
if (is_numeric($max) && $integer >= $max) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Email addres check
|
||||
*
|
||||
* @access public
|
||||
* @param string $string
|
||||
* @param array $exclude
|
||||
* @return bool
|
||||
*/
|
||||
public static function Email($string, $exclude = "")
|
||||
{
|
||||
if (self::textHit($string, $exclude)) return false;
|
||||
return (bool)preg_match("/^([a-z0-9])(([-a-z0-9._])*([a-z0-9]))*\@([a-z0-9])(([a-z0-9-])*([a-z0-9]))+(\.([a-z0-9])([-a-z0-9_-])?([a-z0-9])+)+$/i", $string);
|
||||
}
|
||||
|
||||
/**
|
||||
* URL check
|
||||
*
|
||||
* @access public
|
||||
* @param strin $string
|
||||
* @return bool
|
||||
*/
|
||||
public static function Url($string, $exclude = "")
|
||||
{
|
||||
if (self::textHit($string, $exclude)) return false;
|
||||
return (bool)preg_match("/^(http|https|ftp):\/\/([A-Z0-9][A-Z0-9_-]*(?:\.[A-Z0-9][A-Z0-9_-]*)+):?(\d+)?\/?/i", $string);
|
||||
}
|
||||
|
||||
/**
|
||||
* IP
|
||||
*
|
||||
* @access public
|
||||
* @param string $string
|
||||
* @return void
|
||||
*/
|
||||
public static function Ip($string)
|
||||
{
|
||||
return (bool)preg_match("/^(1?\d{1,2}|2([0-4]\d|5[0-5]))(\.(1?\d{1,2}|2([0-4]\d|5[0-5]))){3}$/", $string);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if it is an number
|
||||
*
|
||||
* @access public
|
||||
* @param int $integer
|
||||
* @param int $max
|
||||
* @param int $min
|
||||
* @return bool
|
||||
*/
|
||||
public static function Number($integer, $max = null, $min = 0)
|
||||
{
|
||||
if (preg_match("/^\-?\+?[0-9e1-9]+$/", $integer)) {
|
||||
if (!self::numberBetween($integer, $max, $min)) return false;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if it is an unsigned number
|
||||
*
|
||||
* @access public
|
||||
* @param int $integer
|
||||
* @return bool
|
||||
*/
|
||||
public static function UnsignedNumber($integer)
|
||||
{
|
||||
return (bool)preg_match("/^\+?[0-9]+$/", $integer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Float
|
||||
*
|
||||
* @access public
|
||||
* @param string $string
|
||||
* @return bool
|
||||
*/
|
||||
public static function Float($string)
|
||||
{
|
||||
return (bool)($string == strval(floatval($string))) ? true : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Alpha check
|
||||
*
|
||||
* @access public
|
||||
* @param string $string
|
||||
* @return void
|
||||
*/
|
||||
public static function Alpha($string)
|
||||
{
|
||||
return (bool)preg_match("/^[a-zA-Z]+$/", $string);
|
||||
}
|
||||
|
||||
/**
|
||||
* Alpha numeric check
|
||||
*
|
||||
* @access public
|
||||
* @param string $string
|
||||
* @return void
|
||||
*/
|
||||
public static function AlphaNumeric($string)
|
||||
{
|
||||
return (bool)preg_match("/^[0-9a-zA-Z]+$/", $string);
|
||||
}
|
||||
|
||||
/**
|
||||
* Specific chars check
|
||||
*
|
||||
* @access public
|
||||
* @param string $string
|
||||
* @param array $allowed
|
||||
* @return void
|
||||
*/
|
||||
public static function Chars($string, $allowed = array("a-z"))
|
||||
{
|
||||
return (bool)preg_match("/^[" . implode("", $allowed) . "]+$/", $string);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check length of an string
|
||||
*
|
||||
* @access public
|
||||
* @param string $stirng
|
||||
* @param int $max
|
||||
* @param int $min
|
||||
* @return bool
|
||||
*/
|
||||
public static function Length($string, $max = null, $min = 0)
|
||||
{
|
||||
$length = strlen($string);
|
||||
if (!self::numberBetween($length, $max, $min)) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Hex color check
|
||||
*
|
||||
* @access public
|
||||
* @param string $string
|
||||
* @return void
|
||||
*/
|
||||
public static function HexColor($string)
|
||||
{
|
||||
return (bool)preg_match("/^(#)?([0-9a-f]{1,2}){3}$/i", $string);
|
||||
}
|
||||
|
||||
/**
|
||||
* Data validation
|
||||
*
|
||||
* Does'nt matter how you provide the date
|
||||
* dd/mm/yyyy
|
||||
* dd-mm-yyyy
|
||||
* yyyy/mm/dd
|
||||
* yyyy-mm-dd
|
||||
*
|
||||
* @access public
|
||||
* @param string $string
|
||||
* @return bool
|
||||
*/
|
||||
public static function Date($string)
|
||||
{
|
||||
$date = date('Y', strtotime($string));
|
||||
return ($date == "1970" || $date == '') ? false : true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Older than check
|
||||
*
|
||||
* @access public
|
||||
* @param string $string
|
||||
* @param int $age
|
||||
* @return bool
|
||||
*/
|
||||
public static function OlderThan($string, $age)
|
||||
{
|
||||
$date = date('Y', strtotime($string));
|
||||
if ($date == "1970" || $date == '') return false;
|
||||
return (date('Y') - $date) > $age ? true : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* XML valid
|
||||
*
|
||||
* @access public
|
||||
* @param string $string
|
||||
* @return bool
|
||||
*/
|
||||
public static function Xml($string)
|
||||
{
|
||||
$Xml = @simplexml_load_string($string);
|
||||
return ($Xml === false) ? false : true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is filesize between
|
||||
*
|
||||
* @access public
|
||||
* @param string $file
|
||||
* @param int $max
|
||||
* @param int $min
|
||||
* @return bool
|
||||
*/
|
||||
public static function FilesizeBetween($file, $max = null, $min = 0)
|
||||
{
|
||||
$filesize = filesize($file);
|
||||
return self::numberBetween($filesize, $max, $min);
|
||||
}
|
||||
|
||||
/**
|
||||
* Is image width between
|
||||
*
|
||||
* @access public
|
||||
* @param string $image
|
||||
* @param int $max_width
|
||||
* @param int $min_width
|
||||
* @param int $max_height
|
||||
* @param int $min_height
|
||||
* @return void
|
||||
*/
|
||||
public static function ImageSizeBetween($image, $max_width = "", $min_width = 0, $max_height = "", $min_height = 0)
|
||||
{
|
||||
$size = getimagesize($image);
|
||||
if (!self::numberBetween($size[0], $max_width, $min_width)) return false;
|
||||
if (!self::numberBetween($size[1], $max_height, $min_height)) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Phone numbers
|
||||
*
|
||||
* @access public
|
||||
* @param string $phone
|
||||
* @return bool
|
||||
*/
|
||||
public static function Phone($phone)
|
||||
{
|
||||
$formats = array(
|
||||
'###-###-####',
|
||||
'####-###-###',
|
||||
'(###) ###-###',
|
||||
'####-####-####',
|
||||
'##-###-####-####',
|
||||
'####-####',
|
||||
'###-###-###',
|
||||
'#####-###-###',
|
||||
'##########',
|
||||
'####-##-##-##'
|
||||
);
|
||||
$format = trim(preg_replace("/[0-9]/", "#", $phone));
|
||||
return (bool)in_array($format, $formats);
|
||||
}
|
||||
|
||||
public static function countRouterPlan($plans, $router){
|
||||
$n = 0;
|
||||
foreach ($plans as $plan){
|
||||
if($plan['routers'] == $router){
|
||||
$n++;
|
||||
}
|
||||
}
|
||||
return $n;
|
||||
}
|
||||
|
||||
public static function isRouterHasPlan($plans, $router){
|
||||
foreach ($plans as $plan){
|
||||
if($plan['routers'] == $router){
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
50
system/autoload/Widget.php
Normal file
50
system/autoload/Widget.php
Normal file
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* PHP Mikrotik Billing (https://github.com/hotspotbilling/phpnuxbill/)
|
||||
* by https://t.me/ibnux
|
||||
**/
|
||||
|
||||
|
||||
/**
|
||||
* Validator class
|
||||
*/
|
||||
class Widget
|
||||
{
|
||||
|
||||
public static function rows($rows, $result){
|
||||
$result .= '<div class="row">';
|
||||
foreach($rows as $row){
|
||||
|
||||
}
|
||||
$result .= '</div>';
|
||||
}
|
||||
|
||||
public static function columns($cols, $result){
|
||||
$c = count($cols);
|
||||
switch($c){
|
||||
case 1:
|
||||
$result .= '<div class="col-md-12">';
|
||||
break;
|
||||
case 2:
|
||||
$result .= '<div class="col-md-6">';
|
||||
break;
|
||||
case 3:
|
||||
$result .= '<div class="col-md-4">';
|
||||
break;
|
||||
case 4:
|
||||
$result .= '<div class="col-md-4">';
|
||||
break;
|
||||
case 5:
|
||||
$result .= '<div class="col-md-4">';
|
||||
break;
|
||||
default:
|
||||
$result .= '<div class="col-md-1">';
|
||||
break;
|
||||
}
|
||||
|
||||
foreach($cols as $col){
|
||||
}
|
||||
$result .= '</div>';
|
||||
}
|
||||
}
|
||||
8
system/autoload/index.html
Normal file
8
system/autoload/index.html
Normal file
@@ -0,0 +1,8 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>403 Forbidden</title>
|
||||
</head>
|
||||
<body>
|
||||
<p>Directory access is forbidden.</p>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user