فهرست منبع

本次提交是为了申请phpstorm开源者注册码

admin 6 سال پیش
والد
کامیت
359e2166b4
65فایلهای تغییر یافته به همراه1996 افزوده شده و 460 حذف شده
  1. 571 87
      _ide_helper.php
  2. 33 1
      app/Components/Curl.php
  3. 5 2
      app/Components/ServerChan.php
  4. 59 0
      app/Components/Sms.php
  5. 67 0
      app/Components/TelegramBot.php
  6. 6 6
      app/Console/Commands/AutoClearLog.php
  7. 66 9
      app/Exceptions/Handler.php
  8. 0 150
      app/Http/Controllers/Api/LoginController.php
  9. 0 81
      app/Http/Controllers/Api/PingController.php
  10. 1 1
      app/Http/Middleware/Affiliate.php
  11. 1 1
      app/Http/Middleware/TrustProxies.php
  12. 7 0
      app/Http/Middleware/isForbidden.php
  13. 1 1
      app/Http/Middleware/isSecurity.php
  14. 39 0
      app/Mail/closeOrder.php
  15. 39 0
      app/Mail/sendCustomMessage.php
  16. 38 0
      app/Mail/userTrafficAbnormalWarning.php
  17. 42 5
      app/helpers.php
  18. 108 2
      ca/cacert.pem
  19. 9 5
      config/app.php
  20. 1 1
      config/auth.php
  21. 8 0
      config/bt.php
  22. 16 0
      config/common.php
  23. 1 1
      config/geetest.php
  24. 0 32
      config/hashing.php
  25. 304 0
      config/jwt.php
  26. 2 13
      config/logging.php
  27. 1 1
      config/services.php
  28. 27 0
      config/sms.php
  29. 204 0
      config/telegram.php
  30. 1 1
      config/version.php
  31. 6 2
      public/install.php
  32. BIN
      public/ipip.ipdb
  33. BIN
      public/qqwry.dat
  34. 7 0
      readme.md
  35. 3 1
      resources/lang/en/home.php
  36. 3 0
      resources/lang/ja/home.php
  37. 3 0
      resources/lang/ko/home.php
  38. 3 0
      resources/lang/zh-CN/home.php
  39. 3 0
      resources/lang/zh-tw/home.php
  40. 1 1
      resources/views/auth/active.blade.php
  41. 2 2
      resources/views/auth/activeUser.blade.php
  42. 3 9
      resources/views/auth/free.blade.php
  43. 2 2
      resources/views/auth/layouts.blade.php
  44. 3 3
      resources/views/auth/login.blade.php
  45. 6 6
      resources/views/auth/register.blade.php
  46. 1 1
      resources/views/auth/reset.blade.php
  47. 2 2
      resources/views/auth/resetPassword.blade.php
  48. 2 2
      resources/views/coupon/addCoupon.blade.php
  49. 5 5
      resources/views/coupon/couponList.blade.php
  50. 87 0
      resources/views/emails/closeOrder.blade.php
  51. 87 0
      resources/views/emails/sendCustomMessage.blade.php
  52. 1 1
      resources/views/emails/userExpireWarning.blade.php
  53. 1 1
      resources/views/emails/userExpireWarningToday.blade.php
  54. 87 0
      resources/views/emails/userTrafficAbnormalWarning.blade.php
  55. 1 1
      resources/views/emails/userTrafficWarning.blade.php
  56. 6 1
      resources/views/marketing/emailList.blade.php
  57. 3 3
      resources/views/payment/detail.blade.php
  58. 3 3
      resources/views/sensitiveWords/addSensitiveWords.blade.php
  59. 4 4
      resources/views/ticket/replyTicket.blade.php
  60. 2 2
      resources/views/ticket/ticketList.blade.php
  61. 1 1
      resources/views/vendor/geetest/geetest.blade.php
  62. 0 6
      routes/api.php
  63. BIN
      scripts/servers/shadowsocksr-3.2.2.tar.gz
  64. BIN
      scripts/servers/vnet-0.0.6.zip
  65. 1 1
      sql/update/20190129.sql

+ 571 - 87
_ide_helper.php

@@ -3,7 +3,7 @@
 
 /**
  * A helper file for Laravel 5, to provide autocomplete information to your IDE
- * Generated for Laravel 5.6.39 on 2019-04-12 15:28:13.
+ * Generated for Laravel 5.6.39 on 2019-06-09 16:33:20.
  *
  * This file should not be included in your code, only analyzed by your IDE!
  *
@@ -3299,20 +3299,6 @@ namespace Illuminate\Support\Facades {
                         return $instance->macroCall($method, $parameters);
         }
         
-        /**
-         * Get a lock instance.
-         *
-         * @param string $name
-         * @param int $seconds
-         * @return \Illuminate\Contracts\Cache\Lock 
-         * @static 
-         */ 
-        public static function lock($name, $seconds = 0)
-        {
-                        /** @var \Illuminate\Cache\RedisStore $instance */
-                        return $instance->lock($name, $seconds);
-        }
-        
         /**
          * Remove all items from the cache.
          *
@@ -3321,45 +3307,32 @@ namespace Illuminate\Support\Facades {
          */ 
         public static function flush()
         {
-                        /** @var \Illuminate\Cache\RedisStore $instance */
+                        /** @var \Illuminate\Cache\FileStore $instance */
                         return $instance->flush();
         }
         
         /**
-         * Get the Redis connection instance.
+         * Get the Filesystem instance.
          *
-         * @return \Predis\ClientInterface 
+         * @return \Illuminate\Filesystem\Filesystem 
          * @static 
          */ 
-        public static function connection()
+        public static function getFilesystem()
         {
-                        /** @var \Illuminate\Cache\RedisStore $instance */
-                        return $instance->connection();
+                        /** @var \Illuminate\Cache\FileStore $instance */
+                        return $instance->getFilesystem();
         }
         
         /**
-         * Set the connection name to be used.
+         * Get the working directory of the cache.
          *
-         * @param string $connection
-         * @return void 
-         * @static 
-         */ 
-        public static function setConnection($connection)
-        {
-                        /** @var \Illuminate\Cache\RedisStore $instance */
-                        $instance->setConnection($connection);
-        }
-        
-        /**
-         * Get the Redis database instance.
-         *
-         * @return \Illuminate\Contracts\Redis\Factory 
+         * @return string 
          * @static 
          */ 
-        public static function getRedis()
+        public static function getDirectory()
         {
-                        /** @var \Illuminate\Cache\RedisStore $instance */
-                        return $instance->getRedis();
+                        /** @var \Illuminate\Cache\FileStore $instance */
+                        return $instance->getDirectory();
         }
         
         /**
@@ -3370,22 +3343,9 @@ namespace Illuminate\Support\Facades {
          */ 
         public static function getPrefix()
         {
-                        /** @var \Illuminate\Cache\RedisStore $instance */
+                        /** @var \Illuminate\Cache\FileStore $instance */
                         return $instance->getPrefix();
         }
-        
-        /**
-         * Set the cache key prefix.
-         *
-         * @param string $prefix
-         * @return void 
-         * @static 
-         */ 
-        public static function setPrefix($prefix)
-        {
-                        /** @var \Illuminate\Cache\RedisStore $instance */
-                        $instance->setPrefix($prefix);
-        }
          
     }
 
@@ -7700,46 +7660,33 @@ namespace Illuminate\Support\Facades {
         }
         
         /**
-         * Migrate the delayed jobs that are ready to the regular queue.
-         *
-         * @param string $from
-         * @param string $to
-         * @return array 
-         * @static 
-         */ 
-        public static function migrateExpiredJobs($from, $to)
-        {
-                        /** @var \Illuminate\Queue\RedisQueue $instance */
-                        return $instance->migrateExpiredJobs($from, $to);
-        }
-        
-        /**
-         * Delete a reserved job from the queue.
+         * Release a reserved job back onto the queue.
          *
          * @param string $queue
-         * @param \Illuminate\Queue\Jobs\RedisJob $job
-         * @return void 
+         * @param \Illuminate\Queue\Jobs\DatabaseJobRecord $job
+         * @param int $delay
+         * @return mixed 
          * @static 
          */ 
-        public static function deleteReserved($queue, $job)
+        public static function release($queue, $job, $delay)
         {
-                        /** @var \Illuminate\Queue\RedisQueue $instance */
-                        $instance->deleteReserved($queue, $job);
+                        /** @var \Illuminate\Queue\DatabaseQueue $instance */
+                        return $instance->release($queue, $job, $delay);
         }
         
         /**
-         * Delete a reserved job from the reserved queue and release it.
+         * Delete a reserved job from the queue.
          *
          * @param string $queue
-         * @param \Illuminate\Queue\Jobs\RedisJob $job
-         * @param int $delay
+         * @param string $id
          * @return void 
+         * @throws \Exception|\Throwable
          * @static 
          */ 
-        public static function deleteAndRelease($queue, $job, $delay)
+        public static function deleteReserved($queue, $id)
         {
-                        /** @var \Illuminate\Queue\RedisQueue $instance */
-                        $instance->deleteAndRelease($queue, $job, $delay);
+                        /** @var \Illuminate\Queue\DatabaseQueue $instance */
+                        $instance->deleteReserved($queue, $id);
         }
         
         /**
@@ -7751,20 +7698,20 @@ namespace Illuminate\Support\Facades {
          */ 
         public static function getQueue($queue)
         {
-                        /** @var \Illuminate\Queue\RedisQueue $instance */
+                        /** @var \Illuminate\Queue\DatabaseQueue $instance */
                         return $instance->getQueue($queue);
         }
         
         /**
-         * Get the underlying Redis instance.
+         * Get the underlying database instance.
          *
-         * @return \Illuminate\Contracts\Redis\Factory 
+         * @return \Illuminate\Database\Connection 
          * @static 
          */ 
-        public static function getRedis()
+        public static function getDatabase()
         {
-                        /** @var \Illuminate\Queue\RedisQueue $instance */
-                        return $instance->getRedis();
+                        /** @var \Illuminate\Queue\DatabaseQueue $instance */
+                        return $instance->getDatabase();
         }
         
         /**
@@ -7777,7 +7724,7 @@ namespace Illuminate\Support\Facades {
         public static function getJobExpiration($job)
         {
             //Method inherited from \Illuminate\Queue\Queue            
-                        /** @var \Illuminate\Queue\RedisQueue $instance */
+                        /** @var \Illuminate\Queue\DatabaseQueue $instance */
                         return $instance->getJobExpiration($job);
         }
         
@@ -7791,7 +7738,7 @@ namespace Illuminate\Support\Facades {
         public static function setContainer($container)
         {
             //Method inherited from \Illuminate\Queue\Queue            
-                        /** @var \Illuminate\Queue\RedisQueue $instance */
+                        /** @var \Illuminate\Queue\DatabaseQueue $instance */
                         $instance->setContainer($container);
         }
          
@@ -15157,6 +15104,539 @@ namespace Misechow\NoCaptcha\Facades {
  
 }
 
+namespace Tymon\JWTAuth\Facades { 
+
+    /**
+     * 
+     *
+     */ 
+    class JWTAuth {
+        
+        /**
+         * Attempt to authenticate the user and return the token.
+         *
+         * @param array $credentials
+         * @return false|string 
+         * @static 
+         */ 
+        public static function attempt($credentials)
+        {
+                        /** @var \Tymon\JWTAuth\JWTAuth $instance */
+                        return $instance->attempt($credentials);
+        }
+        
+        /**
+         * Authenticate a user via a token.
+         *
+         * @return \Tymon\JWTAuth\Contracts\JWTSubject|false 
+         * @static 
+         */ 
+        public static function authenticate()
+        {
+                        /** @var \Tymon\JWTAuth\JWTAuth $instance */
+                        return $instance->authenticate();
+        }
+        
+        /**
+         * Alias for authenticate().
+         *
+         * @return \Tymon\JWTAuth\Contracts\JWTSubject|false 
+         * @static 
+         */ 
+        public static function toUser()
+        {
+                        /** @var \Tymon\JWTAuth\JWTAuth $instance */
+                        return $instance->toUser();
+        }
+        
+        /**
+         * Get the authenticated user.
+         *
+         * @return \Tymon\JWTAuth\Contracts\JWTSubject 
+         * @static 
+         */ 
+        public static function user()
+        {
+                        /** @var \Tymon\JWTAuth\JWTAuth $instance */
+                        return $instance->user();
+        }
+        
+        /**
+         * Generate a token for a given subject.
+         *
+         * @param \Tymon\JWTAuth\Contracts\JWTSubject $subject
+         * @return string 
+         * @static 
+         */ 
+        public static function fromSubject($subject)
+        {
+            //Method inherited from \Tymon\JWTAuth\JWT            
+                        /** @var \Tymon\JWTAuth\JWTAuth $instance */
+                        return $instance->fromSubject($subject);
+        }
+        
+        /**
+         * Alias to generate a token for a given user.
+         *
+         * @param \Tymon\JWTAuth\Contracts\JWTSubject $user
+         * @return string 
+         * @static 
+         */ 
+        public static function fromUser($user)
+        {
+            //Method inherited from \Tymon\JWTAuth\JWT            
+                        /** @var \Tymon\JWTAuth\JWTAuth $instance */
+                        return $instance->fromUser($user);
+        }
+        
+        /**
+         * Refresh an expired token.
+         *
+         * @param bool $forceForever
+         * @param bool $resetClaims
+         * @return string 
+         * @static 
+         */ 
+        public static function refresh($forceForever = false, $resetClaims = false)
+        {
+            //Method inherited from \Tymon\JWTAuth\JWT            
+                        /** @var \Tymon\JWTAuth\JWTAuth $instance */
+                        return $instance->refresh($forceForever, $resetClaims);
+        }
+        
+        /**
+         * Invalidate a token (add it to the blacklist).
+         *
+         * @param bool $forceForever
+         * @return \Tymon\JWTAuth\JWTAuth 
+         * @static 
+         */ 
+        public static function invalidate($forceForever = false)
+        {
+            //Method inherited from \Tymon\JWTAuth\JWT            
+                        /** @var \Tymon\JWTAuth\JWTAuth $instance */
+                        return $instance->invalidate($forceForever);
+        }
+        
+        /**
+         * Alias to get the payload, and as a result checks that
+         * the token is valid i.e. not expired or blacklisted.
+         *
+         * @throws \Tymon\JWTAuth\Exceptions\JWTException
+         * @return \Tymon\JWTAuth\Payload 
+         * @static 
+         */ 
+        public static function checkOrFail()
+        {
+            //Method inherited from \Tymon\JWTAuth\JWT            
+                        /** @var \Tymon\JWTAuth\JWTAuth $instance */
+                        return $instance->checkOrFail();
+        }
+        
+        /**
+         * Check that the token is valid.
+         *
+         * @param bool $getPayload
+         * @return \Tymon\JWTAuth\Payload|bool 
+         * @static 
+         */ 
+        public static function check($getPayload = false)
+        {
+            //Method inherited from \Tymon\JWTAuth\JWT            
+                        /** @var \Tymon\JWTAuth\JWTAuth $instance */
+                        return $instance->check($getPayload);
+        }
+        
+        /**
+         * Get the token.
+         *
+         * @return \Tymon\JWTAuth\Token|null 
+         * @static 
+         */ 
+        public static function getToken()
+        {
+            //Method inherited from \Tymon\JWTAuth\JWT            
+                        /** @var \Tymon\JWTAuth\JWTAuth $instance */
+                        return $instance->getToken();
+        }
+        
+        /**
+         * Parse the token from the request.
+         *
+         * @throws \Tymon\JWTAuth\Exceptions\JWTException
+         * @return \Tymon\JWTAuth\JWTAuth 
+         * @static 
+         */ 
+        public static function parseToken()
+        {
+            //Method inherited from \Tymon\JWTAuth\JWT            
+                        /** @var \Tymon\JWTAuth\JWTAuth $instance */
+                        return $instance->parseToken();
+        }
+        
+        /**
+         * Get the raw Payload instance.
+         *
+         * @return \Tymon\JWTAuth\Payload 
+         * @static 
+         */ 
+        public static function getPayload()
+        {
+            //Method inherited from \Tymon\JWTAuth\JWT            
+                        /** @var \Tymon\JWTAuth\JWTAuth $instance */
+                        return $instance->getPayload();
+        }
+        
+        /**
+         * Alias for getPayload().
+         *
+         * @return \Tymon\JWTAuth\Payload 
+         * @static 
+         */ 
+        public static function payload()
+        {
+            //Method inherited from \Tymon\JWTAuth\JWT            
+                        /** @var \Tymon\JWTAuth\JWTAuth $instance */
+                        return $instance->payload();
+        }
+        
+        /**
+         * Convenience method to get a claim value.
+         *
+         * @param string $claim
+         * @return mixed 
+         * @static 
+         */ 
+        public static function getClaim($claim)
+        {
+            //Method inherited from \Tymon\JWTAuth\JWT            
+                        /** @var \Tymon\JWTAuth\JWTAuth $instance */
+                        return $instance->getClaim($claim);
+        }
+        
+        /**
+         * Create a Payload instance.
+         *
+         * @param \Tymon\JWTAuth\Contracts\JWTSubject $subject
+         * @return \Tymon\JWTAuth\Payload 
+         * @static 
+         */ 
+        public static function makePayload($subject)
+        {
+            //Method inherited from \Tymon\JWTAuth\JWT            
+                        /** @var \Tymon\JWTAuth\JWTAuth $instance */
+                        return $instance->makePayload($subject);
+        }
+        
+        /**
+         * Check if the subject model matches the one saved in the token.
+         *
+         * @param string|object $model
+         * @return bool 
+         * @static 
+         */ 
+        public static function checkSubjectModel($model)
+        {
+            //Method inherited from \Tymon\JWTAuth\JWT            
+                        /** @var \Tymon\JWTAuth\JWTAuth $instance */
+                        return $instance->checkSubjectModel($model);
+        }
+        
+        /**
+         * Set the token.
+         *
+         * @param \Tymon\JWTAuth\Token|string $token
+         * @return \Tymon\JWTAuth\JWTAuth 
+         * @static 
+         */ 
+        public static function setToken($token)
+        {
+            //Method inherited from \Tymon\JWTAuth\JWT            
+                        /** @var \Tymon\JWTAuth\JWTAuth $instance */
+                        return $instance->setToken($token);
+        }
+        
+        /**
+         * Unset the current token.
+         *
+         * @return \Tymon\JWTAuth\JWTAuth 
+         * @static 
+         */ 
+        public static function unsetToken()
+        {
+            //Method inherited from \Tymon\JWTAuth\JWT            
+                        /** @var \Tymon\JWTAuth\JWTAuth $instance */
+                        return $instance->unsetToken();
+        }
+        
+        /**
+         * Set the request instance.
+         *
+         * @param \Illuminate\Http\Request $request
+         * @return \Tymon\JWTAuth\JWTAuth 
+         * @static 
+         */ 
+        public static function setRequest($request)
+        {
+            //Method inherited from \Tymon\JWTAuth\JWT            
+                        /** @var \Tymon\JWTAuth\JWTAuth $instance */
+                        return $instance->setRequest($request);
+        }
+        
+        /**
+         * Set whether the subject should be "locked".
+         *
+         * @param bool $lock
+         * @return \Tymon\JWTAuth\JWTAuth 
+         * @static 
+         */ 
+        public static function lockSubject($lock)
+        {
+            //Method inherited from \Tymon\JWTAuth\JWT            
+                        /** @var \Tymon\JWTAuth\JWTAuth $instance */
+                        return $instance->lockSubject($lock);
+        }
+        
+        /**
+         * Get the Manager instance.
+         *
+         * @return \Tymon\JWTAuth\Manager 
+         * @static 
+         */ 
+        public static function manager()
+        {
+            //Method inherited from \Tymon\JWTAuth\JWT            
+                        /** @var \Tymon\JWTAuth\JWTAuth $instance */
+                        return $instance->manager();
+        }
+        
+        /**
+         * Get the Parser instance.
+         *
+         * @return \Tymon\JWTAuth\Http\Parser\Parser 
+         * @static 
+         */ 
+        public static function parser()
+        {
+            //Method inherited from \Tymon\JWTAuth\JWT            
+                        /** @var \Tymon\JWTAuth\JWTAuth $instance */
+                        return $instance->parser();
+        }
+        
+        /**
+         * Get the Payload Factory.
+         *
+         * @return \Tymon\JWTAuth\Factory 
+         * @static 
+         */ 
+        public static function factory()
+        {
+            //Method inherited from \Tymon\JWTAuth\JWT            
+                        /** @var \Tymon\JWTAuth\JWTAuth $instance */
+                        return $instance->factory();
+        }
+        
+        /**
+         * Get the Blacklist.
+         *
+         * @return \Tymon\JWTAuth\Blacklist 
+         * @static 
+         */ 
+        public static function blacklist()
+        {
+            //Method inherited from \Tymon\JWTAuth\JWT            
+                        /** @var \Tymon\JWTAuth\JWTAuth $instance */
+                        return $instance->blacklist();
+        }
+        
+        /**
+         * Set the custom claims.
+         *
+         * @param array $customClaims
+         * @return \Tymon\JWTAuth\JWTAuth 
+         * @static 
+         */ 
+        public static function customClaims($customClaims)
+        {
+            //Method inherited from \Tymon\JWTAuth\JWT            
+                        /** @var \Tymon\JWTAuth\JWTAuth $instance */
+                        return $instance->customClaims($customClaims);
+        }
+        
+        /**
+         * Alias to set the custom claims.
+         *
+         * @param array $customClaims
+         * @return \Tymon\JWTAuth\JWTAuth 
+         * @static 
+         */ 
+        public static function claims($customClaims)
+        {
+            //Method inherited from \Tymon\JWTAuth\JWT            
+                        /** @var \Tymon\JWTAuth\JWTAuth $instance */
+                        return $instance->claims($customClaims);
+        }
+        
+        /**
+         * Get the custom claims.
+         *
+         * @return array 
+         * @static 
+         */ 
+        public static function getCustomClaims()
+        {
+            //Method inherited from \Tymon\JWTAuth\JWT            
+                        /** @var \Tymon\JWTAuth\JWTAuth $instance */
+                        return $instance->getCustomClaims();
+        }
+         
+    }
+ 
+}
+
+namespace Telegram\Bot\Laravel\Facades { 
+
+    /**
+     * Class Telegram.
+     *
+     */ 
+    class Telegram {
+        
+        /**
+         * Set the IoC Container.
+         *
+         * @param $container Container instance
+         * @return \Telegram\Bot\BotsManager 
+         * @static 
+         */ 
+        public static function setContainer($container)
+        {
+                        /** @var \Telegram\Bot\BotsManager $instance */
+                        return $instance->setContainer($container);
+        }
+        
+        /**
+         * Get the configuration for a bot.
+         *
+         * @param string|null $name
+         * @throws \InvalidArgumentException
+         * @return array 
+         * @static 
+         */ 
+        public static function getBotConfig($name = null)
+        {
+                        /** @var \Telegram\Bot\BotsManager $instance */
+                        return $instance->getBotConfig($name);
+        }
+        
+        /**
+         * Get a bot instance.
+         *
+         * @param string $name
+         * @return \Telegram\Bot\Api 
+         * @static 
+         */ 
+        public static function bot($name = null)
+        {
+                        /** @var \Telegram\Bot\BotsManager $instance */
+                        return $instance->bot($name);
+        }
+        
+        /**
+         * Reconnect to the given bot.
+         *
+         * @param string $name
+         * @return \Telegram\Bot\Api 
+         * @static 
+         */ 
+        public static function reconnect($name = null)
+        {
+                        /** @var \Telegram\Bot\BotsManager $instance */
+                        return $instance->reconnect($name);
+        }
+        
+        /**
+         * Disconnect from the given bot.
+         *
+         * @param string $name
+         * @return \Telegram\Bot\BotsManager 
+         * @static 
+         */ 
+        public static function disconnect($name = null)
+        {
+                        /** @var \Telegram\Bot\BotsManager $instance */
+                        return $instance->disconnect($name);
+        }
+        
+        /**
+         * Get the specified configuration value for Telegram.
+         *
+         * @param string $key
+         * @param mixed $default
+         * @return mixed 
+         * @static 
+         */ 
+        public static function getConfig($key, $default = null)
+        {
+                        /** @var \Telegram\Bot\BotsManager $instance */
+                        return $instance->getConfig($key, $default);
+        }
+        
+        /**
+         * Get the default bot name.
+         *
+         * @throws TelegramSDKException
+         * @return string|null 
+         * @static 
+         */ 
+        public static function getDefaultBotName()
+        {
+                        /** @var \Telegram\Bot\BotsManager $instance */
+                        return $instance->getDefaultBotName();
+        }
+        
+        /**
+         * Set the default bot name.
+         *
+         * @param string $name
+         * @return \Telegram\Bot\BotsManager 
+         * @static 
+         */ 
+        public static function setDefaultBot($name)
+        {
+                        /** @var \Telegram\Bot\BotsManager $instance */
+                        return $instance->setDefaultBot($name);
+        }
+        
+        /**
+         * Return all of the created bots.
+         *
+         * @return \Telegram\Bot\Api[] 
+         * @static 
+         */ 
+        public static function getBots()
+        {
+                        /** @var \Telegram\Bot\BotsManager $instance */
+                        return $instance->getBots();
+        }
+        
+        /**
+         * Builds the list of commands for the given commands array.
+         *
+         * @param array $commands
+         * @return array An array of commands which includes global and bot specific commands.
+         * @static 
+         */ 
+        public static function parseBotCommands($commands)
+        {
+                        /** @var \Telegram\Bot\BotsManager $instance */
+                        return $instance->parseBotCommands($commands);
+        }
+         
+    }
+ 
+}
+
 namespace Intervention\Image\Facades { 
 
     /**
@@ -17754,6 +18234,10 @@ namespace  {
 
     class NoCaptcha extends \Misechow\NoCaptcha\Facades\NoCaptcha {}
 
+    class JWTAuth extends \Tymon\JWTAuth\Facades\JWTAuth {}
+
+    class Telegram extends \Telegram\Bot\Laravel\Facades\Telegram {}
+
     class Image extends \Intervention\Image\Facades\Image {}
  
 }

+ 33 - 1
app/Components/Curl.php

@@ -14,7 +14,7 @@ class Curl
     {
         $ch = curl_init();
         curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
-        curl_setopt($ch, CURLOPT_TIMEOUT, 10);
+        curl_setopt($ch, CURLOPT_TIMEOUT, 3);
         curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
         curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
         curl_setopt($ch, CURLOPT_URL, $url);
@@ -29,4 +29,36 @@ class Curl
 
         return $res;
     }
+
+    /**
+     * POST JSON数据
+     *
+     * @param string $url    请求地址
+     * @param string $data   JSON数据
+     * @param string $secret 通信密钥
+     *
+     * @return mixed
+     */
+    public static function sendJson($url, $data, $secret)
+    {
+        $header = [
+            'Content-Type: application/json; charset=utf-8',
+            'Content-Length: ' . strlen($data),
+            'Secret: ' . $secret
+        ];
+
+        $ch = curl_init();
+        curl_setopt($ch, CURLOPT_URL, $url);
+        curl_setopt($ch, CURLOPT_POST, true);
+        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
+        curl_setopt($ch, CURLOPT_TIMEOUT, 3);
+        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
+        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
+        curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
+        curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
+        $res = curl_exec($ch);
+        curl_close($ch);
+
+        return json_decode($res);
+    }
 }

+ 5 - 2
app/Components/ServerChan.php

@@ -19,6 +19,7 @@ class ServerChan
     {
         if (Helpers::systemConfig()['is_server_chan'] && Helpers::systemConfig()['server_chan_key']) {
             try {
+                // TODO:一天仅可发送不超过500条
                 $url = 'https://sc.ftqq.com/' . Helpers::systemConfig()['server_chan_key'] . '.send?text=' . $title . '&desp=' . urlencode($content);
                 $response = Curl::send($url);
                 $result = json_decode($response);
@@ -28,13 +29,15 @@ class ServerChan
                     self::addLog($title, $content, 0, $result->errmsg);
                 }
             } catch (\Exception $e) {
-                Log::error($e);
+                Log::error('ServerChan消息推送异常:' . $e);
             }
+        } else {
+            Log::error('消息推送失败:未启用或未正确配置ServerChan');
         }
     }
 
     /**
-     * 添加serverChan投递日志
+     * 添加serverChan推送日志
      *
      * @param string $title   标题
      * @param string $content 内容

+ 59 - 0
app/Components/Sms.php

@@ -0,0 +1,59 @@
+<?php
+
+namespace App\Components;
+
+use Overtrue\EasySms\EasySms;
+
+/**
+ * 发送短信
+ *
+ * 参考文档:\vendor\overtrue\easy-sms\README.md
+ *
+ * Class Sms
+ *
+ * @package App\Components
+ */
+class Sms
+{
+    public static function send()
+    {
+
+        $config = [
+            // HTTP 请求的超时时间(秒)
+            'timeout'  => 5.0,
+
+            // 默认发送配置
+            'default'  => [
+                // 网关调用策略,默认:顺序调用
+                'strategy' => \Overtrue\EasySms\Strategies\OrderStrategy::class,
+
+                // 默认可用的发送网关
+                'gateways' => [
+                    'yunpian',
+                ],
+            ],
+
+            // 可用的网关配置
+            'gateways' => [
+                'errorlog' => [
+                    'file' => '/tmp/easy-sms.log',
+                ],
+                'yunpian'  => [
+                    'api_key' => '0c9c87c41aac355520d47d3c84e5a532',
+                ],
+            ],
+        ];
+
+        $easySms = new EasySms($config);
+
+        $result = $easySms->send(15960271718, [
+            'content'  => '您的验证码为: 6379',
+            'template' => '2189086',
+            'data'     => [
+                'code' => 6379
+            ],
+        ]);
+
+        return $result;
+    }
+}

+ 67 - 0
app/Components/TelegramBot.php

@@ -0,0 +1,67 @@
+<?php
+
+namespace App\Components;
+
+use App\Http\Models\EmailLog;
+use Log;
+use Telegram\Bot\Api;
+
+/**
+ * Telegram操作类
+ *
+ * Class Telegram
+ *
+ * @package App\Components
+ */
+class TelegramBot
+{
+    public static function send($title, $content)
+    {
+        if (Helpers::systemConfig()['is_telegram']) {
+            $telegram = new Api(Helpers::systemConfig()['telegram_token']);
+            try {
+                $response = $telegram->sendMessage([
+                    'chat_id'    => Helpers::systemConfig()['telegram_chatid'],
+                    'text'       => $content,
+                    'parse_mode' => 'Markdown'
+                ]);
+
+                if ($response->getMessageId()) {
+                    self::addLog($title, $content);
+                } else {
+                    self::addLog($title, $content, 0, 'Telegram消息推送失败');
+                }
+            } catch (\Exception $e) {
+                Log::error('Telegram消息推送异常:' . $e);
+            }
+        } else {
+            Log::error('消息推送失败:未启用或未正确配置Telegram');
+        }
+    }
+
+    /**
+     * 添加Telegram推送日志
+     *
+     * @param string $title   标题
+     * @param string $content 内容
+     * @param int    $status  投递状态
+     * @param string $error   投递失败时记录的异常信息
+     *
+     * @return int
+     */
+    private static function addLog($title, $content, $status = 1, $error = '')
+    {
+        $code = Helpers::makeEmailLogCode();
+
+        $log = new EmailLog();
+        $log->type = 4;
+        $log->code = $code;
+        $log->address = 'admin';
+        $log->title = $title;
+        $log->content = $content;
+        $log->status = $status;
+        $log->error = $error;
+
+        return $log->save();
+    }
+}

+ 6 - 6
app/Console/Commands/AutoClearLog.php

@@ -53,11 +53,11 @@ class AutoClearLog extends Command
         // 自动清除1小时以前的节点在线用户数日志
         SsNodeOnlineLog::query()->where('log_time', '<=', strtotime("-1 hour"))->delete();
 
-        // 自动清除7天以前的用户流量日志
-        UserTrafficLog::query()->where('log_time', '<=', strtotime("-7 days"))->delete();
+        // 自动清除3天以前的用户流量日志
+        UserTrafficLog::query()->where('log_time', '<=', strtotime("-3 days"))->delete();
 
-        // 自动清除10天以前的用户每小时流量数据日志
-        UserTrafficHourly::query()->where('created_at', '<=', date('Y-m-d H:i:s', strtotime('-10 days')))->delete();
+        // 自动清除3天以前的用户每小时流量数据日志
+        UserTrafficHourly::query()->where('created_at', '<=', date('Y-m-d H:i:s', strtotime('-3 days')))->delete();
 
         // 自动清除1个月以前的用户每天流量数据日志
         UserTrafficDaily::query()->where('created_at', '<=', date('Y-m-d H:i:s', strtotime('-1 month')))->delete();
@@ -71,8 +71,8 @@ class AutoClearLog extends Command
         // 自动清除30天以前用户封禁日志
         UserBanLog::query()->where('created_at', '<=', date('Y-m-d H:i:s', strtotime("-1 month")))->delete();
 
-        // 自动清除3天前用户连接IP
-        SsNodeIp::query()->where('created_at', '<=', strtotime("-3 days"))->delete();
+        // 自动清除1天前用户连接IP
+        SsNodeIp::query()->where('created_at', '<=', strtotime("-1 day"))->delete();
 
         // 自动清除3个月以前用户登陆日志
         UserLoginLog::query()->where('created_at', '<=', date('Y-m-d H:i:s', strtotime("-3 month")))->delete();

+ 66 - 9
app/Exceptions/Handler.php

@@ -7,8 +7,14 @@ use Exception;
 use Illuminate\Auth\AuthenticationException;
 use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
 use Illuminate\Session\TokenMismatchException;
+use InvalidArgumentException;
 use ReflectionException;
+use RuntimeException;
+use Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException;
 use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
+use Symfony\Component\HttpKernel\Exception\UnauthorizedHttpException;
+use Tymon\JWTAuth\Exceptions\TokenExpiredException;
+use Tymon\JWTAuth\Exceptions\TokenInvalidException;
 
 class Handler extends ExceptionHandler
 {
@@ -44,6 +50,11 @@ class Handler extends ExceptionHandler
         // 记录异常来源
         \Log::info('异常来源:' . get_class($exception));
 
+        // 调试模式下记录错误详情
+        if (config('app.debug')) {
+            \Log::info($exception);
+        }
+
         parent::report($exception);
     }
 
@@ -62,29 +73,56 @@ class Handler extends ExceptionHandler
             return parent::render($request, $exception);
         }
 
+        // 捕获未生成key异常
+        if ($exception instanceof RuntimeException) {
+            if ($request->expectsJson()) {
+                return response()->json(['status' => 'fail', 'data' => '', 'message' => $exception->getMessage()]);
+            } else {
+                return response()->view('auth.error', ['message' => $exception->getMessage()]);
+            }
+        }
+
         // 捕获访问异常
         if ($exception instanceof NotFoundHttpException) {
             \Log::info("异常请求:" . $request->fullUrl() . ",IP:" . getClientIp());
 
-            if ($request->ajax()) {
-                return response()->json(['status' => 'fail', 'data' => '', 'message' => 'Page Not Found']);
+            if ($request->expectsJson()) {
+                return response()->json(['status' => 'fail', 'data' => '', 'message' => $exception->getMessage()]);
+            } else {
+                return response()->view('auth.error', ['message' => $exception->getMessage()]);
+            }
+        }
+
+        // 路由参数异常
+        if ($exception instanceof InvalidArgumentException) {
+            if ($request->expectsJson()) {
+                return response()->json(['status' => 'fail', 'data' => '', 'message' => $exception->getMessage()]);
             } else {
-                return response()->view('auth.error', ['message' => 'Page Not Found']);
+                return response()->view('auth.error', ['message' => $exception->getMessage()]);
+            }
+        }
+
+        // 请求方式不允许异常
+        if ($exception instanceof MethodNotAllowedHttpException) {
+            if ($request->expectsJson()) {
+                return response()->json(['status' => 'fail', 'data' => '', 'message' => $exception->getMessage()]);
+            } else {
+                return response()->view('auth.error', ['message' => $exception->getMessage()]);
             }
         }
 
         // 捕获身份校验异常
         if ($exception instanceof AuthenticationException) {
-            if ($request->ajax()) {
-                return response()->json(['status' => 'fail', 'data' => '', 'message' => 'Unauthorized']);
+            if ($request->expectsJson()) {
+                return response()->json(['status' => 'fail', 'data' => '', 'message' => $exception->getMessage()]);
             } else {
-                return response()->view('auth.error', ['message' => 'Unauthorized']);
+                return response()->view('auth.error', ['message' => $exception->getMessage()]);
             }
         }
 
         // 捕获CSRF异常
         if ($exception instanceof TokenMismatchException) {
-            if ($request->ajax()) {
+            if ($request->expectsJson()) {
                 return response()->json(['status' => 'fail', 'data' => '', 'message' => 'System Error, Please Refresh Page, Try One More Time']);
             } else {
                 return response()->view('auth.error', ['message' => 'System Error, Please Refresh Page, Try One More Time']);
@@ -93,7 +131,7 @@ class Handler extends ExceptionHandler
 
         // 捕获反射异常
         if ($exception instanceof ReflectionException) {
-            if ($request->ajax()) {
+            if ($request->expectsJson()) {
                 return response()->json(['status' => 'fail', 'data' => '', 'message' => 'System Error']);
             } else {
                 return response()->view('auth.error', ['message' => 'System Error']);
@@ -102,13 +140,32 @@ class Handler extends ExceptionHandler
 
         // 捕获系统错误异常
         if ($exception instanceof ErrorException) {
-            if ($request->ajax()) {
+            if ($request->expectsJson()) {
                 return response()->json(['status' => 'fail', 'data' => '', 'message' => 'System Error']);
             } else {
                 return response()->view('auth.error', ['message' => 'System Error, See <a href="/logs" target="_blank">Logs</a>']);
             }
         }
 
+        // 未授权异常
+        if ($exception instanceof UnauthorizedHttpException) {
+            if ($request->expectsJson()) {
+                return response()->json(['status' => 'fail', 'data' => '', 'message' => $exception->getMessage()]);
+            } else {
+                return response()->view('auth.error', ['message' => $exception->getMessage()]);
+            }
+        }
+
+        // 客户端API:捕获认证过期异常
+        if ($exception instanceof TokenExpiredException) {
+            return response()->json(['status' => 'fail', 'data' => '', 'message' => $exception->getMessage()]);
+        }
+
+        // 客户端API:捕获认证不合法异常
+        if ($exception instanceof TokenInvalidException) {
+            return response()->json(['status' => 'fail', 'data' => '', 'message' => $exception->getMessage()]);
+        }
+
         return parent::render($request, $exception);
     }
 }

+ 0 - 150
app/Http/Controllers/Api/LoginController.php

@@ -1,150 +0,0 @@
-<?php
-
-namespace App\Http\Controllers\Api;
-
-use App\Components\Helpers;
-use App\Http\Controllers\Controller;
-use App\Http\Models\User;
-use App\Http\Models\UserLabel;
-use App\Http\Models\UserSubscribe;
-use App\Http\Models\UserSubscribeLog;
-use Illuminate\Http\Request;
-use Response;
-use Cache;
-use Hash;
-use DB;
-
-/**
- * 登录接口
- *
- * Class LoginController
- *
- * @package App\Http\Controllers
- */
-class LoginController extends Controller
-{
-    protected static $systemConfig;
-
-    function __construct()
-    {
-        self::$systemConfig = Helpers::systemConfig();
-    }
-
-    // 登录返回订阅信息
-    public function login(Request $request)
-    {
-        $username = trim($request->get('username'));
-        $password = trim($request->get('password'));
-        $cacheKey = 'request_times_' . md5(getClientIp());
-
-        if (!$username || !$password) {
-            Cache::increment($cacheKey);
-
-            return Response::json(['status' => 'fail', 'data' => [], 'message' => '请输入用户名和密码']);
-        }
-
-        // 连续请求失败15次,则封IP一小时
-        if (Cache::has($cacheKey)) {
-            if (Cache::get($cacheKey) >= 15) {
-                return Response::json(['status' => 'fail', 'data' => [], 'message' => '请求失败超限,禁止访问1小时']);
-            }
-        } else {
-            Cache::put($cacheKey, 1, 60);
-        }
-
-        $user = User::query()->where('username', $username)->where('status', '>=', 0)->first();
-        if (!$user) {
-            Cache::increment($cacheKey);
-
-            return Response::json(['status' => 'fail', 'data' => [], 'message' => '账号不存在或已被禁用']);
-        } elseif (!Hash::check($password, $user->password)) {
-            return Response::json(['status' => 'fail', 'data' => [], 'message' => '用户名或密码错误']);
-        }
-
-        DB::beginTransaction();
-        try {
-            // 如果未生成过订阅链接则生成一个
-            $subscribe = UserSubscribe::query()->where('user_id', $user->id)->first();
-
-            // 更新订阅链接访问次数
-            $subscribe->increment('times', 1);
-
-            // 记录每次请求
-            $this->log($subscribe->id, getClientIp(), 'API访问');
-
-            // 订阅链接
-            $url = self::$systemConfig['subscribe_domain'] ? self::$systemConfig['subscribe_domain'] : self::$systemConfig['website_url'];
-
-            // 节点列表
-            $userLabelIds = UserLabel::query()->where('user_id', $user->id)->pluck('label_id');
-            if (empty($userLabelIds)) {
-                return Response::json(['status' => 'fail', 'message' => '', 'data' => []]);
-            }
-
-            $nodeList = DB::table('ss_node')
-                ->selectRaw('ss_node.*')
-                ->leftJoin('ss_node_label', 'ss_node.id', '=', 'ss_node_label.node_id')
-                ->whereIn('ss_node_label.label_id', $userLabelIds)
-                ->where('ss_node.status', 1)
-                ->groupBy('ss_node.id')
-                ->orderBy('ss_node.sort', 'desc')
-                ->orderBy('ss_node.id', 'asc')
-                ->get();
-
-            $c_nodes = collect();
-            foreach ($nodeList as $node) {
-                $temp_node = [
-                    'name'          => $node->name,
-                    'server'        => $node->server,
-                    'server_port'   => $user->port,
-                    'method'        => $user->method,
-                    'obfs'          => $user->obfs,
-                    'flags'         => $url . '/assets/images/country/' . $node->country_code . '.png',
-                    'obfsparam'     => '',
-                    'password'      => $user->passwd,
-                    'group'         => '',
-                    'protocol'      => $user->protocol,
-                    'protoparam'    => '',
-                    'protocolparam' => ''
-                ];
-                $c_nodes = $c_nodes->push($temp_node);
-            }
-
-            $data = [
-                'status'       => 1,
-                'class'        => 0,
-                'level'        => 2,
-                'expire_in'    => $user->expire_time,
-                'text'         => '',
-                'buy_link'     => '',
-                'money'        => '0.00',
-                'sspannelName' => 'ssrpanel',
-                'usedTraffic'  => flowAutoShow($user->u + $user->d),
-                'Traffic'      => flowAutoShow($user->transfer_enable),
-                'all'          => 1,
-                'residue'      => '',
-                'nodes'        => $c_nodes,
-                'link'         => $url . '/s/' . $subscribe->code
-            ];
-
-            DB::commit();
-
-            return Response::json(['status' => 'success', 'data' => $data, 'message' => '登录成功']);
-        } catch (\Exception $e) {
-            DB::rollBack();
-
-            return Response::json(['status' => 'success', 'data' => [], 'message' => '登录失败']);
-        }
-    }
-
-    // 写入订阅访问日志
-    private function log($subscribeId, $ip, $headers)
-    {
-        $log = new UserSubscribeLog();
-        $log->sid = $subscribeId;
-        $log->request_ip = $ip;
-        $log->request_time = date('Y-m-d H:i:s');
-        $log->request_header = $headers;
-        $log->save();
-    }
-}

+ 0 - 81
app/Http/Controllers/Api/PingController.php

@@ -1,81 +0,0 @@
-<?php
-
-namespace App\Http\Controllers\Api;
-
-use App\Http\Controllers\Controller;
-use Illuminate\Http\Request;
-use Log;
-
-/**
- * PING检测工具
- *
- * Class PingController
- *
- * @package App\Http\Controllers\Api
- */
-class PingController extends Controller
-{
-    public function ping(Request $request)
-    {
-        $token = $request->input('token');
-        $host = $request->input('host');
-        $port = $request->input('port', 22);
-        $transport = $request->input('transport', 'tcp');
-        $timeout = $request->input('timeout', 0.5);
-
-        if (empty($host)) {
-            echo "<pre>";
-            echo "使用方法:";
-            echo "<br>";
-            echo "GET /api/ping?token=toke_value&host=www.baidu.com&port=80&transport=tcp&timeout=0.5";
-            echo "<br>";
-            echo "token:.env下加入API_TOKEN,其值就是token的值";
-            echo "<br>";
-            echo "host:检测地址,必传,可以是域名、IPv4、IPv6";
-            echo "<br>";
-            echo "port:检测端口,可不传,默认22";
-            echo "<br>";
-            echo "transport:检测协议,可不传,默认tcp,可以是tcp、udp";
-            echo "<br>";
-            echo "timeout:检测超时,单位秒,可不传,默认0.5秒,建议不超过3秒";
-            echo "<br>";
-            echo "成功返回:1,失败返回:0";
-            echo "</pre>";
-            exit();
-        }
-
-        // 验证TOKEN,防止滥用
-        if (env('API_TOKEN') != $token) {
-            return response()->json(['status' => 0, 'message' => 'token invalid']);
-        }
-
-        // 如果不是IPv4
-        if (false === filter_var($host, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) {
-            // 如果是IPv6
-            if (filter_var($host, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) {
-                $host = '[' . $host . ']';
-            }
-        }
-
-        try {
-            $host = gethostbyname($host); // 这里如果挂了,说明服务器的DNS解析不给力,必须换
-            $fp = stream_socket_client($transport . '://' . $host . ':' . $port, $errno, $errstr, $timeout);
-            if (!$fp) {
-                Log::info("$errstr ($errno)");
-                $ret = 0;
-                $message = 'port close';
-            } else {
-                $ret = 1;
-                $message = 'port open';
-            }
-
-            fclose($fp);
-
-            return response()->json(['status' => $ret, 'message' => $message]);
-        } catch (\Exception $e) {
-            Log::info($e);
-
-            return response()->json(['status' => 0, 'message' => 'port close']);
-        }
-    }
-}

+ 1 - 1
app/Http/Middleware/Affiliate.php

@@ -17,7 +17,7 @@ class Affiliate
      */
     public function handle($request, Closure $next)
     {
-        $aff = trim($request->get('aff', 0));
+        $aff = trim($request->input('aff', 0));
         if ($aff) {
             Cookie::queue('register_aff', $aff, 129600);
         }

+ 1 - 1
app/Http/Middleware/TrustProxies.php

@@ -17,7 +17,7 @@ class TrustProxies extends Middleware
     /**
      * The headers that should be used to detect proxies.
      *
-     * @var int
+     * @var string
      */
     protected $headers = Request::HEADER_X_FORWARDED_ALL;
 }

+ 7 - 0
app/Http/Middleware/isForbidden.php

@@ -30,6 +30,13 @@ class isForbidden
             }
         }
 
+        // 拒绝通过订阅链接域名访问网站,防止网站被探测
+        if (false !== strpos(Helpers::systemConfig()['subscribe_domain'], $request->getHost())) {
+            Log::info("识别到通过订阅链接访问,强制跳转至百度(" . getClientIp() . ")");
+
+            return redirect('https://www.baidu.com');
+        }
+
         $ip = getClientIP();
         if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) {
             Log::info('识别到IPv6,尝试解析:' . $ip);

+ 1 - 1
app/Http/Middleware/isSecurity.php

@@ -20,7 +20,7 @@ class isSecurity
     public function handle($request, Closure $next)
     {
         $ip = getClientIP();
-        $code = $request->get('securityCode');
+        $code = $request->input('securityCode');
         $cacheKey = 'SecurityLogin_' . ip2long($ip);
         $websiteSecurityCode = Helpers::systemConfig()['website_security_code'];
 

+ 39 - 0
app/Mail/closeOrder.php

@@ -0,0 +1,39 @@
+<?php
+
+namespace App\Mail;
+
+use App\Http\Models\EmailLog;
+use Illuminate\Bus\Queueable;
+use Illuminate\Mail\Mailable;
+use Illuminate\Queue\SerializesModels;
+use Illuminate\Contracts\Queue\ShouldQueue;
+
+class closeOrder extends Mailable implements ShouldQueue
+{
+    use Queueable, SerializesModels;
+
+    protected $id; // 邮件记录ID
+    protected $title; // 邮件标题
+    protected $content; // 邮件内容
+
+    public function __construct($id, $title, $content)
+    {
+        $this->id = $id;
+        $this->title = $title;
+        $this->content = $content;
+    }
+
+    public function build()
+    {
+        return $this->view('emails.closeOrder')->subject('订单关闭通知')->with([
+            'title'   => $this->title,
+            'content' => $this->content
+        ]);
+    }
+
+    // 发件失败处理
+    public function failed(\Exception $e)
+    {
+        EmailLog::query()->where('id', $this->id)->update(['status' => -1, 'error' => $e->getMessage()]);
+    }
+}

+ 39 - 0
app/Mail/sendCustomMessage.php

@@ -0,0 +1,39 @@
+<?php
+
+namespace App\Mail;
+
+use App\Http\Models\EmailLog;
+use Illuminate\Bus\Queueable;
+use Illuminate\Mail\Mailable;
+use Illuminate\Queue\SerializesModels;
+use Illuminate\Contracts\Queue\ShouldQueue;
+
+class sendCustomMessage extends Mailable implements ShouldQueue
+{
+    use Queueable, SerializesModels;
+
+    protected $id; // 邮件记录ID
+    protected $title; // 邮件标题
+    protected $content; // 邮件内容
+
+    public function __construct($id, $title, $content)
+    {
+        $this->id = $id;
+        $this->title = $title;
+        $this->content = $content;
+    }
+
+    public function build()
+    {
+        return $this->view('emails.sendCustomMessage')->subject($this->title)->with([
+            'title'   => $this->title,
+            'content' => $this->content
+        ]);
+    }
+
+    // 发件失败处理
+    public function failed(\Exception $e)
+    {
+        EmailLog::query()->where('id', $this->id)->update(['status' => -1, 'error' => $e->getMessage()]);
+    }
+}

+ 38 - 0
app/Mail/userTrafficAbnormalWarning.php

@@ -0,0 +1,38 @@
+<?php
+
+namespace App\Mail;
+
+use App\Http\Models\EmailLog;
+use Illuminate\Bus\Queueable;
+use Illuminate\Mail\Mailable;
+use Illuminate\Queue\SerializesModels;
+use Illuminate\Contracts\Queue\ShouldQueue;
+
+class userTrafficAbnormalWarning extends Mailable implements ShouldQueue
+{
+    use Queueable, SerializesModels;
+
+    protected $id; // 邮件记录ID
+    protected $title; // 邮件标题
+    protected $content; // 邮件内容
+
+    public function __construct($id, $title, $content)
+    {
+        $this->id = $id;
+        $this->title = $title;
+        $this->content = $content;
+    }
+
+    public function build()
+    {
+        return $this->view('emails.userTrafficAbnormalWarning')->subject('流量异常警告')->with([
+            'content' => $this->content
+        ]);
+    }
+
+    // 发件失败处理
+    public function failed(\Exception $e)
+    {
+        EmailLog::query()->where('id', $this->id)->update(['status' => -1, 'error' => $e->getMessage()]);
+    }
+}

+ 42 - 5
app/helpers.php

@@ -136,8 +136,8 @@ if (!function_exists('getClientIP')) {
                 $ip = $_SERVER['REMOTE_ADDR'];
             } elseif (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
                 $ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
-            } elseif (isset($_SERVER['HTTP_CLIENT_ip'])) {
-                $ip = $_SERVER['HTTP_CLIENT_ip'];
+            } elseif (isset($_SERVER['HTTP_CLIENT_IP'])) {
+                $ip = $_SERVER['HTTP_CLIENT_IP'];
             } elseif (isset($_SERVER['REMOTE_ADDR'])) {
                 $ip = $_SERVER['REMOTE_ADDR'];
             } else {
@@ -147,8 +147,8 @@ if (!function_exists('getClientIP')) {
             // 绕过CDN获取真实访客IP
             if (getenv('HTTP_X_FORWARDED_FOR')) {
                 $ip = getenv('HTTP_X_FORWARDED_FOR');
-            } elseif (getenv('HTTP_CLIENT_ip')) {
-                $ip = getenv('HTTP_CLIENT_ip');
+            } elseif (getenv('HTTP_CLIENT_IP')) {
+                $ip = getenv('HTTP_CLIENT_IP');
             } else {
                 $ip = getenv('REMOTE_ADDR');
             }
@@ -158,6 +158,15 @@ if (!function_exists('getClientIP')) {
             $ip = '127.0.0.1';
         }
 
+        // 多IP容错判断
+        if (false !== strpos($ip, ',')) {
+            \Log::info("检测到用户通过多级代理访问,请求IP串:" . $ip);
+
+            $ipArr = explode(',', $ip);
+
+            return $ipArr[0]; // 第一个是真实IP,后面都是代理IP
+        }
+
         return $ip;
     }
 }
@@ -262,4 +271,32 @@ if (!function_exists('isMobile')) {
 
         return preg_match('#^13[\d]{9}$|^14[5,7]{1}\d{8}$|^15[^4]{1}\d{8}$|^17[0,6,7,8]{1}\d{8}$|^18[\d]{9}$#', $mobile) ? true : false;
     }
-}
+}
+
+// 网速速率转换
+if (!function_exists('formatNetSpeed')) {
+    function formatNetSpeed($value)
+    {
+        if ($value < 0) {
+            return '';
+        }
+
+        if ($value == 0) {
+            return '不限速';
+        }
+
+        $kb = 1024;
+        $mb = 1024 * 1024;
+
+        if (abs($value) >= $mb) {
+            $speed = round($value / $mb, 2) * 8;
+            if (abs($speed / 1024) >= 1) {
+                return round($speed / 1024, 2) . "Gbps";
+            } else {
+                return $speed . "Mbps";
+            }
+        } else {
+            return round($value / $kb, 2) * 8 / 1024 . "Mbps";
+        }
+    }
+}

+ 108 - 2
ca/cacert.pem

@@ -1,7 +1,7 @@
 ##
 ## Bundle of CA Root Certificates
 ##
-## Certificate data from Mozilla as of: Wed Jan 23 04:12:09 2019 GMT
+## Certificate data from Mozilla as of: Wed May 15 03:12:09 2019 GMT
 ##
 ## This is a bundle of X.509 certificates of public Certificate Authorities
 ## (CA). These were automatically extracted from Mozilla's root certificates
@@ -14,7 +14,7 @@
 ## Just configure this file as the SSLCACertificateFile.
 ##
 ## Conversion done with mk-ca-bundle.pl version 1.27.
-## SHA256: 18372117493b5b7ec006c31d966143fc95a9464a2b5f8d5188e23c5557b2292d
+## SHA256: 61eaa79ac46d923f2f74dfe401189424e96fa8736102b47ba2cdb4ea19af2cc8
 ##
 
 
@@ -3399,3 +3399,109 @@ tlu3zM63Nwf9JtmYhST/WSMDmu2dnajkXjjO11INb9I/bbEFa0nOipFGc/T2L/Coc3cOZayhjWZS
 aX5LaAzHHjcng6WMxwLkFM1JAbBzs/3GkDpv0mztO+7skb6iQ12LAEpmJURw3kAP+HwV96LOPNde
 E4yBFxgX0b3xdxA61GU5wSesVywlVP+i2k+KYTlerj1KjL0=
 -----END CERTIFICATE-----
+
+emSign Root CA - G1
+===================
+-----BEGIN CERTIFICATE-----
+MIIDlDCCAnygAwIBAgIKMfXkYgxsWO3W2DANBgkqhkiG9w0BAQsFADBnMQswCQYDVQQGEwJJTjET
+MBEGA1UECxMKZW1TaWduIFBLSTElMCMGA1UEChMcZU11ZGhyYSBUZWNobm9sb2dpZXMgTGltaXRl
+ZDEcMBoGA1UEAxMTZW1TaWduIFJvb3QgQ0EgLSBHMTAeFw0xODAyMTgxODMwMDBaFw00MzAyMTgx
+ODMwMDBaMGcxCzAJBgNVBAYTAklOMRMwEQYDVQQLEwplbVNpZ24gUEtJMSUwIwYDVQQKExxlTXVk
+aHJhIFRlY2hub2xvZ2llcyBMaW1pdGVkMRwwGgYDVQQDExNlbVNpZ24gUm9vdCBDQSAtIEcxMIIB
+IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAk0u76WaK7p1b1TST0Bsew+eeuGQzf2N4aLTN
+LnF115sgxk0pvLZoYIr3IZpWNVrzdr3YzZr/k1ZLpVkGoZM0Kd0WNHVO8oG0x5ZOrRkVUkr+PHB1
+cM2vK6sVmjM8qrOLqs1D/fXqcP/tzxE7lM5OMhbTI0Aqd7OvPAEsbO2ZLIvZTmmYsvePQbAyeGHW
+DV/D+qJAkh1cF+ZwPjXnorfCYuKrpDhMtTk1b+oDafo6VGiFbdbyL0NVHpENDtjVaqSW0RM8LHhQ
+6DqS0hdW5TUaQBw+jSztOd9C4INBdN+jzcKGYEho42kLVACL5HZpIQ15TjQIXhTCzLG3rdd8cIrH
+hQIDAQABo0IwQDAdBgNVHQ4EFgQU++8Nhp6w492pufEhF38+/PB3KxowDgYDVR0PAQH/BAQDAgEG
+MA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAFn/8oz1h31xPaOfG1vR2vjTnGs2
+vZupYeveFix0PZ7mddrXuqe8QhfnPZHr5X3dPpzxz5KsbEjMwiI/aTvFthUvozXGaCocV685743Q
+NcMYDHsAVhzNixl03r4PEuDQqqE/AjSxcM6dGNYIAwlG7mDgfrbESQRRfXBgvKqy/3lyeqYdPV8q
++Mri/Tm3R7nrft8EI6/6nAYH6ftjk4BAtcZsCjEozgyfz7MjNYBBjWzEN3uBL4ChQEKF6dk4jeih
+U80Bv2noWgbyRQuQ+q7hv53yrlc8pa6yVvSLZUDp/TGBLPQ5Cdjua6e0ph0VpZj3AYHYhX3zUVxx
+iN66zB+Afko=
+-----END CERTIFICATE-----
+
+emSign ECC Root CA - G3
+=======================
+-----BEGIN CERTIFICATE-----
+MIICTjCCAdOgAwIBAgIKPPYHqWhwDtqLhDAKBggqhkjOPQQDAzBrMQswCQYDVQQGEwJJTjETMBEG
+A1UECxMKZW1TaWduIFBLSTElMCMGA1UEChMcZU11ZGhyYSBUZWNobm9sb2dpZXMgTGltaXRlZDEg
+MB4GA1UEAxMXZW1TaWduIEVDQyBSb290IENBIC0gRzMwHhcNMTgwMjE4MTgzMDAwWhcNNDMwMjE4
+MTgzMDAwWjBrMQswCQYDVQQGEwJJTjETMBEGA1UECxMKZW1TaWduIFBLSTElMCMGA1UEChMcZU11
+ZGhyYSBUZWNobm9sb2dpZXMgTGltaXRlZDEgMB4GA1UEAxMXZW1TaWduIEVDQyBSb290IENBIC0g
+RzMwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQjpQy4LRL1KPOxst3iAhKAnjlfSU2fySU0WXTsuwYc
+58Byr+iuL+FBVIcUqEqy6HyC5ltqtdyzdc6LBtCGI79G1Y4PPwT01xySfvalY8L1X44uT6EYGQIr
+MgqCZH0Wk9GjQjBAMB0GA1UdDgQWBBR8XQKEE9TMipuBzhccLikenEhjQjAOBgNVHQ8BAf8EBAMC
+AQYwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAwNpADBmAjEAvvNhzwIQHWSVB7gYboiFBS+D
+CBeQyh+KTOgNG3qxrdWBCUfvO6wIBHxcmbHtRwfSAjEAnbpV/KlK6O3t5nYBQnvI+GDZjVGLVTv7
+jHvrZQnD+JbNR6iC8hZVdyR+EhCVBCyj
+-----END CERTIFICATE-----
+
+emSign Root CA - C1
+===================
+-----BEGIN CERTIFICATE-----
+MIIDczCCAlugAwIBAgILAK7PALrEzzL4Q7IwDQYJKoZIhvcNAQELBQAwVjELMAkGA1UEBhMCVVMx
+EzARBgNVBAsTCmVtU2lnbiBQS0kxFDASBgNVBAoTC2VNdWRocmEgSW5jMRwwGgYDVQQDExNlbVNp
+Z24gUm9vdCBDQSAtIEMxMB4XDTE4MDIxODE4MzAwMFoXDTQzMDIxODE4MzAwMFowVjELMAkGA1UE
+BhMCVVMxEzARBgNVBAsTCmVtU2lnbiBQS0kxFDASBgNVBAoTC2VNdWRocmEgSW5jMRwwGgYDVQQD
+ExNlbVNpZ24gUm9vdCBDQSAtIEMxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAz+up
+ufGZBczYKCFK83M0UYRWEPWgTywS4/oTmifQz/l5GnRfHXk5/Fv4cI7gklL35CX5VIPZHdPIWoU/
+Xse2B+4+wM6ar6xWQio5JXDWv7V7Nq2s9nPczdcdioOl+yuQFTdrHCZH3DspVpNqs8FqOp099cGX
+OFgFixwR4+S0uF2FHYP+eF8LRWgYSKVGczQ7/g/IdrvHGPMF0Ybzhe3nudkyrVWIzqa2kbBPrH4V
+I5b2P/AgNBbeCsbEBEV5f6f9vtKppa+cxSMq9zwhbL2vj07FOrLzNBL834AaSaTUqZX3noleooms
+lMuoaJuvimUnzYnu3Yy1aylwQ6BpC+S5DwIDAQABo0IwQDAdBgNVHQ4EFgQU/qHgcB4qAzlSWkK+
+XJGFehiqTbUwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQAD
+ggEBAMJKVvoVIXsoounlHfv4LcQ5lkFMOycsxGwYFYDGrK9HWS8mC+M2sO87/kOXSTKZEhVb3xEp
+/6tT+LvBeA+snFOvV71ojD1pM/CjoCNjO2RnIkSt1XHLVip4kqNPEjE2NuLe/gDEo2APJ62gsIq1
+NnpSob0n9CAnYuhNlCQT5AoE6TyrLshDCUrGYQTlSTR+08TI9Q/Aqum6VF7zYytPT1DU/rl7mYw9
+wC68AivTxEDkigcxHpvOJpkT+xHqmiIMERnHXhuBUDDIlhJu58tBf5E7oke3VIAb3ADMmpDqw8NQ
+BmIMMMAVSKeoWXzhriKi4gp6D/piq1JM4fHfyr6DDUI=
+-----END CERTIFICATE-----
+
+emSign ECC Root CA - C3
+=======================
+-----BEGIN CERTIFICATE-----
+MIICKzCCAbGgAwIBAgIKe3G2gla4EnycqDAKBggqhkjOPQQDAzBaMQswCQYDVQQGEwJVUzETMBEG
+A1UECxMKZW1TaWduIFBLSTEUMBIGA1UEChMLZU11ZGhyYSBJbmMxIDAeBgNVBAMTF2VtU2lnbiBF
+Q0MgUm9vdCBDQSAtIEMzMB4XDTE4MDIxODE4MzAwMFoXDTQzMDIxODE4MzAwMFowWjELMAkGA1UE
+BhMCVVMxEzARBgNVBAsTCmVtU2lnbiBQS0kxFDASBgNVBAoTC2VNdWRocmEgSW5jMSAwHgYDVQQD
+ExdlbVNpZ24gRUNDIFJvb3QgQ0EgLSBDMzB2MBAGByqGSM49AgEGBSuBBAAiA2IABP2lYa57JhAd
+6bciMK4G9IGzsUJxlTm801Ljr6/58pc1kjZGDoeVjbk5Wum739D+yAdBPLtVb4OjavtisIGJAnB9
+SMVK4+kiVCJNk7tCDK93nCOmfddhEc5lx/h//vXyqaNCMEAwHQYDVR0OBBYEFPtaSNCAIEDyqOkA
+B2kZd6fmw/TPMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MAoGCCqGSM49BAMDA2gA
+MGUCMQC02C8Cif22TGK6Q04ThHK1rt0c3ta13FaPWEBaLd4gTCKDypOofu4SQMfWh0/434UCMBwU
+ZOR8loMRnLDRWmFLpg9J0wD8ofzkpf9/rdcw0Md3f76BB1UwUCAU9Vc4CqgxUQ==
+-----END CERTIFICATE-----
+
+Hongkong Post Root CA 3
+=======================
+-----BEGIN CERTIFICATE-----
+MIIFzzCCA7egAwIBAgIUCBZfikyl7ADJk0DfxMauI7gcWqQwDQYJKoZIhvcNAQELBQAwbzELMAkG
+A1UEBhMCSEsxEjAQBgNVBAgTCUhvbmcgS29uZzESMBAGA1UEBxMJSG9uZyBLb25nMRYwFAYDVQQK
+Ew1Ib25na29uZyBQb3N0MSAwHgYDVQQDExdIb25na29uZyBQb3N0IFJvb3QgQ0EgMzAeFw0xNzA2
+MDMwMjI5NDZaFw00MjA2MDMwMjI5NDZaMG8xCzAJBgNVBAYTAkhLMRIwEAYDVQQIEwlIb25nIEtv
+bmcxEjAQBgNVBAcTCUhvbmcgS29uZzEWMBQGA1UEChMNSG9uZ2tvbmcgUG9zdDEgMB4GA1UEAxMX
+SG9uZ2tvbmcgUG9zdCBSb290IENBIDMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCz
+iNfqzg8gTr7m1gNt7ln8wlffKWihgw4+aMdoWJwcYEuJQwy51BWy7sFOdem1p+/l6TWZ5Mwc50tf
+jTMwIDNT2aa71T4Tjukfh0mtUC1Qyhi+AViiE3CWu4mIVoBc+L0sPOFMV4i707mV78vH9toxdCim
+5lSJ9UExyuUmGs2C4HDaOym71QP1mbpV9WTRYA6ziUm4ii8F0oRFKHyPaFASePwLtVPLwpgchKOe
+sL4jpNrcyCse2m5FHomY2vkALgbpDDtw1VAliJnLzXNg99X/NWfFobxeq81KuEXryGgeDQ0URhLj
+0mRiikKYvLTGCAj4/ahMZJx2Ab0vqWwzD9g/KLg8aQFChn5pwckGyuV6RmXpwtZQQS4/t+TtbNe/
+JgERohYpSms0BpDsE9K2+2p20jzt8NYt3eEV7KObLyzJPivkaTv/ciWxNoZbx39ri1UbSsUgYT2u
+y1DhCDq+sI9jQVMwCFk8mB13umOResoQUGC/8Ne8lYePl8X+l2oBlKN8W4UdKjk60FSh0Tlxnf0h
++bV78OLgAo9uliQlLKAeLKjEiafv7ZkGL7YKTE/bosw3Gq9HhS2KX8Q0NEwA/RiTZxPRN+ZItIsG
+xVd7GYYKecsAyVKvQv83j+GjHno9UKtjBucVtT+2RTeUN7F+8kjDf8V1/peNRY8apxpyKBpADwID
+AQABo2MwYTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAfBgNVHSMEGDAWgBQXnc0e
+i9Y5K3DTXNSguB+wAPzFYTAdBgNVHQ4EFgQUF53NHovWOStw01zUoLgfsAD8xWEwDQYJKoZIhvcN
+AQELBQADggIBAFbVe27mIgHSQpsY1Q7XZiNc4/6gx5LS6ZStS6LG7BJ8dNVI0lkUmcDrudHr9Egw
+W62nV3OZqdPlt9EuWSRY3GguLmLYauRwCy0gUCCkMpXRAJi70/33MvJJrsZ64Ee+bs7Lo3I6LWld
+y8joRTnU+kLBEUx3XZL7av9YROXrgZ6voJmtvqkBZss4HTzfQx/0TW60uhdG/H39h4F5ag0zD/ov
++BS5gLNdTaqX4fnkGMX41TiMJjz98iji7lpJiCzfeT2OnpA8vUFKOt1b9pq0zj8lMH8yfaIDlNDc
+eqFS3m6TjRgm/VWsvY+b0s+v54Ysyx8Jb6NvqYTUc79NoXQbTiNg8swOqn+knEwlqLJmOzj/2ZQw
+9nKEvmhVEA/GcywWaZMH/rFF7buiVWqw2rVKAiUnhde3t4ZEFolsgCs+l6mc1X5VTMbeRRAc6uk7
+nwNT7u56AQIWeNTowr5GdogTPyK7SBIdUgC0An4hGh6cJfTzPV4e0hz5sy229zdcxsshTrD3mUcY
+hcErulWuBurQB7Lcq9CClnXO0lD+mefPL5/ndtFhKvshuzHQqp9HpLIiyhY6UFfEW0NnxWViA0kB
+60PZ2Pierc+xYw5F9KBaLJstxabArahH9CdMOA0uG0k7UvToiIMrVCjU8jVStDKDYmlkDJGcn5fq
+dBb9HxEGmpv0
+-----END CERTIFICATE-----

+ 9 - 5
config/app.php

@@ -146,14 +146,16 @@ return [
         // Illuminate\Translation\TranslationServiceProvider::class, // 弃用自带多国语言包功能
         Illuminate\Validation\ValidationServiceProvider::class,
         Illuminate\View\ViewServiceProvider::class,
-        
-        
+
+
         /*
         * Package Service Providers...
         */
-        Misechow\Geetest\GeetestServiceProvider::class,  // Geetest Service
-        Misechow\NoCaptcha\NoCaptchaServiceProvider::class, // Google reCAPTCHA Service
+        Misechow\Geetest\GeetestServiceProvider::class,  // Geetest极验
+        Misechow\NoCaptcha\NoCaptchaServiceProvider::class, // Google reCAPTCHA
         Overtrue\LaravelLang\TranslationServiceProvider::class, // 多国语言包功能
+        Tymon\JWTAuth\Providers\LaravelServiceProvider::class, // jwt auth
+        Telegram\Bot\Laravel\TelegramServiceProvider::class, // Telegram Bot
 
         /*
          * Application Service Providers...
@@ -215,7 +217,9 @@ return [
         'Agent'        => Jenssegers\Agent\Facades\Agent::class,
         'Purifier'     => Mews\Purifier\Facades\Purifier::class,
         'Geetest'      => Misechow\Geetest\Geetest::class,
-        'NoCaptcha' => Misechow\NoCaptcha\Facades\NoCaptcha::class,
+        'NoCaptcha'    => Misechow\NoCaptcha\Facades\NoCaptcha::class,
+        'JWTAuth'      => Tymon\JWTAuth\Facades\JWTAuth::class,
+        'Telegram'     => Telegram\Bot\Laravel\Facades\Telegram::class
     ],
 
 ];

+ 1 - 1
config/auth.php

@@ -42,7 +42,7 @@ return [
         ],
 
         'api' => [
-            'driver' => 'token',
+            'driver' => 'jwt',
             'provider' => 'users',
         ],
     ],

+ 8 - 0
config/bt.php

@@ -0,0 +1,8 @@
+<?php
+
+// 宝塔API action
+return [
+    'getSystemTotal' => '/system?action=GetSystemTotal',
+    'getDiskInfo'    => '/system?action=GetDiskInfo',
+    'getNetWork'     => '/system?action=GetNetWork',
+];

+ 16 - 0
config/common.php

@@ -0,0 +1,16 @@
+<?php
+
+return [
+    'level_map' => [ // 等级映射表
+        0 => '免费',
+        1 => 'VIP1',
+        2 => 'VIP2',
+        3 => 'VIP3',
+        4 => 'VIP4',
+        5 => 'VIP5',
+        6 => 'VIP6',
+        7 => 'VIP7',
+        8 => 'VIP8',
+        9 => 'VIP9'
+    ],
+];

+ 1 - 1
config/geetest.php

@@ -21,7 +21,7 @@ return [
 	| Here you can decision whether to get the geetest key from database or not.
 	|
 	*/
-	'server-get-config' => TRUE,
+	'server-get-config' => true,
 
 	/*
 	|--------------------------------------------------------------------------

+ 0 - 32
config/hashing.php

@@ -17,36 +17,4 @@ return [
 
     'driver' => 'bcrypt',
 
-    /*
-    |--------------------------------------------------------------------------
-    | Bcrypt Options
-    |--------------------------------------------------------------------------
-    |
-    | Here you may specify the configuration options that should be used when
-    | passwords are hashed using the Bcrypt algorithm. This will allow you
-    | to control the amount of time it takes to hash the given password.
-    |
-    */
-
-    'bcrypt' => [
-        'rounds' => env('BCRYPT_ROUNDS', 10),
-    ],
-
-    /*
-    |--------------------------------------------------------------------------
-    | Argon Options
-    |--------------------------------------------------------------------------
-    |
-    | Here you may specify the configuration options that should be used when
-    | passwords are hashed using the Argon algorithm. These will allow you
-    | to control the amount of time it takes to hash the given password.
-    |
-    */
-
-    'argon' => [
-        'memory' => 1024,
-        'threads' => 2,
-        'time' => 2,
-    ],
-
 ];

+ 304 - 0
config/jwt.php

@@ -0,0 +1,304 @@
+<?php
+
+/*
+ * This file is part of jwt-auth.
+ *
+ * (c) Sean Tymon <[email protected]>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+return [
+
+    /*
+    |--------------------------------------------------------------------------
+    | JWT Authentication Secret
+    |--------------------------------------------------------------------------
+    |
+    | Don't forget to set this in your .env file, as it will be used to sign
+    | your tokens. A helper command is provided for this:
+    | `php artisan jwt:secret`
+    |
+    | Note: This will be used for Symmetric algorithms only (HMAC),
+    | since RSA and ECDSA use a private/public key combo (See below).
+    |
+    */
+
+    'secret' => env('JWT_SECRET'),
+
+    /*
+    |--------------------------------------------------------------------------
+    | JWT Authentication Keys
+    |--------------------------------------------------------------------------
+    |
+    | The algorithm you are using, will determine whether your tokens are
+    | signed with a random string (defined in `JWT_SECRET`) or using the
+    | following public & private keys.
+    |
+    | Symmetric Algorithms:
+    | HS256, HS384 & HS512 will use `JWT_SECRET`.
+    |
+    | Asymmetric Algorithms:
+    | RS256, RS384 & RS512 / ES256, ES384 & ES512 will use the keys below.
+    |
+    */
+
+    'keys' => [
+
+        /*
+        |--------------------------------------------------------------------------
+        | Public Key
+        |--------------------------------------------------------------------------
+        |
+        | A path or resource to your public key.
+        |
+        | E.g. 'file://path/to/public/key'
+        |
+        */
+
+        'public' => env('JWT_PUBLIC_KEY'),
+
+        /*
+        |--------------------------------------------------------------------------
+        | Private Key
+        |--------------------------------------------------------------------------
+        |
+        | A path or resource to your private key.
+        |
+        | E.g. 'file://path/to/private/key'
+        |
+        */
+
+        'private' => env('JWT_PRIVATE_KEY'),
+
+        /*
+        |--------------------------------------------------------------------------
+        | Passphrase
+        |--------------------------------------------------------------------------
+        |
+        | The passphrase for your private key. Can be null if none set.
+        |
+        */
+
+        'passphrase' => env('JWT_PASSPHRASE'),
+
+    ],
+
+    /*
+    |--------------------------------------------------------------------------
+    | JWT time to live
+    |--------------------------------------------------------------------------
+    |
+    | Specify the length of time (in minutes) that the token will be valid for.
+    | Defaults to 1 hour.
+    |
+    | You can also set this to null, to yield a never expiring token.
+    | Some people may want this behaviour for e.g. a mobile app.
+    | This is not particularly recommended, so make sure you have appropriate
+    | systems in place to revoke the token if necessary.
+    | Notice: If you set this to null you should remove 'exp' element from 'required_claims' list.
+    |
+    */
+
+    'ttl' => env('JWT_TTL', 60),
+
+    /*
+    |--------------------------------------------------------------------------
+    | Refresh time to live
+    |--------------------------------------------------------------------------
+    |
+    | Specify the length of time (in minutes) that the token can be refreshed
+    | within. I.E. The user can refresh their token within a 2 week window of
+    | the original token being created until they must re-authenticate.
+    | Defaults to 2 weeks.
+    |
+    | You can also set this to null, to yield an infinite refresh time.
+    | Some may want this instead of never expiring tokens for e.g. a mobile app.
+    | This is not particularly recommended, so make sure you have appropriate
+    | systems in place to revoke the token if necessary.
+    |
+    */
+
+    'refresh_ttl' => env('JWT_REFRESH_TTL', 20160),
+
+    /*
+    |--------------------------------------------------------------------------
+    | JWT hashing algorithm
+    |--------------------------------------------------------------------------
+    |
+    | Specify the hashing algorithm that will be used to sign the token.
+    |
+    | See here: https://github.com/namshi/jose/tree/master/src/Namshi/JOSE/Signer/OpenSSL
+    | for possible values.
+    |
+    */
+
+    'algo' => env('JWT_ALGO', 'HS256'),
+
+    /*
+    |--------------------------------------------------------------------------
+    | Required Claims
+    |--------------------------------------------------------------------------
+    |
+    | Specify the required claims that must exist in any token.
+    | A TokenInvalidException will be thrown if any of these claims are not
+    | present in the payload.
+    |
+    */
+
+    'required_claims' => [
+        'iss',
+        'iat',
+        'exp',
+        'nbf',
+        'sub',
+        'jti',
+    ],
+
+    /*
+    |--------------------------------------------------------------------------
+    | Persistent Claims
+    |--------------------------------------------------------------------------
+    |
+    | Specify the claim keys to be persisted when refreshing a token.
+    | `sub` and `iat` will automatically be persisted, in
+    | addition to the these claims.
+    |
+    | Note: If a claim does not exist then it will be ignored.
+    |
+    */
+
+    'persistent_claims' => [
+        // 'foo',
+        // 'bar',
+    ],
+
+    /*
+    |--------------------------------------------------------------------------
+    | Lock Subject
+    |--------------------------------------------------------------------------
+    |
+    | This will determine whether a `prv` claim is automatically added to
+    | the token. The purpose of this is to ensure that if you have multiple
+    | authentication models e.g. `App\User` & `App\OtherPerson`, then we
+    | should prevent one authentication request from impersonating another,
+    | if 2 tokens happen to have the same id across the 2 different models.
+    |
+    | Under specific circumstances, you may want to disable this behaviour
+    | e.g. if you only have one authentication model, then you would save
+    | a little on token size.
+    |
+    */
+
+    'lock_subject' => true,
+
+    /*
+    |--------------------------------------------------------------------------
+    | Leeway
+    |--------------------------------------------------------------------------
+    |
+    | This property gives the jwt timestamp claims some "leeway".
+    | Meaning that if you have any unavoidable slight clock skew on
+    | any of your servers then this will afford you some level of cushioning.
+    |
+    | This applies to the claims `iat`, `nbf` and `exp`.
+    |
+    | Specify in seconds - only if you know you need it.
+    |
+    */
+
+    'leeway' => env('JWT_LEEWAY', 0),
+
+    /*
+    |--------------------------------------------------------------------------
+    | Blacklist Enabled
+    |--------------------------------------------------------------------------
+    |
+    | In order to invalidate tokens, you must have the blacklist enabled.
+    | If you do not want or need this functionality, then set this to false.
+    |
+    */
+
+    'blacklist_enabled' => env('JWT_BLACKLIST_ENABLED', true),
+
+    /*
+    | -------------------------------------------------------------------------
+    | Blacklist Grace Period
+    | -------------------------------------------------------------------------
+    |
+    | When multiple concurrent requests are made with the same JWT,
+    | it is possible that some of them fail, due to token regeneration
+    | on every request.
+    |
+    | Set grace period in seconds to prevent parallel request failure.
+    |
+    */
+
+    'blacklist_grace_period' => env('JWT_BLACKLIST_GRACE_PERIOD', 0),
+
+    /*
+    |--------------------------------------------------------------------------
+    | Cookies encryption
+    |--------------------------------------------------------------------------
+    |
+    | By default Laravel encrypt cookies for security reason.
+    | If you decide to not decrypt cookies, you will have to configure Laravel
+    | to not encrypt your cookie token by adding its name into the $except
+    | array available in the middleware "EncryptCookies" provided by Laravel.
+    | see https://laravel.com/docs/master/responses#cookies-and-encryption
+    | for details.
+    |
+    | Set it to true if you want to decrypt cookies.
+    |
+    */
+
+    'decrypt_cookies' => false,
+
+    /*
+    |--------------------------------------------------------------------------
+    | Providers
+    |--------------------------------------------------------------------------
+    |
+    | Specify the various providers used throughout the package.
+    |
+    */
+
+    'providers' => [
+
+        /*
+        |--------------------------------------------------------------------------
+        | JWT Provider
+        |--------------------------------------------------------------------------
+        |
+        | Specify the provider that is used to create and decode the tokens.
+        |
+        */
+
+        'jwt' => Tymon\JWTAuth\Providers\JWT\Lcobucci::class,
+
+        /*
+        |--------------------------------------------------------------------------
+        | Authentication Provider
+        |--------------------------------------------------------------------------
+        |
+        | Specify the provider that is used to authenticate users.
+        |
+        */
+
+        'auth' => Tymon\JWTAuth\Providers\Auth\Illuminate::class,
+
+        /*
+        |--------------------------------------------------------------------------
+        | Storage Provider
+        |--------------------------------------------------------------------------
+        |
+        | Specify the provider that is used to store tokens in the blacklist.
+        |
+        */
+
+        'storage' => Tymon\JWTAuth\Providers\Storage\Illuminate::class,
+
+    ],
+
+];

+ 2 - 13
config/logging.php

@@ -1,7 +1,5 @@
 <?php
 
-use Monolog\Handler\StreamHandler;
-
 return [
 
     /*
@@ -27,8 +25,7 @@ return [
     | you a variety of powerful log handlers / formatters to utilize.
     |
     | Available Drivers: "single", "daily", "slack", "syslog",
-    |                    "errorlog", "monolog",
-    |                    "custom", "stack"
+    |                    "errorlog", "custom", "stack"
     |
     */
 
@@ -48,7 +45,7 @@ return [
             'driver' => 'daily',
             'path' => storage_path('logs/laravel.log'),
             'level' => 'debug',
-            'days' => 30,
+            'days' => 7,
         ],
 
         'slack' => [
@@ -59,14 +56,6 @@ return [
             'level' => 'critical',
         ],
 
-        'stderr' => [
-            'driver' => 'monolog',
-            'handler' => StreamHandler::class,
-            'with' => [
-                'stream' => 'php://stderr',
-            ],
-        ],
-
         'syslog' => [
             'driver' => 'syslog',
             'level' => 'debug',

+ 1 - 1
config/services.php

@@ -22,7 +22,7 @@ return [
     'ses' => [
         'key' => env('SES_KEY'),
         'secret' => env('SES_SECRET'),
-        'region' => env('SES_REGION', 'us-east-1'),
+        'region' => 'us-east-1',
     ],
 
     'sparkpost' => [

+ 27 - 0
config/sms.php

@@ -0,0 +1,27 @@
+<?php
+
+return [
+    // HTTP 请求的超时时间(秒)
+    'timeout'  => 5.0,
+
+    // 默认发送配置
+    'default'  => [
+        // 网关调用策略,默认:顺序调用
+        'strategy' => \Overtrue\EasySms\Strategies\OrderStrategy::class,
+
+        // 默认可用的发送网关
+        'gateways' => [
+            'yunpian',
+        ],
+    ],
+
+    // 可用的网关配置
+    'gateways' => [
+        'errorlog' => [
+            'file' => '/tmp/easy-sms.log',
+        ],
+        'yunpian'  => [
+            'api_key' => '0c9c87c41aac355520d47d3c84e5a532',
+        ],
+    ],
+];

+ 204 - 0
config/telegram.php

@@ -0,0 +1,204 @@
+<?php
+
+return [
+    /*
+    |--------------------------------------------------------------------------
+    | Your Telegram Bots
+    |--------------------------------------------------------------------------
+    | You may use multiple bots at once using the manager class. Each bot
+    | that you own should be configured here.
+    |
+    | Here are each of the telegram bots config parameters.
+    |
+    | Supported Params:
+    |
+    | - name: The *personal* name you would like to refer to your bot as.
+    |
+    |       - username: Your Telegram Bot's Username.
+    |                       Example: (string) 'BotFather'.
+    |
+    |       - token:    Your Telegram Bot's Access Token.
+                        Refer for more details: https://core.telegram.org/bots#botfather
+    |                   Example: (string) '123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11'.
+    |
+    |       - commands: (Optional) Commands to register for this bot,
+    |                   Supported Values: "Command Group Name", "Shared Command Name", "Full Path to Class".
+    |                   Default: Registers Global Commands.
+    |                   Example: (array) [
+    |                       'admin', // Command Group Name.
+    |                       'status', // Shared Command Name.
+    |                       Acme\Project\Commands\BotFather\HelloCommand::class,
+    |                       Acme\Project\Commands\BotFather\ByeCommand::class,
+    |             ]
+    */
+    'bots'                         => [
+        'mybot' => [
+            'username'         => 'TelegramBot',
+            'token'            => env('TELEGRAM_BOT_TOKEN', 'YOUR-BOT-TOKEN'),
+            'certificate_path' => env('TELEGRAM_CERTIFICATE_PATH', 'YOUR-CERTIFICATE-PATH'),
+            'webhook_url'      => env('TELEGRAM_WEBHOOK_URL', 'YOUR-BOT-WEBHOOK-URL'),
+            'commands'         => [
+                //Acme\Project\Commands\MyTelegramBot\BotCommand::class
+            ],
+        ],
+
+//        'mySecondBot' => [
+//            'username'  => 'AnotherTelegram_Bot',
+//            'token' => '123456:abc',
+//        ],
+    ],
+
+    /*
+    |--------------------------------------------------------------------------
+    | Default Bot Name
+    |--------------------------------------------------------------------------
+    |
+    | Here you may specify which of the bots you wish to use as
+    | your default bot for regular use.
+    |
+    */
+    'default'                      => 'mybot',
+
+    /*
+    |--------------------------------------------------------------------------
+    | Asynchronous Requests [Optional]
+    |--------------------------------------------------------------------------
+    |
+    | When set to True, All the requests would be made non-blocking (Async).
+    |
+    | Default: false
+    | Possible Values: (Boolean) "true" OR "false"
+    |
+    */
+    'async_requests'               => env('TELEGRAM_ASYNC_REQUESTS', false),
+
+    /*
+    |--------------------------------------------------------------------------
+    | HTTP Client Handler [Optional]
+    |--------------------------------------------------------------------------
+    |
+    | If you'd like to use a custom HTTP Client Handler.
+    | Should be an instance of \Telegram\Bot\HttpClients\HttpClientInterface
+    |
+    | Default: GuzzlePHP
+    |
+    */
+    'http_client_handler'          => null,
+
+    /*
+    |--------------------------------------------------------------------------
+    | Resolve Injected Dependencies in commands [Optional]
+    |--------------------------------------------------------------------------
+    |
+    | Using Laravel's IoC container, we can easily type hint dependencies in
+    | our command's constructor and have them automatically resolved for us.
+    |
+    | Default: true
+    | Possible Values: (Boolean) "true" OR "false"
+    |
+    */
+    'resolve_command_dependencies' => true,
+
+    /*
+    |--------------------------------------------------------------------------
+    | Register Telegram Global Commands [Optional]
+    |--------------------------------------------------------------------------
+    |
+    | If you'd like to use the SDK's built in command handler system,
+    | You can register all the global commands here.
+    |
+    | Global commands will apply to all the bots in system and are always active.
+    |
+    | The command class should extend the \Telegram\Bot\Commands\Command class.
+    |
+    | Default: The SDK registers, a help command which when a user sends /help
+    | will respond with a list of available commands and description.
+    |
+    */
+    'commands'                     => [
+        Telegram\Bot\Commands\HelpCommand::class,
+    ],
+
+    /*
+    |--------------------------------------------------------------------------
+    | Command Groups [Optional]
+    |--------------------------------------------------------------------------
+    |
+    | You can organize a set of commands into groups which can later,
+    | be re-used across all your bots.
+    |
+    | You can create 4 types of groups:
+    | 1. Group using full path to command classes.
+    | 2. Group using shared commands: Provide the key name of the shared command
+    | and the system will automatically resolve to the appropriate command.
+    | 3. Group using other groups of commands: You can create a group which uses other
+    | groups of commands to bundle them into one group.
+    | 4. You can create a group with a combination of 1, 2 and 3 all together in one group.
+    |
+    | Examples shown below are by the group type for you to understand each of them.
+    */
+    'command_groups'               => [
+        /* // Group Type: 1
+           'commmon' => [
+                Acme\Project\Commands\TodoCommand::class,
+                Acme\Project\Commands\TaskCommand::class,
+           ],
+        */
+
+        /* // Group Type: 2
+           'subscription' => [
+                'start', // Shared Command Name.
+                'stop', // Shared Command Name.
+           ],
+        */
+
+        /* // Group Type: 3
+            'auth' => [
+                Acme\Project\Commands\LoginCommand::class,
+                Acme\Project\Commands\SomeCommand::class,
+            ],
+
+            'stats' => [
+                Acme\Project\Commands\UserStatsCommand::class,
+                Acme\Project\Commands\SubscriberStatsCommand::class,
+                Acme\Project\Commands\ReportsCommand::class,
+            ],
+
+            'admin' => [
+                'auth', // Command Group Name.
+                'stats' // Command Group Name.
+            ],
+        */
+
+        /* // Group Type: 4
+           'myBot' => [
+                'admin', // Command Group Name.
+                'subscription', // Command Group Name.
+                'status', // Shared Command Name.
+                'Acme\Project\Commands\BotCommand' // Full Path to Command Class.
+           ],
+        */
+    ],
+
+    /*
+    |--------------------------------------------------------------------------
+    | Shared Commands [Optional]
+    |--------------------------------------------------------------------------
+    |
+    | Shared commands let you register commands that can be shared between,
+    | one or more bots across the project.
+    |
+    | This will help you prevent from having to register same set of commands,
+    | for each bot over and over again and make it easier to maintain them.
+    |
+    | Shared commands are not active by default, You need to use the key name to register them,
+    | individually in a group of commands or in bot commands.
+    | Think of this as a central storage, to register, reuse and maintain them across all bots.
+    |
+    */
+    'shared_commands'              => [
+        // 'start' => Acme\Project\Commands\StartCommand::class,
+        // 'stop' => Acme\Project\Commands\StopCommand::class,
+        // 'status' => Acme\Project\Commands\StatusCommand::class,
+    ],
+];

+ 1 - 1
config/version.php

@@ -1,6 +1,6 @@
 <?php
 
 return [
-    'number' => '450',
+    'number' => '500',
     'name'   => 'Standard'
 ];

+ 6 - 2
public/install.php

@@ -27,6 +27,7 @@ function is_really_writable($file)
     if (DIRECTORY_SEPARATOR == '/' and @ ini_get("safe_mode") == false) {
         return is_writable($file);
     }
+
     if (!is_file($file) or ($fp = @fopen($file, "r+")) === false) {
         return false;
     }
@@ -120,6 +121,7 @@ if (is_file($lockFile)) {
             $errInfo = '当前服务器因配置了open_basedir,导致无法读取应用根目录';
         }
     }
+
     if (!$errInfo) {
         $errInfo = '权限不足,无法写入配置文件.env';
     }
@@ -178,6 +180,7 @@ if (isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] == 'POST') {
         if (!$sql) {
             throw new Exception("无法读取所需的sql/db.sql,请检查是否有读权限");
         }
+
         $pdo = new PDO("mysql:host={$DB_HOST};port={$DB_PORT}", $DB_USERNAME, $DB_PASSWORD, [
             PDO::ATTR_ERRMODE            => PDO::ERRMODE_EXCEPTION,
             PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8"
@@ -191,20 +194,20 @@ if (isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] == 'POST') {
         }
 
         $pdo->query("CREATE DATABASE IF NOT EXISTS `{$DB_DATABASE}` CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;");
-
         $pdo->query("USE `{$DB_DATABASE}`");
-
         $pdo->exec($sql);
 
         $config = @file_get_contents($exampleConfigFile);
         if (!$config) {
             throw new Exception("无法写入读取配置.env.example文件,请检查是否有读权限");
         }
+
         $callback = function ($matches) use ($APP_KEY, $DB_HOST, $DB_PORT, $DB_USERNAME, $DB_PASSWORD, $DB_DATABASE) {
             $field = $matches[1];
             $replace = ${"{$field}"};
             return "{$matches[1]}={$replace}" . PHP_EOL;
         };
+
         $config = preg_replace_callback("/(APP_KEY|DB_HOST|DB_DATABASE|DB_USERNAME|DB_PASSWORD|DB_PORT)=(.*)(\s+)/", $callback, $config);
 
         // 检测能否成功写入数据库配置
@@ -219,6 +222,7 @@ if (isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] == 'POST') {
     } catch (Exception $e) {
         $err = $e->getMessage();
     }
+
     echo $err;
     exit;
 }

BIN
public/ipip.ipdb


BIN
public/qqwry.dat


+ 7 - 0
readme.md

@@ -6,6 +6,13 @@ Support but not limited to: Shadowsocks,ShadowsocksR,ShadowsocksRR,V2Ray
 - [Issues](https://github.com/ssrpanel/SSRPanel/issues)
 - [WIKI](https://github.com/ssrpanel/SSRPanel/wiki)
 
+
+**WARNING : This version only fixes BUG and no new features are added.**
+
+Star Number of Projects as of May 13, 2019 (Project was set to private)
+![stars](https://i.loli.net/2019/08/05/t7NsEWFQ3crZMYj.png)
+
+
 ## Donate
 **ETH** : 0x968f797f194fcec05ea571723199748b58de38ba
 

+ 3 - 1
resources/lang/en/home.php

@@ -14,6 +14,7 @@ return [
 
     // 菜单
     'home'                            => 'Home',
+    'my_service'                      => 'My Services',
     'services'                        => 'Services',
     'traffic_log'                     => 'Monitor',
     'help'                            => 'Help',
@@ -23,6 +24,7 @@ return [
     'referrals'                       => 'Referrals',
     'free_invite_codes_title'         => 'Free Invite Codes',
     'no_need_invite_codes'            => 'In the open registration system, no invitation code is required',
+    'no_notice'                       => 'No Notice',
 
     // 首页
     'ratio_tips'                      => 'Recommends the use of support node subscription function of the client, through subscription function can quickly synchronize node information in the client.',
@@ -132,7 +134,7 @@ return [
     'invoice_table_pay_way'           => 'Pay Method',
     'invoice_table_price'             => 'Amount',
     'invoice_table_create_date'       => 'Created On',
-    'invoice_table_expire_at' 	      => 'Expire Time',
+    'invoice_table_expire_at'         => 'Expire Time',
     'invoice_table_status'            => 'Status',
     'invoice_table_none'              => 'None Data',
     'invoice_table_closed'            => 'Closed',

+ 3 - 0
resources/lang/ja/home.php

@@ -14,6 +14,7 @@ return [
 
     // 菜单
     'home'                            => 'パーソナルセンター',
+    'my_service'                      => '私のサービス',
     'services'                        => 'ショップ',
     'traffic_log'                     => '使用記録',
     'help'                            => '手伝いをする',
@@ -23,6 +24,8 @@ return [
     'referrals'                       => '招待リンク',
     'free_invite_codes_title'         => '無料招待コード',
     'no_need_invite_codes'            => 'プラットフォームオープン登録、招待コードなし',
+    'check_in'                        => '署名する',
+    'no_notice'                       => 'しばらく公告がない',
 
     // 首页
     'ratio_tips'                      => 'ノードの購読機能をサポートするクライアントを使用することをお勧めします。',

+ 3 - 0
resources/lang/ko/home.php

@@ -14,6 +14,7 @@ return [
 
     // 菜单
     'home'                            => '개인 센터',
+    'my_service'                      => '나의 서비스',
     'services'                        => '서버구축',
     'traffic_log'                     => '트래픽',
     'help'                            => '도와주다',
@@ -23,6 +24,8 @@ return [
     'referrals'                       => '홍보센트',
     'free_invite_codes_title'         => '무료초청코드',
     'no_need_invite_codes'            => '초청코드 없이 가입가능합니다',
+    'check_in'                        => '도착하다',
+    'no_notice'                       => '공고',
 
     // 首页
     'ratio_tips'                      => '지원 기능의 구독 기능을 사용하는 클라이언트 사용, 구독 기능으로 클라이언트 동기화 정보를 입력할 수 있습니다.',

+ 3 - 0
resources/lang/zh-CN/home.php

@@ -14,6 +14,7 @@ return [
 
     // 菜单
     'home'                            => '个人中心',
+    'my_service'                      => '我的服务',
     'services'                        => '购买服务',
     'traffic_log'                     => '流量记录',
     'help'                            => '帮助中心',
@@ -23,6 +24,8 @@ return [
     'referrals'                       => '推广返利',
     'free_invite_codes_title'         => '免费邀请码',
     'no_need_invite_codes'            => '现在无需邀请码',
+    'check_in'                        => '签到',
+    'no_notice'                       => '暂无公告',
 
     // 首页
     'ratio_tips'                      => '推荐使用支持节点订阅功能的客户端,通过订阅功能可以在客户端快速同步节点信息。',

+ 3 - 0
resources/lang/zh-tw/home.php

@@ -14,6 +14,7 @@ return [
 
     // 菜单
     'home'                            => '個人中心',
+    'my_service'                      => '我的服務',
     'services'                        => '購買服務',
     'traffic_log'                     => '流量記錄',
     'help'                            => '援助中心',
@@ -23,6 +24,8 @@ return [
     'referrals'                       => '推廣返利',
     'free_invite_codes_title'         => '免費邀請碼',
     'no_need_invite_codes'            => '現在無需邀請碼,即可注册',
+    'check_in'                        => '簽到',
+    'no_notice'                       => '暫無公告',
 
     // 首页
     'ratio_tips'                      => '推薦使用支持節點訂閱功能的用戶端,通過訂閱功能可以在用戶端快速同步節點資訊。',

+ 1 - 1
resources/views/auth/active.blade.php

@@ -26,7 +26,7 @@
     <script type="text/javascript">
         // 登录
         function login() {
-            window.location.href = '{{url('login')}}';
+            window.location.href = '/login';
         }
     </script>
 @endsection

+ 2 - 2
resources/views/auth/activeUser.blade.php

@@ -16,7 +16,7 @@
         </div>
     @endif
     <!-- BEGIN FORGOT PASSWORD FORM -->
-    <form class="forget-form" action="{{url('activeUser')}}" method="post" style="display: block;">
+    <form class="forget-form" action="/activeUser" method="post" style="display: block;">
         @if(\App\Components\Helpers::systemConfig()['is_active_register'])
             <div class="form-title">
                 <span class="form-title">{{trans('active.title')}}</span>
@@ -43,7 +43,7 @@
     <script type="text/javascript">
         // 登录
         function login() {
-            window.location.href = '{{url('login')}}';
+            window.location.href = '/login';
         }
     </script>
 @endsection

+ 3 - 9
resources/views/auth/free.blade.php

@@ -40,18 +40,12 @@
             <!-- BEGIN LOGO -->
             <div class="page-logo">
                 @if(\App\Components\Helpers::systemConfig()['website_logo'])
-                    <a href="{{url('/')}}"> <img src="{{\App\Components\Helpers::systemConfig()['website_logo']}}" alt="" style="width:300px; height:90px;"/> </a>
+                    <a href="/"> <img src="{{\App\Components\Helpers::systemConfig()['website_logo']}}" alt="" style="width:300px; height:90px;"/> </a>
                 @else
-                    <a href="{{url('/')}}"> <img src="/assets/images/logo.png" alt="logo" class="logo-default" /> </a>
+                    <a href="/"> <img src="/assets/images/logo.png" alt="logo" class="logo-default" /> </a>
                 @endif
             </div>
             <!-- END LOGO -->
-            <!-- BEGIN PAGE TOP -->
-            <div class="page-top">
-                <div class="top-menu">
-                    <ul class="nav navbar-nav pull-right"></ul>
-                </div>
-            </div>
         </div>
         <!-- END HEADER INNER -->
     </div>
@@ -93,7 +87,7 @@
                                                     @else
                                                         @foreach($inviteList as $key => $invite)
                                                             <tr>
-                                                                <td style="width: 50%; text-align: center;"> <a href="{{url('register?code='.$invite->code)}}" target="_blank">{{$invite->code}}</a> </td>
+                                                                <td style="width: 50%; text-align: center;"> <a href="/register?code={{$invite->code}}" target="_blank">{{$invite->code}}</a> </td>
                                                                 <td style="width: 50%; text-align: center;"> {{$invite->dateline}} </td>
                                                             </tr>
                                                         @endforeach

+ 2 - 2
resources/views/auth/layouts.blade.php

@@ -33,9 +33,9 @@
     <!-- BEGIN LOGO -->
     <div class="logo">
         @if(\App\Components\Helpers::systemConfig()['website_home_logo'])
-            <a href="{{url('/')}}"> <img src="{{\App\Components\Helpers::systemConfig()['website_home_logo']}}" alt="" style="max-width:300px; max-height:90px;"/> </a>
+            <a href="/"> <img src="{{\App\Components\Helpers::systemConfig()['website_home_logo']}}" alt="" style="max-width:300px; max-height:90px;"/> </a>
         @else
-            <a href="{{url('/')}}"> <img src="/assets/images/home_logo.png" alt="" /> </a>
+            <a href="/"> <img src="/assets/images/home_logo.png" alt="" /> </a>
         @endif
     </div>
     <!-- END LOGO -->

+ 3 - 3
resources/views/auth/login.blade.php

@@ -18,7 +18,7 @@
 @endsection
 @section('content')
     <!-- BEGIN LOGIN FORM -->
-    <form class="login-form" action="{{url('login')}}" id="login-form" method="post">
+    <form class="login-form" action="/login" id="login-form" method="post">
         @if($errors->any())
             <div class="alert alert-danger">
                 <span> {!! $errors->first() !!} </span>
@@ -71,7 +71,7 @@
                 </label>
             </div>
             <div class="pull-right forget-password-block">
-                <a href="{{url('resetPassword')}}" class="forget-password">{{trans('login.forget_password')}}</a>
+                <a href="/resetPassword" class="forget-password">{{trans('login.forget_password')}}</a>
             </div>
         </div>
         <div class="form-actions">
@@ -80,7 +80,7 @@
         @if(\App\Components\Helpers::systemConfig()['is_register'])
             <div class="create-account">
                 <p>
-                    <a href="{{url('register')}}" class="btn-primary btn">{{trans('login.register')}}</a>
+                    <a href="/register" class="btn-primary btn">{{trans('login.register')}}</a>
                 </p>
             </div>
         @endif

+ 6 - 6
resources/views/auth/register.blade.php

@@ -18,7 +18,7 @@
 @endsection
 @section('content')
     <!-- BEGIN REGISTRATION FORM -->
-    <form class="register-form" id="register-form" action="{{url('register')}}" method="post" style="display: block;">
+    <form class="register-form" id="register-form" action="/register" method="post" style="display: block;">
         @if(\App\Components\Helpers::systemConfig()['is_register'])
             @if($errors->any())
                 <div class="alert alert-danger">
@@ -41,11 +41,11 @@
             @endif
             <div class="form-group">
                 <label class="control-label visible-ie8 visible-ie9">{{trans('register.password')}}</label>
-                <input class="form-control placeholder-no-fix" type="password" autocomplete="off" placeholder="{{trans('register.password')}}" name="password" value="{{Request::old('password')}}" required />
+                <input class="form-control placeholder-no-fix" type="password" autocomplete="off" placeholder="{{trans('register.password')}}" name="password" value="" required />
             </div>
             <div class="form-group">
                 <label class="control-label visible-ie8 visible-ie9">{{trans('register.retype_password')}}</label>
-                <input class="form-control placeholder-no-fix" type="password" autocomplete="off" placeholder="{{trans('register.retype_password')}}" name="repassword" value="{{Request::old('repassword')}}" required />
+                <input class="form-control placeholder-no-fix" type="password" autocomplete="off" placeholder="{{trans('register.retype_password')}}" name="repassword" value="" required />
             </div>
             @if(\App\Components\Helpers::systemConfig()['is_invite_register'])
                 <div class="form-group">
@@ -53,7 +53,7 @@
                     <input class="form-control placeholder-no-fix" type="text" autocomplete="off" placeholder="{{trans('register.code')}}" name="code" value="{{Request::old('code') ? Request::old('code') : Request::get('code')}}" @if(\App\Components\Helpers::systemConfig()['is_invite_register'] == 2) required @endif />
                 </div>
                 @if(\App\Components\Helpers::systemConfig()['is_free_code'])
-                    <p class="hint"> <a href="{{url('free')}}" target="_blank">{{trans('register.get_free_code')}}</a> </p>
+                    <p class="hint"> <a href="/free" target="_blank">{{trans('register.get_free_code')}}</a> </p>
                 @endif
             @endif
             @if(!\App\Components\Helpers::systemConfig()['is_verify_register'])
@@ -108,7 +108,7 @@
     <script type="text/javascript">
         // 登录
         function login() {
-            window.location.href = '{{url('login')}}';
+            window.location.href = '/login';
         }
 
         // 服务条款
@@ -142,7 +142,7 @@
 
             $.ajax({
                 type: "POST",
-                url: "{{url('sendCode')}}",
+                url: "/sendCode",
                 async: false,
                 data: {_token: '{{csrf_token()}}', username: username},
                 dataType: 'json',

+ 1 - 1
resources/views/auth/reset.blade.php

@@ -47,7 +47,7 @@
     <script type="text/javascript">
         // 登录
         function login() {
-            window.location.href = '{{url('login')}}';
+            window.location.href = '/login';
         }
     </script>
 @endsection

+ 2 - 2
resources/views/auth/resetPassword.blade.php

@@ -14,7 +14,7 @@
             <span> {{$errors->first()}} </span>
         </div>
     @endif
-    <form class="forget-form" action="{{url('resetPassword')}}" method="post" style="display: block;">
+    <form class="forget-form" action="/resetPassword" method="post" style="display: block;">
         @if(\App\Components\Helpers::systemConfig()['is_reset_password'])
             <div class="form-title">
                 <span class="form-title">{{trans('home.reset_password_title')}}</span>
@@ -40,7 +40,7 @@
     <script type="text/javascript">
         // 登录
         function login() {
-            window.location.href = '{{url('login')}}';
+            window.location.href = '/login';
         }
     </script>
 @endsection

+ 2 - 2
resources/views/coupon/addCoupon.blade.php

@@ -23,13 +23,13 @@
                 <div class="portlet light bordered">
                     <div class="portlet-title">
                         <div class="caption">
-                            <span class="caption-subject font-dark sbold uppercase">生成卡券</span>
+                            <span class="caption-subject font-dark uppercase">生成卡券</span>
                         </div>
                         <div class="actions"></div>
                     </div>
                     <div class="portlet-body form">
                         <!-- BEGIN FORM-->
-                        <form action="{{url('coupon/addCoupon')}}" method="post" enctype="multipart/form-data" class="form-horizontal" role="form">
+                        <form action="/coupon/addCoupon" method="post" enctype="multipart/form-data" class="form-horizontal" role="form">
                             <div class="form-body">
                                 <div class="form-group">
                                     <label class="control-label col-md-3">卡券名称</label>

+ 5 - 5
resources/views/coupon/couponList.blade.php

@@ -22,8 +22,8 @@
                         </div>
                         <div class="actions">
                             <div class="btn-group btn-group-devided" data-toggle="buttons">
-                                <button class="btn sbold blue" onclick="exportCoupon()"> 批量导出 </button>
-                                <button class="btn sbold blue" onclick="addCoupon()"> 生成 </button>
+                                <button class="btn blue" onclick="exportCoupon()"> 批量导出 </button>
+                                <button class="btn blue" onclick="addCoupon()"> 生成 </button>
                             </div>
                         </div>
                     </div>
@@ -121,18 +121,18 @@
     <script type="text/javascript">
         // 批量导出卡券
         function exportCoupon() {
-            window.location.href = '{{url('coupon/exportCoupon')}}';
+            window.location.href = '/coupon/exportCoupon';
         }
 
         // 添加卡券
         function addCoupon() {
-            window.location.href = '{{url('coupon/addCoupon')}}';
+            window.location.href = '/coupon/addCoupon';
         }
 
         // 删除卡券
         function delCoupon(id) {
             layer.confirm('确定删除该卡券吗?', {icon: 2, title:'警告'}, function(index) {
-                $.post("{{url('coupon/delCoupon')}}", {id:id, _token:'{{csrf_token()}}'}, function(ret) {
+                $.post("/coupon/delCoupon", {id:id, _token:'{{csrf_token()}}'}, function(ret) {
                     layer.msg(ret.message, {time:1000}, function() {
                         if (ret.status == 'success') {
                             window.location.reload();

+ 87 - 0
resources/views/emails/closeOrder.blade.php

@@ -0,0 +1,87 @@
+<table class="body" style="Margin:0;background:#FAFAFA;border-collapse:collapse;border-spacing:0;color:#333;font-family:Helvetica,Arial,sans-serif;font-size:16px;font-weight:400;line-height:19px;margin:0;padding:0;text-align:left;vertical-align:top;width:100%">
+    <tbody>
+    <tr style="padding:0;text-align:left;vertical-align:top">
+        <td class="center" align="center" valign="top" style="-moz-hyphens:auto;-webkit-hyphens:auto;Margin:0;border-collapse:collapse!important;color:#333;font-family:Helvetica,Arial,sans-serif;font-size:16px;font-weight:400;hyphens:auto;line-height:19px;margin:0;padding:0;text-align:left;vertical-align:top;word-wrap:break-word">
+            <center data-parsed="" style="min-width:580px;width:100%">
+                <table align="center" class="container no-bg float-center" style="Margin:0 auto;background:0 0;border:0;border-collapse:collapse;border-radius:3px;border-spacing:0;box-shadow:none;float:none;margin:0 auto;margin-top:20px;padding:0;text-align:center;vertical-align:top;width:580px">
+                    <tbody>
+                    <tr style="padding:0;text-align:left;vertical-align:top">
+                        <td style="-moz-hyphens:auto;-webkit-hyphens:auto;Margin:0;border-collapse:collapse!important;color:#333;font-family:Helvetica,Arial,sans-serif;font-size:16px;font-weight:400;hyphens:auto;line-height:19px;margin:0;padding:0;text-align:left;vertical-align:top;word-wrap:break-word">
+                            <table class="row" style="border-collapse:collapse;border-spacing:0;display:table;padding:0;position:relative;text-align:left;vertical-align:top;width:100%">
+                                <tbody>
+                                <tr style="padding:0;text-align:left;vertical-align:top">
+
+                                    <th class="small-11 large-11 columns last" style="Margin:0 auto;color:#333;font-family:Helvetica,Arial,sans-serif;font-size:16px;font-weight:400;line-height:19px;margin:0 auto;padding:0;padding-bottom:0;padding-left:8px;padding-right:16px;text-align:left;width:515.67px">
+                                        <table style="border-collapse:collapse;border-spacing:0;padding:0;text-align:left;vertical-align:top;width:100%">
+                                            <tbody>
+                                            <tr style="padding:0;text-align:left;vertical-align:top">
+                                                <th style="Margin:0;color:#333;font-family:Helvetica,Arial,sans-serif;font-size:16px;font-weight:400;line-height:19px;margin:0;padding:0;text-align:left">
+                                                    <h3 style="Margin:0;Margin-bottom:10px;color:inherit;font-family:Helvetica,Arial,sans-serif;font-size:28px;font-weight:400;line-height:1.3;margin:0;margin-bottom:0;padding:0;text-align:left;word-wrap:normal">
+                                                        <a href="#" style="Margin:0;color:#40253b;font-family:Helvetica,Arial,sans-serif;font-weight:400;line-height:1.3;margin:0;padding:0;text-align:left;text-decoration:none" target="_blank">
+                                                            {{\App\Components\Helpers::systemConfig()['website_name']}}
+                                                        </a>
+                                                    </h3>
+                                                </th>
+                                            </tr>
+                                            </tbody>
+                                        </table>
+                                    </th>
+                                </tr>
+                                </tbody>
+                            </table>
+                        </td>
+                    </tr>
+                    </tbody>
+                </table>
+                <table align="center" class="container float-center" style="Margin:0 auto;background:#fefefe;border:1px solid #cdcdcd;border-collapse:collapse;border-radius:3px;border-spacing:0;float:none;margin:0 auto;margin-top:20px;padding:0;text-align:center;vertical-align:top;width:580px">
+                    <tbody>
+                    <tr style="padding:0;text-align:left;vertical-align:top">
+                        <td style="-moz-hyphens:auto;-webkit-hyphens:auto;Margin:0;border-collapse:collapse!important;color:#333;font-family:Helvetica,Arial,sans-serif;font-size:16px;font-weight:400;hyphens:auto;line-height:19px;margin:0;padding:0;text-align:left;vertical-align:top;word-wrap:break-word">
+                            <table class="row container-header-row" style="background-color:#5c97bd;border-collapse:collapse;border-spacing:0;color:#f3f3f3;display:table;padding:0;padding-bottom:8px;padding-top:8px;position:relative;text-align:left;vertical-align:top;width:100%">
+                                <tbody>
+                                <tr style="padding:0;text-align:left;vertical-align:top">
+                                    <th class="small-12 large-12 columns first last" style="Margin:0 auto;color:#333;font-family:Helvetica,Arial,sans-serif;font-size:16px;font-weight:400;line-height:19px;margin:0 auto;padding:0;padding-bottom:0;padding-left:16px;padding-right:16px;text-align:left;width:564px">
+                                        <table style="border-collapse:collapse;border-spacing:0;padding:0;text-align:left;vertical-align:top;width:100%">
+                                            <tbody>
+                                            <tr style="padding:0;text-align:left;vertical-align:top">
+                                                <th style="Margin:0;color:#333;font-family:Helvetica,Arial,sans-serif;font-size:16px;font-weight:400;line-height:19px;margin:0;padding:0;text-align:left">
+                                                    <h6 style="Margin:0;Margin-bottom:10px;color:#f3f3f3;font-family:Helvetica,Arial,sans-serif;font-size:18px;font-weight:400;line-height:1.3;margin:0;margin-bottom:8px;margin-top:8px;padding:0;text-align:left;word-wrap:normal">
+                                                        <a href="#" style="Margin:0;color:#f3f3f3;font-family:Helvetica,Arial,sans-serif;font-weight:400;line-height:1.3;margin:0;padding:0;text-align:left;text-decoration:none" target="_blank">
+                                                            订单关闭通知
+                                                        </a>
+                                                    </h6>
+                                                </th>
+                                                <th class="expander" style="Margin:0;color:#333;font-family:Helvetica,Arial,sans-serif;font-size:16px;font-weight:400;line-height:19px;margin:0;padding:0!important;text-align:left;visibility:hidden;width:0"></th>
+                                            </tr>
+                                            </tbody>
+                                        </table>
+                                    </th>
+                                </tr>
+                                </tbody>
+                            </table>
+                            <table class="row" style="border-collapse:collapse;border-spacing:0;display:table;padding:0;position:relative;text-align:left;vertical-align:top;width:100%">
+                                <tbody>
+                                <tr style="padding:0;text-align:left;vertical-align:top">
+                                    <th class="small-12 large-12 columns first last" style="Margin:0 auto;color:#333;font-family:Helvetica,Arial,sans-serif;font-size:16px;font-weight:400;line-height:19px;margin:0 auto;padding:0;padding-bottom:0;padding-left:16px;padding-right:16px;text-align:left;width:564px">
+                                        <p style="border-collapse:collapse;border-spacing:0;padding:0;text-align:left;vertical-align:top;width:100%"></p>
+                                <tbody>
+                                <tr style="padding:0;text-align:left;vertical-align:top">
+                                    <th style="Margin:0;color:#333;font-family:Helvetica,Arial,sans-serif;font-size:16px;font-weight:400;line-height:19px;margin:0;padding:0;text-align:left">
+                                        <div class="release" style="padding-top:5px;padding-left:20px;padding-bottom:20px;">
+                                            <p>{{$content}}</p>
+                                        </div>
+                                    </th>
+                                    <th class="expander" style="Margin:0;color:#333;font-family:Helvetica,Arial,sans-serif;font-size:16px;font-weight:400;line-height:19px;margin:0;padding:0!important;text-align:left;visibility:hidden;width:0"></th>
+                                </tr>
+                                </tbody>
+                                </th></tr></tbody>
+                            </table>
+                        </td>
+                    </tr>
+                    </tbody>
+                </table>
+            </center>
+        </td>
+    </tr>
+    </tbody>
+</table>

+ 87 - 0
resources/views/emails/sendCustomMessage.blade.php

@@ -0,0 +1,87 @@
+<table class="body" style="Margin:0;background:#FAFAFA;border-collapse:collapse;border-spacing:0;color:#333;font-family:Helvetica,Arial,sans-serif;font-size:16px;font-weight:400;line-height:19px;margin:0;padding:0;text-align:left;vertical-align:top;width:100%">
+    <tbody>
+    <tr style="padding:0;text-align:left;vertical-align:top">
+        <td class="center" align="center" valign="top" style="-moz-hyphens:auto;-webkit-hyphens:auto;Margin:0;border-collapse:collapse!important;color:#333;font-family:Helvetica,Arial,sans-serif;font-size:16px;font-weight:400;hyphens:auto;line-height:19px;margin:0;padding:0;text-align:left;vertical-align:top;word-wrap:break-word">
+            <center data-parsed="" style="min-width:580px;width:100%">
+                <table align="center" class="container no-bg float-center" style="Margin:0 auto;background:0 0;border:0;border-collapse:collapse;border-radius:3px;border-spacing:0;box-shadow:none;float:none;margin:0 auto;margin-top:20px;padding:0;text-align:center;vertical-align:top;width:580px">
+                    <tbody>
+                    <tr style="padding:0;text-align:left;vertical-align:top">
+                        <td style="-moz-hyphens:auto;-webkit-hyphens:auto;Margin:0;border-collapse:collapse!important;color:#333;font-family:Helvetica,Arial,sans-serif;font-size:16px;font-weight:400;hyphens:auto;line-height:19px;margin:0;padding:0;text-align:left;vertical-align:top;word-wrap:break-word">
+                            <table class="row" style="border-collapse:collapse;border-spacing:0;display:table;padding:0;position:relative;text-align:left;vertical-align:top;width:100%">
+                                <tbody>
+                                <tr style="padding:0;text-align:left;vertical-align:top">
+
+                                    <th class="small-11 large-11 columns last" style="Margin:0 auto;color:#333;font-family:Helvetica,Arial,sans-serif;font-size:16px;font-weight:400;line-height:19px;margin:0 auto;padding:0;padding-bottom:0;padding-left:8px;padding-right:16px;text-align:left;width:515.67px">
+                                        <table style="border-collapse:collapse;border-spacing:0;padding:0;text-align:left;vertical-align:top;width:100%">
+                                            <tbody>
+                                            <tr style="padding:0;text-align:left;vertical-align:top">
+                                                <th style="Margin:0;color:#333;font-family:Helvetica,Arial,sans-serif;font-size:16px;font-weight:400;line-height:19px;margin:0;padding:0;text-align:left">
+                                                    <h3 style="Margin:0;Margin-bottom:10px;color:inherit;font-family:Helvetica,Arial,sans-serif;font-size:28px;font-weight:400;line-height:1.3;margin:0;margin-bottom:0;padding:0;text-align:left;word-wrap:normal">
+                                                        <a href="#" style="Margin:0;color:#40253b;font-family:Helvetica,Arial,sans-serif;font-weight:400;line-height:1.3;margin:0;padding:0;text-align:left;text-decoration:none" target="_blank">
+                                                            {{\App\Components\Helpers::systemConfig()['website_name']}}
+                                                        </a>
+                                                    </h3>
+                                                </th>
+                                            </tr>
+                                            </tbody>
+                                        </table>
+                                    </th>
+                                </tr>
+                                </tbody>
+                            </table>
+                        </td>
+                    </tr>
+                    </tbody>
+                </table>
+                <table align="center" class="container float-center" style="Margin:0 auto;background:#fefefe;border:1px solid #cdcdcd;border-collapse:collapse;border-radius:3px;border-spacing:0;float:none;margin:0 auto;margin-top:20px;padding:0;text-align:center;vertical-align:top;width:580px">
+                    <tbody>
+                    <tr style="padding:0;text-align:left;vertical-align:top">
+                        <td style="-moz-hyphens:auto;-webkit-hyphens:auto;Margin:0;border-collapse:collapse!important;color:#333;font-family:Helvetica,Arial,sans-serif;font-size:16px;font-weight:400;hyphens:auto;line-height:19px;margin:0;padding:0;text-align:left;vertical-align:top;word-wrap:break-word">
+                            <table class="row container-header-row" style="background-color:#5c97bd;border-collapse:collapse;border-spacing:0;color:#f3f3f3;display:table;padding:0;padding-bottom:8px;padding-top:8px;position:relative;text-align:left;vertical-align:top;width:100%">
+                                <tbody>
+                                <tr style="padding:0;text-align:left;vertical-align:top">
+                                    <th class="small-12 large-12 columns first last" style="Margin:0 auto;color:#333;font-family:Helvetica,Arial,sans-serif;font-size:16px;font-weight:400;line-height:19px;margin:0 auto;padding:0;padding-bottom:0;padding-left:16px;padding-right:16px;text-align:left;width:564px">
+                                        <table style="border-collapse:collapse;border-spacing:0;padding:0;text-align:left;vertical-align:top;width:100%">
+                                            <tbody>
+                                            <tr style="padding:0;text-align:left;vertical-align:top">
+                                                <th style="Margin:0;color:#333;font-family:Helvetica,Arial,sans-serif;font-size:16px;font-weight:400;line-height:19px;margin:0;padding:0;text-align:left">
+                                                    <h6 style="Margin:0;Margin-bottom:10px;color:#f3f3f3;font-family:Helvetica,Arial,sans-serif;font-size:18px;font-weight:400;line-height:1.3;margin:0;margin-bottom:8px;margin-top:8px;padding:0;text-align:left;word-wrap:normal">
+                                                        <a href="#" style="Margin:0;color:#f3f3f3;font-family:Helvetica,Arial,sans-serif;font-weight:400;line-height:1.3;margin:0;padding:0;text-align:left;text-decoration:none" target="_blank">
+                                                            {{$title}}
+                                                        </a>
+                                                    </h6>
+                                                </th>
+                                                <th class="expander" style="Margin:0;color:#333;font-family:Helvetica,Arial,sans-serif;font-size:16px;font-weight:400;line-height:19px;margin:0;padding:0!important;text-align:left;visibility:hidden;width:0"></th>
+                                            </tr>
+                                            </tbody>
+                                        </table>
+                                    </th>
+                                </tr>
+                                </tbody>
+                            </table>
+                            <table class="row" style="border-collapse:collapse;border-spacing:0;display:table;padding:0;position:relative;text-align:left;vertical-align:top;width:100%">
+                                <tbody>
+                                <tr style="padding:0;text-align:left;vertical-align:top">
+                                    <th class="small-12 large-12 columns first last" style="Margin:0 auto;color:#333;font-family:Helvetica,Arial,sans-serif;font-size:16px;font-weight:400;line-height:19px;margin:0 auto;padding:0;padding-bottom:0;padding-left:16px;padding-right:16px;text-align:left;width:564px">
+                                        <p style="border-collapse:collapse;border-spacing:0;padding:0;text-align:left;vertical-align:top;width:100%"></p>
+                                <tbody>
+                                <tr style="padding:0;text-align:left;vertical-align:top">
+                                    <th style="Margin:0;color:#333;font-family:Helvetica,Arial,sans-serif;font-size:16px;font-weight:400;line-height:19px;margin:0;padding:0;text-align:left">
+                                        <div class="release" style="padding-top:5px;padding-left:20px;padding-bottom:20px;">
+                                            <p>{{$content}}。详情见网站:{{\App\Components\Helpers::systemConfig()['website_url']}}</p>
+                                        </div>
+                                    </th>
+                                    <th class="expander" style="Margin:0;color:#333;font-family:Helvetica,Arial,sans-serif;font-size:16px;font-weight:400;line-height:19px;margin:0;padding:0!important;text-align:left;visibility:hidden;width:0"></th>
+                                </tr>
+                                </tbody>
+                                </th></tr></tbody>
+                            </table>
+                        </td>
+                    </tr>
+                    </tbody>
+                </table>
+            </center>
+        </td>
+    </tr>
+    </tbody>
+</table>

+ 1 - 1
resources/views/emails/userExpireWarning.blade.php

@@ -68,7 +68,7 @@
                                 <tr style="padding:0;text-align:left;vertical-align:top">
                                     <th style="Margin:0;color:#333;font-family:Helvetica,Arial,sans-serif;font-size:16px;font-weight:400;line-height:19px;margin:0;padding:0;text-align:left">
                                         <div class="release" style="padding-top:5px;padding-left:20px;padding-bottom:20px;">
-                                            <p>您的账号【{{$lastCanUseDays}}】天后即将过期,为了确保您可以继续正常使用我们的服务,请及时续费。</p>
+                                            <p>您的账号【{{$lastCanUseDays}}】天后即将过期,为了确保您可以继续使用我们的服务,请及时续费或者购买服务详情见网站:{{\App\Components\Helpers::systemConfig()['website_url']}}</p>
                                         </div>
                                     </th>
                                     <th class="expander" style="Margin:0;color:#333;font-family:Helvetica,Arial,sans-serif;font-size:16px;font-weight:400;line-height:19px;margin:0;padding:0!important;text-align:left;visibility:hidden;width:0"></th>

+ 1 - 1
resources/views/emails/userExpireWarningToday.blade.php

@@ -68,7 +68,7 @@
                                 <tr style="padding:0;text-align:left;vertical-align:top">
                                     <th style="Margin:0;color:#333;font-family:Helvetica,Arial,sans-serif;font-size:16px;font-weight:400;line-height:19px;margin:0;padding:0;text-align:left">
                                         <div class="release" style="padding-top:5px;padding-left:20px;padding-bottom:20px;">
-                                            <p>您的账号将于今天晚上【24:00】过期,为了确保您可以继续正常使用我们的服务,请及时续费。</p>
+                                            <p>您的账号将于今天晚上【24:00】过期,为了确保您可以继续使用我们的服务,请及时续费或者购买服务详情见网站:{{\App\Components\Helpers::systemConfig()['website_url']}}</p>
                                         </div>
                                     </th>
                                     <th class="expander" style="Margin:0;color:#333;font-family:Helvetica,Arial,sans-serif;font-size:16px;font-weight:400;line-height:19px;margin:0;padding:0!important;text-align:left;visibility:hidden;width:0"></th>

+ 87 - 0
resources/views/emails/userTrafficAbnormalWarning.blade.php

@@ -0,0 +1,87 @@
+<table class="body" style="Margin:0;background:#FAFAFA;border-collapse:collapse;border-spacing:0;color:#333;font-family:Helvetica,Arial,sans-serif;font-size:16px;font-weight:400;line-height:19px;margin:0;padding:0;text-align:left;vertical-align:top;width:100%">
+    <tbody>
+    <tr style="padding:0;text-align:left;vertical-align:top">
+        <td class="center" align="center" valign="top" style="-moz-hyphens:auto;-webkit-hyphens:auto;Margin:0;border-collapse:collapse!important;color:#333;font-family:Helvetica,Arial,sans-serif;font-size:16px;font-weight:400;hyphens:auto;line-height:19px;margin:0;padding:0;text-align:left;vertical-align:top;word-wrap:break-word">
+            <center data-parsed="" style="min-width:580px;width:100%">
+                <table align="center" class="container no-bg float-center" style="Margin:0 auto;background:0 0;border:0;border-collapse:collapse;border-radius:3px;border-spacing:0;box-shadow:none;float:none;margin:0 auto;margin-top:20px;padding:0;text-align:center;vertical-align:top;width:580px">
+                    <tbody>
+                    <tr style="padding:0;text-align:left;vertical-align:top">
+                        <td style="-moz-hyphens:auto;-webkit-hyphens:auto;Margin:0;border-collapse:collapse!important;color:#333;font-family:Helvetica,Arial,sans-serif;font-size:16px;font-weight:400;hyphens:auto;line-height:19px;margin:0;padding:0;text-align:left;vertical-align:top;word-wrap:break-word">
+                            <table class="row" style="border-collapse:collapse;border-spacing:0;display:table;padding:0;position:relative;text-align:left;vertical-align:top;width:100%">
+                                <tbody>
+                                <tr style="padding:0;text-align:left;vertical-align:top">
+
+                                    <th class="small-11 large-11 columns last" style="Margin:0 auto;color:#333;font-family:Helvetica,Arial,sans-serif;font-size:16px;font-weight:400;line-height:19px;margin:0 auto;padding:0;padding-bottom:0;padding-left:8px;padding-right:16px;text-align:left;width:515.67px">
+                                        <table style="border-collapse:collapse;border-spacing:0;padding:0;text-align:left;vertical-align:top;width:100%">
+                                            <tbody>
+                                            <tr style="padding:0;text-align:left;vertical-align:top">
+                                                <th style="Margin:0;color:#333;font-family:Helvetica,Arial,sans-serif;font-size:16px;font-weight:400;line-height:19px;margin:0;padding:0;text-align:left">
+                                                    <h3 style="Margin:0;Margin-bottom:10px;color:inherit;font-family:Helvetica,Arial,sans-serif;font-size:28px;font-weight:400;line-height:1.3;margin:0;margin-bottom:0;padding:0;text-align:left;word-wrap:normal">
+                                                        <a href="#" style="Margin:0;color:#40253b;font-family:Helvetica,Arial,sans-serif;font-weight:400;line-height:1.3;margin:0;padding:0;text-align:left;text-decoration:none" target="_blank">
+                                                            {{\App\Components\Helpers::systemConfig()['website_name']}}
+                                                        </a>
+                                                    </h3>
+                                                </th>
+                                            </tr>
+                                            </tbody>
+                                        </table>
+                                    </th>
+                                </tr>
+                                </tbody>
+                            </table>
+                        </td>
+                    </tr>
+                    </tbody>
+                </table>
+                <table align="center" class="container float-center" style="Margin:0 auto;background:#fefefe;border:1px solid #cdcdcd;border-collapse:collapse;border-radius:3px;border-spacing:0;float:none;margin:0 auto;margin-top:20px;padding:0;text-align:center;vertical-align:top;width:580px">
+                    <tbody>
+                    <tr style="padding:0;text-align:left;vertical-align:top">
+                        <td style="-moz-hyphens:auto;-webkit-hyphens:auto;Margin:0;border-collapse:collapse!important;color:#333;font-family:Helvetica,Arial,sans-serif;font-size:16px;font-weight:400;hyphens:auto;line-height:19px;margin:0;padding:0;text-align:left;vertical-align:top;word-wrap:break-word">
+                            <table class="row container-header-row" style="background-color:#5c97bd;border-collapse:collapse;border-spacing:0;color:#f3f3f3;display:table;padding:0;padding-bottom:8px;padding-top:8px;position:relative;text-align:left;vertical-align:top;width:100%">
+                                <tbody>
+                                <tr style="padding:0;text-align:left;vertical-align:top">
+                                    <th class="small-12 large-12 columns first last" style="Margin:0 auto;color:#333;font-family:Helvetica,Arial,sans-serif;font-size:16px;font-weight:400;line-height:19px;margin:0 auto;padding:0;padding-bottom:0;padding-left:16px;padding-right:16px;text-align:left;width:564px">
+                                        <table style="border-collapse:collapse;border-spacing:0;padding:0;text-align:left;vertical-align:top;width:100%">
+                                            <tbody>
+                                            <tr style="padding:0;text-align:left;vertical-align:top">
+                                                <th style="Margin:0;color:#333;font-family:Helvetica,Arial,sans-serif;font-size:16px;font-weight:400;line-height:19px;margin:0;padding:0;text-align:left">
+                                                    <h6 style="Margin:0;Margin-bottom:10px;color:#f3f3f3;font-family:Helvetica,Arial,sans-serif;font-size:18px;font-weight:400;line-height:1.3;margin:0;margin-bottom:8px;margin-top:8px;padding:0;text-align:left;word-wrap:normal">
+                                                        <a href="#" style="Margin:0;color:#f3f3f3;font-family:Helvetica,Arial,sans-serif;font-weight:400;line-height:1.3;margin:0;padding:0;text-align:left;text-decoration:none" target="_blank">
+                                                            流量异常警告
+                                                        </a>
+                                                    </h6>
+                                                </th>
+                                                <th class="expander" style="Margin:0;color:#333;font-family:Helvetica,Arial,sans-serif;font-size:16px;font-weight:400;line-height:19px;margin:0;padding:0!important;text-align:left;visibility:hidden;width:0"></th>
+                                            </tr>
+                                            </tbody>
+                                        </table>
+                                    </th>
+                                </tr>
+                                </tbody>
+                            </table>
+                            <table class="row" style="border-collapse:collapse;border-spacing:0;display:table;padding:0;position:relative;text-align:left;vertical-align:top;width:100%">
+                                <tbody>
+                                <tr style="padding:0;text-align:left;vertical-align:top">
+                                    <th class="small-12 large-12 columns first last" style="Margin:0 auto;color:#333;font-family:Helvetica,Arial,sans-serif;font-size:16px;font-weight:400;line-height:19px;margin:0 auto;padding:0;padding-bottom:0;padding-left:16px;padding-right:16px;text-align:left;width:564px">
+                                        <p style="border-collapse:collapse;border-spacing:0;padding:0;text-align:left;vertical-align:top;width:100%"></p>
+                                <tbody>
+                                <tr style="padding:0;text-align:left;vertical-align:top">
+                                    <th style="Margin:0;color:#333;font-family:Helvetica,Arial,sans-serif;font-size:16px;font-weight:400;line-height:19px;margin:0;padding:0;text-align:left">
+                                        <div class="release" style="padding-top:5px;padding-left:20px;padding-bottom:20px;">
+                                            <p>{{$content}}。详情见网站:{{\App\Components\Helpers::systemConfig()['website_url']}}</p>
+                                        </div>
+                                    </th>
+                                    <th class="expander" style="Margin:0;color:#333;font-family:Helvetica,Arial,sans-serif;font-size:16px;font-weight:400;line-height:19px;margin:0;padding:0!important;text-align:left;visibility:hidden;width:0"></th>
+                                </tr>
+                                </tbody>
+                                </th></tr></tbody>
+                            </table>
+                        </td>
+                    </tr>
+                    </tbody>
+                </table>
+            </center>
+        </td>
+    </tr>
+    </tbody>
+</table>

+ 1 - 1
resources/views/emails/userTrafficWarning.blade.php

@@ -68,7 +68,7 @@
                                 <tr style="padding:0;text-align:left;vertical-align:top">
                                     <th style="Margin:0;color:#333;font-family:Helvetica,Arial,sans-serif;font-size:16px;font-weight:400;line-height:19px;margin:0;padding:0;text-align:left">
                                         <div class="release" style="padding-top:5px;padding-left:20px;padding-bottom:20px;">
-                                            <p>您的流量已使用【{{$usedPercent}}%】,为了确保您可以继续正常使用我们的服务,请及时续费或者购买流量包。</p>
+                                            <p>您的流量已使用【{{$usedPercent}}%】,为了确保您可以继续使用我们的服务,请及时续费或者购买服务。详情见网站:{{\App\Components\Helpers::systemConfig()['website_url']}}</p>
                                         </div>
                                     </th>
                                     <th class="expander" style="Margin:0;color:#333;font-family:Helvetica,Arial,sans-serif;font-size:16px;font-weight:400;line-height:19px;margin:0;padding:0!important;text-align:left;visibility:hidden;width:0"></th>

+ 6 - 1
resources/views/marketing/emailList.blade.php

@@ -2,6 +2,11 @@
 @section('css')
     <link href="/assets/global/plugins/datatables/datatables.min.css" rel="stylesheet" type="text/css" />
     <link href="/assets/global/plugins/datatables/plugins/bootstrap/datatables.bootstrap.css" rel="stylesheet" type="text/css" />
+    <style type="text/css">
+        input,select {
+            margin-bottom: 5px;
+        }
+    </style>
 @endsection
 @section('content')
     <!-- BEGIN CONTENT BODY -->
@@ -17,7 +22,7 @@
                         </div>
                         <div class="actions">
                             <div class="btn-group btn-group-devided">
-                                <button class="btn sbold blue" onclick="send()"> 群发邮件 </button>
+                                <button class="btn blue" onclick="send()"> 群发邮件 </button>
                             </div>
                         </div>
                     </div>

+ 3 - 3
resources/views/payment/detail.blade.php

@@ -66,15 +66,15 @@
         function getStatus() {
             var sn = '{{$payment->sn}}';
 
-            $.get("{{url('payment/getStatus')}}", {sn:sn}, function (ret) {
+            $.get("/payment/getStatus", {sn:sn}, function (ret) {
                 console.log(ret);
                 if (ret.status == 'success') {
                     layer.msg(ret.message, {time:1500}, function() {
-                        window.location.href = '{{url('invoices')}}';
+                        window.location.href = '/invoices';
                     });
                 } else if(ret.status == 'error') {
                     layer.msg(ret.message, {time:1500}, function () {
-                        window.location.href = '{{url('invoices')}}';
+                        window.location.href = '/invoices';
                     })
                 }
             });

+ 3 - 3
resources/views/sensitiveWords/addSensitiveWords.blade.php

@@ -11,7 +11,7 @@
                 <div class="portlet light bordered">
                     <div class="portlet-title">
                         <div class="caption">
-                            <span class="caption-subject font-dark sbold uppercase">添加敏感词</span>
+                            <span class="caption-subject font-dark uppercase">添加敏感词</span>
                         </div>
                         <div class="actions"></div>
                     </div>
@@ -78,14 +78,14 @@
 
             $.ajax({
                 type: "POST",
-                url: "{{url('admin/addSensitiveWords')}}",
+                url: "/admin/addSensitiveWords",
                 async: false,
                 data: {_token:_token, words:words},
                 dataType: 'json',
                 success: function (ret) {
                     layer.msg(ret.message, {time:1000}, function() {
                         if (ret.status == 'success') {
-                            window.location.href = '{{url('admin/sensitiveWordsList')}}';
+                            window.location.href = '/admin/sensitiveWordsList';
                         }
                     });
                 }

+ 4 - 4
resources/views/ticket/replyTicket.blade.php

@@ -18,7 +18,7 @@
                         <div class="actions">
                             @if($ticket->status != 2)
                                 <div class="btn-group btn-group-devided" data-toggle="buttons">
-                                    <a class="btn red btn-outline sbold" data-toggle="modal" href="#closeTicket"> 关闭 </a>
+                                    <a class="btn red btn-outline" data-toggle="modal" href="#closeTicket"> 关闭 </a>
                                 </div>
                             @endif
                         </div>
@@ -136,14 +136,14 @@
         function closeTicket() {
             $.ajax({
                 type: "POST",
-                url: "{{url('ticket/closeTicket')}}",
+                url: "/ticket/closeTicket",
                 async: true,
                 data: {_token:'{{csrf_token()}}', id:'{{$ticket->id}}'},
                 dataType: 'json',
                 success: function (ret) {
                     layer.msg(ret.message, {time:1000}, function() {
                         if (ret.status == 'success') {
-                            window.location.href = '{{url('ticket/ticketList')}}';
+                            window.location.href = '/ticket/ticketList';
                         }
                     });
                 }
@@ -160,7 +160,7 @@
             }
 
             layer.confirm('确定回复工单?', {icon: 3, title:'提示'}, function(index) {
-                $.post("{{url('ticket/replyTicket')}}",{_token:'{{csrf_token()}}', id:'{{$ticket->id}}', content:content}, function(ret) {
+                $.post("/ticket/replyTicket",{_token:'{{csrf_token()}}', id:'{{$ticket->id}}', content:content}, function(ret) {
                     layer.msg(ret.message, {time:1000}, function() {
                         if (ret.status == 'success') {
                             window.location.reload();

+ 2 - 2
resources/views/ticket/ticketList.blade.php

@@ -40,9 +40,9 @@
                                                 @if(empty($ticket->user))
                                                     【账号已删除】
                                                 @else
-                                                    <a href="{{url('admin/userList?id=' . $ticket->user->id)}}" target="_blank">{{$ticket->user->username}}</a> </td>
+                                                    <a href="/admin/userList?id={{$ticket->user->id}}" target="_blank">{{$ticket->user->username}}</a> </td>
                                                 @endif
-                                            <td> <a href="{{url('ticket/replyTicket?id=') . $ticket->id}}" target="_blank">{{$ticket->title}}</a> </td>
+                                            <td> <a href="/ticket/replyTicket?id={{$ticket->id}}" target="_blank">{{$ticket->title}}</a> </td>
                                             <td style="text-align: center;">
                                                 @if ($ticket->status == 0)
                                                     <span class="label label-info"> 待处理 </span>

+ 1 - 1
resources/views/vendor/geetest/geetest.blade.php

@@ -36,7 +36,7 @@
                     product: "{{ $product?$product:Config::get('geetest.product', 'float') }}",
                     offline: !data.success, // 表示用户后台检测极验服务器是否宕机
                     new_captcha: data.new_captcha,  // 用于宕机时表示是新验证码的宕机
-                    lang: '{{session::get('locale')}}',
+                    lang: '{{session::get('locale', 'zh-cn')}}', // 免费版本仅支持中文
                     http: '{{ Config::get('geetest.protocol', 'http') }}' + '://',
                     width: '100%'
                 }, handlerEmbed);

+ 0 - 6
routes/api.php

@@ -4,10 +4,4 @@ Route::group(['namespace' => 'Api'], function () {
     Route::resource('yzy', 'YzyController');
     Route::resource('alipay', 'AlipayController');
     Route::resource('f2fpay', 'F2fpayController');
-
-    // 定制客户端
-    Route::any('login', 'LoginController@login');
-
-    // PING检测
-    Route::get('ping', 'PingController@ping');
 });

BIN
scripts/servers/shadowsocksr-3.2.2.tar.gz


BIN
scripts/servers/vnet-0.0.6.zip


+ 1 - 1
sql/update/20190129.sql

@@ -1,7 +1,7 @@
 -- 加入订阅设备表
 CREATE TABLE `device` (
 	`id` INT(11) NOT NULL AUTO_INCREMENT,
-	`type` TINYINT(4) NOT NULL DEFAULT '1' COMMENT '类型:0-兼容、1-Shadowsocks(R)、2-V2Ray',
+	`type` TINYINT(4) NOT NULL DEFAULT '1' COMMENT '类型:0-兼容、1-ShadowsocksR、2-V2Ray',
 	`platform` TINYINT(4) NOT NULL DEFAULT '1' COMMENT '所属平台:0-其他、1-iOS、2-Android、3-Mac、4-Windows、5-Linux',
 	`name` VARCHAR(50) NOT NULL COMMENT '设备名称',
 	`status` TINYINT(4) NOT NULL DEFAULT '1' COMMENT '状态:0-禁止订阅、1-允许订阅',