mirror of
https://github.com/v2board/v2board.git
synced 2025-02-15 01:40:28 +08:00
commit
32c539d2c0
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
namespace App\Console\Commands;
|
namespace App\Console\Commands;
|
||||||
|
|
||||||
|
use App\Models\CommissionLog;
|
||||||
use Illuminate\Console\Command;
|
use Illuminate\Console\Command;
|
||||||
use App\Models\Order;
|
use App\Models\Order;
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
@ -59,27 +60,66 @@ class CheckCommission extends Command
|
|||||||
|
|
||||||
public function autoPayCommission()
|
public function autoPayCommission()
|
||||||
{
|
{
|
||||||
$order = Order::where('commission_status', 1)
|
$orders = Order::where('commission_status', 1)
|
||||||
->where('invite_user_id', '!=', NULL)
|
->where('invite_user_id', '!=', NULL)
|
||||||
->get();
|
->get();
|
||||||
foreach ($order as $item) {
|
foreach ($orders as $order) {
|
||||||
$inviter = User::find($item->invite_user_id);
|
|
||||||
if (!$inviter) continue;
|
|
||||||
if ((int)config('v2board.withdraw_close_enable', 0)) {
|
|
||||||
$inviter->balance = $inviter->balance + $item->commission_balance;
|
|
||||||
} else {
|
|
||||||
$inviter->commission_balance = $inviter->commission_balance + $item->commission_balance;
|
|
||||||
}
|
|
||||||
DB::beginTransaction();
|
DB::beginTransaction();
|
||||||
if ($inviter->save()) {
|
if (!$this->payHandle($order->invite_user_id, $order)) {
|
||||||
$item->commission_status = 2;
|
DB::rollBack();
|
||||||
if (!$item->save()) {
|
continue;
|
||||||
DB::rollBack();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
DB::commit();
|
|
||||||
}
|
}
|
||||||
|
$order->commission_status = 2;
|
||||||
|
if (!$order->save()) {
|
||||||
|
DB::rollBack();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
DB::commit();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function payHandle($inviteUserId, Order $order)
|
||||||
|
{
|
||||||
|
if ((int)config('v2board.commission_distribution_enable', 0)) {
|
||||||
|
$level = 3;
|
||||||
|
$commissionShareLevels = [
|
||||||
|
0 => (int)config('v2board.commission_distribution_l1'),
|
||||||
|
1 => (int)config('v2board.commission_distribution_l2'),
|
||||||
|
2 => (int)config('v2board.commission_distribution_l3')
|
||||||
|
];
|
||||||
|
} else {
|
||||||
|
$level = 3;
|
||||||
|
$commissionShareLevels = [
|
||||||
|
0 => 100
|
||||||
|
];
|
||||||
|
}
|
||||||
|
for ($l = 0; $l < $level; $l++) {
|
||||||
|
$inviter = User::find($inviteUserId);
|
||||||
|
if (!$inviter) continue;
|
||||||
|
if (!isset($commissionShareLevels[$l])) continue;
|
||||||
|
$commissionBalance = $order->commission_balance * ($commissionShareLevels[$l] / 100);
|
||||||
|
if ((int)config('v2board.withdraw_close_enable', 0)) {
|
||||||
|
$inviter->balance = $inviter->balance + $commissionBalance;
|
||||||
|
} else {
|
||||||
|
$inviter->commission_balance = $inviter->commission_balance + $commissionBalance;
|
||||||
|
}
|
||||||
|
if (!$inviter->save()) {
|
||||||
|
DB::rollBack();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!CommissionLog::create([
|
||||||
|
'invite_user_id' => $inviteUserId,
|
||||||
|
'user_id' => $order->user_id,
|
||||||
|
'trade_no' => $order->trade_no,
|
||||||
|
'order_amount' => $order->total_amount,
|
||||||
|
'get_amount' => $commissionBalance
|
||||||
|
])) {
|
||||||
|
DB::rollBack();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$inviteUserId = $inviter->invite_user_id;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
namespace App\Console\Commands;
|
namespace App\Console\Commands;
|
||||||
|
|
||||||
|
use App\Jobs\OrderHandleJob;
|
||||||
use App\Services\OrderService;
|
use App\Services\OrderService;
|
||||||
use Illuminate\Console\Command;
|
use Illuminate\Console\Command;
|
||||||
use App\Models\Order;
|
use App\Models\Order;
|
||||||
@ -45,20 +46,8 @@ class CheckOrder extends Command
|
|||||||
ini_set('memory_limit', -1);
|
ini_set('memory_limit', -1);
|
||||||
$orders = Order::whereIn('status', [0, 1])
|
$orders = Order::whereIn('status', [0, 1])
|
||||||
->get();
|
->get();
|
||||||
foreach ($orders as $item) {
|
foreach ($orders as $order) {
|
||||||
$orderService = new OrderService($item);
|
OrderHandleJob::dispatch($order->trade_no);
|
||||||
switch ($item->status) {
|
|
||||||
// cancel
|
|
||||||
case 0:
|
|
||||||
if (strtotime($item->created_at) <= (time() - 1800)) {
|
|
||||||
$orderService->cancel();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
$orderService->open();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
namespace App\Console\Commands;
|
namespace App\Console\Commands;
|
||||||
|
|
||||||
|
use App\Models\Plan;
|
||||||
use Illuminate\Console\Command;
|
use Illuminate\Console\Command;
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
use Illuminate\Support\Facades\DB;
|
use Illuminate\Support\Facades\DB;
|
||||||
@ -42,24 +43,45 @@ class ResetTraffic extends Command
|
|||||||
*/
|
*/
|
||||||
public function handle()
|
public function handle()
|
||||||
{
|
{
|
||||||
DB::beginTransaction();
|
ini_set('memory_limit', -1);
|
||||||
$resetTrafficMethod = config('v2board.reset_traffic_method', 0);
|
foreach (Plan::get() as $plan) {
|
||||||
switch ((int)$resetTrafficMethod) {
|
switch ($plan->reset_traffic_method) {
|
||||||
// 1 a month
|
case null: {
|
||||||
case 0:
|
$resetTrafficMethod = config('v2board.reset_traffic_method', 0);
|
||||||
$this->resetByMonthFirstDay();
|
switch ((int)$resetTrafficMethod) {
|
||||||
break;
|
// month first day
|
||||||
// expire day
|
case 0:
|
||||||
case 1:
|
$this->resetByMonthFirstDay($this->builder);
|
||||||
$this->resetByExpireDay();
|
break;
|
||||||
break;
|
// expire day
|
||||||
|
case 1:
|
||||||
|
$this->resetByExpireDay($this->builder);
|
||||||
|
break;
|
||||||
|
// no action
|
||||||
|
case 2:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 0: {
|
||||||
|
$builder = $this->builder->where('plan_id', $plan->id);
|
||||||
|
$this->resetByMonthFirstDay($builder);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 1: {
|
||||||
|
$builder = $this->builder->where('plan_id', $plan->id);
|
||||||
|
$this->resetByExpireDay($builder);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 2: {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
DB::commit();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private function resetByMonthFirstDay():void
|
private function resetByMonthFirstDay($builder):void
|
||||||
{
|
{
|
||||||
$builder = $this->builder;
|
|
||||||
if ((string)date('d') === '01') {
|
if ((string)date('d') === '01') {
|
||||||
$builder->update([
|
$builder->update([
|
||||||
'u' => 0,
|
'u' => 0,
|
||||||
@ -68,9 +90,8 @@ class ResetTraffic extends Command
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private function resetByExpireDay():void
|
private function resetByExpireDay($builder):void
|
||||||
{
|
{
|
||||||
$builder = $this->builder;
|
|
||||||
$lastDay = date('d', strtotime('last day of +0 months'));
|
$lastDay = date('d', strtotime('last day of +0 months'));
|
||||||
$users = [];
|
$users = [];
|
||||||
foreach ($builder->get() as $item) {
|
foreach ($builder->get() as $item) {
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
namespace App\Console\Commands;
|
namespace App\Console\Commands;
|
||||||
|
|
||||||
|
use App\Services\MailService;
|
||||||
use Illuminate\Console\Command;
|
use Illuminate\Console\Command;
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
use App\Models\MailLog;
|
use App\Models\MailLog;
|
||||||
@ -41,23 +42,9 @@ class SendRemindMail extends Command
|
|||||||
public function handle()
|
public function handle()
|
||||||
{
|
{
|
||||||
$users = User::all();
|
$users = User::all();
|
||||||
|
$mailService = new MailService();
|
||||||
foreach ($users as $user) {
|
foreach ($users as $user) {
|
||||||
if ($user->remind_expire) $this->remindExpire($user);
|
if ($user->remind_expire) $mailService->remindExpire($user);
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private function remindExpire($user)
|
|
||||||
{
|
|
||||||
if ($user->expired_at !== NULL && ($user->expired_at - 86400) < time() && $user->expired_at > time()) {
|
|
||||||
SendEmailJob::dispatch([
|
|
||||||
'email' => $user->email,
|
|
||||||
'subject' => '在' . config('v2board.app_name', 'V2board') . '的服务即将到期',
|
|
||||||
'template_name' => 'remindExpire',
|
|
||||||
'template_value' => [
|
|
||||||
'name' => config('v2board.app_name', 'V2Board'),
|
|
||||||
'url' => config('v2board.app_url')
|
|
||||||
]
|
|
||||||
]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,10 @@
|
|||||||
namespace App\Console\Commands;
|
namespace App\Console\Commands;
|
||||||
|
|
||||||
use App\Models\Order;
|
use App\Models\Order;
|
||||||
|
use App\Models\User;
|
||||||
|
use App\Utils\Helper;
|
||||||
use Illuminate\Console\Command;
|
use Illuminate\Console\Command;
|
||||||
|
use Matriphe\Larinfo;
|
||||||
|
|
||||||
class Test extends Command
|
class Test extends Command
|
||||||
{
|
{
|
||||||
|
@ -47,13 +47,12 @@ class V2boardInstall extends Command
|
|||||||
$this->info(" \ \ / / __) | _ \ / _ \ / _` | '__/ _` | ");
|
$this->info(" \ \ / / __) | _ \ / _ \ / _` | '__/ _` | ");
|
||||||
$this->info(" \ V / / __/| |_) | (_) | (_| | | | (_| | ");
|
$this->info(" \ V / / __/| |_) | (_) | (_| | | | (_| | ");
|
||||||
$this->info(" \_/ |_____|____/ \___/ \__,_|_| \__,_| ");
|
$this->info(" \_/ |_____|____/ \___/ \__,_|_| \__,_| ");
|
||||||
if (\File::exists(base_path() . '/.lock')) {
|
if (\File::exists(base_path() . '/.env')) {
|
||||||
abort(500, 'V2board 已安装,如需重新安装请删除目录下.lock文件');
|
abort(500, 'V2board 已安装,如需重新安装请删除目录下.lock文件');
|
||||||
}
|
}
|
||||||
if (!\File::exists(base_path() . '/.env')) {
|
|
||||||
if (!copy(base_path() . '/.env.example', base_path() . '/.env')) {
|
if (!copy(base_path() . '/.env.example', base_path() . '/.env')) {
|
||||||
abort(500, '复制环境文件失败,请检查目录权限');
|
abort(500, '复制环境文件失败,请检查目录权限');
|
||||||
}
|
|
||||||
}
|
}
|
||||||
$this->saveToEnv([
|
$this->saveToEnv([
|
||||||
'APP_KEY' => 'base64:' . base64_encode(Encrypter::generateKey('AES-256-CBC')),
|
'APP_KEY' => 'base64:' . base64_encode(Encrypter::generateKey('AES-256-CBC')),
|
||||||
|
@ -42,16 +42,16 @@ class V2boardStatistics extends Command
|
|||||||
*/
|
*/
|
||||||
public function handle()
|
public function handle()
|
||||||
{
|
{
|
||||||
$this->statOrder();
|
$this->statOrder();
|
||||||
$this->statServer();
|
$this->statServer();
|
||||||
}
|
}
|
||||||
|
|
||||||
private function statOrder()
|
private function statOrder()
|
||||||
{
|
{
|
||||||
$endAt = strtotime(date('Y-m-d'));
|
$endAt = strtotime(date('Y-m-d'));
|
||||||
$startAt = strtotime('-1 day', $endAt);
|
$startAt = strtotime('-1 day', $endAt);
|
||||||
$builder = Order::where('created_at', '>=', $startAt)
|
$builder = Order::where('paid_at', '>=', $startAt)
|
||||||
->where('created_at', '<', $endAt)
|
->where('paid_at', '<', $endAt)
|
||||||
->whereNotIn('status', [0, 2]);
|
->whereNotIn('status', [0, 2]);
|
||||||
$orderCount = $builder->count();
|
$orderCount = $builder->count();
|
||||||
$orderAmount = $builder->sum('total_amount');
|
$orderAmount = $builder->sum('total_amount');
|
||||||
|
@ -51,11 +51,12 @@ class V2boardUpdate extends Command
|
|||||||
}
|
}
|
||||||
$this->info('正在导入数据库请稍等...');
|
$this->info('正在导入数据库请稍等...');
|
||||||
foreach ($sql as $item) {
|
foreach ($sql as $item) {
|
||||||
|
if (!$item) continue;
|
||||||
try {
|
try {
|
||||||
DB::select(DB::raw($item));
|
DB::select(DB::raw($item));
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$this->info('更新完毕');
|
$this->info('更新完毕,请重新启动队列服务。');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
4
app/Console/Kernel.php
Executable file → Normal file
4
app/Console/Kernel.php
Executable file → Normal file
@ -31,9 +31,11 @@ class Kernel extends ConsoleKernel
|
|||||||
$schedule->command('check:commission')->everyMinute();
|
$schedule->command('check:commission')->everyMinute();
|
||||||
// reset
|
// reset
|
||||||
$schedule->command('reset:traffic')->daily();
|
$schedule->command('reset:traffic')->daily();
|
||||||
$schedule->command('reset:serverLog')->quarterly();
|
$schedule->command('reset:serverLog')->quarterly()->at('0:15');
|
||||||
// send
|
// send
|
||||||
$schedule->command('send:remindMail')->dailyAt('11:30');
|
$schedule->command('send:remindMail')->dailyAt('11:30');
|
||||||
|
// horizon metrics
|
||||||
|
$schedule->command('horizon:snapshot')->everyFiveMinutes();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -2,8 +2,8 @@
|
|||||||
|
|
||||||
namespace App\Exceptions;
|
namespace App\Exceptions;
|
||||||
|
|
||||||
use Exception;
|
|
||||||
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
|
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
|
||||||
|
use Throwable;
|
||||||
|
|
||||||
class Handler extends ExceptionHandler
|
class Handler extends ExceptionHandler
|
||||||
{
|
{
|
||||||
@ -29,10 +29,12 @@ class Handler extends ExceptionHandler
|
|||||||
/**
|
/**
|
||||||
* Report or log an exception.
|
* Report or log an exception.
|
||||||
*
|
*
|
||||||
* @param \Exception $exception
|
* @param \Throwable $exception
|
||||||
* @return void
|
* @return void
|
||||||
|
*
|
||||||
|
* @throws \Throwable
|
||||||
*/
|
*/
|
||||||
public function report(Exception $exception)
|
public function report(Throwable $exception)
|
||||||
{
|
{
|
||||||
parent::report($exception);
|
parent::report($exception);
|
||||||
}
|
}
|
||||||
@ -40,16 +42,14 @@ class Handler extends ExceptionHandler
|
|||||||
/**
|
/**
|
||||||
* Render an exception into an HTTP response.
|
* Render an exception into an HTTP response.
|
||||||
*
|
*
|
||||||
* @param \Illuminate\Http\Request $request
|
* @param \Illuminate\Http\Request $request
|
||||||
* @param \Exception $exception
|
* @param \Throwable $exception
|
||||||
* @return \Illuminate\Http\Response
|
* @return \Symfony\Component\HttpFoundation\Response
|
||||||
|
*
|
||||||
|
* @throws \Throwable
|
||||||
*/
|
*/
|
||||||
public function render($request, Exception $exception)
|
public function render($request, Throwable $exception)
|
||||||
{
|
{
|
||||||
if($exception instanceof \Illuminate\Http\Exceptions\ThrottleRequestsException) {
|
|
||||||
abort(429, '请求频繁,请稍后再试');
|
|
||||||
}
|
|
||||||
return parent::render($request, $exception);
|
return parent::render($request, $exception);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -60,7 +60,11 @@ class ConfigController extends Controller
|
|||||||
'commission_auto_check_enable' => config('v2board.commission_auto_check_enable', 1),
|
'commission_auto_check_enable' => config('v2board.commission_auto_check_enable', 1),
|
||||||
'commission_withdraw_limit' => config('v2board.commission_withdraw_limit', 100),
|
'commission_withdraw_limit' => config('v2board.commission_withdraw_limit', 100),
|
||||||
'commission_withdraw_method' => config('v2board.commission_withdraw_method', Dict::WITHDRAW_METHOD_WHITELIST_DEFAULT),
|
'commission_withdraw_method' => config('v2board.commission_withdraw_method', Dict::WITHDRAW_METHOD_WHITELIST_DEFAULT),
|
||||||
'withdraw_close_enable' => config('v2board.withdraw_close_enable', 0)
|
'withdraw_close_enable' => config('v2board.withdraw_close_enable', 0),
|
||||||
|
'commission_distribution_enable' => config('v2board.commission_distribution_enable', 0),
|
||||||
|
'commission_distribution_l1' => config('v2board.commission_distribution_l1'),
|
||||||
|
'commission_distribution_l2' => config('v2board.commission_distribution_l2'),
|
||||||
|
'commission_distribution_l3' => config('v2board.commission_distribution_l3')
|
||||||
],
|
],
|
||||||
'site' => [
|
'site' => [
|
||||||
'safe_mode_enable' => (int)config('v2board.safe_mode_enable', 0),
|
'safe_mode_enable' => (int)config('v2board.safe_mode_enable', 0),
|
||||||
@ -136,9 +140,6 @@ class ConfigController extends Controller
|
|||||||
'server_v2ray_domain' => config('v2board.server_v2ray_domain'),
|
'server_v2ray_domain' => config('v2board.server_v2ray_domain'),
|
||||||
'server_v2ray_protocol' => config('v2board.server_v2ray_protocol'),
|
'server_v2ray_protocol' => config('v2board.server_v2ray_protocol'),
|
||||||
],
|
],
|
||||||
'tutorial' => [
|
|
||||||
'apple_id' => config('v2board.apple_id')
|
|
||||||
],
|
|
||||||
'email' => [
|
'email' => [
|
||||||
'email_template' => config('v2board.email_template', 'default'),
|
'email_template' => config('v2board.email_template', 'default'),
|
||||||
'email_host' => config('v2board.email_host'),
|
'email_host' => config('v2board.email_host'),
|
||||||
@ -166,7 +167,7 @@ class ConfigController extends Controller
|
|||||||
|
|
||||||
public function save(ConfigSave $request)
|
public function save(ConfigSave $request)
|
||||||
{
|
{
|
||||||
$data = $request->input();
|
$data = $request->validated();
|
||||||
$array = \Config::get('v2board');
|
$array = \Config::get('v2board');
|
||||||
foreach ($data as $k => $v) {
|
foreach ($data as $k => $v) {
|
||||||
if (!in_array($k, array_keys($request->validated()))) {
|
if (!in_array($k, array_keys($request->validated()))) {
|
||||||
|
@ -24,42 +24,12 @@ class CouponController extends Controller
|
|||||||
$total = $builder->count();
|
$total = $builder->count();
|
||||||
$coupons = $builder->forPage($current, $pageSize)
|
$coupons = $builder->forPage($current, $pageSize)
|
||||||
->get();
|
->get();
|
||||||
|
|
||||||
foreach ($coupons as $k => $v) {
|
|
||||||
if ($coupons[$k]['limit_plan_ids']) $coupons[$k]['limit_plan_ids'] = json_decode($coupons[$k]['limit_plan_ids']);
|
|
||||||
}
|
|
||||||
return response([
|
return response([
|
||||||
'data' => $coupons,
|
'data' => $coupons,
|
||||||
'total' => $total
|
'total' => $total
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function save(CouponSave $request)
|
|
||||||
{
|
|
||||||
$params = $request->validated();
|
|
||||||
if (isset($params['limit_plan_ids'])) {
|
|
||||||
$params['limit_plan_ids'] = json_encode($params['limit_plan_ids']);
|
|
||||||
}
|
|
||||||
if (!$request->input('id')) {
|
|
||||||
if (!isset($params['code'])) {
|
|
||||||
$params['code'] = Helper::randomChar(8);
|
|
||||||
}
|
|
||||||
if (!Coupon::create($params)) {
|
|
||||||
abort(500, '创建失败');
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
try {
|
|
||||||
Coupon::find($request->input('id'))->update($params);
|
|
||||||
} catch (\Exception $e) {
|
|
||||||
abort(500, '保存失败');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return response([
|
|
||||||
'data' => true
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function generate(CouponGenerate $request)
|
public function generate(CouponGenerate $request)
|
||||||
{
|
{
|
||||||
if ($request->input('generate_count')) {
|
if ($request->input('generate_count')) {
|
||||||
@ -68,9 +38,6 @@ class CouponController extends Controller
|
|||||||
}
|
}
|
||||||
|
|
||||||
$params = $request->validated();
|
$params = $request->validated();
|
||||||
if (isset($params['limit_plan_ids'])) {
|
|
||||||
$params['limit_plan_ids'] = json_encode($params['limit_plan_ids']);
|
|
||||||
}
|
|
||||||
if (!$request->input('id')) {
|
if (!$request->input('id')) {
|
||||||
if (!isset($params['code'])) {
|
if (!isset($params['code'])) {
|
||||||
$params['code'] = Helper::randomChar(8);
|
$params['code'] = Helper::randomChar(8);
|
||||||
@ -95,10 +62,8 @@ class CouponController extends Controller
|
|||||||
{
|
{
|
||||||
$coupons = [];
|
$coupons = [];
|
||||||
$coupon = $request->validated();
|
$coupon = $request->validated();
|
||||||
if (isset($coupon['limit_plan_ids'])) {
|
|
||||||
$coupon['limit_plan_ids'] = json_encode($coupon['limit_plan_ids']);
|
|
||||||
}
|
|
||||||
$coupon['created_at'] = $coupon['updated_at'] = time();
|
$coupon['created_at'] = $coupon['updated_at'] = time();
|
||||||
|
$coupon['limit_plan_ids'] = json_encode($coupon['limit_plan_ids']);
|
||||||
unset($coupon['generate_count']);
|
unset($coupon['generate_count']);
|
||||||
for ($i = 0;$i < $request->input('generate_count');$i++) {
|
for ($i = 0;$i < $request->input('generate_count');$i++) {
|
||||||
$coupon['code'] = Helper::randomChar(8);
|
$coupon['code'] = Helper::randomChar(8);
|
||||||
@ -118,7 +83,7 @@ class CouponController extends Controller
|
|||||||
$endTime = date('Y-m-d H:i:s', $coupon['ended_at']);
|
$endTime = date('Y-m-d H:i:s', $coupon['ended_at']);
|
||||||
$limitUse = $coupon['limit_use'] ?? '不限制';
|
$limitUse = $coupon['limit_use'] ?? '不限制';
|
||||||
$createTime = date('Y-m-d H:i:s', $coupon['created_at']);
|
$createTime = date('Y-m-d H:i:s', $coupon['created_at']);
|
||||||
$limitPlanIds = $coupon['limit_plan_ids'] ?? '不限制';
|
$limitPlanIds = implode("/", json_decode($coupon['limit_plan_ids'], true)) ?? '不限制';
|
||||||
$data .= "{$coupon['name']},{$type},{$value},{$startTime},{$endTime},{$limitUse},{$limitPlanIds},{$coupon['code']},{$createTime}\r\n";
|
$data .= "{$coupon['name']},{$type},{$value},{$startTime},{$endTime},{$limitUse},{$limitPlanIds},{$coupon['code']},{$createTime}\r\n";
|
||||||
}
|
}
|
||||||
echo $data;
|
echo $data;
|
||||||
|
@ -6,6 +6,7 @@ use App\Http\Requests\Admin\OrderAssign;
|
|||||||
use App\Http\Requests\Admin\OrderUpdate;
|
use App\Http\Requests\Admin\OrderUpdate;
|
||||||
use App\Http\Requests\Admin\OrderFetch;
|
use App\Http\Requests\Admin\OrderFetch;
|
||||||
use App\Services\OrderService;
|
use App\Services\OrderService;
|
||||||
|
use App\Services\UserService;
|
||||||
use App\Utils\Helper;
|
use App\Utils\Helper;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use App\Http\Controllers\Controller;
|
use App\Http\Controllers\Controller;
|
||||||
@ -63,10 +64,45 @@ class OrderController extends Controller
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function paid(Request $request)
|
||||||
|
{
|
||||||
|
$order = Order::where('trade_no', $request->input('trade_no'))
|
||||||
|
->first();
|
||||||
|
if (!$order) {
|
||||||
|
abort(500, '订单不存在');
|
||||||
|
}
|
||||||
|
if ($order->status !== 0) abort(500, '只能对待支付的订单进行操作');
|
||||||
|
|
||||||
|
$orderService = new OrderService($order);
|
||||||
|
if (!$orderService->paid('manual_operation')) {
|
||||||
|
abort(500, '更新失败');
|
||||||
|
}
|
||||||
|
return response([
|
||||||
|
'data' => true
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function cancel(Request $request)
|
||||||
|
{
|
||||||
|
$order = Order::where('trade_no', $request->input('trade_no'))
|
||||||
|
->first();
|
||||||
|
if (!$order) {
|
||||||
|
abort(500, '订单不存在');
|
||||||
|
}
|
||||||
|
if ($order->status !== 0) abort(500, '只能对待支付的订单进行操作');
|
||||||
|
|
||||||
|
$orderService = new OrderService($order);
|
||||||
|
if (!$orderService->cancel()) {
|
||||||
|
abort(500, '更新失败');
|
||||||
|
}
|
||||||
|
return response([
|
||||||
|
'data' => true
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
public function update(OrderUpdate $request)
|
public function update(OrderUpdate $request)
|
||||||
{
|
{
|
||||||
$params = $request->only([
|
$params = $request->only([
|
||||||
'status',
|
|
||||||
'commission_status'
|
'commission_status'
|
||||||
]);
|
]);
|
||||||
|
|
||||||
@ -76,16 +112,6 @@ class OrderController extends Controller
|
|||||||
abort(500, '订单不存在');
|
abort(500, '订单不存在');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isset($params['status']) && (int)$params['status'] === 2) {
|
|
||||||
$orderService = new OrderService($order);
|
|
||||||
if (!$orderService->cancel()) {
|
|
||||||
abort(500, '更新失败');
|
|
||||||
}
|
|
||||||
return response([
|
|
||||||
'data' => true
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$order->update($params);
|
$order->update($params);
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
@ -97,26 +123,6 @@ class OrderController extends Controller
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function repair(Request $request)
|
|
||||||
{
|
|
||||||
if (empty($request->input('trade_no'))) {
|
|
||||||
abort(500, '参数错误');
|
|
||||||
}
|
|
||||||
$order = Order::where('trade_no', $request->input('trade_no'))
|
|
||||||
->where('status', 0)
|
|
||||||
->first();
|
|
||||||
if (!$order) {
|
|
||||||
abort(500, '订单不存在或订单已支付');
|
|
||||||
}
|
|
||||||
$order->status = 1;
|
|
||||||
if (!$order->save()) {
|
|
||||||
abort(500, '保存失败');
|
|
||||||
}
|
|
||||||
return response([
|
|
||||||
'data' => true
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function assign(OrderAssign $request)
|
public function assign(OrderAssign $request)
|
||||||
{
|
{
|
||||||
$plan = Plan::find($request->input('plan_id'));
|
$plan = Plan::find($request->input('plan_id'));
|
||||||
@ -130,6 +136,11 @@ class OrderController extends Controller
|
|||||||
abort(500, '该订阅不存在');
|
abort(500, '该订阅不存在');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$userService = new UserService();
|
||||||
|
if ($userService->isNotCompleteOrderByUserId($user->id)) {
|
||||||
|
abort(500, '该用户还有待支付的订单,无法分配');
|
||||||
|
}
|
||||||
|
|
||||||
DB::beginTransaction();
|
DB::beginTransaction();
|
||||||
$order = new Order();
|
$order = new Order();
|
||||||
$orderService = new OrderService($order);
|
$orderService = new OrderService($order);
|
||||||
|
@ -42,6 +42,9 @@ class PaymentController extends Controller
|
|||||||
|
|
||||||
public function save(Request $request)
|
public function save(Request $request)
|
||||||
{
|
{
|
||||||
|
if (!config('v2board.app_url')) {
|
||||||
|
abort(500, '请在站点配置中配置站点地址');
|
||||||
|
}
|
||||||
if ($request->input('id')) {
|
if ($request->input('id')) {
|
||||||
$payment = Payment::find($request->input('id'));
|
$payment = Payment::find($request->input('id'));
|
||||||
if (!$payment) abort(500, '支付方式不存在');
|
if (!$payment) abort(500, '支付方式不存在');
|
||||||
@ -58,7 +61,7 @@ class PaymentController extends Controller
|
|||||||
'name' => $request->input('name'),
|
'name' => $request->input('name'),
|
||||||
'payment' => $request->input('payment'),
|
'payment' => $request->input('payment'),
|
||||||
'config' => $request->input('config'),
|
'config' => $request->input('config'),
|
||||||
'uuid' => Helper::guid()
|
'uuid' => Helper::randomChar(8)
|
||||||
])) {
|
])) {
|
||||||
abort(500, '保存失败');
|
abort(500, '保存失败');
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
namespace App\Http\Controllers\Admin\Server;
|
namespace App\Http\Controllers\Admin\Server;
|
||||||
|
|
||||||
use App\Models\Plan;
|
use App\Models\Plan;
|
||||||
use App\Models\Server;
|
use App\Models\ServerV2ray;
|
||||||
use App\Models\ServerGroup;
|
use App\Models\ServerGroup;
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
@ -50,10 +50,9 @@ class GroupController extends Controller
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$servers = Server::all();
|
$servers = ServerV2ray::all();
|
||||||
foreach ($servers as $server) {
|
foreach ($servers as $server) {
|
||||||
$groupId = json_decode($server->group_id);
|
if (in_array($request->input('id'), $server->group_id)) {
|
||||||
if (in_array($request->input('id'), $groupId)) {
|
|
||||||
abort(500, '该组已被节点所使用,无法删除');
|
abort(500, '该组已被节点所使用,无法删除');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
namespace App\Http\Controllers\Admin\Server;
|
namespace App\Http\Controllers\Admin\Server;
|
||||||
|
|
||||||
use App\Models\Server;
|
use App\Models\ServerV2ray;
|
||||||
use App\Models\ServerShadowsocks;
|
use App\Models\ServerShadowsocks;
|
||||||
use App\Models\ServerTrojan;
|
use App\Models\ServerTrojan;
|
||||||
use App\Services\ServerService;
|
use App\Services\ServerService;
|
||||||
@ -32,7 +32,7 @@ class ManageController extends Controller
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'v2ray':
|
case 'v2ray':
|
||||||
if (!Server::find($v['value'])->update(['sort' => $k + 1])) {
|
if (!ServerV2ray::find($v['value'])->update(['sort' => $k + 1])) {
|
||||||
DB::rollBack();
|
DB::rollBack();
|
||||||
abort(500, '保存失败');
|
abort(500, '保存失败');
|
||||||
}
|
}
|
||||||
|
@ -14,11 +14,6 @@ class ShadowsocksController extends Controller
|
|||||||
public function save(ServerShadowsocksSave $request)
|
public function save(ServerShadowsocksSave $request)
|
||||||
{
|
{
|
||||||
$params = $request->validated();
|
$params = $request->validated();
|
||||||
$params['group_id'] = json_encode($params['group_id']);
|
|
||||||
if (isset($params['tags'])) {
|
|
||||||
$params['tags'] = json_encode($params['tags']);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($request->input('id')) {
|
if ($request->input('id')) {
|
||||||
$server = ServerShadowsocks::find($request->input('id'));
|
$server = ServerShadowsocks::find($request->input('id'));
|
||||||
if (!$server) {
|
if (!$server) {
|
||||||
|
@ -14,11 +14,6 @@ class TrojanController extends Controller
|
|||||||
public function save(ServerTrojanSave $request)
|
public function save(ServerTrojanSave $request)
|
||||||
{
|
{
|
||||||
$params = $request->validated();
|
$params = $request->validated();
|
||||||
$params['group_id'] = json_encode($params['group_id']);
|
|
||||||
if (isset($params['tags'])) {
|
|
||||||
$params['tags'] = json_encode($params['tags']);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($request->input('id')) {
|
if ($request->input('id')) {
|
||||||
$server = ServerTrojan::find($request->input('id'));
|
$server = ServerTrojan::find($request->input('id'));
|
||||||
if (!$server) {
|
if (!$server) {
|
||||||
|
@ -7,44 +7,16 @@ use App\Http\Requests\Admin\ServerV2rayUpdate;
|
|||||||
use App\Services\ServerService;
|
use App\Services\ServerService;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use App\Http\Controllers\Controller;
|
use App\Http\Controllers\Controller;
|
||||||
use App\Models\Server;
|
use App\Models\ServerV2ray;
|
||||||
|
|
||||||
class V2rayController extends Controller
|
class V2rayController extends Controller
|
||||||
{
|
{
|
||||||
public function save(ServerV2raySave $request)
|
public function save(ServerV2raySave $request)
|
||||||
{
|
{
|
||||||
$params = $request->validated();
|
$params = $request->validated();
|
||||||
$params['group_id'] = json_encode($params['group_id']);
|
|
||||||
if (isset($params['tags'])) {
|
|
||||||
$params['tags'] = json_encode($params['tags']);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isset($params['dnsSettings'])) {
|
|
||||||
if (!is_object(json_decode($params['dnsSettings']))) {
|
|
||||||
abort(500, 'DNS规则配置格式不正确');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isset($params['ruleSettings'])) {
|
|
||||||
if (!is_object(json_decode($params['ruleSettings']))) {
|
|
||||||
abort(500, '审计规则配置格式不正确');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isset($params['networkSettings'])) {
|
|
||||||
if (!is_object(json_decode($params['networkSettings']))) {
|
|
||||||
abort(500, '传输协议配置格式不正确');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isset($params['tlsSettings'])) {
|
|
||||||
if (!is_object(json_decode($params['tlsSettings']))) {
|
|
||||||
abort(500, 'TLS配置格式不正确');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($request->input('id')) {
|
if ($request->input('id')) {
|
||||||
$server = Server::find($request->input('id'));
|
$server = ServerV2ray::find($request->input('id'));
|
||||||
if (!$server) {
|
if (!$server) {
|
||||||
abort(500, '服务器不存在');
|
abort(500, '服务器不存在');
|
||||||
}
|
}
|
||||||
@ -58,7 +30,7 @@ class V2rayController extends Controller
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!Server::create($params)) {
|
if (!ServerV2ray::create($params)) {
|
||||||
abort(500, '创建失败');
|
abort(500, '创建失败');
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -70,7 +42,7 @@ class V2rayController extends Controller
|
|||||||
public function drop(Request $request)
|
public function drop(Request $request)
|
||||||
{
|
{
|
||||||
if ($request->input('id')) {
|
if ($request->input('id')) {
|
||||||
$server = Server::find($request->input('id'));
|
$server = ServerV2ray::find($request->input('id'));
|
||||||
if (!$server) {
|
if (!$server) {
|
||||||
abort(500, '节点ID不存在');
|
abort(500, '节点ID不存在');
|
||||||
}
|
}
|
||||||
@ -86,7 +58,7 @@ class V2rayController extends Controller
|
|||||||
'show',
|
'show',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$server = Server::find($request->input('id'));
|
$server = ServerV2ray::find($request->input('id'));
|
||||||
|
|
||||||
if (!$server) {
|
if (!$server) {
|
||||||
abort(500, '该服务器不存在');
|
abort(500, '该服务器不存在');
|
||||||
@ -104,12 +76,12 @@ class V2rayController extends Controller
|
|||||||
|
|
||||||
public function copy(Request $request)
|
public function copy(Request $request)
|
||||||
{
|
{
|
||||||
$server = Server::find($request->input('id'));
|
$server = ServerV2ray::find($request->input('id'));
|
||||||
$server->show = 0;
|
$server->show = 0;
|
||||||
if (!$server) {
|
if (!$server) {
|
||||||
abort(500, '服务器不存在');
|
abort(500, '服务器不存在');
|
||||||
}
|
}
|
||||||
if (!Server::create($server->toArray())) {
|
if (!ServerV2ray::create($server->toArray())) {
|
||||||
abort(500, '复制失败');
|
abort(500, '复制失败');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@ use App\Services\ServerService;
|
|||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use App\Http\Controllers\Controller;
|
use App\Http\Controllers\Controller;
|
||||||
use App\Models\ServerGroup;
|
use App\Models\ServerGroup;
|
||||||
use App\Models\Server;
|
use App\Models\ServerV2ray;
|
||||||
use App\Models\Plan;
|
use App\Models\Plan;
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
use App\Models\Ticket;
|
use App\Models\Ticket;
|
||||||
@ -91,7 +91,7 @@ class StatController extends Controller
|
|||||||
{
|
{
|
||||||
$servers = [
|
$servers = [
|
||||||
'shadowsocks' => ServerShadowsocks::where('parent_id', null)->get()->toArray(),
|
'shadowsocks' => ServerShadowsocks::where('parent_id', null)->get()->toArray(),
|
||||||
'vmess' => Server::where('parent_id', null)->get()->toArray(),
|
'vmess' => ServerV2ray::where('parent_id', null)->get()->toArray(),
|
||||||
'trojan' => ServerTrojan::where('parent_id', null)->get()->toArray()
|
'trojan' => ServerTrojan::where('parent_id', null)->get()->toArray()
|
||||||
];
|
];
|
||||||
$timestamp = strtotime('-1 day', strtotime(date('Y-m-d')));
|
$timestamp = strtotime('-1 day', strtotime(date('Y-m-d')));
|
||||||
|
@ -68,7 +68,7 @@ class UserController extends Controller
|
|||||||
$res[$i]['plan_name'] = $plan[$k]['name'];
|
$res[$i]['plan_name'] = $plan[$k]['name'];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$res[$i]['subscribe_url'] = config('v2board.subscribe_url', config('v2board.app_url', env('APP_URL'))) . '/api/v1/client/subscribe?token=' . $res[$i]['token'];
|
$res[$i]['subscribe_url'] = Helper::getSubscribeHost() . '/api/v1/client/subscribe?token=' . $res[$i]['token'];
|
||||||
}
|
}
|
||||||
return response([
|
return response([
|
||||||
'data' => $res,
|
'data' => $res,
|
||||||
|
@ -7,7 +7,7 @@ use App\Services\ServerService;
|
|||||||
use App\Services\UserService;
|
use App\Services\UserService;
|
||||||
use App\Utils\Clash;
|
use App\Utils\Clash;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use App\Models\Server;
|
use App\Models\ServerV2ray;
|
||||||
use Illuminate\Support\Facades\File;
|
use Illuminate\Support\Facades\File;
|
||||||
use Symfony\Component\Yaml\Yaml;
|
use Symfony\Component\Yaml\Yaml;
|
||||||
|
|
||||||
|
@ -4,7 +4,7 @@ namespace App\Http\Controllers\Client\Protocols;
|
|||||||
|
|
||||||
class AnXray
|
class AnXray
|
||||||
{
|
{
|
||||||
public $flag = 'anxray';
|
public $flag = 'axxray';
|
||||||
private $servers;
|
private $servers;
|
||||||
private $user;
|
private $user;
|
||||||
|
|
||||||
@ -64,15 +64,21 @@ class AnXray
|
|||||||
"encryption" => "none",
|
"encryption" => "none",
|
||||||
"type" => urlencode($server['network']),
|
"type" => urlencode($server['network']),
|
||||||
"security" => $server['tls'] ? "tls" : "",
|
"security" => $server['tls'] ? "tls" : "",
|
||||||
"sni" => $server['tls'] ? urlencode(json_decode($server['tlsSettings'], true)['serverName']) : ""
|
|
||||||
];
|
];
|
||||||
|
if ($server['tls']) {
|
||||||
|
if ($server['tlsSettings']) {
|
||||||
|
$tlsSettings = $server['tlsSettings'];
|
||||||
|
if (isset($tlsSettings['serverName']) && !empty($tlsSettings['serverName']))
|
||||||
|
$config['sni'] = urlencode($tlsSettings['serverName']);
|
||||||
|
}
|
||||||
|
}
|
||||||
if ((string)$server['network'] === 'ws') {
|
if ((string)$server['network'] === 'ws') {
|
||||||
$wsSettings = json_decode($server['networkSettings'], true);
|
$wsSettings = $server['networkSettings'];
|
||||||
if (isset($wsSettings['path'])) $config['path'] = urlencode($wsSettings['path']);
|
if (isset($wsSettings['path'])) $config['path'] = urlencode($wsSettings['path']);
|
||||||
if (isset($wsSettings['headers']['Host'])) $config['host'] = urlencode($wsSettings['headers']['Host']);
|
if (isset($wsSettings['headers']['Host'])) $config['host'] = urlencode($wsSettings['headers']['Host']);
|
||||||
}
|
}
|
||||||
if ((string)$server['network'] === 'grpc') {
|
if ((string)$server['network'] === 'grpc') {
|
||||||
$grpcSettings = json_decode($server['networkSettings'], true);
|
$grpcSettings = $server['networkSettings'];
|
||||||
if (isset($grpcSettings['serviceName'])) $config['serviceName'] = urlencode($grpcSettings['serviceName']);
|
if (isset($grpcSettings['serviceName'])) $config['serviceName'] = urlencode($grpcSettings['serviceName']);
|
||||||
}
|
}
|
||||||
return "vmess://" . $uuid . "@" . $server['host'] . ":" . $server['port'] . "?" . http_build_query($config) . "#" . urlencode($server['name']) . "\r\n";
|
return "vmess://" . $uuid . "@" . $server['host'] . ":" . $server['port'] . "?" . http_build_query($config) . "#" . urlencode($server['name']) . "\r\n";
|
||||||
|
@ -20,7 +20,10 @@ class Clash
|
|||||||
{
|
{
|
||||||
$servers = $this->servers;
|
$servers = $this->servers;
|
||||||
$user = $this->user;
|
$user = $this->user;
|
||||||
|
$appName = config('v2board.app_name', 'V2Board');
|
||||||
header("subscription-userinfo: upload={$user['u']}; download={$user['d']}; total={$user['transfer_enable']}; expire={$user['expired_at']}");
|
header("subscription-userinfo: upload={$user['u']}; download={$user['d']}; total={$user['transfer_enable']}; expire={$user['expired_at']}");
|
||||||
|
header('profile-update-interval: 24');
|
||||||
|
header("content-disposition: filename={$appName}");
|
||||||
$defaultConfig = base_path() . '/resources/rules/default.clash.yaml';
|
$defaultConfig = base_path() . '/resources/rules/default.clash.yaml';
|
||||||
$customConfig = base_path() . '/resources/rules/custom.clash.yaml';
|
$customConfig = base_path() . '/resources/rules/custom.clash.yaml';
|
||||||
if (\File::exists($customConfig)) {
|
if (\File::exists($customConfig)) {
|
||||||
@ -51,6 +54,11 @@ class Clash
|
|||||||
if (!is_array($config['proxy-groups'][$k]['proxies'])) continue;
|
if (!is_array($config['proxy-groups'][$k]['proxies'])) continue;
|
||||||
$config['proxy-groups'][$k]['proxies'] = array_merge($config['proxy-groups'][$k]['proxies'], $proxies);
|
$config['proxy-groups'][$k]['proxies'] = array_merge($config['proxy-groups'][$k]['proxies'], $proxies);
|
||||||
}
|
}
|
||||||
|
// Force the current subscription domain to be a direct rule
|
||||||
|
$subsDomain = $_SERVER['SERVER_NAME'];
|
||||||
|
$subsDomainRule = "DOMAIN,{$subsDomain},DIRECT";
|
||||||
|
array_unshift($config['rules'], $subsDomainRule);
|
||||||
|
|
||||||
$yaml = Yaml::dump($config);
|
$yaml = Yaml::dump($config);
|
||||||
$yaml = str_replace('$app_name', config('v2board.app_name', 'V2Board'), $yaml);
|
$yaml = str_replace('$app_name', config('v2board.app_name', 'V2Board'), $yaml);
|
||||||
return $yaml;
|
return $yaml;
|
||||||
@ -84,7 +92,7 @@ class Clash
|
|||||||
if ($server['tls']) {
|
if ($server['tls']) {
|
||||||
$array['tls'] = true;
|
$array['tls'] = true;
|
||||||
if ($server['tlsSettings']) {
|
if ($server['tlsSettings']) {
|
||||||
$tlsSettings = json_decode($server['tlsSettings'], true);
|
$tlsSettings = $server['tlsSettings'];
|
||||||
if (isset($tlsSettings['allowInsecure']) && !empty($tlsSettings['allowInsecure']))
|
if (isset($tlsSettings['allowInsecure']) && !empty($tlsSettings['allowInsecure']))
|
||||||
$array['skip-cert-verify'] = ($tlsSettings['allowInsecure'] ? true : false);
|
$array['skip-cert-verify'] = ($tlsSettings['allowInsecure'] ? true : false);
|
||||||
if (isset($tlsSettings['serverName']) && !empty($tlsSettings['serverName']))
|
if (isset($tlsSettings['serverName']) && !empty($tlsSettings['serverName']))
|
||||||
@ -94,7 +102,7 @@ class Clash
|
|||||||
if ($server['network'] === 'ws') {
|
if ($server['network'] === 'ws') {
|
||||||
$array['network'] = 'ws';
|
$array['network'] = 'ws';
|
||||||
if ($server['networkSettings']) {
|
if ($server['networkSettings']) {
|
||||||
$wsSettings = json_decode($server['networkSettings'], true);
|
$wsSettings = $server['networkSettings'];
|
||||||
if (isset($wsSettings['path']) && !empty($wsSettings['path']))
|
if (isset($wsSettings['path']) && !empty($wsSettings['path']))
|
||||||
$array['ws-path'] = $wsSettings['path'];
|
$array['ws-path'] = $wsSettings['path'];
|
||||||
if (isset($wsSettings['headers']['Host']) && !empty($wsSettings['headers']['Host']))
|
if (isset($wsSettings['headers']['Host']) && !empty($wsSettings['headers']['Host']))
|
||||||
@ -104,7 +112,7 @@ class Clash
|
|||||||
if ($server['network'] === 'grpc') {
|
if ($server['network'] === 'grpc') {
|
||||||
$array['network'] = 'grpc';
|
$array['network'] = 'grpc';
|
||||||
if ($server['networkSettings']) {
|
if ($server['networkSettings']) {
|
||||||
$grpcObject = json_decode($server['networkSettings'], true);
|
$grpcObject = $server['networkSettings'];
|
||||||
$array['grpc-opts'] = [];
|
$array['grpc-opts'] = [];
|
||||||
$array['grpc-opts']['grpc-service-name'] = $grpcObject['serviceName'];
|
$array['grpc-opts']['grpc-service-name'] = $grpcObject['serviceName'];
|
||||||
}
|
}
|
||||||
|
@ -63,19 +63,19 @@ class Passwall
|
|||||||
];
|
];
|
||||||
if ($server['tls']) {
|
if ($server['tls']) {
|
||||||
if ($server['tlsSettings']) {
|
if ($server['tlsSettings']) {
|
||||||
$tlsSettings = json_decode($server['tlsSettings'], true);
|
$tlsSettings = $server['tlsSettings'];
|
||||||
if (isset($tlsSettings['serverName']) && !empty($tlsSettings['serverName']))
|
if (isset($tlsSettings['serverName']) && !empty($tlsSettings['serverName']))
|
||||||
$config['sni'] = $tlsSettings['serverName'];
|
$config['sni'] = $tlsSettings['serverName'];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ((string)$server['network'] === 'ws') {
|
if ((string)$server['network'] === 'ws') {
|
||||||
$wsSettings = json_decode($server['networkSettings'], true);
|
$wsSettings = $server['networkSettings'];
|
||||||
if (isset($wsSettings['path'])) $config['path'] = $wsSettings['path'];
|
if (isset($wsSettings['path'])) $config['path'] = $wsSettings['path'];
|
||||||
if (isset($wsSettings['headers']['Host'])) $config['host'] = $wsSettings['headers']['Host'];
|
if (isset($wsSettings['headers']['Host'])) $config['host'] = $wsSettings['headers']['Host'];
|
||||||
}
|
}
|
||||||
if ((string)$server['network'] === 'grpc') {
|
if ((string)$server['network'] === 'grpc') {
|
||||||
$grpcSettings = json_decode($server['networkSettings'], true);
|
$grpcSettings = $server['networkSettings'];
|
||||||
if (isset($grpcSettings['path'])) $config['path'] = $grpcSettings['serviceName'];
|
if (isset($grpcSettings['serviceName'])) $config['path'] = $grpcSettings['serviceName'];
|
||||||
}
|
}
|
||||||
return "vmess://" . base64_encode(json_encode($config)) . "\r\n";
|
return "vmess://" . base64_encode(json_encode($config)) . "\r\n";
|
||||||
}
|
}
|
||||||
|
@ -66,7 +66,7 @@ class QuantumultX
|
|||||||
if ($server['network'] === 'tcp')
|
if ($server['network'] === 'tcp')
|
||||||
array_push($config, 'obfs=over-tls');
|
array_push($config, 'obfs=over-tls');
|
||||||
if ($server['tlsSettings']) {
|
if ($server['tlsSettings']) {
|
||||||
$tlsSettings = json_decode($server['tlsSettings'], true);
|
$tlsSettings = $server['tlsSettings'];
|
||||||
if (isset($tlsSettings['allowInsecure']) && !empty($tlsSettings['allowInsecure']))
|
if (isset($tlsSettings['allowInsecure']) && !empty($tlsSettings['allowInsecure']))
|
||||||
array_push($config, 'tls-verification=' . ($tlsSettings['allowInsecure'] ? 'false' : 'true'));
|
array_push($config, 'tls-verification=' . ($tlsSettings['allowInsecure'] ? 'false' : 'true'));
|
||||||
if (isset($tlsSettings['serverName']) && !empty($tlsSettings['serverName']))
|
if (isset($tlsSettings['serverName']) && !empty($tlsSettings['serverName']))
|
||||||
@ -79,7 +79,7 @@ class QuantumultX
|
|||||||
else
|
else
|
||||||
array_push($config, 'obfs=ws');
|
array_push($config, 'obfs=ws');
|
||||||
if ($server['networkSettings']) {
|
if ($server['networkSettings']) {
|
||||||
$wsSettings = json_decode($server['networkSettings'], true);
|
$wsSettings = $server['networkSettings'];
|
||||||
if (isset($wsSettings['path']) && !empty($wsSettings['path']))
|
if (isset($wsSettings['path']) && !empty($wsSettings['path']))
|
||||||
array_push($config, "obfs-uri={$wsSettings['path']}");
|
array_push($config, "obfs-uri={$wsSettings['path']}");
|
||||||
if (isset($wsSettings['headers']['Host']) && !empty($wsSettings['headers']['Host']) && !isset($host))
|
if (isset($wsSettings['headers']['Host']) && !empty($wsSettings['headers']['Host']) && !isset($host))
|
||||||
|
@ -63,19 +63,19 @@ class SSRPlus
|
|||||||
];
|
];
|
||||||
if ($server['tls']) {
|
if ($server['tls']) {
|
||||||
if ($server['tlsSettings']) {
|
if ($server['tlsSettings']) {
|
||||||
$tlsSettings = json_decode($server['tlsSettings'], true);
|
$tlsSettings = $server['tlsSettings'];
|
||||||
if (isset($tlsSettings['serverName']) && !empty($tlsSettings['serverName']))
|
if (isset($tlsSettings['serverName']) && !empty($tlsSettings['serverName']))
|
||||||
$config['sni'] = $tlsSettings['serverName'];
|
$config['sni'] = $tlsSettings['serverName'];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ((string)$server['network'] === 'ws') {
|
if ((string)$server['network'] === 'ws') {
|
||||||
$wsSettings = json_decode($server['networkSettings'], true);
|
$wsSettings = $server['networkSettings'];
|
||||||
if (isset($wsSettings['path'])) $config['path'] = $wsSettings['path'];
|
if (isset($wsSettings['path'])) $config['path'] = $wsSettings['path'];
|
||||||
if (isset($wsSettings['headers']['Host'])) $config['host'] = $wsSettings['headers']['Host'];
|
if (isset($wsSettings['headers']['Host'])) $config['host'] = $wsSettings['headers']['Host'];
|
||||||
}
|
}
|
||||||
if ((string)$server['network'] === 'grpc') {
|
if ((string)$server['network'] === 'grpc') {
|
||||||
$grpcSettings = json_decode($server['networkSettings'], true);
|
$grpcSettings = $server['networkSettings'];
|
||||||
if (isset($grpcSettings['path'])) $config['path'] = $grpcSettings['serviceName'];
|
if (isset($grpcSettings['serviceName'])) $config['path'] = $grpcSettings['serviceName'];
|
||||||
}
|
}
|
||||||
return "vmess://" . base64_encode(json_encode($config)) . "\r\n";
|
return "vmess://" . base64_encode(json_encode($config)) . "\r\n";
|
||||||
}
|
}
|
||||||
|
@ -63,7 +63,7 @@ class Shadowrocket
|
|||||||
if ($server['tls']) {
|
if ($server['tls']) {
|
||||||
$config['tls'] = 1;
|
$config['tls'] = 1;
|
||||||
if ($server['tlsSettings']) {
|
if ($server['tlsSettings']) {
|
||||||
$tlsSettings = json_decode($server['tlsSettings'], true);
|
$tlsSettings = $server['tlsSettings'];
|
||||||
if (isset($tlsSettings['allowInsecure']) && !empty($tlsSettings['allowInsecure']))
|
if (isset($tlsSettings['allowInsecure']) && !empty($tlsSettings['allowInsecure']))
|
||||||
$config['allowInsecure'] = (int)$tlsSettings['allowInsecure'];
|
$config['allowInsecure'] = (int)$tlsSettings['allowInsecure'];
|
||||||
if (isset($tlsSettings['serverName']) && !empty($tlsSettings['serverName']))
|
if (isset($tlsSettings['serverName']) && !empty($tlsSettings['serverName']))
|
||||||
@ -73,7 +73,7 @@ class Shadowrocket
|
|||||||
if ($server['network'] === 'ws') {
|
if ($server['network'] === 'ws') {
|
||||||
$config['obfs'] = "websocket";
|
$config['obfs'] = "websocket";
|
||||||
if ($server['networkSettings']) {
|
if ($server['networkSettings']) {
|
||||||
$wsSettings = json_decode($server['networkSettings'], true);
|
$wsSettings = $server['networkSettings'];
|
||||||
if (isset($wsSettings['path']) && !empty($wsSettings['path']))
|
if (isset($wsSettings['path']) && !empty($wsSettings['path']))
|
||||||
$config['path'] = $wsSettings['path'];
|
$config['path'] = $wsSettings['path'];
|
||||||
if (isset($wsSettings['headers']['Host']) && !empty($wsSettings['headers']['Host']))
|
if (isset($wsSettings['headers']['Host']) && !empty($wsSettings['headers']['Host']))
|
||||||
@ -83,7 +83,7 @@ class Shadowrocket
|
|||||||
if ($server['network'] === 'grpc') {
|
if ($server['network'] === 'grpc') {
|
||||||
$config['obfs'] = "grpc";
|
$config['obfs'] = "grpc";
|
||||||
if ($server['networkSettings']) {
|
if ($server['networkSettings']) {
|
||||||
$grpcSettings = json_decode($server['networkSettings'], true);
|
$grpcSettings = $server['networkSettings'];
|
||||||
if (isset($grpcSettings['serviceName']) && !empty($grpcSettings['serviceName']))
|
if (isset($grpcSettings['serviceName']) && !empty($grpcSettings['serviceName']))
|
||||||
$config['path'] = $grpcSettings['serviceName'];
|
$config['path'] = $grpcSettings['serviceName'];
|
||||||
}
|
}
|
||||||
|
@ -26,13 +26,19 @@ class Surfboard
|
|||||||
foreach ($servers as $item) {
|
foreach ($servers as $item) {
|
||||||
if ($item['type'] === 'shadowsocks') {
|
if ($item['type'] === 'shadowsocks') {
|
||||||
// [Proxy]
|
// [Proxy]
|
||||||
$proxies .= Surfboard::buildShadowsocks($user['uuid'], $item);
|
$proxies .= self::buildShadowsocks($user['uuid'], $item);
|
||||||
// [Proxy Group]
|
// [Proxy Group]
|
||||||
$proxyGroup .= $item['name'] . ', ';
|
$proxyGroup .= $item['name'] . ', ';
|
||||||
}
|
}
|
||||||
if ($item['type'] === 'v2ray') {
|
if ($item['type'] === 'v2ray') {
|
||||||
// [Proxy]
|
// [Proxy]
|
||||||
$proxies .= Surfboard::buildVmess($user['uuid'], $item);
|
$proxies .= self::buildVmess($user['uuid'], $item);
|
||||||
|
// [Proxy Group]
|
||||||
|
$proxyGroup .= $item['name'] . ', ';
|
||||||
|
}
|
||||||
|
if ($item['type'] === 'trojan') {
|
||||||
|
// [Proxy]
|
||||||
|
$proxies .= self::buildTrojan($user['uuid'], $item);
|
||||||
// [Proxy Group]
|
// [Proxy Group]
|
||||||
$proxyGroup .= $item['name'] . ', ';
|
$proxyGroup .= $item['name'] . ', ';
|
||||||
}
|
}
|
||||||
@ -48,8 +54,10 @@ class Surfboard
|
|||||||
|
|
||||||
// Subscription link
|
// Subscription link
|
||||||
$subsURL = config('v2board.subscribe_url', config('v2board.app_url', env('APP_URL'))) . '/api/v1/client/subscribe?token=' . $user['token'];
|
$subsURL = config('v2board.subscribe_url', config('v2board.app_url', env('APP_URL'))) . '/api/v1/client/subscribe?token=' . $user['token'];
|
||||||
|
$subsDomain = $_SERVER['SERVER_NAME'];
|
||||||
|
|
||||||
$config = str_replace('$subs_link', $subsURL, $config);
|
$config = str_replace('$subs_link', $subsURL, $config);
|
||||||
|
$config = str_replace('$subs_domain', $subsDomain, $config);
|
||||||
$config = str_replace('$proxies', $proxies, $config);
|
$config = str_replace('$proxies', $proxies, $config);
|
||||||
$config = str_replace('$proxy_group', rtrim($proxyGroup, ', '), $config);
|
$config = str_replace('$proxy_group', rtrim($proxyGroup, ', '), $config);
|
||||||
return $config;
|
return $config;
|
||||||
@ -88,7 +96,7 @@ class Surfboard
|
|||||||
if ($server['tls']) {
|
if ($server['tls']) {
|
||||||
array_push($config, 'tls=true');
|
array_push($config, 'tls=true');
|
||||||
if ($server['tlsSettings']) {
|
if ($server['tlsSettings']) {
|
||||||
$tlsSettings = json_decode($server['tlsSettings'], true);
|
$tlsSettings = $server['tlsSettings'];
|
||||||
if (isset($tlsSettings['allowInsecure']) && !empty($tlsSettings['allowInsecure']))
|
if (isset($tlsSettings['allowInsecure']) && !empty($tlsSettings['allowInsecure']))
|
||||||
array_push($config, 'skip-cert-verify=' . ($tlsSettings['allowInsecure'] ? 'true' : 'false'));
|
array_push($config, 'skip-cert-verify=' . ($tlsSettings['allowInsecure'] ? 'true' : 'false'));
|
||||||
if (isset($tlsSettings['serverName']) && !empty($tlsSettings['serverName']))
|
if (isset($tlsSettings['serverName']) && !empty($tlsSettings['serverName']))
|
||||||
@ -98,7 +106,7 @@ class Surfboard
|
|||||||
if ($server['network'] === 'ws') {
|
if ($server['network'] === 'ws') {
|
||||||
array_push($config, 'ws=true');
|
array_push($config, 'ws=true');
|
||||||
if ($server['networkSettings']) {
|
if ($server['networkSettings']) {
|
||||||
$wsSettings = json_decode($server['networkSettings'], true);
|
$wsSettings = $server['networkSettings'];
|
||||||
if (isset($wsSettings['path']) && !empty($wsSettings['path']))
|
if (isset($wsSettings['path']) && !empty($wsSettings['path']))
|
||||||
array_push($config, "ws-path={$wsSettings['path']}");
|
array_push($config, "ws-path={$wsSettings['path']}");
|
||||||
if (isset($wsSettings['headers']['Host']) && !empty($wsSettings['headers']['Host']))
|
if (isset($wsSettings['headers']['Host']) && !empty($wsSettings['headers']['Host']))
|
||||||
@ -110,4 +118,24 @@ class Surfboard
|
|||||||
$uri .= "\r\n";
|
$uri .= "\r\n";
|
||||||
return $uri;
|
return $uri;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static function buildTrojan($password, $server)
|
||||||
|
{
|
||||||
|
$config = [
|
||||||
|
"{$server['name']}=trojan",
|
||||||
|
"{$server['host']}",
|
||||||
|
"{$server['port']}",
|
||||||
|
"password={$password}",
|
||||||
|
$server['server_name'] ? "sni={$server['server_name']}" : "",
|
||||||
|
'tfo=true',
|
||||||
|
'udp-relay=true'
|
||||||
|
];
|
||||||
|
if (!empty($server['allow_insecure'])) {
|
||||||
|
array_push($config, $server['allow_insecure'] ? 'skip-cert-verify=true' : 'skip-cert-verify=false');
|
||||||
|
}
|
||||||
|
$config = array_filter($config);
|
||||||
|
$uri = implode(',', $config);
|
||||||
|
$uri .= "\r\n";
|
||||||
|
return $uri;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -53,8 +53,10 @@ class Surge
|
|||||||
|
|
||||||
// Subscription link
|
// Subscription link
|
||||||
$subsURL = config('v2board.subscribe_url', config('v2board.app_url', env('APP_URL'))) . '/api/v1/client/subscribe?token=' . $user['token'];
|
$subsURL = config('v2board.subscribe_url', config('v2board.app_url', env('APP_URL'))) . '/api/v1/client/subscribe?token=' . $user['token'];
|
||||||
|
$subsDomain = $_SERVER['SERVER_NAME'];
|
||||||
|
|
||||||
$config = str_replace('$subs_link', $subsURL, $config);
|
$config = str_replace('$subs_link', $subsURL, $config);
|
||||||
|
$config = str_replace('$subs_domain', $subsDomain, $config);
|
||||||
$config = str_replace('$proxies', $proxies, $config);
|
$config = str_replace('$proxies', $proxies, $config);
|
||||||
$config = str_replace('$proxy_group', rtrim($proxyGroup, ', '), $config);
|
$config = str_replace('$proxy_group', rtrim($proxyGroup, ', '), $config);
|
||||||
return $config;
|
return $config;
|
||||||
@ -92,7 +94,7 @@ class Surge
|
|||||||
if ($server['tls']) {
|
if ($server['tls']) {
|
||||||
array_push($config, 'tls=true');
|
array_push($config, 'tls=true');
|
||||||
if ($server['tlsSettings']) {
|
if ($server['tlsSettings']) {
|
||||||
$tlsSettings = json_decode($server['tlsSettings'], true);
|
$tlsSettings = $server['tlsSettings'];
|
||||||
if (isset($tlsSettings['allowInsecure']) && !empty($tlsSettings['allowInsecure']))
|
if (isset($tlsSettings['allowInsecure']) && !empty($tlsSettings['allowInsecure']))
|
||||||
array_push($config, 'skip-cert-verify=' . ($tlsSettings['allowInsecure'] ? 'true' : 'false'));
|
array_push($config, 'skip-cert-verify=' . ($tlsSettings['allowInsecure'] ? 'true' : 'false'));
|
||||||
if (isset($tlsSettings['serverName']) && !empty($tlsSettings['serverName']))
|
if (isset($tlsSettings['serverName']) && !empty($tlsSettings['serverName']))
|
||||||
@ -102,7 +104,7 @@ class Surge
|
|||||||
if ($server['network'] === 'ws') {
|
if ($server['network'] === 'ws') {
|
||||||
array_push($config, 'ws=true');
|
array_push($config, 'ws=true');
|
||||||
if ($server['networkSettings']) {
|
if ($server['networkSettings']) {
|
||||||
$wsSettings = json_decode($server['networkSettings'], true);
|
$wsSettings = $server['networkSettings'];
|
||||||
if (isset($wsSettings['path']) && !empty($wsSettings['path']))
|
if (isset($wsSettings['path']) && !empty($wsSettings['path']))
|
||||||
array_push($config, "ws-path={$wsSettings['path']}");
|
array_push($config, "ws-path={$wsSettings['path']}");
|
||||||
if (isset($wsSettings['headers']['Host']) && !empty($wsSettings['headers']['Host']))
|
if (isset($wsSettings['headers']['Host']) && !empty($wsSettings['headers']['Host']))
|
||||||
|
@ -63,19 +63,19 @@ class V2rayN
|
|||||||
];
|
];
|
||||||
if ($server['tls']) {
|
if ($server['tls']) {
|
||||||
if ($server['tlsSettings']) {
|
if ($server['tlsSettings']) {
|
||||||
$tlsSettings = json_decode($server['tlsSettings'], true);
|
$tlsSettings = $server['tlsSettings'];
|
||||||
if (isset($tlsSettings['serverName']) && !empty($tlsSettings['serverName']))
|
if (isset($tlsSettings['serverName']) && !empty($tlsSettings['serverName']))
|
||||||
$config['sni'] = $tlsSettings['serverName'];
|
$config['sni'] = $tlsSettings['serverName'];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ((string)$server['network'] === 'ws') {
|
if ((string)$server['network'] === 'ws') {
|
||||||
$wsSettings = json_decode($server['networkSettings'], true);
|
$wsSettings = $server['networkSettings'];
|
||||||
if (isset($wsSettings['path'])) $config['path'] = $wsSettings['path'];
|
if (isset($wsSettings['path'])) $config['path'] = $wsSettings['path'];
|
||||||
if (isset($wsSettings['headers']['Host'])) $config['host'] = $wsSettings['headers']['Host'];
|
if (isset($wsSettings['headers']['Host'])) $config['host'] = $wsSettings['headers']['Host'];
|
||||||
}
|
}
|
||||||
if ((string)$server['network'] === 'grpc') {
|
if ((string)$server['network'] === 'grpc') {
|
||||||
$grpcSettings = json_decode($server['networkSettings'], true);
|
$grpcSettings = $server['networkSettings'];
|
||||||
if (isset($grpcSettings['path'])) $config['path'] = $grpcSettings['serviceName'];
|
if (isset($grpcSettings['serviceName'])) $config['path'] = $grpcSettings['serviceName'];
|
||||||
}
|
}
|
||||||
return "vmess://" . base64_encode(json_encode($config)) . "\r\n";
|
return "vmess://" . base64_encode(json_encode($config)) . "\r\n";
|
||||||
}
|
}
|
||||||
|
@ -63,19 +63,19 @@ class V2rayNG
|
|||||||
];
|
];
|
||||||
if ($server['tls']) {
|
if ($server['tls']) {
|
||||||
if ($server['tlsSettings']) {
|
if ($server['tlsSettings']) {
|
||||||
$tlsSettings = json_decode($server['tlsSettings'], true);
|
$tlsSettings = $server['tlsSettings'];
|
||||||
if (isset($tlsSettings['serverName']) && !empty($tlsSettings['serverName']))
|
if (isset($tlsSettings['serverName']) && !empty($tlsSettings['serverName']))
|
||||||
$config['sni'] = $tlsSettings['serverName'];
|
$config['sni'] = $tlsSettings['serverName'];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ((string)$server['network'] === 'ws') {
|
if ((string)$server['network'] === 'ws') {
|
||||||
$wsSettings = json_decode($server['networkSettings'], true);
|
$wsSettings = $server['networkSettings'];
|
||||||
if (isset($wsSettings['path'])) $config['path'] = $wsSettings['path'];
|
if (isset($wsSettings['path'])) $config['path'] = $wsSettings['path'];
|
||||||
if (isset($wsSettings['headers']['Host'])) $config['host'] = $wsSettings['headers']['Host'];
|
if (isset($wsSettings['headers']['Host'])) $config['host'] = $wsSettings['headers']['Host'];
|
||||||
}
|
}
|
||||||
if ((string)$server['network'] === 'grpc') {
|
if ((string)$server['network'] === 'grpc') {
|
||||||
$grpcSettings = json_decode($server['networkSettings'], true);
|
$grpcSettings = $server['networkSettings'];
|
||||||
if (isset($grpcSettings['path'])) $config['path'] = $grpcSettings['serviceName'];
|
if (isset($grpcSettings['serviceName'])) $config['path'] = $grpcSettings['serviceName'];
|
||||||
}
|
}
|
||||||
return "vmess://" . base64_encode(json_encode($config)) . "\r\n";
|
return "vmess://" . base64_encode(json_encode($config)) . "\r\n";
|
||||||
}
|
}
|
||||||
|
@ -34,7 +34,7 @@ class PaymentController extends Controller
|
|||||||
}
|
}
|
||||||
if ($order->status === 1) return true;
|
if ($order->status === 1) return true;
|
||||||
$orderService = new OrderService($order);
|
$orderService = new OrderService($order);
|
||||||
if (!$orderService->success($callbackNo)) {
|
if (!$orderService->paid($callbackNo)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
$telegramService = new TelegramService();
|
$telegramService = new TelegramService();
|
||||||
|
@ -102,10 +102,15 @@ class AuthController extends Controller
|
|||||||
if ((int)config('v2board.email_verify', 0)) {
|
if ((int)config('v2board.email_verify', 0)) {
|
||||||
Cache::forget(CacheKey::get('EMAIL_VERIFY_CODE', $request->input('email')));
|
Cache::forget(CacheKey::get('EMAIL_VERIFY_CODE', $request->input('email')));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$data = [
|
||||||
|
'token' => $user->token,
|
||||||
|
'auth_data' => base64_encode("{$user->email}:{$user->password}")
|
||||||
|
];
|
||||||
$request->session()->put('email', $user->email);
|
$request->session()->put('email', $user->email);
|
||||||
$request->session()->put('id', $user->id);
|
$request->session()->put('id', $user->id);
|
||||||
return response()->json([
|
return response()->json([
|
||||||
'data' => true
|
'data' => $data
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -120,6 +125,7 @@ class AuthController extends Controller
|
|||||||
}
|
}
|
||||||
if (!Helper::multiPasswordVerify(
|
if (!Helper::multiPasswordVerify(
|
||||||
$user->password_algo,
|
$user->password_algo,
|
||||||
|
$user->password_salt,
|
||||||
$password,
|
$password,
|
||||||
$user->password)
|
$user->password)
|
||||||
) {
|
) {
|
||||||
@ -250,6 +256,7 @@ class AuthController extends Controller
|
|||||||
}
|
}
|
||||||
$user->password = password_hash($request->input('password'), PASSWORD_DEFAULT);
|
$user->password = password_hash($request->input('password'), PASSWORD_DEFAULT);
|
||||||
$user->password_algo = NULL;
|
$user->password_algo = NULL;
|
||||||
|
$user->password_salt = NULL;
|
||||||
if (!$user->save()) {
|
if (!$user->save()) {
|
||||||
abort(500, __('Reset failed'));
|
abort(500, __('Reset failed'));
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,7 @@ use App\Utils\CacheKey;
|
|||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use App\Http\Controllers\Controller;
|
use App\Http\Controllers\Controller;
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
use App\Models\Server;
|
use App\Models\ServerV2ray;
|
||||||
use App\Models\ServerLog;
|
use App\Models\ServerLog;
|
||||||
use Illuminate\Support\Facades\DB;
|
use Illuminate\Support\Facades\DB;
|
||||||
use Illuminate\Support\Facades\Log;
|
use Illuminate\Support\Facades\Log;
|
||||||
@ -35,13 +35,13 @@ class DeepbworkController extends Controller
|
|||||||
public function user(Request $request)
|
public function user(Request $request)
|
||||||
{
|
{
|
||||||
$nodeId = $request->input('node_id');
|
$nodeId = $request->input('node_id');
|
||||||
$server = Server::find($nodeId);
|
$server = ServerV2ray::find($nodeId);
|
||||||
if (!$server) {
|
if (!$server) {
|
||||||
abort(500, 'fail');
|
abort(500, 'fail');
|
||||||
}
|
}
|
||||||
Cache::put(CacheKey::get('SERVER_V2RAY_LAST_CHECK_AT', $server->id), time(), 3600);
|
Cache::put(CacheKey::get('SERVER_V2RAY_LAST_CHECK_AT', $server->id), time(), 3600);
|
||||||
$serverService = new ServerService();
|
$serverService = new ServerService();
|
||||||
$users = $serverService->getAvailableUsers(json_decode($server->group_id));
|
$users = $serverService->getAvailableUsers($server->group_id);
|
||||||
$result = [];
|
$result = [];
|
||||||
foreach ($users as $user) {
|
foreach ($users as $user) {
|
||||||
$user->v2ray_user = [
|
$user->v2ray_user = [
|
||||||
@ -64,7 +64,7 @@ class DeepbworkController extends Controller
|
|||||||
public function submit(Request $request)
|
public function submit(Request $request)
|
||||||
{
|
{
|
||||||
// Log::info('serverSubmitData:' . $request->input('node_id') . ':' . file_get_contents('php://input'));
|
// Log::info('serverSubmitData:' . $request->input('node_id') . ':' . file_get_contents('php://input'));
|
||||||
$server = Server::find($request->input('node_id'));
|
$server = ServerV2ray::find($request->input('node_id'));
|
||||||
if (!$server) {
|
if (!$server) {
|
||||||
return response([
|
return response([
|
||||||
'ret' => 0,
|
'ret' => 0,
|
||||||
@ -76,23 +76,11 @@ class DeepbworkController extends Controller
|
|||||||
Cache::put(CacheKey::get('SERVER_V2RAY_ONLINE_USER', $server->id), count($data), 3600);
|
Cache::put(CacheKey::get('SERVER_V2RAY_ONLINE_USER', $server->id), count($data), 3600);
|
||||||
Cache::put(CacheKey::get('SERVER_V2RAY_LAST_PUSH_AT', $server->id), time(), 3600);
|
Cache::put(CacheKey::get('SERVER_V2RAY_LAST_PUSH_AT', $server->id), time(), 3600);
|
||||||
$userService = new UserService();
|
$userService = new UserService();
|
||||||
DB::beginTransaction();
|
foreach ($data as $item) {
|
||||||
try {
|
$u = $item['u'] * $server->rate;
|
||||||
foreach ($data as $item) {
|
$d = $item['d'] * $server->rate;
|
||||||
$u = $item['u'] * $server->rate;
|
$userService->trafficFetch($u, $d, $item['user_id'], $server, 'vmess');
|
||||||
$d = $item['d'] * $server->rate;
|
|
||||||
if (!$userService->trafficFetch($u, $d, $item['user_id'], $server, 'vmess')) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (\Exception $e) {
|
|
||||||
DB::rollBack();
|
|
||||||
return response([
|
|
||||||
'ret' => 0,
|
|
||||||
'msg' => 'user fetch fail'
|
|
||||||
]);
|
|
||||||
}
|
}
|
||||||
DB::commit();
|
|
||||||
|
|
||||||
return response([
|
return response([
|
||||||
'ret' => 1,
|
'ret' => 1,
|
||||||
|
@ -1,158 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Http\Controllers\Server;
|
|
||||||
|
|
||||||
use App\Services\ServerService;
|
|
||||||
use App\Services\UserService;
|
|
||||||
use App\Utils\CacheKey;
|
|
||||||
use Illuminate\Http\Request;
|
|
||||||
use App\Http\Controllers\Controller;
|
|
||||||
use App\Models\User;
|
|
||||||
use App\Models\Plan;
|
|
||||||
use App\Models\Server;
|
|
||||||
use App\Models\ServerLog;
|
|
||||||
use Illuminate\Support\Facades\Log;
|
|
||||||
use Illuminate\Support\Facades\Cache;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* V2ray Poseidon
|
|
||||||
* Github: https://github.com/ColetteContreras/trojan-poseidon
|
|
||||||
*/
|
|
||||||
class PoseidonController extends Controller
|
|
||||||
{
|
|
||||||
public $poseidonVersion;
|
|
||||||
|
|
||||||
public function __construct(Request $request)
|
|
||||||
{
|
|
||||||
$this->poseidonVersion = $request->input('poseidon_version');
|
|
||||||
}
|
|
||||||
|
|
||||||
// 后端获取用户
|
|
||||||
public function user(Request $request)
|
|
||||||
{
|
|
||||||
if ($r = $this->verifyToken($request)) { return $r; }
|
|
||||||
|
|
||||||
$nodeId = $request->input('node_id');
|
|
||||||
$server = Server::find($nodeId);
|
|
||||||
if (!$server) {
|
|
||||||
return $this->error("server could not be found", 404);
|
|
||||||
}
|
|
||||||
Cache::put(CacheKey::get('SERVER_V2RAY_LAST_CHECK_AT', $server->id), time(), 3600);
|
|
||||||
$serverService = new ServerService();
|
|
||||||
$users = $serverService->getAvailableUsers(json_decode($server->group_id));
|
|
||||||
$result = [];
|
|
||||||
foreach ($users as $user) {
|
|
||||||
$user->v2ray_user = [
|
|
||||||
"uuid" => $user->uuid,
|
|
||||||
"email" => sprintf("%s@v2board.user", $user->uuid),
|
|
||||||
"alter_id" => $server->alter_id,
|
|
||||||
"level" => 0,
|
|
||||||
];
|
|
||||||
unset($user['uuid']);
|
|
||||||
unset($user['email']);
|
|
||||||
array_push($result, $user);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this->success($result);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 后端提交数据
|
|
||||||
public function submit(Request $request)
|
|
||||||
{
|
|
||||||
if ($r = $this->verifyToken($request)) { return $r; }
|
|
||||||
$server = Server::find($request->input('node_id'));
|
|
||||||
if (!$server) {
|
|
||||||
return $this->error("server could not be found", 404);
|
|
||||||
}
|
|
||||||
$data = file_get_contents('php://input');
|
|
||||||
$data = json_decode($data, true);
|
|
||||||
Cache::put(CacheKey::get('SERVER_V2RAY_ONLINE_USER', $server->id), count($data), 3600);
|
|
||||||
Cache::put(CacheKey::get('SERVER_V2RAY_LAST_PUSH_AT', $server->id), time(), 3600);
|
|
||||||
$userService = new UserService();
|
|
||||||
foreach ($data as $item) {
|
|
||||||
$u = $item['u'] * $server->rate;
|
|
||||||
$d = $item['d'] * $server->rate;
|
|
||||||
if (!$userService->trafficFetch($u, $d, $item['user_id'], $server, 'vmess')) {
|
|
||||||
return $this->error("user fetch fail", 500);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this->success('');
|
|
||||||
}
|
|
||||||
|
|
||||||
// 后端获取配置
|
|
||||||
public function config(Request $request)
|
|
||||||
{
|
|
||||||
if ($r = $this->verifyToken($request)) { return $r; }
|
|
||||||
|
|
||||||
$nodeId = $request->input('node_id');
|
|
||||||
$localPort = $request->input('local_port');
|
|
||||||
if (empty($nodeId) || empty($localPort)) {
|
|
||||||
return $this->error('invalid parameters', 400);
|
|
||||||
}
|
|
||||||
|
|
||||||
$serverService = new ServerService();
|
|
||||||
try {
|
|
||||||
$json = $serverService->getV2RayConfig($nodeId, $localPort);
|
|
||||||
$json->poseidon = [
|
|
||||||
'license_key' => (string)config('v2board.server_license'),
|
|
||||||
];
|
|
||||||
if ($this->poseidonVersion >= 'v1.5.0') {
|
|
||||||
// don't need it after v1.5.0
|
|
||||||
unset($json->inboundDetour);
|
|
||||||
unset($json->stats);
|
|
||||||
unset($json->api);
|
|
||||||
array_shift($json->routing->rules);
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach($json->policy->levels as &$level) {
|
|
||||||
$level->handshake = 2;
|
|
||||||
$level->uplinkOnly = 2;
|
|
||||||
$level->downlinkOnly = 2;
|
|
||||||
$level->connIdle = 60;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this->success($json);
|
|
||||||
} catch (\Exception $e) {
|
|
||||||
return $this->error($e->getMessage(), 500);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function verifyToken(Request $request)
|
|
||||||
{
|
|
||||||
$token = $request->input('token');
|
|
||||||
if (empty($token)) {
|
|
||||||
return $this->error("token must be set");
|
|
||||||
}
|
|
||||||
if ($token !== config('v2board.server_token')) {
|
|
||||||
return $this->error("invalid token");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function error($msg, int $status = 400) {
|
|
||||||
return response([
|
|
||||||
'msg' => $msg,
|
|
||||||
], $status);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function success($data) {
|
|
||||||
$req = request();
|
|
||||||
// Only for "GET" method
|
|
||||||
if (!$req->isMethod('GET') || !$data) {
|
|
||||||
return response([
|
|
||||||
'msg' => 'ok',
|
|
||||||
'data' => $data,
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
$etag = sha1(json_encode($data));
|
|
||||||
if ($etag == $req->header("IF-NONE-MATCH")) {
|
|
||||||
return response(null, 304);
|
|
||||||
}
|
|
||||||
|
|
||||||
return response([
|
|
||||||
'msg' => 'ok',
|
|
||||||
'data' => $data,
|
|
||||||
])->header('ETAG', $etag);
|
|
||||||
}
|
|
||||||
}
|
|
@ -8,10 +8,6 @@ use App\Services\UserService;
|
|||||||
use App\Utils\CacheKey;
|
use App\Utils\CacheKey;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use App\Http\Controllers\Controller;
|
use App\Http\Controllers\Controller;
|
||||||
use App\Models\User;
|
|
||||||
use App\Models\ServerLog;
|
|
||||||
use Illuminate\Support\Facades\DB;
|
|
||||||
use Illuminate\Support\Facades\Log;
|
|
||||||
use Illuminate\Support\Facades\Cache;
|
use Illuminate\Support\Facades\Cache;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -41,7 +37,7 @@ class ShadowsocksTidalabController extends Controller
|
|||||||
}
|
}
|
||||||
Cache::put(CacheKey::get('SERVER_SHADOWSOCKS_LAST_CHECK_AT', $server->id), time(), 3600);
|
Cache::put(CacheKey::get('SERVER_SHADOWSOCKS_LAST_CHECK_AT', $server->id), time(), 3600);
|
||||||
$serverService = new ServerService();
|
$serverService = new ServerService();
|
||||||
$users = $serverService->getAvailableUsers(json_decode($server->group_id));
|
$users = $serverService->getAvailableUsers($server->group_id);
|
||||||
$result = [];
|
$result = [];
|
||||||
foreach ($users as $user) {
|
foreach ($users as $user) {
|
||||||
array_push($result, [
|
array_push($result, [
|
||||||
@ -72,23 +68,11 @@ class ShadowsocksTidalabController extends Controller
|
|||||||
Cache::put(CacheKey::get('SERVER_SHADOWSOCKS_ONLINE_USER', $server->id), count($data), 3600);
|
Cache::put(CacheKey::get('SERVER_SHADOWSOCKS_ONLINE_USER', $server->id), count($data), 3600);
|
||||||
Cache::put(CacheKey::get('SERVER_SHADOWSOCKS_LAST_PUSH_AT', $server->id), time(), 3600);
|
Cache::put(CacheKey::get('SERVER_SHADOWSOCKS_LAST_PUSH_AT', $server->id), time(), 3600);
|
||||||
$userService = new UserService();
|
$userService = new UserService();
|
||||||
DB::beginTransaction();
|
foreach ($data as $item) {
|
||||||
try {
|
$u = $item['u'] * $server->rate;
|
||||||
foreach ($data as $item) {
|
$d = $item['d'] * $server->rate;
|
||||||
$u = $item['u'] * $server->rate;
|
$userService->trafficFetch($u, $d, $item['user_id'], $server, 'shadowsocks');
|
||||||
$d = $item['d'] * $server->rate;
|
|
||||||
if (!$userService->trafficFetch((float)$u, (float)$d, (int)$item['user_id'], $server, 'shadowsocks')) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (\Exception $e) {
|
|
||||||
DB::rollBack();
|
|
||||||
return response([
|
|
||||||
'ret' => 0,
|
|
||||||
'msg' => 'user fetch fail'
|
|
||||||
]);
|
|
||||||
}
|
}
|
||||||
DB::commit();
|
|
||||||
|
|
||||||
return response([
|
return response([
|
||||||
'ret' => 1,
|
'ret' => 1,
|
||||||
|
@ -41,7 +41,7 @@ class TrojanTidalabController extends Controller
|
|||||||
}
|
}
|
||||||
Cache::put(CacheKey::get('SERVER_TROJAN_LAST_CHECK_AT', $server->id), time(), 3600);
|
Cache::put(CacheKey::get('SERVER_TROJAN_LAST_CHECK_AT', $server->id), time(), 3600);
|
||||||
$serverService = new ServerService();
|
$serverService = new ServerService();
|
||||||
$users = $serverService->getAvailableUsers(json_decode($server->group_id));
|
$users = $serverService->getAvailableUsers($server->group_id);
|
||||||
$result = [];
|
$result = [];
|
||||||
foreach ($users as $user) {
|
foreach ($users as $user) {
|
||||||
$user->trojan_user = [
|
$user->trojan_user = [
|
||||||
@ -73,23 +73,11 @@ class TrojanTidalabController extends Controller
|
|||||||
Cache::put(CacheKey::get('SERVER_TROJAN_ONLINE_USER', $server->id), count($data), 3600);
|
Cache::put(CacheKey::get('SERVER_TROJAN_ONLINE_USER', $server->id), count($data), 3600);
|
||||||
Cache::put(CacheKey::get('SERVER_TROJAN_LAST_PUSH_AT', $server->id), time(), 3600);
|
Cache::put(CacheKey::get('SERVER_TROJAN_LAST_PUSH_AT', $server->id), time(), 3600);
|
||||||
$userService = new UserService();
|
$userService = new UserService();
|
||||||
DB::beginTransaction();
|
foreach ($data as $item) {
|
||||||
try {
|
$u = $item['u'] * $server->rate;
|
||||||
foreach ($data as $item) {
|
$d = $item['d'] * $server->rate;
|
||||||
$u = $item['u'] * $server->rate;
|
$userService->trafficFetch($u, $d, $item['user_id'], $server, 'trojan');
|
||||||
$d = $item['d'] * $server->rate;
|
|
||||||
if (!$userService->trafficFetch($u, $d, $item['user_id'], $server, 'trojan')) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (\Exception $e) {
|
|
||||||
DB::rollBack();
|
|
||||||
return response([
|
|
||||||
'ret' => 0,
|
|
||||||
'msg' => 'user fetch fail'
|
|
||||||
]);
|
|
||||||
}
|
}
|
||||||
DB::commit();
|
|
||||||
|
|
||||||
return response([
|
return response([
|
||||||
'ret' => 1,
|
'ret' => 1,
|
||||||
|
@ -27,9 +27,8 @@ class CommController extends Controller
|
|||||||
->where('payment', 'StripeCredit')
|
->where('payment', 'StripeCredit')
|
||||||
->first();
|
->first();
|
||||||
if (!$payment) abort(500, 'payment is not found');
|
if (!$payment) abort(500, 'payment is not found');
|
||||||
$config = json_decode($payment->config, true);
|
|
||||||
return response([
|
return response([
|
||||||
'data' => $config['stripe_pk_live']
|
'data' => $payment->config['stripe_pk_live']
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
namespace App\Http\Controllers\User;
|
namespace App\Http\Controllers\User;
|
||||||
|
|
||||||
use App\Http\Controllers\Controller;
|
use App\Http\Controllers\Controller;
|
||||||
|
use App\Services\CouponService;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use App\Models\Coupon;
|
use App\Models\Coupon;
|
||||||
|
|
||||||
@ -13,27 +14,12 @@ class CouponController extends Controller
|
|||||||
if (empty($request->input('code'))) {
|
if (empty($request->input('code'))) {
|
||||||
abort(500, __('Coupon cannot be empty'));
|
abort(500, __('Coupon cannot be empty'));
|
||||||
}
|
}
|
||||||
$coupon = Coupon::where('code', $request->input('code'))->first();
|
$couponService = new CouponService($request->input('code'));
|
||||||
if (!$coupon) {
|
$couponService->setPlanId($request->input('plan_id'));
|
||||||
abort(500, __('Invalid coupon'));
|
$couponService->setUserId($request->session()->get('id'));
|
||||||
}
|
$couponService->check();
|
||||||
if ($coupon->limit_use <= 0 && $coupon->limit_use !== NULL) {
|
|
||||||
abort(500, __('This coupon is no longer available'));
|
|
||||||
}
|
|
||||||
if (time() < $coupon->started_at) {
|
|
||||||
abort(500, __('This coupon has not yet started'));
|
|
||||||
}
|
|
||||||
if (time() > $coupon->ended_at) {
|
|
||||||
abort(500, __('This coupon has expired'));
|
|
||||||
}
|
|
||||||
if ($coupon->limit_plan_ids) {
|
|
||||||
$limitPlanIds = json_decode($coupon->limit_plan_ids);
|
|
||||||
if (!in_array($request->input('plan_id'), $limitPlanIds)) {
|
|
||||||
abort(500, __('The coupon code cannot be used for this subscription'));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return response([
|
return response([
|
||||||
'data' => $coupon
|
'data' => $couponService->getCoupon()
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -35,8 +35,6 @@ class KnowledgeController extends Controller
|
|||||||
}
|
}
|
||||||
$subscribeUrl = "{$subscribeUrl}/api/v1/client/subscribe?token={$user['token']}";
|
$subscribeUrl = "{$subscribeUrl}/api/v1/client/subscribe?token={$user['token']}";
|
||||||
$knowledge['body'] = str_replace('{{siteName}}', config('v2board.app_name', 'V2Board'), $knowledge['body']);
|
$knowledge['body'] = str_replace('{{siteName}}', config('v2board.app_name', 'V2Board'), $knowledge['body']);
|
||||||
$knowledge['body'] = str_replace('{{appleId}}', $appleId, $knowledge['body']);
|
|
||||||
$knowledge['body'] = str_replace('{{appleIdPassword}}', $appleIdPassword, $knowledge['body']);
|
|
||||||
$knowledge['body'] = str_replace('{{subscribeUrl}}', $subscribeUrl, $knowledge['body']);
|
$knowledge['body'] = str_replace('{{subscribeUrl}}', $subscribeUrl, $knowledge['body']);
|
||||||
$knowledge['body'] = str_replace('{{urlEncodeSubscribeUrl}}', urlencode($subscribeUrl), $knowledge['body']);
|
$knowledge['body'] = str_replace('{{urlEncodeSubscribeUrl}}', urlencode($subscribeUrl), $knowledge['body']);
|
||||||
$knowledge['body'] = str_replace(
|
$knowledge['body'] = str_replace(
|
||||||
|
@ -108,7 +108,7 @@ class OrderController extends Controller
|
|||||||
$order->user_id = $request->session()->get('id');
|
$order->user_id = $request->session()->get('id');
|
||||||
$order->plan_id = $plan->id;
|
$order->plan_id = $plan->id;
|
||||||
$order->cycle = $request->input('cycle');
|
$order->cycle = $request->input('cycle');
|
||||||
$order->trade_no = Helper::guid();
|
$order->trade_no = Helper::generateOrderNo();
|
||||||
$order->total_amount = $plan[$request->input('cycle')];
|
$order->total_amount = $plan[$request->input('cycle')];
|
||||||
|
|
||||||
if ($request->input('coupon_code')) {
|
if ($request->input('coupon_code')) {
|
||||||
@ -169,9 +169,8 @@ class OrderController extends Controller
|
|||||||
}
|
}
|
||||||
// free process
|
// free process
|
||||||
if ($order->total_amount <= 0) {
|
if ($order->total_amount <= 0) {
|
||||||
$order->total_amount = 0;
|
$orderService = new OrderService($order);
|
||||||
$order->status = 1;
|
if (!$orderService->paid($order->trade_no)) abort(500, '');
|
||||||
$order->save();
|
|
||||||
return response([
|
return response([
|
||||||
'type' => -1,
|
'type' => -1,
|
||||||
'data' => true
|
'data' => true
|
||||||
|
@ -8,7 +8,7 @@ use App\Services\UserService;
|
|||||||
use App\Utils\CacheKey;
|
use App\Utils\CacheKey;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Illuminate\Support\Facades\Cache;
|
use Illuminate\Support\Facades\Cache;
|
||||||
use App\Models\Server;
|
use App\Models\ServerV2ray;
|
||||||
use App\Models\ServerLog;
|
use App\Models\ServerLog;
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
|
|
||||||
@ -36,16 +36,16 @@ class ServerController extends Controller
|
|||||||
$current = $request->input('current') ? $request->input('current') : 1;
|
$current = $request->input('current') ? $request->input('current') : 1;
|
||||||
$pageSize = $request->input('pageSize') >= 10 ? $request->input('pageSize') : 10;
|
$pageSize = $request->input('pageSize') >= 10 ? $request->input('pageSize') : 10;
|
||||||
$serverLogModel = ServerLog::where('user_id', $request->session()->get('id'))
|
$serverLogModel = ServerLog::where('user_id', $request->session()->get('id'))
|
||||||
->orderBy('created_at', 'DESC');
|
->orderBy('log_at', 'DESC');
|
||||||
switch ($type) {
|
switch ($type) {
|
||||||
case 0:
|
case 0:
|
||||||
$serverLogModel->where('created_at', '>=', strtotime(date('Y-m-d')));
|
$serverLogModel->where('log_at', '>=', strtotime(date('Y-m-d')));
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
$serverLogModel->where('created_at', '>=', strtotime(date('Y-m-d')) - 604800);
|
$serverLogModel->where('log_at', '>=', strtotime(date('Y-m-d')) - 604800);
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
$serverLogModel->where('created_at', '>=', strtotime(date('Y-m-1')));
|
$serverLogModel->where('log_at', '>=', strtotime(date('Y-m-1')));
|
||||||
}
|
}
|
||||||
$total = $serverLogModel->count();
|
$total = $serverLogModel->count();
|
||||||
$res = $serverLogModel->forPage($current, $pageSize)
|
$res = $serverLogModel->forPage($current, $pageSize)
|
||||||
|
@ -168,7 +168,7 @@ class TicketController extends Controller
|
|||||||
$user = User::find($request->session()->get('id'));
|
$user = User::find($request->session()->get('id'));
|
||||||
$limit = config('v2board.commission_withdraw_limit', 100);
|
$limit = config('v2board.commission_withdraw_limit', 100);
|
||||||
if ($limit > ($user->commission_balance / 100)) {
|
if ($limit > ($user->commission_balance / 100)) {
|
||||||
abort(500, __('The current required minimum withdrawal commission is', ['limit' => $limit]));
|
abort(500, __('The current required minimum withdrawal commission is :limit', ['limit' => $limit]));
|
||||||
}
|
}
|
||||||
DB::beginTransaction();
|
DB::beginTransaction();
|
||||||
$subject = __('[Commission Withdrawal Request] This ticket is opened by the system');
|
$subject = __('[Commission Withdrawal Request] This ticket is opened by the system');
|
||||||
|
@ -6,14 +6,16 @@ use App\Http\Controllers\Controller;
|
|||||||
use App\Http\Requests\User\UserTransfer;
|
use App\Http\Requests\User\UserTransfer;
|
||||||
use App\Http\Requests\User\UserUpdate;
|
use App\Http\Requests\User\UserUpdate;
|
||||||
use App\Http\Requests\User\UserChangePassword;
|
use App\Http\Requests\User\UserChangePassword;
|
||||||
|
use App\Utils\CacheKey;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
use App\Models\Plan;
|
use App\Models\Plan;
|
||||||
use App\Models\Server;
|
use App\Models\ServerV2ray;
|
||||||
use App\Models\Ticket;
|
use App\Models\Ticket;
|
||||||
use App\Utils\Helper;
|
use App\Utils\Helper;
|
||||||
use App\Models\Order;
|
use App\Models\Order;
|
||||||
use App\Models\ServerLog;
|
use App\Models\ServerLog;
|
||||||
|
use Illuminate\Support\Facades\Cache;
|
||||||
|
|
||||||
class UserController extends Controller
|
class UserController extends Controller
|
||||||
{
|
{
|
||||||
@ -33,6 +35,7 @@ class UserController extends Controller
|
|||||||
}
|
}
|
||||||
if (!Helper::multiPasswordVerify(
|
if (!Helper::multiPasswordVerify(
|
||||||
$user->password_algo,
|
$user->password_algo,
|
||||||
|
$user->password_salt,
|
||||||
$request->input('old_password'),
|
$request->input('old_password'),
|
||||||
$user->password)
|
$user->password)
|
||||||
) {
|
) {
|
||||||
@ -40,6 +43,7 @@ class UserController extends Controller
|
|||||||
}
|
}
|
||||||
$user->password = password_hash($request->input('new_password'), PASSWORD_DEFAULT);
|
$user->password = password_hash($request->input('new_password'), PASSWORD_DEFAULT);
|
||||||
$user->password_algo = NULL;
|
$user->password_algo = NULL;
|
||||||
|
$user->password_salt = NULL;
|
||||||
if (!$user->save()) {
|
if (!$user->save()) {
|
||||||
abort(500, __('Save failed'));
|
abort(500, __('Save failed'));
|
||||||
}
|
}
|
||||||
@ -118,12 +122,7 @@ class UserController extends Controller
|
|||||||
abort(500, __('Subscription plan does not exist'));
|
abort(500, __('Subscription plan does not exist'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$subscribeUrl = config('v2board.app_url', env('APP_URL'));
|
$user['subscribe_url'] = Helper::getSubscribeHost() . "/api/v1/client/subscribe?token={$user['token']}";
|
||||||
$subscribeUrls = explode(',', config('v2board.subscribe_url'));
|
|
||||||
if ($subscribeUrls) {
|
|
||||||
$subscribeUrl = $subscribeUrls[rand(0, count($subscribeUrls) - 1)];
|
|
||||||
}
|
|
||||||
$user['subscribe_url'] = "{$subscribeUrl}/api/v1/client/subscribe?token={$user['token']}";
|
|
||||||
$user['reset_day'] = $this->getResetDay($user);
|
$user['reset_day'] = $this->getResetDay($user);
|
||||||
return response([
|
return response([
|
||||||
'data' => $user
|
'data' => $user
|
||||||
@ -209,4 +208,26 @@ class UserController extends Controller
|
|||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function getQuickLoginUrl(Request $request)
|
||||||
|
{
|
||||||
|
$user = User::find($request->session()->get('id'));
|
||||||
|
if (!$user) {
|
||||||
|
abort(500, __('The user does not exist'));
|
||||||
|
}
|
||||||
|
|
||||||
|
$code = Helper::guid();
|
||||||
|
$key = CacheKey::get('TEMP_TOKEN', $code);
|
||||||
|
Cache::put($key, $user->id, 60);
|
||||||
|
$redirect = '/#/login?verify=' . $code . '&redirect=' . ($request->input('redirect') ? $request->input('redirect') : 'dashboard');
|
||||||
|
if (config('v2board.app_url')) {
|
||||||
|
$url = config('v2board.app_url') . $redirect;
|
||||||
|
} else {
|
||||||
|
$url = url($redirect);
|
||||||
|
}
|
||||||
|
return response([
|
||||||
|
'data' => $url
|
||||||
|
]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -35,6 +35,7 @@ class Kernel extends HttpKernel
|
|||||||
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
|
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
|
||||||
\App\Http\Middleware\VerifyCsrfToken::class,
|
\App\Http\Middleware\VerifyCsrfToken::class,
|
||||||
\Illuminate\Routing\Middleware\SubstituteBindings::class,
|
\Illuminate\Routing\Middleware\SubstituteBindings::class,
|
||||||
|
\App\Http\Middleware\CORS::class,
|
||||||
],
|
],
|
||||||
|
|
||||||
'api' => [
|
'api' => [
|
||||||
|
@ -15,8 +15,9 @@ class User
|
|||||||
*/
|
*/
|
||||||
public function handle($request, Closure $next)
|
public function handle($request, Closure $next)
|
||||||
{
|
{
|
||||||
if ($request->input('auth_data')) {
|
$authorization = $request->input('auth_data') ?? $request->header('authorization');
|
||||||
$authData = explode(':', base64_decode($request->input('auth_data')));
|
if ($authorization) {
|
||||||
|
$authData = explode(':', base64_decode($authorization));
|
||||||
if (!isset($authData[1]) || !isset($authData[0])) abort(403, '鉴权失败,请重新登入');
|
if (!isset($authData[1]) || !isset($authData[0])) abort(403, '鉴权失败,请重新登入');
|
||||||
$user = \App\Models\User::where('password', $authData[1])
|
$user = \App\Models\User::where('password', $authData[1])
|
||||||
->where('email', $authData[0])
|
->where('email', $authData[0])
|
||||||
|
@ -25,6 +25,10 @@ class ConfigSave extends FormRequest
|
|||||||
'commission_withdraw_limit' => 'nullable|numeric',
|
'commission_withdraw_limit' => 'nullable|numeric',
|
||||||
'commission_withdraw_method' => 'nullable|array',
|
'commission_withdraw_method' => 'nullable|array',
|
||||||
'withdraw_close_enable' => 'in:0,1',
|
'withdraw_close_enable' => 'in:0,1',
|
||||||
|
'commission_distribution_enable' => 'in:0,1',
|
||||||
|
'commission_distribution_l1' => 'nullable|numeric',
|
||||||
|
'commission_distribution_l2' => 'nullable|numeric',
|
||||||
|
'commission_distribution_l3' => 'nullable|numeric',
|
||||||
// site
|
// site
|
||||||
'stop_register' => 'in:0,1',
|
'stop_register' => 'in:0,1',
|
||||||
'email_verify' => 'in:0,1',
|
'email_verify' => 'in:0,1',
|
||||||
@ -44,7 +48,7 @@ class ConfigSave extends FormRequest
|
|||||||
'tos_url' => 'nullable|url',
|
'tos_url' => 'nullable|url',
|
||||||
// subscribe
|
// subscribe
|
||||||
'plan_change_enable' => 'in:0,1',
|
'plan_change_enable' => 'in:0,1',
|
||||||
'reset_traffic_method' => 'in:0,1',
|
'reset_traffic_method' => 'in:0,1,2',
|
||||||
'surplus_enable' => 'in:0,1',
|
'surplus_enable' => 'in:0,1',
|
||||||
'new_order_event_id' => 'in:0,1',
|
'new_order_event_id' => 'in:0,1',
|
||||||
'renew_order_event_id' => 'in:0,1',
|
'renew_order_event_id' => 'in:0,1',
|
||||||
@ -88,14 +92,11 @@ class ConfigSave extends FormRequest
|
|||||||
'frontend_theme' => '',
|
'frontend_theme' => '',
|
||||||
'frontend_theme_sidebar' => 'in:dark,light',
|
'frontend_theme_sidebar' => 'in:dark,light',
|
||||||
'frontend_theme_header' => 'in:dark,light',
|
'frontend_theme_header' => 'in:dark,light',
|
||||||
'frontend_theme_color' => 'in:default,darkblue,black',
|
'frontend_theme_color' => 'in:default,darkblue,black,green',
|
||||||
'frontend_background_url' => 'nullable|url',
|
'frontend_background_url' => 'nullable|url',
|
||||||
'frontend_admin_path' => '',
|
'frontend_admin_path' => '',
|
||||||
'frontend_customer_service_method' => '',
|
'frontend_customer_service_method' => '',
|
||||||
'frontend_customer_service_id' => '',
|
'frontend_customer_service_id' => '',
|
||||||
// tutorial
|
|
||||||
'apple_id' => 'nullable|email',
|
|
||||||
'apple_id_password' => '',
|
|
||||||
// email
|
// email
|
||||||
'email_template' => '',
|
'email_template' => '',
|
||||||
'email_host' => '',
|
'email_host' => '',
|
||||||
|
@ -21,6 +21,7 @@ class CouponGenerate extends FormRequest
|
|||||||
'started_at' => 'required|integer',
|
'started_at' => 'required|integer',
|
||||||
'ended_at' => 'required|integer',
|
'ended_at' => 'required|integer',
|
||||||
'limit_use' => 'nullable|integer',
|
'limit_use' => 'nullable|integer',
|
||||||
|
'limit_use_with_user' => 'nullable|integer',
|
||||||
'limit_plan_ids' => 'nullable|array',
|
'limit_plan_ids' => 'nullable|array',
|
||||||
'code' => ''
|
'code' => ''
|
||||||
];
|
];
|
||||||
@ -40,7 +41,8 @@ class CouponGenerate extends FormRequest
|
|||||||
'started_at.integer' => '开始时间格式有误',
|
'started_at.integer' => '开始时间格式有误',
|
||||||
'ended_at.required' => '结束时间不能为空',
|
'ended_at.required' => '结束时间不能为空',
|
||||||
'ended_at.integer' => '结束时间格式有误',
|
'ended_at.integer' => '结束时间格式有误',
|
||||||
'limit_use.integer' => '使用次数格式有误',
|
'limit_use.integer' => '最大使用次数格式有误',
|
||||||
|
'limit_use_with_user.integer' => '限制用户使用次数格式有误',
|
||||||
'limit_plan_ids.array' => '指定订阅格式有误'
|
'limit_plan_ids.array' => '指定订阅格式有误'
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
@ -1,44 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Http\Requests\Admin;
|
|
||||||
|
|
||||||
use Illuminate\Foundation\Http\FormRequest;
|
|
||||||
|
|
||||||
class CouponSave extends FormRequest
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Get the validation rules that apply to the request.
|
|
||||||
*
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
public function rules()
|
|
||||||
{
|
|
||||||
return [
|
|
||||||
'name' => 'required',
|
|
||||||
'type' => 'required|in:1,2',
|
|
||||||
'value' => 'required|integer',
|
|
||||||
'started_at' => 'required|integer',
|
|
||||||
'ended_at' => 'required|integer',
|
|
||||||
'limit_use' => 'nullable|integer',
|
|
||||||
'limit_plan_ids' => 'nullable|array',
|
|
||||||
'code' => ''
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
public function messages()
|
|
||||||
{
|
|
||||||
return [
|
|
||||||
'name.required' => '名称不能为空',
|
|
||||||
'type.required' => '类型不能为空',
|
|
||||||
'type.in' => '类型格式有误',
|
|
||||||
'value.required' => '金额或比例不能为空',
|
|
||||||
'value.integer' => '金额或比例格式有误',
|
|
||||||
'started_at.required' => '开始时间不能为空',
|
|
||||||
'started_at.integer' => '开始时间格式有误',
|
|
||||||
'ended_at.required' => '结束时间不能为空',
|
|
||||||
'ended_at.integer' => '结束时间格式有误',
|
|
||||||
'limit_use.integer' => '使用次数格式有误',
|
|
||||||
'limit_plan_ids.array' => '指定订阅格式有误'
|
|
||||||
];
|
|
||||||
}
|
|
||||||
}
|
|
@ -25,7 +25,8 @@ class PlanSave extends FormRequest
|
|||||||
'two_year_price' => 'nullable|integer',
|
'two_year_price' => 'nullable|integer',
|
||||||
'three_year_price' => 'nullable|integer',
|
'three_year_price' => 'nullable|integer',
|
||||||
'onetime_price' => 'nullable|integer',
|
'onetime_price' => 'nullable|integer',
|
||||||
'reset_price' => 'nullable|integer'
|
'reset_price' => 'nullable|integer',
|
||||||
|
'reset_traffic_method' => 'nullable|integer|in:0,1,2'
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -44,7 +45,9 @@ class PlanSave extends FormRequest
|
|||||||
'two_year_price.integer' => '两年付金额格式有误',
|
'two_year_price.integer' => '两年付金额格式有误',
|
||||||
'three_year_price.integer' => '三年付金额格式有误',
|
'three_year_price.integer' => '三年付金额格式有误',
|
||||||
'onetime_price.integer' => '一次性金额有误',
|
'onetime_price.integer' => '一次性金额有误',
|
||||||
'reset_price.integer' => '流量重置包金额有误'
|
'reset_price.integer' => '流量重置包金额有误',
|
||||||
|
'reset_traffic_method.integer' => '流量重置方式格式有误',
|
||||||
|
'reset_traffic_method.in' => '流量重置方式格式有误'
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -26,10 +26,10 @@ class ServerV2raySave extends FormRequest
|
|||||||
'rate' => 'required|numeric',
|
'rate' => 'required|numeric',
|
||||||
'alter_id' => 'required|integer',
|
'alter_id' => 'required|integer',
|
||||||
'network' => 'required|in:tcp,kcp,ws,http,domainsocket,quic,grpc',
|
'network' => 'required|in:tcp,kcp,ws,http,domainsocket,quic,grpc',
|
||||||
'networkSettings' => '',
|
'networkSettings' => 'nullable|array',
|
||||||
'ruleSettings' => '',
|
'ruleSettings' => 'nullable|array',
|
||||||
'tlsSettings' => '',
|
'tlsSettings' => 'nullable|array',
|
||||||
'dnsSettings' => ''
|
'dnsSettings' => 'nullable|array'
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -48,7 +48,11 @@ class ServerV2raySave extends FormRequest
|
|||||||
'rate.required' => '倍率不能为空',
|
'rate.required' => '倍率不能为空',
|
||||||
'rate.numeric' => '倍率格式不正确',
|
'rate.numeric' => '倍率格式不正确',
|
||||||
'network.required' => '传输协议不能为空',
|
'network.required' => '传输协议不能为空',
|
||||||
'network.in' => '传输协议格式不正确'
|
'network.in' => '传输协议格式不正确',
|
||||||
|
'networkSettings.array' => '传输协议配置有误',
|
||||||
|
'ruleSettings.array' => '规则配置有误',
|
||||||
|
'tlsSettings.array' => 'tls配置有误',
|
||||||
|
'dnsSettings.array' => 'dns配置有误'
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -63,9 +63,10 @@ class AdminRoute
|
|||||||
});
|
});
|
||||||
// Order
|
// Order
|
||||||
$router->get ('/order/fetch', 'Admin\\OrderController@fetch');
|
$router->get ('/order/fetch', 'Admin\\OrderController@fetch');
|
||||||
$router->post('/order/repair', 'Admin\\OrderController@repair');
|
|
||||||
$router->post('/order/update', 'Admin\\OrderController@update');
|
$router->post('/order/update', 'Admin\\OrderController@update');
|
||||||
$router->post('/order/assign', 'Admin\\OrderController@assign');
|
$router->post('/order/assign', 'Admin\\OrderController@assign');
|
||||||
|
$router->post('/order/paid', 'Admin\\OrderController@paid');
|
||||||
|
$router->post('/order/cancel', 'Admin\\OrderController@cancel');
|
||||||
// User
|
// User
|
||||||
$router->get ('/user/fetch', 'Admin\\UserController@fetch');
|
$router->get ('/user/fetch', 'Admin\\UserController@fetch');
|
||||||
$router->post('/user/update', 'Admin\\UserController@update');
|
$router->post('/user/update', 'Admin\\UserController@update');
|
||||||
|
@ -20,6 +20,7 @@ class UserRoute
|
|||||||
$router->get ('/getSubscribe', 'User\\UserController@getSubscribe');
|
$router->get ('/getSubscribe', 'User\\UserController@getSubscribe');
|
||||||
$router->get ('/getStat', 'User\\UserController@getStat');
|
$router->get ('/getStat', 'User\\UserController@getStat');
|
||||||
$router->post('/transfer', 'User\\UserController@transfer');
|
$router->post('/transfer', 'User\\UserController@transfer');
|
||||||
|
$router->post('/getQuickLoginUrl', 'User\\UserController@getQuickLoginUrl');
|
||||||
// Order
|
// Order
|
||||||
$router->post('/order/save', 'User\\OrderController@save');
|
$router->post('/order/save', 'User\\OrderController@save');
|
||||||
$router->post('/order/checkout', 'User\\OrderController@checkout');
|
$router->post('/order/checkout', 'User\\OrderController@checkout');
|
||||||
|
52
app/Jobs/OrderHandleJob.php
Normal file
52
app/Jobs/OrderHandleJob.php
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Jobs;
|
||||||
|
|
||||||
|
use App\Models\Order;
|
||||||
|
use App\Services\OrderService;
|
||||||
|
use Illuminate\Bus\Queueable;
|
||||||
|
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||||
|
use Illuminate\Foundation\Bus\Dispatchable;
|
||||||
|
use Illuminate\Queue\InteractsWithQueue;
|
||||||
|
use Illuminate\Queue\SerializesModels;
|
||||||
|
|
||||||
|
class OrderHandleJob implements ShouldQueue
|
||||||
|
{
|
||||||
|
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
||||||
|
protected $order;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new job instance.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function __construct($tradeNo)
|
||||||
|
{
|
||||||
|
$this->onQueue('order_handle');
|
||||||
|
$this->order = Order::where('trade_no', $tradeNo)
|
||||||
|
->lockForUpdate()
|
||||||
|
->first();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute the job.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function handle()
|
||||||
|
{
|
||||||
|
if (!$this->order) return;
|
||||||
|
$orderService = new OrderService($this->order);
|
||||||
|
switch ($this->order->status) {
|
||||||
|
// cancel
|
||||||
|
case 0:
|
||||||
|
if ($this->order->created_at <= (time() - 1800)) {
|
||||||
|
$orderService->cancel();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
$orderService->open();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
58
app/Jobs/ServerLogJob.php
Normal file
58
app/Jobs/ServerLogJob.php
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Jobs;
|
||||||
|
|
||||||
|
use App\Services\ServerService;
|
||||||
|
use Illuminate\Bus\Queueable;
|
||||||
|
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||||
|
use Illuminate\Foundation\Bus\Dispatchable;
|
||||||
|
use Illuminate\Queue\InteractsWithQueue;
|
||||||
|
use Illuminate\Queue\SerializesModels;
|
||||||
|
|
||||||
|
class ServerLogJob implements ShouldQueue
|
||||||
|
{
|
||||||
|
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
||||||
|
protected $u;
|
||||||
|
protected $d;
|
||||||
|
protected $userId;
|
||||||
|
protected $server;
|
||||||
|
protected $protocol;
|
||||||
|
|
||||||
|
public $tries = 3;
|
||||||
|
public $timeout = 3;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new job instance.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function __construct($u, $d, $userId, $server, $protocol)
|
||||||
|
{
|
||||||
|
$this->onQueue('server_log');
|
||||||
|
$this->u = $u;
|
||||||
|
$this->d = $d;
|
||||||
|
$this->userId = $userId;
|
||||||
|
$this->server = $server;
|
||||||
|
$this->protocol = $protocol;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute the job.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function handle()
|
||||||
|
{
|
||||||
|
$serverService = new ServerService();
|
||||||
|
if (!$serverService->log(
|
||||||
|
$this->userId,
|
||||||
|
$this->server->id,
|
||||||
|
$this->u,
|
||||||
|
$this->d,
|
||||||
|
$this->server->rate,
|
||||||
|
$this->protocol
|
||||||
|
)) {
|
||||||
|
throw new \Exception('日志记录失败');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
57
app/Jobs/TrafficFetchJob.php
Normal file
57
app/Jobs/TrafficFetchJob.php
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Jobs;
|
||||||
|
|
||||||
|
use App\Models\User;
|
||||||
|
use App\Services\MailService;
|
||||||
|
use Illuminate\Bus\Queueable;
|
||||||
|
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||||
|
use Illuminate\Foundation\Bus\Dispatchable;
|
||||||
|
use Illuminate\Queue\InteractsWithQueue;
|
||||||
|
use Illuminate\Queue\SerializesModels;
|
||||||
|
|
||||||
|
class TrafficFetchJob implements ShouldQueue
|
||||||
|
{
|
||||||
|
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
||||||
|
protected $u;
|
||||||
|
protected $d;
|
||||||
|
protected $userId;
|
||||||
|
protected $server;
|
||||||
|
protected $protocol;
|
||||||
|
|
||||||
|
public $tries = 3;
|
||||||
|
public $timeout = 3;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new job instance.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function __construct($u, $d, $userId, $server, $protocol)
|
||||||
|
{
|
||||||
|
$this->onQueue('traffic_fetch');
|
||||||
|
$this->u = $u;
|
||||||
|
$this->d = $d;
|
||||||
|
$this->userId = $userId;
|
||||||
|
$this->server = $server;
|
||||||
|
$this->protocol = $protocol;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute the job.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function handle()
|
||||||
|
{
|
||||||
|
$user = User::lockForUpdate()->find($this->userId);
|
||||||
|
if (!$user) return;
|
||||||
|
|
||||||
|
$user->t = time();
|
||||||
|
$user->u = $user->u + $this->u;
|
||||||
|
$user->d = $user->d + $this->d;
|
||||||
|
if (!$user->save()) throw new \Exception('流量更新失败');
|
||||||
|
$mailService = new MailService();
|
||||||
|
$mailService->remindTraffic($user);
|
||||||
|
}
|
||||||
|
}
|
16
app/Models/CommissionLog.php
Normal file
16
app/Models/CommissionLog.php
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Models;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
|
||||||
|
class CommissionLog extends Model
|
||||||
|
{
|
||||||
|
protected $table = 'v2_commission_log';
|
||||||
|
protected $dateFormat = 'U';
|
||||||
|
protected $guarded = ['id'];
|
||||||
|
protected $casts = [
|
||||||
|
'created_at' => 'timestamp',
|
||||||
|
'updated_at' => 'timestamp'
|
||||||
|
];
|
||||||
|
}
|
@ -9,4 +9,9 @@ class Coupon extends Model
|
|||||||
protected $table = 'v2_coupon';
|
protected $table = 'v2_coupon';
|
||||||
protected $dateFormat = 'U';
|
protected $dateFormat = 'U';
|
||||||
protected $guarded = ['id'];
|
protected $guarded = ['id'];
|
||||||
|
protected $casts = [
|
||||||
|
'created_at' => 'timestamp',
|
||||||
|
'updated_at' => 'timestamp',
|
||||||
|
'limit_plan_ids' => 'array'
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
@ -8,4 +8,8 @@ class InviteCode extends Model
|
|||||||
{
|
{
|
||||||
protected $table = 'v2_invite_code';
|
protected $table = 'v2_invite_code';
|
||||||
protected $dateFormat = 'U';
|
protected $dateFormat = 'U';
|
||||||
|
protected $casts = [
|
||||||
|
'created_at' => 'timestamp',
|
||||||
|
'updated_at' => 'timestamp'
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
@ -9,4 +9,8 @@ class Knowledge extends Model
|
|||||||
protected $table = 'v2_knowledge';
|
protected $table = 'v2_knowledge';
|
||||||
protected $dateFormat = 'U';
|
protected $dateFormat = 'U';
|
||||||
protected $guarded = ['id'];
|
protected $guarded = ['id'];
|
||||||
|
protected $casts = [
|
||||||
|
'created_at' => 'timestamp',
|
||||||
|
'updated_at' => 'timestamp'
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
@ -9,4 +9,8 @@ class MailLog extends Model
|
|||||||
protected $table = 'v2_mail_log';
|
protected $table = 'v2_mail_log';
|
||||||
protected $dateFormat = 'U';
|
protected $dateFormat = 'U';
|
||||||
protected $guarded = ['id'];
|
protected $guarded = ['id'];
|
||||||
|
protected $casts = [
|
||||||
|
'created_at' => 'timestamp',
|
||||||
|
'updated_at' => 'timestamp'
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
@ -9,4 +9,8 @@ class Notice extends Model
|
|||||||
protected $table = 'v2_notice';
|
protected $table = 'v2_notice';
|
||||||
protected $dateFormat = 'U';
|
protected $dateFormat = 'U';
|
||||||
protected $guarded = ['id'];
|
protected $guarded = ['id'];
|
||||||
|
protected $casts = [
|
||||||
|
'created_at' => 'timestamp',
|
||||||
|
'updated_at' => 'timestamp'
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
@ -9,4 +9,9 @@ class Order extends Model
|
|||||||
protected $table = 'v2_order';
|
protected $table = 'v2_order';
|
||||||
protected $dateFormat = 'U';
|
protected $dateFormat = 'U';
|
||||||
protected $guarded = ['id'];
|
protected $guarded = ['id'];
|
||||||
|
protected $casts = [
|
||||||
|
'created_at' => 'timestamp',
|
||||||
|
'updated_at' => 'timestamp',
|
||||||
|
'surplus_order_ids' => 'array'
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
@ -9,4 +9,9 @@ class Payment extends Model
|
|||||||
protected $table = 'v2_payment';
|
protected $table = 'v2_payment';
|
||||||
protected $dateFormat = 'U';
|
protected $dateFormat = 'U';
|
||||||
protected $guarded = ['id'];
|
protected $guarded = ['id'];
|
||||||
|
protected $casts = [
|
||||||
|
'created_at' => 'timestamp',
|
||||||
|
'updated_at' => 'timestamp',
|
||||||
|
'config' => 'array'
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
@ -9,4 +9,8 @@ class Plan extends Model
|
|||||||
protected $table = 'v2_plan';
|
protected $table = 'v2_plan';
|
||||||
protected $dateFormat = 'U';
|
protected $dateFormat = 'U';
|
||||||
protected $guarded = ['id'];
|
protected $guarded = ['id'];
|
||||||
|
protected $casts = [
|
||||||
|
'created_at' => 'timestamp',
|
||||||
|
'updated_at' => 'timestamp'
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
@ -1,12 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Models;
|
|
||||||
|
|
||||||
use Illuminate\Database\Eloquent\Model;
|
|
||||||
|
|
||||||
class Server extends Model
|
|
||||||
{
|
|
||||||
protected $table = 'v2_server';
|
|
||||||
protected $dateFormat = 'U';
|
|
||||||
protected $guarded = ['id'];
|
|
||||||
}
|
|
@ -8,4 +8,8 @@ class ServerGroup extends Model
|
|||||||
{
|
{
|
||||||
protected $table = 'v2_server_group';
|
protected $table = 'v2_server_group';
|
||||||
protected $dateFormat = 'U';
|
protected $dateFormat = 'U';
|
||||||
|
protected $casts = [
|
||||||
|
'created_at' => 'timestamp',
|
||||||
|
'updated_at' => 'timestamp'
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
@ -9,4 +9,8 @@ class ServerLog extends Model
|
|||||||
{
|
{
|
||||||
protected $table = 'v2_server_log';
|
protected $table = 'v2_server_log';
|
||||||
protected $dateFormat = 'U';
|
protected $dateFormat = 'U';
|
||||||
|
protected $casts = [
|
||||||
|
'created_at' => 'timestamp',
|
||||||
|
'updated_at' => 'timestamp'
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
@ -9,4 +9,10 @@ class ServerShadowsocks extends Model
|
|||||||
protected $table = 'v2_server_shadowsocks';
|
protected $table = 'v2_server_shadowsocks';
|
||||||
protected $dateFormat = 'U';
|
protected $dateFormat = 'U';
|
||||||
protected $guarded = ['id'];
|
protected $guarded = ['id'];
|
||||||
|
protected $casts = [
|
||||||
|
'created_at' => 'timestamp',
|
||||||
|
'updated_at' => 'timestamp',
|
||||||
|
'group_id' => 'array',
|
||||||
|
'tags' => 'array'
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
@ -9,4 +9,8 @@ class ServerStat extends Model
|
|||||||
protected $table = 'v2_server_stat';
|
protected $table = 'v2_server_stat';
|
||||||
protected $dateFormat = 'U';
|
protected $dateFormat = 'U';
|
||||||
protected $guarded = ['id'];
|
protected $guarded = ['id'];
|
||||||
|
protected $casts = [
|
||||||
|
'created_at' => 'timestamp',
|
||||||
|
'updated_at' => 'timestamp'
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
@ -9,4 +9,10 @@ class ServerTrojan extends Model
|
|||||||
protected $table = 'v2_server_trojan';
|
protected $table = 'v2_server_trojan';
|
||||||
protected $dateFormat = 'U';
|
protected $dateFormat = 'U';
|
||||||
protected $guarded = ['id'];
|
protected $guarded = ['id'];
|
||||||
|
protected $casts = [
|
||||||
|
'created_at' => 'timestamp',
|
||||||
|
'updated_at' => 'timestamp',
|
||||||
|
'group_id' => 'array',
|
||||||
|
'tags' => 'array'
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
22
app/Models/ServerV2ray.php
Executable file
22
app/Models/ServerV2ray.php
Executable file
@ -0,0 +1,22 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Models;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
|
||||||
|
class ServerV2ray extends Model
|
||||||
|
{
|
||||||
|
protected $table = 'v2_server_v2ray';
|
||||||
|
protected $dateFormat = 'U';
|
||||||
|
protected $guarded = ['id'];
|
||||||
|
protected $casts = [
|
||||||
|
'created_at' => 'timestamp',
|
||||||
|
'updated_at' => 'timestamp',
|
||||||
|
'group_id' => 'array',
|
||||||
|
'tlsSettings' => 'array',
|
||||||
|
'networkSettings' => 'array',
|
||||||
|
'dnsSettings' => 'array',
|
||||||
|
'ruleSettings' => 'array',
|
||||||
|
'tags' => 'array'
|
||||||
|
];
|
||||||
|
}
|
@ -9,4 +9,8 @@ class StatOrder extends Model
|
|||||||
protected $table = 'v2_stat_order';
|
protected $table = 'v2_stat_order';
|
||||||
protected $dateFormat = 'U';
|
protected $dateFormat = 'U';
|
||||||
protected $guarded = ['id'];
|
protected $guarded = ['id'];
|
||||||
|
protected $casts = [
|
||||||
|
'created_at' => 'timestamp',
|
||||||
|
'updated_at' => 'timestamp'
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
@ -9,4 +9,8 @@ class StatServer extends Model
|
|||||||
protected $table = 'v2_stat_server';
|
protected $table = 'v2_stat_server';
|
||||||
protected $dateFormat = 'U';
|
protected $dateFormat = 'U';
|
||||||
protected $guarded = ['id'];
|
protected $guarded = ['id'];
|
||||||
|
protected $casts = [
|
||||||
|
'created_at' => 'timestamp',
|
||||||
|
'updated_at' => 'timestamp'
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
@ -9,4 +9,8 @@ class Ticket extends Model
|
|||||||
protected $table = 'v2_ticket';
|
protected $table = 'v2_ticket';
|
||||||
protected $dateFormat = 'U';
|
protected $dateFormat = 'U';
|
||||||
protected $guarded = ['id'];
|
protected $guarded = ['id'];
|
||||||
|
protected $casts = [
|
||||||
|
'created_at' => 'timestamp',
|
||||||
|
'updated_at' => 'timestamp'
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
@ -9,4 +9,8 @@ class TicketMessage extends Model
|
|||||||
protected $table = 'v2_ticket_message';
|
protected $table = 'v2_ticket_message';
|
||||||
protected $dateFormat = 'U';
|
protected $dateFormat = 'U';
|
||||||
protected $guarded = ['id'];
|
protected $guarded = ['id'];
|
||||||
|
protected $casts = [
|
||||||
|
'created_at' => 'timestamp',
|
||||||
|
'updated_at' => 'timestamp'
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
@ -9,4 +9,8 @@ class User extends Model
|
|||||||
protected $table = 'v2_user';
|
protected $table = 'v2_user';
|
||||||
protected $dateFormat = 'U';
|
protected $dateFormat = 'U';
|
||||||
protected $guarded = ['id'];
|
protected $guarded = ['id'];
|
||||||
|
protected $casts = [
|
||||||
|
'created_at' => 'timestamp',
|
||||||
|
'updated_at' => 'timestamp'
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,8 @@ namespace App\Payments;
|
|||||||
use \Curl\Curl;
|
use \Curl\Curl;
|
||||||
|
|
||||||
class MGate {
|
class MGate {
|
||||||
|
private $config;
|
||||||
|
|
||||||
public function __construct($config)
|
public function __construct($config)
|
||||||
{
|
{
|
||||||
$this->config = $config;
|
$this->config = $config;
|
||||||
@ -47,6 +49,7 @@ class MGate {
|
|||||||
$str = http_build_query($params) . $this->config['mgate_app_secret'];
|
$str = http_build_query($params) . $this->config['mgate_app_secret'];
|
||||||
$params['sign'] = md5($str);
|
$params['sign'] = md5($str);
|
||||||
$curl = new Curl();
|
$curl = new Curl();
|
||||||
|
$curl->setUserAgent('MGate');
|
||||||
$curl->post($this->config['mgate_url'] . '/v1/gateway/fetch', http_build_query($params));
|
$curl->post($this->config['mgate_url'] . '/v1/gateway/fetch', http_build_query($params));
|
||||||
$result = $curl->response;
|
$result = $curl->response;
|
||||||
if (!$result) {
|
if (!$result) {
|
||||||
|
43
app/Providers/HorizonServiceProvider.php
Normal file
43
app/Providers/HorizonServiceProvider.php
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Providers;
|
||||||
|
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Support\Facades\Gate;
|
||||||
|
use Laravel\Horizon\Horizon;
|
||||||
|
use Laravel\Horizon\HorizonApplicationServiceProvider;
|
||||||
|
|
||||||
|
class HorizonServiceProvider extends HorizonApplicationServiceProvider
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Bootstrap any application services.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function boot()
|
||||||
|
{
|
||||||
|
parent::boot();
|
||||||
|
|
||||||
|
// Horizon::routeSmsNotificationsTo('15556667777');
|
||||||
|
// Horizon::routeMailNotificationsTo('example@example.com');
|
||||||
|
// Horizon::routeSlackNotificationsTo('slack-webhook-url', '#channel');
|
||||||
|
|
||||||
|
// Horizon::night();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register the Horizon gate.
|
||||||
|
*
|
||||||
|
* This gate determines who can access Horizon in non-local environments.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
protected function gate()
|
||||||
|
{
|
||||||
|
Gate::define('viewHorizon', function ($user) {
|
||||||
|
return in_array($user->email, [
|
||||||
|
//
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
@ -8,27 +8,20 @@ use Illuminate\Support\Facades\DB;
|
|||||||
|
|
||||||
class CouponService
|
class CouponService
|
||||||
{
|
{
|
||||||
public $order;
|
public $coupon;
|
||||||
|
public $planId;
|
||||||
|
public $userId;
|
||||||
|
|
||||||
public function __construct($code)
|
public function __construct($code)
|
||||||
{
|
{
|
||||||
$this->coupon = Coupon::where('code', $code)->first();
|
$this->coupon = Coupon::where('code', $code)->first();
|
||||||
if (!$this->coupon) {
|
|
||||||
abort(500, '优惠券无效');
|
|
||||||
}
|
|
||||||
if ($this->coupon->limit_use <= 0 && $this->coupon->limit_use !== NULL) {
|
|
||||||
abort(500, '优惠券已无可用次数');
|
|
||||||
}
|
|
||||||
if (time() < $this->coupon->started_at) {
|
|
||||||
abort(500, '优惠券还未到可用时间');
|
|
||||||
}
|
|
||||||
if (time() > $this->coupon->ended_at) {
|
|
||||||
abort(500, '优惠券已过期');
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function use(Order $order)
|
public function use(Order $order):bool
|
||||||
{
|
{
|
||||||
|
$this->setPlanId($order->plan_id);
|
||||||
|
$this->setUserId($order->user_id);
|
||||||
|
$this->check();
|
||||||
switch ($this->coupon->type) {
|
switch ($this->coupon->type) {
|
||||||
case 1:
|
case 1:
|
||||||
$order->discount_amount = $this->coupon->value;
|
$order->discount_amount = $this->coupon->value;
|
||||||
@ -43,12 +36,6 @@ class CouponService
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ($this->coupon->limit_plan_ids) {
|
|
||||||
$limitPlanIds = json_decode($this->coupon->limit_plan_ids);
|
|
||||||
if (!in_array($order->plan_id, $limitPlanIds)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -56,4 +43,57 @@ class CouponService
|
|||||||
{
|
{
|
||||||
return $this->coupon->id;
|
return $this->coupon->id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getCoupon()
|
||||||
|
{
|
||||||
|
return $this->coupon;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setPlanId($planId)
|
||||||
|
{
|
||||||
|
$this->planId = $planId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setUserId($userId)
|
||||||
|
{
|
||||||
|
$this->userId = $userId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function checkLimitUseWithUser():bool
|
||||||
|
{
|
||||||
|
$usedCount = Order::where('coupon_id', $this->coupon->id)
|
||||||
|
->where('user_id', $this->userId)
|
||||||
|
->whereNotIn('status', [0, 2])
|
||||||
|
->count();
|
||||||
|
if ($usedCount >= $this->coupon->limit_use_with_user) return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function check()
|
||||||
|
{
|
||||||
|
if (!$this->coupon) {
|
||||||
|
abort(500, __('Invalid coupon'));
|
||||||
|
}
|
||||||
|
if ($this->coupon->limit_use <= 0 && $this->coupon->limit_use !== NULL) {
|
||||||
|
abort(500, __('This coupon is no longer available'));
|
||||||
|
}
|
||||||
|
if (time() < $this->coupon->started_at) {
|
||||||
|
abort(500, __('This coupon has not yet started'));
|
||||||
|
}
|
||||||
|
if (time() > $this->coupon->ended_at) {
|
||||||
|
abort(500, __('This coupon has expired'));
|
||||||
|
}
|
||||||
|
if ($this->coupon->limit_plan_ids && $this->planId) {
|
||||||
|
if (!in_array($this->planId, $this->coupon->limit_plan_ids)) {
|
||||||
|
abort(500, __('The coupon code cannot be used for this subscription'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ($this->coupon->limit_use_with_user !== NULL && $this->userId) {
|
||||||
|
if (!$this->checkLimitUseWithUser()) {
|
||||||
|
abort(500, __('The coupon can only be used :limit_use_with_user per person', [
|
||||||
|
'limit_use_with_user' => $this->coupon->limit_use_with_user
|
||||||
|
]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,13 +12,15 @@ class MailService
|
|||||||
public function remindTraffic (User $user)
|
public function remindTraffic (User $user)
|
||||||
{
|
{
|
||||||
if (!$user->remind_traffic) return;
|
if (!$user->remind_traffic) return;
|
||||||
if (!$this->remindTrafficIsWarnValue(($user->u + $user->d), $user->transfer_enable)) return;
|
if (!$this->remindTrafficIsWarnValue($user->u, $user->d, $user->transfer_enable)) return;
|
||||||
$flag = CacheKey::get('LAST_SEND_EMAIL_REMIND_TRAFFIC', $user->id);
|
$flag = CacheKey::get('LAST_SEND_EMAIL_REMIND_TRAFFIC', $user->id);
|
||||||
if (Cache::get($flag)) return;
|
if (Cache::get($flag)) return;
|
||||||
if (!Cache::put($flag, 1, 24 * 3600)) return;
|
if (!Cache::put($flag, 1, 24 * 3600)) return;
|
||||||
SendEmailJob::dispatch([
|
SendEmailJob::dispatch([
|
||||||
'email' => $user->email,
|
'email' => $user->email,
|
||||||
'subject' => '在' . config('v2board.app_name', 'V2board') . '的流量使用已达到80%',
|
'subject' => __('The traffic usage in :app_name has reached 80%', [
|
||||||
|
'app_name' => config('v2board.app_name', 'V2board')
|
||||||
|
]),
|
||||||
'template_name' => 'remindTraffic',
|
'template_name' => 'remindTraffic',
|
||||||
'template_value' => [
|
'template_value' => [
|
||||||
'name' => config('v2board.app_name', 'V2Board'),
|
'name' => config('v2board.app_name', 'V2Board'),
|
||||||
@ -27,8 +29,25 @@ class MailService
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
private function remindTrafficIsWarnValue($ud, $transfer_enable)
|
public function remindExpire(User $user)
|
||||||
{
|
{
|
||||||
|
if (!($user->expired_at !== NULL && ($user->expired_at - 86400) < time() && $user->expired_at > time())) return;
|
||||||
|
SendEmailJob::dispatch([
|
||||||
|
'email' => $user->email,
|
||||||
|
'subject' => __('The service in :app_name is about to expire', [
|
||||||
|
'app_name' => config('v2board.app_name', 'V2board')
|
||||||
|
]),
|
||||||
|
'template_name' => 'remindExpire',
|
||||||
|
'template_value' => [
|
||||||
|
'name' => config('v2board.app_name', 'V2Board'),
|
||||||
|
'url' => config('v2board.app_url')
|
||||||
|
]
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function remindTrafficIsWarnValue($u, $d, $transfer_enable)
|
||||||
|
{
|
||||||
|
$ud = $u + $d;
|
||||||
if (!$ud) return false;
|
if (!$ud) return false;
|
||||||
if (!$transfer_enable) return false;
|
if (!$transfer_enable) return false;
|
||||||
$percentage = ($ud / $transfer_enable) * 100;
|
$percentage = ($ud / $transfer_enable) * 100;
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
namespace App\Services;
|
namespace App\Services;
|
||||||
|
|
||||||
|
use App\Jobs\OrderHandleJob;
|
||||||
use App\Models\Order;
|
use App\Models\Order;
|
||||||
use App\Models\Plan;
|
use App\Models\Plan;
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
@ -37,7 +38,7 @@ class OrderService
|
|||||||
DB::beginTransaction();
|
DB::beginTransaction();
|
||||||
if ($order->surplus_order_ids) {
|
if ($order->surplus_order_ids) {
|
||||||
try {
|
try {
|
||||||
Order::whereIn('id', json_decode($order->surplus_order_ids))->update([
|
Order::whereIn('id', $order->surplus_order_ids)->update([
|
||||||
'status' => 4
|
'status' => 4
|
||||||
]);
|
]);
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
@ -81,25 +82,6 @@ class OrderService
|
|||||||
DB::commit();
|
DB::commit();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function cancel():bool
|
|
||||||
{
|
|
||||||
$order = $this->order;
|
|
||||||
DB::beginTransaction();
|
|
||||||
$order->status = 2;
|
|
||||||
if (!$order->save()) {
|
|
||||||
DB::rollBack();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if ($order->balance_amount) {
|
|
||||||
$userService = new UserService();
|
|
||||||
if (!$userService->addBalance($order->user_id, $order->balance_amount)) {
|
|
||||||
DB::rollBack();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
DB::commit();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setOrderType(User $user)
|
public function setOrderType(User $user)
|
||||||
{
|
{
|
||||||
@ -190,13 +172,13 @@ class OrderService
|
|||||||
$result = $trafficUnitPrice * $notUsedTraffic;
|
$result = $trafficUnitPrice * $notUsedTraffic;
|
||||||
$orderModel = Order::where('user_id', $user->id)->where('cycle', '!=', 'reset_price')->where('status', 3);
|
$orderModel = Order::where('user_id', $user->id)->where('cycle', '!=', 'reset_price')->where('status', 3);
|
||||||
$order->surplus_amount = $result > 0 ? $result : 0;
|
$order->surplus_amount = $result > 0 ? $result : 0;
|
||||||
$order->surplus_order_ids = json_encode(array_column($orderModel->get()->toArray(), 'id'));
|
$order->surplus_order_ids = array_column($orderModel->get()->toArray(), 'id');
|
||||||
}
|
}
|
||||||
|
|
||||||
private function orderIsUsed(Order $order):bool
|
private function orderIsUsed(Order $order):bool
|
||||||
{
|
{
|
||||||
$month = self::STR_TO_TIME[$order->cycle];
|
$month = self::STR_TO_TIME[$order->cycle];
|
||||||
$orderExpireDay = strtotime('+' . $month . ' month', $order->created_at->timestamp);
|
$orderExpireDay = strtotime('+' . $month . ' month', $order->created_at);
|
||||||
if ($orderExpireDay < time()) return true;
|
if ($orderExpireDay < time()) return true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -229,20 +211,40 @@ class OrderService
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
$order->surplus_amount = $orderSurplusAmount > 0 ? $orderSurplusAmount : 0;
|
$order->surplus_amount = $orderSurplusAmount > 0 ? $orderSurplusAmount : 0;
|
||||||
$order->surplus_order_ids = json_encode(array_column($orders->toArray(), 'id'));
|
$order->surplus_order_ids = array_column($orders->toArray(), 'id');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function success(string $callbackNo)
|
public function paid(string $callbackNo)
|
||||||
{
|
{
|
||||||
$order = $this->order;
|
$order = $this->order;
|
||||||
if ($order->status !== 0) {
|
if ($order->status !== 0) return true;
|
||||||
return true;
|
|
||||||
}
|
|
||||||
$order->status = 1;
|
$order->status = 1;
|
||||||
|
$order->paid_at = time();
|
||||||
$order->callback_no = $callbackNo;
|
$order->callback_no = $callbackNo;
|
||||||
return $order->save();
|
if (!$order->save()) return false;
|
||||||
|
OrderHandleJob::dispatch($order->trade_no);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function cancel():bool
|
||||||
|
{
|
||||||
|
$order = $this->order;
|
||||||
|
DB::beginTransaction();
|
||||||
|
$order->status = 2;
|
||||||
|
if (!$order->save()) {
|
||||||
|
DB::rollBack();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ($order->balance_amount) {
|
||||||
|
$userService = new UserService();
|
||||||
|
if (!$userService->addBalance($order->user_id, $order->balance_amount)) {
|
||||||
|
DB::rollBack();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DB::commit();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
private function buyByResetTraffic()
|
private function buyByResetTraffic()
|
||||||
{
|
{
|
||||||
|
@ -22,7 +22,7 @@ class PaymentService
|
|||||||
if ($uuid) $payment = Payment::where('uuid', $uuid)->first()->toArray();
|
if ($uuid) $payment = Payment::where('uuid', $uuid)->first()->toArray();
|
||||||
$this->config = [];
|
$this->config = [];
|
||||||
if (isset($payment)) {
|
if (isset($payment)) {
|
||||||
$this->config = json_decode($payment['config'], true);
|
$this->config = $payment['config'];
|
||||||
$this->config['enable'] = $payment['enable'];
|
$this->config['enable'] = $payment['enable'];
|
||||||
$this->config['id'] = $payment['id'];
|
$this->config['id'] = $payment['id'];
|
||||||
$this->config['uuid'] = $payment['uuid'];
|
$this->config['uuid'] = $payment['uuid'];
|
||||||
|
@ -5,7 +5,7 @@ namespace App\Services;
|
|||||||
use App\Models\ServerLog;
|
use App\Models\ServerLog;
|
||||||
use App\Models\ServerShadowsocks;
|
use App\Models\ServerShadowsocks;
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
use App\Models\Server;
|
use App\Models\ServerV2ray;
|
||||||
use App\Models\ServerTrojan;
|
use App\Models\ServerTrojan;
|
||||||
use App\Utils\CacheKey;
|
use App\Utils\CacheKey;
|
||||||
use Illuminate\Support\Facades\Cache;
|
use Illuminate\Support\Facades\Cache;
|
||||||
@ -18,14 +18,14 @@ class ServerService
|
|||||||
public function getV2ray(User $user, $all = false):array
|
public function getV2ray(User $user, $all = false):array
|
||||||
{
|
{
|
||||||
$servers = [];
|
$servers = [];
|
||||||
$model = Server::orderBy('sort', 'ASC');
|
$model = ServerV2ray::orderBy('sort', 'ASC');
|
||||||
if (!$all) {
|
if (!$all) {
|
||||||
$model->where('show', 1);
|
$model->where('show', 1);
|
||||||
}
|
}
|
||||||
$v2ray = $model->get();
|
$v2ray = $model->get();
|
||||||
for ($i = 0; $i < count($v2ray); $i++) {
|
for ($i = 0; $i < count($v2ray); $i++) {
|
||||||
$v2ray[$i]['type'] = 'v2ray';
|
$v2ray[$i]['type'] = 'v2ray';
|
||||||
$groupId = json_decode($v2ray[$i]['group_id']);
|
$groupId = $v2ray[$i]['group_id'];
|
||||||
if (in_array($user->group_id, $groupId)) {
|
if (in_array($user->group_id, $groupId)) {
|
||||||
if ($v2ray[$i]['parent_id']) {
|
if ($v2ray[$i]['parent_id']) {
|
||||||
$v2ray[$i]['last_check_at'] = Cache::get(CacheKey::get('SERVER_V2RAY_LAST_CHECK_AT', $v2ray[$i]['parent_id']));
|
$v2ray[$i]['last_check_at'] = Cache::get(CacheKey::get('SERVER_V2RAY_LAST_CHECK_AT', $v2ray[$i]['parent_id']));
|
||||||
@ -50,7 +50,7 @@ class ServerService
|
|||||||
$trojan = $model->get();
|
$trojan = $model->get();
|
||||||
for ($i = 0; $i < count($trojan); $i++) {
|
for ($i = 0; $i < count($trojan); $i++) {
|
||||||
$trojan[$i]['type'] = 'trojan';
|
$trojan[$i]['type'] = 'trojan';
|
||||||
$groupId = json_decode($trojan[$i]['group_id']);
|
$groupId = $trojan[$i]['group_id'];
|
||||||
if (in_array($user->group_id, $groupId)) {
|
if (in_array($user->group_id, $groupId)) {
|
||||||
if ($trojan[$i]['parent_id']) {
|
if ($trojan[$i]['parent_id']) {
|
||||||
$trojan[$i]['last_check_at'] = Cache::get(CacheKey::get('SERVER_TROJAN_LAST_CHECK_AT', $trojan[$i]['parent_id']));
|
$trojan[$i]['last_check_at'] = Cache::get(CacheKey::get('SERVER_TROJAN_LAST_CHECK_AT', $trojan[$i]['parent_id']));
|
||||||
@ -73,7 +73,7 @@ class ServerService
|
|||||||
$shadowsocks = $model->get();
|
$shadowsocks = $model->get();
|
||||||
for ($i = 0; $i < count($shadowsocks); $i++) {
|
for ($i = 0; $i < count($shadowsocks); $i++) {
|
||||||
$shadowsocks[$i]['type'] = 'shadowsocks';
|
$shadowsocks[$i]['type'] = 'shadowsocks';
|
||||||
$groupId = json_decode($shadowsocks[$i]['group_id']);
|
$groupId = $shadowsocks[$i]['group_id'];
|
||||||
if (in_array($user->group_id, $groupId)) {
|
if (in_array($user->group_id, $groupId)) {
|
||||||
if ($shadowsocks[$i]['parent_id']) {
|
if ($shadowsocks[$i]['parent_id']) {
|
||||||
$shadowsocks[$i]['last_check_at'] = Cache::get(CacheKey::get('SERVER_SHADOWSOCKS_LAST_CHECK_AT', $shadowsocks[$i]['parent_id']));
|
$shadowsocks[$i]['last_check_at'] = Cache::get(CacheKey::get('SERVER_SHADOWSOCKS_LAST_CHECK_AT', $shadowsocks[$i]['parent_id']));
|
||||||
@ -123,7 +123,7 @@ class ServerService
|
|||||||
|
|
||||||
public function getV2RayConfig(int $nodeId, int $localPort)
|
public function getV2RayConfig(int $nodeId, int $localPort)
|
||||||
{
|
{
|
||||||
$server = Server::find($nodeId);
|
$server = ServerV2ray::find($nodeId);
|
||||||
if (!$server) {
|
if (!$server) {
|
||||||
abort(500, '节点不存在');
|
abort(500, '节点不存在');
|
||||||
}
|
}
|
||||||
@ -156,10 +156,10 @@ class ServerService
|
|||||||
return $json;
|
return $json;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function setDns(Server $server, object $json)
|
private function setDns(ServerV2ray $server, object $json)
|
||||||
{
|
{
|
||||||
if ($server->dnsSettings) {
|
if ($server->dnsSettings) {
|
||||||
$dns = json_decode($server->dnsSettings);
|
$dns = $server->dnsSettings;
|
||||||
if (isset($dns->servers)) {
|
if (isset($dns->servers)) {
|
||||||
array_push($dns->servers, '1.1.1.1');
|
array_push($dns->servers, '1.1.1.1');
|
||||||
array_push($dns->servers, 'localhost');
|
array_push($dns->servers, 'localhost');
|
||||||
@ -169,41 +169,41 @@ class ServerService
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private function setNetwork(Server $server, object $json)
|
private function setNetwork(ServerV2ray $server, object $json)
|
||||||
{
|
{
|
||||||
if ($server->networkSettings) {
|
if ($server->networkSettings) {
|
||||||
switch ($server->network) {
|
switch ($server->network) {
|
||||||
case 'tcp':
|
case 'tcp':
|
||||||
$json->inbound->streamSettings->tcpSettings = json_decode($server->networkSettings);
|
$json->inbound->streamSettings->tcpSettings = $server->networkSettings;
|
||||||
break;
|
break;
|
||||||
case 'kcp':
|
case 'kcp':
|
||||||
$json->inbound->streamSettings->kcpSettings = json_decode($server->networkSettings);
|
$json->inbound->streamSettings->kcpSettings = $server->networkSettings;
|
||||||
break;
|
break;
|
||||||
case 'ws':
|
case 'ws':
|
||||||
$json->inbound->streamSettings->wsSettings = json_decode($server->networkSettings);
|
$json->inbound->streamSettings->wsSettings = $server->networkSettings;
|
||||||
break;
|
break;
|
||||||
case 'http':
|
case 'http':
|
||||||
$json->inbound->streamSettings->httpSettings = json_decode($server->networkSettings);
|
$json->inbound->streamSettings->httpSettings = $server->networkSettings;
|
||||||
break;
|
break;
|
||||||
case 'domainsocket':
|
case 'domainsocket':
|
||||||
$json->inbound->streamSettings->dsSettings = json_decode($server->networkSettings);
|
$json->inbound->streamSettings->dsSettings = $server->networkSettings;
|
||||||
break;
|
break;
|
||||||
case 'quic':
|
case 'quic':
|
||||||
$json->inbound->streamSettings->quicSettings = json_decode($server->networkSettings);
|
$json->inbound->streamSettings->quicSettings = $server->networkSettings;
|
||||||
break;
|
break;
|
||||||
case 'grpc':
|
case 'grpc':
|
||||||
$json->inbound->streamSettings->grpcSettings = json_decode($server->networkSettings);
|
$json->inbound->streamSettings->grpcSettings = $server->networkSettings;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private function setRule(Server $server, object $json)
|
private function setRule(ServerV2ray $server, object $json)
|
||||||
{
|
{
|
||||||
$domainRules = array_filter(explode(PHP_EOL, config('v2board.server_v2ray_domain')));
|
$domainRules = array_filter(explode(PHP_EOL, config('v2board.server_v2ray_domain')));
|
||||||
$protocolRules = array_filter(explode(PHP_EOL, config('v2board.server_v2ray_protocol')));
|
$protocolRules = array_filter(explode(PHP_EOL, config('v2board.server_v2ray_protocol')));
|
||||||
if ($server->ruleSettings) {
|
if ($server->ruleSettings) {
|
||||||
$ruleSettings = json_decode($server->ruleSettings);
|
$ruleSettings = $server->ruleSettings;
|
||||||
// domain
|
// domain
|
||||||
if (isset($ruleSettings->domain)) {
|
if (isset($ruleSettings->domain)) {
|
||||||
$ruleSettings->domain = array_filter($ruleSettings->domain);
|
$ruleSettings->domain = array_filter($ruleSettings->domain);
|
||||||
@ -238,10 +238,10 @@ class ServerService
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private function setTls(Server $server, object $json)
|
private function setTls(ServerV2ray $server, object $json)
|
||||||
{
|
{
|
||||||
if ((int)$server->tls) {
|
if ((int)$server->tls) {
|
||||||
$tlsSettings = json_decode($server->tlsSettings);
|
$tlsSettings = $server->tlsSettings;
|
||||||
$json->inbound->streamSettings->security = 'tls';
|
$json->inbound->streamSettings->security = 'tls';
|
||||||
$tls = (object)[
|
$tls = (object)[
|
||||||
'certificateFile' => '/root/.cert/server.crt',
|
'certificateFile' => '/root/.cert/server.crt',
|
||||||
@ -260,20 +260,23 @@ class ServerService
|
|||||||
|
|
||||||
public function log(int $userId, int $serverId, int $u, int $d, float $rate, string $method)
|
public function log(int $userId, int $serverId, int $u, int $d, float $rate, string $method)
|
||||||
{
|
{
|
||||||
if (($u + $d) <= 10240) return;
|
if (($u + $d) < 10240) return true;
|
||||||
$timestamp = strtotime(date('Y-m-d H:0'));
|
$timestamp = strtotime(date('Y-m-d'));
|
||||||
$serverLog = ServerLog::where('log_at', '>=', $timestamp)
|
$serverLog = ServerLog::where('log_at', '>=', $timestamp)
|
||||||
->where('log_at', '<', $timestamp + 3600)
|
->where('log_at', '<', $timestamp + 3600)
|
||||||
->where('server_id', $serverId)
|
->where('server_id', $serverId)
|
||||||
->where('user_id', $userId)
|
->where('user_id', $userId)
|
||||||
->where('rate', $rate)
|
->where('rate', $rate)
|
||||||
->where('method', $method)
|
->where('method', $method)
|
||||||
->lockForUpdate()
|
|
||||||
->first();
|
->first();
|
||||||
if ($serverLog) {
|
if ($serverLog) {
|
||||||
$serverLog->u = $serverLog->u + $u;
|
try {
|
||||||
$serverLog->d = $serverLog->d + $d;
|
$serverLog->increment('u', $u);
|
||||||
$serverLog->save();
|
$serverLog->increment('d', $d);
|
||||||
|
return true;
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
$serverLog = new ServerLog();
|
$serverLog = new ServerLog();
|
||||||
$serverLog->user_id = $userId;
|
$serverLog->user_id = $userId;
|
||||||
@ -283,7 +286,7 @@ class ServerService
|
|||||||
$serverLog->rate = $rate;
|
$serverLog->rate = $rate;
|
||||||
$serverLog->log_at = $timestamp;
|
$serverLog->log_at = $timestamp;
|
||||||
$serverLog->method = $method;
|
$serverLog->method = $method;
|
||||||
$serverLog->save();
|
return $serverLog->save();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -292,32 +295,15 @@ class ServerService
|
|||||||
$server = ServerShadowsocks::orderBy('sort', 'ASC')->get();
|
$server = ServerShadowsocks::orderBy('sort', 'ASC')->get();
|
||||||
for ($i = 0; $i < count($server); $i++) {
|
for ($i = 0; $i < count($server); $i++) {
|
||||||
$server[$i]['type'] = 'shadowsocks';
|
$server[$i]['type'] = 'shadowsocks';
|
||||||
if (!empty($server[$i]['tags'])) {
|
|
||||||
$server[$i]['tags'] = json_decode($server[$i]['tags']);
|
|
||||||
}
|
|
||||||
$server[$i]['group_id'] = json_decode($server[$i]['group_id']);
|
|
||||||
}
|
}
|
||||||
return $server->toArray();
|
return $server->toArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getV2rayServers()
|
public function getV2rayServers()
|
||||||
{
|
{
|
||||||
$server = Server::orderBy('sort', 'ASC')->get();
|
$server = ServerV2ray::orderBy('sort', 'ASC')->get();
|
||||||
for ($i = 0; $i < count($server); $i++) {
|
for ($i = 0; $i < count($server); $i++) {
|
||||||
$server[$i]['type'] = 'v2ray';
|
$server[$i]['type'] = 'v2ray';
|
||||||
if (!empty($server[$i]['tags'])) {
|
|
||||||
$server[$i]['tags'] = json_decode($server[$i]['tags']);
|
|
||||||
}
|
|
||||||
if (!empty($server[$i]['dnsSettings'])) {
|
|
||||||
$server[$i]['dnsSettings'] = json_decode($server[$i]['dnsSettings']);
|
|
||||||
}
|
|
||||||
if (!empty($server[$i]['tlsSettings'])) {
|
|
||||||
$server[$i]['tlsSettings'] = json_decode($server[$i]['tlsSettings']);
|
|
||||||
}
|
|
||||||
if (!empty($server[$i]['ruleSettings'])) {
|
|
||||||
$server[$i]['ruleSettings'] = json_decode($server[$i]['ruleSettings']);
|
|
||||||
}
|
|
||||||
$server[$i]['group_id'] = json_decode($server[$i]['group_id']);
|
|
||||||
}
|
}
|
||||||
return $server->toArray();
|
return $server->toArray();
|
||||||
}
|
}
|
||||||
@ -327,10 +313,6 @@ class ServerService
|
|||||||
$server = ServerTrojan::orderBy('sort', 'ASC')->get();
|
$server = ServerTrojan::orderBy('sort', 'ASC')->get();
|
||||||
for ($i = 0; $i < count($server); $i++) {
|
for ($i = 0; $i < count($server); $i++) {
|
||||||
$server[$i]['type'] = 'trojan';
|
$server[$i]['type'] = 'trojan';
|
||||||
if (!empty($server[$i]['tags'])) {
|
|
||||||
$server[$i]['tags'] = json_decode($server[$i]['tags']);
|
|
||||||
}
|
|
||||||
$server[$i]['group_id'] = json_decode($server[$i]['group_id']);
|
|
||||||
}
|
}
|
||||||
return $server->toArray();
|
return $server->toArray();
|
||||||
}
|
}
|
||||||
|
@ -40,6 +40,7 @@ class TelegramService {
|
|||||||
$curl->get($this->api . $method . '?' . http_build_query($params));
|
$curl->get($this->api . $method . '?' . http_build_query($params));
|
||||||
$response = $curl->response;
|
$response = $curl->response;
|
||||||
$curl->close();
|
$curl->close();
|
||||||
|
if (!isset($response->ok)) abort(500, '请求失败');
|
||||||
if (!$response->ok) {
|
if (!$response->ok) {
|
||||||
abort(500, '来自TG的错误:' . $response->description);
|
abort(500, '来自TG的错误:' . $response->description);
|
||||||
}
|
}
|
||||||
|
@ -12,6 +12,7 @@ use Illuminate\Support\Facades\DB;
|
|||||||
class TicketService {
|
class TicketService {
|
||||||
public function replyByAdmin($ticketId, $message, $userId):void
|
public function replyByAdmin($ticketId, $message, $userId):void
|
||||||
{
|
{
|
||||||
|
if ($message)
|
||||||
$ticket = Ticket::where('id', $ticketId)
|
$ticket = Ticket::where('id', $ticketId)
|
||||||
->first();
|
->first();
|
||||||
if (!$ticket) {
|
if (!$ticket) {
|
||||||
|
@ -2,9 +2,11 @@
|
|||||||
|
|
||||||
namespace App\Services;
|
namespace App\Services;
|
||||||
|
|
||||||
|
use App\Jobs\ServerLogJob;
|
||||||
|
use App\Jobs\TrafficFetchJob;
|
||||||
use App\Models\InviteCode;
|
use App\Models\InviteCode;
|
||||||
use App\Models\Order;
|
use App\Models\Order;
|
||||||
use App\Models\Server;
|
use App\Models\ServerV2ray;
|
||||||
use App\Models\Ticket;
|
use App\Models\Ticket;
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
use Illuminate\Support\Facades\DB;
|
use Illuminate\Support\Facades\DB;
|
||||||
@ -80,33 +82,9 @@ class UserService
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function trafficFetch(int $u, int $d, int $userId, object $server, string $protocol):bool
|
public function trafficFetch(int $u, int $d, int $userId, object $server, string $protocol)
|
||||||
{
|
{
|
||||||
$user = User::lockForUpdate()
|
TrafficFetchJob::dispatch($u, $d, $userId, $server, $protocol);
|
||||||
->find($userId);
|
ServerLogJob::dispatch($u, $d, $userId, $server, $protocol);
|
||||||
if (!$user) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
$user->t = time();
|
|
||||||
$user->u = $user->u + $u;
|
|
||||||
$user->d = $user->d + $d;
|
|
||||||
if (!$user->save()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
$mailService = new MailService();
|
|
||||||
$serverService = new ServerService();
|
|
||||||
try {
|
|
||||||
$mailService->remindTraffic($user);
|
|
||||||
$serverService->log(
|
|
||||||
$userId,
|
|
||||||
$server->id,
|
|
||||||
$u,
|
|
||||||
$d,
|
|
||||||
$server->rate,
|
|
||||||
$protocol
|
|
||||||
);
|
|
||||||
} catch (\Exception $e) {
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,7 @@ class CacheKey
|
|||||||
'SERVER_SHADOWSOCKS_LAST_CHECK_AT' => 'ss节点最后检查时间',
|
'SERVER_SHADOWSOCKS_LAST_CHECK_AT' => 'ss节点最后检查时间',
|
||||||
'SERVER_SHADOWSOCKS_LAST_PUSH_AT' => 'ss节点最后推送时间',
|
'SERVER_SHADOWSOCKS_LAST_PUSH_AT' => 'ss节点最后推送时间',
|
||||||
'TEMP_TOKEN' => '临时令牌',
|
'TEMP_TOKEN' => '临时令牌',
|
||||||
'LAST_SEND_EMAIL_REMIND_TRAFFIC'
|
'LAST_SEND_EMAIL_REMIND_TRAFFIC' => '最后发送流量邮件提醒'
|
||||||
];
|
];
|
||||||
|
|
||||||
public static function get(string $key, $uniqueValue)
|
public static function get(string $key, $uniqueValue)
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
namespace App\Utils;
|
namespace App\Utils;
|
||||||
|
|
||||||
use App\Models\Server;
|
use App\Models\ServerV2ray;
|
||||||
use App\Models\ServerShadowsocks;
|
use App\Models\ServerShadowsocks;
|
||||||
use App\Models\ServerTrojan;
|
use App\Models\ServerTrojan;
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
@ -23,6 +23,12 @@ class Helper
|
|||||||
return md5(vsprintf('%s%s-%s-%s-%s-%s%s%s', str_split(bin2hex($data), 4)) . '-' . time());
|
return md5(vsprintf('%s%s-%s-%s-%s-%s%s%s', str_split(bin2hex($data), 4)) . '-' . time());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static function generateOrderNo(): string
|
||||||
|
{
|
||||||
|
$randomChar = rand(10000, 99999);
|
||||||
|
return date('YmdHms') . $randomChar;
|
||||||
|
}
|
||||||
|
|
||||||
public static function exchange($from, $to)
|
public static function exchange($from, $to)
|
||||||
{
|
{
|
||||||
$result = file_get_contents('https://api.exchangerate.host/latest?symbols=' . $to . '&base=' . $from);
|
$result = file_get_contents('https://api.exchangerate.host/latest?symbols=' . $to . '&base=' . $from);
|
||||||
@ -58,11 +64,12 @@ class Helper
|
|||||||
return $str;
|
return $str;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function multiPasswordVerify($algo, $password, $hash)
|
public static function multiPasswordVerify($algo, $salt, $password, $hash)
|
||||||
{
|
{
|
||||||
switch($algo) {
|
switch($algo) {
|
||||||
case 'md5': return md5($password) === $hash;
|
case 'md5': return md5($password) === $hash;
|
||||||
case 'sha256': return hash('sha256', $password) === $hash;
|
case 'sha256': return hash('sha256', $password) === $hash;
|
||||||
|
case 'md5salt': return md5($password . $salt) === $hash;
|
||||||
default: return password_verify($password, $hash);
|
default: return password_verify($password, $hash);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -95,4 +102,14 @@ class Helper
|
|||||||
return round($byte, 2) . ' B';
|
return round($byte, 2) . ' B';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static function getSubscribeHost()
|
||||||
|
{
|
||||||
|
$subscribeUrl = config('v2board.app_url');
|
||||||
|
$subscribeUrls = explode(',', config('v2board.subscribe_url'));
|
||||||
|
if ($subscribeUrls && $subscribeUrls[0]) {
|
||||||
|
$subscribeUrl = $subscribeUrls[rand(0, count($subscribeUrls) - 1)];
|
||||||
|
}
|
||||||
|
return $subscribeUrl;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,31 +1,37 @@
|
|||||||
{
|
{
|
||||||
"name": "v2board/v2board",
|
"name": "v2board/v2board",
|
||||||
"type": "project",
|
"type": "project",
|
||||||
"description": "v2board is a v2ray manage.",
|
"description": "v2board is a proxy protocol manage.",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"v2board",
|
"v2board",
|
||||||
"v2ray",
|
"v2ray",
|
||||||
|
"shadowsocks",
|
||||||
|
"trojan",
|
||||||
"laravel"
|
"laravel"
|
||||||
],
|
],
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"require": {
|
"require": {
|
||||||
"php": "^7.2",
|
"php": "^7.2.5|^8.0",
|
||||||
"fideloper/proxy": "^4.0",
|
"fideloper/proxy": "^4.4",
|
||||||
|
"fruitcake/laravel-cors": "^2.0",
|
||||||
"google/recaptcha": "^1.2",
|
"google/recaptcha": "^1.2",
|
||||||
"laravel/framework": "^6.0",
|
"guzzlehttp/guzzle": "^6.3.1|^7.0.1",
|
||||||
"laravel/tinker": "^1.0",
|
"laravel/framework": "^7.29",
|
||||||
"lokielse/omnipay-alipay": "3.0.6",
|
"laravel/horizon": "^4.3.5",
|
||||||
|
"laravel/tinker": "^2.5",
|
||||||
|
"linfo/linfo": "^4.0",
|
||||||
|
"lokielse/omnipay-alipay": "3.1.2",
|
||||||
"lokielse/omnipay-wechatpay": "^3.0",
|
"lokielse/omnipay-wechatpay": "^3.0",
|
||||||
"php-curl-class/php-curl-class": "^8.6",
|
"php-curl-class/php-curl-class": "^8.6",
|
||||||
"stripe/stripe-php": "^7.36.1",
|
"stripe/stripe-php": "^7.36.1",
|
||||||
"symfony/yaml": "^4.3"
|
"symfony/yaml": "^4.3"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"facade/ignition": "^1.4",
|
"facade/ignition": "^2.0",
|
||||||
"fzaninotto/faker": "^1.4",
|
"fakerphp/faker": "^1.9.1",
|
||||||
"mockery/mockery": "^1.0",
|
"mockery/mockery": "^1.3.1",
|
||||||
"nunomaduro/collision": "^3.0",
|
"nunomaduro/collision": "^4.3",
|
||||||
"phpunit/phpunit": "^8.0"
|
"phpunit/phpunit": "^8.5.8|^9.3.3"
|
||||||
},
|
},
|
||||||
"config": {
|
"config": {
|
||||||
"optimize-autoloader": true,
|
"optimize-autoloader": true,
|
||||||
|
@ -173,6 +173,7 @@ return [
|
|||||||
App\Providers\AuthServiceProvider::class,
|
App\Providers\AuthServiceProvider::class,
|
||||||
// App\Providers\BroadcastServiceProvider::class,
|
// App\Providers\BroadcastServiceProvider::class,
|
||||||
App\Providers\EventServiceProvider::class,
|
App\Providers\EventServiceProvider::class,
|
||||||
|
App\Providers\HorizonServiceProvider::class,
|
||||||
App\Providers\RouteServiceProvider::class,
|
App\Providers\RouteServiceProvider::class,
|
||||||
|
|
||||||
],
|
],
|
||||||
@ -236,5 +237,5 @@ return [
|
|||||||
| The only modification by laravel config
|
| The only modification by laravel config
|
||||||
|
|
|
|
||||||
*/
|
*/
|
||||||
'version' => '1.5.2.1627559775390'
|
'version' => '1.5.3.1628409393360'
|
||||||
];
|
];
|
||||||
|
34
config/cors.php
Normal file
34
config/cors.php
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
return [
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Cross-Origin Resource Sharing (CORS) Configuration
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| Here you may configure your settings for cross-origin resource sharing
|
||||||
|
| or "CORS". This determines what cross-origin operations may execute
|
||||||
|
| in web browsers. You are free to adjust these settings as needed.
|
||||||
|
|
|
||||||
|
| To learn more: https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'paths' => ['api/*'],
|
||||||
|
|
||||||
|
'allowed_methods' => ['*'],
|
||||||
|
|
||||||
|
'allowed_origins' => ['*'],
|
||||||
|
|
||||||
|
'allowed_origins_patterns' => [],
|
||||||
|
|
||||||
|
'allowed_headers' => ['*'],
|
||||||
|
|
||||||
|
'exposed_headers' => [],
|
||||||
|
|
||||||
|
'max_age' => 0,
|
||||||
|
|
||||||
|
'supports_credentials' => false,
|
||||||
|
|
||||||
|
];
|
191
config/horizon.php
Normal file
191
config/horizon.php
Normal file
@ -0,0 +1,191 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Support\Str;
|
||||||
|
use Linfo\Linfo;
|
||||||
|
|
||||||
|
$lInfo = new Linfo();
|
||||||
|
$parser = $lInfo->getParser();
|
||||||
|
|
||||||
|
return [
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Horizon Domain
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| This is the subdomain where Horizon will be accessible from. If this
|
||||||
|
| setting is null, Horizon will reside under the same domain as the
|
||||||
|
| application. Otherwise, this value will serve as the subdomain.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'domain' => null,
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Horizon Path
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| This is the URI path where Horizon will be accessible from. Feel free
|
||||||
|
| to change this path to anything you like. Note that the URI will not
|
||||||
|
| affect the paths of its internal API that aren't exposed to users.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'path' => 'monitor',
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Horizon Redis Connection
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| This is the name of the Redis connection where Horizon will store the
|
||||||
|
| meta information required for it to function. It includes the list
|
||||||
|
| of supervisors, failed jobs, job metrics, and other information.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'use' => 'default',
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Horizon Redis Prefix
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| This prefix will be used when storing all Horizon data in Redis. You
|
||||||
|
| may modify the prefix when you are running multiple installations
|
||||||
|
| of Horizon on the same server so that they don't have problems.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'prefix' => env(
|
||||||
|
'HORIZON_PREFIX',
|
||||||
|
Str::slug(env('APP_NAME', 'laravel'), '_').'_horizon:'
|
||||||
|
),
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Horizon Route Middleware
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| These middleware will get attached onto each Horizon route, giving you
|
||||||
|
| the chance to add your own middleware to this list or change any of
|
||||||
|
| the existing middleware. Or, you can simply stick with this list.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'middleware' => ['web', 'admin'],
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Queue Wait Time Thresholds
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| This option allows you to configure when the LongWaitDetected event
|
||||||
|
| will be fired. Every connection / queue combination may have its
|
||||||
|
| own, unique threshold (in seconds) before this event is fired.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'waits' => [
|
||||||
|
'redis:default' => 60,
|
||||||
|
],
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Job Trimming Times
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| Here you can configure for how long (in minutes) you desire Horizon to
|
||||||
|
| persist the recent and failed jobs. Typically, recent jobs are kept
|
||||||
|
| for one hour while all failed jobs are stored for an entire week.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'trim' => [
|
||||||
|
'recent' => 60,
|
||||||
|
'pending' => 60,
|
||||||
|
'completed' => 60,
|
||||||
|
'recent_failed' => 10080,
|
||||||
|
'failed' => 10080,
|
||||||
|
'monitored' => 10080,
|
||||||
|
],
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Metrics
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| Here you can configure how many snapshots should be kept to display in
|
||||||
|
| the metrics graph. This will get used in combination with Horizon's
|
||||||
|
| `horizon:snapshot` schedule to define how long to retain metrics.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'metrics' => [
|
||||||
|
'trim_snapshots' => [
|
||||||
|
'job' => 24,
|
||||||
|
'queue' => 24,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Fast Termination
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| When this option is enabled, Horizon's "terminate" command will not
|
||||||
|
| wait on all of the workers to terminate unless the --wait option
|
||||||
|
| is provided. Fast termination can shorten deployment delay by
|
||||||
|
| allowing a new instance of Horizon to start while the last
|
||||||
|
| instance will continue to terminate each of its workers.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'fast_termination' => false,
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Memory Limit (MB)
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| This value describes the maximum amount of memory the Horizon worker
|
||||||
|
| may consume before it is terminated and restarted. You should set
|
||||||
|
| this value according to the resources available to your server.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'memory_limit' => 32,
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Queue Worker Configuration
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| Here you may define the queue worker settings used by your application
|
||||||
|
| in all environments. These supervisors and settings handle all your
|
||||||
|
| queued jobs and will be provisioned by Horizon during deployment.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'environments' => [
|
||||||
|
'local' => [
|
||||||
|
'V2board' => [
|
||||||
|
'connection' => 'redis',
|
||||||
|
'queue' => [
|
||||||
|
'traffic_fetch',
|
||||||
|
'server_log',
|
||||||
|
'send_email',
|
||||||
|
'send_telegram',
|
||||||
|
'stat_server',
|
||||||
|
'order_handle'
|
||||||
|
],
|
||||||
|
'balance' => 'auto',
|
||||||
|
'minProcesses' => 1,
|
||||||
|
'maxProcesses' => (int)ceil($parser->getRam()['total'] / 1024 / 1024 / 1024 * 6),
|
||||||
|
'tries' => 1,
|
||||||
|
'nice' => 0,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
],
|
||||||
|
];
|
@ -19,6 +19,20 @@ CREATE TABLE `failed_jobs` (
|
|||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||||
|
|
||||||
|
|
||||||
|
DROP TABLE IF EXISTS `v2_commission_log`;
|
||||||
|
CREATE TABLE `v2_commission_log` (
|
||||||
|
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||||
|
`invite_user_id` int(11) NOT NULL,
|
||||||
|
`user_id` int(11) NOT NULL,
|
||||||
|
`trade_no` char(36) NOT NULL,
|
||||||
|
`order_amount` int(11) NOT NULL,
|
||||||
|
`get_amount` int(11) NOT NULL,
|
||||||
|
`created_at` int(11) NOT NULL,
|
||||||
|
`updated_at` int(11) NOT NULL,
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||||
|
|
||||||
|
|
||||||
DROP TABLE IF EXISTS `v2_coupon`;
|
DROP TABLE IF EXISTS `v2_coupon`;
|
||||||
CREATE TABLE `v2_coupon` (
|
CREATE TABLE `v2_coupon` (
|
||||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||||
@ -27,6 +41,7 @@ CREATE TABLE `v2_coupon` (
|
|||||||
`type` tinyint(1) NOT NULL,
|
`type` tinyint(1) NOT NULL,
|
||||||
`value` int(11) NOT NULL,
|
`value` int(11) NOT NULL,
|
||||||
`limit_use` int(11) DEFAULT NULL,
|
`limit_use` int(11) DEFAULT NULL,
|
||||||
|
`limit_use_with_user` int(11) DEFAULT NULL,
|
||||||
`limit_plan_ids` varchar(255) DEFAULT NULL,
|
`limit_plan_ids` varchar(255) DEFAULT NULL,
|
||||||
`started_at` int(11) NOT NULL,
|
`started_at` int(11) NOT NULL,
|
||||||
`ended_at` int(11) NOT NULL,
|
`ended_at` int(11) NOT NULL,
|
||||||
@ -110,6 +125,7 @@ CREATE TABLE `v2_order` (
|
|||||||
`status` tinyint(1) NOT NULL DEFAULT '0' COMMENT '0待支付1开通中2已取消3已完成4已折抵',
|
`status` tinyint(1) NOT NULL DEFAULT '0' COMMENT '0待支付1开通中2已取消3已完成4已折抵',
|
||||||
`commission_status` tinyint(1) NOT NULL DEFAULT '0' COMMENT '0待确认1发放中2有效3无效',
|
`commission_status` tinyint(1) NOT NULL DEFAULT '0' COMMENT '0待确认1发放中2有效3无效',
|
||||||
`commission_balance` int(11) NOT NULL DEFAULT '0',
|
`commission_balance` int(11) NOT NULL DEFAULT '0',
|
||||||
|
`paid_at` int(11) DEFAULT NULL,
|
||||||
`created_at` int(11) NOT NULL,
|
`created_at` int(11) NOT NULL,
|
||||||
`updated_at` int(11) NOT NULL,
|
`updated_at` int(11) NOT NULL,
|
||||||
PRIMARY KEY (`id`)
|
PRIMARY KEY (`id`)
|
||||||
@ -149,40 +165,13 @@ CREATE TABLE `v2_plan` (
|
|||||||
`three_year_price` int(11) DEFAULT NULL,
|
`three_year_price` int(11) DEFAULT NULL,
|
||||||
`onetime_price` int(11) DEFAULT NULL,
|
`onetime_price` int(11) DEFAULT NULL,
|
||||||
`reset_price` int(11) DEFAULT NULL,
|
`reset_price` int(11) DEFAULT NULL,
|
||||||
|
`reset_traffic_method` tinyint(1) DEFAULT NULL,
|
||||||
`created_at` int(11) NOT NULL,
|
`created_at` int(11) NOT NULL,
|
||||||
`updated_at` int(11) NOT NULL,
|
`updated_at` int(11) NOT NULL,
|
||||||
PRIMARY KEY (`id`)
|
PRIMARY KEY (`id`)
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||||
|
|
||||||
|
|
||||||
DROP TABLE IF EXISTS `v2_server`;
|
|
||||||
CREATE TABLE `v2_server` (
|
|
||||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
|
||||||
`group_id` varchar(255) NOT NULL,
|
|
||||||
`name` varchar(255) CHARACTER SET utf8mb4 NOT NULL,
|
|
||||||
`parent_id` int(11) DEFAULT NULL,
|
|
||||||
`host` varchar(255) NOT NULL,
|
|
||||||
`port` int(11) NOT NULL,
|
|
||||||
`server_port` int(11) NOT NULL,
|
|
||||||
`tls` tinyint(4) NOT NULL DEFAULT '0',
|
|
||||||
`tags` varchar(255) DEFAULT NULL,
|
|
||||||
`rate` varchar(11) NOT NULL,
|
|
||||||
`network` text NOT NULL,
|
|
||||||
`alter_id` int(11) NOT NULL DEFAULT '1',
|
|
||||||
`settings` text,
|
|
||||||
`rules` text,
|
|
||||||
`networkSettings` text,
|
|
||||||
`tlsSettings` text,
|
|
||||||
`ruleSettings` text,
|
|
||||||
`dnsSettings` text,
|
|
||||||
`show` tinyint(1) NOT NULL DEFAULT '0',
|
|
||||||
`sort` int(11) DEFAULT NULL,
|
|
||||||
`created_at` int(11) NOT NULL,
|
|
||||||
`updated_at` int(11) NOT NULL,
|
|
||||||
PRIMARY KEY (`id`)
|
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
|
||||||
|
|
||||||
|
|
||||||
DROP TABLE IF EXISTS `v2_server_group`;
|
DROP TABLE IF EXISTS `v2_server_group`;
|
||||||
CREATE TABLE `v2_server_group` (
|
CREATE TABLE `v2_server_group` (
|
||||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||||
@ -206,7 +195,9 @@ CREATE TABLE `v2_server_log` (
|
|||||||
`created_at` int(11) NOT NULL,
|
`created_at` int(11) NOT NULL,
|
||||||
`updated_at` int(11) NOT NULL,
|
`updated_at` int(11) NOT NULL,
|
||||||
PRIMARY KEY (`id`),
|
PRIMARY KEY (`id`),
|
||||||
KEY `log_at` (`log_at`)
|
KEY `log_at` (`log_at`),
|
||||||
|
KEY `user_id` (`user_id`),
|
||||||
|
KEY `server_id` (`server_id`)
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||||
|
|
||||||
|
|
||||||
@ -251,6 +242,34 @@ CREATE TABLE `v2_server_trojan` (
|
|||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='trojan伺服器表';
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='trojan伺服器表';
|
||||||
|
|
||||||
|
|
||||||
|
DROP TABLE IF EXISTS `v2_server_v2ray`;
|
||||||
|
CREATE TABLE `v2_server_v2ray` (
|
||||||
|
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||||
|
`group_id` varchar(255) NOT NULL,
|
||||||
|
`name` varchar(255) CHARACTER SET utf8mb4 NOT NULL,
|
||||||
|
`parent_id` int(11) DEFAULT NULL,
|
||||||
|
`host` varchar(255) NOT NULL,
|
||||||
|
`port` int(11) NOT NULL,
|
||||||
|
`server_port` int(11) NOT NULL,
|
||||||
|
`tls` tinyint(4) NOT NULL DEFAULT '0',
|
||||||
|
`tags` varchar(255) DEFAULT NULL,
|
||||||
|
`rate` varchar(11) NOT NULL,
|
||||||
|
`network` text NOT NULL,
|
||||||
|
`alter_id` int(11) NOT NULL DEFAULT '1',
|
||||||
|
`settings` text,
|
||||||
|
`rules` text,
|
||||||
|
`networkSettings` text,
|
||||||
|
`tlsSettings` text,
|
||||||
|
`ruleSettings` text,
|
||||||
|
`dnsSettings` text,
|
||||||
|
`show` tinyint(1) NOT NULL DEFAULT '0',
|
||||||
|
`sort` int(11) DEFAULT NULL,
|
||||||
|
`created_at` int(11) NOT NULL,
|
||||||
|
`updated_at` int(11) NOT NULL,
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||||
|
|
||||||
|
|
||||||
DROP TABLE IF EXISTS `v2_stat_order`;
|
DROP TABLE IF EXISTS `v2_stat_order`;
|
||||||
CREATE TABLE `v2_stat_order` (
|
CREATE TABLE `v2_stat_order` (
|
||||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||||
@ -304,7 +323,7 @@ CREATE TABLE `v2_ticket_message` (
|
|||||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||||
`user_id` int(11) NOT NULL,
|
`user_id` int(11) NOT NULL,
|
||||||
`ticket_id` int(11) NOT NULL,
|
`ticket_id` int(11) NOT NULL,
|
||||||
`message` varchar(255) NOT NULL,
|
`message` text CHARACTER SET utf8mb4 NOT NULL,
|
||||||
`created_at` int(11) NOT NULL,
|
`created_at` int(11) NOT NULL,
|
||||||
`updated_at` int(11) NOT NULL,
|
`updated_at` int(11) NOT NULL,
|
||||||
PRIMARY KEY (`id`)
|
PRIMARY KEY (`id`)
|
||||||
@ -319,6 +338,7 @@ CREATE TABLE `v2_user` (
|
|||||||
`email` varchar(64) NOT NULL,
|
`email` varchar(64) NOT NULL,
|
||||||
`password` varchar(64) NOT NULL,
|
`password` varchar(64) NOT NULL,
|
||||||
`password_algo` char(10) DEFAULT NULL,
|
`password_algo` char(10) DEFAULT NULL,
|
||||||
|
`password_salt` char(10) DEFAULT NULL,
|
||||||
`balance` int(11) NOT NULL DEFAULT '0',
|
`balance` int(11) NOT NULL DEFAULT '0',
|
||||||
`discount` int(11) DEFAULT NULL,
|
`discount` int(11) DEFAULT NULL,
|
||||||
`commission_type` tinyint(4) NOT NULL DEFAULT '0' COMMENT '0: system 1: cycle 2: onetime',
|
`commission_type` tinyint(4) NOT NULL DEFAULT '0' COMMENT '0: system 1: cycle 2: onetime',
|
||||||
@ -336,8 +356,8 @@ CREATE TABLE `v2_user` (
|
|||||||
`uuid` varchar(36) NOT NULL,
|
`uuid` varchar(36) NOT NULL,
|
||||||
`group_id` int(11) DEFAULT NULL,
|
`group_id` int(11) DEFAULT NULL,
|
||||||
`plan_id` int(11) DEFAULT NULL,
|
`plan_id` int(11) DEFAULT NULL,
|
||||||
`remind_expire` tinyint(4) DEFAULT '1',
|
`remind_expire` tinyint(4) DEFAULT '0',
|
||||||
`remind_traffic` tinyint(4) DEFAULT '1',
|
`remind_traffic` tinyint(4) DEFAULT '0',
|
||||||
`token` char(32) NOT NULL,
|
`token` char(32) NOT NULL,
|
||||||
`remarks` text,
|
`remarks` text,
|
||||||
`expired_at` bigint(20) DEFAULT '0',
|
`expired_at` bigint(20) DEFAULT '0',
|
||||||
@ -348,4 +368,4 @@ CREATE TABLE `v2_user` (
|
|||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||||
|
|
||||||
|
|
||||||
-- 2021-07-13 13:50:52
|
-- 2021-09-21 10:07:22
|
||||||
|
@ -425,3 +425,40 @@ DROP INDEX `email_deleted_at`;
|
|||||||
|
|
||||||
ALTER TABLE `v2_user`
|
ALTER TABLE `v2_user`
|
||||||
ADD `commission_type` tinyint NOT NULL DEFAULT '0' COMMENT '0: system 1: cycle 2: onetime' AFTER `discount`;
|
ADD `commission_type` tinyint NOT NULL DEFAULT '0' COMMENT '0: system 1: cycle 2: onetime' AFTER `discount`;
|
||||||
|
|
||||||
|
ALTER TABLE `v2_order`
|
||||||
|
ADD `paid_at` int(11) NULL AFTER `commission_balance`;
|
||||||
|
|
||||||
|
ALTER TABLE `v2_server_log`
|
||||||
|
ADD INDEX `user_id` (`user_id`),
|
||||||
|
ADD INDEX `server_id` (`server_id`);
|
||||||
|
|
||||||
|
ALTER TABLE `v2_ticket_message`
|
||||||
|
CHANGE `message` `message` text COLLATE 'utf8mb4_general_ci' NOT NULL AFTER `ticket_id`;
|
||||||
|
|
||||||
|
ALTER TABLE `v2_coupon`
|
||||||
|
ADD `limit_use_with_user` int(11) NULL AFTER `limit_use`;
|
||||||
|
|
||||||
|
ALTER TABLE `v2_user`
|
||||||
|
ADD `password_salt` char(10) COLLATE 'utf8_general_ci' NULL AFTER `password_algo`;
|
||||||
|
|
||||||
|
CREATE TABLE `v2_commission_log` (
|
||||||
|
`id` int NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||||
|
`invite_user_id` int(11) NOT NULL,
|
||||||
|
`user_id` int(11) NOT NULL,
|
||||||
|
`trade_no` char(36) NOT NULL,
|
||||||
|
`order_amount` int(11) NOT NULL,
|
||||||
|
`get_amount` int(11) NOT NULL,
|
||||||
|
`created_at` int(11) NOT NULL,
|
||||||
|
`updated_at` int(11) NOT NULL
|
||||||
|
) COLLATE 'utf8mb4_general_ci';
|
||||||
|
|
||||||
|
ALTER TABLE `v2_plan`
|
||||||
|
ADD `reset_traffic_method` tinyint(1) NULL AFTER `reset_price`;
|
||||||
|
|
||||||
|
ALTER TABLE `v2_server`
|
||||||
|
RENAME TO `v2_server_v2ray`;
|
||||||
|
|
||||||
|
ALTER TABLE `v2_user`
|
||||||
|
CHANGE `remind_expire` `remind_expire` tinyint(4) NULL DEFAULT '0' AFTER `plan_id`,
|
||||||
|
CHANGE `remind_traffic` `remind_traffic` tinyint(4) NULL DEFAULT '0' AFTER `remind_expire`;
|
||||||
|
1
init.sh
1
init.sh
@ -1,3 +1,4 @@
|
|||||||
|
rm -rf composer.phar
|
||||||
wget https://getcomposer.org/download/2.0.13/composer.phar
|
wget https://getcomposer.org/download/2.0.13/composer.phar
|
||||||
php composer.phar install -vvv
|
php composer.phar install -vvv
|
||||||
php artisan v2board:install
|
php artisan v2board:install
|
||||||
|
4
pm2.yaml
4
pm2.yaml
@ -1,5 +1,5 @@
|
|||||||
apps:
|
apps:
|
||||||
- name : 'V2Board'
|
- name : 'V2Board'
|
||||||
script : 'php artisan queue:work --queue=send_email,send_telegram,stat_server'
|
script : 'php artisan horizon'
|
||||||
instances: 4
|
instances: 1
|
||||||
out_file : './storage/logs/queue/queue.log'
|
out_file : './storage/logs/queue/queue.log'
|
||||||
|
4
public/assets/admin/theme/green.css
vendored
Normal file
4
public/assets/admin/theme/green.css
vendored
Normal file
File diff suppressed because one or more lines are too long
2
public/assets/admin/umi.css
vendored
2
public/assets/admin/umi.css
vendored
File diff suppressed because one or more lines are too long
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user