Radius Rest API
This commit is contained in:
parent
835276fef5
commit
410eb34d4a
227
radius.php
227
radius.php
@ -0,0 +1,227 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PHP Mikrotik Billing (https://github.com/hotspotbilling/phpnuxbill)
|
||||||
|
* by https://t.me/ibnux
|
||||||
|
*
|
||||||
|
* Authorize
|
||||||
|
* - Voucher activation
|
||||||
|
* Authenticate
|
||||||
|
* - is it allow to login
|
||||||
|
* Accounting
|
||||||
|
* - log
|
||||||
|
**/
|
||||||
|
|
||||||
|
header("Content-Type: application/json");
|
||||||
|
|
||||||
|
include "init.php";
|
||||||
|
|
||||||
|
$action = $_SERVER['HTTP_X_FREERADIUS_SECTION'];
|
||||||
|
if (empty($action)) {
|
||||||
|
$action = _get('action');
|
||||||
|
}
|
||||||
|
|
||||||
|
$code = 200;
|
||||||
|
|
||||||
|
try {
|
||||||
|
switch ($action) {
|
||||||
|
case 'authenticate':
|
||||||
|
$username = _req('username');
|
||||||
|
$password = _req('password');
|
||||||
|
if ($username == $password) {
|
||||||
|
$d = ORM::for_table('tbl_voucher')->where('code', $username)->find_one();
|
||||||
|
} else {
|
||||||
|
$d = ORM::for_table('tbl_customers')->where('username', $username)->find_one();
|
||||||
|
}
|
||||||
|
if ($d) {
|
||||||
|
header("HTTP/1.1 204 No Content");
|
||||||
|
die();
|
||||||
|
} else {
|
||||||
|
show_radius_result([
|
||||||
|
"control:Auth-Type" => "Reject",
|
||||||
|
"reply:Reply-Message" => 'Login invalid......'
|
||||||
|
], 401);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'authorize':
|
||||||
|
$username = _req('username');
|
||||||
|
$password = _req('password');
|
||||||
|
$isVoucher = ($username == $password);
|
||||||
|
if (empty($username)) {
|
||||||
|
show_radius_result([
|
||||||
|
"control:Auth-Type" => "Reject",
|
||||||
|
"reply:Reply-Message" => 'Login invalid......'
|
||||||
|
], 401);
|
||||||
|
}
|
||||||
|
$tur = ORM::for_table('tbl_user_recharges')->where('username', $username)->find_one();
|
||||||
|
if ($tur) {
|
||||||
|
if (!$isVoucher) {
|
||||||
|
$d = ORM::for_table('tbl_customers')->select('password')->where('username', $username)->find_one();
|
||||||
|
if ($d['password'] != $password) {
|
||||||
|
show_radius_result(['Reply-Message' => 'Username or Password is wrong'], 401);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
process_radiust_rest($tur, $code);
|
||||||
|
} else {
|
||||||
|
if ($isVoucher) {
|
||||||
|
$v = ORM::for_table('tbl_voucher')->where('code', $username)->where('routers', 'radius')->find_one();
|
||||||
|
if ($v) {
|
||||||
|
if ($v['status'] == 0) {
|
||||||
|
// voucher activation
|
||||||
|
if (Package::rechargeUser(0, $v['routers'], $v1['id_plan'], "Voucher", $username)) {
|
||||||
|
$v->status = "1";
|
||||||
|
$v->save();
|
||||||
|
$tur = ORM::for_table('tbl_user_recharges')->where('username', $username)->find_one();
|
||||||
|
if ($tur) {
|
||||||
|
process_radiust_rest($tur, $code);
|
||||||
|
} else {
|
||||||
|
show_radius_result(['Reply-Message' => 'Voucher activation failed'], 401);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
show_radius_result(['Reply-Message' => 'Voucher activation failed.'], 401);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
show_radius_result(['Reply-Message' => 'Voucher Expired...'], 401);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
show_radius_result(['Reply-Message' => 'Voucher Expired..'], 401);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
show_radius_result(['Reply-Message' => 'Internet Plan Expired..'], 401);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'accounting':
|
||||||
|
$username = _req('username');
|
||||||
|
if (empty($username)) {
|
||||||
|
die();
|
||||||
|
}
|
||||||
|
header("HTTP/1.1 200 ok");
|
||||||
|
$d = ORM::for_table('rad_acct')
|
||||||
|
->where('username', $username)
|
||||||
|
->where('macaddr', _post('macAddr'))
|
||||||
|
->where('acctstatustype', _post('acctStatusType'))
|
||||||
|
->findOne();
|
||||||
|
if (!$d) {
|
||||||
|
$d = ORM::for_table('rad_acct')->create();
|
||||||
|
}
|
||||||
|
$d->acctsessionid = _post('acctSessionId');
|
||||||
|
$d->username = $username;
|
||||||
|
$d->nasipaddress = _post('nasip');
|
||||||
|
$d->nasid = _post('nasid');
|
||||||
|
$d->nasportid = _post('nasPortId');
|
||||||
|
$d->nasporttype = _post('nasPortType');
|
||||||
|
$d->framedipaddress = _post('framedIPAddress');
|
||||||
|
$d->acctstatustype = _post('acctStatusType');
|
||||||
|
$d->macaddr = _post('macAddr');
|
||||||
|
$d->dateAdded = date('Y-m-d H:i:s');
|
||||||
|
$d->save();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
die();
|
||||||
|
} catch (Throwable $e) {
|
||||||
|
Message::sendTelegram(
|
||||||
|
"Sistem Error.\n" .
|
||||||
|
$e->getMessage() . "\n" .
|
||||||
|
$e->getTraceAsString(),
|
||||||
|
$config['telegram_topik_error']
|
||||||
|
);
|
||||||
|
} catch (Exception $e) {
|
||||||
|
Message::sendTelegram(
|
||||||
|
"Sistem Error.\n" .
|
||||||
|
$e->getMessage() . "\n" .
|
||||||
|
$e->getTraceAsString(),
|
||||||
|
$config['telegram_topik_error']
|
||||||
|
);
|
||||||
|
}
|
||||||
|
show_radius_result(['Reply-Message' => 'Invalid Command'], 401);
|
||||||
|
|
||||||
|
function process_radiust_rest($tur, $code)
|
||||||
|
{
|
||||||
|
global $config;
|
||||||
|
$plan = ORM::for_table('tbl_plans')->where('id', $tur['plan_id'])->find_one();
|
||||||
|
$bw = ORM::for_table("tbl_bandwidth")->find_one($plan['id_bw']);
|
||||||
|
if ($bw['rate_down_unit'] == 'Kbps') {
|
||||||
|
$unitdown = 'K';
|
||||||
|
} else {
|
||||||
|
$unitdown = 'M';
|
||||||
|
}
|
||||||
|
if ($bw['rate_up_unit'] == 'Kbps') {
|
||||||
|
$unitup = 'K';
|
||||||
|
} else {
|
||||||
|
$unitup = 'M';
|
||||||
|
}
|
||||||
|
$rate = $bw['rate_up'] . $unitup . "/" . $bw['rate_down'] . $unitdown;
|
||||||
|
$rates = explode('/', $rate);
|
||||||
|
|
||||||
|
if (!empty(trim($bw['burst']))) {
|
||||||
|
$ratos = $rate . ' ' . $bw['burst'];
|
||||||
|
} else {
|
||||||
|
$ratos = $rates[0] . '/' . $rates[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
$attrs = [];
|
||||||
|
$timeexp = strtotime($tur['expiration'] . ' ' . $tur['time']);
|
||||||
|
$attrs['reply:Reply-Message'] = 'success';
|
||||||
|
$attrs['Simultaneous-Use'] = $plan['shared_users'];
|
||||||
|
$attrs['reply:Mikrotik-Wireless-Comment'] = $plan['name_plan'] . ' | ' . $tur['expiration'] . ' ' . $tur['time'];
|
||||||
|
|
||||||
|
$attrs['reply:Ascend-Data-Rate'] = str_replace('M', '000000', str_replace('K', '000', $rates[1]));
|
||||||
|
$attrs['reply:Ascend-Xmit-Rate'] = str_replace('M', '000000', str_replace('K', '000', $rates[0]));
|
||||||
|
$attrs['reply:Mikrotik-Rate-Limit'] = $ratos;
|
||||||
|
$attrs['reply:WISPr-Bandwidth-Max-Up'] = str_replace('M', '000000', str_replace('K', '000', $rates[0]));
|
||||||
|
$attrs['reply:WISPr-Bandwidth-Max-Down'] = str_replace('M', '000000', str_replace('K', '000', $rates[1]));
|
||||||
|
$attrs['reply:expiration'] = date('d M Y H:i:s', $timeexp);
|
||||||
|
$attrs['reply:WISPr-Session-Terminate-Time'] = date('Y-m-d', $timeexp) . 'T' . date('H:i:sP', $timeexp);
|
||||||
|
|
||||||
|
if ($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;
|
||||||
|
$attrs['reply:Max-All-Session'] = $timelimit;
|
||||||
|
$attrs['reply: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";
|
||||||
|
$attrs['reply:Max-Data'] = $datalimit;
|
||||||
|
$attrs['reply:Mikrotik-Recv-Limit-Gigawords'] = $datalimit;
|
||||||
|
$attrs['reply:Mikrotik-Xmit-Limit-Gigawords'] = $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";
|
||||||
|
$attrs['reply:Max-All-Session'] = $timelimit;
|
||||||
|
$attrs['reply:Max-Data'] = $datalimit;
|
||||||
|
$attrs['reply:Mikrotik-Recv-Limit-Gigawords'] = $datalimit;
|
||||||
|
$attrs['reply:Mikrotik-Xmit-Limit-Gigawords'] = $datalimit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$result = array_merge([
|
||||||
|
"control:Auth-Type" => "Accept",
|
||||||
|
"reply" => ["Reply-Message" => ['value' => 'success']]
|
||||||
|
], $attrs);
|
||||||
|
show_radius_result($result, $code);
|
||||||
|
}
|
||||||
|
|
||||||
|
function show_radius_result($array, $code = 200)
|
||||||
|
{
|
||||||
|
if ($code == 401) {
|
||||||
|
header("HTTP/1.1 401 Unauthorized");
|
||||||
|
} else if ($code == 200) {
|
||||||
|
header("HTTP/1.1 200 OK");
|
||||||
|
} else if ($code == 204) {
|
||||||
|
header("HTTP/1.1 204 No Content");
|
||||||
|
die();
|
||||||
|
}
|
||||||
|
die(json_encode($array));
|
||||||
|
die();
|
||||||
|
}
|
@ -26,17 +26,26 @@ class Package
|
|||||||
$time_only = date("H:i:s");
|
$time_only = date("H:i:s");
|
||||||
$time = date("H:i:s");
|
$time = date("H:i:s");
|
||||||
$inv = "";
|
$inv = "";
|
||||||
|
$isVoucher = false;
|
||||||
|
|
||||||
if ($id_customer == '' or $router_name == '' or $plan_id == '') {
|
if ($id_customer == '' or $router_name == '' or $plan_id == '') {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
if($channel == 'Voucher' && $id_customer = 0){
|
||||||
|
$isVoucher = true;
|
||||||
|
}
|
||||||
|
|
||||||
$c = ORM::for_table('tbl_customers')->where('id', $id_customer)->find_one();
|
|
||||||
$p = ORM::for_table('tbl_plans')->where('id', $plan_id)->find_one();
|
$p = ORM::for_table('tbl_plans')->where('id', $plan_id)->find_one();
|
||||||
|
|
||||||
|
if(!$isVoucher){
|
||||||
|
$c = ORM::for_table('tbl_customers')->where('id', $id_customer)->find_one();
|
||||||
if ($c['status'] != 'Active') {
|
if ($c['status'] != 'Active') {
|
||||||
_alert(Lang::T('This account status') . ' : ' . Lang::T($c['status']), 'danger', "");
|
_alert(Lang::T('This account status') . ' : ' . Lang::T($c['status']), 'danger', "");
|
||||||
}
|
}
|
||||||
|
}else{
|
||||||
|
$c['username'] = $channel;
|
||||||
|
$c['fullname'] = $gateway;
|
||||||
|
}
|
||||||
|
|
||||||
$add_cost = 0;
|
$add_cost = 0;
|
||||||
$bills = [];
|
$bills = [];
|
||||||
|
@ -31,9 +31,23 @@ class MikrotikPppoe
|
|||||||
{
|
{
|
||||||
$mikrotik = $this->info($plan['routers']);
|
$mikrotik = $this->info($plan['routers']);
|
||||||
$client = $this->getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']);
|
$client = $this->getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']);
|
||||||
$this->removePpoeUser($client, $customer['username']);
|
//check if customer exists
|
||||||
$this->removePpoeActive($client, $customer['username']);
|
$printRequest = new RouterOS\Request('/ppp/secret/print');
|
||||||
|
$printRequest->setQuery(RouterOS\Query::where('name', $customer['username']));
|
||||||
|
$cid = $client->sendSync($printRequest)->getProperty('.id');
|
||||||
|
if (empty($cid)) {
|
||||||
|
//customer not exists, add it
|
||||||
$this->addPpoeUser($client, $plan, $customer);
|
$this->addPpoeUser($client, $plan, $customer);
|
||||||
|
}else{
|
||||||
|
$setRequest = new RouterOS\Request('/ppp/secret/set');
|
||||||
|
$setRequest->setArgument('numbers', $cid);
|
||||||
|
$setRequest->setArgument('profile', $plan['name_plan']);
|
||||||
|
$setRequest->setArgument('comment', $customer['fullname'] . ' | ' . $customer['email']);
|
||||||
|
$setRequest->setArgument('password', $customer['password']);
|
||||||
|
$client->sendSync($setRequest);
|
||||||
|
//disconnect then
|
||||||
|
$this->removePpoeActive($client, $customer['username']);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function remove_customer($customer, $plan)
|
function remove_customer($customer, $plan)
|
||||||
@ -212,15 +226,6 @@ class MikrotikPppoe
|
|||||||
return $client->sendSync($printRequest)->getProperty('.id');
|
return $client->sendSync($printRequest)->getProperty('.id');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function connect_customer($customer, $ip, $mac_address, $router_name)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
function disconnect_customer($customer, $router_name)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
function info($name)
|
function info($name)
|
||||||
{
|
{
|
||||||
return ORM::for_table('tbl_routers')->where('name', $name)->find_one();
|
return ORM::for_table('tbl_routers')->where('name', $name)->find_one();
|
||||||
|
@ -10,7 +10,7 @@ class RadiusRest {
|
|||||||
'description' => 'This devices will handle Radius Connection using Rest API',
|
'description' => 'This devices will handle Radius Connection using Rest API',
|
||||||
'author' => 'ibnu maksum',
|
'author' => 'ibnu maksum',
|
||||||
'url' => [
|
'url' => [
|
||||||
'Wiki/Tutorial' => 'https://github.com/hotspotbilling/phpnuxbill/wiki/Radius-Rest',
|
'Wiki Tutorial' => 'https://github.com/hotspotbilling/phpnuxbill/wiki/FreeRadius-Rest',
|
||||||
'Telegram' => 'https://t.me/ibnux',
|
'Telegram' => 'https://t.me/ibnux',
|
||||||
'Donate' => 'https://paypal.me/ibnux'
|
'Donate' => 'https://paypal.me/ibnux'
|
||||||
]
|
]
|
||||||
|
@ -561,5 +561,6 @@
|
|||||||
"Please_wait_1015_seconds_before_sending_another_SMS": "Harap tunggu 1015 detik sebelum mengirim SMS lainnya",
|
"Please_wait_1015_seconds_before_sending_another_SMS": "Harap tunggu 1015 detik sebelum mengirim SMS lainnya",
|
||||||
"Phone_number_updated_successfully": "Nomor telepon berhasil diperbarui",
|
"Phone_number_updated_successfully": "Nomor telepon berhasil diperbarui",
|
||||||
"You_cannot_use_your_current_phone_number": "Anda tidak dapat menggunakan nomor telepon Anda saat ini",
|
"You_cannot_use_your_current_phone_number": "Anda tidak dapat menggunakan nomor telepon Anda saat ini",
|
||||||
"Devices": "Perangkat"
|
"Devices": "Perangkat",
|
||||||
|
"Voucher_Prefix": "Awalan Voucher"
|
||||||
}
|
}
|
@ -120,5 +120,10 @@
|
|||||||
"2024.6.21" : [
|
"2024.6.21" : [
|
||||||
"ALTER TABLE `tbl_plans` ADD `on_login` TEXT NULL DEFAULT NULL AFTER `device`;",
|
"ALTER TABLE `tbl_plans` ADD `on_login` TEXT NULL DEFAULT NULL AFTER `device`;",
|
||||||
"ALTER TABLE `tbl_plans` ADD `on_logout` TEXT NULL DEFAULT NULL AFTER `on_login`;"
|
"ALTER TABLE `tbl_plans` ADD `on_logout` TEXT NULL DEFAULT NULL AFTER `on_login`;"
|
||||||
|
],
|
||||||
|
"2024.7.6" : [
|
||||||
|
"CREATE TABLE IF NOT EXISTS `rad_acct` ( `id` bigint NOT NULL, `acctsessionid` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '', `username` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '', `nasid` varchar(32) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '', `nasipaddress` varchar(15) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '', `nasportid` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL, `nasporttype` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL, `framedipaddress` varchar(15) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '',`acctstatustype` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL, `macaddr` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, `dateAdded` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;",
|
||||||
|
"ALTER TABLE `rad_acct` ADD PRIMARY KEY (`id`), ADD KEY `username` (`username`), ADD KEY `framedipaddress` (`framedipaddress`), ADD KEY `acctsessionid` (`acctsessionid`), ADD KEY `nasipaddress` (`nasipaddress`);",
|
||||||
|
"ALTER TABLE `rad_acct` MODIFY `id` bigint NOT NULL AUTO_INCREMENT;"
|
||||||
]
|
]
|
||||||
}
|
}
|
@ -1,3 +1,3 @@
|
|||||||
{
|
{
|
||||||
"version": "2024.6.25"
|
"version": "2024.7.6"
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user