diff --git a/app/Channels/BarkChannel.php b/app/Channels/BarkChannel.php index 76e54a1f..11619ff4 100644 --- a/app/Channels/BarkChannel.php +++ b/app/Channels/BarkChannel.php @@ -5,7 +5,9 @@ namespace App\Channels; use Helpers; use Http; use Illuminate\Notifications\Notification; +use Illuminate\Support\Arr; use Log; +use Str; class BarkChannel { @@ -17,18 +19,25 @@ class BarkChannel $message = $notification->toCustom($notifiable); } - $response = Http::timeout(15)->get('https://api.day.app/'.sysConfig('bark_key').'/'.$message['title'].'/'.$message['content']); + if (isset($message['url_type'])) { // 生成对公消息查询URL + $msgId = Str::uuid(); + $message['url'] = route('message.show', ['type' => $message['url_type'], $msgId]); + unset($message['url_type']); + } + + $response = Http::timeout(15) + ->get('https://api.day.app/'.sysConfig('bark_key')."/{$message['title']}/{$message['content']}?".http_build_query(Arr::except($message, ['title', 'content']))); if ($response->ok()) { $ret = $response->json(); // 发送成功 if ($ret['code'] === 200) { - Helpers::addNotificationLog($message['title'], $message['content'], 3); + Helpers::addNotificationLog($message['title'], $message['content'], 3, 1, null, $msgId ?? null); return $ret; } // 发送失败 - Helpers::addNotificationLog($message['title'], $message['content'], 3, 'admin', -1, $message); + Helpers::addNotificationLog($message['title'], $message['content'], 3, -1); return false; } diff --git a/app/Channels/Components/WeChat.php b/app/Channels/Components/WeChat.php index d2067f37..bf45acfa 100644 --- a/app/Channels/Components/WeChat.php +++ b/app/Channels/Components/WeChat.php @@ -5,6 +5,7 @@ namespace App\Channels\Components; use DOMDocument; use Exception; use Log; +use Str; class WeChat { @@ -193,8 +194,8 @@ class PKCS7Encoder */ class Prpcrypt { - public $key = null; - public $iv = null; + public $key; + public $iv; public function __construct() { diff --git a/app/Channels/PushBearChannel.php b/app/Channels/PushBearChannel.php index eaca0c7e..bf023779 100644 --- a/app/Channels/PushBearChannel.php +++ b/app/Channels/PushBearChannel.php @@ -26,7 +26,7 @@ class PushBearChannel return $ret; } // 发送失败 - Helpers::addMarketing(2, $message['title'], $message['content'], -1, $ret['message']); + Helpers::addMarketing(2, $message['title'], $message['content'], -1, '无返回内容'); return false; } diff --git a/app/Channels/PushPlusChannel.php b/app/Channels/PushPlusChannel.php index c9d83361..b9c38b70 100644 --- a/app/Channels/PushPlusChannel.php +++ b/app/Channels/PushPlusChannel.php @@ -30,7 +30,7 @@ class PushPlusChannel return $ret; } // 发送失败 - Helpers::addNotificationLog($message['title'], $message['content'], 7, 'admin', -1, $ret ? $ret['msg'] : '未知'); + Helpers::addNotificationLog($message['title'], $message['content'], 7, -1, $ret ? $ret['msg'] : '未知'); return false; } diff --git a/app/Channels/ServerChanChannel.php b/app/Channels/ServerChanChannel.php index 81fce1e9..2707e24d 100644 --- a/app/Channels/ServerChanChannel.php +++ b/app/Channels/ServerChanChannel.php @@ -40,7 +40,7 @@ class ServerChanChannel return $ret; } // 发送失败 - Helpers::addNotificationLog($message['title'], $message['content'], 2, 'admin', -1, $ret ? $ret['errmsg'] : '未知'); + Helpers::addNotificationLog($message['title'], $message['content'], 2, -1, $ret ? $ret['errmsg'] : '未知'); return false; } diff --git a/app/Channels/TgChatChannel.php b/app/Channels/TgChatChannel.php index b109e312..1e947b09 100644 --- a/app/Channels/TgChatChannel.php +++ b/app/Channels/TgChatChannel.php @@ -24,7 +24,7 @@ class TgChatChannel return $ret; } // 发送失败 - Helpers::addNotificationLog($message['title'], $message['content'], 6, 'admin', -1, $ret ? $ret['message'] : '未知'); + Helpers::addNotificationLog($message['title'], $message['content'], 6, -1, $ret ? $ret['message'] : '未知'); return false; } diff --git a/app/Channels/WeChatChannel.php b/app/Channels/WeChatChannel.php index e23ba924..9eb0412a 100644 --- a/app/Channels/WeChatChannel.php +++ b/app/Channels/WeChatChannel.php @@ -7,7 +7,6 @@ use Cache; use Helpers; use Http; use Illuminate\Http\Request; -use Illuminate\Mail\Markdown; use Illuminate\Notifications\Notification; use Log; use Str; @@ -17,29 +16,39 @@ class WeChatChannel private $access_token; public function __construct() + { + $this->access_token = $this->getAccessToken(); + } + + private function getAccessToken() { if (Cache::has('wechat_access_token')) { - $this->access_token = Cache::get('wechat_access_token'); + $access_token = Cache::get('wechat_access_token'); } else { // https://work.weixin.qq.com/api/doc/90000/90135/91039 $response = Http::get('https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid='.sysConfig('wechat_cid').'&corpsecret='.sysConfig('wechat_secret')); if ($response->ok() && isset($response->json()['access_token'])) { - $this->access_token = $response->json()['access_token']; + $access_token = $response->json()['access_token']; Cache::put('wechat_access_token', $response->json()['access_token'], 7200); // 2小时 } else { Log::critical('Wechat消息推送异常:获取access_token失败!'.PHP_EOL.'携带访问参数:'.$response->body()); abort(400); } } + + return $access_token ?? null; } public function send($notifiable, Notification $notification) - { + { // route('message.show', ['type' => 'markdownMsg', 'msgId' => '']) $message = $notification->toCustom($notifiable); + if (! $this->access_token) { + $this->access_token = $this->getAccessToken(); + } $url = 'https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token='.$this->access_token; - if (isset($message['button'])) { + if (isset($message['button'])) { // 按钮交互型 // https://work.weixin.qq.com/api/doc/90000/90135/90236#%E6%8C%89%E9%92%AE%E4%BA%A4%E4%BA%92%E5%9E%8B $body = [ 'touser' => '@all', @@ -66,18 +75,27 @@ class WeChatChannel ], ], ]; - } else { + } elseif (isset($message['url_type'])) { // 文本卡片 + $msgId = Str::uuid(); // 生成对公消息查询URL $body = [ 'touser' => '@all', 'agentid' => sysConfig('wechat_aid'), 'msgtype' => 'textcard', 'textcard' => [ 'title' => $message['title'], - 'description' => Markdown::parse($message['content'])->toHtml(), - 'url' => route('admin.index'), - 'btntxt' => '', + 'description' => '请点击下方按钮【查看详情】', + 'url' => route('message.show', ['type' => $message['url_type'], $msgId]), + 'btntxt' => '查看详情', ], ]; + } else { // 文本消息 + $body = [ + 'touser' => '@all', + 'agentid' => sysConfig('wechat_aid'), + 'msgtype' => 'text', + 'text' => ['content' => $message['content']], + 'duplicate_check_interval' => 600, + ]; } $response = Http::timeout(15)->withBody(json_encode($body, JSON_UNESCAPED_UNICODE), 'application/json; charset=utf-8')->post($url); @@ -86,12 +104,12 @@ class WeChatChannel if ($response->ok()) { $ret = $response->json(); if (! $ret['errcode'] && $ret['errmsg'] === 'ok') { - Helpers::addNotificationLog($message['title'], $message['content'] ?? var_export($message['body'], true), 5); + Helpers::addNotificationLog($message['title'], $message['content'] ?? var_export($message['body'], true), 5, 1, null, $msgId ?? null); return $ret; } // 发送失败 - Helpers::addNotificationLog($message['title'], $message['content'] ?? var_export($message['body'], true), 5, 'admin', -1, $ret ? $ret['errmsg'] : '未知'); + Helpers::addNotificationLog($message['title'], $message['content'] ?? var_export($message['body'], true), 5, -1, $ret ? $ret['errmsg'] : '未知'); return false; } diff --git a/app/Components/Helpers.php b/app/Components/Helpers.php index 034de517..a5113987 100644 --- a/app/Components/Helpers.php +++ b/app/Components/Helpers.php @@ -150,15 +150,17 @@ class Helpers * @param string $title 标题 * @param string $content 内容 * @param int $type 发送类型 - * @param string $address 收信方 * @param int $status 投递状态 - * @param string $error 投递失败时记录的异常信息 + * @param string|null $error 投递失败时记录的异常信息 + * @param string|null $msgId 对公查询ID + * @param string $address 收信方 * @return int */ - public static function addNotificationLog(string $title, string $content, int $type, string $address = 'admin', int $status = 1, string $error = ''): int + public static function addNotificationLog(string $title, string $content, int $type, int $status = 1, string $error = null, string $msgId = null, string $address = 'admin'): int { $log = new NotificationLog(); $log->type = $type; + $log->msg_id = $msgId; $log->address = $address; $log->title = $title; $log->content = $content; diff --git a/app/Http/Controllers/MessageController.php b/app/Http/Controllers/MessageController.php new file mode 100644 index 00000000..4da9949f --- /dev/null +++ b/app/Http/Controllers/MessageController.php @@ -0,0 +1,21 @@ +latest()->firstOrFail(); + $title = $log->title; + $content = Markdown::parse($log->content)->toHtml(); + } + + return view('components.message', compact('title', 'content')); + } +} diff --git a/app/Notifications/Custom.php b/app/Notifications/Custom.php index a35611c9..647d128f 100644 --- a/app/Notifications/Custom.php +++ b/app/Notifications/Custom.php @@ -49,4 +49,16 @@ class Custom extends Notification implements ShouldQueue ->token(sysConfig('telegram_token')) ->content($this->content); } + + public function toBark($notifiable) + { + return [ + 'title' => $this->title, + 'content' => $this->content, + 'group' => '自定义信息', + 'icon' => asset('assets/images/notification/custom.png'), + 'sound' => 'newmail', + 'url_type' => 'markdown', + ]; + } } diff --git a/app/Notifications/NodeBlocked.php b/app/Notifications/NodeBlocked.php index eef4628c..95d262d9 100644 --- a/app/Notifications/NodeBlocked.php +++ b/app/Notifications/NodeBlocked.php @@ -53,8 +53,9 @@ class NodeBlocked extends Notification implements ShouldQueue public function toCustom($notifiable) { return [ - 'title' => trans('notification.node_block'), - 'content' => $this->markdownMessage(), + 'title' => trans('notification.node_block'), + 'content' => $this->markdownMessage(), + 'url_type' => 'markdown', ]; } diff --git a/app/Notifications/NodeDailyReport.php b/app/Notifications/NodeDailyReport.php index 9f445b3e..f99d726c 100644 --- a/app/Notifications/NodeDailyReport.php +++ b/app/Notifications/NodeDailyReport.php @@ -46,6 +46,7 @@ class NodeDailyReport extends Notification implements ShouldQueue return [ 'title' => __('Nodes Daily Report'), 'content' => $this->markdownMessage(), + 'url_type' => 'markdown', ]; } diff --git a/app/Notifications/NodeOffline.php b/app/Notifications/NodeOffline.php index 1df40d30..ca39e421 100644 --- a/app/Notifications/NodeOffline.php +++ b/app/Notifications/NodeOffline.php @@ -46,6 +46,7 @@ class NodeOffline extends Notification implements ShouldQueue return [ 'title' => trans('notification.node_offline'), 'content' => $this->markdownMessage(), + 'url_type' => 'markdown', ]; } @@ -54,6 +55,8 @@ class NodeOffline extends Notification implements ShouldQueue return [ 'title' => trans('notification.node_offline'), 'content' => $this->stringMessage(), + 'group' => '节点状态', + 'icon' => asset('assets/images/notification/offline.png'), ]; } diff --git a/app/Notifications/PaymentConfirm.php b/app/Notifications/PaymentConfirm.php index d2473cef..164e962c 100644 --- a/app/Notifications/PaymentConfirm.php +++ b/app/Notifications/PaymentConfirm.php @@ -6,7 +6,6 @@ use App\Models\Order; use App\Models\User; use Illuminate\Bus\Queueable; use Illuminate\Notifications\Notification; -use NotificationChannels\Telegram\TelegramChannel; use NotificationChannels\Telegram\TelegramMessage; class PaymentConfirm extends Notification @@ -31,7 +30,7 @@ class PaymentConfirm extends Notification { $order = $this->order; $goods = $this->order->goods; - $message = sprintf("🛒 人工支付\n———————————————\n\t\tℹ️ 账号:%s\n\t\t💰 金额:%s\n\t\t📦 商品:%s\n\t\t", $order->user->username, $order->amount, $goods->name ?? '余额充值'); + $message = sprintf("🛒 人工支付\n———————————————\n\t\tℹ️ 账号:%s\n\t\t💰 金额:%1.2f\n\t\t📦 商品:%s\n\t\t", $order->user->username, $order->amount, $goods->name ?? '余额充值'); foreach (User::role('Super Admin')->get() as $admin) { if (! $admin->telegram_user_id) { continue; @@ -62,7 +61,7 @@ class PaymentConfirm extends Notification ], [ 'keyname' => '💰 金额', - 'value' => $order->amount, + 'value' => sprintf('%1.2f', $order->amount), ], [ 'keyname' => '📦 商品', diff --git a/app/Notifications/PaymentReceived.php b/app/Notifications/PaymentReceived.php index 0b6d9d8f..6b7eb444 100644 --- a/app/Notifications/PaymentReceived.php +++ b/app/Notifications/PaymentReceived.php @@ -2,7 +2,6 @@ namespace App\Notifications; -use App\Models\User; use Illuminate\Bus\Queueable; use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Notifications\Messages\MailMessage; @@ -46,17 +45,15 @@ class PaymentReceived extends Notification implements ShouldQueue // todo: 需要重新审视发送对象 public function toTelegram($notifiable) { - foreach (User::role('Super Admin')->get() as $admin) { - $message = sprintf( - "💰成功收款%s元\n———————————————\n订单号:%s", - $this->amount, - $this->sn - ); + $message = sprintf( + "💰成功收款%s元\n———————————————\n订单号:%s", + $this->amount, + $this->sn + ); - return TelegramMessage::create() - ->to($admin->telegram_user_id) - ->token(sysConfig('telegram_token')) - ->content($message); - } + return TelegramMessage::create() + ->to($notifiable->telegram_user_id) + ->token(sysConfig('telegram_token')) + ->content($message); } } diff --git a/app/Notifications/TicketClosed.php b/app/Notifications/TicketClosed.php index b7b65f64..0be08d2b 100644 --- a/app/Notifications/TicketClosed.php +++ b/app/Notifications/TicketClosed.php @@ -55,4 +55,15 @@ class TicketClosed extends Notification implements ShouldQueue ->token(sysConfig('telegram_token')) ->content($this->reason); } + + public function toBark($notifiable) + { + return [ + 'title' => trans('notification.close_ticket', ['id' => $this->ticketId, 'title' => $this->title]), + 'content' => $this->reason, + 'group' => '工单', + 'icon' => asset('assets/images/notification/ticket.png'), + 'url' => $this->url, + ]; + } } diff --git a/app/Notifications/TicketCreated.php b/app/Notifications/TicketCreated.php index 418f58d1..3bfa39d0 100644 --- a/app/Notifications/TicketCreated.php +++ b/app/Notifications/TicketCreated.php @@ -58,4 +58,15 @@ class TicketCreated extends Notification implements ShouldQueue { return "📮工单提醒 #{$ticket->id}\n———————————————\n主题:\n`{$ticket->title}`\n内容:\n`{$ticket->content}`"; } + + public function toBark($notifiable) + { + return [ + 'title' => trans('notification.new_ticket', ['title' => $this->ticket->title]), + 'content' => trans('notification.ticket_content').strip_tags($this->ticket->content), + 'group' => '工单', + 'icon' => asset('assets/images/notification/ticket.png'), + 'url' => $this->url, + ]; + } } diff --git a/app/Notifications/TicketReplied.php b/app/Notifications/TicketReplied.php index 1a939b4f..1f1bf34b 100644 --- a/app/Notifications/TicketReplied.php +++ b/app/Notifications/TicketReplied.php @@ -58,4 +58,15 @@ class TicketReplied extends Notification implements ShouldQueue { return "📮工单回复提醒 #{$reply->ticket->id}\n———————————————\n主题:\n`{$reply->ticket->title}`\n内容:\n`{$reply->content}`"; } + + public function toBark($notifiable) + { + return [ + 'title' => trans('notification.reply_ticket', ['title' => $this->reply->ticket->title]), + 'content' => trans('notification.ticket_content').strip_tags($this->reply->content), + 'group' => '工单', + 'icon' => asset('assets/images/notification/ticket.png'), + 'url' => $this->url, + ]; + } } diff --git a/database/migrations/2022_01_16_160308_add_msgid_notification_log.php b/database/migrations/2022_01_16_160308_add_msgid_notification_log.php new file mode 100644 index 00000000..a94b52d8 --- /dev/null +++ b/database/migrations/2022_01_16_160308_add_msgid_notification_log.php @@ -0,0 +1,32 @@ +uuid('msg_id')->nullable()->comment('消息对公查询号')->after('id'); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('notification_log', static function (Blueprint $table) { + $table->dropColumn('msg_id'); + }); + } +} diff --git a/public/assets/images/notification/custom.png b/public/assets/images/notification/custom.png new file mode 100644 index 00000000..90bc8dfc Binary files /dev/null and b/public/assets/images/notification/custom.png differ diff --git a/public/assets/images/notification/offline.png b/public/assets/images/notification/offline.png new file mode 100644 index 00000000..ceb52727 Binary files /dev/null and b/public/assets/images/notification/offline.png differ diff --git a/public/assets/images/notification/ticket.png b/public/assets/images/notification/ticket.png new file mode 100644 index 00000000..c377a65b Binary files /dev/null and b/public/assets/images/notification/ticket.png differ diff --git a/resources/views/_layout.blade.php b/resources/views/_layout.blade.php index 894732b5..4fbff22e 100644 --- a/resources/views/_layout.blade.php +++ b/resources/views/_layout.blade.php @@ -14,7 +14,7 @@ content="An account management Panel based on Laravel7 framework. Include multiple payment, account management, system caching, admin notification, products models, and more."> - + @yield('title') diff --git a/resources/views/components/message.blade.php b/resources/views/components/message.blade.php new file mode 100644 index 00000000..9b920332 --- /dev/null +++ b/resources/views/components/message.blade.php @@ -0,0 +1,44 @@ +@extends('_layout') +@section('title', sysConfig('website_name')) +@section('body_class','page-login-v3 layout-full') +@section('layout_css') + + +@endsection +@section('layout_content') +
+
+
+
+

+ {{ $title }} +

+
+
+ {!! $content !!} +
+
+
+
+@endsection diff --git a/resources/views/components/payment/detail.blade.php b/resources/views/components/payment/detail.blade.php index 1dd68971..4a148486 100644 --- a/resources/views/components/payment/detail.blade.php +++ b/resources/views/components/payment/detail.blade.php @@ -88,7 +88,6 @@ - @endsection diff --git a/resources/views/user/components/payment/manual.blade.php b/resources/views/user/components/payment/manual.blade.php index 2e9cd442..f9d7cc91 100644 --- a/resources/views/user/components/payment/manual.blade.php +++ b/resources/views/user/components/payment/manual.blade.php @@ -10,12 +10,47 @@ display: none; } + @media (max-width: 768px) { + #ad { + right: 1vw; + bottom: 20vh; + } + + #ad img { + width: 40vw; + } + } + + @media (min-width: 768px) { + #ad { + right: 3vw; + bottom: 15vh; + } + + #ad img { + width: 30vw; + } + } + + @media (min-width: 1200px) { + #ad { + right: 10vw; + bottom: 15vh; + } + + #ad img { + width: 20vw; + } + } + #ad { position: fixed; z-index: 9999; - right: 30px; - bottom: 30px; - margin-left: 535px; + margin-right: auto; + } + + #ad img { + max-width: 300px; } #ad > button { @@ -28,10 +63,8 @@ @section('content')
@@ -40,7 +73,10 @@ {{sysConfig('website_name').' '.trans('common.payment.manual')}}
-
+
+
+

扫完二维码,支付完成后。记得回来 点击👇【下一步】 直到 点击👇【{{trans('common.submit')}}】 才算正式支付完成呦!

+
1 @@ -59,7 +95,7 @@
3
- 等待 + 完成

等待支付被确认

@@ -120,7 +156,7 @@
支付时,请充值正确金额(多不退,少要补)
-
+
  • {{trans('user.shop.service').':'.$name}}
  • {{trans('user.shop.price').':¥'.$payment->amount}}
  • @@ -133,7 +169,7 @@
    - +
@@ -159,12 +195,14 @@ if (n === x.length - 1) { document.getElementById('payment-group').style.display = 'none'; - document.getElementById('nextBtn').classList.remove('btn-default'); - document.getElementById('nextBtn').classList.add('btn-primary'); - document.getElementById('nextBtn').innerHTML = '{{trans('user.status.completed')}}'; + document.getElementById('nextBtn').classList.remove('btn-primary'); + document.getElementById('nextBtn').classList.add('btn-success'); + document.getElementById('nextBtn').innerHTML = '{{trans('common.submit')}}'; } else { document.getElementById('payment-group').style.display = 'inline-flex'; document.getElementById('nextBtn').innerHTML = '下一步'; + document.getElementById('nextBtn').classList.remove('btn-success'); + document.getElementById('nextBtn').classList.add('btn-primary'); document.getElementById('nextBtn').style.display = 'inline'; } @@ -174,10 +212,8 @@ function nextPrev(n) { // This function will figure out which tab to display const x = document.getElementsByClassName('tab'); - // Hide the current tab: - x[currentTab].style.display = 'none'; // if you have reached the end of the form... : - if (currentTab === x.length - 1) { + if (currentTab === x.length - 1 && n === 1) { //...the form gets submitted: $.post('{{route('manual.inform', ['payment' => $payment->trade_no])}}', {_token: '{{csrf_token()}}'}, function(ret) { if (ret.status === 'success') { @@ -188,11 +224,11 @@ }); return false; } else { - // Increase or decrease the current tab by 1: - currentTab += n; - showTab(currentTab); + x[currentTab].style.display = 'none';// Hide the current tab: + currentTab += n;// Increase or decrease the current tab by 1: } + showTab(currentTab); } function fixStepIndicator(n) { diff --git a/resources/views/user/help.blade.php b/resources/views/user/help.blade.php index c12d5f6a..5ba269cf 100644 --- a/resources/views/user/help.blade.php +++ b/resources/views/user/help.blade.php @@ -198,25 +198,21 @@
+

方法一

+

电脑有安装任何电脑管家类的软件,都可以使用他们自带的网络修复工具来重置网络。

+

方法二

  1. - 电脑有安装任何电脑管家类的软件,都可以使用他们自带的网络修复工具来重置网络。 + 键盘操作Win + X,或右击左下角开始菜单键 + (Win键看起来像 这样)
  2. -
      -
    1. - 键盘操作Win + X,或右击左下角开始菜单键 - (Win键看起来像 这样) -
    2. -
    3. - 按下 A键 或者 手动选择 - 命令提示符(管理员)/ Windows PowerShell(管理员) -
    4. -
    5. - 输入Netsh winsock reset 后回车,再输入 - netsh advfirewall reset 后回车; -
    6. -
    + 按下 A键 或者 手动选择 + 命令提示符(管理员)/ Windows PowerShell(管理员) +
  3. +
  4. + 输入Netsh winsock reset 后回车,再输入 + netsh advfirewall reset 后回车;
@@ -237,7 +233,7 @@ 账号在2种情况下会显示禁用;
  1. - 套餐过期/流量枯竭;此情况您需要重新 + 套餐过期/流量枯竭;此情况您需要重新购买/重置 【{{trans('user.menu.shop')}}】
  2. diff --git a/resources/views/user/layouts.blade.php b/resources/views/user/layouts.blade.php index 07a97689..280e051b 100644 --- a/resources/views/user/layouts.blade.php +++ b/resources/views/user/layouts.blade.php @@ -181,7 +181,7 @@
-