first commit
This commit is contained in:
39
Xboard/app/Http/Controllers/V1/User/CommController.php
Normal file
39
Xboard/app/Http/Controllers/V1/User/CommController.php
Normal file
@@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\V1\User;
|
||||
|
||||
use App\Exceptions\ApiException;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\Payment;
|
||||
use App\Utils\Dict;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class CommController extends Controller
|
||||
{
|
||||
public function config()
|
||||
{
|
||||
$data = [
|
||||
'is_telegram' => (int)admin_setting('telegram_bot_enable', 0),
|
||||
'telegram_discuss_link' => admin_setting('telegram_discuss_link'),
|
||||
'stripe_pk' => admin_setting('stripe_pk_live'),
|
||||
'withdraw_methods' => admin_setting('commission_withdraw_method', Dict::WITHDRAW_METHOD_WHITELIST_DEFAULT),
|
||||
'withdraw_close' => (int)admin_setting('withdraw_close_enable', 0),
|
||||
'currency' => admin_setting('currency', 'CNY'),
|
||||
'currency_symbol' => admin_setting('currency_symbol', '¥'),
|
||||
'commission_distribution_enable' => (int)admin_setting('commission_distribution_enable', 0),
|
||||
'commission_distribution_l1' => admin_setting('commission_distribution_l1'),
|
||||
'commission_distribution_l2' => admin_setting('commission_distribution_l2'),
|
||||
'commission_distribution_l3' => admin_setting('commission_distribution_l3')
|
||||
];
|
||||
return $this->success($data);
|
||||
}
|
||||
|
||||
public function getStripePublicKey(Request $request)
|
||||
{
|
||||
$payment = Payment::where('id', $request->input('id'))
|
||||
->where('payment', 'StripeCredit')
|
||||
->first();
|
||||
if (!$payment) throw new ApiException('payment is not found');
|
||||
return $this->success($payment->config['stripe_pk_live']);
|
||||
}
|
||||
}
|
||||
25
Xboard/app/Http/Controllers/V1/User/CouponController.php
Normal file
25
Xboard/app/Http/Controllers/V1/User/CouponController.php
Normal file
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\V1\User;
|
||||
|
||||
use App\Exceptions\ApiException;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Resources\CouponResource;
|
||||
use App\Services\CouponService;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class CouponController extends Controller
|
||||
{
|
||||
public function check(Request $request)
|
||||
{
|
||||
if (empty($request->input('code'))) {
|
||||
return $this->fail([422, __('Coupon cannot be empty')]);
|
||||
}
|
||||
$couponService = new CouponService($request->input('code'));
|
||||
$couponService->setPlanId($request->input('plan_id'));
|
||||
$couponService->setUserId($request->user()->id);
|
||||
$couponService->setPeriod($request->input('period'));
|
||||
$couponService->check();
|
||||
return $this->success(CouponResource::make($couponService->getCoupon()));
|
||||
}
|
||||
}
|
||||
193
Xboard/app/Http/Controllers/V1/User/GiftCardController.php
Normal file
193
Xboard/app/Http/Controllers/V1/User/GiftCardController.php
Normal file
@@ -0,0 +1,193 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\V1\User;
|
||||
|
||||
use App\Exceptions\ApiException;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\User\GiftCardCheckRequest;
|
||||
use App\Http\Requests\User\GiftCardRedeemRequest;
|
||||
use App\Models\GiftCardUsage;
|
||||
use App\Services\GiftCardService;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
class GiftCardController extends Controller
|
||||
{
|
||||
/**
|
||||
* 查询兑换码信息
|
||||
*/
|
||||
public function check(GiftCardCheckRequest $request)
|
||||
{
|
||||
try {
|
||||
$giftCardService = new GiftCardService($request->input('code'));
|
||||
$giftCardService->setUser($request->user());
|
||||
|
||||
// 1. 验证礼品卡本身是否有效 (如不存在、已过期、已禁用)
|
||||
$giftCardService->validateIsActive();
|
||||
|
||||
// 2. 检查用户是否满足使用条件,但不在此处抛出异常
|
||||
$eligibility = $giftCardService->checkUserEligibility();
|
||||
|
||||
// 3. 获取卡片信息和奖励预览
|
||||
$codeInfo = $giftCardService->getCodeInfo();
|
||||
$rewardPreview = $giftCardService->previewRewards();
|
||||
|
||||
return $this->success([
|
||||
'code_info' => $codeInfo, // 这里面已经包含 plan_info
|
||||
'reward_preview' => $rewardPreview,
|
||||
'can_redeem' => $eligibility['can_redeem'],
|
||||
'reason' => $eligibility['reason'],
|
||||
]);
|
||||
|
||||
} catch (ApiException $e) {
|
||||
// 这里只捕获 validateIsActive 抛出的异常
|
||||
return $this->fail([400, $e->getMessage()]);
|
||||
} catch (\Exception $e) {
|
||||
Log::error('礼品卡查询失败', [
|
||||
'code' => $request->input('code'),
|
||||
'user_id' => $request->user()->id,
|
||||
'error' => $e->getMessage(),
|
||||
]);
|
||||
return $this->fail([500, '查询失败,请稍后重试']);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用兑换码
|
||||
*/
|
||||
public function redeem(GiftCardRedeemRequest $request)
|
||||
{
|
||||
try {
|
||||
$giftCardService = new GiftCardService($request->input('code'));
|
||||
$giftCardService->setUser($request->user());
|
||||
$giftCardService->validate();
|
||||
|
||||
// 使用礼品卡
|
||||
$result = $giftCardService->redeem([
|
||||
// 'ip_address' => $request->ip(),
|
||||
'user_agent' => $request->userAgent(),
|
||||
]);
|
||||
|
||||
Log::info('礼品卡使用成功', [
|
||||
'code' => $request->input('code'),
|
||||
'user_id' => $request->user()->id,
|
||||
'rewards' => $result['rewards'],
|
||||
]);
|
||||
|
||||
return $this->success([
|
||||
'message' => '兑换成功!',
|
||||
'rewards' => $result['rewards'],
|
||||
'invite_rewards' => $result['invite_rewards'],
|
||||
'template_name' => $result['template_name'],
|
||||
]);
|
||||
|
||||
} catch (ApiException $e) {
|
||||
return $this->fail([400, $e->getMessage()]);
|
||||
} catch (\Exception $e) {
|
||||
Log::error('礼品卡使用失败', [
|
||||
'code' => $request->input('code'),
|
||||
'user_id' => $request->user()->id,
|
||||
'error' => $e->getMessage(),
|
||||
'trace' => $e->getTraceAsString(),
|
||||
]);
|
||||
return $this->fail([500, '兑换失败,请稍后重试']);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户兑换记录
|
||||
*/
|
||||
public function history(Request $request)
|
||||
{
|
||||
$request->validate([
|
||||
'page' => 'integer|min:1',
|
||||
'per_page' => 'integer|min:1|max:100',
|
||||
]);
|
||||
|
||||
$perPage = $request->input('per_page', 15);
|
||||
|
||||
$usages = GiftCardUsage::with(['template', 'code'])
|
||||
->where('user_id', $request->user()->id)
|
||||
->orderBy('created_at', 'desc')
|
||||
->paginate($perPage);
|
||||
|
||||
$data = $usages->getCollection()->map(function (GiftCardUsage $usage) {
|
||||
return [
|
||||
'id' => $usage->id,
|
||||
'code' => ($usage->code instanceof \App\Models\GiftCardCode && $usage->code->code)
|
||||
? (substr($usage->code->code, 0, 8) . '****')
|
||||
: '',
|
||||
'template_name' => $usage->template->name ?? '',
|
||||
'template_type' => $usage->template->type ?? '',
|
||||
'template_type_name' => $usage->template->type_name ?? '',
|
||||
'rewards_given' => $usage->rewards_given,
|
||||
'invite_rewards' => $usage->invite_rewards,
|
||||
'multiplier_applied' => $usage->multiplier_applied,
|
||||
'created_at' => $usage->created_at,
|
||||
];
|
||||
})->values();
|
||||
return response()->json([
|
||||
'data' => $data,
|
||||
'pagination' => [
|
||||
'current_page' => $usages->currentPage(),
|
||||
'last_page' => $usages->lastPage(),
|
||||
'per_page' => $usages->perPage(),
|
||||
'total' => $usages->total(),
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取兑换记录详情
|
||||
*/
|
||||
public function detail(Request $request)
|
||||
{
|
||||
$request->validate([
|
||||
'id' => 'required|integer|exists:v2_gift_card_usage,id',
|
||||
]);
|
||||
|
||||
$usage = GiftCardUsage::with(['template', 'code', 'inviteUser'])
|
||||
->where('user_id', $request->user()->id)
|
||||
->where('id', $request->input('id'))
|
||||
->first();
|
||||
|
||||
if (!$usage) {
|
||||
return $this->fail([404, '记录不存在']);
|
||||
}
|
||||
|
||||
return $this->success([
|
||||
'id' => $usage->id,
|
||||
'code' => $usage->code->code ?? '',
|
||||
'template' => [
|
||||
'name' => $usage->template->name ?? '',
|
||||
'description' => $usage->template->description ?? '',
|
||||
'type' => $usage->template->type ?? '',
|
||||
'type_name' => $usage->template->type_name ?? '',
|
||||
'icon' => $usage->template->icon ?? '',
|
||||
'theme_color' => $usage->template->theme_color ?? '',
|
||||
],
|
||||
'rewards_given' => $usage->rewards_given,
|
||||
'invite_rewards' => $usage->invite_rewards,
|
||||
'invite_user' => $usage->inviteUser ? [
|
||||
'id' => $usage->inviteUser->id ?? '',
|
||||
'email' => isset($usage->inviteUser->email) ? (substr($usage->inviteUser->email, 0, 3) . '***@***') : '',
|
||||
] : null,
|
||||
'user_level_at_use' => $usage->user_level_at_use,
|
||||
'plan_id_at_use' => $usage->plan_id_at_use,
|
||||
'multiplier_applied' => $usage->multiplier_applied,
|
||||
// 'ip_address' => $usage->ip_address,
|
||||
'notes' => $usage->notes,
|
||||
'created_at' => $usage->created_at,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取可用的礼品卡类型
|
||||
*/
|
||||
public function types(Request $request)
|
||||
{
|
||||
return $this->success([
|
||||
'types' => \App\Models\GiftCardTemplate::getTypeMap(),
|
||||
]);
|
||||
}
|
||||
}
|
||||
79
Xboard/app/Http/Controllers/V1/User/InviteController.php
Normal file
79
Xboard/app/Http/Controllers/V1/User/InviteController.php
Normal file
@@ -0,0 +1,79 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\V1\User;
|
||||
|
||||
use App\Exceptions\ApiException;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Resources\ComissionLogResource;
|
||||
use App\Http\Resources\InviteCodeResource;
|
||||
use App\Models\CommissionLog;
|
||||
use App\Models\InviteCode;
|
||||
use App\Models\Order;
|
||||
use App\Models\User;
|
||||
use App\Utils\Helper;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class InviteController extends Controller
|
||||
{
|
||||
public function save(Request $request)
|
||||
{
|
||||
if (InviteCode::where('user_id', $request->user()->id)->where('status', 0)->count() >= admin_setting('invite_gen_limit', 5)) {
|
||||
return $this->fail([400,__('The maximum number of creations has been reached')]);
|
||||
}
|
||||
$inviteCode = new InviteCode();
|
||||
$inviteCode->user_id = $request->user()->id;
|
||||
$inviteCode->code = Helper::randomChar(8);
|
||||
return $this->success($inviteCode->save());
|
||||
}
|
||||
|
||||
public function details(Request $request)
|
||||
{
|
||||
$current = $request->input('current') ? $request->input('current') : 1;
|
||||
$pageSize = $request->input('page_size') >= 10 ? $request->input('page_size') : 10;
|
||||
$builder = CommissionLog::where('invite_user_id', $request->user()->id)
|
||||
->where('get_amount', '>', 0)
|
||||
->orderBy('created_at', 'DESC');
|
||||
$total = $builder->count();
|
||||
$details = $builder->forPage($current, $pageSize)
|
||||
->get();
|
||||
return response([
|
||||
'data' => ComissionLogResource::collection($details),
|
||||
'total' => $total
|
||||
]);
|
||||
}
|
||||
|
||||
public function fetch(Request $request)
|
||||
{
|
||||
$commission_rate = admin_setting('invite_commission', 10);
|
||||
$user = User::find($request->user()->id)
|
||||
->load(['codes' => fn($query) => $query->where('status', 0)]);
|
||||
if ($user->commission_rate) {
|
||||
$commission_rate = $user->commission_rate;
|
||||
}
|
||||
$uncheck_commission_balance = (int)Order::where('status', 3)
|
||||
->where('commission_status', 0)
|
||||
->where('invite_user_id', $user->id)
|
||||
->sum('commission_balance');
|
||||
if (admin_setting('commission_distribution_enable', 0)) {
|
||||
$uncheck_commission_balance = $uncheck_commission_balance * (admin_setting('commission_distribution_l1') / 100);
|
||||
}
|
||||
$stat = [
|
||||
//已注册用户数
|
||||
(int)User::where('invite_user_id', $user->id)->count(),
|
||||
//有效的佣金
|
||||
(int)CommissionLog::where('invite_user_id', $user->id)
|
||||
->sum('get_amount'),
|
||||
//确认中的佣金
|
||||
$uncheck_commission_balance,
|
||||
//佣金比例
|
||||
(int)$commission_rate,
|
||||
//可用佣金
|
||||
(int)$user->commission_balance
|
||||
];
|
||||
$data = [
|
||||
'codes' => InviteCodeResource::collection($user->codes),
|
||||
'stat' => $stat
|
||||
];
|
||||
return $this->success($data);
|
||||
}
|
||||
}
|
||||
150
Xboard/app/Http/Controllers/V1/User/KnowledgeController.php
Normal file
150
Xboard/app/Http/Controllers/V1/User/KnowledgeController.php
Normal file
@@ -0,0 +1,150 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\V1\User;
|
||||
|
||||
use App\Exceptions\ApiException;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Resources\KnowledgeResource;
|
||||
use App\Models\Knowledge;
|
||||
use App\Models\User;
|
||||
use App\Services\Plugin\HookManager;
|
||||
use App\Services\UserService;
|
||||
use App\Utils\Helper;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class KnowledgeController extends Controller
|
||||
{
|
||||
private UserService $userService;
|
||||
|
||||
public function __construct(UserService $userService)
|
||||
{
|
||||
$this->userService = $userService;
|
||||
}
|
||||
|
||||
public function fetch(Request $request)
|
||||
{
|
||||
$request->validate([
|
||||
'id' => 'nullable|sometimes|integer|min:1',
|
||||
'language' => 'nullable|sometimes|string|max:10',
|
||||
'keyword' => 'nullable|sometimes|string|max:255',
|
||||
]);
|
||||
|
||||
return $request->input('id')
|
||||
? $this->fetchSingle($request)
|
||||
: $this->fetchList($request);
|
||||
}
|
||||
|
||||
private function fetchSingle(Request $request)
|
||||
{
|
||||
$knowledge = $this->buildKnowledgeQuery()
|
||||
->where('id', $request->input('id'))
|
||||
->first();
|
||||
|
||||
if (!$knowledge) {
|
||||
return $this->fail([500, __('Article does not exist')]);
|
||||
}
|
||||
|
||||
$knowledge = $knowledge->toArray();
|
||||
$knowledge = $this->processKnowledgeContent($knowledge, $request->user());
|
||||
|
||||
return $this->success(KnowledgeResource::make($knowledge));
|
||||
}
|
||||
|
||||
private function fetchList(Request $request)
|
||||
{
|
||||
$builder = $this->buildKnowledgeQuery(['id', 'category', 'title', 'updated_at', 'body'])
|
||||
->where('language', $request->input('language'))
|
||||
->orderBy('sort', 'ASC');
|
||||
|
||||
$keyword = $request->input('keyword');
|
||||
if ($keyword) {
|
||||
$builder = $builder->where(function ($query) use ($keyword) {
|
||||
$query->where('title', 'LIKE', "%{$keyword}%")
|
||||
->orWhere('body', 'LIKE', "%{$keyword}%");
|
||||
});
|
||||
}
|
||||
|
||||
$knowledges = $builder->get()
|
||||
->map(function ($knowledge) use ($request) {
|
||||
$knowledge = $knowledge->toArray();
|
||||
$knowledge = $this->processKnowledgeContent($knowledge, $request->user());
|
||||
return KnowledgeResource::make($knowledge);
|
||||
})
|
||||
->groupBy('category');
|
||||
|
||||
return $this->success($knowledges);
|
||||
}
|
||||
|
||||
private function buildKnowledgeQuery(array $select = ['*'])
|
||||
{
|
||||
return Knowledge::select($select)->where('show', 1);
|
||||
}
|
||||
|
||||
private function processKnowledgeContent(array $knowledge, User $user): array
|
||||
{
|
||||
if (!isset($knowledge['body'])) {
|
||||
return $knowledge;
|
||||
}
|
||||
|
||||
if (!$this->userService->isAvailable($user)) {
|
||||
$this->formatAccessData($knowledge['body']);
|
||||
}
|
||||
$subscribeUrl = Helper::getSubscribeUrl($user['token']);
|
||||
$knowledge['body'] = $this->replacePlaceholders($knowledge['body'], $subscribeUrl);
|
||||
|
||||
return $knowledge;
|
||||
}
|
||||
|
||||
private function formatAccessData(&$body): void
|
||||
{
|
||||
$rules = [
|
||||
[
|
||||
'type' => 'regex',
|
||||
'pattern' => '/<!--access start-->(.*?)<!--access end-->/s',
|
||||
'replacement' => '<div class="v2board-no-access">' . __('You must have a valid subscription to view content in this area') . '</div>'
|
||||
]
|
||||
];
|
||||
|
||||
$this->applyReplacementRules($body, $rules);
|
||||
}
|
||||
|
||||
private function replacePlaceholders(string $body, string $subscribeUrl): string
|
||||
{
|
||||
$rules = [
|
||||
[
|
||||
'type' => 'string',
|
||||
'search' => '{{siteName}}',
|
||||
'replacement' => admin_setting('app_name', 'XBoard')
|
||||
],
|
||||
[
|
||||
'type' => 'string',
|
||||
'search' => '{{subscribeUrl}}',
|
||||
'replacement' => $subscribeUrl
|
||||
],
|
||||
[
|
||||
'type' => 'string',
|
||||
'search' => '{{urlEncodeSubscribeUrl}}',
|
||||
'replacement' => urlencode($subscribeUrl)
|
||||
],
|
||||
[
|
||||
'type' => 'string',
|
||||
'search' => '{{safeBase64SubscribeUrl}}',
|
||||
'replacement' => str_replace(['+', '/', '='], ['-', '_', ''], base64_encode($subscribeUrl))
|
||||
]
|
||||
];
|
||||
|
||||
$this->applyReplacementRules($body, $rules);
|
||||
return $body;
|
||||
}
|
||||
|
||||
private function applyReplacementRules(string &$body, array $rules): void
|
||||
{
|
||||
foreach ($rules as $rule) {
|
||||
if ($rule['type'] === 'regex') {
|
||||
$body = preg_replace($rule['pattern'], $rule['replacement'], $body);
|
||||
} else {
|
||||
$body = str_replace($rule['search'], $rule['replacement'], $body);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
26
Xboard/app/Http/Controllers/V1/User/NoticeController.php
Normal file
26
Xboard/app/Http/Controllers/V1/User/NoticeController.php
Normal file
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\V1\User;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\Notice;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class NoticeController extends Controller
|
||||
{
|
||||
public function fetch(Request $request)
|
||||
{
|
||||
$current = $request->input('current') ? $request->input('current') : 1;
|
||||
$pageSize = 5;
|
||||
$model = Notice::orderBy('sort', 'ASC')
|
||||
->orderBy('id', 'DESC')
|
||||
->where('show', true);
|
||||
$total = $model->count();
|
||||
$res = $model->forPage($current, $pageSize)
|
||||
->get();
|
||||
return response([
|
||||
'data' => $res,
|
||||
'total' => $total
|
||||
]);
|
||||
}
|
||||
}
|
||||
212
Xboard/app/Http/Controllers/V1/User/OrderController.php
Normal file
212
Xboard/app/Http/Controllers/V1/User/OrderController.php
Normal file
@@ -0,0 +1,212 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\V1\User;
|
||||
|
||||
use App\Exceptions\ApiException;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\User\OrderSave;
|
||||
use App\Http\Resources\OrderResource;
|
||||
use App\Models\Order;
|
||||
use App\Models\Payment;
|
||||
use App\Models\Plan;
|
||||
use App\Models\User;
|
||||
use App\Services\CouponService;
|
||||
use App\Services\OrderService;
|
||||
use App\Services\PaymentService;
|
||||
use App\Services\PlanService;
|
||||
use App\Services\UserService;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
class OrderController extends Controller
|
||||
{
|
||||
public function fetch(Request $request)
|
||||
{
|
||||
$request->validate([
|
||||
'status' => 'nullable|integer|in:0,1,2,3',
|
||||
]);
|
||||
$orders = Order::with('plan')
|
||||
->where('user_id', $request->user()->id)
|
||||
->when($request->input('status') !== null, function ($query) use ($request) {
|
||||
$query->where('status', $request->input('status'));
|
||||
})
|
||||
->orderBy('created_at', 'DESC')
|
||||
->get();
|
||||
|
||||
return $this->success(OrderResource::collection($orders));
|
||||
}
|
||||
|
||||
public function detail(Request $request)
|
||||
{
|
||||
$request->validate([
|
||||
'trade_no' => 'required|string',
|
||||
]);
|
||||
$order = Order::with(['payment', 'plan'])
|
||||
->where('user_id', $request->user()->id)
|
||||
->where('trade_no', $request->input('trade_no'))
|
||||
->first();
|
||||
if (!$order) {
|
||||
return $this->fail([400, __('Order does not exist or has been paid')]);
|
||||
}
|
||||
$order['try_out_plan_id'] = (int) admin_setting('try_out_plan_id');
|
||||
if (!$order->plan) {
|
||||
return $this->fail([400, __('Subscription plan does not exist')]);
|
||||
}
|
||||
if ($order->surplus_order_ids) {
|
||||
$order['surplus_orders'] = Order::whereIn('id', $order->surplus_order_ids)->get();
|
||||
}
|
||||
return $this->success(OrderResource::make($order));
|
||||
}
|
||||
|
||||
public function save(OrderSave $request)
|
||||
{
|
||||
$request->validate([
|
||||
'plan_id' => 'required|exists:App\Models\Plan,id',
|
||||
'period' => 'required|string'
|
||||
]);
|
||||
|
||||
$user = User::findOrFail($request->user()->id);
|
||||
$userService = app(UserService::class);
|
||||
|
||||
if ($userService->isNotCompleteOrderByUserId($user->id)) {
|
||||
throw new ApiException(__('You have an unpaid or pending order, please try again later or cancel it'));
|
||||
}
|
||||
|
||||
$plan = Plan::findOrFail($request->input('plan_id'));
|
||||
$planService = new PlanService($plan);
|
||||
|
||||
$planService->validatePurchase($user, $request->input('period'));
|
||||
|
||||
$order = OrderService::createFromRequest(
|
||||
$user,
|
||||
$plan,
|
||||
$request->input('period'),
|
||||
$request->input('coupon_code')
|
||||
);
|
||||
|
||||
return $this->success($order->trade_no);
|
||||
}
|
||||
|
||||
protected function applyCoupon(Order $order, string $couponCode): void
|
||||
{
|
||||
$couponService = new CouponService($couponCode);
|
||||
if (!$couponService->use($order)) {
|
||||
throw new ApiException(__('Coupon failed'));
|
||||
}
|
||||
$order->coupon_id = $couponService->getId();
|
||||
}
|
||||
|
||||
protected function handleUserBalance(Order $order, User $user, UserService $userService): void
|
||||
{
|
||||
$remainingBalance = $user->balance - $order->total_amount;
|
||||
|
||||
if ($remainingBalance > 0) {
|
||||
if (!$userService->addBalance($order->user_id, -$order->total_amount)) {
|
||||
throw new ApiException(__('Insufficient balance'));
|
||||
}
|
||||
$order->balance_amount = $order->total_amount;
|
||||
$order->total_amount = 0;
|
||||
} else {
|
||||
if (!$userService->addBalance($order->user_id, -$user->balance)) {
|
||||
throw new ApiException(__('Insufficient balance'));
|
||||
}
|
||||
$order->balance_amount = $user->balance;
|
||||
$order->total_amount = $order->total_amount - $user->balance;
|
||||
}
|
||||
}
|
||||
|
||||
public function checkout(Request $request)
|
||||
{
|
||||
$tradeNo = $request->input('trade_no');
|
||||
$method = $request->input('method');
|
||||
$order = Order::where('trade_no', $tradeNo)
|
||||
->where('user_id', $request->user()->id)
|
||||
->where('status', 0)
|
||||
->first();
|
||||
if (!$order) {
|
||||
return $this->fail([400, __('Order does not exist or has been paid')]);
|
||||
}
|
||||
// free process
|
||||
if ($order->total_amount <= 0) {
|
||||
$orderService = new OrderService($order);
|
||||
if (!$orderService->paid($order->trade_no))
|
||||
return $this->fail([400, '支付失败']);
|
||||
return response([
|
||||
'type' => -1,
|
||||
'data' => true
|
||||
]);
|
||||
}
|
||||
$payment = Payment::find($method);
|
||||
if (!$payment || !$payment->enable) {
|
||||
return $this->fail([400, __('Payment method is not available')]);
|
||||
}
|
||||
$paymentService = new PaymentService($payment->payment, $payment->id);
|
||||
$order->handling_amount = NULL;
|
||||
if ($payment->handling_fee_fixed || $payment->handling_fee_percent) {
|
||||
$order->handling_amount = (int) round(($order->total_amount * ($payment->handling_fee_percent / 100)) + $payment->handling_fee_fixed);
|
||||
}
|
||||
$order->payment_id = $method;
|
||||
if (!$order->save())
|
||||
return $this->fail([400, __('Request failed, please try again later')]);
|
||||
$result = $paymentService->pay([
|
||||
'trade_no' => $tradeNo,
|
||||
'total_amount' => isset($order->handling_amount) ? ($order->total_amount + $order->handling_amount) : $order->total_amount,
|
||||
'user_id' => $order->user_id,
|
||||
'stripe_token' => $request->input('token')
|
||||
]);
|
||||
return response([
|
||||
'type' => $result['type'],
|
||||
'data' => $result['data']
|
||||
]);
|
||||
}
|
||||
|
||||
public function check(Request $request)
|
||||
{
|
||||
$tradeNo = $request->input('trade_no');
|
||||
$order = Order::where('trade_no', $tradeNo)
|
||||
->where('user_id', $request->user()->id)
|
||||
->first();
|
||||
if (!$order) {
|
||||
return $this->fail([400, __('Order does not exist')]);
|
||||
}
|
||||
return $this->success($order->status);
|
||||
}
|
||||
|
||||
public function getPaymentMethod()
|
||||
{
|
||||
$methods = Payment::select([
|
||||
'id',
|
||||
'name',
|
||||
'payment',
|
||||
'icon',
|
||||
'handling_fee_fixed',
|
||||
'handling_fee_percent'
|
||||
])
|
||||
->where('enable', 1)
|
||||
->orderBy('sort', 'ASC')
|
||||
->get();
|
||||
|
||||
return $this->success($methods);
|
||||
}
|
||||
|
||||
public function cancel(Request $request)
|
||||
{
|
||||
if (empty($request->input('trade_no'))) {
|
||||
return $this->fail([422, __('Invalid parameter')]);
|
||||
}
|
||||
$order = Order::where('trade_no', $request->input('trade_no'))
|
||||
->where('user_id', $request->user()->id)
|
||||
->first();
|
||||
if (!$order) {
|
||||
return $this->fail([400, __('Order does not exist')]);
|
||||
}
|
||||
if ($order->status !== 0) {
|
||||
return $this->fail([400, __('You can only cancel pending orders')]);
|
||||
}
|
||||
$orderService = new OrderService($order);
|
||||
if (!$orderService->cancel()) {
|
||||
return $this->fail([400, __('Cancel failed')]);
|
||||
}
|
||||
return $this->success(true);
|
||||
}
|
||||
}
|
||||
38
Xboard/app/Http/Controllers/V1/User/PlanController.php
Normal file
38
Xboard/app/Http/Controllers/V1/User/PlanController.php
Normal file
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\V1\User;
|
||||
|
||||
use App\Exceptions\ApiException;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Resources\PlanResource;
|
||||
use App\Models\Plan;
|
||||
use App\Models\User;
|
||||
use App\Services\PlanService;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class PlanController extends Controller
|
||||
{
|
||||
protected PlanService $planService;
|
||||
|
||||
public function __construct(PlanService $planService)
|
||||
{
|
||||
$this->planService = $planService;
|
||||
}
|
||||
public function fetch(Request $request)
|
||||
{
|
||||
$user = User::find($request->user()->id);
|
||||
if ($request->input('id')) {
|
||||
$plan = Plan::where('id', $request->input('id'))->first();
|
||||
if (!$plan) {
|
||||
return $this->fail([400, __('Subscription plan does not exist')]);
|
||||
}
|
||||
if (!$this->planService->isPlanAvailableForUser($plan, $user)) {
|
||||
return $this->fail([400, __('Subscription plan does not exist')]);
|
||||
}
|
||||
return $this->success(PlanResource::make($plan));
|
||||
}
|
||||
|
||||
$plans = $this->planService->getAvailablePlans();
|
||||
return $this->success(PlanResource::collection($plans));
|
||||
}
|
||||
}
|
||||
31
Xboard/app/Http/Controllers/V1/User/ServerController.php
Normal file
31
Xboard/app/Http/Controllers/V1/User/ServerController.php
Normal file
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\V1\User;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Resources\NodeResource;
|
||||
use App\Models\User;
|
||||
use App\Services\ServerService;
|
||||
use App\Services\UserService;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class ServerController extends Controller
|
||||
{
|
||||
public function fetch(Request $request)
|
||||
{
|
||||
$user = User::find($request->user()->id);
|
||||
$servers = [];
|
||||
$userService = new UserService();
|
||||
if ($userService->isAvailable($user)) {
|
||||
$servers = ServerService::getAvailableServers($user);
|
||||
}
|
||||
$eTag = sha1(json_encode(array_column($servers, 'cache_key')));
|
||||
if (strpos($request->header('If-None-Match', ''), $eTag) !== false ) {
|
||||
return response(null,304);
|
||||
}
|
||||
$data = NodeResource::collection($servers);
|
||||
return response([
|
||||
'data' => $data
|
||||
])->header('ETag', "\"{$eTag}\"");
|
||||
}
|
||||
}
|
||||
26
Xboard/app/Http/Controllers/V1/User/StatController.php
Normal file
26
Xboard/app/Http/Controllers/V1/User/StatController.php
Normal file
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\V1\User;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Resources\TrafficLogResource;
|
||||
use App\Models\StatUser;
|
||||
use App\Services\StatisticalService;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
class StatController extends Controller
|
||||
{
|
||||
public function getTrafficLog(Request $request)
|
||||
{
|
||||
$startDate = now()->startOfMonth()->timestamp;
|
||||
$records = StatUser::query()
|
||||
->where('user_id', $request->user()->id)
|
||||
->where('record_at', '>=', $startDate)
|
||||
->orderBy('record_at', 'DESC')
|
||||
->get();
|
||||
|
||||
$data = TrafficLogResource::collection(collect($records));
|
||||
return $this->success($data);
|
||||
}
|
||||
}
|
||||
26
Xboard/app/Http/Controllers/V1/User/TelegramController.php
Normal file
26
Xboard/app/Http/Controllers/V1/User/TelegramController.php
Normal file
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\V1\User;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\User;
|
||||
use App\Services\TelegramService;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class TelegramController extends Controller
|
||||
{
|
||||
public function getBotInfo()
|
||||
{
|
||||
$telegramService = new TelegramService();
|
||||
$response = $telegramService->getMe();
|
||||
$data = [
|
||||
'username' => $response->result->username
|
||||
];
|
||||
return $this->success($data);
|
||||
}
|
||||
|
||||
public function unbind(Request $request)
|
||||
{
|
||||
$user = User::where('user_id', $request->user()->id)->first();
|
||||
}
|
||||
}
|
||||
154
Xboard/app/Http/Controllers/V1/User/TicketController.php
Normal file
154
Xboard/app/Http/Controllers/V1/User/TicketController.php
Normal file
@@ -0,0 +1,154 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\V1\User;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\User\TicketSave;
|
||||
use App\Http\Requests\User\TicketWithdraw;
|
||||
use App\Http\Resources\TicketResource;
|
||||
use App\Models\Ticket;
|
||||
use App\Models\TicketMessage;
|
||||
use App\Models\User;
|
||||
use App\Services\TicketService;
|
||||
use App\Utils\Dict;
|
||||
use Illuminate\Http\Request;
|
||||
use App\Services\Plugin\HookManager;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
class TicketController extends Controller
|
||||
{
|
||||
public function fetch(Request $request)
|
||||
{
|
||||
if ($request->input('id')) {
|
||||
$ticket = Ticket::where('id', $request->input('id'))
|
||||
->where('user_id', $request->user()->id)
|
||||
->first()
|
||||
->load('message');
|
||||
if (!$ticket) {
|
||||
return $this->fail([400, __('Ticket does not exist')]);
|
||||
}
|
||||
$ticket['message'] = TicketMessage::where('ticket_id', $ticket->id)->get();
|
||||
$ticket['message']->each(function ($message) use ($ticket) {
|
||||
$message['is_me'] = ($message['user_id'] == $ticket->user_id);
|
||||
});
|
||||
return $this->success(TicketResource::make($ticket)->additional(['message' => true]));
|
||||
}
|
||||
$ticket = Ticket::where('user_id', $request->user()->id)
|
||||
->orderBy('created_at', 'DESC')
|
||||
->get();
|
||||
return $this->success(TicketResource::collection($ticket));
|
||||
}
|
||||
|
||||
public function save(TicketSave $request)
|
||||
{
|
||||
$ticketService = new TicketService();
|
||||
$ticket = $ticketService->createTicket(
|
||||
$request->user()->id,
|
||||
$request->input('subject'),
|
||||
$request->input('level'),
|
||||
$request->input('message')
|
||||
);
|
||||
HookManager::call('ticket.create.after', $ticket);
|
||||
return $this->success(true);
|
||||
|
||||
}
|
||||
|
||||
public function reply(Request $request)
|
||||
{
|
||||
if (empty($request->input('id'))) {
|
||||
return $this->fail([400, __('Invalid parameter')]);
|
||||
}
|
||||
if (empty($request->input('message'))) {
|
||||
return $this->fail([400, __('Message cannot be empty')]);
|
||||
}
|
||||
$ticket = Ticket::where('id', $request->input('id'))
|
||||
->where('user_id', $request->user()->id)
|
||||
->first();
|
||||
if (!$ticket) {
|
||||
return $this->fail([400, __('Ticket does not exist')]);
|
||||
}
|
||||
if ($ticket->status) {
|
||||
return $this->fail([400, __('The ticket is closed and cannot be replied')]);
|
||||
}
|
||||
if ((int) admin_setting('ticket_must_wait_reply', 0) && $request->user()->id == $this->getLastMessage($ticket->id)->user_id) {
|
||||
return $this->fail(codeResponse: [400, __('Please wait for the technical enginneer to reply')]);
|
||||
}
|
||||
$ticketService = new TicketService();
|
||||
if (
|
||||
!$ticketService->reply(
|
||||
$ticket,
|
||||
$request->input('message'),
|
||||
$request->user()->id
|
||||
)
|
||||
) {
|
||||
return $this->fail([400, __('Ticket reply failed')]);
|
||||
}
|
||||
HookManager::call('ticket.reply.user.after', $ticket);
|
||||
return $this->success(true);
|
||||
}
|
||||
|
||||
|
||||
public function close(Request $request)
|
||||
{
|
||||
if (empty($request->input('id'))) {
|
||||
return $this->fail([422, __('Invalid parameter')]);
|
||||
}
|
||||
$ticket = Ticket::where('id', $request->input('id'))
|
||||
->where('user_id', $request->user()->id)
|
||||
->first();
|
||||
if (!$ticket) {
|
||||
return $this->fail([400, __('Ticket does not exist')]);
|
||||
}
|
||||
$ticket->status = Ticket::STATUS_CLOSED;
|
||||
if (!$ticket->save()) {
|
||||
return $this->fail([500, __('Close failed')]);
|
||||
}
|
||||
return $this->success(true);
|
||||
}
|
||||
|
||||
private function getLastMessage($ticketId)
|
||||
{
|
||||
return TicketMessage::where('ticket_id', $ticketId)
|
||||
->orderBy('id', 'DESC')
|
||||
->first();
|
||||
}
|
||||
|
||||
public function withdraw(TicketWithdraw $request)
|
||||
{
|
||||
if ((int) admin_setting('withdraw_close_enable', 0)) {
|
||||
return $this->fail([400, 'Unsupported withdraw']);
|
||||
}
|
||||
if (
|
||||
!in_array(
|
||||
$request->input('withdraw_method'),
|
||||
admin_setting('commission_withdraw_method', Dict::WITHDRAW_METHOD_WHITELIST_DEFAULT)
|
||||
)
|
||||
) {
|
||||
return $this->fail([422, __('Unsupported withdrawal method')]);
|
||||
}
|
||||
$user = User::find($request->user()->id);
|
||||
$limit = admin_setting('commission_withdraw_limit', 100);
|
||||
if ($limit > ($user->commission_balance / 100)) {
|
||||
return $this->fail([422, __('The current required minimum withdrawal commission is :limit', ['limit' => $limit])]);
|
||||
}
|
||||
try {
|
||||
$ticketService = new TicketService();
|
||||
$subject = __('[Commission Withdrawal Request] This ticket is opened by the system');
|
||||
$message = sprintf(
|
||||
"%s\r\n%s",
|
||||
__('Withdrawal method') . ":" . $request->input('withdraw_method'),
|
||||
__('Withdrawal account') . ":" . $request->input('withdraw_account')
|
||||
);
|
||||
$ticket = $ticketService->createTicket(
|
||||
$request->user()->id,
|
||||
$subject,
|
||||
2,
|
||||
$message
|
||||
);
|
||||
} catch (\Exception $e) {
|
||||
throw $e;
|
||||
}
|
||||
HookManager::call('ticket.create.after', $ticket);
|
||||
return $this->success(true);
|
||||
}
|
||||
}
|
||||
223
Xboard/app/Http/Controllers/V1/User/UserController.php
Normal file
223
Xboard/app/Http/Controllers/V1/User/UserController.php
Normal file
@@ -0,0 +1,223 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\V1\User;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\User\UserChangePassword;
|
||||
use App\Http\Requests\User\UserTransfer;
|
||||
use App\Http\Requests\User\UserUpdate;
|
||||
use App\Models\Order;
|
||||
use App\Models\Plan;
|
||||
use App\Models\Ticket;
|
||||
use App\Models\User;
|
||||
use App\Services\Auth\LoginService;
|
||||
use App\Services\AuthService;
|
||||
use App\Services\Plugin\HookManager;
|
||||
use App\Services\UserService;
|
||||
use App\Utils\CacheKey;
|
||||
use App\Utils\Helper;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
class UserController extends Controller
|
||||
{
|
||||
protected $loginService;
|
||||
|
||||
public function __construct(
|
||||
LoginService $loginService
|
||||
) {
|
||||
$this->loginService = $loginService;
|
||||
}
|
||||
|
||||
public function getActiveSession(Request $request)
|
||||
{
|
||||
$user = $request->user();
|
||||
$authService = new AuthService($user);
|
||||
return $this->success($authService->getSessions());
|
||||
}
|
||||
|
||||
public function removeActiveSession(Request $request)
|
||||
{
|
||||
$user = $request->user();
|
||||
$authService = new AuthService($user);
|
||||
return $this->success($authService->removeSession($request->input('session_id')));
|
||||
}
|
||||
|
||||
public function checkLogin(Request $request)
|
||||
{
|
||||
$data = [
|
||||
'is_login' => $request->user()?->id ? true : false
|
||||
];
|
||||
if ($request->user()?->is_admin) {
|
||||
$data['is_admin'] = true;
|
||||
}
|
||||
return $this->success($data);
|
||||
}
|
||||
|
||||
public function changePassword(UserChangePassword $request)
|
||||
{
|
||||
$user = $request->user();
|
||||
if (
|
||||
!Helper::multiPasswordVerify(
|
||||
$user->password_algo,
|
||||
$user->password_salt,
|
||||
$request->input('old_password'),
|
||||
$user->password
|
||||
)
|
||||
) {
|
||||
return $this->fail([400, __('The old password is wrong')]);
|
||||
}
|
||||
$user->password = password_hash($request->input('new_password'), PASSWORD_DEFAULT);
|
||||
$user->password_algo = NULL;
|
||||
$user->password_salt = NULL;
|
||||
if (!$user->save()) {
|
||||
return $this->fail([400, __('Save failed')]);
|
||||
}
|
||||
|
||||
$currentToken = $user->currentAccessToken();
|
||||
if ($currentToken) {
|
||||
$user->tokens()->where('id', '!=', $currentToken->id)->delete();
|
||||
} else {
|
||||
$user->tokens()->delete();
|
||||
}
|
||||
|
||||
return $this->success(true);
|
||||
}
|
||||
|
||||
public function info(Request $request)
|
||||
{
|
||||
$user = User::where('id', $request->user()->id)
|
||||
->select([
|
||||
'email',
|
||||
'transfer_enable',
|
||||
'last_login_at',
|
||||
'created_at',
|
||||
'banned',
|
||||
'remind_expire',
|
||||
'remind_traffic',
|
||||
'expired_at',
|
||||
'balance',
|
||||
'commission_balance',
|
||||
'plan_id',
|
||||
'discount',
|
||||
'commission_rate',
|
||||
'telegram_id',
|
||||
'uuid'
|
||||
])
|
||||
->first();
|
||||
if (!$user) {
|
||||
return $this->fail([400, __('The user does not exist')]);
|
||||
}
|
||||
$user['avatar_url'] = 'https://cdn.v2ex.com/gravatar/' . md5($user->email) . '?s=64&d=identicon';
|
||||
return $this->success($user);
|
||||
}
|
||||
|
||||
public function getStat(Request $request)
|
||||
{
|
||||
$stat = [
|
||||
Order::where('status', 0)
|
||||
->where('user_id', $request->user()->id)
|
||||
->count(),
|
||||
Ticket::where('status', 0)
|
||||
->where('user_id', $request->user()->id)
|
||||
->count(),
|
||||
User::where('invite_user_id', $request->user()->id)
|
||||
->count()
|
||||
];
|
||||
return $this->success($stat);
|
||||
}
|
||||
|
||||
public function getSubscribe(Request $request)
|
||||
{
|
||||
$user = User::where('id', $request->user()->id)
|
||||
->select([
|
||||
'plan_id',
|
||||
'token',
|
||||
'expired_at',
|
||||
'u',
|
||||
'd',
|
||||
'transfer_enable',
|
||||
'email',
|
||||
'uuid',
|
||||
'device_limit',
|
||||
'speed_limit',
|
||||
'next_reset_at'
|
||||
])
|
||||
->first();
|
||||
if (!$user) {
|
||||
return $this->fail([400, __('The user does not exist')]);
|
||||
}
|
||||
if ($user->plan_id) {
|
||||
$user['plan'] = Plan::find($user->plan_id);
|
||||
if (!$user['plan']) {
|
||||
return $this->fail([400, __('Subscription plan does not exist')]);
|
||||
}
|
||||
}
|
||||
$user['subscribe_url'] = Helper::getSubscribeUrl($user['token']);
|
||||
$userService = new UserService();
|
||||
$user['reset_day'] = $userService->getResetDay($user);
|
||||
$user = HookManager::filter('user.subscribe.response', $user);
|
||||
return $this->success($user);
|
||||
}
|
||||
|
||||
public function resetSecurity(Request $request)
|
||||
{
|
||||
$user = $request->user();
|
||||
$user->uuid = Helper::guid(true);
|
||||
$user->token = Helper::guid();
|
||||
if (!$user->save()) {
|
||||
return $this->fail([400, __('Reset failed')]);
|
||||
}
|
||||
return $this->success(Helper::getSubscribeUrl($user->token));
|
||||
}
|
||||
|
||||
public function update(UserUpdate $request)
|
||||
{
|
||||
$updateData = $request->only([
|
||||
'remind_expire',
|
||||
'remind_traffic'
|
||||
]);
|
||||
|
||||
$user = $request->user();
|
||||
try {
|
||||
$user->update($updateData);
|
||||
} catch (\Exception $e) {
|
||||
return $this->fail([400, __('Save failed')]);
|
||||
}
|
||||
|
||||
return $this->success(true);
|
||||
}
|
||||
|
||||
public function transfer(UserTransfer $request)
|
||||
{
|
||||
$amount = $request->input('transfer_amount');
|
||||
try {
|
||||
DB::transaction(function () use ($request, $amount) {
|
||||
$user = User::lockForUpdate()->find($request->user()->id);
|
||||
if (!$user) {
|
||||
throw new \Exception(__('The user does not exist'));
|
||||
}
|
||||
if ($amount > $user->commission_balance) {
|
||||
throw new \Exception(__('Insufficient commission balance'));
|
||||
}
|
||||
$user->commission_balance -= $amount;
|
||||
$user->balance += $amount;
|
||||
if (!$user->save()) {
|
||||
throw new \Exception(__('Transfer failed'));
|
||||
}
|
||||
});
|
||||
} catch (\Exception $e) {
|
||||
return $this->fail([400, $e->getMessage()]);
|
||||
}
|
||||
return $this->success(true);
|
||||
}
|
||||
|
||||
public function getQuickLoginUrl(Request $request)
|
||||
{
|
||||
$user = $request->user();
|
||||
|
||||
$url = $this->loginService->generateQuickLoginUrl($user, $request->input('redirect'));
|
||||
return $this->success($url);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user