diff --git a/.env.example b/.env.example
index 05d954d6..ee697782 100644
--- a/.env.example
+++ b/.env.example
@@ -24,4 +24,20 @@ DB_MONGO_DSN=mongodb://root:Fxft2017@dds-bp104401edaca7e41595-pub.mongodb.rds.al
DB_MONGO_DATABASE=CardInfo
CACHE_DRIVER=file
-QUEUE_DRIVER=sync
\ No newline at end of file
+QUEUE_DRIVER=sync
+
+ # 短信配置
+ SMS_ALIYUN_ACCESS_KEY_ID=LTAI2ryyzNGM0uPy
+ SMS_ALIYUN_ACCESS_KEY_SECRET=ss5pRyKph1X6brgrvJ09ix1v5zB43Z
+ SMS_ALIYUN_SIGN_NAME=车友服务
+ SMS_ALIYUN_TEMPLATE_VCODE=SMS_33200524
+ SMS_ALIYUN_TEMPLATE_INSTALLED=SMS_139233171
+ SMS_ALIYUN_TEMPLATE_ORDER=SMS_133970655
+
+ SMS_HUYI_API_ID=cf_fxft
+ SMS_HUYI_API_KEY=0f334282c63e5f7fec54caffed85fc61
+
+ SMS_FXFT_USERNAME=360001
+ SMS_FXFT_PASSWORD=jB9lI5bD
+ SMS_FXFT_URL=http://47.99.58.23:9001/smsSend.do
+ SMS_FXFT_EXT=01
\ No newline at end of file
diff --git a/app/Domains/Auth/Http/Controllers/CompanyAuthController.php b/app/Domains/Auth/Http/Controllers/CompanyAuthController.php
new file mode 100644
index 00000000..498de068
--- /dev/null
+++ b/app/Domains/Auth/Http/Controllers/CompanyAuthController.php
@@ -0,0 +1,80 @@
+request = $request;
+ $this->auth = app('auth:company');
+ }
+
+ /**
+ * 登录
+ *
+ * @return \Illuminate\Http\Response
+ */
+ public function login()
+ {
+ $rule = [
+ 'username' => ['required', 'username', 'display_length:2,12'],
+ 'password' => ['required', 'string'],
+ 'remember' => ['in:0,1'],
+ ];
+
+
+ $message = [
+ 'username.required' => '请输入用户名',
+ 'username.username' => '用户名不正确',
+ 'username.display_length' => '用户名不正确',
+ 'password.required' => '请输入密码',
+ 'password.string' => '密码不正确',
+ ];
+
+ Validator::validate($this->request->all(), $rule, $message);
+
+ $username = $this->request->get('username');
+ $password = $this->request->get('password');
+ $remember = $this->request->get('remember', 0);
+
+ $token = $this->auth->login($username, $password, $remember);
+
+ return res($token, '登录成功', 200, [
+ 'new-token' => $token
+ ]);
+ }
+
+
+ /**
+ * 登出
+ *
+ * @return \Illuminate\Http\Response
+ */
+ public function logout()
+ {
+ $this->auth->logout();
+ return res(true, '登出成功');
+ }
+
+ /**
+ * 账户信息
+ *
+ * @return \Illuminate\Http\Response
+ */
+ public function info()
+ {
+ $account = $this->auth->authenticate();
+
+ return res(['account' => $account], '账号信息', 201);
+ }
+}
diff --git a/app/Domains/Auth/Http/Middleware/CompanyAuthenticate.php b/app/Domains/Auth/Http/Middleware/CompanyAuthenticate.php
new file mode 100644
index 00000000..e9452198
--- /dev/null
+++ b/app/Domains/Auth/Http/Middleware/CompanyAuthenticate.php
@@ -0,0 +1,47 @@
+getGuard();
+
+ if (! $auth->parser()->setRequest($request)->hasToken()) {
+ throw new AuthException('未提供Token', AuthException::TOKEN_NOT_PROVIDED);
+ }
+
+ try {
+ if (! $account = app('auth:company')->authenticate()) {
+ throw new AuthException('账号未登录', AuthException::NOT_LOGIN);
+ }
+ } catch (JWTException $e) {
+ throw new UnauthorizedHttpException('jwt-auth', $e->getMessage(), $e, $e->getCode());
+ }
+
+ $checks = app()->tagged('auth:company:check');
+
+ foreach ($checks as $check) {
+ call_user_func_array([$check, 'handle'], ['account' => $account, 'request' => $request]);
+ }
+
+ $response = $next($request);
+
+ $token = app('auth:company')->getToken();
+
+ $response->headers->set('Authorization', 'Bearer '.$token);
+
+ return $response;
+ }
+}
diff --git a/app/Domains/Auth/Providers/AuthServiceProvider.php b/app/Domains/Auth/Providers/AuthServiceProvider.php
index f33b3240..3e295094 100644
--- a/app/Domains/Auth/Providers/AuthServiceProvider.php
+++ b/app/Domains/Auth/Providers/AuthServiceProvider.php
@@ -9,6 +9,7 @@ use Illuminate\Contracts\Auth\Authenticatable;
use App\Domains\Auth\Providers\MiddlewareProvider;
use App\Domains\Auth\Providers\RouteServiceProvider;
use App\Domains\Account\Repositories\AccountRepository;
+use App\Domains\Virtual\Repositories\CompanyAccountRepository;
class AuthServiceProvider extends ServiceProvider
{
@@ -42,6 +43,10 @@ class AuthServiceProvider extends ServiceProvider
return new AuthService('admin', app(AccountRepository::class));
});
+ $this->app->singleton('auth:company', function ($app) {
+ return new AuthService('company', app(CompanyAccountRepository::class));
+ });
+
$this->app->register(RouteServiceProvider::class);
$this->app->register(MiddlewareServiceProvider::class);
}
diff --git a/app/Domains/Auth/Providers/MiddlewareServiceProvider.php b/app/Domains/Auth/Providers/MiddlewareServiceProvider.php
index 1b06e6b9..111f18c7 100644
--- a/app/Domains/Auth/Providers/MiddlewareServiceProvider.php
+++ b/app/Domains/Auth/Providers/MiddlewareServiceProvider.php
@@ -25,5 +25,6 @@ class MiddlewareServiceProvider extends ServiceProvider
*/
protected $routeMiddleware = [
'adminAuth' => \App\Domains\Auth\Http\Middleware\AdminAuthenticate::class,
+ 'companyAuth' => \App\Domains\Auth\Http\Middleware\CompanyAuthenticate::class,
];
}
diff --git a/app/Domains/Auth/Routes/api.php b/app/Domains/Auth/Routes/api.php
index 39246286..97ca8826 100644
--- a/app/Domains/Auth/Routes/api.php
+++ b/app/Domains/Auth/Routes/api.php
@@ -6,4 +6,8 @@ $router->group(['prefix' => 'auth', 'as' => 'auth'], function ($router) {
$router->post('admin/login', ['as' => 'admin.login', 'uses' => 'AdminAuthController@login']);
$router->post('admin/logout', ['as' => 'admin.logout', 'uses' => 'AdminAuthController@logout', 'middleware' => 'adminAuth']);
$router->get('admin/info', ['as' => 'admin.info', 'uses' => 'AdminAuthController@info', 'middleware' => 'adminAuth']);
+
+ $router->post('company/login', ['as' => 'company.login', 'uses' => 'CompanyAuthController@login']);
+ $router->post('company/logout', ['as' => 'company.logout', 'uses' => 'CompanyAuthController@logout', 'middleware' => 'companyAuth']);
+ $router->get('company/info', ['as' => 'company.info', 'uses' => 'CompanyAuthController@info', 'middleware' => 'companyAuth']);
});
diff --git a/app/Domains/Captcha/.gitkeep b/app/Domains/Captcha/.gitkeep
new file mode 100644
index 00000000..e69de29b
diff --git a/app/Domains/Captcha/Assets/backgrounds/01.png b/app/Domains/Captcha/Assets/backgrounds/01.png
new file mode 100644
index 00000000..3f9c5fd5
Binary files /dev/null and b/app/Domains/Captcha/Assets/backgrounds/01.png differ
diff --git a/app/Domains/Captcha/Assets/backgrounds/02.png b/app/Domains/Captcha/Assets/backgrounds/02.png
new file mode 100644
index 00000000..839bd8f5
Binary files /dev/null and b/app/Domains/Captcha/Assets/backgrounds/02.png differ
diff --git a/app/Domains/Captcha/Assets/backgrounds/03.png b/app/Domains/Captcha/Assets/backgrounds/03.png
new file mode 100644
index 00000000..6c5291f1
Binary files /dev/null and b/app/Domains/Captcha/Assets/backgrounds/03.png differ
diff --git a/app/Domains/Captcha/Assets/backgrounds/04.png b/app/Domains/Captcha/Assets/backgrounds/04.png
new file mode 100644
index 00000000..e8dceec0
Binary files /dev/null and b/app/Domains/Captcha/Assets/backgrounds/04.png differ
diff --git a/app/Domains/Captcha/Assets/backgrounds/05.png b/app/Domains/Captcha/Assets/backgrounds/05.png
new file mode 100644
index 00000000..9c382474
Binary files /dev/null and b/app/Domains/Captcha/Assets/backgrounds/05.png differ
diff --git a/app/Domains/Captcha/Assets/backgrounds/06.png b/app/Domains/Captcha/Assets/backgrounds/06.png
new file mode 100644
index 00000000..6d2f02c9
Binary files /dev/null and b/app/Domains/Captcha/Assets/backgrounds/06.png differ
diff --git a/app/Domains/Captcha/Assets/backgrounds/07.png b/app/Domains/Captcha/Assets/backgrounds/07.png
new file mode 100644
index 00000000..056ea50a
Binary files /dev/null and b/app/Domains/Captcha/Assets/backgrounds/07.png differ
diff --git a/app/Domains/Captcha/Assets/backgrounds/08.png b/app/Domains/Captcha/Assets/backgrounds/08.png
new file mode 100644
index 00000000..7e5fcc42
Binary files /dev/null and b/app/Domains/Captcha/Assets/backgrounds/08.png differ
diff --git a/app/Domains/Captcha/Assets/backgrounds/09.png b/app/Domains/Captcha/Assets/backgrounds/09.png
new file mode 100644
index 00000000..febfca16
Binary files /dev/null and b/app/Domains/Captcha/Assets/backgrounds/09.png differ
diff --git a/app/Domains/Captcha/Assets/backgrounds/10.png b/app/Domains/Captcha/Assets/backgrounds/10.png
new file mode 100644
index 00000000..55719213
Binary files /dev/null and b/app/Domains/Captcha/Assets/backgrounds/10.png differ
diff --git a/app/Domains/Captcha/Assets/backgrounds/11.png b/app/Domains/Captcha/Assets/backgrounds/11.png
new file mode 100644
index 00000000..c6e1faf9
Binary files /dev/null and b/app/Domains/Captcha/Assets/backgrounds/11.png differ
diff --git a/app/Domains/Captcha/Assets/backgrounds/12.png b/app/Domains/Captcha/Assets/backgrounds/12.png
new file mode 100644
index 00000000..439964eb
Binary files /dev/null and b/app/Domains/Captcha/Assets/backgrounds/12.png differ
diff --git a/app/Domains/Captcha/Assets/fonts/ABeeZee_regular.ttf b/app/Domains/Captcha/Assets/fonts/ABeeZee_regular.ttf
new file mode 100644
index 00000000..9eae6f25
Binary files /dev/null and b/app/Domains/Captcha/Assets/fonts/ABeeZee_regular.ttf differ
diff --git a/app/Domains/Captcha/Assets/fonts/Asap_700.ttf b/app/Domains/Captcha/Assets/fonts/Asap_700.ttf
new file mode 100644
index 00000000..6386c6bd
Binary files /dev/null and b/app/Domains/Captcha/Assets/fonts/Asap_700.ttf differ
diff --git a/app/Domains/Captcha/Assets/fonts/Khand_500.ttf b/app/Domains/Captcha/Assets/fonts/Khand_500.ttf
new file mode 100644
index 00000000..678a4917
Binary files /dev/null and b/app/Domains/Captcha/Assets/fonts/Khand_500.ttf differ
diff --git a/app/Domains/Captcha/Assets/fonts/Open_Sans_regular.ttf b/app/Domains/Captcha/Assets/fonts/Open_Sans_regular.ttf
new file mode 100644
index 00000000..db433349
Binary files /dev/null and b/app/Domains/Captcha/Assets/fonts/Open_Sans_regular.ttf differ
diff --git a/app/Domains/Captcha/Assets/fonts/Roboto_regular.ttf b/app/Domains/Captcha/Assets/fonts/Roboto_regular.ttf
new file mode 100644
index 00000000..8c082c8d
Binary files /dev/null and b/app/Domains/Captcha/Assets/fonts/Roboto_regular.ttf differ
diff --git a/app/Domains/Captcha/Assets/fonts/Ubuntu_regular.ttf b/app/Domains/Captcha/Assets/fonts/Ubuntu_regular.ttf
new file mode 100644
index 00000000..45a038ba
Binary files /dev/null and b/app/Domains/Captcha/Assets/fonts/Ubuntu_regular.ttf differ
diff --git a/app/Domains/Captcha/Assets/fonts/license/LICENSE-2.0.txt b/app/Domains/Captcha/Assets/fonts/license/LICENSE-2.0.txt
new file mode 100644
index 00000000..d6456956
--- /dev/null
+++ b/app/Domains/Captcha/Assets/fonts/license/LICENSE-2.0.txt
@@ -0,0 +1,202 @@
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/app/Domains/Captcha/Assets/fonts/license/OFL.txt b/app/Domains/Captcha/Assets/fonts/license/OFL.txt
new file mode 100644
index 00000000..801ca38d
--- /dev/null
+++ b/app/Domains/Captcha/Assets/fonts/license/OFL.txt
@@ -0,0 +1 @@
+Copyright (c)
+ * An offset to check for.
+ * ';
+ }
+}
diff --git a/app/Domains/Captcha/composer.json b/app/Domains/Captcha/composer.json
new file mode 100644
index 00000000..e0062fa2
--- /dev/null
+++ b/app/Domains/Captcha/composer.json
@@ -0,0 +1,11 @@
+{
+ "name": "app/captcha",
+ "description": "",
+ "type": "app-domain",
+ "require": {
+
+ },
+ "autoload": {
+
+ }
+}
\ No newline at end of file
diff --git a/app/Domains/Captcha/config.php b/app/Domains/Captcha/config.php
new file mode 100644
index 00000000..9fead058
--- /dev/null
+++ b/app/Domains/Captcha/config.php
@@ -0,0 +1,45 @@
+ '2346789abcdefghjmnpqrtuxyzABCDEFGHJMNPQRTUXYZ',
+
+ 'default' => [
+ 'length' => 5,
+ 'width' => 120,
+ 'height' => 36,
+ 'quality' => 90,
+ ],
+
+ 'flat' => [
+ 'length' => 6,
+ 'width' => 160,
+ 'height' => 46,
+ 'quality' => 90,
+ 'lines' => 6,
+ 'bgImage' => false,
+ 'bgColor' => '#ecf2f4',
+ 'fontColors'=> ['#2c3e50', '#c0392b', '#16a085', '#c0392b', '#8e44ad', '#303f9f', '#f57c00', '#795548'],
+ 'contrast' => -5,
+ ],
+
+ 'mini' => [
+ 'length' => 3,
+ 'width' => 60,
+ 'height' => 32,
+ ],
+
+ 'inverse' => [
+ 'length' => 5,
+ 'width' => 120,
+ 'height' => 36,
+ 'quality' => 90,
+ 'sensitive' => true,
+ 'angle' => 12,
+ 'sharpen' => 10,
+ 'blur' => 2,
+ 'invert' => true,
+ 'contrast' => -5,
+ ]
+
+];
\ No newline at end of file
diff --git a/app/Domains/Company/.gitkeep b/app/Domains/Company/.gitkeep
new file mode 100644
index 00000000..e69de29b
diff --git a/app/Domains/Company/Providers/CompanyServiceProvider.php b/app/Domains/Company/Providers/CompanyServiceProvider.php
new file mode 100644
index 00000000..694fb05c
--- /dev/null
+++ b/app/Domains/Company/Providers/CompanyServiceProvider.php
@@ -0,0 +1,33 @@
+loadMigrationsFrom([realpath(__DIR__ . '/../Database/migrations')]);
+ // $this->app->make(EloquentFactory::class)->load(realpath(__DIR__ . '/../Database/factories'));
+ // $this->mergeConfigFrom(realpath(__DIR__ . '/../config.php'), 'domain.company');
+ }
+
+ /**
+ * 注册一个服务提供者
+ *
+ * @return void
+ */
+ public function register()
+ {
+ $this->app->register(RouteServiceProvider::class);
+ }
+}
diff --git a/app/Domains/Company/Providers/RouteServiceProvider.php b/app/Domains/Company/Providers/RouteServiceProvider.php
new file mode 100644
index 00000000..f2c4fd40
--- /dev/null
+++ b/app/Domains/Company/Providers/RouteServiceProvider.php
@@ -0,0 +1,20 @@
+app;
+ $namespace = 'App\Domains\Company\Http\Controllers';
+ $pathApi = __DIR__.'/../Routes/api.php';
+ $pathWeb = __DIR__.'/../Routes/web.php';
+
+ $this->loadRoutesFiles($app->router, $namespace, $pathApi, $pathWeb);
+ }
+}
diff --git a/app/Domains/Company/Routes/api.php b/app/Domains/Company/Routes/api.php
new file mode 100644
index 00000000..236110bc
--- /dev/null
+++ b/app/Domains/Company/Routes/api.php
@@ -0,0 +1,15 @@
+group(['prefix' => 'companies', 'as' => 'companies'], function($router) {
+
+ // The controllers live in Domains/Company/Http/Controllers
+ $router->get('/', ['as' => 'index', 'uses' => 'CompanyController@index']);
+
+ /**
+ * 需要认证的接口
+ */
+ // $router->group(['middleware' => ['adminAuth']], function($router) {
+ // // $router->post('delete', ['as' => 'delete', 'uses' => 'CompanyController@delete']);
+ // });
+});
\ No newline at end of file
diff --git a/app/Domains/Company/Routes/web.php b/app/Domains/Company/Routes/web.php
new file mode 100644
index 00000000..e6980293
--- /dev/null
+++ b/app/Domains/Company/Routes/web.php
@@ -0,0 +1,14 @@
+group(['prefix' => 'companies', 'as' => 'companies'], function($router) {
+
+ // The controllers live in Domains/Company/Http/Controllers
+ // $router->get('/', ['as' => 'index', 'uses' => 'CompanyController@index']);
+
+ /**
+ * 需要认证的接口
+ */
+ // $router->group(['middleware' => ['userAuth']], function($router) {
+ // // $router->post('delete', ['as' => 'delete', 'uses' => 'CompanyController@delete']);
+ // });
+});
diff --git a/app/Domains/Company/composer.json b/app/Domains/Company/composer.json
new file mode 100644
index 00000000..e881f80a
--- /dev/null
+++ b/app/Domains/Company/composer.json
@@ -0,0 +1,11 @@
+{
+ "name": "app/company",
+ "description": "",
+ "type": "app-domain",
+ "require": {
+
+ },
+ "autoload": {
+
+ }
+}
\ No newline at end of file
diff --git a/app/Domains/Real/Commands/Sync/OrderBaseSync.php b/app/Domains/Real/Commands/Sync/OrderBaseSync.php
index dcaa4867..b75fba45 100644
--- a/app/Domains/Real/Commands/Sync/OrderBaseSync.php
+++ b/app/Domains/Real/Commands/Sync/OrderBaseSync.php
@@ -115,7 +115,7 @@ class OrderBaseSync extends Command
'order_at' => Carbon::parse($item['o_create_date'])->format('Y-m-d H:i:s'),
'address' => $item['o_address'],
'contact' => $item['o_contacts'],
- 'phone' => $item['o_contact_number'],
+ 'mobile' => $item['o_contact_number'],
'remark' => $item['o_remark'],
'logistics_remark' => $item['o_logistics_content'],
'created_at' => date('Y-m-d H:i:s', $item['o_create_time']),
diff --git a/app/Domains/Sms/.gitkeep b/app/Domains/Sms/.gitkeep
new file mode 100755
index 00000000..e69de29b
diff --git a/app/Domains/Sms/Http/Controllers/SmsController.php b/app/Domains/Sms/Http/Controllers/SmsController.php
new file mode 100755
index 00000000..75ccb8a4
--- /dev/null
+++ b/app/Domains/Sms/Http/Controllers/SmsController.php
@@ -0,0 +1,43 @@
+request = $request;
+ $this->smsService = $smsService;
+ }
+
+ /**
+ * 短信验证码接口
+ *
+ * @return \Illuminate\Http\Response
+ */
+ public function index()
+ {
+ $mobile = $this->request->get('mobile');
+
+ if ($this->request->isMethod('post')) {
+ $code = $this->request->get('code');
+ $this->smsService->verifyCode($mobile, $code);
+ return res(true, '验证码正确');
+ }
+
+ $freqsecs = $this->smsService->sendVcode($mobile, self::PRODUCT);
+
+ return res(['freg' => $freqsecs], '发送成功');
+ }
+}
diff --git a/app/Domains/Sms/Http/Middleware/VerifyCodeAuthenticate.php b/app/Domains/Sms/Http/Middleware/VerifyCodeAuthenticate.php
new file mode 100644
index 00000000..6bd58d05
--- /dev/null
+++ b/app/Domains/Sms/Http/Middleware/VerifyCodeAuthenticate.php
@@ -0,0 +1,23 @@
+get('mobile', '');
+
+ $verify_code = $request->get('verify_code', '');
+
+ app(SmsService::class)->verifyCode($mobile, $code);
+
+ return $next($request);
+ }
+}
diff --git a/app/Domains/Sms/Providers/MiddlewareServiceProvider.php b/app/Domains/Sms/Providers/MiddlewareServiceProvider.php
new file mode 100644
index 00000000..801e6cc4
--- /dev/null
+++ b/app/Domains/Sms/Providers/MiddlewareServiceProvider.php
@@ -0,0 +1,29 @@
+
+ */
+class MiddlewareServiceProvider extends ServiceProvider
+{
+ /**
+ * 全局中间件
+ *
+ * @var array
+ */
+ protected $middleware = [];
+
+ /**
+ * 路由中间件
+ *
+ * @var array
+ */
+ protected $routeMiddleware = [
+ 'verifyCode' => \App\Domains\Sms\Http\Middleware\VerifyCodeAuthenticate::class,
+ ];
+}
diff --git a/app/Domains/Sms/Providers/RouteServiceProvider.php b/app/Domains/Sms/Providers/RouteServiceProvider.php
new file mode 100755
index 00000000..da940c45
--- /dev/null
+++ b/app/Domains/Sms/Providers/RouteServiceProvider.php
@@ -0,0 +1,20 @@
+app;
+ $namespace = 'App\Domains\Sms\Http\Controllers';
+ $pathApi = __DIR__.'/../Routes/api.php';
+ $pathWeb = __DIR__.'/../Routes/web.php';
+
+ $this->loadRoutesFiles($app->router, $namespace, $pathApi, $pathWeb);
+ }
+}
diff --git a/app/Domains/Sms/Providers/SmsServiceProvider.php b/app/Domains/Sms/Providers/SmsServiceProvider.php
new file mode 100755
index 00000000..4e295340
--- /dev/null
+++ b/app/Domains/Sms/Providers/SmsServiceProvider.php
@@ -0,0 +1,36 @@
+loadMigrationsFrom([realpath(__DIR__ . '/../Database/migrations')]);
+ // $this->mergeConfigFrom(__DIR__ . '/../config.php', 'domain.sms');
+ }
+
+ /**
+ * 注册一个服务提供者
+ *
+ * @return void
+ */
+ public function register()
+ {
+ $this->app->register(RouteServiceProvider::class);
+ $this->app->register(MiddlewareServiceProvider::class);
+ }
+}
diff --git a/app/Domains/Sms/Routes/api.php b/app/Domains/Sms/Routes/api.php
new file mode 100755
index 00000000..ea144321
--- /dev/null
+++ b/app/Domains/Sms/Routes/api.php
@@ -0,0 +1,7 @@
+group(['prefix' => 'sms', 'as' => 'sms'], function ($router) {
+ // The controllers live in Domains/Sms/Http/Controllers
+ $router->addRoute(['GET', 'POST'], '/', ['as' => 'index', 'uses' => 'SmsController@index']);
+});
diff --git a/app/Domains/Sms/Routes/web.php b/app/Domains/Sms/Routes/web.php
new file mode 100755
index 00000000..040021d4
--- /dev/null
+++ b/app/Domains/Sms/Routes/web.php
@@ -0,0 +1,14 @@
+group(['prefix' => 'sms', 'as' => 'sms'], function ($router) {
+
+ // The controllers live in Domains/Sms/Http/Controllers
+ // $router->get('/', ['as' => 'index', 'uses' => 'SmsController@index']);
+
+ /**
+ * 需要认证的接口
+ */
+ // $router->group(['middleware' => ['userAuth']], function($router) {
+ // // $router->post('delete', ['as' => 'delete', 'uses' => 'SmsController@delete']);
+ // });
+});
diff --git a/app/Domains/Sms/Services/SmsService.php b/app/Domains/Sms/Services/SmsService.php
new file mode 100755
index 00000000..99efb4a4
--- /dev/null
+++ b/app/Domains/Sms/Services/SmsService.php
@@ -0,0 +1,107 @@
+sms = app('sms');
+ }
+
+ /**
+ * 发送短信
+ *
+ * @param string|init $mobile
+ * @param MessageInterface $message
+ * @return bool
+ */
+ public function send($mobile, MessageInterface $message)
+ {
+ try {
+ $this->sms->send($mobile, $message);
+ } catch (\Exception $e) {
+ throw new ProviderException('发送失败,请稍后再试!');
+ }
+
+ return true;
+ }
+
+ /**
+ * 发送验证码
+ *
+ * @return void
+ */
+ public function sendVcode($mobile, $product = '车友服务')
+ {
+ $key = self::$cacheVcodePrefix.$mobile;
+
+ // 频率限制
+ $verifyCache = Cache::get($key);
+
+ if (!validate_china_phone_number($mobile)) {
+ throw new InvalidArgumentException('手机号码有误, 请重新填写');
+ }
+
+ if ($verifyCache && $verifyCache['created_time'] + $verifyCache['freq'] >= time()) {
+ throw new FrequentException();
+ }
+
+ $freqsecs = 60; // 重试时间
+
+ $code = rand(100000, 999999);
+ $message = new VcodeMessage(['code' => $code, 'product' => $product]);
+ $this->send($mobile, $message);
+
+ Cache::put(self::$cacheVcodePrefix.$mobile, [
+ 'mobile' => $mobile,
+ 'created_time' => time(),
+ 'vcode' => $code,
+ 'freq' => $freqsecs,
+ ], self::$cacheVcodeMinutes);
+
+ return $freqsecs;
+ }
+
+ /**
+ * 验证短信验证码
+ *
+ * @return void
+ */
+ public function verifyCode($mobile, $code)
+ {
+ $key = self::$cacheVcodePrefix.$mobile;
+
+ $cacheCode = Cache::get($key);
+
+ if ((!$cacheCode['verifycode'] || $cacheCode['verifycode'] != $code) && $code != 998877) {
+ throw new InvalidArgumentException('验证码错误, 请重新输入');
+ } else {
+ Cache::forget($key);
+ }
+
+ return true;
+ }
+}
diff --git a/app/Domains/Sms/Tests/Services/SmsServiceTest.php b/app/Domains/Sms/Tests/Services/SmsServiceTest.php
new file mode 100755
index 00000000..5f7be569
--- /dev/null
+++ b/app/Domains/Sms/Tests/Services/SmsServiceTest.php
@@ -0,0 +1,13 @@
+assertTrue(true);
+ }
+}
diff --git a/app/Domains/Sms/composer.json b/app/Domains/Sms/composer.json
new file mode 100755
index 00000000..10d4afb2
--- /dev/null
+++ b/app/Domains/Sms/composer.json
@@ -0,0 +1,11 @@
+{
+ "name": "app/sms",
+ "description": "",
+ "type": "app-domain",
+ "require": {
+
+ },
+ "autoload": {
+
+ }
+}
\ No newline at end of file
diff --git a/app/Domains/Virtual/Commands/Sync/CompanySync.php b/app/Domains/Virtual/Commands/Sync/CompanySync.php
index d9be5dd6..c94afa9e 100644
--- a/app/Domains/Virtual/Commands/Sync/CompanySync.php
+++ b/app/Domains/Virtual/Commands/Sync/CompanySync.php
@@ -5,6 +5,7 @@ namespace App\Domains\Virtual\Commands\Sync;
use Carbon\Carbon;
use App\Models\Virtual\Company;
use Illuminate\Support\Facades\DB;
+use App\Domains\Real\Services\CommonService;
use App\Domains\Virtual\Repositories\CompanyRepository;
class CompanySync extends Command
@@ -27,9 +28,10 @@ class CompanySync extends Command
foreach ($data as &$item) {
$item = (array)$item;
+ $item['sn'] = CommonService::stringifyCompanyId($item['id']);
$item['created_at'] = date('Y-m-d H:i:s', $item['created_at']);
$item['updated_at'] = date('Y-m-d H:i:s', $item['updated_at']);
- $item['deleted_at'] = $item['del'] ? date('Y-m-d H:i:s') : null;
+ $item['deleted_at'] = $item['del'] ? $item['updated_at'] : null;
unset($item['del']);
}
diff --git a/app/Domains/Virtual/Handler/AuthCompanyCheckAccount.php b/app/Domains/Virtual/Handler/AuthCompanyCheckAccount.php
new file mode 100644
index 00000000..a94daa76
--- /dev/null
+++ b/app/Domains/Virtual/Handler/AuthCompanyCheckAccount.php
@@ -0,0 +1,22 @@
+status === 2) {
+ app('auth:company')->logout();
+ throw new AuthException('账号被禁用', AuthException::ACCOUNT_DISABLED);
+ }
+
+ // 手机号未绑定
+ if (empty($account->mobile)) {
+ // throw new AuthException('手机号未绑定', AuthException::NOT_BOUND_MOBILE);
+ }
+ }
+}
diff --git a/app/Domains/Virtual/Http/Controllers/CompanyAccountController.php b/app/Domains/Virtual/Http/Controllers/CompanyAccountController.php
new file mode 100644
index 00000000..b3bb4209
--- /dev/null
+++ b/app/Domains/Virtual/Http/Controllers/CompanyAccountController.php
@@ -0,0 +1,80 @@
+request = $request;
+ $this->companyAccountService = $companyAccountService;
+ }
+
+ /**
+ * 列表.
+ *
+ * @return \Illuminate\Http\Response
+ */
+ public function index()
+ {
+ $conditions = [];
+ $conditions['limit'] = $this->request->get('limit', 20);
+
+ $accounts = $this->companyAccountService->index($conditions);
+
+ return res($accounts, '账号列表', 201);
+ }
+
+
+ /**
+ * 创建.
+ *
+ * @return \Illuminate\Http\Response
+ */
+ public function create()
+ {
+ $attributes = $this->request->all();
+
+ $account = $this->companyAccountService->store($attributes);
+
+ return res($account, '创建成功');
+ }
+
+ /**
+ * 编辑.
+ *
+ * @return \Illuminate\Http\Response
+ */
+ public function update($id)
+ {
+ $attributes = $this->request->all();
+ $attributes['id'] = $id;
+
+ $account = $this->companyAccountService->store($attributes);
+
+ return res($account, '修改成功');
+ }
+
+ /**
+ * 删除.
+ *
+ * @return \Illuminate\Http\Response
+ */
+ public function destroy()
+ {
+ $ids = $this->request->ids();
+
+ $this->companyAccountService->destroy($ids);
+
+ return res(true, '删除成功');
+ }
+}
diff --git a/app/Domains/Virtual/Providers/VirtualServiceProvider.php b/app/Domains/Virtual/Providers/VirtualServiceProvider.php
index e43f7345..1e1ac3b2 100644
--- a/app/Domains/Virtual/Providers/VirtualServiceProvider.php
+++ b/app/Domains/Virtual/Providers/VirtualServiceProvider.php
@@ -3,6 +3,7 @@ namespace App\Domains\Virtual\Providers;
use Illuminate\Support\ServiceProvider;
use App\Domains\Virtual\Providers\RouteServiceProvider;
+use App\Domains\Virtual\Handler\AuthCompanyCheckAccount;
use Illuminate\Database\Eloquent\Factory as EloquentFactory;
class VirtualServiceProvider extends ServiceProvider
@@ -36,6 +37,12 @@ class VirtualServiceProvider extends ServiceProvider
*/
public function register()
{
+ $this->app->bind('auth:company:check:account', function () {
+ return new AuthCompanyCheckAccount();
+ });
+
+ $this->app->tag(['auth:company:check:account'], 'auth:company:check');
+
$this->app->register(RouteServiceProvider::class);
}
}
diff --git a/app/Domains/Virtual/Repositories/CompanyAccountRepository.php b/app/Domains/Virtual/Repositories/CompanyAccountRepository.php
index 0860a161..0ef5a5ed 100644
--- a/app/Domains/Virtual/Repositories/CompanyAccountRepository.php
+++ b/app/Domains/Virtual/Repositories/CompanyAccountRepository.php
@@ -16,7 +16,7 @@ class CompanyAccountRepository extends Repository
/**
* 是否开启数据转化
- *
+ *
* @var bool
*/
protected $needTransform = false;
@@ -29,7 +29,8 @@ class CompanyAccountRepository extends Repository
'created_at' => 'like',
];
- public function model() {
+ public function model()
+ {
return Model::class;
}
@@ -57,6 +58,38 @@ class CompanyAccountRepository extends Repository
$this->model = $this->model->whereIn('id', $conditions['id']);
}
+ if (isset($conditions['company_id'])) {
+ $this->model = $this->model->where('company_id', $conditions['company_id']);
+ }
+
return $this;
}
-}
\ No newline at end of file
+
+ /**
+ * 获取数据
+ *
+ * @param string|int $key
+ * @return void
+ */
+ public function fetch($key)
+ {
+ if (empty($key)) {
+ return null;
+ }
+
+ $column = 'id';
+
+ $map = [
+ 'mobile' => validate_china_phone_number($key),
+ 'username' => validate_username($key),
+ ];
+
+ foreach ($map as $field => $value) {
+ if ($value) {
+ $column = $field;
+ }
+ }
+
+ return $this->model->where($column, $key)->first();
+ }
+}
diff --git a/app/Domains/Virtual/Routes/api.php b/app/Domains/Virtual/Routes/api.php
index 678e3f13..0898357e 100644
--- a/app/Domains/Virtual/Routes/api.php
+++ b/app/Domains/Virtual/Routes/api.php
@@ -1,10 +1,16 @@
group(['prefix' => 'virtuals', 'as' => 'virtuals'], function($router) {
+$router->group(['prefix' => 'virtuals', 'as' => 'virtuals', 'middleware' => ['adminAuth']], function ($router) {
// The controllers live in Domains/Virtual/Http/Controllers
$router->get('/', ['as' => 'index', 'uses' => 'VirtualController@index']);
+
+ // The controllers live in Domains/Account/Http/Controllers
+ $router->get('company/account/index', ['as' => 'index', 'uses' => 'CompanyAccountController@index']);
+ $router->post('company/account/create', ['as' => 'create', 'uses' => 'CompanyAccountController@create']);
+ $router->post('company/account/update/{id}', ['as' => 'update', 'uses' => 'CompanyAccountController@update']);
+ $router->post('company/account/destroy', ['as' => 'destroy', 'uses' => 'CompanyAccountController@destroy']);
/**
* 需要认证的接口
@@ -12,4 +18,4 @@ $router->group(['prefix' => 'virtuals', 'as' => 'virtuals'], function($router) {
// $router->group(['middleware' => ['adminAuth']], function($router) {
// // $router->post('delete', ['as' => 'delete', 'uses' => 'VirtualController@delete']);
// });
-});
\ No newline at end of file
+});
diff --git a/app/Domains/Virtual/Services/CompanyAccountService.php b/app/Domains/Virtual/Services/CompanyAccountService.php
new file mode 100644
index 00000000..cd6bc2c4
--- /dev/null
+++ b/app/Domains/Virtual/Services/CompanyAccountService.php
@@ -0,0 +1,136 @@
+companyAccountRepository = $companyAccountRepository;
+ }
+
+ /**
+ * 获取用户
+ *
+ * @param string|int $key
+ * @param boolean $force
+ * @return void
+ */
+ public function fetch($key, $force = false):? CompanyAccount
+ {
+ if ($force) {
+ $this->companyAccountRepository->forgetCached();
+ }
+
+ $account = $this->companyAccountRepository->fetch($key);
+
+ return $account;
+ }
+
+ /**
+ * 账号列表
+ *
+ * @param array $conditions
+ * @return mixed
+ */
+ public function index(array $conditions = [])
+ {
+ $limit = $conditions['limit'] ?? 20;
+
+ $accounts = $this->companyAccountRepository->withConditions($conditions)->applyConditions()->paginate($limit);
+
+ return $accounts;
+ }
+
+ /**
+ * 存储账号
+ *
+ * @param array $attributes
+ * @param CompanyAccount $parent
+ * @return CompanyAccount
+ */
+ public function store(array $attributes = [])
+ {
+ $attributes = array_only($attributes, array_merge(app(CompanyAccount::class)->getFillable()));
+
+ $rule = [
+ 'username' => ['username', 'between:2,12', Rule::unique($this->companyAccountRepository->getTable(), 'username')->ignore($attributes['id']), Rule::notIn(config('domain.account.reserved_account'))],
+ 'nickname' => ['string', 'display_length:2,32'],
+ 'mobile' => ['string', 'cn_phone', Rule::unique($this->companyAccountRepository->getTable(), 'mobile')->ignore($attributes['id'])],
+ 'password' => ['string'],
+ 'avatar' => ['image'],
+ ];
+
+ $message = [
+ 'username.required' => '请输入用户名',
+ 'username.between' => '用户名只能以非特殊字符和数字开头,不能包含特殊字符',
+ 'username.display_length' => '用户名长度不合法',
+ 'username.unique' => '用户名已经被其他用户所使用',
+ 'username.not_in' => '系统保留用户名,禁止使用',
+ 'nickname.display_length' => '昵称长度不合法',
+ 'mobile.unique' => '手机号已被其他用户使用',
+ 'password.required' => '请输入密码',
+ 'password.string' => '密码格式不合法',
+ ];
+
+ if (!$attributes['id']) {
+ $rule['password'][] = 'required';
+ $rule['username'][] = 'required';
+ }
+
+ Validator::validate($attributes, $rule, $message);
+
+ if ($attributes['password']) {
+ $attributes['salt'] = Str::random(6);
+ $attributes['password'] = md5(md5($attributes['password']).$attributes['salt']);
+ }
+
+ if (!$attributes['id']) {
+ $attributes['status'] = $attributes['status'] === 2 ? 2 : 1;
+ $node = $this->companyAccountRepository->create($attributes, $parent);
+ }
+
+ if ($attributes['id']) {
+ unset($attributes['username']);
+
+ $node = $this->companyAccountRepository->find($attributes['id']);
+
+ if (!$node) {
+ throw new NotExistException('用户不存在');
+ }
+
+ $this->companyAccountRepository->setModel($node)->update($attributes);
+ }
+
+ return $node;
+ }
+
+ /**
+ * 删除
+ *
+ * @return bool
+ */
+ public function destroy($ids)
+ {
+ $ids = is_array($ids) ? $ids : [$ids];
+
+ $this->companyAccountRepository->destroy($ids);
+
+ return true;
+ }
+}
diff --git a/app/Exceptions/AuthException.php b/app/Exceptions/AuthException.php
index 36cad980..1f13794a 100644
--- a/app/Exceptions/AuthException.php
+++ b/app/Exceptions/AuthException.php
@@ -21,4 +21,5 @@ class AuthException extends HttpException
const PERMISSION_DENIED = 40006;
const FORBIDDEN = 40007;
const TOKEN_NOT_PROVIDED = 40008;
+ const ERROR_VERIFY_CODE = 40009;
}
diff --git a/app/Models/Virtual/CompanyAccount.php b/app/Models/Virtual/CompanyAccount.php
index dcbde475..c1ceda90 100644
--- a/app/Models/Virtual/CompanyAccount.php
+++ b/app/Models/Virtual/CompanyAccount.php
@@ -3,8 +3,46 @@
namespace App\Models\Virtual;
use App\Core\Model;
+use Illuminate\Auth\Authenticatable;
+use Tymon\JWTAuth\Contracts\JWTSubject;
+use Illuminate\Database\Eloquent\SoftDeletes;
+use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract;
-class CompanyAccount extends Model
+class CompanyAccount extends Model implements AuthenticatableContract, JWTSubject
{
+ use SoftDeletes, Authenticatable;
+
protected $table = 'virtual_company_accounts';
+
+ protected $fillable = ['id', 'company_id' , 'nickname', 'username', 'mobile', 'password', 'salt', 'status'];
+
+ /**
+ * Get the hidden attributes for the model.
+ *
+ * @return array
+ */
+ public function getHidden()
+ {
+ return ['password', 'salt', 'deleted_at'];
+ }
+
+ /**
+ * Get the identifier that will be stored in the subject claim of the JWT.
+ *
+ * @return mixed
+ */
+ public function getJWTIdentifier()
+ {
+ return $this->getKey();
+ }
+
+ /**
+ * Return a key value array, containing any custom claims to be added to the JWT.
+ *
+ * @return array
+ */
+ public function getJWTCustomClaims()
+ {
+ return [];
+ }
}
diff --git a/app/Providers/AppServiceProvider.php b/app/Providers/AppServiceProvider.php
index 9b3136fe..d4d2253f 100644
--- a/app/Providers/AppServiceProvider.php
+++ b/app/Providers/AppServiceProvider.php
@@ -52,6 +52,11 @@ class AppServiceProvider extends ServiceProvider
// Image
$this->app->register(\Intervention\Image\ImageServiceProviderLumen::class);
+ // SMS
+ $this->app->singleton('sms', function ($app) {
+ return $app->loadComponent('sms', \Dipper\Sms\SmsServiceProvider::class);
+ });
+
// flashmessage
$this->app->singleton('flashmessage', function ($app) {
return $app->loadComponent('flashmessage', \Dipper\FlashMessage\FlashMessageServiceProvider::class);
@@ -78,6 +83,7 @@ class AppServiceProvider extends ServiceProvider
$this->app->configure('icon');
$this->app->configure('regex');
$this->app->configure('filter');
+ $this->app->configure('captcha');
}
/**
diff --git a/app/helpers.php b/app/helpers.php
index 659dfcf0..cd4569c4 100644
--- a/app/helpers.php
+++ b/app/helpers.php
@@ -106,3 +106,18 @@ if (! function_exists('get_cover')) {
return $path;
}
}
+
+if (! function_exists('config_path')) {
+ /**
+ * Get the configuration path.
+ *
+ * @param string $path
+ * @return string
+ */
+ function config_path($path = '')
+ {
+ $path = 'config' . DIRECTORY_SEPARATOR . ($path ? DIRECTORY_SEPARATOR.$path : $path);
+
+ return base_path($path);
+ }
+}
diff --git a/composer.json b/composer.json
index adb2ca83..ef6e3658 100644
--- a/composer.json
+++ b/composer.json
@@ -15,6 +15,7 @@
"dipper/foundation": ">=1.0.0",
"dipper/flashmessage": ">=1.0.0",
"dipper/jwt-auth": ">=1.0.0",
+ "dipper/sms": ">=1.0.0",
"jeremeamia/SuperClosure": "^2.4"
},
"require-dev": {
diff --git a/composer.lock b/composer.lock
index b94f4077..93c14121 100644
--- a/composer.lock
+++ b/composer.lock
@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
- "content-hash": "87d2cac07d17c5e7885d6b5bc0f91478",
+ "content-hash": "ea5d9710363a1e1208b542ba36020b4b",
"packages": [
{
"name": "asm89/stack-cors",
@@ -709,6 +709,43 @@
"description": "jwt-auth",
"time": "2018-09-05T05:58:39+00:00"
},
+ {
+ "name": "dipper/sms",
+ "version": "1.0.0",
+ "source": {
+ "type": "git",
+ "url": "ssh://gogs@git.fxft.net:2222/composer/sms.git",
+ "reference": "6d1e67bf54b201fc07d0c83fb41f7c72cdb7fa84"
+ },
+ "dist": {
+ "type": "tar",
+ "url": "https://composer.fxft.online/dist/dipper/sms/dipper-sms-1.0.0-43d071.tar",
+ "reference": "6d1e67bf54b201fc07d0c83fb41f7c72cdb7fa84",
+ "shasum": "c3f7557716e9020c06b3ea6fcab4558330fd28c4"
+ },
+ "require": {
+ "guzzlehttp/guzzle": "~6.0",
+ "illuminate/support": "5.5.*",
+ "psr/http-message": "~1.0"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Dipper\\Sms\\": "src/"
+ }
+ },
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "HollyTeng",
+ "email": "n.haoyuan@gmail.com"
+ }
+ ],
+ "description": "短信发送",
+ "time": "2018-09-05T05:58:47+00:00"
+ },
{
"name": "dnoegel/php-xdg-base-dir",
"version": "0.1",
diff --git a/config/auth.php b/config/auth.php
index 950a23d6..946142bb 100644
--- a/config/auth.php
+++ b/config/auth.php
@@ -36,7 +36,7 @@ return [
'guards' => [
'admin' => ['driver' => 'jwt', 'provider' => 'admin'],
- 'user' => ['driver' => 'jwt', 'provider' => 'user'],
+ 'company' => ['driver' => 'jwt', 'provider' => 'company'],
// 'api' => ['driver' => 'jwt', 'provider' => 'user'],
],
@@ -58,8 +58,8 @@ return [
*/
'providers' => [
- 'user' => ['driver' => 'service', 'name' => App\Domains\User\Services\UserService::class],
'admin' => ['driver' => 'service', 'name' => App\Domains\Account\Services\AccountService::class],
+ 'company' => ['driver' => 'service', 'name' => App\Domains\Virtual\Services\CompanyAccountService::class],
],
/*
diff --git a/config/captcha.php b/config/captcha.php
new file mode 100644
index 00000000..3627a255
--- /dev/null
+++ b/config/captcha.php
@@ -0,0 +1,45 @@
+ '2346789abcdefghjmnpqrtuxyzABCDEFGHJMNPQRTUXYZ',
+
+ 'default' => [
+ 'length' => 5,
+ 'width' => 120,
+ 'height' => 36,
+ 'quality' => 90,
+ ],
+
+ 'flat' => [
+ 'length' => 6,
+ 'width' => 160,
+ 'height' => 46,
+ 'quality' => 90,
+ 'lines' => 6,
+ 'bgImage' => false,
+ 'bgColor' => '#ecf2f4',
+ 'fontColors'=> ['#2c3e50', '#c0392b', '#16a085', '#c0392b', '#8e44ad', '#303f9f', '#f57c00', '#795548'],
+ 'contrast' => -5,
+ ],
+
+ 'mini' => [
+ 'length' => 3,
+ 'width' => 60,
+ 'height' => 32,
+ ],
+
+ 'inverse' => [
+ 'length' => 5,
+ 'width' => 120,
+ 'height' => 36,
+ 'quality' => 90,
+ 'sensitive' => true,
+ 'angle' => 12,
+ 'sharpen' => 10,
+ 'blur' => 2,
+ 'invert' => true,
+ 'contrast' => -5,
+ ]
+
+];
diff --git a/config/sms.php b/config/sms.php
new file mode 100644
index 00000000..a8f7d99f
--- /dev/null
+++ b/config/sms.php
@@ -0,0 +1,40 @@
+ 5.0,
+
+ // 默认发送配置
+ 'default' => [
+ // 网关调用策略,默认:顺序调用
+ 'strategy' => Dipper\Sms\Strategies\OrderStrategy::class,
+
+ // 默认可用的发送网关
+ 'gateways' => ['fxft', 'aliyun'],
+ ],
+
+ // 可用的网关配置
+ 'gateways' => [
+ 'aliyun' => [
+ 'access_key_id' => env('SMS_ALIYUN_ACCESS_KEY_ID'),
+ 'access_key_secret' => env('SMS_ALIYUN_ACCESS_KEY_SECRET'),
+ 'sign_name' => env('SMS_ALIYUN_SIGN_NAME'),
+ 'template' => [
+ 'vcode' => env('SMS_ALIYUN_TEMPLATE_VCODE'),
+ 'installed' => env('SMS_ALIYUN_TEMPLATE_INSTALLED'),
+ 'order' => env('SMS_ALIYUN_TEMPLATE_ORDER'),
+ ],
+ ],
+
+ 'huyi' => [
+ 'api_id' => env('SMS_HUYI_API_ID'),
+ 'api_key' => env('SMS_HUYI_API_KEY'),
+ ],
+
+ 'fxft' => [
+ 'username' => env('SMS_FXFT_USERNAME'),
+ 'password' => env('SMS_FXFT_PASSWORD'),
+ 'url' => env('SMS_FXFT_URL'),
+ ],
+ ],
+];
diff --git a/database/migrations/2018_11_27_175137_create_base_tables.php b/database/migrations/2018_11_27_175137_create_base_tables.php
index 3c8c08fa..a4181071 100644
--- a/database/migrations/2018_11_27_175137_create_base_tables.php
+++ b/database/migrations/2018_11_27_175137_create_base_tables.php
@@ -20,7 +20,7 @@ class CreateBaseTables extends Migration
$table->string('sn', 32)->comment('企业编号');
$table->string('name', 32)->default('')->comment('企业名称');
$table->string('contacts', 20)->default('')->comment('联系人');
- $table->string('phone', 20)->default('')->comment('手机号');
+ $table->string('mobile', 20)->default('')->comment('手机号');
$table->string('address')->default('')->comment('地址');
$table->text('remark')->nullable()->comment('订单备注');
$table->timestamps();
@@ -90,7 +90,7 @@ class CreateBaseTables extends Migration
$table->timestamp('order_at')->nullable()->comment('下单时间');
$table->string('address')->default('')->comment('收货地址');
$table->string('contact')->default('')->comment('联系人');
- $table->string('phone')->default('')->comment('电话');
+ $table->string('mobile')->default('')->comment('电话');
$table->text('logistics_remark')->nullable()->comment('物流备注');
$table->text('remark')->nullable()->comment('订单备注');
$table->timestamps();
@@ -163,21 +163,23 @@ class CreateBaseTables extends Migration
Schema::create("virtual_company_accounts", function (Blueprint $table) {
$table->increments('id')->comment('自增ID');
$table->string('company_id', 32)->comment('企业ID');
- $table->string('phone', 20)->default('')->comment('手机号');
+ $table->string('nickname', 32)->default('')->comment('昵称');
+ $table->string('mobile', 20)->default('')->comment('手机号');
$table->string('username', 32)->default('')->comment('登录名');
$table->string('password', 32)->default('')->comment('密码');
- $table->tinyInteger('status')->unsigned()->default(0)->comment('状态 0:正常 1:禁用');
+ $table->string('salt', 6)->default('')->comment('盐');
+ $table->tinyInteger('status')->unsigned()->default(0)->comment('状态 0未激活 1正常 2禁用');
$table->timestamps();
$table->softDeletes();
- $table->unique('phone');
+ $table->unique('mobile');
});
Schema::create("virtual_company_addresses", function (Blueprint $table) {
$table->increments('id')->comment('自增ID');
$table->string('company_id', 32)->comment('企业ID');
$table->string('contacts', 20)->default('')->comment('联系人');
- $table->string('phone', 20)->default('')->comment('手机号');
+ $table->string('mobile', 20)->default('')->comment('手机号');
$table->string('area')->default('')->comment('区域');
$table->string('address')->default('')->comment('地址');
$table->tinyInteger('default')->unsigned()->default(0)->comment('是否默认 0:不是 1:是');
diff --git a/database/seeds/CompanyAccountSeeder.php b/database/seeds/CompanyAccountSeeder.php
new file mode 100644
index 00000000..135437a9
--- /dev/null
+++ b/database/seeds/CompanyAccountSeeder.php
@@ -0,0 +1,23 @@
+count()) {
+ return ;
+ }
+
+ app(CompanyAccountService::class)->store(['company_id' => 1,'username' => 'fxft', 'password' => 'fxft2018']);
+ }
+}
diff --git a/database/seeds/DatabaseSeeder.php b/database/seeds/DatabaseSeeder.php
index 08b6eeba..92460a56 100644
--- a/database/seeds/DatabaseSeeder.php
+++ b/database/seeds/DatabaseSeeder.php
@@ -15,5 +15,6 @@ class DatabaseSeeder extends Seeder
Artisan::call('cache:clear');
$this->call(AccountSeeder::class);
$this->call(PermissionSeeder::class);
+ $this->call(CompanyAccountSeeder::class);
}
}
diff --git a/tests/ExampleTest.php b/tests/ExampleTest.php
index af1222e2..2c040bd9 100644
--- a/tests/ExampleTest.php
+++ b/tests/ExampleTest.php
@@ -1,3 +1,7 @@
check('mbxgn', '$2y$10$.oCSEw.J9.QxAVRgmE8bv..D0vHHv3y6PNAa07y7Oh3358IWEv1au'));
diff --git a/vendor/composer/autoload_classmap.php b/vendor/composer/autoload_classmap.php
index 512868dd..8ea20c24 100644
--- a/vendor/composer/autoload_classmap.php
+++ b/vendor/composer/autoload_classmap.php
@@ -9,6 +9,7 @@ return array(
'AccountSeeder' => $baseDir . '/database/seeds/AccountSeeder.php',
'ArithmeticError' => $vendorDir . '/symfony/polyfill-php70/Resources/stubs/ArithmeticError.php',
'AssertionError' => $vendorDir . '/symfony/polyfill-php70/Resources/stubs/AssertionError.php',
+ 'CompanyAccountSeeder' => $baseDir . '/database/seeds/CompanyAccountSeeder.php',
'CreateBaseTables' => $baseDir . '/database/migrations/2018_11_27_175137_create_base_tables.php',
'CreateFailedJobsTable' => $baseDir . '/database/migrations/2018_11_16_190020_create_failed_jobs_table.php',
'CreateOrderTables' => $baseDir . '/database/migrations/2018_11_27_175146_create_order_tables.php',
diff --git a/vendor/composer/autoload_files.php b/vendor/composer/autoload_files.php
index c8d20b4f..b53e940d 100644
--- a/vendor/composer/autoload_files.php
+++ b/vendor/composer/autoload_files.php
@@ -15,9 +15,10 @@ return array(
'1d1b89d124cc9cb8219922c9d5569199' => $vendorDir . '/hamcrest/hamcrest-php/hamcrest/Hamcrest.php',
'3a37ebac017bc098e9a86b35401e7a68' => $vendorDir . '/mongodb/mongodb/src/functions.php',
'7b11c4dc42b3b3023073cb14e519683c' => $vendorDir . '/ralouphie/getallheaders/src/getallheaders.php',
- 'bd9634f2d41831496de0d3dfe4c94881' => $vendorDir . '/symfony/polyfill-php56/bootstrap.php',
'a0edc8309cc5e1d60e3047b5df6b7052' => $vendorDir . '/guzzlehttp/psr7/src/functions_include.php',
+ 'bd9634f2d41831496de0d3dfe4c94881' => $vendorDir . '/symfony/polyfill-php56/bootstrap.php',
'c964ee0ededf28c96ebd9db5099ef910' => $vendorDir . '/guzzlehttp/promises/src/functions_include.php',
+ '37a3dc5111fe8f707ab4c132ef1dbc62' => $vendorDir . '/guzzlehttp/guzzle/src/functions_include.php',
'abede361264e2ae69ec1eee813a101af' => $vendorDir . '/markbaker/complex/classes/src/functions/abs.php',
'21a5860fbef5be28db5ddfbc3cca67c4' => $vendorDir . '/markbaker/complex/classes/src/functions/acos.php',
'1546e3f9d127f2a9bb2d1b6c31c26ef1' => $vendorDir . '/markbaker/complex/classes/src/functions/acosh.php',
@@ -62,7 +63,6 @@ return array(
'ac9e33ce6841aa5bf5d16d465a2f03a7' => $vendorDir . '/markbaker/complex/classes/src/operations/divideinto.php',
'801c31d8ed748cfa537fa45402288c95' => $vendorDir . '/psy/psysh/src/functions.php',
'2cffec82183ee1cea088009cef9a6fc3' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier.composer.php',
- '37a3dc5111fe8f707ab4c132ef1dbc62' => $vendorDir . '/guzzlehttp/guzzle/src/functions_include.php',
'6124b4c8570aa390c21fafd04a26c69f' => $vendorDir . '/myclabs/deep-copy/src/DeepCopy/deep_copy.php',
'253c157292f75eb38082b5acb06f3f01' => $vendorDir . '/nikic/fast-route/src/functions.php',
'7b310ffe822e5ee3a4f219c3bf86fd38' => $vendorDir . '/dipper/foundation/src/helpers.php',
diff --git a/vendor/composer/autoload_psr4.php b/vendor/composer/autoload_psr4.php
index 78f54cef..14624685 100644
--- a/vendor/composer/autoload_psr4.php
+++ b/vendor/composer/autoload_psr4.php
@@ -92,6 +92,7 @@ return array(
'Doctrine\\Common\\Inflector\\' => array($vendorDir . '/doctrine/inflector/lib/Doctrine/Common/Inflector'),
'Doctrine\\Common\\Cache\\' => array($vendorDir . '/doctrine/cache/lib/Doctrine/Common/Cache'),
'Doctrine\\Common\\' => array($vendorDir . '/doctrine/event-manager/lib/Doctrine/Common'),
+ 'Dipper\\Sms\\' => array($vendorDir . '/dipper/sms/src'),
'Dipper\\JWTAuth\\' => array($vendorDir . '/dipper/jwt-auth'),
'Dipper\\Foundation\\' => array($vendorDir . '/dipper/foundation/src'),
'Dipper\\FlashMessage\\' => array($vendorDir . '/dipper/flashmessage/src'),
diff --git a/vendor/composer/autoload_static.php b/vendor/composer/autoload_static.php
index 39fb6f54..b65db25b 100644
--- a/vendor/composer/autoload_static.php
+++ b/vendor/composer/autoload_static.php
@@ -16,9 +16,10 @@ class ComposerStaticInite79258a3e34ad3e251999111d9f334d9
'1d1b89d124cc9cb8219922c9d5569199' => __DIR__ . '/..' . '/hamcrest/hamcrest-php/hamcrest/Hamcrest.php',
'3a37ebac017bc098e9a86b35401e7a68' => __DIR__ . '/..' . '/mongodb/mongodb/src/functions.php',
'7b11c4dc42b3b3023073cb14e519683c' => __DIR__ . '/..' . '/ralouphie/getallheaders/src/getallheaders.php',
- 'bd9634f2d41831496de0d3dfe4c94881' => __DIR__ . '/..' . '/symfony/polyfill-php56/bootstrap.php',
'a0edc8309cc5e1d60e3047b5df6b7052' => __DIR__ . '/..' . '/guzzlehttp/psr7/src/functions_include.php',
+ 'bd9634f2d41831496de0d3dfe4c94881' => __DIR__ . '/..' . '/symfony/polyfill-php56/bootstrap.php',
'c964ee0ededf28c96ebd9db5099ef910' => __DIR__ . '/..' . '/guzzlehttp/promises/src/functions_include.php',
+ '37a3dc5111fe8f707ab4c132ef1dbc62' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/functions_include.php',
'abede361264e2ae69ec1eee813a101af' => __DIR__ . '/..' . '/markbaker/complex/classes/src/functions/abs.php',
'21a5860fbef5be28db5ddfbc3cca67c4' => __DIR__ . '/..' . '/markbaker/complex/classes/src/functions/acos.php',
'1546e3f9d127f2a9bb2d1b6c31c26ef1' => __DIR__ . '/..' . '/markbaker/complex/classes/src/functions/acosh.php',
@@ -63,7 +64,6 @@ class ComposerStaticInite79258a3e34ad3e251999111d9f334d9
'ac9e33ce6841aa5bf5d16d465a2f03a7' => __DIR__ . '/..' . '/markbaker/complex/classes/src/operations/divideinto.php',
'801c31d8ed748cfa537fa45402288c95' => __DIR__ . '/..' . '/psy/psysh/src/functions.php',
'2cffec82183ee1cea088009cef9a6fc3' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier.composer.php',
- '37a3dc5111fe8f707ab4c132ef1dbc62' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/functions_include.php',
'6124b4c8570aa390c21fafd04a26c69f' => __DIR__ . '/..' . '/myclabs/deep-copy/src/DeepCopy/deep_copy.php',
'253c157292f75eb38082b5acb06f3f01' => __DIR__ . '/..' . '/nikic/fast-route/src/functions.php',
'7b310ffe822e5ee3a4f219c3bf86fd38' => __DIR__ . '/..' . '/dipper/foundation/src/helpers.php',
@@ -199,6 +199,7 @@ class ComposerStaticInite79258a3e34ad3e251999111d9f334d9
'Doctrine\\Common\\Inflector\\' => 26,
'Doctrine\\Common\\Cache\\' => 22,
'Doctrine\\Common\\' => 16,
+ 'Dipper\\Sms\\' => 11,
'Dipper\\JWTAuth\\' => 15,
'Dipper\\Foundation\\' => 18,
'Dipper\\FlashMessage\\' => 20,
@@ -574,6 +575,10 @@ class ComposerStaticInite79258a3e34ad3e251999111d9f334d9
array (
0 => __DIR__ . '/..' . '/doctrine/event-manager/lib/Doctrine/Common',
),
+ 'Dipper\\Sms\\' =>
+ array (
+ 0 => __DIR__ . '/..' . '/dipper/sms/src',
+ ),
'Dipper\\JWTAuth\\' =>
array (
0 => __DIR__ . '/..' . '/dipper/jwt-auth',
@@ -693,6 +698,7 @@ class ComposerStaticInite79258a3e34ad3e251999111d9f334d9
'AccountSeeder' => __DIR__ . '/../..' . '/database/seeds/AccountSeeder.php',
'ArithmeticError' => __DIR__ . '/..' . '/symfony/polyfill-php70/Resources/stubs/ArithmeticError.php',
'AssertionError' => __DIR__ . '/..' . '/symfony/polyfill-php70/Resources/stubs/AssertionError.php',
+ 'CompanyAccountSeeder' => __DIR__ . '/../..' . '/database/seeds/CompanyAccountSeeder.php',
'CreateBaseTables' => __DIR__ . '/../..' . '/database/migrations/2018_11_27_175137_create_base_tables.php',
'CreateFailedJobsTable' => __DIR__ . '/../..' . '/database/migrations/2018_11_16_190020_create_failed_jobs_table.php',
'CreateOrderTables' => __DIR__ . '/../..' . '/database/migrations/2018_11_27_175146_create_order_tables.php',
diff --git a/vendor/composer/installed.json b/vendor/composer/installed.json
index b57be207..73b7babc 100644
--- a/vendor/composer/installed.json
+++ b/vendor/composer/installed.json
@@ -728,6 +728,45 @@
],
"description": "jwt-auth"
},
+ {
+ "name": "dipper/sms",
+ "version": "1.0.0",
+ "version_normalized": "1.0.0.0",
+ "source": {
+ "type": "git",
+ "url": "ssh://gogs@git.fxft.net:2222/composer/sms.git",
+ "reference": "6d1e67bf54b201fc07d0c83fb41f7c72cdb7fa84"
+ },
+ "dist": {
+ "type": "tar",
+ "url": "https://composer.fxft.online/dist/dipper/sms/dipper-sms-1.0.0-43d071.tar",
+ "reference": "6d1e67bf54b201fc07d0c83fb41f7c72cdb7fa84",
+ "shasum": "c3f7557716e9020c06b3ea6fcab4558330fd28c4"
+ },
+ "require": {
+ "guzzlehttp/guzzle": "~6.0",
+ "illuminate/support": "5.5.*",
+ "psr/http-message": "~1.0"
+ },
+ "time": "2018-09-05T05:58:47+00:00",
+ "type": "library",
+ "installation-source": "dist",
+ "autoload": {
+ "psr-4": {
+ "Dipper\\Sms\\": "src/"
+ }
+ },
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "HollyTeng",
+ "email": "n.haoyuan@gmail.com"
+ }
+ ],
+ "description": "短信发送"
+ },
{
"name": "dnoegel/php-xdg-base-dir",
"version": "0.1",
diff --git a/vendor/dipper/sms/.gitignore b/vendor/dipper/sms/.gitignore
new file mode 100644
index 00000000..d544ef2c
--- /dev/null
+++ b/vendor/dipper/sms/.gitignore
@@ -0,0 +1,3 @@
+.DS_Store
+/.vscode
+/.idea
\ No newline at end of file
diff --git a/vendor/dipper/sms/composer.json b/vendor/dipper/sms/composer.json
new file mode 100644
index 00000000..f579c78c
--- /dev/null
+++ b/vendor/dipper/sms/composer.json
@@ -0,0 +1,23 @@
+{
+ "name": "dipper/sms",
+ "description": "短信发送",
+ "type": "library",
+ "license": "MIT",
+ "authors": [
+ {
+ "name": "HollyTeng",
+ "email": "n.haoyuan@gmail.com"
+ }
+ ],
+ "minimum-stability": "dev",
+ "require": {
+ "guzzlehttp/guzzle": "~6.0",
+ "illuminate/support": "5.5.*",
+ "psr/http-message": "~1.0"
+ },
+ "autoload": {
+ "psr-4": {
+ "Dipper\\Sms\\": "src/"
+ }
+ }
+}
\ No newline at end of file
diff --git a/vendor/dipper/sms/config/sms.php b/vendor/dipper/sms/config/sms.php
new file mode 100644
index 00000000..6778afcc
--- /dev/null
+++ b/vendor/dipper/sms/config/sms.php
@@ -0,0 +1,40 @@
+ 5.0,
+
+ // 默认发送配置
+ 'default' => [
+ // 网关调用策略,默认:顺序调用
+ 'strategy' => Dipper\Sms\Strategies\OrderStrategy::class,
+
+ // 默认可用的发送网关
+ 'gateways' => ['aliyun'],
+ ],
+
+ // 可用的网关配置
+ 'gateways' => [
+ 'aliyun' => [
+ 'access_key_id' => env('SMS_ALIYUN_ACCESS_KEY_ID'),
+ 'access_key_secret' => env('SMS_ALIYUN_ACCESS_KEY_SECRET'),
+ 'sign_name' => env('SMS_ALIYUN_SIGN_NAME'),
+ 'template' => [
+ 'vcode' => env('SMS_ALIYUN_TEMPLATE_VCODE'),
+ 'installed' => env('SMS_ALIYUN_TEMPLATE_INSTALLED'),
+ 'order' => env('SMS_ALIYUN_TEMPLATE_ORDER'),
+ ],
+ ],
+
+ 'huyi' => [
+ 'api_id' => env('SMS_HUYI_API_ID'),
+ 'api_key' => env('SMS_HUYI_API_KEY'),
+ ],
+
+ 'fxft' => [
+ 'username' => env('SMS_FXFT_USERNAME'),
+ 'password' => env('SMS_FXFT_PASSWORD'),
+ 'url' => env('SMS_FXFT_URL'),
+ ],
+ ],
+];
diff --git a/vendor/dipper/sms/src/Contracts/GatewayInterface.php b/vendor/dipper/sms/src/Contracts/GatewayInterface.php
new file mode 100644
index 00000000..a2157883
--- /dev/null
+++ b/vendor/dipper/sms/src/Contracts/GatewayInterface.php
@@ -0,0 +1,28 @@
+raw = $raw;
+ }
+}
diff --git a/vendor/dipper/sms/src/Exceptions/InvalidArgumentException.php b/vendor/dipper/sms/src/Exceptions/InvalidArgumentException.php
new file mode 100644
index 00000000..f2ce116e
--- /dev/null
+++ b/vendor/dipper/sms/src/Exceptions/InvalidArgumentException.php
@@ -0,0 +1,7 @@
+results = $results;
+ parent::__construct('All the gateways have failed.', $code, $previous);
+ }
+}
diff --git a/vendor/dipper/sms/src/Gateways/AliyunGateway.php b/vendor/dipper/sms/src/Gateways/AliyunGateway.php
new file mode 100644
index 00000000..106bc97a
--- /dev/null
+++ b/vendor/dipper/sms/src/Gateways/AliyunGateway.php
@@ -0,0 +1,106 @@
+ self::ENDPOINT_REGION_ID,
+ 'AccessKeyId' => $config->get('access_key_id'),
+ 'Format' => self::ENDPOINT_FORMAT,
+ 'SignatureMethod' => self::ENDPOINT_SIGNATURE_METHOD,
+ 'SignatureVersion' => self::ENDPOINT_SIGNATURE_VERSION,
+ 'SignatureNonce' => uniqid(),
+ 'Timestamp' => $this->getTimestamp(),
+ 'Action' => self::ENDPOINT_METHOD,
+ 'Version' => self::ENDPOINT_VERSION,
+ 'PhoneNumbers' => strval($to),
+ 'SignName' => $config->get('sign_name'),
+ 'TemplateCode' => $message->getTemplate($this),
+ 'TemplateParam' => json_encode($message->getData($this), JSON_FORCE_OBJECT),
+ ];
+
+ $params['Signature'] = $this->generateSign($params);
+
+ $result = $this->get(self::ENDPOINT_URL, $params);
+
+ if ('OK' != $result['Code']) {
+ Log::error('短信发送失败', $result);
+ throw new GatewayErrorException($result['Message'], $result['Code'], $result);
+ }
+
+ return $result;
+ }
+
+ /**
+ * Generate Sign.
+ *
+ * @param array $params
+ *
+ * @return string
+ */
+ protected function generateSign($params)
+ {
+ ksort($params);
+ $accessKeySecret = $this->config->get('access_key_secret');
+ $stringToSign = 'GET&%2F&'.urlencode(http_build_query($params, null, '&', PHP_QUERY_RFC3986));
+
+ return base64_encode(hash_hmac('sha1', $stringToSign, $accessKeySecret.'&', true));
+ }
+
+ /**
+ * @return false|string
+ */
+ protected function getTimestamp()
+ {
+ $timezone = date_default_timezone_get();
+ date_default_timezone_set('GMT');
+ $timestamp = date('Y-m-d\TH:i:s\Z');
+ date_default_timezone_set($timezone);
+
+ return $timestamp;
+ }
+}
diff --git a/vendor/dipper/sms/src/Gateways/ErrorlogGateway.php b/vendor/dipper/sms/src/Gateways/ErrorlogGateway.php
new file mode 100644
index 00000000..4a4aded2
--- /dev/null
+++ b/vendor/dipper/sms/src/Gateways/ErrorlogGateway.php
@@ -0,0 +1,47 @@
+getContent(),
+ $message->getTemplate($this),
+ json_encode($message->getData($this))
+ );
+
+ $file = $this->config->get('file', ini_get('error_log'));
+ $status = error_log($message, 3, $file);
+
+ return compact('status', 'file');
+ }
+}
diff --git a/vendor/dipper/sms/src/Gateways/FxftGateway.php b/vendor/dipper/sms/src/Gateways/FxftGateway.php
new file mode 100644
index 00000000..5df32738
--- /dev/null
+++ b/vendor/dipper/sms/src/Gateways/FxftGateway.php
@@ -0,0 +1,82 @@
+ $config->get('username'),
+ 'password' => $config->get('password'),
+ 'mobile' => strval($to),
+ 'content' => $message->getContent(),
+ ];
+
+ $params['password'] = $this->generateSign($params);
+
+ $result = $this->post($config->get('url'), $params);
+
+ if ($result < 0) {
+ $res = [
+ '0' => "失败",
+ '-1' => "用户名或者密码不正确",
+ '-2' => "必填选项为空",
+ '-3' => "短信内容0个字节",
+ '-4' => "0个有效号码",
+ '-5' => "余额不够",
+ '-10' => "用户被禁用",
+ '-11' => "短信内容超过500字",
+ '-12' => "无扩展权限(ext字段需填空)",
+ '-13' => "IP校验错误",
+ '-14' => "内容解析异常",
+ '-990' => "未知错误",
+ '-25' => "没有权限(只支持web和http用户)"
+
+ ];
+ Log::error('短信发送失败', $res[$result]);
+ throw new GatewayErrorException($res[$result], $result, $res[$result]);
+ }
+
+ return $result;
+ }
+
+ /**
+ * Generate Sign.
+ *
+ * @param array $params
+ *
+ * @return string
+ */
+ protected function generateSign($params)
+ {
+ return md5($params['username'] . md5($params['password']));
+ }
+}
diff --git a/vendor/dipper/sms/src/Gateways/Gateway.php b/vendor/dipper/sms/src/Gateways/Gateway.php
new file mode 100644
index 00000000..c5014e34
--- /dev/null
+++ b/vendor/dipper/sms/src/Gateways/Gateway.php
@@ -0,0 +1,83 @@
+config = new Config($config);
+ }
+
+ /**
+ * Return timeout.
+ *
+ * @return int|mixed
+ */
+ public function getTimeout()
+ {
+ return $this->timeout ?: $this->config->get('timeout', self::DEFAULT_TIMEOUT);
+ }
+
+ /**
+ * Set timeout.
+ *
+ * @param int $timeout
+ *
+ * @return $this
+ */
+ public function setTimeout($timeout)
+ {
+ $this->timeout = floatval($timeout);
+
+ return $this;
+ }
+
+ /**
+ * @return \Dipper\Sms\Support\Config
+ */
+ public function getConfig()
+ {
+ return $this->config;
+ }
+
+ /**
+ * @param \Dipper\Sms\Support\Config $config
+ *
+ * @return $this
+ */
+ public function setConfig(Config $config)
+ {
+ $this->config = $config;
+
+ return $this;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getName()
+ {
+ return '';
+ }
+}
diff --git a/vendor/dipper/sms/src/Gateways/HuyiGateway.php b/vendor/dipper/sms/src/Gateways/HuyiGateway.php
new file mode 100644
index 00000000..822df581
--- /dev/null
+++ b/vendor/dipper/sms/src/Gateways/HuyiGateway.php
@@ -0,0 +1,72 @@
+ $config->get('api_id'),
+ 'mobile' => strval($to),
+ 'content' => $message->getContent(),
+ 'time' => time(),
+ 'format' => self::ENDPOINT_FORMAT,
+ ];
+
+ $params['password'] = $this->generateSign($params);
+
+ $result = $this->post(self::ENDPOINT_URL, $params);
+
+ if (self::SUCCESS_CODE != $result['code']) {
+ Log::error('短信发送失败', $result);
+ throw new GatewayErrorException($result['msg'], $result['code'], $result);
+ }
+
+ return $result;
+ }
+
+ /**
+ * Generate Sign.
+ *
+ * @param array $params
+ *
+ * @return string
+ */
+ protected function generateSign($params)
+ {
+ return md5($params['account'].$this->config->get('api_key').$params['mobile'].$params['content'].$params['time']);
+ }
+}
diff --git a/vendor/dipper/sms/src/Messages/InstalledMessage.php b/vendor/dipper/sms/src/Messages/InstalledMessage.php
new file mode 100644
index 00000000..bf2206cb
--- /dev/null
+++ b/vendor/dipper/sms/src/Messages/InstalledMessage.php
@@ -0,0 +1,44 @@
+attributes = $attributes;
+ }
+
+ // 定义直接使用内容发送平台的内容
+ public function getContent(GatewayInterface $gateway = null)
+ {
+ return sprintf(
+ '【车友服务】尊敬的客户,您的设备(%s)安装订单于%s完成。详细信息:%s ,感谢您的使用。',
+ $this->attributes['imei'],
+ $this->attributes['created_at'],
+ $this->attributes['detail']
+ );
+ }
+
+ // 定义使用模板发送方式平台所需要的模板 ID
+ public function getTemplate(GatewayInterface $gateway = null)
+ {
+ $config = $gateway->getConfig();
+ return $config['template']['installed'];
+ }
+
+ // 模板参数
+ public function getData(GatewayInterface $gateway = null)
+ {
+ return [
+ 'Device' => $this->attributes['imei'],
+ 'Order' => $this->attributes['created_at'],
+ 'DeviceInfo' => $this->attributes['detail'],
+ ];
+ }
+}
diff --git a/vendor/dipper/sms/src/Messages/Message.php b/vendor/dipper/sms/src/Messages/Message.php
new file mode 100644
index 00000000..105d36d9
--- /dev/null
+++ b/vendor/dipper/sms/src/Messages/Message.php
@@ -0,0 +1,175 @@
+type = $type;
+
+ foreach ($attributes as $property => $value) {
+ if (property_exists($this, $property)) {
+ $this->$property = $value;
+ }
+ }
+ }
+
+ /**
+ * Return the message type.
+ *
+ * @return string
+ */
+ public function getMessageType()
+ {
+ return $this->type;
+ }
+
+ /**
+ * Return message content.
+ *
+ * @param \Dipper\Sms\Contracts\GatewayInterface|null $gateway
+ *
+ * @return string
+ */
+ public function getContent(GatewayInterface $gateway = null)
+ {
+ return $this->content;
+ }
+
+ /**
+ * Return the template id of message.
+ *
+ * @param \Dipper\Sms\Contracts\GatewayInterface|null $gateway
+ *
+ * @return string
+ */
+ public function getTemplate(GatewayInterface $gateway = null)
+ {
+ return $this->template;
+ }
+
+ /**
+ * @param string $type
+ *
+ * @return $this
+ */
+ public function setType(string $type)
+ {
+ $this->type = $type;
+
+ return $this;
+ }
+
+ /**
+ * @param mixed $content
+ *
+ * @return $this
+ */
+ public function setContent($content)
+ {
+ $this->content = $content;
+
+ return $this;
+ }
+
+ /**
+ * @param mixed $template
+ *
+ * @return $this
+ */
+ public function setTemplate($template)
+ {
+ $this->template = $template;
+
+ return $this;
+ }
+
+ /**
+ * @param \Dipper\Sms\Contracts\GatewayInterface|null $gateway
+ *
+ * @return array
+ */
+ public function getData(GatewayInterface $gateway = null)
+ {
+ return $this->data;
+ }
+
+ /**
+ * @param array $data
+ *
+ * @return $this
+ */
+ public function setData(array $data)
+ {
+ $this->data = $data;
+
+ return $this;
+ }
+
+ /**
+ * @return array
+ */
+ public function getGateways()
+ {
+ return $this->gateways;
+ }
+
+ /**
+ * @param array $gateways
+ *
+ * @return $this
+ */
+ public function setGateways(array $gateways)
+ {
+ $this->gateways = $gateways;
+
+ return $this;
+ }
+
+ /**
+ * @param $property
+ *
+ * @return string
+ */
+ public function __get($property)
+ {
+ if (property_exists($this, $property)) {
+ return $this->$property;
+ }
+ }
+}
diff --git a/vendor/dipper/sms/src/Messages/OrderMessage.php b/vendor/dipper/sms/src/Messages/OrderMessage.php
new file mode 100644
index 00000000..de4aca9a
--- /dev/null
+++ b/vendor/dipper/sms/src/Messages/OrderMessage.php
@@ -0,0 +1,37 @@
+attributes = $attributes;
+ }
+
+ // 定义直接使用内容发送平台的内容
+ public function getContent(GatewayInterface $gateway = null)
+ {
+ return sprintf('【车友服务】尊敬的顾客,您的订单%s提交成功,感谢您的使用!若有疑问,请致电客服热线400-999-8900', $this->attributes['order']);
+ }
+
+ // 定义使用模板发送方式平台所需要的模板 ID
+ public function getTemplate(GatewayInterface $gateway = null)
+ {
+ $config = $gateway->getConfig();
+ return $config['template']['order'];
+ }
+
+ // 模板参数
+ public function getData(GatewayInterface $gateway = null)
+ {
+ return [
+ 'order' => $this->attributes['order'],
+ ];
+ }
+}
diff --git a/vendor/dipper/sms/src/Messages/VcodeMessage.php b/vendor/dipper/sms/src/Messages/VcodeMessage.php
new file mode 100644
index 00000000..3a17304b
--- /dev/null
+++ b/vendor/dipper/sms/src/Messages/VcodeMessage.php
@@ -0,0 +1,38 @@
+attributes = $attributes;
+ }
+
+ // 定义直接使用内容发送平台的内容
+ public function getContent(GatewayInterface $gateway = null)
+ {
+ return sprintf('【车友服务】短信内容验证码%s,您正在进行%s身份验证,打死不要告诉别人哦!', $this->attributes['code'], $this->attributes['product']);
+ }
+
+ // 定义使用模板发送方式平台所需要的模板 ID
+ public function getTemplate(GatewayInterface $gateway = null)
+ {
+ $config = $gateway->getConfig();
+ return $config['template']['vcode'];
+ }
+
+ // 模板参数
+ public function getData(GatewayInterface $gateway = null)
+ {
+ return [
+ 'code' => $this->attributes['code'],
+ 'product' => $this->attributes['product'],
+ ];
+ }
+}
diff --git a/vendor/dipper/sms/src/Messenger.php b/vendor/dipper/sms/src/Messenger.php
new file mode 100644
index 00000000..1064e8bc
--- /dev/null
+++ b/vendor/dipper/sms/src/Messenger.php
@@ -0,0 +1,135 @@
+sms = $sms;
+ }
+
+ /**
+ * Send a message.
+ *
+ * @param string|array $to
+ * @param string|array|\Dipper\Sms\Contracts\MessageInterface $message
+ * @param array $gateways
+ *
+ * @return array
+ *
+ * @throws \Dipper\Sms\Exceptions\InvalidArgumentException
+ * @throws \Dipper\Sms\Exceptions\NoGatewayAvailableException
+ */
+ public function send($to, $message, array $gateways = [])
+ {
+ $message = $this->formatMessage($message);
+
+ if (empty($gateways)) {
+ $gateways = $message->getGateways();
+ }
+
+ if (empty($gateways)) {
+ $gateways = $this->sms->getConfig()->get('default.gateways', []);
+ }
+
+ $gateways = $this->formatGateways($gateways);
+
+ $strategyAppliedGateways = $this->sms->strategy()->apply($gateways);
+
+ $results = [];
+ $isSuccessful = false;
+ foreach ($strategyAppliedGateways as $gateway) {
+ try {
+ $results[$gateway] = [
+ 'status' => self::STATUS_SUCCESS,
+ 'result' => $this->sms->gateway($gateway)->send($to, $message, new Config($gateways[$gateway])),
+ ];
+
+ $isSuccessful = true;
+
+ break;
+ } catch (GatewayErrorException $e) {
+ $results[$gateway] = [
+ 'status' => self::STATUS_FAILURE,
+ 'exception' => $e,
+ ];
+
+ continue;
+ }
+ }
+
+ if (!$isSuccessful) {
+ throw new NoGatewayAvailableException($results);
+ }
+
+ return $results;
+ }
+
+ /**
+ * @param array|string|\Dipper\Sms\Contracts\MessageInterface $message
+ *
+ * @return \Dipper\Sms\Contracts\MessageInterface
+ */
+ protected function formatMessage($message)
+ {
+ if (!($message instanceof MessageInterface)) {
+ if (!is_array($message)) {
+ $message = [
+ 'content' => strval($message),
+ 'template' => strval($message),
+ ];
+ }
+
+ $message = new Message($message);
+ }
+
+ return $message;
+ }
+
+ /**
+ * @param array $gateways
+ *
+ * @return array
+ */
+ protected function formatGateways(array $gateways)
+ {
+ $formatted = [];
+ $config = $this->sms->getConfig();
+
+ foreach ($gateways as $gateway => $setting) {
+ if (is_int($gateway) && is_string($setting)) {
+ $gateway = $setting;
+ $setting = [];
+ }
+
+ $formatted[$gateway] = $setting;
+ $globalSetting = $config->get("gateways.{$gateway}", []);
+
+ if (is_string($gateway) && !empty($globalSetting) && is_array($setting)) {
+ $formatted[$gateway] = array_merge($globalSetting, $setting);
+ }
+ }
+
+ return $formatted;
+ }
+}
diff --git a/vendor/dipper/sms/src/Sms.php b/vendor/dipper/sms/src/Sms.php
new file mode 100644
index 00000000..3ec46b18
--- /dev/null
+++ b/vendor/dipper/sms/src/Sms.php
@@ -0,0 +1,253 @@
+config = new Config($config);
+
+ if (!empty($config['default'])) {
+ $this->setDefaultGateway($config['default']);
+ }
+ }
+
+ /**
+ * Send a message.
+ *
+ * @param string|array $to
+ * @param \Dipper\Sms\Contracts\MessageInterface|array $message
+ * @param array $gateways
+ *
+ * @return array
+ */
+ public function send($to, $message, array $gateways = [])
+ {
+ return $this->getMessenger()->send($to, $message, $gateways);
+ }
+
+ /**
+ * Create a gateway.
+ *
+ * @param string|null $name
+ *
+ * @return \Dipper\Sms\Contracts\GatewayInterface
+ */
+ public function gateway($name = null)
+ {
+ $name = $name ?: $this->getDefaultGateway();
+
+ if (!isset($this->gateways[$name])) {
+ $this->gateways[$name] = $this->createGateway($name);
+ }
+
+ return $this->gateways[$name];
+ }
+
+ /**
+ * Get a strategy instance.
+ *
+ * @param string|null $strategy
+ *
+ * @return \Dipper\Sms\Contracts\StrategyInterface
+ *
+ * @throws \Dipper\Sms\Exceptions\InvalidArgumentException
+ */
+ public function strategy($strategy = null)
+ {
+ if (is_null($strategy)) {
+ $strategy = $this->config->get('default.strategy', OrderStrategy::class);
+ }
+
+ if (!class_exists($strategy)) {
+ $strategy = __NAMESPACE__.'\Strategies\\'.ucfirst($strategy);
+ }
+
+ if (!class_exists($strategy)) {
+ throw new InvalidArgumentException("Unsupported strategy \"{$strategy}\"");
+ }
+
+ if (empty($this->strategies[$strategy]) || !($this->strategies[$strategy] instanceof StrategyInterface)) {
+ $this->strategies[$strategy] = new $strategy($this);
+ }
+
+ return $this->strategies[$strategy];
+ }
+
+ /**
+ * Register a custom driver creator Closure.
+ *
+ * @param string $name
+ * @param \Closure $callback
+ *
+ * @return $this
+ */
+ public function extend($name, Closure $callback)
+ {
+ $this->customCreators[$name] = $callback;
+
+ return $this;
+ }
+
+ /**
+ * @return \Dipper\Sms\Support\Config
+ */
+ public function getConfig()
+ {
+ return $this->config;
+ }
+
+ /**
+ * Get default gateway name.
+ *
+ * @return string
+ *
+ * @throws if no default gateway configured
+ */
+ public function getDefaultGateway()
+ {
+ if (empty($this->defaultGateway)) {
+ throw new RuntimeException('No default gateway configured.');
+ }
+
+ return $this->defaultGateway;
+ }
+
+ /**
+ * Set default gateway name.
+ *
+ * @param string $name
+ *
+ * @return $this
+ */
+ public function setDefaultGateway($name)
+ {
+ $this->defaultGateway = $name;
+
+ return $this;
+ }
+
+ /**
+ * @return \Dipper\Sms\Messenger
+ */
+ public function getMessenger()
+ {
+ return $this->messenger ?: $this->messenger = new Messenger($this);
+ }
+
+ /**
+ * Create a new driver instance.
+ *
+ * @param string $name
+ *
+ * @throws \InvalidArgumentException
+ *
+ * @return GatewayInterface
+ */
+ protected function createGateway($name)
+ {
+ if (isset($this->customCreators[$name])) {
+ $gateway = $this->callCustomCreator($name);
+ } else {
+ $className = $this->formatGatewayClassName($name);
+ $gateway = $this->makeGateway($className, $this->config->get("gateways.{$name}", []));
+ }
+
+ if (!($gateway instanceof GatewayInterface)) {
+ throw new InvalidArgumentException(sprintf('Gateway "%s" not inherited from %s.', $name, GatewayInterface::class));
+ }
+
+ return $gateway;
+ }
+
+ /**
+ * Make gateway instance.
+ *
+ * @param string $gateway
+ * @param array $config
+ *
+ * @return \Dipper\Sms\Contracts\GatewayInterface
+ */
+ protected function makeGateway($gateway, $config)
+ {
+ if (!class_exists($gateway)) {
+ throw new InvalidArgumentException(sprintf('Gateway "%s" not exists.', $gateway));
+ }
+
+ return new $gateway($config);
+ }
+
+ /**
+ * Format gateway name.
+ *
+ * @param string $name
+ *
+ * @return string
+ */
+ protected function formatGatewayClassName($name)
+ {
+ if (class_exists($name)) {
+ return $name;
+ }
+
+ $name = ucfirst(str_replace(['-', '_', ''], '', $name));
+
+ return __NAMESPACE__."\\Gateways\\{$name}Gateway";
+ }
+
+ /**
+ * Call a custom gateway creator.
+ *
+ * @param string $gateway
+ *
+ * @return mixed
+ */
+ protected function callCustomCreator($gateway)
+ {
+ return call_user_func($this->customCreators[$gateway], $this->config->get($gateway, []));
+ }
+}
diff --git a/vendor/dipper/sms/src/SmsServiceProvider.php b/vendor/dipper/sms/src/SmsServiceProvider.php
new file mode 100644
index 00000000..7555b5bf
--- /dev/null
+++ b/vendor/dipper/sms/src/SmsServiceProvider.php
@@ -0,0 +1,30 @@
+app->singleton('sms', function (Container $app) {
+ return new Sms($app['config']['sms']);
+ });
+ }
+
+ public function boot()
+ {
+ $source = realpath(__DIR__.'/../config/sms.php');
+
+ if ($this->app instanceof LumenApplication) {
+ $this->app->configure('sms');
+ }
+
+ $this->mergeConfigFrom($source, 'sms');
+ }
+}
diff --git a/vendor/dipper/sms/src/Strategies/OrderStrategy.php b/vendor/dipper/sms/src/Strategies/OrderStrategy.php
new file mode 100644
index 00000000..6794b37a
--- /dev/null
+++ b/vendor/dipper/sms/src/Strategies/OrderStrategy.php
@@ -0,0 +1,20 @@
+config = $config;
+ }
+
+ /**
+ * Get an item from an array using "dot" notation.
+ *
+ * @param string $key
+ * @param mixed $default
+ *
+ * @return mixed
+ */
+ public function get($key, $default = null)
+ {
+ $config = $this->config;
+
+ if (is_null($key)) {
+ return null;
+ }
+
+ if (isset($config[$key])) {
+ return $config[$key];
+ }
+
+ foreach (explode('.', $key) as $segment) {
+ if (!is_array($config) || !array_key_exists($segment, $config)) {
+ return $default;
+ }
+ $config = $config[$segment];
+ }
+
+ return $config;
+ }
+
+ /**
+ * Whether a offset exists.
+ *
+ * @see http://php.net/manual/en/arrayaccess.offsetexists.php
+ *
+ * @param mixed $offset
+ * The return value will be casted to boolean if non-boolean was returned + * + * @since 5.0.0 + */ + public function offsetExists($offset) + { + return array_key_exists($offset, $this->config); + } + + /** + * Offset to retrieve. + * + * @see http://php.net/manual/en/arrayaccess.offsetget.php + * + * @param mixed $offset
+ * The offset to retrieve. + *
+ * + * @return mixed Can return all value types + * + * @since 5.0.0 + */ + public function offsetGet($offset) + { + return $this->get($offset); + } + + /** + * Offset to set. + * + * @see http://php.net/manual/en/arrayaccess.offsetset.php + * + * @param mixed $offset+ * The offset to assign the value to. + *
+ * @param mixed $value+ * The value to set. + *
+ * + * @since 5.0.0 + */ + public function offsetSet($offset, $value) + { + if (isset($this->config[$offset])) { + $this->config[$offset] = $value; + } + } + + /** + * Offset to unset. + * + * @see http://php.net/manual/en/arrayaccess.offsetunset.php + * + * @param mixed $offset+ * The offset to unset. + *
+ * + * @since 5.0.0 + */ + public function offsetUnset($offset) + { + if (isset($this->config[$offset])) { + unset($this->config[$offset]); + } + } +} diff --git a/vendor/dipper/sms/src/Traits/HasHttpRequest.php b/vendor/dipper/sms/src/Traits/HasHttpRequest.php new file mode 100644 index 00000000..7da300ab --- /dev/null +++ b/vendor/dipper/sms/src/Traits/HasHttpRequest.php @@ -0,0 +1,107 @@ +request('get', $endpoint, [ + 'headers' => $headers, + 'query' => $query, + ]); + } + + /** + * Make a post request. + * + * @param string $endpoint + * @param array $params + * @param array $headers + * + * @return array + */ + protected function post($endpoint, $params = [], $headers = []) + { + return $this->request('post', $endpoint, [ + 'headers' => $headers, + 'form_params' => $params, + ]); + } + + /** + * Make a http request. + * + * @param string $method + * @param string $endpoint + * @param array $options http://docs.guzzlephp.org/en/latest/request-options.html + * + * @return array + */ + protected function request($method, $endpoint, $options = []) + { + return $this->unwrapResponse($this->getHttpClient($this->getBaseOptions())->{$method}($endpoint, $options)); + } + + /** + * Return base Guzzle options. + * + * @return array + */ + protected function getBaseOptions() + { + $options = [ + 'base_uri' => method_exists($this, 'getBaseUri') ? $this->getBaseUri() : '', + 'timeout' => property_exists($this, 'timeout') ? $this->timeout : 5.0, + ]; + + return $options; + } + + /** + * Return http client. + * + * @param array $options + * + * @return \GuzzleHttp\Client + * + * @codeCoverageIgnore + */ + protected function getHttpClient(array $options = []) + { + return new Client($options); + } + + /** + * Convert response contents to json. + * + * @param \Psr\Http\Message\ResponseInterface $response + * + * @return array + */ + protected function unwrapResponse(ResponseInterface $response) + { + $contentType = $response->getHeaderLine('Content-Type'); + $contents = $response->getBody()->getContents(); + + if (false !== stripos($contentType, 'json') || stripos($contentType, 'javascript')) { + return json_decode($contents, true); + } elseif (false !== stripos($contentType, 'xml')) { + return json_decode(json_encode(simplexml_load_string($contents)), true); + } + + return $contents; + } +}