refactor: 重构规范部分代码、邮件队列增加失败重试、去除多个支付方式、更新依赖

This commit is contained in:
xboard
2024-04-10 00:51:03 +08:00
parent ec63e05575
commit 4c6c7182e2
50 changed files with 421 additions and 1005 deletions
+72 -11
View File
@@ -9,13 +9,17 @@ use Illuminate\Support\Facades\Cache;
class MailService
{
public function remindTraffic (User $user)
public function remindTraffic(User $user)
{
if (!$user->remind_traffic) return;
if (!$this->remindTrafficIsWarnValue($user->u, $user->d, $user->transfer_enable)) return;
if (!$user->remind_traffic)
return;
if (!$this->remindTrafficIsWarnValue($user->u, $user->d, $user->transfer_enable))
return;
$flag = CacheKey::get('LAST_SEND_EMAIL_REMIND_TRAFFIC', $user->id);
if (Cache::get($flag)) return;
if (!Cache::put($flag, 1, 24 * 3600)) return;
if (Cache::get($flag))
return;
if (!Cache::put($flag, 1, 24 * 3600))
return;
SendEmailJob::dispatch([
'email' => $user->email,
'subject' => __('The traffic usage in :app_name has reached 80%', [
@@ -31,11 +35,12 @@ class MailService
public function remindExpire(User $user)
{
if (!($user->expired_at !== NULL && ($user->expired_at - 86400) < time() && $user->expired_at > time())) return;
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' => admin_setting('app_name', 'XBoard')
'app_name' => admin_setting('app_name', 'XBoard')
]),
'template_name' => 'remindExpire',
'template_value' => [
@@ -48,11 +53,67 @@ class MailService
private function remindTrafficIsWarnValue($u, $d, $transfer_enable)
{
$ud = $u + $d;
if (!$ud) return false;
if (!$transfer_enable) return false;
if (!$ud)
return false;
if (!$transfer_enable)
return false;
$percentage = ($ud / $transfer_enable) * 100;
if ($percentage < 80) return false;
if ($percentage >= 100) return false;
if ($percentage < 80)
return false;
if ($percentage >= 100)
return false;
return true;
}
/**
* 发送邮件
*
* @param array $params 包含邮件参数的数组,必须包含以下字段:
* - email: 收件人邮箱地址
* - subject: 邮件主题
* - template_name: 邮件模板名称,例如 "welcome" 或 "password_reset"
* - template_value: 邮件模板变量,一个关联数组,包含模板中需要替换的变量和对应的值
* @return array 包含邮件发送结果的数组,包含以下字段:
* - email: 收件人邮箱地址
* - subject: 邮件主题
* - template_name: 邮件模板名称
* - error: 如果邮件发送失败,包含错误信息;否则为 null
* @throws \InvalidArgumentException 如果 $params 参数缺少必要的字段,抛出此异常
*/
public static function sendEmail(array $params)
{
if (admin_setting('email_host')) {
\Config::set('mail.host', admin_setting('email_host', config('mail.host')));
\Config::set('mail.port', admin_setting('email_port', config('mail.port')));
\Config::set('mail.encryption', admin_setting('email_encryption', config('mail.encryption')));
\Config::set('mail.username', admin_setting('email_username', config('mail.username')));
\Config::set('mail.password', admin_setting('email_password', config('mail.password')));
\Config::set('mail.from.address', admin_setting('email_from_address', config('mail.from.address')));
\Config::set('mail.from.name', admin_setting('app_name', 'XBoard'));
}
$email = $params['email'];
$subject = $params['subject'];
$params['template_name'] = 'mail.' . admin_setting('email_template', 'default') . '.' . $params['template_name'];
try {
\Mail::send(
$params['template_name'],
$params['template_value'],
function ($message) use ($email, $subject) {
$message->to($email)->subject($subject);
}
);
$error = null;
} catch (\Exception $e) {
$error = $e->getMessage();
}
$log = [
'email' => $params['email'],
'subject' => $params['subject'],
'template_name' => $params['template_name'],
'error' => $error,
'config' => config('mail')
];
\App\Models\MailLog::create($log);
return $log;
}
}
+9 -9
View File
@@ -40,7 +40,7 @@ class OrderService
DB::beginTransaction();
if ($order->surplus_order_ids) {
Order::whereIn('id', $order->surplus_order_ids)->update([
'status' => 4
'status' => Order::STATUS_DISCOUNTED
]);
}
switch ((string)$order->period) {
@@ -71,7 +71,7 @@ class OrderService
if (!$this->user->save()) {
throw new \Exception('用户信息保存失败');
}
$order->status = 3;
$order->status = Order::STATUS_COMPLETED;
if (!$order->save()) {
throw new \Exception('订单信息保存失败');
}
@@ -88,10 +88,10 @@ class OrderService
{
$order = $this->order;
if ($order->period === 'reset_price') {
$order->type = 4;
$order->type = Order::TYPE_RESET_TRAFFIC;
} else if ($user->plan_id !== NULL && $order->plan_id !== $user->plan_id && ($user->expired_at > time() || $user->expired_at === NULL)) {
if (!(int)admin_setting('plan_change_enable', 1)) throw new ApiException('目前不允许更改订阅,请联系客服或提交工单操作');
$order->type = 3;
$order->type = Order::TYPE_UPGRADE;
if ((int)admin_setting('surplus_enable', 1)) $this->getSurplusValue($user, $order);
if ($order->surplus_amount >= $order->total_amount) {
$order->refund_amount = $order->surplus_amount - $order->total_amount;
@@ -100,9 +100,9 @@ class OrderService
$order->total_amount = $order->total_amount - $order->surplus_amount;
}
} else if ($user->expired_at > time() && $order->plan_id == $user->plan_id) { // 用户订阅未过期且购买订阅与当前订阅相同 === 续费
$order->type = 2;
$order->type = Order::TYPE_RENEWAL;
} else { // 新购
$order->type = 1;
$order->type = Order::TYPE_NEW_PURCHASE;
}
}
@@ -215,8 +215,8 @@ class OrderService
public function paid(string $callbackNo)
{
$order = $this->order;
if ($order->status !== 0) return true;
$order->status = 1;
if ($order->status !== Order::STATUS_PENDING) return true;
$order->status = Order::STATUS_PROCESSING;
$order->paid_at = time();
$order->callback_no = $callbackNo;
if (!$order->save()) return false;
@@ -233,7 +233,7 @@ class OrderService
$order = $this->order;
try {
DB::beginTransaction();
$order->status = 2;
$order->status = Order::STATUS_CANCELLED;
if (!$order->save()) {
throw new \Exception('Failed to save order status.');
}
+48 -33
View File
@@ -17,7 +17,8 @@ use Illuminate\Support\Facades\Cache;
class ServerService
{
public function getAvailableVless(User $user):array
// 获取可用的 VLESS 服务器列表
public static function getAvailableVless(User $user): array
{
$servers = [];
$model = ServerVless::orderBy('sort', 'ASC');
@@ -41,15 +42,15 @@ class ServerService
unset($serverData['tls_settings']['private_key']);
}
}
$servers[] = $serverData;
}
return $servers;
}
public function getAvailableVmess(User $user):array
// 获取可用的 VMESS 服务器列表
public static function getAvailableVmess(User $user): array
{
$servers = [];
$model = ServerVmess::orderBy('sort', 'ASC');
@@ -69,11 +70,11 @@ class ServerService
$servers[] = $vmess[$key]->toArray();
}
return $servers;
}
public function getAvailableTrojan(User $user):array
// 获取可用的 TROJAN 服务器列表
public static function getAvailableTrojan(User $user): array
{
$servers = [];
$model = ServerTrojan::orderBy('sort', 'ASC');
@@ -95,7 +96,8 @@ class ServerService
return $servers;
}
public function getAvailableHysteria(User $user)
// 获取可用的 HYSTERIA 服务器列表
public static function getAvailableHysteria(User $user)
{
$availableServers = [];
$model = ServerHysteria::orderBy('sort', 'ASC');
@@ -119,7 +121,8 @@ class ServerService
return $availableServers;
}
public function getAvailableShadowsocks(User $user)
// 获取可用的 SHADOWSOCKS 服务器列表
public static function getAvailableShadowsocks(User $user)
{
$servers = [];
$model = ServerShadowsocks::orderBy('sort', 'ASC');
@@ -141,15 +144,16 @@ class ServerService
return $servers;
}
public function getAvailableServers(User $user)
// 获取可用的服务器列表
public static function getAvailableServers(User $user)
{
$servers = Cache::remember('serversAvailable_'. $user->id, 5, function() use($user){
return array_merge(
$this->getAvailableShadowsocks($user),
$this->getAvailableVmess($user),
$this->getAvailableTrojan($user),
$this->getAvailableHysteria($user),
$this->getAvailableVless($user)
self::getAvailableShadowsocks($user),
self::getAvailableVmess($user),
self::getAvailableTrojan($user),
self::getAvailableHysteria($user),
self::getAvailableVless($user)
);
});
$tmp = array_column($servers, 'sort');
@@ -162,7 +166,8 @@ class ServerService
}, $servers);
}
public function getAvailableUsers($groupId): Collection
// 获取可用的用户列表
public static function getAvailableUsers($groupId): Collection
{
return \DB::table('v2_user')
->whereIn('group_id', $groupId)
@@ -180,7 +185,8 @@ class ServerService
->get();
}
public function log(int $userId, int $serverId, int $u, int $d, float $rate, string $method)
// 记录流量日志
public static function log(int $userId, int $serverId, int $u, int $d, float $rate, string $method)
{
if (($u + $d) < 10240) return true;
$timestamp = strtotime(date('Y-m-d'));
@@ -212,7 +218,8 @@ class ServerService
}
}
public function getAllShadowsocks()
// 获取所有 SHADOWSOCKS 服务器列表
public static function getAllShadowsocks()
{
$servers = ServerShadowsocks::orderBy('sort', 'ASC')
->get()
@@ -223,7 +230,8 @@ class ServerService
return $servers;
}
public function getAllVMess()
// 获取所有 VMESS 服务器列表
public static function getAllVMess()
{
$servers = ServerVmess::orderBy('sort', 'ASC')
->get()
@@ -234,7 +242,8 @@ class ServerService
return $servers;
}
public function getAllVLess()
// 获取所有 VLESS 服务器列表
public static function getAllVLess()
{
$servers = ServerVless::orderBy('sort', 'ASC')
->get()
@@ -245,7 +254,8 @@ class ServerService
return $servers;
}
public function getAllTrojan()
// 获取所有 TROJAN 服务器列表
public static function getAllTrojan()
{
$servers = ServerTrojan::orderBy('sort', 'ASC')
->get()
@@ -256,7 +266,8 @@ class ServerService
return $servers;
}
public function getAllHysteria()
// 获取所有 HYSTERIA 服务器列表
public static function getAllHysteria()
{
$servers = ServerHysteria::orderBy('sort', 'ASC')
->get()
@@ -267,7 +278,8 @@ class ServerService
return $servers;
}
private function mergeData(&$servers)
// 合并数据
private static function mergeData(&$servers)
{
foreach ($servers as $k => $v) {
$serverType = strtoupper($v['type']);
@@ -291,22 +303,24 @@ class ServerService
}
}
public function getAllServers()
// 获取所有服务器列表
public static function getAllServers()
{
$servers = array_merge(
$this->getAllShadowsocks(),
$this->getAllVMess(),
$this->getAllTrojan(),
$this->getAllHysteria(),
$this->getAllVLess()
self::getAllShadowsocks(),
self::getAllVMess(),
self::getAllTrojan(),
self::getAllHysteria(),
self::getAllVLess()
);
$this->mergeData($servers);
self::mergeData($servers);
$tmp = array_column($servers, 'sort');
array_multisort($tmp, SORT_ASC, $servers);
return $servers;
}
public function getRoutes(array $routeIds)
// 获取路由规则
public static function getRoutes(array $routeIds)
{
$routes = ServerRoute::select(['id', 'match', 'action', 'action_value'])->whereIn('id', $routeIds)->get();
// TODO: remove on 1.8.0
@@ -318,7 +332,8 @@ class ServerService
return $routes;
}
public function getServer($serverId, $serverType)
// 获取服务器
public static function getServer($serverId, $serverType)
{
switch ($serverType) {
case 'vmess':
@@ -336,8 +351,8 @@ class ServerService
}
}
// 根据节点IP和父级别节点ID查询节点
public function getChildServer($serverId, $serverType, $nodeIp){
// 根据节点IP和父级别节点ID查询节点
public static function getChildServer($serverId, $serverType, $nodeIp){
switch ($serverType) {
case 'vmess':
return ServerVmess::query()
+5 -5
View File
@@ -21,9 +21,9 @@ class TicketService {
'message' => $message
]);
if ($userId !== $ticket->user_id) {
$ticket->reply_status = 0;
$ticket->reply_status = Ticket::STATUS_OPENING;
} else {
$ticket->reply_status = 1;
$ticket->reply_status = Ticket::STATUS_CLOSED;
}
if (!$ticketMessage || !$ticket->save()) {
throw new \Exception();
@@ -43,7 +43,7 @@ class TicketService {
if (!$ticket) {
throw new ApiException('工单不存在');
}
$ticket->status = 0;
$ticket->status = Ticket::STATUS_OPENING;
try{
DB::beginTransaction();
$ticketMessage = TicketMessage::create([
@@ -52,9 +52,9 @@ class TicketService {
'message' => $message
]);
if ($userId !== $ticket->user_id) {
$ticket->reply_status = 0;
$ticket->reply_status = Ticket::STATUS_OPENING;
} else {
$ticket->reply_status = 1;
$ticket->reply_status = Ticket::STATUS_CLOSED;
}
if (!$ticketMessage || !$ticket->save()) {
throw new ApiException('工单回复失败');
+1 -3
View File
@@ -2,8 +2,6 @@
namespace App\Services;
use App\Jobs\StatServerJob;
use App\Jobs\StatUserJob;
use App\Jobs\TrafficFetchJob;
use App\Models\Order;
use App\Models\Plan;
@@ -172,7 +170,7 @@ class UserService
{
// 获取子节点
$childServer = ($server['parent_id'] == null && !blank($nodeIp))
? (new ServerService())->getChildServer($server['id'], $protocol, $nodeIp)
? ServerService::getChildServer($server['id'], $protocol, $nodeIp)
: null;
$timestamp = strtotime(date('Y-m-d'));
collect($data)->chunk(1000)->each(function($chunk) use ($timestamp,$server,$protocol, $childServer){