Browse Source

first commit

wzq 5 years ago
commit
b4d2282b06
67 changed files with 2809 additions and 0 deletions
  1. 15 0
      .editorconfig
  2. 29 0
      .env.example
  3. 8 0
      .gitignore
  4. 84 0
      .rocketeer/config.php
  5. 40 0
      .rocketeer/hooks.php
  6. 24 0
      .rocketeer/paths.php
  7. 80 0
      .rocketeer/remote.php
  8. 35 0
      .rocketeer/scm.php
  9. 19 0
      .rocketeer/stages.php
  10. 61 0
      .rocketeer/strategies.php
  11. 0 0
      app/Console/Commands/.gitkeep
  12. 86 0
      app/Console/Commands/apollo.php
  13. 30 0
      app/Console/Kernel.php
  14. 10 0
      app/Events/Event.php
  15. 16 0
      app/Events/ExampleEvent.php
  16. 50 0
      app/Exceptions/Handler.php
  17. 18 0
      app/Helper/helper.php
  18. 10 0
      app/Http/Controllers/Controller.php
  19. 12 0
      app/Http/Controllers/V1/Controller.php
  20. 18 0
      app/Http/Controllers/V1/TestController.php
  21. 48 0
      app/Http/Middleware/Authenticate.php
  22. 20 0
      app/Http/Middleware/ExampleMiddleware.php
  23. 61 0
      app/Http/Middleware/JwtAuthMiddleware.php
  24. 26 0
      app/Jobs/ExampleJob.php
  25. 24 0
      app/Jobs/Job.php
  26. 31 0
      app/Listeners/ExampleListener.php
  27. 18 0
      app/Providers/AppServiceProvider.php
  28. 39 0
      app/Providers/AuthServiceProvider.php
  29. 19 0
      app/Providers/EventServiceProvider.php
  30. 88 0
      app/Service/RabbitMqUtil.php
  31. 35 0
      artisan
  32. 26 0
      bin/fswatch
  33. 11 0
      bin/laravels
  34. 110 0
      bootstrap/app.php
  35. 59 0
      composer.json
  36. 232 0
      config/api.php
  37. 10 0
      config/apollo.php
  38. 90 0
      config/auth.php
  39. 6 0
      config/customer.tpl
  40. 131 0
      config/database.php
  41. 304 0
      config/jwt.php
  42. 79 0
      config/laravels.php
  43. 19 0
      database/factories/ModelFactory.php
  44. 0 0
      database/migrations/.gitkeep
  45. 16 0
      database/seeds/DatabaseSeeder.php
  46. 20 0
      deploy/nginx/conf.d/app.beta.conf
  47. 20 0
      deploy/nginx/conf.d/app.dev.conf
  48. 2 0
      deploy/php/local.ini
  49. 32 0
      docker-compose-beta.yml
  50. 31 0
      docker-compose-dev.yml
  51. 26 0
      phpunit.xml
  52. 21 0
      public/.htaccess
  53. 28 0
      public/index.php
  54. 21 0
      readme.md
  55. 19 0
      resources/lang/en/auth.php
  56. 19 0
      resources/lang/en/pagination.php
  57. 22 0
      resources/lang/en/passwords.php
  58. 146 0
      resources/lang/en/validation.php
  59. 17 0
      resources/lang/zh-CN/auth.php
  60. 17 0
      resources/lang/zh-CN/pagination.php
  61. 20 0
      resources/lang/zh-CN/passwords.php
  62. 106 0
      resources/lang/zh-CN/validation.php
  63. 0 0
      resources/views/.gitkeep
  64. 40 0
      routes/api.php
  65. 20 0
      routes/web.php
  66. 21 0
      tests/ExampleTest.php
  67. 14 0
      tests/TestCase.php

+ 15 - 0
.editorconfig

@@ -0,0 +1,15 @@
+root = true
+
+[*]
+charset = utf-8
+end_of_line = lf
+insert_final_newline = true
+indent_style = space
+indent_size = 4
+trim_trailing_whitespace = true
+
+[*.md]
+trim_trailing_whitespace = false
+
+[*.yml]
+indent_size = 2

+ 29 - 0
.env.example

@@ -0,0 +1,29 @@
+APP_NAME=community-manage
+APP_ENV=local
+APP_KEY=
+APP_DEBUG=true
+APP_URL=http://localhost
+APP_TIMEZONE=Asia/Shanghai
+APP_LOCALE=zh-CN
+
+LOG_CHANNEL=stack
+LOG_SLACK_WEBHOOK_URL=
+
+DB_CONNECTION=mysql
+DB_HOST=127.0.0.1
+DB_PORT=3306
+DB_DATABASE=homestead
+DB_USERNAME=homestead
+DB_PASSWORD=secret
+
+CACHE_DRIVER=file
+QUEUE_CONNECTION=sync
+
+JWT_SECRET=chxqyhnjuikm67wshaed8ij3hyf2ndh3
+
+PER_PAGE=20
+
+APP_ID=chxq-platform-manage
+CLUSTER=default
+APOLLO_NAMESPACES="application,community-manage"
+APOLLO_CONFIG_SERVER=http://127.0.0.1:18080

+ 8 - 0
.gitignore

@@ -0,0 +1,8 @@
+/vendor
+/.idea
+Homestead.json
+Homestead.yaml
+.env
+composer.lock
+/storage/*
+/config/customer.php

+ 84 - 0
.rocketeer/config.php

@@ -0,0 +1,84 @@
+<?php
+
+use Rocketeer\Services\Connections\ConnectionsHandler;
+
+return [
+
+    // The name of the application to deploy
+    // This will create a folder of the same name in the root directory
+    // configured above, so be careful about the characters used
+    'application_name' => 'order-manage',
+
+    // Plugins
+    ////////////////////////////////////////////////////////////////////
+
+    // The plugins to load
+    'plugins'          => [// 'Rocketeer\Plugins\Slack\RocketeerSlack',
+    ],
+
+    // Logging
+    ////////////////////////////////////////////////////////////////////
+
+    // The schema to use to name log files
+    'logs'             => function (ConnectionsHandler $connections) {
+        return sprintf('%s-%s-%s.log', $connections->getConnection(), $connections->getStage(), date('Ymd'));
+    },
+
+    // Remote access
+    //
+    // You can either use a single connection or an array of connections
+    ////////////////////////////////////////////////////////////////////
+
+    // The default remote connection(s) to execute tasks on
+    'default'          => ['production'],
+
+    // The various connections you defined
+    // You can leave all of this empty or remove it entirely if you don't want
+    // to track files with credentials : Rocketeer will prompt you for your credentials
+    // and store them locally
+    'connections'      => [
+        'production' => [
+            'host'      => '47.92.174.125:2345',
+            'username'  => 'root',
+            'password'  => '',
+            'key'       => '/root/.ssh/id_rsa',
+            'keyphrase' => '',
+            'agent'     => '',
+            'db_role'   => true,
+        ],
+    ],
+
+    /*
+     * In most multiserver scenarios, migrations must be run in an exclusive server.
+     * In the event of not having a separate database server (in which case it can
+     * be handled through connections), you can assign a 'db_role' => true to the
+     * server's configuration and it will only run the migrations in that specific
+     * server at the time of deployment.
+     */
+    'use_roles'        => false,
+
+    // Contextual options
+    //
+    // In this section you can fine-tune the above configuration according
+    // to the stage or connection currently in use.
+    // Per example :
+    // 'stages' => array(
+    // 	'staging' => array(
+    // 		'scm' => array('branch' => 'staging'),
+    // 	),
+    //  'production' => array(
+    //    'scm' => array('branch' => 'master'),
+    //  ),
+    // ),
+    ////////////////////////////////////////////////////////////////////
+
+    'on'               => [
+
+        // Stages configurations
+        'stages'      => [],
+        // Connections configuration
+        'connections' => [],
+
+    ],
+
+];

+ 40 - 0
.rocketeer/hooks.php

@@ -0,0 +1,40 @@
+<?php
+
+return [
+
+    // Tasks
+    //
+    // Here you can define in the `before` and `after` array, Tasks to execute
+    // before or after the core Rocketeer Tasks. You can either put a simple command,
+    // a closure which receives a $task object, or the name of a class extending
+    // the Rocketeer\Abstracts\AbstractTask class
+    //
+    // In the `custom` array you can list custom Tasks classes to be added
+    // to Rocketeer. Those will then be available in the command line
+    // with all the other tasks
+    //////////////////////////////////////////////////////////////////////
+
+    // Tasks to execute before the core Rocketeer Tasks
+    'before' => [
+        'setup'   => [],
+        'deploy'  => [],
+        'cleanup' => [],
+    ],
+
+    // Tasks to execute after the core Rocketeer Tasks
+    'after'  => [
+        'setup'   => [],
+        'deploy'  => [
+            'composer dumpautoload',
+            'php artisan route:clear',
+            'chmod -R 777 bootstrap',
+            'chmod -R 777 storage',
+            'chmod -R 777 public'
+        ],
+        'cleanup' => [],
+    ],
+
+    // Custom Tasks to register with Rocketeer
+    'custom' => [],
+
+];

+ 24 - 0
.rocketeer/paths.php

@@ -0,0 +1,24 @@
+<?php
+
+return [
+
+    // Configurable paths
+    //
+    // Here you can manually set paths to some commands Rocketeer
+    // might try to use, if you leave those empty it will try to find them
+    // manually or assume they're in the root folder
+    //
+    // You can also add in this file custom paths for any command or binary
+    // Rocketeer might go looking for
+    ////////////////////////////////////////////////////////////////////
+
+    // Path to the PHP binary
+    'php'      => '/usr/local/php/bin/php',
+
+    // Path to Composer
+    'composer' => '/usr/local/bin/composer',
+
+    // Path to the Artisan CLI
+    'artisan'  => 'artisan',
+
+];

+ 80 - 0
.rocketeer/remote.php

@@ -0,0 +1,80 @@
+<?php
+
+return [
+
+    // Remote server
+    //////////////////////////////////////////////////////////////////////
+
+    // Variables about the servers. Those can be guessed but in
+    // case of problem it's best to input those manually
+    'variables'      => [
+        'directory_separator' => '/',
+        'line_endings'        => "\n",
+    ],
+
+    // The number of releases to keep at all times
+    'keep_releases'  => 4,
+
+    // Folders
+    ////////////////////////////////////////////////////////////////////
+
+    // The root directory where your applications will be deployed
+    // This path *needs* to start at the root, ie. start with a /
+    'root_directory' => '/data/wwwroot/beta',
+
+    // The folder the application will be cloned in
+    // Leave empty to use `application_name` as your folder name
+    'app_directory'  => '',
+
+    // A list of folders/file to be shared between releases
+    // Use this to list folders that need to keep their state, like
+    // user uploaded data, file-based databases, etc.
+    'shared'         => [
+        'storage',
+        'vendor',
+        '.env',
+    ],
+
+    // Execution
+    //////////////////////////////////////////////////////////////////////
+
+    // If enabled will force a shell to be created
+    // which is required for some tools like RVM or NVM
+    'shell'          => false,
+
+    // An array of commands to run under shell
+    'shelled'        => ['which', 'ruby', 'npm', 'bower', 'bundle', 'grunt'],
+
+    // Enable use of sudo for some commands
+    // You can specify a sudo user by doing
+    // 'sudo' => 'the_user'
+    'sudo' => false,
+
+    // An array of commands to run under sudo
+    'sudoed' => [],
+
+    // Permissions$
+    ////////////////////////////////////////////////////////////////////
+
+    'permissions'    => [
+
+        // The folders and files to set as web writable
+        'files'    => [
+            'bootstrap/cache',
+            'storage',
+        ],
+
+        // Here you can configure what actions will be executed to set
+        // permissions on the folder above. The Closure can return
+        // a single command as a string or an array of commands
+        'callback' => function ($task, $file) {
+            return [
+                sprintf('chmod -R 777 %s', $file),
+                sprintf('chmod -R g+s %s', $file),
+                sprintf('chown -R www:www %s', $file),
+            ];
+        },
+
+    ],
+
+];

+ 35 - 0
.rocketeer/scm.php

@@ -0,0 +1,35 @@
+<?php
+
+return [
+
+    // SCM repository
+    //////////////////////////////////////////////////////////////////////
+
+    // The SCM used (supported: "git", "svn")
+    'scm'        => 'git',
+
+    // The SSH/HTTPS address to your repository
+    // Example: https://github.com/vendor/website.git
+    'repository' => 'http://caihongxingqiu:Ch20151002@git.caihongxingqiu.net/rainbow/order-manage.git',
+
+    // The repository credentials : you can leave those empty
+    // if you're using SSH or if your repository is public
+    // In other cases you can leave this empty too, and you will
+    // be prompted for the credentials on deploy. If you don't want
+    // to be prompted (public repo, etc) set the values to null
+    'username'   => 'null',
+    'password'   => 'null',
+
+    // The branch to deploy
+    'branch'     => 'master',
+
+    // Whether your SCM should do a "shallow" clone of the repository
+    // or not – this means a clone with just the latest state of your
+    // application (no history)
+    // If you're having problems cloning, try setting this to false
+    'shallow'    => true,
+
+    // Recursively pull in submodules. Works only with GIT.
+    'submodules' => true,
+
+];

+ 19 - 0
.rocketeer/stages.php

@@ -0,0 +1,19 @@
+<?php
+
+return [
+
+    // Stages
+    //
+    // The multiples stages of your application
+    // if you don't know what this does, then you don't need it
+    //////////////////////////////////////////////////////////////////////
+
+    // Adding entries to this array will split the remote folder in stages
+    // Like /var/www/yourapp/staging and /var/www/yourapp/production
+    'stages'  => [],
+
+    // The default stage to execute tasks on when --stage is not provided
+    // Falsey means all of them
+    'default' => '',
+
+];

+ 61 - 0
.rocketeer/strategies.php

@@ -0,0 +1,61 @@
+<?php
+
+/*
+ * This file is part of Rocketeer
+ *
+ * (c) Maxime Fabre <ehtnam6@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+use Rocketeer\Binaries\PackageManagers\Composer;
+use Rocketeer\Tasks\Subtasks\Primer;
+
+return [
+
+    // Task strategies
+    //
+    // Here you can configure in a modular way which tasks to use to
+    // execute various core parts of your deployment's flow
+    //////////////////////////////////////////////////////////////////////
+
+    // Which strategy to use to check the server
+    'check'        => 'Php',
+
+    // Which strategy to use to create a new release
+    'deploy'       => 'Clone',
+
+    // Which strategy to use to test your application
+    'test'         => 'Phpunit',
+
+    // Which strategy to use to migrate your database
+    'migrate'      => 'Artisan',
+
+    // Which strategy to use to install your application's dependencies
+    'dependencies' => 'Composer',
+
+    // Execution hooks
+    //////////////////////////////////////////////////////////////////////
+
+    'composer'     => [
+        'install' => function (Composer $composer, $task) {
+            return $composer->install([], ['--no-interaction' => null, '--prefer-dist' => null]);
+        },
+        'update'  => function (Composer $composer) {
+            return $composer->update();
+        },
+    ],
+
+    // Here you can configure the Primer tasks
+    // which will run a set of commands on the local
+    // machine, determining whether the deploy can proceed
+    // or not
+    'primer'       => function (Primer $task) {
+        return [
+            // $task->executeTask('Test'),
+            // $task->binary('grunt')->execute('lint'),
+        ];
+    },
+
+];

+ 0 - 0
app/Console/Commands/.gitkeep


+ 86 - 0
app/Console/Commands/apollo.php

@@ -0,0 +1,86 @@
+<?php
+
+namespace App\Console\Commands;
+
+use Illuminate\Console\Command;
+use Illuminate\Support\Facades\Log;
+use Org\Multilinguals\Apollo\Client\ApolloClient;
+
+class Apollo extends Command
+{
+    /**
+     * The name and signature of the console command.
+     *
+     * @var string
+     */
+    protected $signature = 'apollo';
+
+    /**
+     * The console command description.
+     *
+     * @var string
+     */
+    protected $description = 'Apollo配置服务';
+
+
+    private $apollo;
+
+    /**
+     * Create a new command instance.
+     *
+     * @return void
+     */
+    public function __construct()
+    {
+        parent::__construct();
+
+        $this->save_dir = storage_path('apollo');
+        $this->config_tpl = config_path() . '/customer.tpl';
+        $this->config_file = config_path() . '/customer.php';
+
+        $this->apollo = new ApolloClient(
+            config('apollo.config_server'),
+            config('apollo.app_id'),
+            config('apollo.namespaces')
+        );
+        $this->apollo->save_dir = $this->save_dir;
+        if(!is_dir($this->save_dir)){
+            mkdir($this->save_dir);
+        }
+    }
+
+    /**
+     * Execute the console command.
+     *
+     * @return mixed
+     */
+    public function handle()
+    {
+        $this->line('apollo配置服务开启');
+        $restart = true; //失败自动重启
+        do {
+            $error = $this->apollo->start(function () {
+                $list = glob($this->save_dir . DIRECTORY_SEPARATOR . 'apolloConfig.*');
+                $apollo = [];
+                foreach ($list as $l) {
+                    $config = require $l;
+                    if (is_array($config) && isset($config['configurations'])) {
+                        $apollo = array_merge($apollo, $config['configurations']);
+                    }
+                }
+                if (!$apollo) {
+                    Log::error('Load Apollo Config Failed, no config available');
+                }
+                $tpl = file_get_contents($this->config_tpl);
+                foreach ($apollo as $key =>$value){
+                    $tpl = str_replace('{'.$key.'}',$value,$tpl);
+                }
+                file_put_contents($this->config_file,$tpl);
+            }); //此处传入回调
+            if ($error) {
+                Log::info("Apollo Hand error :" . $error);
+            }
+            sleep(60);
+        } while ($error && $restart);
+    }
+}

+ 30 - 0
app/Console/Kernel.php

@@ -0,0 +1,30 @@
+<?php
+
+namespace App\Console;
+
+use App\Console\Commands\Apollo;
+use Illuminate\Console\Scheduling\Schedule;
+use Laravel\Lumen\Console\Kernel as ConsoleKernel;
+
+class Kernel extends ConsoleKernel
+{
+    /**
+     * The Artisan commands provided by your application.
+     *
+     * @var array
+     */
+    protected $commands = [
+        Apollo::class
+    ];
+
+    /**
+     * Define the application's command schedule.
+     *
+     * @param  \Illuminate\Console\Scheduling\Schedule  $schedule
+     * @return void
+     */
+    protected function schedule(Schedule $schedule)
+    {
+        //
+    }
+}

+ 10 - 0
app/Events/Event.php

@@ -0,0 +1,10 @@
+<?php
+
+namespace App\Events;
+
+use Illuminate\Queue\SerializesModels;
+
+abstract class Event
+{
+    use SerializesModels;
+}

+ 16 - 0
app/Events/ExampleEvent.php

@@ -0,0 +1,16 @@
+<?php
+
+namespace App\Events;
+
+class ExampleEvent extends Event
+{
+    /**
+     * Create a new event instance.
+     *
+     * @return void
+     */
+    public function __construct()
+    {
+        //
+    }
+}

+ 50 - 0
app/Exceptions/Handler.php

@@ -0,0 +1,50 @@
+<?php
+
+namespace App\Exceptions;
+
+use Exception;
+use Illuminate\Validation\ValidationException;
+use Illuminate\Auth\Access\AuthorizationException;
+use Illuminate\Database\Eloquent\ModelNotFoundException;
+use Laravel\Lumen\Exceptions\Handler as ExceptionHandler;
+use Symfony\Component\HttpKernel\Exception\HttpException;
+
+class Handler extends ExceptionHandler
+{
+    /**
+     * A list of the exception types that should not be reported.
+     *
+     * @var array
+     */
+    protected $dontReport = [
+        AuthorizationException::class,
+        HttpException::class,
+        ModelNotFoundException::class,
+        ValidationException::class,
+    ];
+
+    /**
+     * Report or log an exception.
+     *
+     * This is a great spot to send exceptions to Sentry, Bugsnag, etc.
+     *
+     * @param  \Exception  $exception
+     * @return void
+     */
+    public function report(Exception $exception)
+    {
+        parent::report($exception);
+    }
+
+    /**
+     * Render an exception into an HTTP response.
+     *
+     * @param  \Illuminate\Http\Request  $request
+     * @param  \Exception  $exception
+     * @return \Illuminate\Http\Response|\Illuminate\Http\JsonResponse
+     */
+    public function render($request, Exception $exception)
+    {
+        return parent::render($request, $exception);
+    }
+}

+ 18 - 0
app/Helper/helper.php

@@ -0,0 +1,18 @@
+<?php
+/**
+ * 添加自定义辅助函数
+ */
+
+if ( ! function_exists('config_path'))
+{
+    /**
+     * Get the configuration path.
+     *
+     * @param string $path
+     * @return string
+     */
+    function config_path($path = '')
+    {
+        return app()->basePath() . '/config' . ($path ? '/' . $path : $path);
+    }
+}

+ 10 - 0
app/Http/Controllers/Controller.php

@@ -0,0 +1,10 @@
+<?php
+
+namespace App\Http\Controllers;
+
+use Illuminate\Routing\Controller as BaseController;
+
+class Controller extends BaseController
+{
+
+}

+ 12 - 0
app/Http/Controllers/V1/Controller.php

@@ -0,0 +1,12 @@
+<?php
+
+namespace App\Http\Controllers\V1;
+
+
+use Dingo\Api\Routing\Helpers;
+use App\Http\Controllers\Controller as BaseController;
+
+class Controller extends BaseController
+{
+    use Helpers;
+}

+ 18 - 0
app/Http/Controllers/V1/TestController.php

@@ -0,0 +1,18 @@
+<?php
+/**
+ * Created by PhpStorm.
+ * User: Administrator
+ * Date: 2019/6/3
+ * Time: 14:36
+ */
+
+namespace App\Http\Controllers\V1;
+
+
+class TestController extends Controller
+{
+    public function index()
+    {
+        return 123;
+    }
+}

+ 48 - 0
app/Http/Middleware/Authenticate.php

@@ -0,0 +1,48 @@
+<?php
+
+namespace App\Http\Middleware;
+
+use Closure;
+use Illuminate\Contracts\Auth\Factory as Auth;
+
+class Authenticate
+{
+    /**
+     * The authentication guard factory instance.
+     *
+     * @var \Illuminate\Contracts\Auth\Factory
+     */
+    protected $auth;
+
+    /**
+     * Create a new middleware instance.
+     *
+     * @param  \Illuminate\Contracts\Auth\Factory  $auth
+     * @return void
+     */
+    public function __construct(Auth $auth)
+    {
+        $this->auth = $auth;
+    }
+
+    /**
+     * Handle an incoming request.
+     *
+     * @param  \Illuminate\Http\Request  $request
+     * @param  \Closure  $next
+     * @param  string|null  $guard
+     * @return mixed
+     */
+    public function handle($request, Closure $next, $guard = null)
+    {
+        if ($this->auth->guard($guard)->guest()) {
+            $error = [
+                'message' => '请重新登录',
+                'code' => 401,
+            ];
+            return response()->json($error);
+        }
+
+        return $next($request);
+    }
+}

+ 20 - 0
app/Http/Middleware/ExampleMiddleware.php

@@ -0,0 +1,20 @@
+<?php
+
+namespace App\Http\Middleware;
+
+use Closure;
+
+class ExampleMiddleware
+{
+    /**
+     * Handle an incoming request.
+     *
+     * @param  \Illuminate\Http\Request  $request
+     * @param  \Closure  $next
+     * @return mixed
+     */
+    public function handle($request, Closure $next)
+    {
+        return $next($request);
+    }
+}

+ 61 - 0
app/Http/Middleware/JwtAuthMiddleware.php

@@ -0,0 +1,61 @@
+<?php
+
+namespace App\Http\Middleware;
+
+use Closure;
+use Tymon\JWTAuth\Exceptions\JWTException;
+use Tymon\JWTAuth\Exceptions\TokenExpiredException;
+use Tymon\JWTAuth\Exceptions\TokenInvalidException;
+use Tymon\JWTAuth\Facades\JWTAuth;
+use Tymon\JWTAuth\Http\Middleware\BaseMiddleware;
+
+class JwtAuthMiddleware
+{
+    /**
+     * Handle an incoming request.
+     *
+     * @param  \Illuminate\Http\Request $request
+     * @param  \Closure $next
+     * @return mixed
+     */
+    public function handle($request, Closure $next)
+    {
+
+        try {
+            $token = JWTAuth::getToken();
+            if(empty($token)){
+                $error = [
+                    'message' => 'token is required',
+                    'code' => 401,
+                ];
+                return response()->json($error);
+            }
+            $data = JWTAuth::decode($token);
+        } catch (TokenExpiredException $e) {
+            $error = [
+                'message' => 'Token is Expired',
+                'code' => 401,
+            ];
+            return response()->json($error);
+        } catch (TokenInvalidException $e) {
+            $error = [
+                'message' => $e->getMessage(),
+                'code' => 401,
+            ];
+            return response()->json($error);
+        } catch (JWTException $e) {
+            $error = [
+                'message' => $e->getMessage(),
+                'code' => 401,
+            ];
+            return response()->json($error);
+        }catch (\Exception $e){
+            $error = [
+                'message' => $e->getMessage(),
+                'code' => 401,
+            ];
+            return response()->json($error);
+        }
+        return $next($request);
+    }
+}

+ 26 - 0
app/Jobs/ExampleJob.php

@@ -0,0 +1,26 @@
+<?php
+
+namespace App\Jobs;
+
+class ExampleJob extends Job
+{
+    /**
+     * Create a new job instance.
+     *
+     * @return void
+     */
+    public function __construct()
+    {
+        //
+    }
+
+    /**
+     * Execute the job.
+     *
+     * @return void
+     */
+    public function handle()
+    {
+        //
+    }
+}

+ 24 - 0
app/Jobs/Job.php

@@ -0,0 +1,24 @@
+<?php
+
+namespace App\Jobs;
+
+use Illuminate\Bus\Queueable;
+use Illuminate\Queue\SerializesModels;
+use Illuminate\Queue\InteractsWithQueue;
+use Illuminate\Contracts\Queue\ShouldQueue;
+
+abstract class Job implements ShouldQueue
+{
+    /*
+    |--------------------------------------------------------------------------
+    | Queueable Jobs
+    |--------------------------------------------------------------------------
+    |
+    | This job base class provides a central location to place any logic that
+    | is shared across all of your jobs. The trait included with the class
+    | provides access to the "queueOn" and "delay" queue helper methods.
+    |
+    */
+
+    use InteractsWithQueue, Queueable, SerializesModels;
+}

+ 31 - 0
app/Listeners/ExampleListener.php

@@ -0,0 +1,31 @@
+<?php
+
+namespace App\Listeners;
+
+use App\Events\ExampleEvent;
+use Illuminate\Queue\InteractsWithQueue;
+use Illuminate\Contracts\Queue\ShouldQueue;
+
+class ExampleListener
+{
+    /**
+     * Create the event listener.
+     *
+     * @return void
+     */
+    public function __construct()
+    {
+        //
+    }
+
+    /**
+     * Handle the event.
+     *
+     * @param  ExampleEvent  $event
+     * @return void
+     */
+    public function handle(ExampleEvent $event)
+    {
+        //
+    }
+}

+ 18 - 0
app/Providers/AppServiceProvider.php

@@ -0,0 +1,18 @@
+<?php
+
+namespace App\Providers;
+
+use Illuminate\Support\ServiceProvider;
+
+class AppServiceProvider extends ServiceProvider
+{
+    /**
+     * Register any application services.
+     *
+     * @return void
+     */
+    public function register()
+    {
+        //
+    }
+}

+ 39 - 0
app/Providers/AuthServiceProvider.php

@@ -0,0 +1,39 @@
+<?php
+
+namespace App\Providers;
+
+use App\User;
+use Illuminate\Support\Facades\Gate;
+use Illuminate\Support\ServiceProvider;
+
+class AuthServiceProvider extends ServiceProvider
+{
+    /**
+     * Register any application services.
+     *
+     * @return void
+     */
+    public function register()
+    {
+        //
+    }
+
+    /**
+     * Boot the authentication services for the application.
+     *
+     * @return void
+     */
+    public function boot()
+    {
+        // Here you may define how you wish users to be authenticated for your Lumen
+        // application. The callback which receives the incoming request instance
+        // should return either a User instance or null. You're free to obtain
+        // the User instance via an API token or any other method necessary.
+
+        $this->app['auth']->viaRequest('api', function ($request) {
+            if ($request->input('api_token')) {
+                return User::where('api_token', $request->input('api_token'))->first();
+            }
+        });
+    }
+}

+ 19 - 0
app/Providers/EventServiceProvider.php

@@ -0,0 +1,19 @@
+<?php
+
+namespace App\Providers;
+
+use Laravel\Lumen\Providers\EventServiceProvider as ServiceProvider;
+
+class EventServiceProvider extends ServiceProvider
+{
+    /**
+     * The event listener mappings for the application.
+     *
+     * @var array
+     */
+    protected $listen = [
+        'App\Events\ExampleEvent' => [
+            'App\Listeners\ExampleListener',
+        ],
+    ];
+}

+ 88 - 0
app/Service/RabbitMqUtil.php

@@ -0,0 +1,88 @@
+<?php
+/**
+ * Created by PhpStorm.
+ * User: edz
+ * Date: 2019-04-30
+ * Time: 17:22
+ */
+namespace App\Service;
+
+use Illuminate\Support\Facades\Log;
+use PhpAmqpLib\Connection\AMQPStreamConnection;
+use PhpAmqpLib\Message\AMQPMessage;
+
+class RabbitMqUtil
+{
+    protected $connection;
+    protected $queue;
+    protected $channel;
+    public function __construct()
+    {
+        $this->connection = $this->getConnection();
+        $this->channel = $this->connection->channel();
+    }
+
+    public function getConnection()
+    {
+        $conn = false;
+        if ($this->connection) {
+            return $this->connection;
+        }
+        for ($i = 0; $i < 3; $i++) {
+            $connection = $this->createConn();
+            if ($connection) {
+                $conn = $connection;
+                break;
+            }
+            Log::info("create amqp conn retry=" . $i);
+        }
+        return $conn;
+    }
+
+    public function createConn()
+    {
+        try {
+            $connection = new AMQPStreamConnection(env('MQ_HOST'), env('MQ_PORT'), env('MQ_USERNAME'), env('MQ_PWD'), env('MQ_VHOST'));
+        } catch (\Exception $exception) {
+            Log::info("AMQP connection Error" . $exception->getMessage());
+            $connection = false;
+        }
+        return $connection;
+    }
+
+    /**
+     * 生产消息-分布式任务模式(Work queues)
+     * @param $queue
+     * @param $data
+     */
+    public function push($queue,$data){
+        $this->channel->queue_declare($queue, false, true, false, false);
+        $msg = new AMQPMessage(
+            \GuzzleHttp\json_encode($data),
+            array('delivery_mode' => AMQPMessage::DELIVERY_MODE_PERSISTENT)
+        );
+        return $this->channel->basic_publish($msg, '', $queue);
+    }
+
+    /**
+     * 生产消息-发布订阅模式(Publish/Subscribe)
+     *
+     * @param $queue
+     * @param $data
+     */
+    public function publish($queue,$data){
+        $this->channel->exchange_declare($queue, 'fanout', false, true, false);
+        $msg = new AMQPMessage(
+            \GuzzleHttp\json_encode($data),
+            array('delivery_mode' => AMQPMessage::DELIVERY_MODE_PERSISTENT)
+        );
+        return $this->channel->basic_publish($msg, $queue);
+    }
+
+    public function __destruct()
+    {
+        // TODO: Implement __destruct() method.
+        $this->channel->close();
+        $this->connection->close();
+    }
+}

+ 35 - 0
artisan

@@ -0,0 +1,35 @@
+#!/usr/bin/env php
+<?php
+
+use Symfony\Component\Console\Input\ArgvInput;
+use Symfony\Component\Console\Output\ConsoleOutput;
+
+/*
+|--------------------------------------------------------------------------
+| Create The Application
+|--------------------------------------------------------------------------
+|
+| First we need to get an application instance. This creates an instance
+| of the application / container and bootstraps the application so it
+| is ready to receive HTTP / Console requests from the environment.
+|
+*/
+
+$app = require __DIR__.'/bootstrap/app.php';
+
+/*
+|--------------------------------------------------------------------------
+| Run The Artisan Application
+|--------------------------------------------------------------------------
+|
+| When we run the console application, the current CLI command will be
+| executed in this console and the response sent back to a terminal
+| or another output device for the developers. Here goes nothing!
+|
+*/
+
+$kernel = $app->make(
+    'Illuminate\Contracts\Console\Kernel'
+);
+
+exit($kernel->handle(new ArgvInput, new ConsoleOutput));

+ 26 - 0
bin/fswatch

@@ -0,0 +1,26 @@
+#!/usr/bin/env bash
+WORK_DIR=$1
+if [ ! -n "${WORK_DIR}" ] ;then
+    WORK_DIR="."
+fi
+
+echo "Restarting LaravelS..."
+./bin/laravels restart -d -i
+
+echo "Starting fswatch..."
+LOCKING=0
+fswatch -e ".*" -i "\\.php$" -m poll_monitor -r ${WORK_DIR} | while read file
+do
+    if [[ ! ${file} =~ .php$ ]] ;then
+        continue
+    fi
+    if [ ${LOCKING} -eq 1 ] ;then
+        echo "Reloading, skipped."
+        continue
+    fi
+    echo "File ${file} has been modified."
+    LOCKING=1
+    ./bin/laravels reload
+    LOCKING=0
+done
+exit 0

+ 11 - 0
bin/laravels

@@ -0,0 +1,11 @@
+#!/usr/bin/env php
+<?php
+$basePath = realpath(__DIR__ . '/../');
+include $basePath . '/vendor/autoload.php';
+
+$command = new Hhxsv5\LaravelS\Console\Portal($basePath);
+$input = new Symfony\Component\Console\Input\ArgvInput();
+$output = new Symfony\Component\Console\Output\ConsoleOutput();
+
+$code = $command->run($input, $output);
+exit($code);

+ 110 - 0
bootstrap/app.php

@@ -0,0 +1,110 @@
+<?php
+
+require_once __DIR__.'/../vendor/autoload.php';
+
+(new Laravel\Lumen\Bootstrap\LoadEnvironmentVariables(
+    dirname(__DIR__)
+))->bootstrap();
+
+/*
+|--------------------------------------------------------------------------
+| Create The Application
+|--------------------------------------------------------------------------
+|
+| Here we will load the environment and create the application instance
+| that serves as the central piece of this framework. We'll use this
+| application as an "IoC" container and router for this framework.
+|
+*/
+
+$app = new Laravel\Lumen\Application(
+    dirname(__DIR__)
+);
+
+$app->withFacades();
+
+$app->withEloquent();
+$app->configure('api');
+$app->configure('apollo');
+$app->configure('auth');
+$app->configure('jwt');
+$app->configure('customer');
+$app->configure('database');
+
+/*
+|--------------------------------------------------------------------------
+| Register Container Bindings
+|--------------------------------------------------------------------------
+|
+| Now we will register a few bindings in the service container. We will
+| register the exception handler and the console kernel. You may add
+| your own bindings here if you like or you can make another file.
+|
+*/
+
+$app->singleton(
+    Illuminate\Contracts\Debug\ExceptionHandler::class,
+    App\Exceptions\Handler::class
+);
+
+$app->singleton(
+    Illuminate\Contracts\Console\Kernel::class,
+    App\Console\Kernel::class
+);
+
+/*
+|--------------------------------------------------------------------------
+| Register Middleware
+|--------------------------------------------------------------------------
+|
+| Next, we will register the middleware with the application. These can
+| be global middleware that run before and after each request into a
+| route or middleware that'll be assigned to some specific routes.
+|
+*/
+
+// $app->middleware([
+//     App\Http\Middleware\ExampleMiddleware::class
+// ]);
+
+$app->routeMiddleware([
+    'auth' => App\Http\Middleware\Authenticate::class,
+    'jwt.chxq_auth' => App\Http\Middleware\JwtAuthMiddleware::class,
+]);
+
+/*
+|--------------------------------------------------------------------------
+| Register Service Providers
+|--------------------------------------------------------------------------
+|
+| Here we will register all of the application's service providers which
+| are used to bind services into the container. Service providers are
+| totally optional, so you are not required to uncomment this line.
+|
+*/
+
+$app->register(App\Providers\AppServiceProvider::class);
+$app->register(App\Providers\AuthServiceProvider::class);
+
+$app->register(Dingo\Api\Provider\LumenServiceProvider::class);
+$app->register(Tymon\JWTAuth\Providers\LumenServiceProvider::class);
+/*
+|--------------------------------------------------------------------------
+| Load The Application Routes
+|--------------------------------------------------------------------------
+|
+| Next we will include the routes file so that they can all be added to
+| the application. This will provide all of the URLs the application
+| can respond to, as well as the controllers that may handle them.
+|
+*/
+
+$app->router->group([
+    'namespace' => 'App\Http\Controllers',
+], function ($router) {
+    require __DIR__.'/../routes/api.php';
+    require __DIR__.'/../routes/web.php';
+});
+
+$app->register(Hhxsv5\LaravelS\Illuminate\LaravelSServiceProvider::class);
+return $app;

+ 59 - 0
composer.json

@@ -0,0 +1,59 @@
+{
+    "name": "laravel/lumen",
+    "description": "The Laravel Lumen Framework.",
+    "keywords": ["framework", "laravel", "lumen"],
+    "license": "MIT",
+    "type": "project",
+    "require": {
+        "php": ">=7.1.3",
+        "dingo/api": "^2.2",
+        "guzzlehttp/guzzle": "^6.3",
+        "cviebrock/laravel-elasticsearch": "^3.5",
+        "php-amqplib/php-amqplib": "^2.9",
+        "hhxsv5/laravel-s": "~3.4.0",
+        "laravel/lumen-framework": "5.8.*",
+        "vlucas/phpdotenv": "^3.3",
+        "multilinguals/apollo-client": "^0.1.2",
+        "tymon/jwt-auth": "1.0.0-rc.4.1"
+    },
+    "require-dev": {
+        "fzaninotto/faker": "^1.4",
+        "phpunit/phpunit": "^7.0",
+        "mockery/mockery": "^1.0"
+    },
+    "autoload": {
+        "classmap": [
+            "database/seeds",
+            "database/factories"
+        ],
+        "psr-4": {
+            "App\\": "app/"
+        },
+        "files": [
+            "app/Helper/helper.php"
+        ]
+    },
+    "autoload-dev": {
+        "classmap": [
+            "tests/"
+        ]
+    },
+    "scripts": {
+        "post-root-package-install": [
+            "@php -r \"file_exists('.env') || copy('.env.example', '.env');\""
+        ]
+    },
+    "config": {
+        "preferred-install": "dist",
+        "sort-packages": true,
+        "optimize-autoloader": true
+    },
+    "minimum-stability": "dev",
+    "prefer-stable": true,
+    "repositories": {
+        "packagist": {
+            "type": "composer",
+            "url": "https://packagist.laravel-china.org"
+        }
+    }
+}

+ 232 - 0
config/api.php

@@ -0,0 +1,232 @@
+<?php
+
+return [
+
+    /*
+    |--------------------------------------------------------------------------
+    | Standards Tree
+    |--------------------------------------------------------------------------
+    |
+    | Versioning an API with Dingo revolves around content negotiation and
+    | custom MIME types. A custom type will belong to one of three
+    | standards trees, the Vendor tree (vnd), the Personal tree
+    | (prs), and the Unregistered tree (x).
+    |
+    | By default the Unregistered tree (x) is used, however, should you wish
+    | to you can register your type with the IANA. For more details:
+    | https://tools.ietf.org/html/rfc6838
+    |
+    */
+
+    'standardsTree' => env('API_STANDARDS_TREE', 'x'),
+
+    /*
+    |--------------------------------------------------------------------------
+    | API Subtype
+    |--------------------------------------------------------------------------
+    |
+    | Your subtype will follow the standards tree you use when used in the
+    | "Accept" header to negotiate the content type and version.
+    |
+    | For example: Accept: application/x.SUBTYPE.v1+json
+    |
+    */
+
+    'subtype' => env('API_SUBTYPE', ''),
+
+    /*
+    |--------------------------------------------------------------------------
+    | Default API Version
+    |--------------------------------------------------------------------------
+    |
+    | This is the default version when strict mode is disabled and your API
+    | is accessed via a web browser. It's also used as the default version
+    | when generating your APIs documentation.
+    |
+    */
+
+    'version' => env('API_VERSION', 'v1'),
+
+    /*
+    |--------------------------------------------------------------------------
+    | Default API Prefix
+    |--------------------------------------------------------------------------
+    |
+    | A default prefix to use for your API routes so you don't have to
+    | specify it for each group.
+    |
+    */
+
+    'prefix' => env('API_PREFIX', '/'),
+
+    /*
+    |--------------------------------------------------------------------------
+    | Default API Domain
+    |--------------------------------------------------------------------------
+    |
+    | A default domain to use for your API routes so you don't have to
+    | specify it for each group.
+    |
+    */
+
+    'domain' => env('API_DOMAIN', null),
+
+    /*
+    |--------------------------------------------------------------------------
+    | Name
+    |--------------------------------------------------------------------------
+    |
+    | When documenting your API using the API Blueprint syntax you can
+    | configure a default name to avoid having to manually specify
+    | one when using the command.
+    |
+    */
+
+    'name' => env('API_NAME', null),
+
+    /*
+    |--------------------------------------------------------------------------
+    | Conditional Requests
+    |--------------------------------------------------------------------------
+    |
+    | Globally enable conditional requests so that an ETag header is added to
+    | any successful response. Subsequent requests will perform a check and
+    | will return a 304 Not Modified. This can also be enabled or disabled
+    | on certain groups or routes.
+    |
+    */
+
+    'conditionalRequest' => env('API_CONDITIONAL_REQUEST', true),
+
+    /*
+    |--------------------------------------------------------------------------
+    | Strict Mode
+    |--------------------------------------------------------------------------
+    |
+    | Enabling strict mode will require clients to send a valid Accept header
+    | with every request. This also voids the default API version, meaning
+    | your API will not be browsable via a web browser.
+    |
+    */
+
+    'strict' => env('API_STRICT', false),
+
+    /*
+    |--------------------------------------------------------------------------
+    | Debug Mode
+    |--------------------------------------------------------------------------
+    |
+    | Enabling debug mode will result in error responses caused by thrown
+    | exceptions to have a "debug" key that will be populated with
+    | more detailed information on the exception.
+    |
+    */
+
+    'debug' => env('API_DEBUG', true),
+
+    /*
+    |--------------------------------------------------------------------------
+    | Generic Error Format
+    |--------------------------------------------------------------------------
+    |
+    | When some HTTP exceptions are not caught and dealt with the API will
+    | generate a generic error response in the format provided. Any
+    | keys that aren't replaced with corresponding values will be
+    | removed from the final response.
+    |
+    */
+
+    'errorFormat' => [
+        'message' => ':message',
+        'errors' => ':errors',
+        'code' => ':code',
+        'status_code' => ':status_code',
+        'debug' => ':debug',
+    ],
+
+    /*
+    |--------------------------------------------------------------------------
+    | API Middleware
+    |--------------------------------------------------------------------------
+    |
+    | Middleware that will be applied globally to all API requests.
+    |
+    */
+
+    'middleware' => [
+
+    ],
+
+    /*
+    |--------------------------------------------------------------------------
+    | Authentication Providers
+    |--------------------------------------------------------------------------
+    |
+    | The authentication providers that should be used when attempting to
+    | authenticate an incoming API request.
+    |
+    */
+
+    'auth' => [
+        'jwt' => 'Dingo\Api\Auth\Provider\JWT',
+    ],
+
+    /*
+    |--------------------------------------------------------------------------
+    | Throttling / Rate Limiting
+    |--------------------------------------------------------------------------
+    |
+    | Consumers of your API can be limited to the amount of requests they can
+    | make. You can create your own throttles or simply change the default
+    | throttles.
+    |
+    */
+
+    'throttling' => [
+
+    ],
+
+    /*
+    |--------------------------------------------------------------------------
+    | Response Transformer
+    |--------------------------------------------------------------------------
+    |
+    | Responses can be transformed so that they are easier to format. By
+    | default a Fractal transformer will be used to transform any
+    | responses prior to formatting. You can easily replace
+    | this with your own transformer.
+    |
+    */
+
+    'transformer' => env('API_TRANSFORMER', Dingo\Api\Transformer\Adapter\Fractal::class),
+
+    /*
+    |--------------------------------------------------------------------------
+    | Response Formats
+    |--------------------------------------------------------------------------
+    |
+    | Responses can be returned in multiple formats by registering different
+    | response formatters. You can also customize an existing response
+    | formatter with a number of options to configure its output.
+    |
+    */
+
+    'defaultFormat' => env('API_DEFAULT_FORMAT', 'json'),
+
+    'formats' => [
+
+        'json' => Dingo\Api\Http\Response\Format\Json::class,
+
+    ],
+
+    'formatsOptions' => [
+
+        'json' => [
+            'pretty_print' => env('API_JSON_FORMAT_PRETTY_PRINT_ENABLED', false),
+            'indent_style' => env('API_JSON_FORMAT_INDENT_STYLE', 'space'),
+            'indent_size' => env('API_JSON_FORMAT_INDENT_SIZE', 2),
+        ],
+
+    ],
+
+];

+ 10 - 0
config/apollo.php

@@ -0,0 +1,10 @@
+<?php
+
+return [
+    'namespaces' => explode(',', env('APOLLO_NAMESPACES')),
+    'cluster' => env('APOLLO_CLUSTER'),
+    'save_dir' => storage_path('apollo'),
+    'config_server' => env('APOLLO_CONFIG_SERVER'),
+    'app_id' => env('APP_ID'),
+    'timeout_interval' => 70
+];

+ 90 - 0
config/auth.php

@@ -0,0 +1,90 @@
+<?php
+
+return [
+
+    /*
+    |--------------------------------------------------------------------------
+    | Authentication Defaults
+    |--------------------------------------------------------------------------
+    |
+    | This option controls the default authentication "guard" and password
+    | reset options for your application. You may change these defaults
+    | as required, but they're a perfect start for most applications.
+    |
+    */
+
+    'defaults' => [
+        'guard' => env('AUTH_GUARD', 'api'),
+        'passwords'=>'users',
+    ],
+
+    /*
+    |--------------------------------------------------------------------------
+    | Authentication Guards
+    |--------------------------------------------------------------------------
+    |
+    | Next, you may define every authentication guard for your application.
+    | Of course, a great default configuration has been defined for you
+    | here which uses session storage and the Eloquent user provider.
+    |
+    | All authentication drivers have a user provider. This defines how the
+    | users are actually retrieved out of your database or other storage
+    | mechanisms used by this application to persist your user's data.
+    |
+    | Supported: "token"
+    |
+    */
+
+    'guards' => [
+        'api' => ['driver' => 'jwt','provider' => 'users',],
+    ],
+
+    /*
+    |--------------------------------------------------------------------------
+    | User Providers
+    |--------------------------------------------------------------------------
+    |
+    | All authentication drivers have a user provider. This defines how the
+    | users are actually retrieved out of your database or other storage
+    | mechanisms used by this application to persist your user's data.
+    |
+    | If you have multiple user tables or models you may configure multiple
+    | sources which represent each model / table. These sources may then
+    | be assigned to any extra authentication guards you have defined.
+    |
+    | Supported: "database", "eloquent"
+    |
+    */
+
+    'providers' => [
+        //
+        'users' => [
+            'driver' => 'eloquent',
+            'model' => App\User::class,
+        ],
+    ],
+
+    /*
+    |--------------------------------------------------------------------------
+    | Resetting Passwords
+    |--------------------------------------------------------------------------
+    |
+    | Here you may set the options for resetting passwords including the view
+    | that is your password reset e-mail. You may also set the name of the
+    | table that maintains all of the reset tokens for your application.
+    |
+    | You may specify multiple password reset configurations if you have more
+    | than one user table or model in the application and you want to have
+    | separate password reset settings based on the specific user types.
+    |
+    | The expire time is the number of minutes that the reset token should be
+    | considered valid. This security feature keeps tokens short-lived so
+    | they have less time to be guessed. You may change this as needed.
+    |
+    */
+
+    'passwords' => [
+        //
+    ],
+
+];

+ 6 - 0
config/customer.tpl

@@ -0,0 +1,6 @@
+<?php
+//此文件为apollo配置文件模板,禁止修改移动
+return [
+    'jwt_secret' => '{jwt_secret}',
+    'manage_service_url' => '{manage_service_url}',
+];

+ 131 - 0
config/database.php

@@ -0,0 +1,131 @@
+<?php
+
+return [
+
+    /*
+    |--------------------------------------------------------------------------
+    | Default Database Connection Name
+    |--------------------------------------------------------------------------
+    |
+    | Here you may specify which of the database connections below you wish
+    | to use as your default connection for all database work. Of course
+    | you may use many connections at once using the Database library.
+    |
+    */
+
+    'default' => env('DB_CONNECTION', 'mysql'),
+
+    /*
+    |--------------------------------------------------------------------------
+    | Database Connections
+    |--------------------------------------------------------------------------
+    |
+    | Here are each of the database connections setup for your application.
+    | Of course, examples of configuring each database platform that is
+    | supported by Laravel is shown below to make development simple.
+    |
+    |
+    | All database work in Laravel is done through the PHP PDO facilities
+    | so make sure you have the driver for your particular database of
+    | choice installed on your machine before you begin development.
+    |
+    */
+
+    'connections' => [
+
+        'sqlite' => [
+            'driver' => 'sqlite',
+            'database' => env('DB_DATABASE', database_path('database.sqlite')),
+            'prefix' => env('DB_PREFIX', ''),
+        ],
+
+        'mysql' => [
+            'driver' => 'mysql',
+            'host' => env('DB_HOST', '127.0.0.1'),
+            'port' => env('DB_PORT', 3306),
+            'database' => env('DB_DATABASE', 'forge'),
+            'username' => env('DB_USERNAME', 'forge'),
+            'password' => env('DB_PASSWORD', ''),
+            'unix_socket' => env('DB_SOCKET', ''),
+            'charset' => env('DB_CHARSET', 'utf8mb4'),
+            'collation' => env('DB_COLLATION', 'utf8mb4_unicode_ci'),
+            'prefix' => env('DB_PREFIX', ''),
+            'strict' => env('DB_STRICT_MODE', true),
+            'engine' => env('DB_ENGINE', null),
+            'timezone' => env('DB_TIMEZONE', '+08:00'),
+        ],
+
+        'pgsql' => [
+            'driver' => 'pgsql',
+            'host' => env('DB_HOST', '127.0.0.1'),
+            'port' => env('DB_PORT', 5432),
+            'database' => env('DB_DATABASE', 'forge'),
+            'username' => env('DB_USERNAME', 'forge'),
+            'password' => env('DB_PASSWORD', ''),
+            'charset' => env('DB_CHARSET', 'utf8'),
+            'prefix' => env('DB_PREFIX', ''),
+            'schema' => env('DB_SCHEMA', 'public'),
+            'sslmode' => env('DB_SSL_MODE', 'prefer'),
+        ],
+
+        'sqlsrv' => [
+            'driver' => 'sqlsrv',
+            'host' => env('DB_HOST', 'localhost'),
+            'port' => env('DB_PORT', 1433),
+            'database' => env('DB_DATABASE', 'forge'),
+            'username' => env('DB_USERNAME', 'forge'),
+            'password' => env('DB_PASSWORD', ''),
+            'charset' => env('DB_CHARSET', 'utf8'),
+            'prefix' => env('DB_PREFIX', ''),
+        ],
+
+    ],
+
+    /*
+    |--------------------------------------------------------------------------
+    | Migration Repository Table
+    |--------------------------------------------------------------------------
+    |
+    | This table keeps track of all the migrations that have already run for
+    | your application. Using this information, we can determine which of
+    | the migrations on disk haven't actually been run in the database.
+    |
+    */
+
+    'migrations' => 'migrations',
+
+    /*
+    |--------------------------------------------------------------------------
+    | Redis Databases
+    |--------------------------------------------------------------------------
+    |
+    | Redis is an open source, fast, and advanced key-value store that also
+    | provides a richer set of commands than a typical key-value systems
+    | such as APC or Memcached. Laravel makes it easy to dig right in.
+    |
+    */
+
+    'redis' => [
+
+        'client' => 'predis',
+
+        'cluster' => env('REDIS_CLUSTER', false),
+
+        'default' => [
+            'host' => env('REDIS_HOST', '127.0.0.1'),
+            'password' => env('REDIS_PASSWORD', null),
+            'port' => env('REDIS_PORT', 6379),
+            'database' => env('REDIS_DB', 0),
+            'read_write_timeout' => 0,
+        ],
+
+        'cache' => [
+            'host' => env('REDIS_HOST', '127.0.0.1'),
+            'password' => env('REDIS_PASSWORD', null),
+            'port' => env('REDIS_PORT', 6379),
+            'database' => env('REDIS_CACHE_DB', 1),
+        ],
+
+    ],
+
+];

+ 304 - 0
config/jwt.php

@@ -0,0 +1,304 @@
+<?php
+
+/*
+ * This file is part of jwt-auth.
+ *
+ * (c) Sean Tymon <tymon148@gmail.com>
+ *
+ * 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',config('customer.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,
+
+    ],
+
+];

+ 79 - 0
config/laravels.php

@@ -0,0 +1,79 @@
+<?php
+/**
+ * @see https://github.com/hhxsv5/laravel-s/blob/master/Settings-CN.md  Chinese
+ * @see https://github.com/hhxsv5/laravel-s/blob/master/Settings.md  English
+ */
+return [
+    'listen_ip'                => env('LARAVELS_LISTEN_IP', '0.0.0.0'),
+    'listen_port'              => env('LARAVELS_LISTEN_PORT', 18214),
+    'socket_type'              => defined('SWOOLE_SOCK_TCP') ? SWOOLE_SOCK_TCP : 1,
+    'enable_coroutine_runtime' => false,
+    'server'                   => env('LARAVELS_SERVER', 'order-manage'),
+    'handle_static'            => env('LARAVELS_HANDLE_STATIC', false),
+    'laravel_base_path'        => env('LARAVEL_BASE_PATH', base_path()),
+    'inotify_reload'           => [
+        'enable'        => env('LARAVELS_INOTIFY_RELOAD', true),
+        'watch_path'    => base_path(),
+        'file_types'    => ['.php'],
+        'excluded_dirs' => [],
+        'log'           => true,
+    ],
+    'event_handlers'           => [],
+    'websocket'                => [
+        'enable' => false,
+        //'handler' => XxxWebSocketHandler::class,
+    ],
+    'sockets'                  => [],
+    'processes'                => [],
+    'timer'                    => [
+        'enable'        => false,
+        'jobs'          => [
+            // Enable LaravelScheduleJob to run `php artisan schedule:run` every 1 minute, replace Linux Crontab
+            //\Hhxsv5\LaravelS\Illuminate\LaravelScheduleJob::class,
+            // Two ways to configure parameters:
+            // [\App\Jobs\XxxCronJob::class, [1000, true]], // Pass in parameters when registering
+            // \App\Jobs\XxxCronJob::class, // Override the corresponding method to return the configuration
+        ],
+        'pid_file'      => storage_path('laravels-timer.pid'),
+        'max_wait_time' => 5,
+    ],
+    'events'                   => [],
+    'swoole_tables'            => [],
+    'register_providers'       => [],
+    'cleaners'                 => [
+        //Hhxsv5\LaravelS\Illuminate\Cleaners\SessionCleaner::class, // If you use the session/authentication in your project, please uncomment this line
+        //Hhxsv5\LaravelS\Illuminate\Cleaners\AuthCleaner::class,    // If you use the authentication/passport in your project, please uncomment this line
+        Hhxsv5\LaravelS\Illuminate\Cleaners\JWTCleaner::class,     // If you use the package "tymon/jwt-auth" in your project, please uncomment this line
+        // ...
+    ],
+    'swoole'                   => [
+        'daemonize'          => env('LARAVELS_DAEMONIZE', false),
+        'dispatch_mode'      => 2,
+        'reactor_num'        => function_exists('swoole_cpu_num') ? swoole_cpu_num() * 2 : 4,
+        'worker_num'         => function_exists('swoole_cpu_num') ? swoole_cpu_num() * 2 : 8,
+        //'task_worker_num'    => function_exists('swoole_cpu_num') ? swoole_cpu_num() * 2 : 8,
+        'task_ipc_mode'      => 1,
+        'task_max_request'   => 8000,
+        'task_tmpdir'        => @is_writable('/dev/shm/') ? '/dev/shm' : '/tmp',
+        'max_request'        => 8000,
+        'open_tcp_nodelay'   => true,
+        'pid_file'           => storage_path('laravels.pid'),
+        'log_file'           => storage_path(sprintf('logs/swoole-%s.log', date('Y-m'))),
+        'log_level'          => 4,
+        'document_root'      => base_path('public'),
+        'buffer_output_size' => 2 * 1024 * 1024,
+        'socket_buffer_size' => 128 * 1024 * 1024,
+        'package_max_length' => 4 * 1024 * 1024,
+        'reload_async'       => true,
+        'max_wait_time'      => 60,
+        'enable_reuse_port'  => true,
+        'enable_coroutine'   => false,
+        'http_compression'   => false,
+
+        /**
+         * More settings of Swoole
+         * @see https://wiki.swoole.com/wiki/page/274.html  Chinese
+         * @see https://www.swoole.co.uk/docs/modules/swoole-server/configuration  English
+         */
+    ],
+];

+ 19 - 0
database/factories/ModelFactory.php

@@ -0,0 +1,19 @@
+<?php
+
+/*
+|--------------------------------------------------------------------------
+| Model Factories
+|--------------------------------------------------------------------------
+|
+| Here you may define all of your model factories. Model factories give
+| you a convenient way to create models for testing and seeding your
+| database. Just tell the factory how a default model should look.
+|
+*/
+
+$factory->define(App\User::class, function (Faker\Generator $faker) {
+    return [
+        'name' => $faker->name,
+        'email' => $faker->email,
+    ];
+});

+ 0 - 0
database/migrations/.gitkeep


+ 16 - 0
database/seeds/DatabaseSeeder.php

@@ -0,0 +1,16 @@
+<?php
+
+use Illuminate\Database\Seeder;
+
+class DatabaseSeeder extends Seeder
+{
+    /**
+     * Run the database seeds.
+     *
+     * @return void
+     */
+    public function run()
+    {
+        // $this->call('UsersTableSeeder');
+    }
+}

+ 20 - 0
deploy/nginx/conf.d/app.beta.conf

@@ -0,0 +1,20 @@
+server {
+    listen 80;
+    index index.php index.html;
+    error_log  /var/log/nginx/error.log;
+    access_log /var/log/nginx/access.log;
+    root /var/www/public;
+    location ~ \.php$ {
+        try_files $uri =404;
+        fastcgi_split_path_info ^(.+\.php)(/.+)$;
+        fastcgi_pass app_order_manage_beta:9000;
+        fastcgi_index index.php;
+        include fastcgi_params;
+        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
+        fastcgi_param PATH_INFO $fastcgi_path_info;
+    }
+    location / {
+        try_files $uri $uri/ /index.php?$query_string;
+        gzip_static on;
+    }
+}

+ 20 - 0
deploy/nginx/conf.d/app.dev.conf

@@ -0,0 +1,20 @@
+server {
+    listen 80;
+    index index.php index.html;
+    error_log  /var/log/nginx/error.log;
+    access_log /var/log/nginx/access.log;
+    root /var/www/public;
+    location ~ \.php$ {
+        try_files $uri =404;
+        fastcgi_split_path_info ^(.+\.php)(/.+)$;
+        fastcgi_pass app_order_manage_dev:9000;
+        fastcgi_index index.php;
+        include fastcgi_params;
+        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
+        fastcgi_param PATH_INFO $fastcgi_path_info;
+    }
+    location / {
+        try_files $uri $uri/ /index.php?$query_string;
+        gzip_static on;
+    }
+}

+ 2 - 0
deploy/php/local.ini

@@ -0,0 +1,2 @@
+upload_max_filesize=40M
+post_max_size=40M

+ 32 - 0
docker-compose-beta.yml

@@ -0,0 +1,32 @@
+version: '3'
+
+services:
+  app_order_manage_beta:
+    image: harbor.caihongxingqiu.com:9401/library/php:latest
+    tty: true
+    working_dir: /var/www
+    volumes:
+      - ./:/var/www
+      - ./deploy/php/local.ini:/usr/local/etc/php/conf.d/local.ini
+      - /data/wwwroot/beta/order-manage:/data/wwwroot/beta/order-manage
+    networks:
+      - chxq
+
+  server_order_manage_beta:
+    image: harbor.caihongxingqiu.com:9401/library/nginx:latest
+    tty: true
+    depends_on:
+      - app_order_manage_beta
+    ports:
+      - "28214:80"
+    volumes:
+      - ./:/var/www
+      - ./deploy/nginx/conf.d/app.beta.conf:/etc/nginx/conf.d/app.beta.conf
+    networks:
+      - chxq
+
+#docker networks
+#docker network create --driver overlay chxq
+networks:
+  chxq:
+    external: true

+ 31 - 0
docker-compose-dev.yml

@@ -0,0 +1,31 @@
+version: '3'
+
+services:
+  app_order_manage_dev:
+    image: harbor.caihongxingqiu.com:9401/library/php:latest
+    tty: true
+    working_dir: /var/www
+    volumes:
+      - ./:/var/www
+      - ./deploy/php/local.ini:/usr/local/etc/php/conf.d/local.ini
+    networks:
+      - chxq
+
+  server_order_manage_dev:
+    image: harbor.caihongxingqiu.com:9401/library/nginx:latest
+    tty: true
+    depends_on:
+      - app_order_manage_dev
+    ports:
+      - "18214:80"
+    volumes:
+      - ./:/var/www
+      - ./deploy/nginx/conf.d/app.dev.conf:/etc/nginx/conf.d/app.dev.conf
+    networks:
+      - chxq
+
+#docker networks
+#docker network create --driver overlay chxq
+networks:
+  chxq:
+    external: true

+ 26 - 0
phpunit.xml

@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<phpunit backupGlobals="false"
+         backupStaticAttributes="false"
+         bootstrap="bootstrap/app.php"
+         colors="true"
+         convertErrorsToExceptions="true"
+         convertNoticesToExceptions="true"
+         convertWarningsToExceptions="true"
+         processIsolation="false"
+         stopOnFailure="false">
+    <testsuites>
+        <testsuite name="Application Test Suite">
+            <directory suffix="Test.php">./tests</directory>
+        </testsuite>
+    </testsuites>
+    <filter>
+        <whitelist processUncoveredFilesFromWhitelist="true">
+            <directory suffix=".php">./app</directory>
+        </whitelist>
+    </filter>
+    <php>
+        <env name="APP_ENV" value="testing"/>
+        <env name="CACHE_DRIVER" value="array"/>
+        <env name="QUEUE_CONNECTION" value="sync"/>
+    </php>
+</phpunit>

+ 21 - 0
public/.htaccess

@@ -0,0 +1,21 @@
+<IfModule mod_rewrite.c>
+    <IfModule mod_negotiation.c>
+        Options -MultiViews -Indexes
+    </IfModule>
+
+    RewriteEngine On
+
+    # Handle Authorization Header
+    RewriteCond %{HTTP:Authorization} .
+    RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
+
+    # Redirect Trailing Slashes If Not A Folder...
+    RewriteCond %{REQUEST_FILENAME} !-d
+    RewriteCond %{REQUEST_URI} (.+)/$
+    RewriteRule ^ %1 [L,R=301]
+
+    # Handle Front Controller...
+    RewriteCond %{REQUEST_FILENAME} !-d
+    RewriteCond %{REQUEST_FILENAME} !-f
+    RewriteRule ^ index.php [L]
+</IfModule>

+ 28 - 0
public/index.php

@@ -0,0 +1,28 @@
+<?php
+
+/*
+|--------------------------------------------------------------------------
+| Create The Application
+|--------------------------------------------------------------------------
+|
+| First we need to get an application instance. This creates an instance
+| of the application / container and bootstraps the application so it
+| is ready to receive HTTP / Console requests from the environment.
+|
+*/
+
+$app = require __DIR__.'/../bootstrap/app.php';
+
+/*
+|--------------------------------------------------------------------------
+| Run The Application
+|--------------------------------------------------------------------------
+|
+| Once we have the application, we can handle the incoming request
+| through the kernel, and send the associated response back to
+| the client's browser allowing them to enjoy the creative
+| and wonderful application we have prepared for them.
+|
+*/
+
+$app->run();

+ 21 - 0
readme.md

@@ -0,0 +1,21 @@
+# Lumen PHP Framework
+
+[![Build Status](https://travis-ci.org/laravel/lumen-framework.svg)](https://travis-ci.org/laravel/lumen-framework)
+[![Total Downloads](https://poser.pugx.org/laravel/lumen-framework/d/total.svg)](https://packagist.org/packages/laravel/lumen-framework)
+[![Latest Stable Version](https://poser.pugx.org/laravel/lumen-framework/v/stable.svg)](https://packagist.org/packages/laravel/lumen-framework)
+[![Latest Unstable Version](https://poser.pugx.org/laravel/lumen-framework/v/unstable.svg)](https://packagist.org/packages/laravel/lumen-framework)
+[![License](https://poser.pugx.org/laravel/lumen-framework/license.svg)](https://packagist.org/packages/laravel/lumen-framework)
+
+Laravel Lumen is a stunningly fast PHP micro-framework for building web applications with expressive, elegant syntax. We believe development must be an enjoyable, creative experience to be truly fulfilling. Lumen attempts to take the pain out of development by easing common tasks used in the majority of web projects, such as routing, database abstraction, queueing, and caching.
+
+## Official Documentation
+
+Documentation for the framework can be found on the [Lumen website](https://lumen.laravel.com/docs).
+
+## Security Vulnerabilities
+
+If you discover a security vulnerability within Lumen, please send an e-mail to Taylor Otwell at taylor@laravel.com. All security vulnerabilities will be promptly addressed.
+
+## License
+
+The Lumen framework is open-sourced software licensed under the [MIT license](https://opensource.org/licenses/MIT).

+ 19 - 0
resources/lang/en/auth.php

@@ -0,0 +1,19 @@
+<?php
+
+return [
+
+    /*
+    |--------------------------------------------------------------------------
+    | Authentication Language Lines
+    |--------------------------------------------------------------------------
+    |
+    | The following language lines are used during authentication for various
+    | messages that we need to display to the user. You are free to modify
+    | these language lines according to your application's requirements.
+    |
+    */
+
+    'failed' => 'These credentials do not match our records.',
+    'throttle' => 'Too many login attempts. Please try again in :seconds seconds.',
+
+];

+ 19 - 0
resources/lang/en/pagination.php

@@ -0,0 +1,19 @@
+<?php
+
+return [
+
+    /*
+    |--------------------------------------------------------------------------
+    | Pagination Language Lines
+    |--------------------------------------------------------------------------
+    |
+    | The following language lines are used by the paginator library to build
+    | the simple pagination links. You are free to change them to anything
+    | you want to customize your views to better match your application.
+    |
+    */
+
+    'previous' => '&laquo; Previous',
+    'next' => 'Next &raquo;',
+
+];

+ 22 - 0
resources/lang/en/passwords.php

@@ -0,0 +1,22 @@
+<?php
+
+return [
+
+    /*
+    |--------------------------------------------------------------------------
+    | Password Reset Language Lines
+    |--------------------------------------------------------------------------
+    |
+    | The following language lines are the default lines which match reasons
+    | that are given by the password broker for a password update attempt
+    | has failed, such as for an invalid token or invalid new password.
+    |
+    */
+
+    'password' => 'Passwords must be at least six characters and match the confirmation.',
+    'reset' => 'Your password has been reset!',
+    'sent' => 'We have e-mailed your password reset link!',
+    'token' => 'This password reset token is invalid.',
+    'user' => "We can't find a user with that e-mail address.",
+
+];

+ 146 - 0
resources/lang/en/validation.php

@@ -0,0 +1,146 @@
+<?php
+
+return [
+
+    /*
+    |--------------------------------------------------------------------------
+    | Validation Language Lines
+    |--------------------------------------------------------------------------
+    |
+    | The following language lines contain the default error messages used by
+    | the validator class. Some of these rules have multiple versions such
+    | as the size rules. Feel free to tweak each of these messages here.
+    |
+    */
+
+    'accepted'             => 'The :attribute must be accepted.',
+    'active_url'           => 'The :attribute is not a valid URL.',
+    'after'                => 'The :attribute must be a date after :date.',
+    'after_or_equal'       => 'The :attribute must be a date after or equal to :date.',
+    'alpha'                => 'The :attribute may only contain letters.',
+    'alpha_dash'           => 'The :attribute may only contain letters, numbers, dashes and underscores.',
+    'alpha_num'            => 'The :attribute may only contain letters and numbers.',
+    'array'                => 'The :attribute must be an array.',
+    'before'               => 'The :attribute must be a date before :date.',
+    'before_or_equal'      => 'The :attribute must be a date before or equal to :date.',
+    'between'              => [
+        'numeric' => 'The :attribute must be between :min and :max.',
+        'file'    => 'The :attribute must be between :min and :max kilobytes.',
+        'string'  => 'The :attribute must be between :min and :max characters.',
+        'array'   => 'The :attribute must have between :min and :max items.',
+    ],
+    'boolean'              => 'The :attribute field must be true or false.',
+    'confirmed'            => 'The :attribute confirmation does not match.',
+    'date'                 => 'The :attribute is not a valid date.',
+    'date_format'          => 'The :attribute does not match the format :format.',
+    'different'            => 'The :attribute and :other must be different.',
+    'digits'               => 'The :attribute must be :digits digits.',
+    'digits_between'       => 'The :attribute must be between :min and :max digits.',
+    'dimensions'           => 'The :attribute has invalid image dimensions.',
+    'distinct'             => 'The :attribute field has a duplicate value.',
+    'email'                => 'The :attribute must be a valid email address.',
+    'exists'               => 'The selected :attribute is invalid.',
+    'file'                 => 'The :attribute must be a file.',
+    'filled'               => 'The :attribute field must have a value.',
+    'gt'                   => [
+        'numeric' => 'The :attribute must be greater than :value.',
+        'file'    => 'The :attribute must be greater than :value kilobytes.',
+        'string'  => 'The :attribute must be greater than :value characters.',
+        'array'   => 'The :attribute must have more than :value items.',
+    ],
+    'gte'                  => [
+        'numeric' => 'The :attribute must be greater than or equal :value.',
+        'file'    => 'The :attribute must be greater than or equal :value kilobytes.',
+        'string'  => 'The :attribute must be greater than or equal :value characters.',
+        'array'   => 'The :attribute must have :value items or more.',
+    ],
+    'image'                => 'The :attribute must be an image.',
+    'in'                   => 'The selected :attribute is invalid.',
+    'in_array'             => 'The :attribute field does not exist in :other.',
+    'integer'              => 'The :attribute must be an integer.',
+    'ip'                   => 'The :attribute must be a valid IP address.',
+    'ipv4'                 => 'The :attribute must be a valid IPv4 address.',
+    'ipv6'                 => 'The :attribute must be a valid IPv6 address.',
+    'json'                 => 'The :attribute must be a valid JSON string.',
+    'lt'                   => [
+        'numeric' => 'The :attribute must be less than :value.',
+        'file'    => 'The :attribute must be less than :value kilobytes.',
+        'string'  => 'The :attribute must be less than :value characters.',
+        'array'   => 'The :attribute must have less than :value items.',
+    ],
+    'lte'                  => [
+        'numeric' => 'The :attribute must be less than or equal :value.',
+        'file'    => 'The :attribute must be less than or equal :value kilobytes.',
+        'string'  => 'The :attribute must be less than or equal :value characters.',
+        'array'   => 'The :attribute must not have more than :value items.',
+    ],
+    'max'                  => [
+        'numeric' => 'The :attribute may not be greater than :max.',
+        'file'    => 'The :attribute may not be greater than :max kilobytes.',
+        'string'  => 'The :attribute may not be greater than :max characters.',
+        'array'   => 'The :attribute may not have more than :max items.',
+    ],
+    'mimes'                => 'The :attribute must be a file of type: :values.',
+    'mimetypes'            => 'The :attribute must be a file of type: :values.',
+    'min'                  => [
+        'numeric' => 'The :attribute must be at least :min.',
+        'file'    => 'The :attribute must be at least :min kilobytes.',
+        'string'  => 'The :attribute must be at least :min characters.',
+        'array'   => 'The :attribute must have at least :min items.',
+    ],
+    'not_in'               => 'The selected :attribute is invalid.',
+    'not_regex'            => 'The :attribute format is invalid.',
+    'numeric'              => 'The :attribute must be a number.',
+    'present'              => 'The :attribute field must be present.',
+    'regex'                => 'The :attribute format is invalid.',
+    'required'             => 'The :attribute field is required.',
+    'required_if'          => 'The :attribute field is required when :other is :value.',
+    'required_unless'      => 'The :attribute field is required unless :other is in :values.',
+    'required_with'        => 'The :attribute field is required when :values is present.',
+    'required_with_all'    => 'The :attribute field is required when :values is present.',
+    'required_without'     => 'The :attribute field is required when :values is not present.',
+    'required_without_all' => 'The :attribute field is required when none of :values are present.',
+    'same'                 => 'The :attribute and :other must match.',
+    'size'                 => [
+        'numeric' => 'The :attribute must be :size.',
+        'file'    => 'The :attribute must be :size kilobytes.',
+        'string'  => 'The :attribute must be :size characters.',
+        'array'   => 'The :attribute must contain :size items.',
+    ],
+    'string'               => 'The :attribute must be a string.',
+    'timezone'             => 'The :attribute must be a valid zone.',
+    'unique'               => 'The :attribute has already been taken.',
+    'uploaded'             => 'The :attribute failed to upload.',
+    'url'                  => 'The :attribute format is invalid.',
+
+    /*
+    |--------------------------------------------------------------------------
+    | Custom Validation Language Lines
+    |--------------------------------------------------------------------------
+    |
+    | Here you may specify custom validation messages for attributes using the
+    | convention "attribute.rule" to name the lines. This makes it quick to
+    | specify a specific custom language line for a given attribute rule.
+    |
+    */
+
+    'custom' => [
+        'attribute-name' => [
+            'rule-name' => 'custom-message',
+        ],
+    ],
+
+    /*
+    |--------------------------------------------------------------------------
+    | Custom Validation Attributes
+    |--------------------------------------------------------------------------
+    |
+    | The following language lines are used to swap attribute place-holders
+    | with something more reader friendly such as E-Mail Address instead
+    | of "email". This simply helps us make messages a little cleaner.
+    |
+    */
+
+    'attributes' => [],
+
+];

+ 17 - 0
resources/lang/zh-CN/auth.php

@@ -0,0 +1,17 @@
+<?php
+
+return [
+    /*
+    |--------------------------------------------------------------------------
+    | Authentication Language Lines
+    |--------------------------------------------------------------------------
+    |
+    | The following language lines are used during authentication for various
+    | messages that we need to display to the user. You are free to modify
+    | these language lines according to your application's requirements.
+    |
+    */
+
+    'failed' => '用户名或密码错误。',
+    'throttle' => '您的尝试登录次数过多,请 :seconds 秒后再试。',
+];

+ 17 - 0
resources/lang/zh-CN/pagination.php

@@ -0,0 +1,17 @@
+<?php
+
+return [
+    /*
+    |--------------------------------------------------------------------------
+    | Pagination Language Lines
+    |--------------------------------------------------------------------------
+    |
+    | The following language lines are used by the paginator library to build
+    | the simple pagination links. You are free to change them to anything
+    | you want to customize your views to better match your application.
+    |
+    */
+
+    'previous' => '&laquo; 上一页',
+    'next' => '下一页 &raquo;',
+];

+ 20 - 0
resources/lang/zh-CN/passwords.php

@@ -0,0 +1,20 @@
+<?php
+
+return [
+    /*
+    |--------------------------------------------------------------------------
+    | Password Reminder Language Lines
+    |--------------------------------------------------------------------------
+    |
+    | The following language lines are the default lines which match reasons
+    | that are given by the password broker for a password update attempt
+    | has failed, such as for an invalid token or invalid new password.
+    |
+    */
+
+    'password' => '密码至少是六位字符并且匹配。',
+    'reset' => '密码重置成功!',
+    'sent' => '密码重置邮件已发送!',
+    'token' => '密码重置令牌无效。',
+    'user' => '找不到该邮箱对应的用户。',
+];

+ 106 - 0
resources/lang/zh-CN/validation.php

@@ -0,0 +1,106 @@
+<?php
+
+return [
+    /*
+    |--------------------------------------------------------------------------
+    | Validation Language Lines
+    |--------------------------------------------------------------------------
+    |
+    | The following language lines contain the default error messages used by
+    | the validator class. Some of these rules have multiple versions such
+    | as the size rules. Feel free to tweak each of these messages.
+    |
+    */
+
+    'accepted' => ':attribute 必须接受。',
+    'active_url' => ':attribute 不是一个有效的网址。',
+    'after' => ':attribute 必须要晚于 :date。',
+    'after_or_equal' => ':attribute 必须要等于 :date 或更晚。',
+    'alpha' => ':attribute 只能由字母组成。',
+    'alpha_dash' => ':attribute 只能由字母、数字和斜杠组成。',
+    'alpha_num' => ':attribute 只能由字母和数字组成。',
+    'array' => ':attribute 必须是一个数组。',
+    'before' => ':attribute 必须要早于 :date。',
+    'before_or_equal' => ':attribute 必须要等于 :date 或更早。',
+    'between' => [
+        'numeric' => ':attribute 必须介于 :min - :max 之间。',
+        'file' => ':attribute 必须介于 :min - :max kb 之间。',
+        'string' => ':attribute 必须介于 :min - :max 个字符之间。',
+        'array' => ':attribute 必须只有 :min - :max 个单元。',
+    ],
+    'boolean' => ':attribute 必须为布尔值。',
+    'confirmed' => ':attribute 两次输入不一致。',
+    'date' => ':attribute 不是一个有效的日期。',
+    'date_format' => ':attribute 的格式必须为 :format。',
+    'different' => ':attribute 和 :other 必须不同。',
+    'digits' => ':attribute 必须是 :digits 位的数字。',
+    'digits_between' => ':attribute 必须是介于 :min 和 :max 位的数字。',
+    'dimensions' => ':attribute 图片尺寸不正确。',
+    'distinct' => ':attribute 已经存在。',
+    'email' => ':attribute 不是一个合法的邮箱。',
+    'exists' => ':attribute 不存在。',
+    'file' => ':attribute 必须是文件。',
+    'filled' => ':attribute 不能为空。',
+    'image' => ':attribute 必须是图片。',
+    'in' => '已选的属性 :attribute 非法。',
+    'in_array' => ':attribute 没有在 :other 中。',
+    'integer' => ':attribute 必须是整数。',
+    'ip' => ':attribute 必须是有效的 IP 地址。',
+    'ipv4' => ':attribute 必须是有效的 IPv4 地址。',
+    'ipv6' => ':attribute 必须是有效的 IPv6 地址。',
+    'json' => ':attribute 必须是正确的 JSON 格式。',
+    'max' => [
+        'numeric' => ':attribute 不能大于 :max。',
+        'file' => ':attribute 不能大于 :max kb。',
+        'string' => ':attribute 不能大于 :max 个字符。',
+        'array' => ':attribute 最多只有 :max 个单元。',
+    ],
+    'mimes' => ':attribute 必须是一个 :values 类型的文件。',
+    'mimetypes' => ':attribute 必须是一个 :values 类型的文件。',
+    'min' => [
+        'numeric' => ':attribute 必须大于等于 :min。',
+        'file' => ':attribute 大小不能小于 :min kb。',
+        'string' => ':attribute 至少为 :min 个字符。',
+        'array' => ':attribute 至少有 :min 个单元。',
+    ],
+    'not_in' => '已选的属性 :attribute 非法。',
+    'numeric' => ':attribute 必须是一个数字。',
+    'present' => ':attribute 必须存在。',
+    'regex' => ':attribute 格式不正确。',
+    'required' => ':attribute 不能为空。',
+    'required_if' => '当 :other 为 :value 时 :attribute 不能为空。',
+    'required_unless' => '当 :other 不为 :value 时 :attribute 不能为空。',
+    'required_with' => '当 :values 存在时 :attribute 不能为空。',
+    'required_with_all' => '当 :values 存在时 :attribute 不能为空。',
+    'required_without' => '当 :values 不存在时 :attribute 不能为空。',
+    'required_without_all' => '当 :values 都不存在时 :attribute 不能为空。',
+    'same' => ':attribute 和 :other 必须相同。',
+    'size' => [
+        'numeric' => ':attribute 大小必须为 :size。',
+        'file' => ':attribute 大小必须为 :size kb。',
+        'string' => ':attribute 必须是 :size 个字符。',
+        'array' => ':attribute 必须为 :size 个单元。',
+    ],
+    'string' => ':attribute 必须是一个字符串。',
+    'timezone' => ':attribute 必须是一个合法的时区值。',
+    'unique' => ':attribute 已经存在。',
+    'uploaded' => ':attribute 上传失败。',
+    'url' => ':attribute 格式不正确。',
+
+
+    /*
+    |--------------------------------------------------------------------------
+    | Custom Validation Attributes
+    |--------------------------------------------------------------------------
+    |
+    | The following language lines are used to swap attribute place-holders
+    | with something more reader friendly such as E-Mail Address instead
+    | of 'email'. This simply helps us make messages a little cleaner.
+    |
+    */
+
+    'attributes' => [
+        'id' => 'id',
+    ],
+
+];

+ 0 - 0
resources/views/.gitkeep


+ 40 - 0
routes/api.php

@@ -0,0 +1,40 @@
+<?php
+
+/*
+|--------------------------------------------------------------------------
+| Application Routes
+|--------------------------------------------------------------------------
+|
+| Here is where you can register all of the routes for an application.
+| It is a breeze. Simply tell Lumen the URIs it should respond to
+| and give it the Closure to call when that URI is requested.
+|
+*/
+
+$api = app('Dingo\Api\Routing\Router');
+
+$api->version('v1', [
+    'namespace' => 'App\Http\Controllers\V1',
+], function ($api) {
+    //登录
+
+    $api->post('login', 'AuthController@authenticate');
+
+
+
+    $api->group(['middleware' => 'auth:api'], function ($api) {
+        //注册
+        $api->post('reg', 'AuthController@register');
+        //登出
+        $api->post('logout', 'AuthController@logout');
+        //刷新身份令牌
+        $api->post('refresh', 'AuthController@refresh');
+    });
+
+    //测试
+    $api->get('test', 'TestController@index');
+
+    $api->group(['middleware' => 'jwt.chxq_auth'], function ($api) {
+
+    });
+});

+ 20 - 0
routes/web.php

@@ -0,0 +1,20 @@
+<?php
+
+/*
+|--------------------------------------------------------------------------
+| Application Routes
+|--------------------------------------------------------------------------
+|
+| Here is where you can register all of the routes for an application.
+| It is a breeze. Simply tell Lumen the URIs it should respond to
+| and give it the Closure to call when that URI is requested.
+|
+*/
+
+$router->get('/', function () use ($router) {
+    return $router->app->version();
+});
+
+$router->get('/test', function () use ($router) {
+    return 'test-manage';
+});

+ 21 - 0
tests/ExampleTest.php

@@ -0,0 +1,21 @@
+<?php
+
+use Laravel\Lumen\Testing\DatabaseMigrations;
+use Laravel\Lumen\Testing\DatabaseTransactions;
+
+class ExampleTest extends TestCase
+{
+    /**
+     * A basic test example.
+     *
+     * @return void
+     */
+    public function testExample()
+    {
+        $this->get('/');
+
+        $this->assertEquals(
+            $this->app->version(), $this->response->getContent()
+        );
+    }
+}

+ 14 - 0
tests/TestCase.php

@@ -0,0 +1,14 @@
+<?php
+
+abstract class TestCase extends Laravel\Lumen\Testing\TestCase
+{
+    /**
+     * Creates the application.
+     *
+     * @return \Laravel\Lumen\Application
+     */
+    public function createApplication()
+    {
+        return require __DIR__.'/../bootstrap/app.php';
+    }
+}