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."> - +
扫完二维码,支付完成后。记得回来 点击👇【下一步】 直到 点击👇【{{trans('common.submit')}}】 才算正式支付完成呦!
+等待支付被确认
电脑有安装任何电脑管家类的软件,都可以使用他们自带的网络修复工具来重置网络。
+Win + X,或右击左下角开始菜单键
+ (Win键看起来像 这样)
Win + X,或右击左下角开始菜单键
- (Win键看起来像 这样)
- A键 或者 手动选择
- 命令提示符(管理员)/ Windows PowerShell(管理员)
- Netsh winsock reset 后回车,再输入
- netsh advfirewall reset 后回车;
- A键 或者 手动选择
+ 命令提示符(管理员)/ Windows PowerShell(管理员)
+ Netsh winsock reset 后回车,再输入
+ netsh advfirewall reset 后回车;