From b0ac3868a8739d124de05180c13eb99fd7aaabbe Mon Sep 17 00:00:00 2001
From: wanghongjun <1445693971@qq,com>
Date: Tue, 24 Oct 2023 11:07:07 +0800
Subject: [PATCH] =?UTF-8?q?=E9=83=A8=E7=BD=B2=E5=88=B0git?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../overtrue/socialite/.github/FUNDING.yml | 9 +
.../vendor/overtrue/socialite/.gitignore | 9 +
.../vendor/overtrue/socialite/.php_cs | 28 +
.../vendor/overtrue/socialite/.travis.yml | 13 +
.../vendor/overtrue/socialite/LICENSE.txt | 21 +
.../vendor/overtrue/socialite/README.md | 266 +++++++++
.../vendor/overtrue/socialite/composer.json | 26 +
.../vendor/overtrue/socialite/phpunit.xml | 18 +
.../overtrue/socialite/src/AccessToken.php | 64 ++
.../socialite/src/AccessTokenInterface.php | 25 +
.../src/AuthorizeFailedException.php | 35 ++
.../vendor/overtrue/socialite/src/Config.php | 180 ++++++
.../socialite/src/FactoryInterface.php | 27 +
.../overtrue/socialite/src/HasAttributes.php | 135 +++++
.../src/InvalidArgumentException.php | 16 +
.../socialite/src/InvalidStateException.php | 16 +
.../socialite/src/ProviderInterface.php | 31 +
.../src/Providers/AbstractProvider.php | 560 ++++++++++++++++++
.../src/Providers/DouYinProvider.php | 168 ++++++
.../src/Providers/DoubanProvider.php | 88 +++
.../src/Providers/FacebookProvider.php | 167 ++++++
.../src/Providers/GitHubProvider.php | 121 ++++
.../src/Providers/GoogleProvider.php | 118 ++++
.../src/Providers/LinkedinProvider.php | 181 ++++++
.../src/Providers/OutlookProvider.php | 88 +++
.../socialite/src/Providers/QQProvider.php | 206 +++++++
.../src/Providers/TaobaoProvider.php | 242 ++++++++
.../src/Providers/WeChatProvider.php | 234 ++++++++
.../src/Providers/WeWorkProvider.php | 214 +++++++
.../socialite/src/Providers/WeiboProvider.php | 126 ++++
.../socialite/src/SocialiteManager.php | 251 ++++++++
.../vendor/overtrue/socialite/src/User.php | 186 ++++++
.../overtrue/socialite/src/UserInterface.php | 53 ++
.../src/WeChatComponentInterface.php | 32 +
.../overtrue/socialite/tests/OAuthTest.php | 161 +++++
.../tests/Providers/WeWorkProviderTest.php | 48 ++
.../overtrue/socialite/tests/UserTest.php | 24 +
.../socialite/tests/WechatProviderTest.php | 109 ++++
.../wechat/src/BasicService/Application.php | 39 ++
.../BasicService/ContentSecurity/Client.php | 123 ++++
.../ContentSecurity/ServiceProvider.php | 31 +
.../wechat/src/BasicService/Jssdk/Client.php | 207 +++++++
.../BasicService/Jssdk/ServiceProvider.php | 33 ++
.../wechat/src/BasicService/Media/Client.php | 212 +++++++
.../BasicService/Media/ServiceProvider.php | 44 ++
.../wechat/src/BasicService/QrCode/Client.php | 120 ++++
.../BasicService/QrCode/ServiceProvider.php | 31 +
.../wechat/src/BasicService/Url/Client.php | 47 ++
.../src/BasicService/Url/ServiceProvider.php | 31 +
.../wechat/src/Kernel/AccessToken.php | 282 +++++++++
.../overtrue/wechat/src/Kernel/BaseClient.php | 271 +++++++++
.../wechat/src/Kernel/Clauses/Clause.php | 64 ++
.../overtrue/wechat/src/Kernel/Config.php | 23 +
.../Kernel/Contracts/AccessTokenInterface.php | 40 ++
.../wechat/src/Kernel/Contracts/Arrayable.php | 29 +
.../Contracts/EventHandlerInterface.php | 25 +
.../src/Kernel/Contracts/MediaInterface.php | 25 +
.../src/Kernel/Contracts/MessageInterface.php | 35 ++
.../src/Kernel/Decorators/FinallyResult.php | 35 ++
.../src/Kernel/Decorators/TerminateResult.php | 35 ++
.../overtrue/wechat/src/Kernel/Encryptor.php | 219 +++++++
.../Kernel/Events/AccessTokenRefreshed.php | 35 ++
.../Kernel/Events/ApplicationInitialized.php | 35 ++
.../src/Kernel/Events/HttpResponseCreated.php | 35 ++
.../Events/ServerGuardResponseCreated.php | 35 ++
.../Kernel/Exceptions/BadRequestException.php | 21 +
.../Kernel/Exceptions/DecryptException.php | 16 +
.../src/Kernel/Exceptions/Exception.php | 23 +
.../src/Kernel/Exceptions/HttpException.php | 52 ++
.../Exceptions/InvalidArgumentException.php | 21 +
.../Exceptions/InvalidConfigException.php | 21 +
.../Kernel/Exceptions/RuntimeException.php | 21 +
.../Exceptions/UnboundServiceException.php | 21 +
.../overtrue/wechat/src/Kernel/Helpers.php | 57 ++
.../wechat/src/Kernel/Http/Response.php | 121 ++++
.../wechat/src/Kernel/Http/StreamResponse.php | 86 +++
.../wechat/src/Kernel/Messages/Article.php | 58 ++
.../wechat/src/Kernel/Messages/Card.php | 52 ++
.../src/Kernel/Messages/DeviceEvent.php | 40 ++
.../wechat/src/Kernel/Messages/DeviceText.php | 50 ++
.../wechat/src/Kernel/Messages/File.php | 25 +
.../wechat/src/Kernel/Messages/Image.php | 27 +
.../wechat/src/Kernel/Messages/Link.php | 36 ++
.../wechat/src/Kernel/Messages/Location.php | 38 ++
.../wechat/src/Kernel/Messages/Media.php | 70 +++
.../wechat/src/Kernel/Messages/Message.php | 208 +++++++
.../src/Kernel/Messages/MiniProgramPage.php | 31 +
.../wechat/src/Kernel/Messages/Music.php | 73 +++
.../wechat/src/Kernel/Messages/News.php | 73 +++
.../wechat/src/Kernel/Messages/NewsItem.php | 57 ++
.../wechat/src/Kernel/Messages/Raw.php | 56 ++
.../wechat/src/Kernel/Messages/ShortVideo.php | 30 +
.../wechat/src/Kernel/Messages/TaskCard.php | 44 ++
.../wechat/src/Kernel/Messages/Text.php | 54 ++
.../wechat/src/Kernel/Messages/TextCard.php | 40 ++
.../wechat/src/Kernel/Messages/Transfer.php | 56 ++
.../wechat/src/Kernel/Messages/Video.php | 65 ++
.../wechat/src/Kernel/Messages/Voice.php | 37 ++
.../Providers/ConfigServiceProvider.php | 39 ++
.../EventDispatcherServiceProvider.php | 47 ++
.../Providers/ExtensionServiceProvider.php | 39 ++
.../Providers/HttpClientServiceProvider.php | 39 ++
.../Kernel/Providers/LogServiceProvider.php | 79 +++
.../Providers/RequestServiceProvider.php | 39 ++
.../wechat/src/Kernel/ServerGuard.php | 375 ++++++++++++
.../wechat/src/Kernel/ServiceContainer.php | 167 ++++++
.../wechat/src/Kernel/Support/AES.php | 85 +++
.../wechat/src/Kernel/Support/Arr.php | 466 +++++++++++++++
.../src/Kernel/Support/ArrayAccessible.php | 66 +++
.../wechat/src/Kernel/Support/Collection.php | 421 +++++++++++++
.../wechat/src/Kernel/Support/File.php | 135 +++++
.../wechat/src/Kernel/Support/Helpers.php | 131 ++++
.../wechat/src/Kernel/Support/Str.php | 193 ++++++
.../wechat/src/Kernel/Support/XML.php | 167 ++++++
.../src/Kernel/Traits/HasAttributes.php | 251 ++++++++
.../src/Kernel/Traits/HasHttpRequests.php | 231 ++++++++
.../src/Kernel/Traits/InteractsWithCache.php | 105 ++++
.../wechat/src/Kernel/Traits/Observable.php | 273 +++++++++
.../src/Kernel/Traits/ResponseCastable.php | 93 +++
.../wechat/src/MicroMerchant/Application.php | 171 ++++++
.../wechat/src/MicroMerchant/Base/Client.php | 126 ++++
.../MicroMerchant/Base/ServiceProvider.php | 33 ++
.../src/MicroMerchant/Certficates/Client.php | 93 +++
.../Certficates/ServiceProvider.php | 33 ++
.../src/MicroMerchant/Kernel/BaseClient.php | 256 ++++++++
.../Kernel/Exceptions/EncryptException.php | 23 +
.../Exceptions/InvalidExtensionException.php | 23 +
.../Exceptions/InvalidSignException.php | 23 +
.../src/MicroMerchant/Material/Client.php | 73 +++
.../Material/ServiceProvider.php | 33 ++
.../wechat/src/MicroMerchant/Media/Client.php | 49 ++
.../MicroMerchant/Media/ServiceProvider.php | 44 ++
.../MicroMerchant/MerchantConfig/Client.php | 134 +++++
.../MerchantConfig/ServiceProvider.php | 33 ++
.../src/MicroMerchant/Withdraw/Client.php | 67 +++
.../Withdraw/ServiceProvider.php | 33 ++
136 files changed, 12805 insertions(+)
create mode 100644 addons/weliam_smartcity/vendor/overtrue/socialite/.github/FUNDING.yml
create mode 100644 addons/weliam_smartcity/vendor/overtrue/socialite/.gitignore
create mode 100644 addons/weliam_smartcity/vendor/overtrue/socialite/.php_cs
create mode 100644 addons/weliam_smartcity/vendor/overtrue/socialite/.travis.yml
create mode 100644 addons/weliam_smartcity/vendor/overtrue/socialite/LICENSE.txt
create mode 100644 addons/weliam_smartcity/vendor/overtrue/socialite/README.md
create mode 100644 addons/weliam_smartcity/vendor/overtrue/socialite/composer.json
create mode 100644 addons/weliam_smartcity/vendor/overtrue/socialite/phpunit.xml
create mode 100644 addons/weliam_smartcity/vendor/overtrue/socialite/src/AccessToken.php
create mode 100644 addons/weliam_smartcity/vendor/overtrue/socialite/src/AccessTokenInterface.php
create mode 100644 addons/weliam_smartcity/vendor/overtrue/socialite/src/AuthorizeFailedException.php
create mode 100644 addons/weliam_smartcity/vendor/overtrue/socialite/src/Config.php
create mode 100644 addons/weliam_smartcity/vendor/overtrue/socialite/src/FactoryInterface.php
create mode 100644 addons/weliam_smartcity/vendor/overtrue/socialite/src/HasAttributes.php
create mode 100644 addons/weliam_smartcity/vendor/overtrue/socialite/src/InvalidArgumentException.php
create mode 100644 addons/weliam_smartcity/vendor/overtrue/socialite/src/InvalidStateException.php
create mode 100644 addons/weliam_smartcity/vendor/overtrue/socialite/src/ProviderInterface.php
create mode 100644 addons/weliam_smartcity/vendor/overtrue/socialite/src/Providers/AbstractProvider.php
create mode 100644 addons/weliam_smartcity/vendor/overtrue/socialite/src/Providers/DouYinProvider.php
create mode 100644 addons/weliam_smartcity/vendor/overtrue/socialite/src/Providers/DoubanProvider.php
create mode 100644 addons/weliam_smartcity/vendor/overtrue/socialite/src/Providers/FacebookProvider.php
create mode 100644 addons/weliam_smartcity/vendor/overtrue/socialite/src/Providers/GitHubProvider.php
create mode 100644 addons/weliam_smartcity/vendor/overtrue/socialite/src/Providers/GoogleProvider.php
create mode 100644 addons/weliam_smartcity/vendor/overtrue/socialite/src/Providers/LinkedinProvider.php
create mode 100644 addons/weliam_smartcity/vendor/overtrue/socialite/src/Providers/OutlookProvider.php
create mode 100644 addons/weliam_smartcity/vendor/overtrue/socialite/src/Providers/QQProvider.php
create mode 100644 addons/weliam_smartcity/vendor/overtrue/socialite/src/Providers/TaobaoProvider.php
create mode 100644 addons/weliam_smartcity/vendor/overtrue/socialite/src/Providers/WeChatProvider.php
create mode 100644 addons/weliam_smartcity/vendor/overtrue/socialite/src/Providers/WeWorkProvider.php
create mode 100644 addons/weliam_smartcity/vendor/overtrue/socialite/src/Providers/WeiboProvider.php
create mode 100644 addons/weliam_smartcity/vendor/overtrue/socialite/src/SocialiteManager.php
create mode 100644 addons/weliam_smartcity/vendor/overtrue/socialite/src/User.php
create mode 100644 addons/weliam_smartcity/vendor/overtrue/socialite/src/UserInterface.php
create mode 100644 addons/weliam_smartcity/vendor/overtrue/socialite/src/WeChatComponentInterface.php
create mode 100644 addons/weliam_smartcity/vendor/overtrue/socialite/tests/OAuthTest.php
create mode 100644 addons/weliam_smartcity/vendor/overtrue/socialite/tests/Providers/WeWorkProviderTest.php
create mode 100644 addons/weliam_smartcity/vendor/overtrue/socialite/tests/UserTest.php
create mode 100644 addons/weliam_smartcity/vendor/overtrue/socialite/tests/WechatProviderTest.php
create mode 100644 addons/weliam_smartcity/vendor/overtrue/wechat/src/BasicService/Application.php
create mode 100644 addons/weliam_smartcity/vendor/overtrue/wechat/src/BasicService/ContentSecurity/Client.php
create mode 100644 addons/weliam_smartcity/vendor/overtrue/wechat/src/BasicService/ContentSecurity/ServiceProvider.php
create mode 100644 addons/weliam_smartcity/vendor/overtrue/wechat/src/BasicService/Jssdk/Client.php
create mode 100644 addons/weliam_smartcity/vendor/overtrue/wechat/src/BasicService/Jssdk/ServiceProvider.php
create mode 100644 addons/weliam_smartcity/vendor/overtrue/wechat/src/BasicService/Media/Client.php
create mode 100644 addons/weliam_smartcity/vendor/overtrue/wechat/src/BasicService/Media/ServiceProvider.php
create mode 100644 addons/weliam_smartcity/vendor/overtrue/wechat/src/BasicService/QrCode/Client.php
create mode 100644 addons/weliam_smartcity/vendor/overtrue/wechat/src/BasicService/QrCode/ServiceProvider.php
create mode 100644 addons/weliam_smartcity/vendor/overtrue/wechat/src/BasicService/Url/Client.php
create mode 100644 addons/weliam_smartcity/vendor/overtrue/wechat/src/BasicService/Url/ServiceProvider.php
create mode 100644 addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/AccessToken.php
create mode 100644 addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/BaseClient.php
create mode 100644 addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Clauses/Clause.php
create mode 100644 addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Config.php
create mode 100644 addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Contracts/AccessTokenInterface.php
create mode 100644 addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Contracts/Arrayable.php
create mode 100644 addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Contracts/EventHandlerInterface.php
create mode 100644 addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Contracts/MediaInterface.php
create mode 100644 addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Contracts/MessageInterface.php
create mode 100644 addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Decorators/FinallyResult.php
create mode 100644 addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Decorators/TerminateResult.php
create mode 100644 addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Encryptor.php
create mode 100644 addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Events/AccessTokenRefreshed.php
create mode 100644 addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Events/ApplicationInitialized.php
create mode 100644 addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Events/HttpResponseCreated.php
create mode 100644 addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Events/ServerGuardResponseCreated.php
create mode 100644 addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Exceptions/BadRequestException.php
create mode 100644 addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Exceptions/DecryptException.php
create mode 100644 addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Exceptions/Exception.php
create mode 100644 addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Exceptions/HttpException.php
create mode 100644 addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Exceptions/InvalidArgumentException.php
create mode 100644 addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Exceptions/InvalidConfigException.php
create mode 100644 addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Exceptions/RuntimeException.php
create mode 100644 addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Exceptions/UnboundServiceException.php
create mode 100644 addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Helpers.php
create mode 100644 addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Http/Response.php
create mode 100644 addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Http/StreamResponse.php
create mode 100644 addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Messages/Article.php
create mode 100644 addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Messages/Card.php
create mode 100644 addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Messages/DeviceEvent.php
create mode 100644 addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Messages/DeviceText.php
create mode 100644 addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Messages/File.php
create mode 100644 addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Messages/Image.php
create mode 100644 addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Messages/Link.php
create mode 100644 addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Messages/Location.php
create mode 100644 addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Messages/Media.php
create mode 100644 addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Messages/Message.php
create mode 100644 addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Messages/MiniProgramPage.php
create mode 100644 addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Messages/Music.php
create mode 100644 addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Messages/News.php
create mode 100644 addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Messages/NewsItem.php
create mode 100644 addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Messages/Raw.php
create mode 100644 addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Messages/ShortVideo.php
create mode 100644 addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Messages/TaskCard.php
create mode 100644 addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Messages/Text.php
create mode 100644 addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Messages/TextCard.php
create mode 100644 addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Messages/Transfer.php
create mode 100644 addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Messages/Video.php
create mode 100644 addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Messages/Voice.php
create mode 100644 addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Providers/ConfigServiceProvider.php
create mode 100644 addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Providers/EventDispatcherServiceProvider.php
create mode 100644 addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Providers/ExtensionServiceProvider.php
create mode 100644 addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Providers/HttpClientServiceProvider.php
create mode 100644 addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Providers/LogServiceProvider.php
create mode 100644 addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Providers/RequestServiceProvider.php
create mode 100644 addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/ServerGuard.php
create mode 100644 addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/ServiceContainer.php
create mode 100644 addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Support/AES.php
create mode 100644 addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Support/Arr.php
create mode 100644 addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Support/ArrayAccessible.php
create mode 100644 addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Support/Collection.php
create mode 100644 addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Support/File.php
create mode 100644 addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Support/Helpers.php
create mode 100644 addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Support/Str.php
create mode 100644 addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Support/XML.php
create mode 100644 addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Traits/HasAttributes.php
create mode 100644 addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Traits/HasHttpRequests.php
create mode 100644 addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Traits/InteractsWithCache.php
create mode 100644 addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Traits/Observable.php
create mode 100644 addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Traits/ResponseCastable.php
create mode 100644 addons/weliam_smartcity/vendor/overtrue/wechat/src/MicroMerchant/Application.php
create mode 100644 addons/weliam_smartcity/vendor/overtrue/wechat/src/MicroMerchant/Base/Client.php
create mode 100644 addons/weliam_smartcity/vendor/overtrue/wechat/src/MicroMerchant/Base/ServiceProvider.php
create mode 100644 addons/weliam_smartcity/vendor/overtrue/wechat/src/MicroMerchant/Certficates/Client.php
create mode 100644 addons/weliam_smartcity/vendor/overtrue/wechat/src/MicroMerchant/Certficates/ServiceProvider.php
create mode 100644 addons/weliam_smartcity/vendor/overtrue/wechat/src/MicroMerchant/Kernel/BaseClient.php
create mode 100644 addons/weliam_smartcity/vendor/overtrue/wechat/src/MicroMerchant/Kernel/Exceptions/EncryptException.php
create mode 100644 addons/weliam_smartcity/vendor/overtrue/wechat/src/MicroMerchant/Kernel/Exceptions/InvalidExtensionException.php
create mode 100644 addons/weliam_smartcity/vendor/overtrue/wechat/src/MicroMerchant/Kernel/Exceptions/InvalidSignException.php
create mode 100644 addons/weliam_smartcity/vendor/overtrue/wechat/src/MicroMerchant/Material/Client.php
create mode 100644 addons/weliam_smartcity/vendor/overtrue/wechat/src/MicroMerchant/Material/ServiceProvider.php
create mode 100644 addons/weliam_smartcity/vendor/overtrue/wechat/src/MicroMerchant/Media/Client.php
create mode 100644 addons/weliam_smartcity/vendor/overtrue/wechat/src/MicroMerchant/Media/ServiceProvider.php
create mode 100644 addons/weliam_smartcity/vendor/overtrue/wechat/src/MicroMerchant/MerchantConfig/Client.php
create mode 100644 addons/weliam_smartcity/vendor/overtrue/wechat/src/MicroMerchant/MerchantConfig/ServiceProvider.php
create mode 100644 addons/weliam_smartcity/vendor/overtrue/wechat/src/MicroMerchant/Withdraw/Client.php
create mode 100644 addons/weliam_smartcity/vendor/overtrue/wechat/src/MicroMerchant/Withdraw/ServiceProvider.php
diff --git a/addons/weliam_smartcity/vendor/overtrue/socialite/.github/FUNDING.yml b/addons/weliam_smartcity/vendor/overtrue/socialite/.github/FUNDING.yml
new file mode 100644
index 0000000..a3be7fa
--- /dev/null
+++ b/addons/weliam_smartcity/vendor/overtrue/socialite/.github/FUNDING.yml
@@ -0,0 +1,9 @@
+# These are supported funding model platforms
+
+github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
+patreon: overtrue
+open_collective: # Replace with a single Open Collective username
+ko_fi: # Replace with a single Ko-fi username
+tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
+community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
+custom: # Replace with a single custom sponsorship URL
diff --git a/addons/weliam_smartcity/vendor/overtrue/socialite/.gitignore b/addons/weliam_smartcity/vendor/overtrue/socialite/.gitignore
new file mode 100644
index 0000000..d6eb268
--- /dev/null
+++ b/addons/weliam_smartcity/vendor/overtrue/socialite/.gitignore
@@ -0,0 +1,9 @@
+/vendor
+composer.phar
+composer.lock
+.DS_Store
+/.idea
+Thumbs.db
+/*.php
+sftp-config.json
+.php_cs.cache
\ No newline at end of file
diff --git a/addons/weliam_smartcity/vendor/overtrue/socialite/.php_cs b/addons/weliam_smartcity/vendor/overtrue/socialite/.php_cs
new file mode 100644
index 0000000..bda3644
--- /dev/null
+++ b/addons/weliam_smartcity/vendor/overtrue/socialite/.php_cs
@@ -0,0 +1,28 @@
+
+
+This source file is subject to the MIT license that is bundled
+with this source code in the file LICENSE.
+EOF;
+
+return PhpCsFixer\Config::create()
+ ->setRiskyAllowed(true)
+ ->setRules(array(
+ '@Symfony' => true,
+ 'header_comment' => array('header' => $header),
+ 'array_syntax' => array('syntax' => 'short'),
+ 'ordered_imports' => true,
+ 'no_useless_else' => true,
+ 'no_useless_return' => true,
+ 'php_unit_construct' => true,
+ 'php_unit_strict' => true,
+ ))
+ ->setFinder(
+ PhpCsFixer\Finder::create()
+ ->exclude('vendor')
+ ->in(__DIR__)
+ )
+;
\ No newline at end of file
diff --git a/addons/weliam_smartcity/vendor/overtrue/socialite/.travis.yml b/addons/weliam_smartcity/vendor/overtrue/socialite/.travis.yml
new file mode 100644
index 0000000..39912f9
--- /dev/null
+++ b/addons/weliam_smartcity/vendor/overtrue/socialite/.travis.yml
@@ -0,0 +1,13 @@
+language: php
+
+php:
+ - 7.0
+ - 7.1
+ - 7.2
+
+sudo: false
+dist: trusty
+
+install: travis_retry composer install --no-interaction --prefer-source
+
+script: vendor/bin/phpunit --verbose
diff --git a/addons/weliam_smartcity/vendor/overtrue/socialite/LICENSE.txt b/addons/weliam_smartcity/vendor/overtrue/socialite/LICENSE.txt
new file mode 100644
index 0000000..c5fe984
--- /dev/null
+++ b/addons/weliam_smartcity/vendor/overtrue/socialite/LICENSE.txt
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) overtrue
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/addons/weliam_smartcity/vendor/overtrue/socialite/README.md b/addons/weliam_smartcity/vendor/overtrue/socialite/README.md
new file mode 100644
index 0000000..ec7ea88
--- /dev/null
+++ b/addons/weliam_smartcity/vendor/overtrue/socialite/README.md
@@ -0,0 +1,266 @@
+ Socialite
+
+
+
+
+
+
+
+
+
+
+
+
+Socialite is an OAuth2 Authentication tool. It is inspired by laravel/socialite, You can easily use it in any PHP project.
+
+# Requirement
+
+```
+PHP >= 7.0
+```
+# Installation
+
+```shell
+$ composer require "overtrue/socialite" -vvv
+```
+
+# Usage
+
+For Laravel 5: [overtrue/laravel-socialite](https://github.com/overtrue/laravel-socialite)
+
+`authorize.php`:
+
+```php
+ [
+ 'client_id' => 'your-app-id',
+ 'client_secret' => 'your-app-secret',
+ 'redirect' => 'http://localhost/socialite/callback.php',
+ ],
+];
+
+$socialite = new SocialiteManager($config);
+
+$response = $socialite->driver('github')->redirect();
+
+echo $response;// or $response->send();
+```
+
+`callback.php`:
+
+```php
+ [
+ 'client_id' => 'your-app-id',
+ 'client_secret' => 'your-app-secret',
+ 'redirect' => 'http://localhost/socialite/callback.php',
+ ],
+];
+
+$socialite = new SocialiteManager($config);
+
+$user = $socialite->driver('github')->user();
+
+$user->getId(); // 1472352
+$user->getNickname(); // "overtrue"
+$user->getUsername(); // "overtrue"
+$user->getName(); // "安正超"
+$user->getEmail(); // "anzhengchao@gmail.com"
+$user->getProviderName(); // GitHub
+...
+```
+
+### Configuration
+
+Now we support the following sites:
+
+`facebook`, `github`, `google`, `linkedin`, `outlook`, `weibo`, `taobao`, `qq`, `wechat`, `douyin`, and `douban`.
+
+Each driver uses the same configuration keys: `client_id`, `client_secret`, `redirect`.
+
+Example:
+```
+...
+ 'weibo' => [
+ 'client_id' => 'your-app-id',
+ 'client_secret' => 'your-app-secret',
+ 'redirect' => 'http://localhost/socialite/callback.php',
+ ],
+...
+```
+
+### Scope
+
+Before redirecting the user, you may also set "scopes" on the request using the scope method. This method will overwrite all existing scopes:
+
+```php
+$response = $socialite->driver('github')
+ ->scopes(['scope1', 'scope2'])->redirect();
+
+```
+
+### Redirect URL
+
+You may also want to dynamicly set `redirect`,you can use the following methods to change the `redirect` URL:
+
+```php
+$socialite->redirect($url);
+// or
+$socialite->withRedirectUrl($url)->redirect();
+// or
+$socialite->setRedirectUrl($url)->redirect();
+```
+
+> WeChat scopes:
+- `snsapi_base`, `snsapi_userinfo` - Used to Media Platform Authentication.
+- `snsapi_login` - Used to web Authentication.
+
+### Additional parameters
+
+To include any optional parameters in the request, call the with method with an associative array:
+
+```php
+$response = $socialite->driver('google')
+ ->with(['hd' => 'example.com'])->redirect();
+```
+
+### User interface
+
+#### Standard user api:
+
+```php
+
+$user = $socialite->driver('weibo')->user();
+```
+
+```json
+{
+ "id": 1472352,
+ "nickname": "overtrue",
+ "name": "安正超",
+ "email": "anzhengchao@gmail.com",
+ "avatar": "https://avatars.githubusercontent.com/u/1472352?v=3",
+ "original": {
+ "login": "overtrue",
+ "id": 1472352,
+ "avatar_url": "https://avatars.githubusercontent.com/u/1472352?v=3",
+ "gravatar_id": "",
+ "url": "https://api.github.com/users/overtrue",
+ "html_url": "https://github.com/overtrue",
+ ...
+ },
+ "token": {
+ "access_token": "5b1dc56d64fffbd052359f032716cc4e0a1cb9a0",
+ "token_type": "bearer",
+ "scope": "user:email"
+ }
+}
+```
+
+You can fetch the user attribute as a array keys like these:
+
+```php
+$user['id']; // 1472352
+$user['nickname']; // "overtrue"
+$user['name']; // "安正超"
+$user['email']; // "anzhengchao@gmail.com"
+...
+```
+
+Or using the method:
+
+```php
+$user->getId();
+$user->getNickname();
+$user->getName();
+$user->getEmail();
+$user->getAvatar();
+$user->getOriginal();
+$user->getToken();// or $user->getAccessToken()
+$user->getProviderName(); // GitHub/Google/Facebook...
+```
+
+#### Get original response from OAuth API
+
+The `$user->getOriginal()` method will return an array of the API raw response.
+
+#### Get access token Object
+
+You can get the access token instance of current session by call `$user->getToken()` or `$user->getAccessToken()` or `$user['token']` .
+
+
+### Get user with access token
+
+```php
+$accessToken = new AccessToken(['access_token' => $accessToken]);
+$user = $socialite->user($accessToken);
+```
+
+
+### Custom Session or Request instance.
+
+You can set the request with your custom `Request` instance which instanceof `Symfony\Component\HttpFoundation\Request` before you call `driver` method.
+
+
+```php
+
+$request = new Request(); // or use AnotherCustomRequest.
+
+$socialite = new SocialiteManager($config, $request);
+```
+
+Or set request to `SocialiteManager` instance:
+
+```php
+$socialite->setRequest($request);
+```
+
+You can get the request from the `SocialiteManager` instance by `getRequest()`:
+
+```php
+$request = $socialite->getRequest();
+```
+
+#### Set custom session manager.
+
+By default, the `SocialiteManager` uses the `Symfony\Component\HttpFoundation\Session\Session` instance as session manager, you can change it as follows:
+
+```php
+$session = new YourCustomSessionManager();
+$socialite->getRequest()->setSession($session);
+```
+
+> Your custom session manager must be implement the [`Symfony\Component\HttpFoundation\Session\SessionInterface`](http://api.symfony.com/3.0/Symfony/Component/HttpFoundation/Session/SessionInterface.html).
+
+Enjoy it! :heart:
+
+# Reference
+
+- [Google - OpenID Connect](https://developers.google.com/identity/protocols/OpenIDConnect)
+- [Facebook - Graph API](https://developers.facebook.com/docs/graph-api)
+- [Linkedin - Authenticating with OAuth 2.0](https://developer.linkedin.com/docs/oauth2)
+- [微博 - OAuth 2.0 授权机制说明](http://open.weibo.com/wiki/%E6%8E%88%E6%9D%83%E6%9C%BA%E5%88%B6%E8%AF%B4%E6%98%8E)
+- [QQ - OAuth 2.0 登录QQ](http://wiki.connect.qq.com/oauth2-0%E7%AE%80%E4%BB%8B)
+- [微信公众平台 - OAuth文档](http://mp.weixin.qq.com/wiki/9/01f711493b5a02f24b04365ac5d8fd95.html)
+- [微信开放平台 - 网站应用微信登录开发指南](https://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&t=resource/res_list&verify=1&id=open1419316505&token=&lang=zh_CN)
+- [微信开放平台 - 代公众号发起网页授权](https://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&t=resource/res_list&verify=1&id=open1419318590&token=&lang=zh_CN)
+- [豆瓣 - OAuth 2.0 授权机制说明](http://developers.douban.com/wiki/?title=oauth2)
+- [抖音 - 网站应用开发指南](http://open.douyin.com/platform/doc)
+
+## PHP 扩展包开发
+
+> 想知道如何从零开始构建 PHP 扩展包?
+>
+> 请关注我的实战课程,我会在此课程中分享一些扩展开发经验 —— [《PHP 扩展包实战教程 - 从入门到发布》](https://learnku.com/courses/creating-package)
+
+# License
+
+MIT
diff --git a/addons/weliam_smartcity/vendor/overtrue/socialite/composer.json b/addons/weliam_smartcity/vendor/overtrue/socialite/composer.json
new file mode 100644
index 0000000..87dec16
--- /dev/null
+++ b/addons/weliam_smartcity/vendor/overtrue/socialite/composer.json
@@ -0,0 +1,26 @@
+{
+ "name": "overtrue/socialite",
+ "description": "A collection of OAuth 2 packages that extracts from laravel/socialite.",
+ "keywords": ["OAuth", "social", "login", "Weibo", "WeChat", "QQ"],
+ "autoload": {
+ "psr-4": {
+ "Overtrue\\Socialite\\": "src/"
+ }
+ },
+ "require": {
+ "php": ">=7.0",
+ "guzzlehttp/guzzle": "~5.0|~6.0",
+ "symfony/http-foundation": "^2.7|^3.0|^4.0"
+ },
+ "require-dev": {
+ "mockery/mockery": "~1.2",
+ "phpunit/phpunit": "~6"
+ },
+ "license": "MIT",
+ "authors": [
+ {
+ "name": "overtrue",
+ "email": "anzhengchao@gmail.com"
+ }
+ ]
+}
diff --git a/addons/weliam_smartcity/vendor/overtrue/socialite/phpunit.xml b/addons/weliam_smartcity/vendor/overtrue/socialite/phpunit.xml
new file mode 100644
index 0000000..3347b75
--- /dev/null
+++ b/addons/weliam_smartcity/vendor/overtrue/socialite/phpunit.xml
@@ -0,0 +1,18 @@
+
+
+
+
+ ./tests/
+
+
+
diff --git a/addons/weliam_smartcity/vendor/overtrue/socialite/src/AccessToken.php b/addons/weliam_smartcity/vendor/overtrue/socialite/src/AccessToken.php
new file mode 100644
index 0000000..e089bfa
--- /dev/null
+++ b/addons/weliam_smartcity/vendor/overtrue/socialite/src/AccessToken.php
@@ -0,0 +1,64 @@
+
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace Overtrue\Socialite;
+
+use ArrayAccess;
+use InvalidArgumentException;
+use JsonSerializable;
+
+/**
+ * Class AccessToken.
+ */
+class AccessToken implements AccessTokenInterface, ArrayAccess, JsonSerializable
+{
+ use HasAttributes;
+
+ /**
+ * AccessToken constructor.
+ *
+ * @param array $attributes
+ */
+ public function __construct(array $attributes)
+ {
+ if (empty($attributes['access_token'])) {
+ throw new InvalidArgumentException('The key "access_token" could not be empty.');
+ }
+
+ $this->attributes = $attributes;
+ }
+
+ /**
+ * Return the access token string.
+ *
+ * @return string
+ */
+ public function getToken()
+ {
+ return $this->getAttribute('access_token');
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function __toString()
+ {
+ return strval($this->getAttribute('access_token', ''));
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function jsonSerialize()
+ {
+ return $this->getToken();
+ }
+}
diff --git a/addons/weliam_smartcity/vendor/overtrue/socialite/src/AccessTokenInterface.php b/addons/weliam_smartcity/vendor/overtrue/socialite/src/AccessTokenInterface.php
new file mode 100644
index 0000000..f6f54bc
--- /dev/null
+++ b/addons/weliam_smartcity/vendor/overtrue/socialite/src/AccessTokenInterface.php
@@ -0,0 +1,25 @@
+
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace Overtrue\Socialite;
+
+/**
+ * Interface AccessTokenInterface.
+ */
+interface AccessTokenInterface
+{
+ /**
+ * Return the access token string.
+ *
+ * @return string
+ */
+ public function getToken();
+}
diff --git a/addons/weliam_smartcity/vendor/overtrue/socialite/src/AuthorizeFailedException.php b/addons/weliam_smartcity/vendor/overtrue/socialite/src/AuthorizeFailedException.php
new file mode 100644
index 0000000..cc2b128
--- /dev/null
+++ b/addons/weliam_smartcity/vendor/overtrue/socialite/src/AuthorizeFailedException.php
@@ -0,0 +1,35 @@
+
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace Overtrue\Socialite;
+
+class AuthorizeFailedException extends \RuntimeException
+{
+ /**
+ * Response body.
+ *
+ * @var array
+ */
+ public $body;
+
+ /**
+ * Constructor.
+ *
+ * @param string $message
+ * @param array $body
+ */
+ public function __construct($message, $body)
+ {
+ parent::__construct($message, -1);
+
+ $this->body = $body;
+ }
+}
diff --git a/addons/weliam_smartcity/vendor/overtrue/socialite/src/Config.php b/addons/weliam_smartcity/vendor/overtrue/socialite/src/Config.php
new file mode 100644
index 0000000..bbe0862
--- /dev/null
+++ b/addons/weliam_smartcity/vendor/overtrue/socialite/src/Config.php
@@ -0,0 +1,180 @@
+
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace Overtrue\Socialite;
+
+use ArrayAccess;
+use InvalidArgumentException;
+
+/**
+ * Class Config.
+ */
+class Config implements ArrayAccess
+{
+ /**
+ * @var array
+ */
+ protected $config;
+
+ /**
+ * Config constructor.
+ *
+ * @param array $config
+ */
+ public function __construct(array $config)
+ {
+ $this->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 $config;
+ }
+ 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;
+ }
+
+ /**
+ * Set an array item to a given value using "dot" notation.
+ *
+ * @param string $key
+ * @param mixed $value
+ *
+ * @return array
+ */
+ public function set($key, $value)
+ {
+ if (is_null($key)) {
+ throw new InvalidArgumentException('Invalid config key.');
+ }
+
+ $keys = explode('.', $key);
+ $config = &$this->config;
+
+ while (count($keys) > 1) {
+ $key = array_shift($keys);
+ if (!isset($config[$key]) || !is_array($config[$key])) {
+ $config[$key] = [];
+ }
+ $config = &$config[$key];
+ }
+
+ $config[array_shift($keys)] = $value;
+
+ return $config;
+ }
+
+ /**
+ * Determine if the given configuration value exists.
+ *
+ * @param string $key
+ *
+ * @return bool
+ */
+ public function has($key)
+ {
+ return (bool) $this->get($key);
+ }
+
+ /**
+ * Whether a offset exists.
+ *
+ * @see http://php.net/manual/en/arrayaccess.offsetexists.php
+ *
+ * @param mixed $offset
+ * An offset to check for.
+ *
+ *
+ * @return bool true on success or false on failure.
+ *
+ *
+ * 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)
+ {
+ $this->set($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)
+ {
+ $this->set($offset, null);
+ }
+}
diff --git a/addons/weliam_smartcity/vendor/overtrue/socialite/src/FactoryInterface.php b/addons/weliam_smartcity/vendor/overtrue/socialite/src/FactoryInterface.php
new file mode 100644
index 0000000..7a4959c
--- /dev/null
+++ b/addons/weliam_smartcity/vendor/overtrue/socialite/src/FactoryInterface.php
@@ -0,0 +1,27 @@
+
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace Overtrue\Socialite;
+
+/**
+ * Interface FactoryInterface.
+ */
+interface FactoryInterface
+{
+ /**
+ * Get an OAuth provider implementation.
+ *
+ * @param string $driver
+ *
+ * @return \Overtrue\Socialite\ProviderInterface
+ */
+ public function driver($driver);
+}
diff --git a/addons/weliam_smartcity/vendor/overtrue/socialite/src/HasAttributes.php b/addons/weliam_smartcity/vendor/overtrue/socialite/src/HasAttributes.php
new file mode 100644
index 0000000..eeff890
--- /dev/null
+++ b/addons/weliam_smartcity/vendor/overtrue/socialite/src/HasAttributes.php
@@ -0,0 +1,135 @@
+
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace Overtrue\Socialite;
+
+/**
+ * Trait HasAttributes.
+ */
+trait HasAttributes
+{
+ /**
+ * @var array
+ */
+ protected $attributes = [];
+
+ /**
+ * Return the attributes.
+ *
+ * @return array
+ */
+ public function getAttributes()
+ {
+ return $this->attributes;
+ }
+
+ /**
+ * Return the extra attribute.
+ *
+ * @param string $name
+ * @param string $default
+ *
+ * @return mixed
+ */
+ public function getAttribute($name, $default = null)
+ {
+ return isset($this->attributes[$name]) ? $this->attributes[$name] : $default;
+ }
+
+ /**
+ * Set extra attributes.
+ *
+ * @param string $name
+ * @param mixed $value
+ *
+ * @return $this
+ */
+ public function setAttribute($name, $value)
+ {
+ $this->attributes[$name] = $value;
+
+ return $this;
+ }
+
+ /**
+ * Map the given array onto the user's properties.
+ *
+ * @param array $attributes
+ *
+ * @return $this
+ */
+ public function merge(array $attributes)
+ {
+ $this->attributes = array_merge($this->attributes, $attributes);
+
+ return $this;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function offsetExists($offset)
+ {
+ return array_key_exists($offset, $this->attributes);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function offsetGet($offset)
+ {
+ return $this->getAttribute($offset);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function offsetSet($offset, $value)
+ {
+ $this->setAttribute($offset, $value);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function offsetUnset($offset)
+ {
+ unset($this->attributes[$offset]);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function __get($property)
+ {
+ return $this->getAttribute($property);
+ }
+
+ /**
+ * Return array.
+ *
+ * @return array
+ */
+ public function toArray()
+ {
+ return $this->getAttributes();
+ }
+
+ /**
+ * Return JSON.
+ *
+ * @return string
+ */
+ public function toJSON()
+ {
+ return json_encode($this->getAttributes(), JSON_UNESCAPED_UNICODE);
+ }
+}
diff --git a/addons/weliam_smartcity/vendor/overtrue/socialite/src/InvalidArgumentException.php b/addons/weliam_smartcity/vendor/overtrue/socialite/src/InvalidArgumentException.php
new file mode 100644
index 0000000..c044e64
--- /dev/null
+++ b/addons/weliam_smartcity/vendor/overtrue/socialite/src/InvalidArgumentException.php
@@ -0,0 +1,16 @@
+
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace Overtrue\Socialite;
+
+class InvalidArgumentException extends \InvalidArgumentException
+{
+}
diff --git a/addons/weliam_smartcity/vendor/overtrue/socialite/src/InvalidStateException.php b/addons/weliam_smartcity/vendor/overtrue/socialite/src/InvalidStateException.php
new file mode 100644
index 0000000..96ac503
--- /dev/null
+++ b/addons/weliam_smartcity/vendor/overtrue/socialite/src/InvalidStateException.php
@@ -0,0 +1,16 @@
+
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace Overtrue\Socialite;
+
+class InvalidStateException extends \InvalidArgumentException
+{
+}
diff --git a/addons/weliam_smartcity/vendor/overtrue/socialite/src/ProviderInterface.php b/addons/weliam_smartcity/vendor/overtrue/socialite/src/ProviderInterface.php
new file mode 100644
index 0000000..e78d172
--- /dev/null
+++ b/addons/weliam_smartcity/vendor/overtrue/socialite/src/ProviderInterface.php
@@ -0,0 +1,31 @@
+
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace Overtrue\Socialite;
+
+interface ProviderInterface
+{
+ /**
+ * Redirect the user to the authentication page for the provider.
+ *
+ * @return \Symfony\Component\HttpFoundation\RedirectResponse
+ */
+ public function redirect();
+
+ /**
+ * Get the User instance for the authenticated user.
+ *
+ * @param \Overtrue\Socialite\AccessTokenInterface $token
+ *
+ * @return \Overtrue\Socialite\User
+ */
+ public function user(AccessTokenInterface $token = null);
+}
diff --git a/addons/weliam_smartcity/vendor/overtrue/socialite/src/Providers/AbstractProvider.php b/addons/weliam_smartcity/vendor/overtrue/socialite/src/Providers/AbstractProvider.php
new file mode 100644
index 0000000..6b7b886
--- /dev/null
+++ b/addons/weliam_smartcity/vendor/overtrue/socialite/src/Providers/AbstractProvider.php
@@ -0,0 +1,560 @@
+
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace Overtrue\Socialite\Providers;
+
+use GuzzleHttp\Client;
+use GuzzleHttp\ClientInterface;
+use Overtrue\Socialite\AccessToken;
+use Overtrue\Socialite\AccessTokenInterface;
+use Overtrue\Socialite\AuthorizeFailedException;
+use Overtrue\Socialite\InvalidStateException;
+use Overtrue\Socialite\ProviderInterface;
+use Symfony\Component\HttpFoundation\RedirectResponse;
+use Symfony\Component\HttpFoundation\Request;
+
+/**
+ * Class AbstractProvider.
+ */
+abstract class AbstractProvider implements ProviderInterface
+{
+ /**
+ * Provider name.
+ *
+ * @var string
+ */
+ protected $name;
+
+ /**
+ * The HTTP request instance.
+ *
+ * @var \Symfony\Component\HttpFoundation\Request
+ */
+ protected $request;
+
+ /**
+ * The client ID.
+ *
+ * @var string
+ */
+ protected $clientId;
+
+ /**
+ * The client secret.
+ *
+ * @var string
+ */
+ protected $clientSecret;
+
+ /**
+ * @var \Overtrue\Socialite\AccessTokenInterface
+ */
+ protected $accessToken;
+
+ /**
+ * The redirect URL.
+ *
+ * @var string
+ */
+ protected $redirectUrl;
+
+ /**
+ * The custom parameters to be sent with the request.
+ *
+ * @var array
+ */
+ protected $parameters = [];
+
+ /**
+ * The scopes being requested.
+ *
+ * @var array
+ */
+ protected $scopes = [];
+
+ /**
+ * The separating character for the requested scopes.
+ *
+ * @var string
+ */
+ protected $scopeSeparator = ',';
+
+ /**
+ * The type of the encoding in the query.
+ *
+ * @var int Can be either PHP_QUERY_RFC3986 or PHP_QUERY_RFC1738
+ */
+ protected $encodingType = PHP_QUERY_RFC1738;
+
+ /**
+ * Indicates if the session state should be utilized.
+ *
+ * @var bool
+ */
+ protected $stateless = false;
+
+ /**
+ * The options for guzzle\client.
+ *
+ * @var array
+ */
+ protected static $guzzleOptions = ['http_errors' => false];
+
+ /**
+ * Create a new provider instance.
+ *
+ * @param \Symfony\Component\HttpFoundation\Request $request
+ * @param string $clientId
+ * @param string $clientSecret
+ * @param string|null $redirectUrl
+ */
+ public function __construct(Request $request, $clientId, $clientSecret, $redirectUrl = null)
+ {
+ $this->request = $request;
+ $this->clientId = $clientId;
+ $this->clientSecret = $clientSecret;
+ $this->redirectUrl = $redirectUrl;
+ }
+
+ /**
+ * Get the authentication URL for the provider.
+ *
+ * @param string $state
+ *
+ * @return string
+ */
+ abstract protected function getAuthUrl($state);
+
+ /**
+ * Get the token URL for the provider.
+ *
+ * @return string
+ */
+ abstract protected function getTokenUrl();
+
+ /**
+ * Get the raw user for the given access token.
+ *
+ * @param \Overtrue\Socialite\AccessTokenInterface $token
+ *
+ * @return array
+ */
+ abstract protected function getUserByToken(AccessTokenInterface $token);
+
+ /**
+ * Map the raw user array to a Socialite User instance.
+ *
+ * @param array $user
+ *
+ * @return \Overtrue\Socialite\User
+ */
+ abstract protected function mapUserToObject(array $user);
+
+ /**
+ * Redirect the user of the application to the provider's authentication screen.
+ *
+ * @param string $redirectUrl
+ *
+ * @return \Symfony\Component\HttpFoundation\RedirectResponse
+ */
+ public function redirect($redirectUrl = null)
+ {
+ $state = null;
+
+ if (!is_null($redirectUrl)) {
+ $this->redirectUrl = $redirectUrl;
+ }
+
+ if ($this->usesState()) {
+ $state = $this->makeState();
+ }
+
+ return new RedirectResponse($this->getAuthUrl($state));
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function user(AccessTokenInterface $token = null)
+ {
+ if (is_null($token) && $this->hasInvalidState()) {
+ throw new InvalidStateException();
+ }
+
+ $token = $token ?: $this->getAccessToken($this->getCode());
+
+ $user = $this->getUserByToken($token);
+
+ $user = $this->mapUserToObject($user)->merge(['original' => $user]);
+
+ return $user->setToken($token)->setProviderName($this->getName());
+ }
+
+ /**
+ * Set redirect url.
+ *
+ * @param string $redirectUrl
+ *
+ * @return $this
+ */
+ public function setRedirectUrl($redirectUrl)
+ {
+ $this->redirectUrl = $redirectUrl;
+
+ return $this;
+ }
+
+ /**
+ * Set redirect url.
+ *
+ * @param string $redirectUrl
+ *
+ * @return $this
+ */
+ public function withRedirectUrl($redirectUrl)
+ {
+ $this->redirectUrl = $redirectUrl;
+
+ return $this;
+ }
+
+ /**
+ * Return the redirect url.
+ *
+ * @return string
+ */
+ public function getRedirectUrl()
+ {
+ return $this->redirectUrl;
+ }
+
+ /**
+ * @param \Overtrue\Socialite\AccessTokenInterface $accessToken
+ *
+ * @return $this
+ */
+ public function setAccessToken(AccessTokenInterface $accessToken)
+ {
+ $this->accessToken = $accessToken;
+
+ return $this;
+ }
+
+ /**
+ * Get the access token for the given code.
+ *
+ * @param string $code
+ *
+ * @return \Overtrue\Socialite\AccessTokenInterface
+ */
+ public function getAccessToken($code)
+ {
+ if ($this->accessToken) {
+ return $this->accessToken;
+ }
+
+ $postKey = (1 === version_compare(ClientInterface::VERSION, '6')) ? 'form_params' : 'body';
+
+ $response = $this->getHttpClient()->post($this->getTokenUrl(), [
+ 'headers' => ['Accept' => 'application/json'],
+ $postKey => $this->getTokenFields($code),
+ ]);
+
+ return $this->parseAccessToken($response->getBody());
+ }
+
+ /**
+ * Set the scopes of the requested access.
+ *
+ * @param array $scopes
+ *
+ * @return $this
+ */
+ public function scopes(array $scopes)
+ {
+ $this->scopes = $scopes;
+
+ return $this;
+ }
+
+ /**
+ * Set the request instance.
+ *
+ * @param Request $request
+ *
+ * @return $this
+ */
+ public function setRequest(Request $request)
+ {
+ $this->request = $request;
+
+ return $this;
+ }
+
+ /**
+ * Get the request instance.
+ *
+ * @return \Symfony\Component\HttpFoundation\Request
+ */
+ public function getRequest()
+ {
+ return $this->request;
+ }
+
+ /**
+ * Indicates that the provider should operate as stateless.
+ *
+ * @return $this
+ */
+ public function stateless()
+ {
+ $this->stateless = true;
+
+ return $this;
+ }
+
+ /**
+ * Set the custom parameters of the request.
+ *
+ * @param array $parameters
+ *
+ * @return $this
+ */
+ public function with(array $parameters)
+ {
+ $this->parameters = $parameters;
+
+ return $this;
+ }
+
+ /**
+ * @throws \ReflectionException
+ *
+ * @return string
+ */
+ public function getName()
+ {
+ if (empty($this->name)) {
+ $this->name = strstr((new \ReflectionClass(get_class($this)))->getShortName(), 'Provider', true);
+ }
+
+ return $this->name;
+ }
+
+ /**
+ * Get the authentication URL for the provider.
+ *
+ * @param string $url
+ * @param string $state
+ *
+ * @return string
+ */
+ protected function buildAuthUrlFromBase($url, $state)
+ {
+ return $url.'?'.http_build_query($this->getCodeFields($state), '', '&', $this->encodingType);
+ }
+
+ /**
+ * Get the GET parameters for the code request.
+ *
+ * @param string|null $state
+ *
+ * @return array
+ */
+ protected function getCodeFields($state = null)
+ {
+ $fields = array_merge([
+ 'client_id' => $this->clientId,
+ 'redirect_uri' => $this->redirectUrl,
+ 'scope' => $this->formatScopes($this->scopes, $this->scopeSeparator),
+ 'response_type' => 'code',
+ ], $this->parameters);
+
+ if ($this->usesState()) {
+ $fields['state'] = $state;
+ }
+
+ return $fields;
+ }
+
+ /**
+ * Format the given scopes.
+ *
+ * @param array $scopes
+ * @param string $scopeSeparator
+ *
+ * @return string
+ */
+ protected function formatScopes(array $scopes, $scopeSeparator)
+ {
+ return implode($scopeSeparator, $scopes);
+ }
+
+ /**
+ * Determine if the current request / session has a mismatching "state".
+ *
+ * @return bool
+ */
+ protected function hasInvalidState()
+ {
+ if ($this->isStateless()) {
+ return false;
+ }
+
+ $state = $this->request->getSession()->get('state');
+
+ return !(strlen($state) > 0 && $this->request->get('state') === $state);
+ }
+
+ /**
+ * Get the POST fields for the token request.
+ *
+ * @param string $code
+ *
+ * @return array
+ */
+ protected function getTokenFields($code)
+ {
+ return [
+ 'client_id' => $this->clientId,
+ 'client_secret' => $this->clientSecret,
+ 'code' => $code,
+ 'redirect_uri' => $this->redirectUrl,
+ ];
+ }
+
+ /**
+ * Get the access token from the token response body.
+ *
+ * @param \Psr\Http\Message\StreamInterface|array $body
+ *
+ * @return \Overtrue\Socialite\AccessTokenInterface
+ */
+ protected function parseAccessToken($body)
+ {
+ if (!is_array($body)) {
+ $body = json_decode($body, true);
+ }
+
+ if (empty($body['access_token'])) {
+ throw new AuthorizeFailedException('Authorize Failed: '.json_encode($body, JSON_UNESCAPED_UNICODE), $body);
+ }
+
+ return new AccessToken($body);
+ }
+
+ /**
+ * Get the code from the request.
+ *
+ * @return string
+ */
+ protected function getCode()
+ {
+ return $this->request->get('code');
+ }
+
+ /**
+ * Get a fresh instance of the Guzzle HTTP client.
+ *
+ * @return \GuzzleHttp\Client
+ */
+ protected function getHttpClient()
+ {
+ return new Client(self::$guzzleOptions);
+ }
+
+ /**
+ * Set options for Guzzle HTTP client.
+ *
+ * @param array $config
+ *
+ * @return array
+ */
+ public static function setGuzzleOptions($config = [])
+ {
+ return self::$guzzleOptions = $config;
+ }
+
+ /**
+ * Determine if the provider is operating with state.
+ *
+ * @return bool
+ */
+ protected function usesState()
+ {
+ return !$this->stateless;
+ }
+
+ /**
+ * Determine if the provider is operating as stateless.
+ *
+ * @return bool
+ */
+ protected function isStateless()
+ {
+ return !$this->request->hasSession() || $this->stateless;
+ }
+
+ /**
+ * Return array item by key.
+ *
+ * @param array $array
+ * @param string $key
+ * @param mixed $default
+ *
+ * @return mixed
+ */
+ protected function arrayItem(array $array, $key, $default = null)
+ {
+ if (is_null($key)) {
+ return $array;
+ }
+
+ if (isset($array[$key])) {
+ return $array[$key];
+ }
+
+ foreach (explode('.', $key) as $segment) {
+ if (!is_array($array) || !array_key_exists($segment, $array)) {
+ return $default;
+ }
+
+ $array = $array[$segment];
+ }
+
+ return $array;
+ }
+
+ /**
+ * Put state to session storage and return it.
+ *
+ * @return string|bool
+ */
+ protected function makeState()
+ {
+ if (!$this->request->hasSession()) {
+ return false;
+ }
+
+ $state = sha1(uniqid(mt_rand(1, 1000000), true));
+ $session = $this->request->getSession();
+
+ if (is_callable([$session, 'put'])) {
+ $session->put('state', $state);
+ } elseif (is_callable([$session, 'set'])) {
+ $session->set('state', $state);
+ } else {
+ return false;
+ }
+
+ return $state;
+ }
+}
diff --git a/addons/weliam_smartcity/vendor/overtrue/socialite/src/Providers/DouYinProvider.php b/addons/weliam_smartcity/vendor/overtrue/socialite/src/Providers/DouYinProvider.php
new file mode 100644
index 0000000..6e0b108
--- /dev/null
+++ b/addons/weliam_smartcity/vendor/overtrue/socialite/src/Providers/DouYinProvider.php
@@ -0,0 +1,168 @@
+buildAuthUrlFromBase($this->baseUrl.'/platform/oauth/connect', $state);
+ }
+
+ /**
+ * 获取授权码接口参数.
+ *
+ * @param string|null $state
+ *
+ * @return array
+ */
+ public function getCodeFields($state = null)
+ {
+ $fields = [
+ 'client_key' => $this->clientId,
+ 'redirect_uri' => $this->redirectUrl,
+ 'scope' => $this->formatScopes($this->scopes, $this->scopeSeparator),
+ 'response_type' => 'code',
+ ];
+
+ if ($this->usesState()) {
+ $fields['state'] = $state;
+ }
+
+ return $fields;
+ }
+
+ /**
+ * 获取access_token地址.
+ *
+ * {@inheritdoc}
+ */
+ protected function getTokenUrl()
+ {
+ return $this->baseUrl.'/oauth/access_token';
+ }
+
+ /**
+ * 通过code获取access_token.
+ *
+ * @param string $code
+ *
+ * @return \Overtrue\Socialite\AccessToken
+ */
+ public function getAccessToken($code)
+ {
+ $response = $this->getHttpClient()->get($this->getTokenUrl(), [
+ 'query' => $this->getTokenFields($code),
+ ]);
+
+ return $this->parseAccessToken($response->getBody()->getContents());
+ }
+
+ /**
+ * 获取access_token接口参数.
+ *
+ * @param string $code
+ *
+ * @return array
+ */
+ protected function getTokenFields($code)
+ {
+ return [
+ 'client_key' => $this->clientId,
+ 'client_secret' => $this->clientSecret,
+ 'code' => $code,
+ 'grant_type' => 'authorization_code',
+ ];
+ }
+
+ /**
+ * 格式化token.
+ *
+ * @param \Psr\Http\Message\StreamInterface|array $body
+ *
+ * @return \Overtrue\Socialite\AccessTokenInterface
+ */
+ protected function parseAccessToken($body)
+ {
+ if (!is_array($body)) {
+ $body = json_decode($body, true);
+ }
+
+ if (empty($body['data']['access_token'])) {
+ throw new AuthorizeFailedException('Authorize Failed: '.json_encode($body, JSON_UNESCAPED_UNICODE), $body);
+ }
+
+ return new AccessToken($body['data']);
+ }
+
+ /**
+ * 通过token 获取用户信息.
+ *
+ * @param AccessTokenInterface $token
+ *
+ * @return array|mixed
+ */
+ protected function getUserByToken(AccessTokenInterface $token)
+ {
+ $userUrl = $this->baseUrl.'/oauth/userinfo/';
+
+ $response = $this->getHttpClient()->get(
+ $userUrl, [
+ 'query' => [
+ 'access_token' => $token->getToken(),
+ 'open_id' => $token['open_id'],
+ ],
+ ]
+ );
+
+ return json_decode($response->getBody(), true);
+ }
+
+ /**
+ * 格式化用户信息.
+ *
+ * @param array $user
+ *
+ * @return User
+ */
+ protected function mapUserToObject(array $user)
+ {
+ return new User([
+ 'id' => $this->arrayItem($user, 'open_id'),
+ 'username' => $this->arrayItem($user, 'nickname'),
+ 'nickname' => $this->arrayItem($user, 'nickname'),
+ 'avatar' => $this->arrayItem($user, 'avatar'),
+ ]);
+ }
+}
diff --git a/addons/weliam_smartcity/vendor/overtrue/socialite/src/Providers/DoubanProvider.php b/addons/weliam_smartcity/vendor/overtrue/socialite/src/Providers/DoubanProvider.php
new file mode 100644
index 0000000..f3b5c93
--- /dev/null
+++ b/addons/weliam_smartcity/vendor/overtrue/socialite/src/Providers/DoubanProvider.php
@@ -0,0 +1,88 @@
+
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace Overtrue\Socialite\Providers;
+
+use Overtrue\Socialite\AccessTokenInterface;
+use Overtrue\Socialite\ProviderInterface;
+use Overtrue\Socialite\User;
+
+/**
+ * Class DoubanProvider.
+ *
+ * @see http://developers.douban.com/wiki/?title=oauth2 [使用 OAuth 2.0 访问豆瓣 API]
+ */
+class DoubanProvider extends AbstractProvider implements ProviderInterface
+{
+ /**
+ * {@inheritdoc}.
+ */
+ protected function getAuthUrl($state)
+ {
+ return $this->buildAuthUrlFromBase('https://www.douban.com/service/auth2/auth', $state);
+ }
+
+ /**
+ * {@inheritdoc}.
+ */
+ protected function getTokenUrl()
+ {
+ return 'https://www.douban.com/service/auth2/token';
+ }
+
+ /**
+ * {@inheritdoc}.
+ */
+ protected function getUserByToken(AccessTokenInterface $token)
+ {
+ $response = $this->getHttpClient()->get('https://api.douban.com/v2/user/~me', [
+ 'headers' => [
+ 'Authorization' => 'Bearer '.$token->getToken(),
+ ],
+ ]);
+
+ return json_decode($response->getBody()->getContents(), true);
+ }
+
+ /**
+ * {@inheritdoc}.
+ */
+ protected function mapUserToObject(array $user)
+ {
+ return new User([
+ 'id' => $this->arrayItem($user, 'id'),
+ 'nickname' => $this->arrayItem($user, 'name'),
+ 'name' => $this->arrayItem($user, 'name'),
+ 'avatar' => $this->arrayItem($user, 'large_avatar'),
+ 'email' => null,
+ ]);
+ }
+
+ /**
+ * {@inheritdoc}.
+ */
+ protected function getTokenFields($code)
+ {
+ return parent::getTokenFields($code) + ['grant_type' => 'authorization_code'];
+ }
+
+ /**
+ * {@inheritdoc}.
+ */
+ public function getAccessToken($code)
+ {
+ $response = $this->getHttpClient()->post($this->getTokenUrl(), [
+ 'form_params' => $this->getTokenFields($code),
+ ]);
+
+ return $this->parseAccessToken($response->getBody()->getContents());
+ }
+}
diff --git a/addons/weliam_smartcity/vendor/overtrue/socialite/src/Providers/FacebookProvider.php b/addons/weliam_smartcity/vendor/overtrue/socialite/src/Providers/FacebookProvider.php
new file mode 100644
index 0000000..70f7b2e
--- /dev/null
+++ b/addons/weliam_smartcity/vendor/overtrue/socialite/src/Providers/FacebookProvider.php
@@ -0,0 +1,167 @@
+
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace Overtrue\Socialite\Providers;
+
+use Overtrue\Socialite\AccessTokenInterface;
+use Overtrue\Socialite\ProviderInterface;
+use Overtrue\Socialite\User;
+
+/**
+ * Class FacebookProvider.
+ *
+ * @see https://developers.facebook.com/docs/graph-api [Facebook - Graph API]
+ */
+class FacebookProvider extends AbstractProvider implements ProviderInterface
+{
+ /**
+ * The base Facebook Graph URL.
+ *
+ * @var string
+ */
+ protected $graphUrl = 'https://graph.facebook.com';
+
+ /**
+ * The Graph API version for the request.
+ *
+ * @var string
+ */
+ protected $version = 'v3.3';
+
+ /**
+ * The user fields being requested.
+ *
+ * @var array
+ */
+ protected $fields = ['first_name', 'last_name', 'email', 'gender', 'verified'];
+
+ /**
+ * The scopes being requested.
+ *
+ * @var array
+ */
+ protected $scopes = ['email'];
+
+ /**
+ * Display the dialog in a popup view.
+ *
+ * @var bool
+ */
+ protected $popup = false;
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function getAuthUrl($state)
+ {
+ return $this->buildAuthUrlFromBase('https://www.facebook.com/'.$this->version.'/dialog/oauth', $state);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function getTokenUrl()
+ {
+ return $this->graphUrl.'/oauth/access_token';
+ }
+
+ /**
+ * Get the access token for the given code.
+ *
+ * @param string $code
+ *
+ * @return \Overtrue\Socialite\AccessToken
+ */
+ public function getAccessToken($code)
+ {
+ $response = $this->getHttpClient()->get($this->getTokenUrl(), [
+ 'query' => $this->getTokenFields($code),
+ ]);
+
+ return $this->parseAccessToken($response->getBody());
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function getUserByToken(AccessTokenInterface $token)
+ {
+ $appSecretProof = hash_hmac('sha256', $token->getToken(), $this->clientSecret);
+
+ $response = $this->getHttpClient()->get($this->graphUrl.'/'.$this->version.'/me?access_token='.$token.'&appsecret_proof='.$appSecretProof.'&fields='.implode(',', $this->fields), [
+ 'headers' => [
+ 'Accept' => 'application/json',
+ ],
+ ]);
+
+ return json_decode($response->getBody(), true);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function mapUserToObject(array $user)
+ {
+ $avatarUrl = $this->graphUrl.'/'.$this->version.'/'.$user['id'].'/picture';
+
+ $firstName = $this->arrayItem($user, 'first_name');
+ $lastName = $this->arrayItem($user, 'last_name');
+
+ return new User([
+ 'id' => $this->arrayItem($user, 'id'),
+ 'nickname' => null,
+ 'name' => $firstName.' '.$lastName,
+ 'email' => $this->arrayItem($user, 'email'),
+ 'avatar' => $avatarUrl.'?type=normal',
+ 'avatar_original' => $avatarUrl.'?width=1920',
+ ]);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function getCodeFields($state = null)
+ {
+ $fields = parent::getCodeFields($state);
+
+ if ($this->popup) {
+ $fields['display'] = 'popup';
+ }
+
+ return $fields;
+ }
+
+ /**
+ * Set the user fields to request from Facebook.
+ *
+ * @param array $fields
+ *
+ * @return $this
+ */
+ public function fields(array $fields)
+ {
+ $this->fields = $fields;
+
+ return $this;
+ }
+
+ /**
+ * Set the dialog to be displayed as a popup.
+ *
+ * @return $this
+ */
+ public function asPopup()
+ {
+ $this->popup = true;
+
+ return $this;
+ }
+}
diff --git a/addons/weliam_smartcity/vendor/overtrue/socialite/src/Providers/GitHubProvider.php b/addons/weliam_smartcity/vendor/overtrue/socialite/src/Providers/GitHubProvider.php
new file mode 100644
index 0000000..410c80f
--- /dev/null
+++ b/addons/weliam_smartcity/vendor/overtrue/socialite/src/Providers/GitHubProvider.php
@@ -0,0 +1,121 @@
+
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace Overtrue\Socialite\Providers;
+
+use Exception;
+use Overtrue\Socialite\AccessTokenInterface;
+use Overtrue\Socialite\ProviderInterface;
+use Overtrue\Socialite\User;
+
+/**
+ * Class GitHubProvider.
+ */
+class GitHubProvider extends AbstractProvider implements ProviderInterface
+{
+ /**
+ * The scopes being requested.
+ *
+ * @var array
+ */
+ protected $scopes = ['user:email'];
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function getAuthUrl($state)
+ {
+ return $this->buildAuthUrlFromBase('https://github.com/login/oauth/authorize', $state);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function getTokenUrl()
+ {
+ return 'https://github.com/login/oauth/access_token';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function getUserByToken(AccessTokenInterface $token)
+ {
+ $userUrl = 'https://api.github.com/user?access_token='.$token->getToken();
+
+ $response = $this->getHttpClient()->get(
+ $userUrl, $this->getRequestOptions()
+ );
+
+ $user = json_decode($response->getBody(), true);
+
+ if (in_array('user:email', $this->scopes)) {
+ $user['email'] = $this->getEmailByToken($token);
+ }
+
+ return $user;
+ }
+
+ /**
+ * Get the email for the given access token.
+ *
+ * @param string $token
+ *
+ * @return string|null
+ */
+ protected function getEmailByToken($token)
+ {
+ $emailsUrl = 'https://api.github.com/user/emails?access_token='.$token->getToken();
+
+ try {
+ $response = $this->getHttpClient()->get(
+ $emailsUrl, $this->getRequestOptions()
+ );
+ } catch (Exception $e) {
+ return;
+ }
+
+ foreach (json_decode($response->getBody(), true) as $email) {
+ if ($email['primary'] && $email['verified']) {
+ return $email['email'];
+ }
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function mapUserToObject(array $user)
+ {
+ return new User([
+ 'id' => $this->arrayItem($user, 'id'),
+ 'username' => $this->arrayItem($user, 'login'),
+ 'nickname' => $this->arrayItem($user, 'login'),
+ 'name' => $this->arrayItem($user, 'name'),
+ 'email' => $this->arrayItem($user, 'email'),
+ 'avatar' => $this->arrayItem($user, 'avatar_url'),
+ ]);
+ }
+
+ /**
+ * Get the default options for an HTTP request.
+ *
+ * @return array
+ */
+ protected function getRequestOptions()
+ {
+ return [
+ 'headers' => [
+ 'Accept' => 'application/vnd.github.v3+json',
+ ],
+ ];
+ }
+}
diff --git a/addons/weliam_smartcity/vendor/overtrue/socialite/src/Providers/GoogleProvider.php b/addons/weliam_smartcity/vendor/overtrue/socialite/src/Providers/GoogleProvider.php
new file mode 100644
index 0000000..e74d830
--- /dev/null
+++ b/addons/weliam_smartcity/vendor/overtrue/socialite/src/Providers/GoogleProvider.php
@@ -0,0 +1,118 @@
+
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace Overtrue\Socialite\Providers;
+
+use GuzzleHttp\ClientInterface;
+use Overtrue\Socialite\AccessTokenInterface;
+use Overtrue\Socialite\ProviderInterface;
+use Overtrue\Socialite\User;
+
+/**
+ * Class GoogleProvider.
+ *
+ * @see https://developers.google.com/identity/protocols/OpenIDConnect [OpenID Connect]
+ */
+class GoogleProvider extends AbstractProvider implements ProviderInterface
+{
+ /**
+ * The separating character for the requested scopes.
+ *
+ * @var string
+ */
+ protected $scopeSeparator = ' ';
+
+ /**
+ * The scopes being requested.
+ *
+ * @var array
+ */
+ protected $scopes = [
+ 'https://www.googleapis.com/auth/userinfo.email',
+ 'https://www.googleapis.com/auth/userinfo.profile',
+ ];
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function getAuthUrl($state)
+ {
+ return $this->buildAuthUrlFromBase('https://accounts.google.com/o/oauth2/v2/auth', $state);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function getTokenUrl()
+ {
+ return 'https://www.googleapis.com/oauth2/v4/token';
+ }
+
+ /**
+ * Get the access token for the given code.
+ *
+ * @param string $code
+ *
+ * @return string
+ */
+ public function getAccessToken($code)
+ {
+ $postKey = (1 === version_compare(ClientInterface::VERSION, '6')) ? 'form_params' : 'body';
+
+ $response = $this->getHttpClient()->post($this->getTokenUrl(), [
+ $postKey => $this->getTokenFields($code),
+ ]);
+
+ return $this->parseAccessToken($response->getBody());
+ }
+
+ /**
+ * Get the POST fields for the token request.
+ *
+ * @param string $code
+ *
+ * @return array
+ */
+ protected function getTokenFields($code)
+ {
+ return parent::getTokenFields($code) + ['grant_type' => 'authorization_code'];
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function getUserByToken(AccessTokenInterface $token)
+ {
+ $response = $this->getHttpClient()->get('https://www.googleapis.com/userinfo/v2/me', [
+ 'headers' => [
+ 'Accept' => 'application/json',
+ 'Authorization' => 'Bearer '.$token->getToken(),
+ ],
+ ]);
+
+ return json_decode($response->getBody(), true);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function mapUserToObject(array $user)
+ {
+ return new User([
+ 'id' => $this->arrayItem($user, 'id'),
+ 'username' => $this->arrayItem($user, 'email'),
+ 'nickname' => $this->arrayItem($user, 'name'),
+ 'name' => $this->arrayItem($user, 'name'),
+ 'email' => $this->arrayItem($user, 'email'),
+ 'avatar' => $this->arrayItem($user, 'picture'),
+ ]);
+ }
+}
diff --git a/addons/weliam_smartcity/vendor/overtrue/socialite/src/Providers/LinkedinProvider.php b/addons/weliam_smartcity/vendor/overtrue/socialite/src/Providers/LinkedinProvider.php
new file mode 100644
index 0000000..019167a
--- /dev/null
+++ b/addons/weliam_smartcity/vendor/overtrue/socialite/src/Providers/LinkedinProvider.php
@@ -0,0 +1,181 @@
+
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace Overtrue\Socialite\Providers;
+
+use Overtrue\Socialite\AccessTokenInterface;
+use Overtrue\Socialite\ProviderInterface;
+use Overtrue\Socialite\User;
+
+/**
+ * Class LinkedinProvider.
+ *
+ * @see https://developer.linkedin.com/docs/oauth2 [Authenticating with OAuth 2.0]
+ */
+class LinkedinProvider extends AbstractProvider implements ProviderInterface
+{
+ /**
+ * The scopes being requested.
+ *
+ * @var array
+ */
+ protected $scopes = ['r_liteprofile', 'r_emailaddress'];
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function getAuthUrl($state)
+ {
+ return $this->buildAuthUrlFromBase('https://www.linkedin.com/oauth/v2/authorization', $state);
+ }
+
+ /**
+ * Get the access token for the given code.
+ *
+ * @param string $code
+ *
+ * @return \Overtrue\Socialite\AccessToken
+ */
+ public function getAccessToken($code)
+ {
+ $response = $this->getHttpClient()
+ ->post($this->getTokenUrl(), ['form_params' => $this->getTokenFields($code)]);
+
+ return $this->parseAccessToken($response->getBody());
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function getTokenUrl()
+ {
+ return 'https://www.linkedin.com/oauth/v2/accessToken';
+ }
+
+ /**
+ * Get the POST fields for the token request.
+ *
+ * @param string $code
+ *
+ * @return array
+ */
+ protected function getTokenFields($code)
+ {
+ return parent::getTokenFields($code) + ['grant_type' => 'authorization_code'];
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function getUserByToken(AccessTokenInterface $token)
+ {
+ $basicProfile = $this->getBasicProfile($token);
+ $emailAddress = $this->getEmailAddress($token);
+
+ return array_merge($basicProfile, $emailAddress);
+ }
+
+ /**
+ * Get the basic profile fields for the user.
+ *
+ * @param string $token
+ *
+ * @return array
+ */
+ protected function getBasicProfile($token)
+ {
+ $url = 'https://api.linkedin.com/v2/me?projection=(id,firstName,lastName,profilePicture(displayImage~:playableStreams))';
+
+ $response = $this->getHttpClient()->get($url, [
+ 'headers' => [
+ 'Authorization' => 'Bearer '.$token,
+ 'X-RestLi-Protocol-Version' => '2.0.0',
+ ],
+ ]);
+
+ return (array) json_decode($response->getBody(), true);
+ }
+
+ /**
+ * Get the email address for the user.
+ *
+ * @param string $token
+ *
+ * @return array
+ */
+ protected function getEmailAddress($token)
+ {
+ $url = 'https://api.linkedin.com/v2/emailAddress?q=members&projection=(elements*(handle~))';
+
+ $response = $this->getHttpClient()->get($url, [
+ 'headers' => [
+ 'Authorization' => 'Bearer '.$token,
+ 'X-RestLi-Protocol-Version' => '2.0.0',
+ ],
+ ]);
+
+ return (array) $this->arrayItem(json_decode($response->getBody(), true), 'elements.0.handle~');
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function mapUserToObject(array $user)
+ {
+ $preferredLocale = $this->arrayItem($user, 'firstName.preferredLocale.language').'_'.$this->arrayItem($user, 'firstName.preferredLocale.country');
+ $firstName = $this->arrayItem($user, 'firstName.localized.'.$preferredLocale);
+ $lastName = $this->arrayItem($user, 'lastName.localized.'.$preferredLocale);
+ $name = $firstName.' '.$lastName;
+
+ $images = (array) $this->arrayItem($user, 'profilePicture.displayImage~.elements', []);
+ $avatars = array_filter($images, function ($image) {
+ return $image['data']['com.linkedin.digitalmedia.mediaartifact.StillImage']['storageSize']['width'] === 100;
+ });
+ $avatar = array_shift($avatars);
+ $originalAvatars = array_filter($images, function ($image) {
+ return $image['data']['com.linkedin.digitalmedia.mediaartifact.StillImage']['storageSize']['width'] === 800;
+ });
+ $originalAvatar = array_shift($originalAvatars);
+
+ return new User([
+ 'id' => $this->arrayItem($user, 'id'),
+ 'nickname' => $name,
+ 'name' => $name,
+ 'email' => $this->arrayItem($user, 'emailAddress'),
+ 'avatar' => $avatar ? $this->arrayItem($avatar, 'identifiers.0.identifier') : null,
+ 'avatar_original' => $originalAvatar ? $this->arrayItem($originalAvatar, 'identifiers.0.identifier') : null,
+ ]);
+ }
+
+ /**
+ * Set the user fields to request from LinkedIn.
+ *
+ * @param array $fields
+ *
+ * @return $this
+ */
+ public function fields(array $fields)
+ {
+ $this->fields = $fields;
+
+ return $this;
+ }
+
+ /**
+ * Determine if the provider is operating as stateless.
+ *
+ * @return bool
+ */
+ protected function isStateless()
+ {
+ return true;
+ }
+}
diff --git a/addons/weliam_smartcity/vendor/overtrue/socialite/src/Providers/OutlookProvider.php b/addons/weliam_smartcity/vendor/overtrue/socialite/src/Providers/OutlookProvider.php
new file mode 100644
index 0000000..3a0fb56
--- /dev/null
+++ b/addons/weliam_smartcity/vendor/overtrue/socialite/src/Providers/OutlookProvider.php
@@ -0,0 +1,88 @@
+
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace Overtrue\Socialite\Providers;
+
+use Overtrue\Socialite\AccessTokenInterface;
+use Overtrue\Socialite\ProviderInterface;
+use Overtrue\Socialite\User;
+
+/**
+ * Class OutlookProvider.
+ */
+class OutlookProvider extends AbstractProvider implements ProviderInterface
+{
+ /**
+ * {@inheritdoc}
+ */
+ protected $scopes = ['User.Read'];
+
+ /**
+ * {@inheritdoc}
+ */
+ protected $scopeSeparator = ' ';
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function getAuthUrl($state)
+ {
+ return $this->buildAuthUrlFromBase('https://login.microsoftonline.com/common/oauth2/v2.0/authorize', $state);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function getTokenUrl()
+ {
+ return 'https://login.microsoftonline.com/common/oauth2/v2.0/token';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function getUserByToken(AccessTokenInterface $token)
+ {
+ $response = $this->getHttpClient()->get(
+ 'https://graph.microsoft.com/v1.0/me',
+ ['headers' => [
+ 'Accept' => 'application/json',
+ 'Authorization' => 'Bearer '.$token->getToken(),
+ ],
+ ]);
+
+ return json_decode($response->getBody()->getContents(), true);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function mapUserToObject(array $user)
+ {
+ return new User([
+ 'id' => $this->arrayItem($user, 'id'),
+ 'nickname' => null,
+ 'name' => $this->arrayItem($user, 'displayName'),
+ 'email' => $this->arrayItem($user, 'userPrincipalName'),
+ 'avatar' => null,
+ ]);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function getTokenFields($code)
+ {
+ return array_merge(parent::getTokenFields($code), [
+ 'grant_type' => 'authorization_code',
+ ]);
+ }
+}
diff --git a/addons/weliam_smartcity/vendor/overtrue/socialite/src/Providers/QQProvider.php b/addons/weliam_smartcity/vendor/overtrue/socialite/src/Providers/QQProvider.php
new file mode 100644
index 0000000..921bc20
--- /dev/null
+++ b/addons/weliam_smartcity/vendor/overtrue/socialite/src/Providers/QQProvider.php
@@ -0,0 +1,206 @@
+
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace Overtrue\Socialite\Providers;
+
+use Overtrue\Socialite\AccessTokenInterface;
+use Overtrue\Socialite\ProviderInterface;
+use Overtrue\Socialite\User;
+
+/**
+ * Class QQProvider.
+ *
+ * @see http://wiki.connect.qq.com/oauth2-0%E7%AE%80%E4%BB%8B [QQ - OAuth 2.0 登录QQ]
+ */
+class QQProvider extends AbstractProvider implements ProviderInterface
+{
+ /**
+ * The base url of QQ API.
+ *
+ * @var string
+ */
+ protected $baseUrl = 'https://graph.qq.com';
+
+ /**
+ * User openid.
+ *
+ * @var string
+ */
+ protected $openId;
+
+ /**
+ * get token(openid) with unionid.
+ *
+ * @var bool
+ */
+ protected $withUnionId = false;
+
+ /**
+ * User unionid.
+ *
+ * @var string
+ */
+ protected $unionId;
+
+ /**
+ * The scopes being requested.
+ *
+ * @var array
+ */
+ protected $scopes = ['get_user_info'];
+
+ /**
+ * The uid of user authorized.
+ *
+ * @var int
+ */
+ protected $uid;
+
+ /**
+ * Get the authentication URL for the provider.
+ *
+ * @param string $state
+ *
+ * @return string
+ */
+ protected function getAuthUrl($state)
+ {
+ return $this->buildAuthUrlFromBase($this->baseUrl.'/oauth2.0/authorize', $state);
+ }
+
+ /**
+ * Get the token URL for the provider.
+ *
+ * @return string
+ */
+ protected function getTokenUrl()
+ {
+ return $this->baseUrl.'/oauth2.0/token';
+ }
+
+ /**
+ * Get the Post fields for the token request.
+ *
+ * @param string $code
+ *
+ * @return array
+ */
+ protected function getTokenFields($code)
+ {
+ return parent::getTokenFields($code) + ['grant_type' => 'authorization_code'];
+ }
+
+ /**
+ * Get the access token for the given code.
+ *
+ * @param string $code
+ *
+ * @return \Overtrue\Socialite\AccessToken
+ */
+ public function getAccessToken($code)
+ {
+ $response = $this->getHttpClient()->get($this->getTokenUrl(), [
+ 'query' => $this->getTokenFields($code),
+ ]);
+
+ return $this->parseAccessToken($response->getBody()->getContents());
+ }
+
+ /**
+ * Get the access token from the token response body.
+ *
+ * @param string $body
+ *
+ * @return \Overtrue\Socialite\AccessToken
+ */
+ public function parseAccessToken($body)
+ {
+ parse_str($body, $token);
+
+ return parent::parseAccessToken($token);
+ }
+
+ /**
+ * @return self
+ */
+ public function withUnionId()
+ {
+ $this->withUnionId = true;
+
+ return $this;
+ }
+
+ /**
+ * Get the raw user for the given access token.
+ *
+ * @param \Overtrue\Socialite\AccessTokenInterface $token
+ *
+ * @return array
+ */
+ protected function getUserByToken(AccessTokenInterface $token)
+ {
+ $url = $this->baseUrl.'/oauth2.0/me?access_token='.$token->getToken();
+ $this->withUnionId && $url .= '&unionid=1';
+
+ $response = $this->getHttpClient()->get($url);
+
+ $me = json_decode($this->removeCallback($response->getBody()->getContents()), true);
+ $this->openId = $me['openid'];
+ $this->unionId = isset($me['unionid']) ? $me['unionid'] : '';
+
+ $queries = [
+ 'access_token' => $token->getToken(),
+ 'openid' => $this->openId,
+ 'oauth_consumer_key' => $this->clientId,
+ ];
+
+ $response = $this->getHttpClient()->get($this->baseUrl.'/user/get_user_info?'.http_build_query($queries));
+
+ return json_decode($this->removeCallback($response->getBody()->getContents()), true);
+ }
+
+ /**
+ * Map the raw user array to a Socialite User instance.
+ *
+ * @param array $user
+ *
+ * @return \Overtrue\Socialite\User
+ */
+ protected function mapUserToObject(array $user)
+ {
+ return new User([
+ 'id' => $this->openId,
+ 'unionid' => $this->unionId,
+ 'nickname' => $this->arrayItem($user, 'nickname'),
+ 'name' => $this->arrayItem($user, 'nickname'),
+ 'email' => $this->arrayItem($user, 'email'),
+ 'avatar' => $this->arrayItem($user, 'figureurl_qq_2'),
+ ]);
+ }
+
+ /**
+ * Remove the fucking callback parentheses.
+ *
+ * @param string $response
+ *
+ * @return string
+ */
+ protected function removeCallback($response)
+ {
+ if (false !== strpos($response, 'callback')) {
+ $lpos = strpos($response, '(');
+ $rpos = strrpos($response, ')');
+ $response = substr($response, $lpos + 1, $rpos - $lpos - 1);
+ }
+
+ return $response;
+ }
+}
diff --git a/addons/weliam_smartcity/vendor/overtrue/socialite/src/Providers/TaobaoProvider.php b/addons/weliam_smartcity/vendor/overtrue/socialite/src/Providers/TaobaoProvider.php
new file mode 100644
index 0000000..f7da073
--- /dev/null
+++ b/addons/weliam_smartcity/vendor/overtrue/socialite/src/Providers/TaobaoProvider.php
@@ -0,0 +1,242 @@
+
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace Overtrue\Socialite\Providers;
+
+use Overtrue\Socialite\AccessTokenInterface;
+use Overtrue\Socialite\ProviderInterface;
+use Overtrue\Socialite\User;
+
+/**
+ * Class TaobaoProvider.
+ *
+ * @author mechono
+ *
+ * @see https://open.taobao.com/doc.htm?docId=102635&docType=1&source=search [Taobao - OAuth 2.0 授权登录]
+ */
+class TaobaoProvider extends AbstractProvider implements ProviderInterface
+{
+ /**
+ * The base url of Taobao API.
+ *
+ * @var string
+ */
+ protected $baseUrl = 'https://oauth.taobao.com';
+
+ /**
+ * Taobao API service URL address.
+ *
+ * @var string
+ */
+ protected $gatewayUrl = 'https://eco.taobao.com/router/rest';
+
+ /**
+ * The API version for the request.
+ *
+ * @var string
+ */
+ protected $version = '2.0';
+
+ /**
+ * @var string
+ */
+ protected $format = 'json';
+
+ /**
+ * @var string
+ */
+ protected $signMethod = 'md5';
+
+ /**
+ * Web 对应 PC 端(淘宝 logo )浏览器页面样式;Tmall 对应天猫的浏览器页面样式;Wap 对应无线端的浏览器页面样式。
+ */
+ protected $view = 'web';
+
+ /**
+ * The scopes being requested.
+ *
+ * @var array
+ */
+ protected $scopes = ['user_info'];
+
+ /**
+ * Get the authentication URL for the provider.
+ *
+ * @param string $state
+ *
+ * @return string
+ */
+ protected function getAuthUrl($state)
+ {
+ return $this->buildAuthUrlFromBase($this->baseUrl.'/authorize', $state);
+ }
+
+ /**
+ * 获取授权码接口参数.
+ *
+ * @param string|null $state
+ *
+ * @return array
+ */
+ public function getCodeFields($state = null)
+ {
+ $fields = [
+ 'client_id' => $this->clientId,
+ 'redirect_uri' => $this->redirectUrl,
+ 'view' => $this->view,
+ 'response_type' => 'code',
+ ];
+
+ if ($this->usesState()) {
+ $fields['state'] = $state;
+ }
+
+ return $fields;
+ }
+
+ /**
+ * Get the token URL for the provider.
+ *
+ * @return string
+ */
+ protected function getTokenUrl()
+ {
+ return $this->baseUrl.'/token';
+ }
+
+ /**
+ * Get the Post fields for the token request.
+ *
+ * @param string $code
+ *
+ * @return array
+ */
+ protected function getTokenFields($code)
+ {
+ return parent::getTokenFields($code) + ['grant_type' => 'authorization_code', 'view' => $this->view];
+ }
+
+ /**
+ * Get the access token for the given code.
+ *
+ * @param string $code
+ *
+ * @return \Overtrue\Socialite\AccessToken
+ */
+ public function getAccessToken($code)
+ {
+ $response = $this->getHttpClient()->post($this->getTokenUrl(), [
+ 'query' => $this->getTokenFields($code),
+ ]);
+
+ return $this->parseAccessToken($response->getBody()->getContents());
+ }
+
+ /**
+ * Get the access token from the token response body.
+ *
+ * @param string $body
+ *
+ * @return \Overtrue\Socialite\AccessToken
+ */
+ public function parseAccessToken($body)
+ {
+ return parent::parseAccessToken($body);
+ }
+
+ /**
+ * Get the raw user for the given access token.
+ *
+ * @param \Overtrue\Socialite\AccessTokenInterface $token
+ *
+ * @return array
+ */
+ protected function getUserByToken(AccessTokenInterface $token)
+ {
+ $response = $this->getHttpClient()->post($this->getUserInfoUrl($this->gatewayUrl, $token));
+
+ return json_decode($response->getBody(), true);
+ }
+
+ /**
+ * Map the raw user array to a Socialite User instance.
+ *
+ * @param array $user
+ *
+ * @return \Overtrue\Socialite\User
+ */
+ protected function mapUserToObject(array $user)
+ {
+ return new User([
+ 'id' => $this->arrayItem($user, 'open_id'),
+ 'nickname' => $this->arrayItem($user, 'nick'),
+ 'name' => $this->arrayItem($user, 'nick'),
+ 'avatar' => $this->arrayItem($user, 'avatar'),
+ ]);
+ }
+
+ /**
+ * @param $params
+ *
+ * @return string
+ */
+ protected function generateSign($params)
+ {
+ ksort($params);
+
+ $stringToBeSigned = $this->clientSecret;
+
+ foreach ($params as $k => $v) {
+ if (!is_array($v) && '@' != substr($v, 0, 1)) {
+ $stringToBeSigned .= "$k$v";
+ }
+ }
+
+ $stringToBeSigned .= $this->clientSecret;
+
+ return strtoupper(md5($stringToBeSigned));
+ }
+
+ /**
+ * @param \Overtrue\Socialite\AccessTokenInterface $token
+ * @param array $apiFields
+ *
+ * @return array
+ */
+ protected function getPublicFields(AccessTokenInterface $token, array $apiFields = [])
+ {
+ $fields = [
+ 'app_key' => $this->clientId,
+ 'sign_method' => $this->signMethod,
+ 'session' => $token->getToken(),
+ 'timestamp' => date('Y-m-d H:i:s'),
+ 'v' => $this->version,
+ 'format' => $this->format,
+ ];
+
+ $fields = array_merge($apiFields, $fields);
+ $fields['sign'] = $this->generateSign($fields);
+
+ return $fields;
+ }
+
+ /**
+ * {@inheritdoc}.
+ */
+ protected function getUserInfoUrl($url, AccessTokenInterface $token)
+ {
+ $apiFields = ['method' => 'taobao.miniapp.userInfo.get'];
+
+ $query = http_build_query($this->getPublicFields($token, $apiFields), '', '&', $this->encodingType);
+
+ return $url.'?'.$query;
+ }
+}
diff --git a/addons/weliam_smartcity/vendor/overtrue/socialite/src/Providers/WeChatProvider.php b/addons/weliam_smartcity/vendor/overtrue/socialite/src/Providers/WeChatProvider.php
new file mode 100644
index 0000000..8fb48d3
--- /dev/null
+++ b/addons/weliam_smartcity/vendor/overtrue/socialite/src/Providers/WeChatProvider.php
@@ -0,0 +1,234 @@
+
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace Overtrue\Socialite\Providers;
+
+use Overtrue\Socialite\AccessTokenInterface;
+use Overtrue\Socialite\InvalidArgumentException;
+use Overtrue\Socialite\ProviderInterface;
+use Overtrue\Socialite\User;
+use Overtrue\Socialite\WeChatComponentInterface;
+
+/**
+ * Class WeChatProvider.
+ *
+ * @see http://mp.weixin.qq.com/wiki/9/01f711493b5a02f24b04365ac5d8fd95.html [WeChat - 公众平台OAuth文档]
+ * @see https://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&t=resource/res_list&verify=1&id=open1419316505&token=&lang=zh_CN [网站应用微信登录开发指南]
+ */
+class WeChatProvider extends AbstractProvider implements ProviderInterface
+{
+ /**
+ * The base url of WeChat API.
+ *
+ * @var string
+ */
+ protected $baseUrl = 'https://api.weixin.qq.com/sns';
+
+ /**
+ * {@inheritdoc}.
+ */
+ protected $openId;
+
+ /**
+ * {@inheritdoc}.
+ */
+ protected $scopes = ['snsapi_login'];
+
+ /**
+ * Indicates if the session state should be utilized.
+ *
+ * @var bool
+ */
+ protected $stateless = true;
+
+ /**
+ * Return country code instead of country name.
+ *
+ * @var bool
+ */
+ protected $withCountryCode = false;
+
+ /**
+ * @var WeChatComponentInterface
+ */
+ protected $component;
+
+ /**
+ * Return country code instead of country name.
+ *
+ * @return $this
+ */
+ public function withCountryCode()
+ {
+ $this->withCountryCode = true;
+
+ return $this;
+ }
+
+ /**
+ * WeChat OpenPlatform 3rd component.
+ *
+ * @param WeChatComponentInterface $component
+ *
+ * @return $this
+ */
+ public function component(WeChatComponentInterface $component)
+ {
+ $this->scopes = ['snsapi_base'];
+
+ $this->component = $component;
+
+ return $this;
+ }
+
+ /**
+ * {@inheritdoc}.
+ */
+ public function getAccessToken($code)
+ {
+ $response = $this->getHttpClient()->get($this->getTokenUrl(), [
+ 'headers' => ['Accept' => 'application/json'],
+ 'query' => $this->getTokenFields($code),
+ ]);
+
+ return $this->parseAccessToken($response->getBody());
+ }
+
+ /**
+ * {@inheritdoc}.
+ */
+ protected function getAuthUrl($state)
+ {
+ $path = 'oauth2/authorize';
+
+ if (in_array('snsapi_login', $this->scopes)) {
+ $path = 'qrconnect';
+ }
+
+ return $this->buildAuthUrlFromBase("https://open.weixin.qq.com/connect/{$path}", $state);
+ }
+
+ /**
+ * {@inheritdoc}.
+ */
+ protected function buildAuthUrlFromBase($url, $state)
+ {
+ $query = http_build_query($this->getCodeFields($state), '', '&', $this->encodingType);
+
+ return $url.'?'.$query.'#wechat_redirect';
+ }
+
+ /**
+ * {@inheritdoc}.
+ */
+ protected function getCodeFields($state = null)
+ {
+ if ($this->component) {
+ $this->with(['component_appid' => $this->component->getAppId()]);
+ }
+
+ return array_merge([
+ 'appid' => $this->clientId,
+ 'redirect_uri' => $this->redirectUrl,
+ 'response_type' => 'code',
+ 'scope' => $this->formatScopes($this->scopes, $this->scopeSeparator),
+ 'state' => $state ?: md5(time()),
+ 'connect_redirect' => 1,
+ ], $this->parameters);
+ }
+
+ /**
+ * {@inheritdoc}.
+ */
+ protected function getTokenUrl()
+ {
+ if ($this->component) {
+ return $this->baseUrl.'/oauth2/component/access_token';
+ }
+
+ return $this->baseUrl.'/oauth2/access_token';
+ }
+
+ /**
+ * {@inheritdoc}.
+ */
+ protected function getUserByToken(AccessTokenInterface $token)
+ {
+ $scopes = explode(',', $token->getAttribute('scope', ''));
+
+ if (in_array('snsapi_base', $scopes)) {
+ return $token->toArray();
+ }
+
+ if (empty($token['openid'])) {
+ throw new InvalidArgumentException('openid of AccessToken is required.');
+ }
+
+ $language = $this->withCountryCode ? null : (isset($this->parameters['lang']) ? $this->parameters['lang'] : 'zh_CN');
+
+ $response = $this->getHttpClient()->get($this->baseUrl.'/userinfo', [
+ 'query' => array_filter([
+ 'access_token' => $token->getToken(),
+ 'openid' => $token['openid'],
+ 'lang' => $language,
+ ]),
+ ]);
+
+ return json_decode($response->getBody(), true);
+ }
+
+ /**
+ * {@inheritdoc}.
+ */
+ protected function mapUserToObject(array $user)
+ {
+ return new User([
+ 'id' => $this->arrayItem($user, 'openid'),
+ 'name' => $this->arrayItem($user, 'nickname'),
+ 'nickname' => $this->arrayItem($user, 'nickname'),
+ 'avatar' => $this->arrayItem($user, 'headimgurl'),
+ 'email' => null,
+ ]);
+ }
+
+ /**
+ * {@inheritdoc}.
+ */
+ protected function getTokenFields($code)
+ {
+ return array_filter([
+ 'appid' => $this->clientId,
+ 'secret' => $this->clientSecret,
+ 'component_appid' => $this->component ? $this->component->getAppId() : null,
+ 'component_access_token' => $this->component ? $this->component->getToken() : null,
+ 'code' => $code,
+ 'grant_type' => 'authorization_code',
+ ]);
+ }
+
+ /**
+ * Remove the fucking callback parentheses.
+ *
+ * @param mixed $response
+ *
+ * @return string
+ */
+ protected function removeCallback($response)
+ {
+ if (false !== strpos($response, 'callback')) {
+ $lpos = strpos($response, '(');
+ $rpos = strrpos($response, ')');
+ $response = substr($response, $lpos + 1, $rpos - $lpos - 1);
+ }
+
+ return $response;
+ }
+}
diff --git a/addons/weliam_smartcity/vendor/overtrue/socialite/src/Providers/WeWorkProvider.php b/addons/weliam_smartcity/vendor/overtrue/socialite/src/Providers/WeWorkProvider.php
new file mode 100644
index 0000000..1327e80
--- /dev/null
+++ b/addons/weliam_smartcity/vendor/overtrue/socialite/src/Providers/WeWorkProvider.php
@@ -0,0 +1,214 @@
+
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace Overtrue\Socialite\Providers;
+
+use Overtrue\Socialite\AccessTokenInterface;
+use Overtrue\Socialite\ProviderInterface;
+use Overtrue\Socialite\User;
+
+/**
+ * Class WeWorkProvider.
+ *
+ * @author mingyoung
+ */
+class WeWorkProvider extends AbstractProvider implements ProviderInterface
+{
+ /**
+ * @var string
+ */
+ protected $agentId;
+
+ /**
+ * @var bool
+ */
+ protected $detailed = false;
+
+ /**
+ * Set agent id.
+ *
+ * @param string $agentId
+ *
+ * @return $this
+ */
+ public function setAgentId($agentId)
+ {
+ $this->agentId = $agentId;
+
+ return $this;
+ }
+
+ /**
+ * @param string $agentId
+ *
+ * @return $this
+ */
+ public function agent($agentId)
+ {
+ return $this->setAgentId($agentId);
+ }
+
+ /**
+ * Return user details.
+ *
+ * @return $this
+ */
+ public function detailed()
+ {
+ $this->detailed = true;
+
+ return $this;
+ }
+
+ /**
+ * @param string $state
+ *
+ * @return string
+ */
+ protected function getAuthUrl($state)
+ {
+ // 网页授权登录
+ if (!empty($this->scopes)) {
+ return $this->getOAuthUrl($state);
+ }
+
+ // 第三方网页应用登录(扫码登录)
+ return $this->getQrConnectUrl($state);
+ }
+
+ /**
+ * OAuth url.
+ *
+ * @param string $state
+ *
+ * @return string
+ */
+ protected function getOAuthUrl($state)
+ {
+ $queries = [
+ 'appid' => $this->clientId,
+ 'redirect_uri' => $this->redirectUrl,
+ 'response_type' => 'code',
+ 'scope' => $this->formatScopes($this->scopes, $this->scopeSeparator),
+ 'agentid' => $this->agentId,
+ 'state' => $state,
+ ];
+
+ return sprintf('https://open.weixin.qq.com/connect/oauth2/authorize?%s#wechat_redirect', http_build_query($queries));
+ }
+
+ /**
+ * Qr connect url.
+ *
+ * @param string $state
+ *
+ * @return string
+ */
+ protected function getQrConnectUrl($state)
+ {
+ $queries = [
+ 'appid' => $this->clientId,
+ 'agentid' => $this->agentId,
+ 'redirect_uri' => $this->redirectUrl,
+ 'state' => $state,
+ ];
+
+ return 'https://open.work.weixin.qq.com/wwopen/sso/qrConnect?'.http_build_query($queries);
+ }
+
+ protected function getTokenUrl()
+ {
+ return null;
+ }
+
+ /**
+ * @param \Overtrue\Socialite\AccessTokenInterface $token
+ *
+ * @return mixed
+ */
+ protected function getUserByToken(AccessTokenInterface $token)
+ {
+ $userInfo = $this->getUserInfo($token);
+
+ if ($this->detailed && isset($userInfo['user_ticket'])) {
+ return $this->getUserDetail($token, $userInfo['user_ticket']);
+ }
+
+ $this->detailed = false;
+
+ return $userInfo;
+ }
+
+ /**
+ * Get user base info.
+ *
+ * @param \Overtrue\Socialite\AccessTokenInterface $token
+ *
+ * @return mixed
+ */
+ protected function getUserInfo(AccessTokenInterface $token)
+ {
+ $response = $this->getHttpClient()->get('https://qyapi.weixin.qq.com/cgi-bin/user/getuserinfo', [
+ 'query' => array_filter([
+ 'access_token' => $token->getToken(),
+ 'code' => $this->getCode(),
+ ]),
+ ]);
+
+ return json_decode($response->getBody(), true);
+ }
+
+ /**
+ * Get user detail info.
+ *
+ * @param \Overtrue\Socialite\AccessTokenInterface $token
+ * @param $ticket
+ *
+ * @return mixed
+ */
+ protected function getUserDetail(AccessTokenInterface $token, $ticket)
+ {
+ $response = $this->getHttpClient()->post('https://qyapi.weixin.qq.com/cgi-bin/user/getuserdetail', [
+ 'query' => [
+ 'access_token' => $token->getToken(),
+ ],
+ 'json' => [
+ 'user_ticket' => $ticket,
+ ],
+ ]);
+
+ return json_decode($response->getBody(), true);
+ }
+
+ /**
+ * @param array $user
+ *
+ * @return \Overtrue\Socialite\User
+ */
+ protected function mapUserToObject(array $user)
+ {
+ if ($this->detailed) {
+ return new User([
+ 'id' => $this->arrayItem($user, 'userid'),
+ 'name' => $this->arrayItem($user, 'name'),
+ 'avatar' => $this->arrayItem($user, 'avatar'),
+ 'email' => $this->arrayItem($user, 'email'),
+ ]);
+ }
+
+ return new User(array_filter([
+ 'id' => $this->arrayItem($user, 'UserId') ?: $this->arrayItem($user, 'OpenId'),
+ 'userId' => $this->arrayItem($user, 'UserId'),
+ 'openid' => $this->arrayItem($user, 'OpenId'),
+ 'deviceId' => $this->arrayItem($user, 'DeviceId'),
+ ]));
+ }
+}
diff --git a/addons/weliam_smartcity/vendor/overtrue/socialite/src/Providers/WeiboProvider.php b/addons/weliam_smartcity/vendor/overtrue/socialite/src/Providers/WeiboProvider.php
new file mode 100644
index 0000000..47ec56d
--- /dev/null
+++ b/addons/weliam_smartcity/vendor/overtrue/socialite/src/Providers/WeiboProvider.php
@@ -0,0 +1,126 @@
+
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace Overtrue\Socialite\Providers;
+
+use Overtrue\Socialite\AccessTokenInterface;
+use Overtrue\Socialite\ProviderInterface;
+use Overtrue\Socialite\User;
+
+/**
+ * Class WeiboProvider.
+ *
+ * @see http://open.weibo.com/wiki/%E6%8E%88%E6%9D%83%E6%9C%BA%E5%88%B6%E8%AF%B4%E6%98%8E [OAuth 2.0 授权机制说明]
+ */
+class WeiboProvider extends AbstractProvider implements ProviderInterface
+{
+ /**
+ * The base url of Weibo API.
+ *
+ * @var string
+ */
+ protected $baseUrl = 'https://api.weibo.com';
+
+ /**
+ * The API version for the request.
+ *
+ * @var string
+ */
+ protected $version = '2';
+
+ /**
+ * The scopes being requested.
+ *
+ * @var array
+ */
+ protected $scopes = ['email'];
+
+ /**
+ * The uid of user authorized.
+ *
+ * @var int
+ */
+ protected $uid;
+
+ /**
+ * Get the authentication URL for the provider.
+ *
+ * @param string $state
+ *
+ * @return string
+ */
+ protected function getAuthUrl($state)
+ {
+ return $this->buildAuthUrlFromBase($this->baseUrl.'/oauth2/authorize', $state);
+ }
+
+ /**
+ * Get the token URL for the provider.
+ *
+ * @return string
+ */
+ protected function getTokenUrl()
+ {
+ return $this->baseUrl.'/'.$this->version.'/oauth2/access_token';
+ }
+
+ /**
+ * Get the Post fields for the token request.
+ *
+ * @param string $code
+ *
+ * @return array
+ */
+ protected function getTokenFields($code)
+ {
+ return parent::getTokenFields($code) + ['grant_type' => 'authorization_code'];
+ }
+
+ /**
+ * Get the raw user for the given access token.
+ *
+ * @param \Overtrue\Socialite\AccessTokenInterface $token
+ *
+ * @return array
+ */
+ protected function getUserByToken(AccessTokenInterface $token)
+ {
+ $response = $this->getHttpClient()->get($this->baseUrl.'/'.$this->version.'/users/show.json', [
+ 'query' => [
+ 'uid' => $token['uid'],
+ 'access_token' => $token->getToken(),
+ ],
+ 'headers' => [
+ 'Accept' => 'application/json',
+ ],
+ ]);
+
+ return json_decode($response->getBody(), true);
+ }
+
+ /**
+ * Map the raw user array to a Socialite User instance.
+ *
+ * @param array $user
+ *
+ * @return \Overtrue\Socialite\User
+ */
+ protected function mapUserToObject(array $user)
+ {
+ return new User([
+ 'id' => $this->arrayItem($user, 'id'),
+ 'nickname' => $this->arrayItem($user, 'screen_name'),
+ 'name' => $this->arrayItem($user, 'name'),
+ 'email' => $this->arrayItem($user, 'email'),
+ 'avatar' => $this->arrayItem($user, 'avatar_large'),
+ ]);
+ }
+}
diff --git a/addons/weliam_smartcity/vendor/overtrue/socialite/src/SocialiteManager.php b/addons/weliam_smartcity/vendor/overtrue/socialite/src/SocialiteManager.php
new file mode 100644
index 0000000..8e99cf0
--- /dev/null
+++ b/addons/weliam_smartcity/vendor/overtrue/socialite/src/SocialiteManager.php
@@ -0,0 +1,251 @@
+
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace Overtrue\Socialite;
+
+use Closure;
+use InvalidArgumentException;
+use Symfony\Component\HttpFoundation\Request;
+use Symfony\Component\HttpFoundation\Session\Session;
+
+/**
+ * Class SocialiteManager.
+ */
+class SocialiteManager implements FactoryInterface
+{
+ /**
+ * The configuration.
+ *
+ * @var \Overtrue\Socialite\Config
+ */
+ protected $config;
+
+ /**
+ * The request instance.
+ *
+ * @var Request
+ */
+ protected $request;
+
+ /**
+ * The registered custom driver creators.
+ *
+ * @var array
+ */
+ protected $customCreators = [];
+
+ /**
+ * The initial drivers.
+ *
+ * @var array
+ */
+ protected $initialDrivers = [
+ 'facebook' => 'Facebook',
+ 'github' => 'GitHub',
+ 'google' => 'Google',
+ 'linkedin' => 'Linkedin',
+ 'weibo' => 'Weibo',
+ 'qq' => 'QQ',
+ 'wechat' => 'WeChat',
+ 'douban' => 'Douban',
+ 'wework' => 'WeWork',
+ 'outlook' => 'Outlook',
+ 'douyin' => 'DouYin',
+ 'taobao' => 'Taobao',
+ ];
+
+ /**
+ * The array of created "drivers".
+ *
+ * @var ProviderInterface[]
+ */
+ protected $drivers = [];
+
+ /**
+ * SocialiteManager constructor.
+ *
+ * @param array $config
+ * @param Request|null $request
+ */
+ public function __construct(array $config, Request $request = null)
+ {
+ $this->config = new Config($config);
+
+ if ($this->config->has('guzzle')) {
+ Providers\AbstractProvider::setGuzzleOptions($this->config->get('guzzle'));
+ }
+
+ if ($request) {
+ $this->setRequest($request);
+ }
+ }
+
+ /**
+ * Set config instance.
+ *
+ * @param \Overtrue\Socialite\Config $config
+ *
+ * @return $this
+ */
+ public function config(Config $config)
+ {
+ $this->config = $config;
+
+ return $this;
+ }
+
+ /**
+ * Get a driver instance.
+ *
+ * @param string $driver
+ *
+ * @return ProviderInterface
+ */
+ public function driver($driver)
+ {
+ if (!isset($this->drivers[$driver])) {
+ $this->drivers[$driver] = $this->createDriver($driver);
+ }
+
+ return $this->drivers[$driver];
+ }
+
+ /**
+ * @param \Symfony\Component\HttpFoundation\Request $request
+ *
+ * @return $this
+ */
+ public function setRequest(Request $request)
+ {
+ $this->request = $request;
+
+ return $this;
+ }
+
+ /**
+ * @return \Symfony\Component\HttpFoundation\Request
+ */
+ public function getRequest()
+ {
+ return $this->request ?: $this->createDefaultRequest();
+ }
+
+ /**
+ * Create a new driver instance.
+ *
+ * @param string $driver
+ *
+ * @throws \InvalidArgumentException
+ *
+ * @return ProviderInterface
+ */
+ protected function createDriver($driver)
+ {
+ if (isset($this->initialDrivers[$driver])) {
+ $provider = $this->initialDrivers[$driver];
+ $provider = __NAMESPACE__.'\\Providers\\'.$provider.'Provider';
+
+ return $this->buildProvider($provider, $this->formatConfig($this->config->get($driver)));
+ }
+
+ if (isset($this->customCreators[$driver])) {
+ return $this->callCustomCreator($driver);
+ }
+
+ throw new InvalidArgumentException("Driver [$driver] not supported.");
+ }
+
+ /**
+ * Call a custom driver creator.
+ *
+ * @param string $driver
+ *
+ * @return ProviderInterface
+ */
+ protected function callCustomCreator($driver)
+ {
+ return $this->customCreators[$driver]($this->config);
+ }
+
+ /**
+ * Create default request instance.
+ *
+ * @return Request
+ */
+ protected function createDefaultRequest()
+ {
+ $request = Request::createFromGlobals();
+ $session = new Session();
+
+ $request->setSession($session);
+
+ return $request;
+ }
+
+ /**
+ * Register a custom driver creator Closure.
+ *
+ * @param string $driver
+ * @param \Closure $callback
+ *
+ * @return $this
+ */
+ public function extend($driver, Closure $callback)
+ {
+ $this->customCreators[$driver] = $callback;
+
+ return $this;
+ }
+
+ /**
+ * Get all of the created "drivers".
+ *
+ * @return ProviderInterface[]
+ */
+ public function getDrivers()
+ {
+ return $this->drivers;
+ }
+
+ /**
+ * Build an OAuth 2 provider instance.
+ *
+ * @param string $provider
+ * @param array $config
+ *
+ * @return ProviderInterface
+ */
+ public function buildProvider($provider, $config)
+ {
+ return new $provider(
+ $this->getRequest(),
+ $config['client_id'],
+ $config['client_secret'],
+ $config['redirect']
+ );
+ }
+
+ /**
+ * Format the server configuration.
+ *
+ * @param array $config
+ *
+ * @return array
+ */
+ public function formatConfig(array $config)
+ {
+ return array_merge([
+ 'identifier' => $config['client_id'],
+ 'secret' => $config['client_secret'],
+ 'callback_uri' => $config['redirect'],
+ ], $config);
+ }
+}
diff --git a/addons/weliam_smartcity/vendor/overtrue/socialite/src/User.php b/addons/weliam_smartcity/vendor/overtrue/socialite/src/User.php
new file mode 100644
index 0000000..82827dd
--- /dev/null
+++ b/addons/weliam_smartcity/vendor/overtrue/socialite/src/User.php
@@ -0,0 +1,186 @@
+
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace Overtrue\Socialite;
+
+use ArrayAccess;
+use JsonSerializable;
+
+/**
+ * Class User.
+ */
+class User implements ArrayAccess, UserInterface, JsonSerializable, \Serializable
+{
+ use HasAttributes;
+
+ /**
+ * User constructor.
+ *
+ * @param array $attributes
+ */
+ public function __construct(array $attributes)
+ {
+ $this->attributes = $attributes;
+ }
+
+ /**
+ * Get the unique identifier for the user.
+ *
+ * @return string
+ */
+ public function getId()
+ {
+ return $this->getAttribute('id');
+ }
+
+ /**
+ * Get the username for the user.
+ *
+ * @return string
+ */
+ public function getUsername()
+ {
+ return $this->getAttribute('username', $this->getId());
+ }
+
+ /**
+ * Get the nickname / username for the user.
+ *
+ * @return string
+ */
+ public function getNickname()
+ {
+ return $this->getAttribute('nickname');
+ }
+
+ /**
+ * Get the full name of the user.
+ *
+ * @return string
+ */
+ public function getName()
+ {
+ return $this->getAttribute('name');
+ }
+
+ /**
+ * Get the e-mail address of the user.
+ *
+ * @return string
+ */
+ public function getEmail()
+ {
+ return $this->getAttribute('email');
+ }
+
+ /**
+ * Get the avatar / image URL for the user.
+ *
+ * @return string
+ */
+ public function getAvatar()
+ {
+ return $this->getAttribute('avatar');
+ }
+
+ /**
+ * Set the token on the user.
+ *
+ * @param \Overtrue\Socialite\AccessTokenInterface $token
+ *
+ * @return $this
+ */
+ public function setToken(AccessTokenInterface $token)
+ {
+ $this->setAttribute('token', $token->getToken());
+
+ return $this;
+ }
+
+ /**
+ * @param string $provider
+ *
+ * @return $this
+ */
+ public function setProviderName($provider)
+ {
+ $this->setAttribute('provider', $provider);
+
+ return $this;
+ }
+
+ /**
+ * @return string
+ */
+ public function getProviderName()
+ {
+ return $this->getAttribute('provider');
+ }
+
+ /**
+ * Get the authorized token.
+ *
+ * @return \Overtrue\Socialite\AccessToken
+ */
+ public function getToken()
+ {
+ return new AccessToken(['access_token' => $this->getAttribute('token')]);
+ }
+
+ /**
+ * Alias of getToken().
+ *
+ * @return \Overtrue\Socialite\AccessToken
+ */
+ public function getAccessToken()
+ {
+ return $this->getToken();
+ }
+
+ /**
+ * Get the original attributes.
+ *
+ * @return array
+ */
+ public function getOriginal()
+ {
+ return $this->getAttribute('original');
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function jsonSerialize()
+ {
+ return $this->attributes;
+ }
+
+ public function serialize()
+ {
+ return serialize($this->attributes);
+ }
+
+ /**
+ * Constructs the object.
+ *
+ * @see https://php.net/manual/en/serializable.unserialize.php
+ *
+ * @param string $serialized
+ * The string representation of the object.
+ *
+ *
+ * @since 5.1.0
+ */
+ public function unserialize($serialized)
+ {
+ $this->attributes = \unserialize($serialized) ?? [];
+ }
+}
diff --git a/addons/weliam_smartcity/vendor/overtrue/socialite/src/UserInterface.php b/addons/weliam_smartcity/vendor/overtrue/socialite/src/UserInterface.php
new file mode 100644
index 0000000..1403339
--- /dev/null
+++ b/addons/weliam_smartcity/vendor/overtrue/socialite/src/UserInterface.php
@@ -0,0 +1,53 @@
+
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace Overtrue\Socialite;
+
+/**
+ * Interface UserInterface.
+ */
+interface UserInterface
+{
+ /**
+ * Get the unique identifier for the user.
+ *
+ * @return string
+ */
+ public function getId();
+
+ /**
+ * Get the nickname / username for the user.
+ *
+ * @return string
+ */
+ public function getNickname();
+
+ /**
+ * Get the full name of the user.
+ *
+ * @return string
+ */
+ public function getName();
+
+ /**
+ * Get the e-mail address of the user.
+ *
+ * @return string
+ */
+ public function getEmail();
+
+ /**
+ * Get the avatar / image URL for the user.
+ *
+ * @return string
+ */
+ public function getAvatar();
+}
diff --git a/addons/weliam_smartcity/vendor/overtrue/socialite/src/WeChatComponentInterface.php b/addons/weliam_smartcity/vendor/overtrue/socialite/src/WeChatComponentInterface.php
new file mode 100644
index 0000000..1754521
--- /dev/null
+++ b/addons/weliam_smartcity/vendor/overtrue/socialite/src/WeChatComponentInterface.php
@@ -0,0 +1,32 @@
+
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace Overtrue\Socialite;
+
+/**
+ * Interface WeChatComponentInterface.
+ */
+interface WeChatComponentInterface
+{
+ /**
+ * Return the open-platform component app id.
+ *
+ * @return string
+ */
+ public function getAppId();
+
+ /**
+ * Return the open-platform component access token string.
+ *
+ * @return string
+ */
+ public function getToken();
+}
diff --git a/addons/weliam_smartcity/vendor/overtrue/socialite/tests/OAuthTest.php b/addons/weliam_smartcity/vendor/overtrue/socialite/tests/OAuthTest.php
new file mode 100644
index 0000000..c637606
--- /dev/null
+++ b/addons/weliam_smartcity/vendor/overtrue/socialite/tests/OAuthTest.php
@@ -0,0 +1,161 @@
+
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+use Mockery as m;
+use Overtrue\Socialite\AccessTokenInterface;
+use Overtrue\Socialite\Providers\AbstractProvider;
+use Overtrue\Socialite\User;
+use PHPUnit\Framework\TestCase;
+use Symfony\Component\HttpFoundation\Request;
+
+class OAuthTest extends TestCase
+{
+ public function tearDown()
+ {
+ m::close();
+ }
+
+ public function testRedirectGeneratesTheProperSymfonyRedirectResponse()
+ {
+ $request = Request::create('foo');
+ $request->setSession($session = m::mock('Symfony\Component\HttpFoundation\Session\SessionInterface'));
+ $session->shouldReceive('put')->once();
+ $provider = new OAuthTwoTestProviderStub($request, 'client_id', 'client_secret', 'redirect');
+ $response = $provider->redirect();
+
+ $this->assertInstanceOf('Symfony\Component\HttpFoundation\RedirectResponse', $response);
+ $this->assertSame('http://auth.url', $response->getTargetUrl());
+ }
+
+ public function testRedirectUrl()
+ {
+ $request = Request::create('foo', 'GET', ['state' => str_repeat('A', 40), 'code' => 'code']);
+ $request->setSession($session = m::mock('Symfony\Component\HttpFoundation\Session\SessionInterface'));
+
+ $provider = new OAuthTwoTestProviderStub($request, 'client_id', 'client_secret');
+ $this->assertNull($provider->getRedirectUrl());
+
+ $provider = new OAuthTwoTestProviderStub($request, 'client_id', 'client_secret', 'redirect_uri');
+ $this->assertSame('redirect_uri', $provider->getRedirectUrl());
+ $provider->setRedirectUrl('overtrue.me');
+ $this->assertSame('overtrue.me', $provider->getRedirectUrl());
+
+ $provider->withRedirectUrl('http://overtrue.me');
+ $this->assertSame('http://overtrue.me', $provider->getRedirectUrl());
+ }
+
+ public function testUserReturnsAUserInstanceForTheAuthenticatedRequest()
+ {
+ $request = Request::create('foo', 'GET', ['state' => str_repeat('A', 40), 'code' => 'code']);
+ $request->setSession($session = m::mock('Symfony\Component\HttpFoundation\Session\SessionInterface'));
+
+ $session->shouldReceive('get')->once()->with('state')->andReturn(str_repeat('A', 40));
+ $provider = new OAuthTwoTestProviderStub($request, 'client_id', 'client_secret', 'redirect_uri');
+ $provider->http = m::mock('StdClass');
+ $provider->http->shouldReceive('post')->once()->with('http://token.url', [
+ 'headers' => ['Accept' => 'application/json'], 'form_params' => ['client_id' => 'client_id', 'client_secret' => 'client_secret', 'code' => 'code', 'redirect_uri' => 'redirect_uri'],
+ ])->andReturn($response = m::mock('StdClass'));
+ $response->shouldReceive('getBody')->once()->andReturn('{"access_token":"access_token"}');
+ $user = $provider->user();
+
+ $this->assertInstanceOf('Overtrue\Socialite\User', $user);
+ $this->assertSame('foo', $user->getId());
+ }
+
+ /**
+ * @expectedException \Overtrue\Socialite\InvalidStateException
+ */
+ public function testExceptionIsThrownIfStateIsInvalid()
+ {
+ $request = Request::create('foo', 'GET', ['state' => str_repeat('B', 40), 'code' => 'code']);
+ $request->setSession($session = m::mock('Symfony\Component\HttpFoundation\Session\SessionInterface'));
+ $session->shouldReceive('get')->once()->with('state')->andReturn(str_repeat('A', 40));
+ $provider = new OAuthTwoTestProviderStub($request, 'client_id', 'client_secret', 'redirect');
+ $user = $provider->user();
+ }
+
+ /**
+ * @expectedException \Overtrue\Socialite\AuthorizeFailedException
+ * @expectedExceptionMessage Authorize Failed: {"error":"scope is invalid"}
+ */
+ public function testExceptionisThrownIfAuthorizeFailed()
+ {
+ $request = Request::create('foo', 'GET', ['state' => str_repeat('A', 40), 'code' => 'code']);
+ $request->setSession($session = m::mock('Symfony\Component\HttpFoundation\Session\SessionInterface'));
+ $session->shouldReceive('get')->once()->with('state')->andReturn(str_repeat('A', 40));
+ $provider = new OAuthTwoTestProviderStub($request, 'client_id', 'client_secret', 'redirect_uri');
+ $provider->http = m::mock('StdClass');
+ $provider->http->shouldReceive('post')->once()->with('http://token.url', [
+ 'headers' => ['Accept' => 'application/json'], 'form_params' => ['client_id' => 'client_id', 'client_secret' => 'client_secret', 'code' => 'code', 'redirect_uri' => 'redirect_uri'],
+ ])->andReturn($response = m::mock('StdClass'));
+ $response->shouldReceive('getBody')->once()->andReturn('{"error":"scope is invalid"}');
+ $user = $provider->user();
+ }
+
+ /**
+ * @expectedException \Overtrue\Socialite\InvalidStateException
+ */
+ public function testExceptionIsThrownIfStateIsNotSet()
+ {
+ $request = Request::create('foo', 'GET', ['state' => 'state', 'code' => 'code']);
+ $request->setSession($session = m::mock('Symfony\Component\HttpFoundation\Session\SessionInterface'));
+ $session->shouldReceive('get')->once()->with('state');
+ $provider = new OAuthTwoTestProviderStub($request, 'client_id', 'client_secret', 'redirect');
+ $user = $provider->user();
+ }
+
+ public function testDriverName()
+ {
+ $request = Request::create('foo', 'GET', ['state' => 'state', 'code' => 'code']);
+ $provider = new OAuthTwoTestProviderStub($request, 'client_id', 'client_secret', 'redirect');
+
+ $this->assertSame('OAuthTwoTest', $provider->getName());
+ }
+}
+
+class OAuthTwoTestProviderStub extends AbstractProvider
+{
+ public $http;
+
+ protected function getAuthUrl($state)
+ {
+ return 'http://auth.url';
+ }
+
+ protected function getTokenUrl()
+ {
+ return 'http://token.url';
+ }
+
+ protected function getUserByToken(AccessTokenInterface $token)
+ {
+ return ['id' => 'foo'];
+ }
+
+ protected function mapUserToObject(array $user)
+ {
+ return new User(['id' => $user['id']]);
+ }
+
+ /**
+ * Get a fresh instance of the Guzzle HTTP client.
+ *
+ * @return \GuzzleHttp\Client
+ */
+ protected function getHttpClient()
+ {
+ if ($this->http) {
+ return $this->http;
+ }
+
+ return $this->http = m::mock('StdClass');
+ }
+}
diff --git a/addons/weliam_smartcity/vendor/overtrue/socialite/tests/Providers/WeWorkProviderTest.php b/addons/weliam_smartcity/vendor/overtrue/socialite/tests/Providers/WeWorkProviderTest.php
new file mode 100644
index 0000000..88377a7
--- /dev/null
+++ b/addons/weliam_smartcity/vendor/overtrue/socialite/tests/Providers/WeWorkProviderTest.php
@@ -0,0 +1,48 @@
+
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+use Overtrue\Socialite\Providers\WeWorkProvider;
+use PHPUnit\Framework\TestCase;
+use Symfony\Component\HttpFoundation\Request;
+
+class WeWorkProviderTest extends TestCase
+{
+ public function testQrConnect()
+ {
+ $response = (new WeWorkProvider(Request::create('foo'), 'ww100000a5f2191', 'client_secret', 'http://www.oa.com'))
+ ->setAgentId('1000000')
+ ->stateless()
+ ->redirect();
+
+ $this->assertSame('https://open.work.weixin.qq.com/wwopen/sso/qrConnect?appid=ww100000a5f2191&agentid=1000000&redirect_uri=http%3A%2F%2Fwww.oa.com', $response->getTargetUrl());
+ }
+
+ public function testOAuthWithAgentId()
+ {
+ $response = (new WeWorkProvider(Request::create('foo'), 'CORPID', 'client_secret', 'REDIRECT_URI'))
+ ->scopes(['snsapi_base'])
+ ->setAgentId('1000000')
+ ->stateless()
+ ->redirect();
+
+ $this->assertSame('https://open.weixin.qq.com/connect/oauth2/authorize?appid=CORPID&redirect_uri=REDIRECT_URI&response_type=code&scope=snsapi_base&agentid=1000000#wechat_redirect', $response->getTargetUrl());
+ }
+
+ public function testOAuthWithoutAgentId()
+ {
+ $response = (new WeWorkProvider(Request::create('foo'), 'CORPID', 'client_secret', 'REDIRECT_URI'))
+ ->scopes(['snsapi_base'])
+ ->stateless()
+ ->redirect();
+
+ $this->assertSame('https://open.weixin.qq.com/connect/oauth2/authorize?appid=CORPID&redirect_uri=REDIRECT_URI&response_type=code&scope=snsapi_base#wechat_redirect', $response->getTargetUrl());
+ }
+}
diff --git a/addons/weliam_smartcity/vendor/overtrue/socialite/tests/UserTest.php b/addons/weliam_smartcity/vendor/overtrue/socialite/tests/UserTest.php
new file mode 100644
index 0000000..dd42010
--- /dev/null
+++ b/addons/weliam_smartcity/vendor/overtrue/socialite/tests/UserTest.php
@@ -0,0 +1,24 @@
+
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+use Overtrue\Socialite\AccessToken;
+use Overtrue\Socialite\User;
+use PHPUnit\Framework\TestCase;
+
+class UserTest extends TestCase
+{
+ public function testJsonserialize()
+ {
+ $this->assertSame('[]', json_encode(new User([])));
+
+ $this->assertSame('{"token":"mock-token"}', json_encode(new User(['token' => new AccessToken(['access_token' => 'mock-token'])])));
+ }
+}
diff --git a/addons/weliam_smartcity/vendor/overtrue/socialite/tests/WechatProviderTest.php b/addons/weliam_smartcity/vendor/overtrue/socialite/tests/WechatProviderTest.php
new file mode 100644
index 0000000..7576b02
--- /dev/null
+++ b/addons/weliam_smartcity/vendor/overtrue/socialite/tests/WechatProviderTest.php
@@ -0,0 +1,109 @@
+
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+use Overtrue\Socialite\Providers\WeChatProvider as RealWeChatProvider;
+use PHPUnit\Framework\TestCase;
+use Symfony\Component\HttpFoundation\Request;
+
+class WechatProviderTest extends TestCase
+{
+ public function testWeChatProviderHasCorrectlyRedirectResponse()
+ {
+ $response = (new WeChatProvider(Request::create('foo'), 'client_id', 'client_secret', 'http://localhost/socialite/callback.php'))->redirect();
+
+ $this->assertInstanceOf('Symfony\Component\HttpFoundation\RedirectResponse', $response);
+ $this->assertStringStartsWith('https://open.weixin.qq.com/connect/qrconnect', $response->getTargetUrl());
+ $this->assertRegExp('/redirect_uri=http%3A%2F%2Flocalhost%2Fsocialite%2Fcallback.php/', $response->getTargetUrl());
+ }
+
+ public function testWeChatProviderTokenUrlAndRequestFields()
+ {
+ $provider = new WeChatProvider(Request::create('foo'), 'client_id', 'client_secret', 'http://localhost/socialite/callback.php');
+
+ $this->assertSame('https://api.weixin.qq.com/sns/oauth2/access_token', $provider->tokenUrl());
+ $this->assertSame([
+ 'appid' => 'client_id',
+ 'secret' => 'client_secret',
+ 'code' => 'iloveyou',
+ 'grant_type' => 'authorization_code',
+ ], $provider->tokenFields('iloveyou'));
+
+ $this->assertSame([
+ 'appid' => 'client_id',
+ 'redirect_uri' => 'http://localhost/socialite/callback.php',
+ 'response_type' => 'code',
+ 'scope' => 'snsapi_login',
+ 'state' => 'wechat-state',
+ 'connect_redirect' => 1,
+ ], $provider->codeFields('wechat-state'));
+ }
+
+ public function testOpenPlatformComponent()
+ {
+ $provider = new WeChatProvider(Request::create('foo'), 'client_id', null, 'redirect-url');
+ $provider->component(new WeChatComponent());
+ $this->assertSame([
+ 'appid' => 'client_id',
+ 'redirect_uri' => 'redirect-url',
+ 'response_type' => 'code',
+ 'scope' => 'snsapi_base',
+ 'state' => 'state',
+ 'connect_redirect' => 1,
+ 'component_appid' => 'component-app-id',
+ ], $provider->codeFields('state'));
+
+ $this->assertSame([
+ 'appid' => 'client_id',
+ 'component_appid' => 'component-app-id',
+ 'component_access_token' => 'token',
+ 'code' => 'simcode',
+ 'grant_type' => 'authorization_code',
+ ], $provider->tokenFields('simcode'));
+
+ $this->assertSame('https://api.weixin.qq.com/sns/oauth2/component/access_token', $provider->tokenUrl());
+ }
+}
+
+trait ProviderTrait
+{
+ public function tokenUrl()
+ {
+ return $this->getTokenUrl();
+ }
+
+ public function tokenFields($code)
+ {
+ return $this->getTokenFields($code);
+ }
+
+ public function codeFields($state = null)
+ {
+ return $this->getCodeFields($state);
+ }
+}
+
+class WeChatProvider extends RealWeChatProvider
+{
+ use ProviderTrait;
+}
+
+class WeChatComponent implements \Overtrue\Socialite\WeChatComponentInterface
+{
+ public function getAppId()
+ {
+ return 'component-app-id';
+ }
+
+ public function getToken()
+ {
+ return 'token';
+ }
+}
diff --git a/addons/weliam_smartcity/vendor/overtrue/wechat/src/BasicService/Application.php b/addons/weliam_smartcity/vendor/overtrue/wechat/src/BasicService/Application.php
new file mode 100644
index 0000000..e4b1e8a
--- /dev/null
+++ b/addons/weliam_smartcity/vendor/overtrue/wechat/src/BasicService/Application.php
@@ -0,0 +1,39 @@
+
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace EasyWeChat\BasicService;
+
+use EasyWeChat\Kernel\ServiceContainer;
+
+/**
+ * Class Application.
+ *
+ * @author overtrue
+ *
+ * @property \EasyWeChat\BasicService\Jssdk\Client $jssdk
+ * @property \EasyWeChat\BasicService\Media\Client $media
+ * @property \EasyWeChat\BasicService\QrCode\Client $qrcode
+ * @property \EasyWeChat\BasicService\Url\Client $url
+ * @property \EasyWeChat\BasicService\ContentSecurity\Client $content_security
+ */
+class Application extends ServiceContainer
+{
+ /**
+ * @var array
+ */
+ protected $providers = [
+ Jssdk\ServiceProvider::class,
+ QrCode\ServiceProvider::class,
+ Media\ServiceProvider::class,
+ Url\ServiceProvider::class,
+ ContentSecurity\ServiceProvider::class,
+ ];
+}
diff --git a/addons/weliam_smartcity/vendor/overtrue/wechat/src/BasicService/ContentSecurity/Client.php b/addons/weliam_smartcity/vendor/overtrue/wechat/src/BasicService/ContentSecurity/Client.php
new file mode 100644
index 0000000..7bc11bd
--- /dev/null
+++ b/addons/weliam_smartcity/vendor/overtrue/wechat/src/BasicService/ContentSecurity/Client.php
@@ -0,0 +1,123 @@
+
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace EasyWeChat\BasicService\ContentSecurity;
+
+use EasyWeChat\Kernel\BaseClient;
+use EasyWeChat\Kernel\Exceptions\InvalidArgumentException;
+
+/**
+ * Class Client.
+ *
+ * @author tianyong90 <412039588@qq.com>
+ */
+class Client extends BaseClient
+{
+ /**
+ * @var string
+ */
+ protected $baseUri = 'https://api.weixin.qq.com/wxa/';
+
+ /**
+ * Text content security check.
+ *
+ * @param string $text
+ *
+ * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string
+ *
+ * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
+ * @throws \GuzzleHttp\Exception\GuzzleException
+ */
+ public function checkText(string $text)
+ {
+ $params = [
+ 'content' => $text,
+ ];
+
+ return $this->httpPostJson('msg_sec_check', $params);
+ }
+
+ /**
+ * Image security check.
+ *
+ * @param string $path
+ *
+ * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string
+ *
+ * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
+ * @throws \GuzzleHttp\Exception\GuzzleException
+ */
+ public function checkImage(string $path)
+ {
+ return $this->httpUpload('img_sec_check', ['media' => $path]);
+ }
+
+ /**
+ * Media security check.
+ *
+ * @param string $mediaUrl
+ * @param int $mediaType
+ *
+ * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string
+ *
+ * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
+ * @throws \GuzzleHttp\Exception\GuzzleException
+ * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
+ */
+ public function checkMediaAsync(string $mediaUrl, int $mediaType)
+ {
+ /*
+ * 1:音频;2:图片
+ */
+ $mediaTypes = [1, 2];
+
+ if (!in_array($mediaType, $mediaTypes, true)) {
+ throw new InvalidArgumentException('media type must be 1 or 2');
+ }
+
+ $params = [
+ 'media_url' => $mediaUrl,
+ 'media_type' => $mediaType,
+ ];
+
+ return $this->httpPostJson('media_check_async', $params);
+ }
+
+ /**
+ * Image security check async.
+ *
+ * @param string $mediaUrl
+ *
+ * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string
+ *
+ * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
+ * @throws \GuzzleHttp\Exception\GuzzleException
+ */
+ public function checkImageAsync(string $mediaUrl)
+ {
+ return $this->checkMediaAsync($mediaUrl, 2);
+ }
+
+ /**
+ * Audio security check async.
+ *
+ * @param string $mediaUrl
+ *
+ * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string
+ *
+ * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
+ * @throws \GuzzleHttp\Exception\GuzzleException
+ */
+ public function checkAudioAsync(string $mediaUrl)
+ {
+ return $this->checkMediaAsync($mediaUrl, 1);
+ }
+}
diff --git a/addons/weliam_smartcity/vendor/overtrue/wechat/src/BasicService/ContentSecurity/ServiceProvider.php b/addons/weliam_smartcity/vendor/overtrue/wechat/src/BasicService/ContentSecurity/ServiceProvider.php
new file mode 100644
index 0000000..3645de9
--- /dev/null
+++ b/addons/weliam_smartcity/vendor/overtrue/wechat/src/BasicService/ContentSecurity/ServiceProvider.php
@@ -0,0 +1,31 @@
+
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace EasyWeChat\BasicService\ContentSecurity;
+
+use Pimple\Container;
+use Pimple\ServiceProviderInterface;
+
+/**
+ * Class ServiceProvider.
+ */
+class ServiceProvider implements ServiceProviderInterface
+{
+ /**
+ * {@inheritdoc}.
+ */
+ public function register(Container $app)
+ {
+ $app['content_security'] = function ($app) {
+ return new Client($app);
+ };
+ }
+}
diff --git a/addons/weliam_smartcity/vendor/overtrue/wechat/src/BasicService/Jssdk/Client.php b/addons/weliam_smartcity/vendor/overtrue/wechat/src/BasicService/Jssdk/Client.php
new file mode 100644
index 0000000..33367fc
--- /dev/null
+++ b/addons/weliam_smartcity/vendor/overtrue/wechat/src/BasicService/Jssdk/Client.php
@@ -0,0 +1,207 @@
+
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace EasyWeChat\BasicService\Jssdk;
+
+use EasyWeChat\Kernel\BaseClient;
+use EasyWeChat\Kernel\Exceptions\RuntimeException;
+use EasyWeChat\Kernel\Support;
+use EasyWeChat\Kernel\Traits\InteractsWithCache;
+
+/**
+ * Class Client.
+ *
+ * @author overtrue
+ */
+class Client extends BaseClient
+{
+ use InteractsWithCache;
+
+ /**
+ * @var string
+ */
+ protected $ticketEndpoint = 'https://api.weixin.qq.com/cgi-bin/ticket/getticket';
+
+ /**
+ * Current URI.
+ *
+ * @var string
+ */
+ protected $url;
+
+ /**
+ * Get config json for jsapi.
+ *
+ * @param array $jsApiList
+ * @param bool $debug
+ * @param bool $beta
+ * @param bool $json
+ *
+ * @return array|string
+ *
+ * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
+ * @throws \Psr\SimpleCache\InvalidArgumentException
+ * @throws \EasyWeChat\Kernel\Exceptions\RuntimeException
+ */
+ public function buildConfig(array $jsApiList, bool $debug = false, bool $beta = false, bool $json = true)
+ {
+ $config = array_merge(compact('debug', 'beta', 'jsApiList'), $this->configSignature());
+
+ return $json ? json_encode($config) : $config;
+ }
+
+ /**
+ * Return jsapi config as a PHP array.
+ *
+ * @param array $apis
+ * @param bool $debug
+ * @param bool $beta
+ *
+ * @return array
+ *
+ * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
+ * @throws \Psr\SimpleCache\InvalidArgumentException
+ * @throws \EasyWeChat\Kernel\Exceptions\RuntimeException
+ */
+ public function getConfigArray(array $apis, bool $debug = false, bool $beta = false)
+ {
+ return $this->buildConfig($apis, $debug, $beta, false);
+ }
+
+ /**
+ * Get js ticket.
+ *
+ * @param bool $refresh
+ * @param string $type
+ *
+ * @return array
+ *
+ * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
+ * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
+ * @throws \EasyWeChat\Kernel\Exceptions\RuntimeException
+ * @throws \GuzzleHttp\Exception\GuzzleException
+ * @throws \Psr\SimpleCache\InvalidArgumentException
+ */
+ public function getTicket(bool $refresh = false, string $type = 'jsapi'): array
+ {
+ $cacheKey = sprintf('easywechat.basic_service.jssdk.ticket.%s.%s', $type, $this->getAppId());
+
+ if (!$refresh && $this->getCache()->has($cacheKey)) {
+ return $this->getCache()->get($cacheKey);
+ }
+
+ /** @var array $result */
+ $result = $this->castResponseToType(
+ $this->requestRaw($this->ticketEndpoint, 'GET', ['query' => ['type' => $type]]),
+ 'array'
+ );
+
+ $this->getCache()->set($cacheKey, $result, $result['expires_in'] - 500);
+
+ if (!$this->getCache()->has($cacheKey)) {
+ throw new RuntimeException('Failed to cache jssdk ticket.');
+ }
+
+ return $result;
+ }
+
+ /**
+ * Build signature.
+ *
+ * @param string|null $url
+ * @param string|null $nonce
+ * @param int|null $timestamp
+ *
+ * @return array
+ *
+ * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
+ * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
+ * @throws \EasyWeChat\Kernel\Exceptions\RuntimeException
+ * @throws \Psr\SimpleCache\InvalidArgumentException
+ */
+ protected function configSignature(string $url = null, string $nonce = null, $timestamp = null): array
+ {
+ $url = $url ?: $this->getUrl();
+ $nonce = $nonce ?: Support\Str::quickRandom(10);
+ $timestamp = $timestamp ?: time();
+
+ return [
+ 'appId' => $this->getAppId(),
+ 'nonceStr' => $nonce,
+ 'timestamp' => $timestamp,
+ 'url' => $url,
+ 'signature' => $this->getTicketSignature($this->getTicket()['ticket'], $nonce, $timestamp, $url),
+ ];
+ }
+
+ /**
+ * Sign the params.
+ *
+ * @param string $ticket
+ * @param string $nonce
+ * @param int $timestamp
+ * @param string $url
+ *
+ * @return string
+ */
+ public function getTicketSignature($ticket, $nonce, $timestamp, $url): string
+ {
+ return sha1(sprintf('jsapi_ticket=%s&noncestr=%s×tamp=%s&url=%s', $ticket, $nonce, $timestamp, $url));
+ }
+
+ /**
+ * @return string
+ */
+ public function dictionaryOrderSignature()
+ {
+ $params = func_get_args();
+
+ sort($params, SORT_STRING);
+
+ return sha1(implode('', $params));
+ }
+
+ /**
+ * Set current url.
+ *
+ * @param string $url
+ *
+ * @return $this
+ */
+ public function setUrl(string $url)
+ {
+ $this->url = $url;
+
+ return $this;
+ }
+
+ /**
+ * Get current url.
+ *
+ * @return string
+ */
+ public function getUrl(): string
+ {
+ if ($this->url) {
+ return $this->url;
+ }
+
+ return Support\current_url();
+ }
+
+ /**
+ * @return string
+ */
+ protected function getAppId()
+ {
+ return $this->app['config']->get('app_id');
+ }
+}
diff --git a/addons/weliam_smartcity/vendor/overtrue/wechat/src/BasicService/Jssdk/ServiceProvider.php b/addons/weliam_smartcity/vendor/overtrue/wechat/src/BasicService/Jssdk/ServiceProvider.php
new file mode 100644
index 0000000..5581a1e
--- /dev/null
+++ b/addons/weliam_smartcity/vendor/overtrue/wechat/src/BasicService/Jssdk/ServiceProvider.php
@@ -0,0 +1,33 @@
+
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace EasyWeChat\BasicService\Jssdk;
+
+use Pimple\Container;
+use Pimple\ServiceProviderInterface;
+
+/**
+ * Class ServiceProvider.
+ *
+ * @author overtrue
+ */
+class ServiceProvider implements ServiceProviderInterface
+{
+ /**
+ * {@inheritdoc}.
+ */
+ public function register(Container $app)
+ {
+ $app['jssdk'] = function ($app) {
+ return new Client($app);
+ };
+ }
+}
diff --git a/addons/weliam_smartcity/vendor/overtrue/wechat/src/BasicService/Media/Client.php b/addons/weliam_smartcity/vendor/overtrue/wechat/src/BasicService/Media/Client.php
new file mode 100644
index 0000000..13f1afa
--- /dev/null
+++ b/addons/weliam_smartcity/vendor/overtrue/wechat/src/BasicService/Media/Client.php
@@ -0,0 +1,212 @@
+
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace EasyWeChat\BasicService\Media;
+
+use EasyWeChat\Kernel\BaseClient;
+use EasyWeChat\Kernel\Exceptions\InvalidArgumentException;
+use EasyWeChat\Kernel\Http\StreamResponse;
+
+/**
+ * Class Client.
+ *
+ * @author overtrue
+ */
+class Client extends BaseClient
+{
+ /**
+ * @var string
+ */
+ protected $baseUri = 'https://api.weixin.qq.com/cgi-bin/';
+
+ /**
+ * Allow media type.
+ *
+ * @var array
+ */
+ protected $allowTypes = ['image', 'voice', 'video', 'thumb'];
+
+ /**
+ * Upload image.
+ *
+ * @param string $path
+ *
+ * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string
+ *
+ * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
+ * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
+ * @throws \GuzzleHttp\Exception\GuzzleException
+ */
+ public function uploadImage($path)
+ {
+ return $this->upload('image', $path);
+ }
+
+ /**
+ * Upload video.
+ *
+ * @param string $path
+ *
+ * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string
+ *
+ * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
+ * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
+ * @throws \GuzzleHttp\Exception\GuzzleException
+ */
+ public function uploadVideo($path)
+ {
+ return $this->upload('video', $path);
+ }
+
+ /**
+ * @param string $path
+ *
+ * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string
+ *
+ * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
+ * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
+ * @throws \GuzzleHttp\Exception\GuzzleException
+ */
+ public function uploadVoice($path)
+ {
+ return $this->upload('voice', $path);
+ }
+
+ /**
+ * @param string $path
+ *
+ * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string
+ *
+ * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
+ * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
+ * @throws \GuzzleHttp\Exception\GuzzleException
+ */
+ public function uploadThumb($path)
+ {
+ return $this->upload('thumb', $path);
+ }
+
+ /**
+ * Upload temporary material.
+ *
+ * @param string $type
+ * @param string $path
+ *
+ * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string
+ *
+ * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
+ * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
+ * @throws \GuzzleHttp\Exception\GuzzleException
+ */
+ public function upload(string $type, string $path)
+ {
+ if (!file_exists($path) || !is_readable($path)) {
+ throw new InvalidArgumentException(sprintf("File does not exist, or the file is unreadable: '%s'", $path));
+ }
+
+ if (!in_array($type, $this->allowTypes, true)) {
+ throw new InvalidArgumentException(sprintf("Unsupported media type: '%s'", $type));
+ }
+
+ return $this->httpUpload('media/upload', ['media' => $path], ['type' => $type]);
+ }
+
+ /**
+ * @param string $path
+ * @param string $title
+ * @param string $description
+ *
+ * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string
+ *
+ * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
+ * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
+ * @throws \GuzzleHttp\Exception\GuzzleException
+ */
+ public function uploadVideoForBroadcasting(string $path, string $title, string $description)
+ {
+ $response = $this->uploadVideo($path);
+ /** @var array $arrayResponse */
+ $arrayResponse = $this->detectAndCastResponseToType($response, 'array');
+
+ if (!empty($arrayResponse['media_id'])) {
+ return $this->createVideoForBroadcasting($arrayResponse['media_id'], $title, $description);
+ }
+
+ return $response;
+ }
+
+ /**
+ * @param string $mediaId
+ * @param string $title
+ * @param string $description
+ *
+ * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string
+ *
+ * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
+ * @throws \GuzzleHttp\Exception\GuzzleException
+ */
+ public function createVideoForBroadcasting(string $mediaId, string $title, string $description)
+ {
+ return $this->httpPostJson('media/uploadvideo', [
+ 'media_id' => $mediaId,
+ 'title' => $title,
+ 'description' => $description,
+ ]);
+ }
+
+ /**
+ * Fetch item from WeChat server.
+ *
+ * @param string $mediaId
+ *
+ * @return \EasyWeChat\Kernel\Http\StreamResponse|\Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string
+ *
+ * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
+ * @throws \GuzzleHttp\Exception\GuzzleException
+ */
+ public function get(string $mediaId)
+ {
+ $response = $this->requestRaw('media/get', 'GET', [
+ 'query' => [
+ 'media_id' => $mediaId,
+ ],
+ ]);
+
+ if (false !== stripos($response->getHeaderLine('Content-disposition'), 'attachment')) {
+ return StreamResponse::buildFromPsrResponse($response);
+ }
+
+ return $this->castResponseToType($response, $this->app['config']->get('response_type'));
+ }
+
+ /**
+ * @param string $mediaId
+ *
+ * @return array|\EasyWeChat\Kernel\Http\Response|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string
+ *
+ * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
+ * @throws \GuzzleHttp\Exception\GuzzleException
+ */
+ public function getJssdkMedia(string $mediaId)
+ {
+ $response = $this->requestRaw('media/get/jssdk', 'GET', [
+ 'query' => [
+ 'media_id' => $mediaId,
+ ],
+ ]);
+
+ if (false !== stripos($response->getHeaderLine('Content-disposition'), 'attachment')) {
+ return StreamResponse::buildFromPsrResponse($response);
+ }
+
+ return $this->castResponseToType($response, $this->app['config']->get('response_type'));
+ }
+}
diff --git a/addons/weliam_smartcity/vendor/overtrue/wechat/src/BasicService/Media/ServiceProvider.php b/addons/weliam_smartcity/vendor/overtrue/wechat/src/BasicService/Media/ServiceProvider.php
new file mode 100644
index 0000000..45de142
--- /dev/null
+++ b/addons/weliam_smartcity/vendor/overtrue/wechat/src/BasicService/Media/ServiceProvider.php
@@ -0,0 +1,44 @@
+
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+/**
+ * ServiceProvider.php.
+ *
+ * This file is part of the wechat.
+ *
+ * (c) overtrue
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace EasyWeChat\BasicService\Media;
+
+use Pimple\Container;
+use Pimple\ServiceProviderInterface;
+
+/**
+ * Class ServiceProvider.
+ *
+ * @author overtrue
+ */
+class ServiceProvider implements ServiceProviderInterface
+{
+ /**
+ * {@inheritdoc}.
+ */
+ public function register(Container $app)
+ {
+ $app['media'] = function ($app) {
+ return new Client($app);
+ };
+ }
+}
diff --git a/addons/weliam_smartcity/vendor/overtrue/wechat/src/BasicService/QrCode/Client.php b/addons/weliam_smartcity/vendor/overtrue/wechat/src/BasicService/QrCode/Client.php
new file mode 100644
index 0000000..ac606a3
--- /dev/null
+++ b/addons/weliam_smartcity/vendor/overtrue/wechat/src/BasicService/QrCode/Client.php
@@ -0,0 +1,120 @@
+
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace EasyWeChat\BasicService\QrCode;
+
+use EasyWeChat\Kernel\BaseClient;
+
+/**
+ * Class Client.
+ *
+ * @author overtrue
+ */
+class Client extends BaseClient
+{
+ /**
+ * @var string
+ */
+ protected $baseUri = 'https://api.weixin.qq.com/cgi-bin/';
+
+ const DAY = 86400;
+ const SCENE_MAX_VALUE = 100000;
+ const SCENE_QR_CARD = 'QR_CARD';
+ const SCENE_QR_TEMPORARY = 'QR_SCENE';
+ const SCENE_QR_TEMPORARY_STR = 'QR_STR_SCENE';
+ const SCENE_QR_FOREVER = 'QR_LIMIT_SCENE';
+ const SCENE_QR_FOREVER_STR = 'QR_LIMIT_STR_SCENE';
+
+ /**
+ * Create forever QR code.
+ *
+ * @param string|int $sceneValue
+ *
+ * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string
+ */
+ public function forever($sceneValue)
+ {
+ if (is_int($sceneValue) && $sceneValue > 0 && $sceneValue < self::SCENE_MAX_VALUE) {
+ $type = self::SCENE_QR_FOREVER;
+ $sceneKey = 'scene_id';
+ } else {
+ $type = self::SCENE_QR_FOREVER_STR;
+ $sceneKey = 'scene_str';
+ }
+ $scene = [$sceneKey => $sceneValue];
+
+ return $this->create($type, $scene, false);
+ }
+
+ /**
+ * Create temporary QR code.
+ *
+ * @param string|int $sceneValue
+ * @param int|null $expireSeconds
+ *
+ * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string
+ */
+ public function temporary($sceneValue, $expireSeconds = null)
+ {
+ if (is_int($sceneValue) && $sceneValue > 0) {
+ $type = self::SCENE_QR_TEMPORARY;
+ $sceneKey = 'scene_id';
+ } else {
+ $type = self::SCENE_QR_TEMPORARY_STR;
+ $sceneKey = 'scene_str';
+ }
+ $scene = [$sceneKey => $sceneValue];
+
+ return $this->create($type, $scene, true, $expireSeconds);
+ }
+
+ /**
+ * Return url for ticket.
+ * Detail: https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1443433542 .
+ *
+ * @param string $ticket
+ *
+ * @return string
+ */
+ public function url($ticket)
+ {
+ return sprintf('https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket=%s', urlencode($ticket));
+ }
+
+ /**
+ * Create a QrCode.
+ *
+ * @param string $actionName
+ * @param array $actionInfo
+ * @param bool $temporary
+ * @param int $expireSeconds
+ *
+ * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string
+ *
+ * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
+ * @throws \GuzzleHttp\Exception\GuzzleException
+ */
+ protected function create($actionName, $actionInfo, $temporary = true, $expireSeconds = null)
+ {
+ null !== $expireSeconds || $expireSeconds = 7 * self::DAY;
+
+ $params = [
+ 'action_name' => $actionName,
+ 'action_info' => ['scene' => $actionInfo],
+ ];
+
+ if ($temporary) {
+ $params['expire_seconds'] = min($expireSeconds, 30 * self::DAY);
+ }
+
+ return $this->httpPostJson('qrcode/create', $params);
+ }
+}
diff --git a/addons/weliam_smartcity/vendor/overtrue/wechat/src/BasicService/QrCode/ServiceProvider.php b/addons/weliam_smartcity/vendor/overtrue/wechat/src/BasicService/QrCode/ServiceProvider.php
new file mode 100644
index 0000000..1638c66
--- /dev/null
+++ b/addons/weliam_smartcity/vendor/overtrue/wechat/src/BasicService/QrCode/ServiceProvider.php
@@ -0,0 +1,31 @@
+
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace EasyWeChat\BasicService\QrCode;
+
+use Pimple\Container;
+use Pimple\ServiceProviderInterface;
+
+/**
+ * Class ServiceProvider.
+ */
+class ServiceProvider implements ServiceProviderInterface
+{
+ /**
+ * {@inheritdoc}.
+ */
+ public function register(Container $app)
+ {
+ $app['qrcode'] = function ($app) {
+ return new Client($app);
+ };
+ }
+}
diff --git a/addons/weliam_smartcity/vendor/overtrue/wechat/src/BasicService/Url/Client.php b/addons/weliam_smartcity/vendor/overtrue/wechat/src/BasicService/Url/Client.php
new file mode 100644
index 0000000..19a5fb1
--- /dev/null
+++ b/addons/weliam_smartcity/vendor/overtrue/wechat/src/BasicService/Url/Client.php
@@ -0,0 +1,47 @@
+
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace EasyWeChat\BasicService\Url;
+
+use EasyWeChat\Kernel\BaseClient;
+
+/**
+ * Class Client.
+ *
+ * @author overtrue
+ */
+class Client extends BaseClient
+{
+ /**
+ * @var string
+ */
+ protected $baseUri = 'https://api.weixin.qq.com/';
+
+ /**
+ * Shorten the url.
+ *
+ * @param string $url
+ *
+ * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string
+ *
+ * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
+ * @throws \GuzzleHttp\Exception\GuzzleException
+ */
+ public function shorten(string $url)
+ {
+ $params = [
+ 'action' => 'long2short',
+ 'long_url' => $url,
+ ];
+
+ return $this->httpPostJson('cgi-bin/shorturl', $params);
+ }
+}
diff --git a/addons/weliam_smartcity/vendor/overtrue/wechat/src/BasicService/Url/ServiceProvider.php b/addons/weliam_smartcity/vendor/overtrue/wechat/src/BasicService/Url/ServiceProvider.php
new file mode 100644
index 0000000..6740bb8
--- /dev/null
+++ b/addons/weliam_smartcity/vendor/overtrue/wechat/src/BasicService/Url/ServiceProvider.php
@@ -0,0 +1,31 @@
+
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace EasyWeChat\BasicService\Url;
+
+use Pimple\Container;
+use Pimple\ServiceProviderInterface;
+
+/**
+ * Class ServiceProvider.
+ */
+class ServiceProvider implements ServiceProviderInterface
+{
+ /**
+ * {@inheritdoc}.
+ */
+ public function register(Container $app)
+ {
+ $app['url'] = function ($app) {
+ return new Client($app);
+ };
+ }
+}
diff --git a/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/AccessToken.php b/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/AccessToken.php
new file mode 100644
index 0000000..77f23c0
--- /dev/null
+++ b/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/AccessToken.php
@@ -0,0 +1,282 @@
+
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace EasyWeChat\Kernel;
+
+use EasyWeChat\Kernel\Contracts\AccessTokenInterface;
+use EasyWeChat\Kernel\Exceptions\HttpException;
+use EasyWeChat\Kernel\Exceptions\InvalidArgumentException;
+use EasyWeChat\Kernel\Exceptions\RuntimeException;
+use EasyWeChat\Kernel\Traits\HasHttpRequests;
+use EasyWeChat\Kernel\Traits\InteractsWithCache;
+use Psr\Http\Message\RequestInterface;
+use Psr\Http\Message\ResponseInterface;
+
+/**
+ * Class AccessToken.
+ *
+ * @author overtrue
+ */
+abstract class AccessToken implements AccessTokenInterface
+{
+ use HasHttpRequests;
+ use InteractsWithCache;
+
+ /**
+ * @var \EasyWeChat\Kernel\ServiceContainer
+ */
+ protected $app;
+
+ /**
+ * @var string
+ */
+ protected $requestMethod = 'GET';
+
+ /**
+ * @var string
+ */
+ protected $endpointToGetToken;
+
+ /**
+ * @var string
+ */
+ protected $queryName;
+
+ /**
+ * @var array
+ */
+ protected $token;
+
+ /**
+ * @var int
+ */
+ protected $safeSeconds = 500;
+
+ /**
+ * @var string
+ */
+ protected $tokenKey = 'access_token';
+
+ /**
+ * @var string
+ */
+ protected $cachePrefix = 'easywechat.kernel.access_token.';
+
+ /**
+ * AccessToken constructor.
+ *
+ * @param \EasyWeChat\Kernel\ServiceContainer $app
+ */
+ public function __construct(ServiceContainer $app)
+ {
+ $this->app = $app;
+ }
+
+ /**
+ * @return array
+ *
+ * @throws \EasyWeChat\Kernel\Exceptions\HttpException
+ * @throws \Psr\SimpleCache\InvalidArgumentException
+ * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
+ * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
+ * @throws \EasyWeChat\Kernel\Exceptions\RuntimeException
+ */
+ public function getRefreshedToken(): array
+ {
+ return $this->getToken(true);
+ }
+
+ /**
+ * @param bool $refresh
+ *
+ * @return array
+ *
+ * @throws \EasyWeChat\Kernel\Exceptions\HttpException
+ * @throws \Psr\SimpleCache\InvalidArgumentException
+ * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
+ * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
+ * @throws \EasyWeChat\Kernel\Exceptions\RuntimeException
+ */
+ public function getToken(bool $refresh = false): array
+ {
+ $cacheKey = $this->getCacheKey();
+ $cache = $this->getCache();
+
+ if (!$refresh && $cache->has($cacheKey)) {
+ return $cache->get($cacheKey);
+ }
+
+ /** @var array $token */
+ $token = $this->requestToken($this->getCredentials(), true);
+
+ $this->setToken($token[$this->tokenKey], $token['expires_in'] ?? 7200);
+
+ $this->app->events->dispatch(new Events\AccessTokenRefreshed($this));
+
+ return $token;
+ }
+
+ /**
+ * @param string $token
+ * @param int $lifetime
+ *
+ * @return \EasyWeChat\Kernel\Contracts\AccessTokenInterface
+ *
+ * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
+ * @throws \EasyWeChat\Kernel\Exceptions\RuntimeException
+ * @throws \Psr\SimpleCache\InvalidArgumentException
+ */
+ public function setToken(string $token, int $lifetime = 7200): AccessTokenInterface
+ {
+ $this->getCache()->set($this->getCacheKey(), [
+ $this->tokenKey => $token,
+ 'expires_in' => $lifetime,
+ ], $lifetime - $this->safeSeconds);
+
+ if (!$this->getCache()->has($this->getCacheKey())) {
+ throw new RuntimeException('Failed to cache access token.');
+ }
+
+ return $this;
+ }
+
+ /**
+ * @return \EasyWeChat\Kernel\Contracts\AccessTokenInterface
+ *
+ * @throws \EasyWeChat\Kernel\Exceptions\HttpException
+ * @throws \Psr\SimpleCache\InvalidArgumentException
+ * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
+ * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
+ * @throws \EasyWeChat\Kernel\Exceptions\RuntimeException
+ */
+ public function refresh(): AccessTokenInterface
+ {
+ $this->getToken(true);
+
+ return $this;
+ }
+
+ /**
+ * @param array $credentials
+ * @param bool $toArray
+ *
+ * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string
+ *
+ * @throws \EasyWeChat\Kernel\Exceptions\HttpException
+ * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
+ * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
+ */
+ public function requestToken(array $credentials, $toArray = false)
+ {
+ $response = $this->sendRequest($credentials);
+ $result = json_decode($response->getBody()->getContents(), true);
+ $formatted = $this->castResponseToType($response, $this->app['config']->get('response_type'));
+
+ if (empty($result[$this->tokenKey])) {
+ throw new HttpException('Request access_token fail: '.json_encode($result, JSON_UNESCAPED_UNICODE), $response, $formatted);
+ }
+
+ return $toArray ? $result : $formatted;
+ }
+
+ /**
+ * @param \Psr\Http\Message\RequestInterface $request
+ * @param array $requestOptions
+ *
+ * @return \Psr\Http\Message\RequestInterface
+ *
+ * @throws \EasyWeChat\Kernel\Exceptions\HttpException
+ * @throws \Psr\SimpleCache\InvalidArgumentException
+ * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
+ * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
+ * @throws \EasyWeChat\Kernel\Exceptions\RuntimeException
+ */
+ public function applyToRequest(RequestInterface $request, array $requestOptions = []): RequestInterface
+ {
+ parse_str($request->getUri()->getQuery(), $query);
+
+ $query = http_build_query(array_merge($this->getQuery(), $query));
+
+ return $request->withUri($request->getUri()->withQuery($query));
+ }
+
+ /**
+ * Send http request.
+ *
+ * @param array $credentials
+ *
+ * @return ResponseInterface
+ *
+ * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
+ * @throws \GuzzleHttp\Exception\GuzzleException
+ */
+ protected function sendRequest(array $credentials): ResponseInterface
+ {
+ $options = [
+ ('GET' === $this->requestMethod) ? 'query' : 'json' => $credentials,
+ ];
+
+ return $this->setHttpClient($this->app['http_client'])->request($this->getEndpoint(), $this->requestMethod, $options);
+ }
+
+ /**
+ * @return string
+ */
+ protected function getCacheKey()
+ {
+ return $this->cachePrefix.md5(json_encode($this->getCredentials()));
+ }
+
+ /**
+ * The request query will be used to add to the request.
+ *
+ * @return array
+ *
+ * @throws \EasyWeChat\Kernel\Exceptions\HttpException
+ * @throws \Psr\SimpleCache\InvalidArgumentException
+ * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
+ * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
+ * @throws \EasyWeChat\Kernel\Exceptions\RuntimeException
+ */
+ protected function getQuery(): array
+ {
+ return [$this->queryName ?? $this->tokenKey => $this->getToken()[$this->tokenKey]];
+ }
+
+ /**
+ * @return string
+ *
+ * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
+ */
+ public function getEndpoint(): string
+ {
+ if (empty($this->endpointToGetToken)) {
+ throw new InvalidArgumentException('No endpoint for access token request.');
+ }
+
+ return $this->endpointToGetToken;
+ }
+
+ /**
+ * @return string
+ */
+ public function getTokenKey()
+ {
+ return $this->tokenKey;
+ }
+
+ /**
+ * Credential for get token.
+ *
+ * @return array
+ */
+ abstract protected function getCredentials(): array;
+}
diff --git a/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/BaseClient.php b/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/BaseClient.php
new file mode 100644
index 0000000..75e79e8
--- /dev/null
+++ b/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/BaseClient.php
@@ -0,0 +1,271 @@
+
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace EasyWeChat\Kernel;
+
+use EasyWeChat\Kernel\Contracts\AccessTokenInterface;
+use EasyWeChat\Kernel\Http\Response;
+use EasyWeChat\Kernel\Traits\HasHttpRequests;
+use GuzzleHttp\MessageFormatter;
+use GuzzleHttp\Middleware;
+use Psr\Http\Message\RequestInterface;
+use Psr\Http\Message\ResponseInterface;
+use Psr\Log\LogLevel;
+
+/**
+ * Class BaseClient.
+ *
+ * @author overtrue
+ */
+class BaseClient
+{
+ use HasHttpRequests { request as performRequest; }
+
+ /**
+ * @var \EasyWeChat\Kernel\ServiceContainer
+ */
+ protected $app;
+
+ /**
+ * @var \EasyWeChat\Kernel\Contracts\AccessTokenInterface
+ */
+ protected $accessToken;
+
+ /**
+ * @var string
+ */
+ protected $baseUri;
+
+ /**
+ * BaseClient constructor.
+ *
+ * @param \EasyWeChat\Kernel\ServiceContainer $app
+ * @param \EasyWeChat\Kernel\Contracts\AccessTokenInterface|null $accessToken
+ */
+ public function __construct(ServiceContainer $app, AccessTokenInterface $accessToken = null)
+ {
+ $this->app = $app;
+ $this->accessToken = $accessToken ?? $this->app['access_token'];
+ }
+
+ /**
+ * GET request.
+ *
+ * @param string $url
+ * @param array $query
+ *
+ * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string
+ *
+ * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
+ * @throws \GuzzleHttp\Exception\GuzzleException
+ */
+ public function httpGet(string $url, array $query = [])
+ {
+ return $this->request($url, 'GET', ['query' => $query]);
+ }
+
+ /**
+ * POST request.
+ *
+ * @param string $url
+ * @param array $data
+ *
+ * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string
+ *
+ * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
+ * @throws \GuzzleHttp\Exception\GuzzleException
+ */
+ public function httpPost(string $url, array $data = [])
+ {
+ return $this->request($url, 'POST', ['form_params' => $data]);
+ }
+
+ /**
+ * JSON request.
+ *
+ * @param string $url
+ * @param array $data
+ * @param array $query
+ *
+ * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string
+ *
+ * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
+ * @throws \GuzzleHttp\Exception\GuzzleException
+ */
+ public function httpPostJson(string $url, array $data = [], array $query = [])
+ {
+ return $this->request($url, 'POST', ['query' => $query, 'json' => $data]);
+ }
+
+ /**
+ * Upload file.
+ *
+ * @param string $url
+ * @param array $files
+ * @param array $form
+ * @param array $query
+ *
+ * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string
+ *
+ * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
+ * @throws \GuzzleHttp\Exception\GuzzleException
+ */
+ public function httpUpload(string $url, array $files = [], array $form = [], array $query = [])
+ {
+ $multipart = [];
+
+ foreach ($files as $name => $path) {
+ $multipart[] = [
+ 'name' => $name,
+ 'contents' => fopen($path, 'r'),
+ ];
+ }
+
+ foreach ($form as $name => $contents) {
+ $multipart[] = compact('name', 'contents');
+ }
+
+ return $this->request($url, 'POST', ['query' => $query, 'multipart' => $multipart, 'connect_timeout' => 30, 'timeout' => 30, 'read_timeout' => 30]);
+ }
+
+ /**
+ * @return AccessTokenInterface
+ */
+ public function getAccessToken(): AccessTokenInterface
+ {
+ return $this->accessToken;
+ }
+
+ /**
+ * @param \EasyWeChat\Kernel\Contracts\AccessTokenInterface $accessToken
+ *
+ * @return $this
+ */
+ public function setAccessToken(AccessTokenInterface $accessToken)
+ {
+ $this->accessToken = $accessToken;
+
+ return $this;
+ }
+
+ /**
+ * @param string $url
+ * @param string $method
+ * @param array $options
+ * @param bool $returnRaw
+ *
+ * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string
+ *
+ * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
+ * @throws \GuzzleHttp\Exception\GuzzleException
+ */
+ public function request(string $url, string $method = 'GET', array $options = [], $returnRaw = false)
+ {
+ if (empty($this->middlewares)) {
+ $this->registerHttpMiddlewares();
+ }
+
+ $response = $this->performRequest($url, $method, $options);
+
+ $this->app->events->dispatch(new Events\HttpResponseCreated($response));
+
+ return $returnRaw ? $response : $this->castResponseToType($response, $this->app->config->get('response_type'));
+ }
+
+ /**
+ * @param string $url
+ * @param string $method
+ * @param array $options
+ *
+ * @return \EasyWeChat\Kernel\Http\Response
+ *
+ * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
+ * @throws \GuzzleHttp\Exception\GuzzleException
+ */
+ public function requestRaw(string $url, string $method = 'GET', array $options = [])
+ {
+ return Response::buildFromPsrResponse($this->request($url, $method, $options, true));
+ }
+
+ /**
+ * Register Guzzle middlewares.
+ */
+ protected function registerHttpMiddlewares()
+ {
+ // retry
+ $this->pushMiddleware($this->retryMiddleware(), 'retry');
+ // access token
+ $this->pushMiddleware($this->accessTokenMiddleware(), 'access_token');
+ // log
+ $this->pushMiddleware($this->logMiddleware(), 'log');
+ }
+
+ /**
+ * Attache access token to request query.
+ *
+ * @return \Closure
+ */
+ protected function accessTokenMiddleware()
+ {
+ return function (callable $handler) {
+ return function (RequestInterface $request, array $options) use ($handler) {
+ if ($this->accessToken) {
+ $request = $this->accessToken->applyToRequest($request, $options);
+ }
+
+ return $handler($request, $options);
+ };
+ };
+ }
+
+ /**
+ * Log the request.
+ *
+ * @return \Closure
+ */
+ protected function logMiddleware()
+ {
+ $formatter = new MessageFormatter($this->app['config']['http.log_template'] ?? MessageFormatter::DEBUG);
+
+ return Middleware::log($this->app['logger'], $formatter, LogLevel::DEBUG);
+ }
+
+ /**
+ * Return retry middleware.
+ *
+ * @return \Closure
+ */
+ protected function retryMiddleware()
+ {
+ return Middleware::retry(function (
+ $retries,
+ RequestInterface $request,
+ ResponseInterface $response = null
+ ) {
+ // Limit the number of retries to 2
+ if ($retries < $this->app->config->get('http.max_retries', 1) && $response && $body = $response->getBody()) {
+ // Retry on server errors
+ $response = json_decode($body, true);
+
+ if (!empty($response['errcode']) && in_array(abs($response['errcode']), [40001, 40014, 42001], true)) {
+ $this->accessToken->refresh();
+ $this->app['logger']->debug('Retrying with refreshed access token.');
+
+ return true;
+ }
+ }
+
+ return false;
+ }, function () {
+ return abs($this->app->config->get('http.retry_delay', 500));
+ });
+ }
+}
diff --git a/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Clauses/Clause.php b/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Clauses/Clause.php
new file mode 100644
index 0000000..49bbb22
--- /dev/null
+++ b/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Clauses/Clause.php
@@ -0,0 +1,64 @@
+
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace EasyWeChat\Kernel\Clauses;
+
+/**
+ * Class Clause.
+ *
+ * @author mingyoung
+ */
+class Clause
+{
+ /**
+ * @var array
+ */
+ protected $clauses = [
+ 'where' => [],
+ ];
+
+ /**
+ * @param mixed ...$args
+ *
+ * @return $this
+ */
+ public function where(...$args)
+ {
+ array_push($this->clauses['where'], $args);
+
+ return $this;
+ }
+
+ /**
+ * @param mixed $payload
+ *
+ * @return bool
+ */
+ public function intercepted($payload)
+ {
+ return (bool) $this->interceptWhereClause($payload);
+ }
+
+ /**
+ * @param mixed $payload
+ *
+ * @return bool
+ */
+ protected function interceptWhereClause($payload)
+ {
+ foreach ($this->clauses['where'] as $item) {
+ list($key, $value) = $item;
+ if (isset($payload[$key]) && $payload[$key] !== $value) {
+ return true;
+ }
+ }
+ }
+}
diff --git a/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Config.php b/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Config.php
new file mode 100644
index 0000000..081f6fd
--- /dev/null
+++ b/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Config.php
@@ -0,0 +1,23 @@
+
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace EasyWeChat\Kernel;
+
+use EasyWeChat\Kernel\Support\Collection;
+
+/**
+ * Class Config.
+ *
+ * @author overtrue
+ */
+class Config extends Collection
+{
+}
diff --git a/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Contracts/AccessTokenInterface.php b/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Contracts/AccessTokenInterface.php
new file mode 100644
index 0000000..56f4a4d
--- /dev/null
+++ b/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Contracts/AccessTokenInterface.php
@@ -0,0 +1,40 @@
+
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace EasyWeChat\Kernel\Contracts;
+
+use Psr\Http\Message\RequestInterface;
+
+/**
+ * Interface AuthorizerAccessToken.
+ *
+ * @author overtrue
+ */
+interface AccessTokenInterface
+{
+ /**
+ * @return array
+ */
+ public function getToken(): array;
+
+ /**
+ * @return \EasyWeChat\Kernel\Contracts\AccessTokenInterface
+ */
+ public function refresh(): self;
+
+ /**
+ * @param \Psr\Http\Message\RequestInterface $request
+ * @param array $requestOptions
+ *
+ * @return \Psr\Http\Message\RequestInterface
+ */
+ public function applyToRequest(RequestInterface $request, array $requestOptions = []): RequestInterface;
+}
diff --git a/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Contracts/Arrayable.php b/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Contracts/Arrayable.php
new file mode 100644
index 0000000..d947f8f
--- /dev/null
+++ b/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Contracts/Arrayable.php
@@ -0,0 +1,29 @@
+
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace EasyWeChat\Kernel\Contracts;
+
+use ArrayAccess;
+
+/**
+ * Interface Arrayable.
+ *
+ * @author overtrue
+ */
+interface Arrayable extends ArrayAccess
+{
+ /**
+ * Get the instance as an array.
+ *
+ * @return array
+ */
+ public function toArray();
+}
diff --git a/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Contracts/EventHandlerInterface.php b/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Contracts/EventHandlerInterface.php
new file mode 100644
index 0000000..c9d116c
--- /dev/null
+++ b/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Contracts/EventHandlerInterface.php
@@ -0,0 +1,25 @@
+
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace EasyWeChat\Kernel\Contracts;
+
+/**
+ * Interface EventHandlerInterface.
+ *
+ * @author mingyoung
+ */
+interface EventHandlerInterface
+{
+ /**
+ * @param mixed $payload
+ */
+ public function handle($payload = null);
+}
diff --git a/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Contracts/MediaInterface.php b/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Contracts/MediaInterface.php
new file mode 100644
index 0000000..63768cf
--- /dev/null
+++ b/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Contracts/MediaInterface.php
@@ -0,0 +1,25 @@
+
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace EasyWeChat\Kernel\Contracts;
+
+/**
+ * Interface MediaInterface.
+ *
+ * @author overtrue
+ */
+interface MediaInterface extends MessageInterface
+{
+ /**
+ * @return string
+ */
+ public function getMediaId(): string;
+}
diff --git a/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Contracts/MessageInterface.php b/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Contracts/MessageInterface.php
new file mode 100644
index 0000000..29ddb57
--- /dev/null
+++ b/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Contracts/MessageInterface.php
@@ -0,0 +1,35 @@
+
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace EasyWeChat\Kernel\Contracts;
+
+/**
+ * Interface MessageInterface.
+ *
+ * @author overtrue
+ */
+interface MessageInterface
+{
+ /**
+ * @return string
+ */
+ public function getType(): string;
+
+ /**
+ * @return array
+ */
+ public function transformForJsonRequest(): array;
+
+ /**
+ * @return string
+ */
+ public function transformToXml(): string;
+}
diff --git a/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Decorators/FinallyResult.php b/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Decorators/FinallyResult.php
new file mode 100644
index 0000000..e698bbf
--- /dev/null
+++ b/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Decorators/FinallyResult.php
@@ -0,0 +1,35 @@
+
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace EasyWeChat\Kernel\Decorators;
+
+/**
+ * Class FinallyResult.
+ *
+ * @author overtrue
+ */
+class FinallyResult
+{
+ /**
+ * @var mixed
+ */
+ public $content;
+
+ /**
+ * FinallyResult constructor.
+ *
+ * @param mixed $content
+ */
+ public function __construct($content)
+ {
+ $this->content = $content;
+ }
+}
diff --git a/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Decorators/TerminateResult.php b/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Decorators/TerminateResult.php
new file mode 100644
index 0000000..cf1042d
--- /dev/null
+++ b/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Decorators/TerminateResult.php
@@ -0,0 +1,35 @@
+
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace EasyWeChat\Kernel\Decorators;
+
+/**
+ * Class TerminateResult.
+ *
+ * @author overtrue
+ */
+class TerminateResult
+{
+ /**
+ * @var mixed
+ */
+ public $content;
+
+ /**
+ * FinallyResult constructor.
+ *
+ * @param mixed $content
+ */
+ public function __construct($content)
+ {
+ $this->content = $content;
+ }
+}
diff --git a/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Encryptor.php b/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Encryptor.php
new file mode 100644
index 0000000..150ad21
--- /dev/null
+++ b/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Encryptor.php
@@ -0,0 +1,219 @@
+
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace EasyWeChat\Kernel;
+
+use EasyWeChat\Kernel\Exceptions\RuntimeException;
+use EasyWeChat\Kernel\Support\AES;
+use function EasyWeChat\Kernel\Support\str_random;
+use EasyWeChat\Kernel\Support\XML;
+use Throwable;
+
+/**
+ * Class Encryptor.
+ *
+ * @author overtrue
+ */
+class Encryptor
+{
+ const ERROR_INVALID_SIGNATURE = -40001; // Signature verification failed
+ const ERROR_PARSE_XML = -40002; // Parse XML failed
+ const ERROR_CALC_SIGNATURE = -40003; // Calculating the signature failed
+ const ERROR_INVALID_AES_KEY = -40004; // Invalid AESKey
+ const ERROR_INVALID_APP_ID = -40005; // Check AppID failed
+ const ERROR_ENCRYPT_AES = -40006; // AES EncryptionInterface failed
+ const ERROR_DECRYPT_AES = -40007; // AES decryption failed
+ const ERROR_INVALID_XML = -40008; // Invalid XML
+ const ERROR_BASE64_ENCODE = -40009; // Base64 encoding failed
+ const ERROR_BASE64_DECODE = -40010; // Base64 decoding failed
+ const ERROR_XML_BUILD = -40011; // XML build failed
+ const ILLEGAL_BUFFER = -41003; // Illegal buffer
+
+ /**
+ * App id.
+ *
+ * @var string
+ */
+ protected $appId;
+
+ /**
+ * App token.
+ *
+ * @var string
+ */
+ protected $token;
+
+ /**
+ * @var string
+ */
+ protected $aesKey;
+
+ /**
+ * Block size.
+ *
+ * @var int
+ */
+ protected $blockSize = 32;
+
+ /**
+ * Constructor.
+ *
+ * @param string $appId
+ * @param string|null $token
+ * @param string|null $aesKey
+ */
+ public function __construct(string $appId, string $token = null, string $aesKey = null)
+ {
+ $this->appId = $appId;
+ $this->token = $token;
+ $this->aesKey = base64_decode($aesKey.'=', true);
+ }
+
+ /**
+ * Get the app token.
+ *
+ * @return string
+ */
+ public function getToken(): string
+ {
+ return $this->token;
+ }
+
+ /**
+ * Encrypt the message and return XML.
+ *
+ * @param string $xml
+ * @param string $nonce
+ * @param int $timestamp
+ *
+ * @return string
+ *
+ * @throws \EasyWeChat\Kernel\Exceptions\RuntimeException
+ */
+ public function encrypt($xml, $nonce = null, $timestamp = null): string
+ {
+ try {
+ $xml = $this->pkcs7Pad(str_random(16).pack('N', strlen($xml)).$xml.$this->appId, $this->blockSize);
+
+ $encrypted = base64_encode(AES::encrypt(
+ $xml,
+ $this->aesKey,
+ substr($this->aesKey, 0, 16),
+ OPENSSL_NO_PADDING
+ ));
+ // @codeCoverageIgnoreStart
+ } catch (Throwable $e) {
+ throw new RuntimeException($e->getMessage(), self::ERROR_ENCRYPT_AES);
+ }
+ // @codeCoverageIgnoreEnd
+
+ !is_null($nonce) || $nonce = substr($this->appId, 0, 10);
+ !is_null($timestamp) || $timestamp = time();
+
+ $response = [
+ 'Encrypt' => $encrypted,
+ 'MsgSignature' => $this->signature($this->token, $timestamp, $nonce, $encrypted),
+ 'TimeStamp' => $timestamp,
+ 'Nonce' => $nonce,
+ ];
+
+ //生成响应xml
+ return XML::build($response);
+ }
+
+ /**
+ * Decrypt message.
+ *
+ * @param string $content
+ * @param string $msgSignature
+ * @param string $nonce
+ * @param string $timestamp
+ *
+ * @return string
+ *
+ * @throws \EasyWeChat\Kernel\Exceptions\RuntimeException
+ */
+ public function decrypt($content, $msgSignature, $nonce, $timestamp): string
+ {
+ $signature = $this->signature($this->token, $timestamp, $nonce, $content);
+
+ if ($signature !== $msgSignature) {
+ throw new RuntimeException('Invalid Signature.', self::ERROR_INVALID_SIGNATURE);
+ }
+
+ $decrypted = AES::decrypt(
+ base64_decode($content, true),
+ $this->aesKey,
+ substr($this->aesKey, 0, 16),
+ OPENSSL_NO_PADDING
+ );
+ $result = $this->pkcs7Unpad($decrypted);
+ $content = substr($result, 16, strlen($result));
+ $contentLen = unpack('N', substr($content, 0, 4))[1];
+
+ if (trim(substr($content, $contentLen + 4)) !== $this->appId) {
+ throw new RuntimeException('Invalid appId.', self::ERROR_INVALID_APP_ID);
+ }
+
+ return substr($content, 4, $contentLen);
+ }
+
+ /**
+ * Get SHA1.
+ *
+ * @return string
+ */
+ public function signature(): string
+ {
+ $array = func_get_args();
+ sort($array, SORT_STRING);
+
+ return sha1(implode($array));
+ }
+
+ /**
+ * PKCS#7 pad.
+ *
+ * @param string $text
+ * @param int $blockSize
+ *
+ * @return string
+ *
+ * @throws \EasyWeChat\Kernel\Exceptions\RuntimeException
+ */
+ public function pkcs7Pad(string $text, int $blockSize): string
+ {
+ if ($blockSize > 256) {
+ throw new RuntimeException('$blockSize may not be more than 256');
+ }
+ $padding = $blockSize - (strlen($text) % $blockSize);
+ $pattern = chr($padding);
+
+ return $text.str_repeat($pattern, $padding);
+ }
+
+ /**
+ * PKCS#7 unpad.
+ *
+ * @param string $text
+ *
+ * @return string
+ */
+ public function pkcs7Unpad(string $text): string
+ {
+ $pad = ord(substr($text, -1));
+ if ($pad < 1 || $pad > $this->blockSize) {
+ $pad = 0;
+ }
+
+ return substr($text, 0, (strlen($text) - $pad));
+ }
+}
diff --git a/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Events/AccessTokenRefreshed.php b/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Events/AccessTokenRefreshed.php
new file mode 100644
index 0000000..a829901
--- /dev/null
+++ b/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Events/AccessTokenRefreshed.php
@@ -0,0 +1,35 @@
+
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace EasyWeChat\Kernel\Events;
+
+use EasyWeChat\Kernel\AccessToken;
+
+/**
+ * Class AccessTokenRefreshed.
+ *
+ * @author mingyoung
+ */
+class AccessTokenRefreshed
+{
+ /**
+ * @var \EasyWeChat\Kernel\AccessToken
+ */
+ public $accessToken;
+
+ /**
+ * @param \EasyWeChat\Kernel\AccessToken $accessToken
+ */
+ public function __construct(AccessToken $accessToken)
+ {
+ $this->accessToken = $accessToken;
+ }
+}
diff --git a/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Events/ApplicationInitialized.php b/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Events/ApplicationInitialized.php
new file mode 100644
index 0000000..89d67fe
--- /dev/null
+++ b/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Events/ApplicationInitialized.php
@@ -0,0 +1,35 @@
+
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace EasyWeChat\Kernel\Events;
+
+use EasyWeChat\Kernel\ServiceContainer;
+
+/**
+ * Class ApplicationInitialized.
+ *
+ * @author mingyoung
+ */
+class ApplicationInitialized
+{
+ /**
+ * @var \EasyWeChat\Kernel\ServiceContainer
+ */
+ public $app;
+
+ /**
+ * @param \EasyWeChat\Kernel\ServiceContainer $app
+ */
+ public function __construct(ServiceContainer $app)
+ {
+ $this->app = $app;
+ }
+}
diff --git a/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Events/HttpResponseCreated.php b/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Events/HttpResponseCreated.php
new file mode 100644
index 0000000..2257260
--- /dev/null
+++ b/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Events/HttpResponseCreated.php
@@ -0,0 +1,35 @@
+
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace EasyWeChat\Kernel\Events;
+
+use Psr\Http\Message\ResponseInterface;
+
+/**
+ * Class HttpResponseCreated.
+ *
+ * @author mingyoung
+ */
+class HttpResponseCreated
+{
+ /**
+ * @var \Psr\Http\Message\ResponseInterface
+ */
+ public $response;
+
+ /**
+ * @param \Psr\Http\Message\ResponseInterface $response
+ */
+ public function __construct(ResponseInterface $response)
+ {
+ $this->response = $response;
+ }
+}
diff --git a/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Events/ServerGuardResponseCreated.php b/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Events/ServerGuardResponseCreated.php
new file mode 100644
index 0000000..3ab9925
--- /dev/null
+++ b/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Events/ServerGuardResponseCreated.php
@@ -0,0 +1,35 @@
+
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace EasyWeChat\Kernel\Events;
+
+use Symfony\Component\HttpFoundation\Response;
+
+/**
+ * Class ServerGuardResponseCreated.
+ *
+ * @author mingyoung
+ */
+class ServerGuardResponseCreated
+{
+ /**
+ * @var \Symfony\Component\HttpFoundation\Response
+ */
+ public $response;
+
+ /**
+ * @param \Symfony\Component\HttpFoundation\Response $response
+ */
+ public function __construct(Response $response)
+ {
+ $this->response = $response;
+ }
+}
diff --git a/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Exceptions/BadRequestException.php b/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Exceptions/BadRequestException.php
new file mode 100644
index 0000000..a0b4f91
--- /dev/null
+++ b/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Exceptions/BadRequestException.php
@@ -0,0 +1,21 @@
+
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace EasyWeChat\Kernel\Exceptions;
+
+/**
+ * Class BadRequestException.
+ *
+ * @author overtrue
+ */
+class BadRequestException extends Exception
+{
+}
diff --git a/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Exceptions/DecryptException.php b/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Exceptions/DecryptException.php
new file mode 100644
index 0000000..f29acca
--- /dev/null
+++ b/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Exceptions/DecryptException.php
@@ -0,0 +1,16 @@
+
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace EasyWeChat\Kernel\Exceptions;
+
+class DecryptException extends Exception
+{
+}
diff --git a/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Exceptions/Exception.php b/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Exceptions/Exception.php
new file mode 100644
index 0000000..9eba298
--- /dev/null
+++ b/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Exceptions/Exception.php
@@ -0,0 +1,23 @@
+
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace EasyWeChat\Kernel\Exceptions;
+
+use Exception as BaseException;
+
+/**
+ * Class Exception.
+ *
+ * @author overtrue
+ */
+class Exception extends BaseException
+{
+}
diff --git a/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Exceptions/HttpException.php b/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Exceptions/HttpException.php
new file mode 100644
index 0000000..8ab130d
--- /dev/null
+++ b/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Exceptions/HttpException.php
@@ -0,0 +1,52 @@
+
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace EasyWeChat\Kernel\Exceptions;
+
+use Psr\Http\Message\ResponseInterface;
+
+/**
+ * Class HttpException.
+ *
+ * @author overtrue
+ */
+class HttpException extends Exception
+{
+ /**
+ * @var \Psr\Http\Message\ResponseInterface|null
+ */
+ public $response;
+
+ /**
+ * @var \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string|null
+ */
+ public $formattedResponse;
+
+ /**
+ * HttpException constructor.
+ *
+ * @param string $message
+ * @param \Psr\Http\Message\ResponseInterface|null $response
+ * @param null $formattedResponse
+ * @param int|null $code
+ */
+ public function __construct($message, ResponseInterface $response = null, $formattedResponse = null, $code = null)
+ {
+ parent::__construct($message, $code);
+
+ $this->response = $response;
+ $this->formattedResponse = $formattedResponse;
+
+ if ($response) {
+ $response->getBody()->rewind();
+ }
+ }
+}
diff --git a/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Exceptions/InvalidArgumentException.php b/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Exceptions/InvalidArgumentException.php
new file mode 100644
index 0000000..386a144
--- /dev/null
+++ b/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Exceptions/InvalidArgumentException.php
@@ -0,0 +1,21 @@
+
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace EasyWeChat\Kernel\Exceptions;
+
+/**
+ * Class InvalidArgumentException.
+ *
+ * @author overtrue
+ */
+class InvalidArgumentException extends Exception
+{
+}
diff --git a/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Exceptions/InvalidConfigException.php b/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Exceptions/InvalidConfigException.php
new file mode 100644
index 0000000..1e4ae2a
--- /dev/null
+++ b/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Exceptions/InvalidConfigException.php
@@ -0,0 +1,21 @@
+
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace EasyWeChat\Kernel\Exceptions;
+
+/**
+ * Class InvalidConfigException.
+ *
+ * @author overtrue
+ */
+class InvalidConfigException extends Exception
+{
+}
diff --git a/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Exceptions/RuntimeException.php b/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Exceptions/RuntimeException.php
new file mode 100644
index 0000000..25f2f5b
--- /dev/null
+++ b/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Exceptions/RuntimeException.php
@@ -0,0 +1,21 @@
+
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace EasyWeChat\Kernel\Exceptions;
+
+/**
+ * Class RuntimeException.
+ *
+ * @author overtrue
+ */
+class RuntimeException extends Exception
+{
+}
diff --git a/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Exceptions/UnboundServiceException.php b/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Exceptions/UnboundServiceException.php
new file mode 100644
index 0000000..78ea85c
--- /dev/null
+++ b/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Exceptions/UnboundServiceException.php
@@ -0,0 +1,21 @@
+
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace EasyWeChat\Kernel\Exceptions;
+
+/**
+ * Class InvalidConfigException.
+ *
+ * @author overtrue
+ */
+class UnboundServiceException extends Exception
+{
+}
diff --git a/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Helpers.php b/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Helpers.php
new file mode 100644
index 0000000..3ea48a4
--- /dev/null
+++ b/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Helpers.php
@@ -0,0 +1,57 @@
+
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace EasyWeChat\Kernel;
+
+use EasyWeChat\Kernel\Contracts\Arrayable;
+use EasyWeChat\Kernel\Exceptions\RuntimeException;
+use EasyWeChat\Kernel\Support\Arr;
+use EasyWeChat\Kernel\Support\Collection;
+
+function data_get($data, $key, $default = null)
+{
+ switch (true) {
+ case is_array($data):
+ return Arr::get($data, $key, $default);
+ case $data instanceof Collection:
+ return $data->get($key, $default);
+ case $data instanceof Arrayable:
+ return Arr::get($data->toArray(), $key, $default);
+ case $data instanceof \ArrayIterator:
+ return $data->getArrayCopy()[$key] ?? $default;
+ case $data instanceof \ArrayAccess:
+ return $data[$key] ?? $default;
+ case $data instanceof \IteratorAggregate && $data->getIterator() instanceof \ArrayIterator:
+ return $data->getIterator()->getArrayCopy()[$key] ?? $default;
+ case is_object($data):
+ return $data->{$key} ?? $default;
+ default:
+ throw new RuntimeException(sprintf('Can\'t access data with key "%s"', $key));
+ }
+}
+
+function data_to_array($data)
+{
+ switch (true) {
+ case is_array($data):
+ return $data;
+ case $data instanceof Collection:
+ return $data->all();
+ case $data instanceof Arrayable:
+ return $data->toArray();
+ case $data instanceof \IteratorAggregate && $data->getIterator() instanceof \ArrayIterator:
+ return $data->getIterator()->getArrayCopy();
+ case $data instanceof \ArrayIterator:
+ return $data->getArrayCopy();
+ default:
+ throw new RuntimeException(sprintf('Can\'t transform data to array'));
+ }
+}
diff --git a/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Http/Response.php b/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Http/Response.php
new file mode 100644
index 0000000..adcd416
--- /dev/null
+++ b/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Http/Response.php
@@ -0,0 +1,121 @@
+
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace EasyWeChat\Kernel\Http;
+
+use EasyWeChat\Kernel\Support\Collection;
+use EasyWeChat\Kernel\Support\XML;
+use GuzzleHttp\Psr7\Response as GuzzleResponse;
+use Psr\Http\Message\ResponseInterface;
+
+/**
+ * Class Response.
+ *
+ * @author overtrue
+ */
+class Response extends GuzzleResponse
+{
+ /**
+ * @return string
+ */
+ public function getBodyContents()
+ {
+ $this->getBody()->rewind();
+ $contents = $this->getBody()->getContents();
+ $this->getBody()->rewind();
+
+ return $contents;
+ }
+
+ /**
+ * @param \Psr\Http\Message\ResponseInterface $response
+ *
+ * @return \EasyWeChat\Kernel\Http\Response
+ */
+ public static function buildFromPsrResponse(ResponseInterface $response)
+ {
+ return new static(
+ $response->getStatusCode(),
+ $response->getHeaders(),
+ $response->getBody(),
+ $response->getProtocolVersion(),
+ $response->getReasonPhrase()
+ );
+ }
+
+ /**
+ * Build to json.
+ *
+ * @return string
+ */
+ public function toJson()
+ {
+ return json_encode($this->toArray());
+ }
+
+ /**
+ * Build to array.
+ *
+ * @return array
+ */
+ public function toArray()
+ {
+ $content = $this->removeControlCharacters($this->getBodyContents());
+
+ if (false !== stripos($this->getHeaderLine('Content-Type'), 'xml') || 0 === stripos($content, 'toArray());
+ }
+
+ /**
+ * @return object
+ */
+ public function toObject()
+ {
+ return json_decode($this->toJson());
+ }
+
+ /**
+ * @return bool|string
+ */
+ public function __toString()
+ {
+ return $this->getBodyContents();
+ }
+
+ /**
+ * @param string $content
+ *
+ * @return string
+ */
+ protected function removeControlCharacters(string $content)
+ {
+ return \preg_replace('/[\x00-\x1F\x80-\x9F]/u', '', $content);
+ }
+}
diff --git a/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Http/StreamResponse.php b/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Http/StreamResponse.php
new file mode 100644
index 0000000..104e8c3
--- /dev/null
+++ b/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Http/StreamResponse.php
@@ -0,0 +1,86 @@
+
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace EasyWeChat\Kernel\Http;
+
+use EasyWeChat\Kernel\Exceptions\InvalidArgumentException;
+use EasyWeChat\Kernel\Exceptions\RuntimeException;
+use EasyWeChat\Kernel\Support\File;
+
+/**
+ * Class StreamResponse.
+ *
+ * @author overtrue
+ */
+class StreamResponse extends Response
+{
+ /**
+ * @param string $directory
+ * @param string $filename
+ * @param bool $appendSuffix
+ *
+ * @return bool|int
+ *
+ * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
+ * @throws \EasyWeChat\Kernel\Exceptions\RuntimeException
+ */
+ public function save(string $directory, string $filename = '', bool $appendSuffix = true)
+ {
+ $this->getBody()->rewind();
+
+ $directory = rtrim($directory, '/');
+
+ if (!is_dir($directory)) {
+ mkdir($directory, 0755, true); // @codeCoverageIgnore
+ }
+
+ if (!is_writable($directory)) {
+ throw new InvalidArgumentException(sprintf("'%s' is not writable.", $directory));
+ }
+
+ $contents = $this->getBody()->getContents();
+
+ if (empty($contents) || '{' === $contents[0]) {
+ throw new RuntimeException('Invalid media response content.');
+ }
+
+ if (empty($filename)) {
+ if (preg_match('/filename="(?.*?)"/', $this->getHeaderLine('Content-Disposition'), $match)) {
+ $filename = $match['filename'];
+ } else {
+ $filename = md5($contents);
+ }
+ }
+
+ if ($appendSuffix && empty(pathinfo($filename, PATHINFO_EXTENSION))) {
+ $filename .= File::getStreamExt($contents);
+ }
+
+ file_put_contents($directory.'/'.$filename, $contents);
+
+ return $filename;
+ }
+
+ /**
+ * @param string $directory
+ * @param string $filename
+ * @param bool $appendSuffix
+ *
+ * @return bool|int
+ *
+ * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
+ * @throws \EasyWeChat\Kernel\Exceptions\RuntimeException
+ */
+ public function saveAs(string $directory, string $filename, bool $appendSuffix = true)
+ {
+ return $this->save($directory, $filename, $appendSuffix);
+ }
+}
diff --git a/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Messages/Article.php b/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Messages/Article.php
new file mode 100644
index 0000000..4792a1f
--- /dev/null
+++ b/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Messages/Article.php
@@ -0,0 +1,58 @@
+
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace EasyWeChat\Kernel\Messages;
+
+/**
+ * Class Article.
+ */
+class Article extends Message
+{
+ /**
+ * @var string
+ */
+ protected $type = 'mpnews';
+
+ /**
+ * Properties.
+ *
+ * @var array
+ */
+ protected $properties = [
+ 'thumb_media_id',
+ 'author',
+ 'title',
+ 'content',
+ 'digest',
+ 'source_url',
+ 'show_cover',
+ ];
+
+ /**
+ * Aliases of attribute.
+ *
+ * @var array
+ */
+ protected $jsonAliases = [
+ 'content_source_url' => 'source_url',
+ 'show_cover_pic' => 'show_cover',
+ ];
+
+ /**
+ * @var array
+ */
+ protected $required = [
+ 'thumb_media_id',
+ 'title',
+ 'content',
+ 'show_cover',
+ ];
+}
diff --git a/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Messages/Card.php b/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Messages/Card.php
new file mode 100644
index 0000000..0e21231
--- /dev/null
+++ b/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Messages/Card.php
@@ -0,0 +1,52 @@
+
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+/**
+ * Card.php.
+ *
+ * @author overtrue
+ * @copyright 2015 overtrue
+ *
+ * @see https://github.com/overtrue
+ * @see http://overtrue.me
+ */
+
+namespace EasyWeChat\Kernel\Messages;
+
+/**
+ * Class Card.
+ */
+class Card extends Message
+{
+ /**
+ * Message type.
+ *
+ * @var string
+ */
+ protected $type = 'wxcard';
+
+ /**
+ * Properties.
+ *
+ * @var array
+ */
+ protected $properties = ['card_id'];
+
+ /**
+ * Media constructor.
+ *
+ * @param string $cardId
+ */
+ public function __construct(string $cardId)
+ {
+ parent::__construct(['card_id' => $cardId]);
+ }
+}
diff --git a/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Messages/DeviceEvent.php b/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Messages/DeviceEvent.php
new file mode 100644
index 0000000..ae57910
--- /dev/null
+++ b/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Messages/DeviceEvent.php
@@ -0,0 +1,40 @@
+
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace EasyWeChat\Kernel\Messages;
+
+/**
+ * Class DeviceEvent.
+ *
+ * @property string $media_id
+ */
+class DeviceEvent extends Message
+{
+ /**
+ * Messages type.
+ *
+ * @var string
+ */
+ protected $type = 'device_event';
+
+ /**
+ * Properties.
+ *
+ * @var array
+ */
+ protected $properties = [
+ 'device_type',
+ 'device_id',
+ 'content',
+ 'session_id',
+ 'open_id',
+ ];
+}
diff --git a/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Messages/DeviceText.php b/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Messages/DeviceText.php
new file mode 100644
index 0000000..87e627a
--- /dev/null
+++ b/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Messages/DeviceText.php
@@ -0,0 +1,50 @@
+
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace EasyWeChat\Kernel\Messages;
+
+/**
+ * Class DeviceText.
+ *
+ * @property string $content
+ */
+class DeviceText extends Message
+{
+ /**
+ * Messages type.
+ *
+ * @var string
+ */
+ protected $type = 'device_text';
+
+ /**
+ * Properties.
+ *
+ * @var array
+ */
+ protected $properties = [
+ 'device_type',
+ 'device_id',
+ 'content',
+ 'session_id',
+ 'open_id',
+ ];
+
+ public function toXmlArray()
+ {
+ return [
+ 'DeviceType' => $this->get('device_type'),
+ 'DeviceID' => $this->get('device_id'),
+ 'SessionID' => $this->get('session_id'),
+ 'Content' => base64_encode($this->get('content')),
+ ];
+ }
+}
diff --git a/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Messages/File.php b/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Messages/File.php
new file mode 100644
index 0000000..a14c42f
--- /dev/null
+++ b/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Messages/File.php
@@ -0,0 +1,25 @@
+
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace EasyWeChat\Kernel\Messages;
+
+/**
+ * Class Image.
+ *
+ * @property string $media_id
+ */
+class File extends Media
+{
+ /**
+ * @var string
+ */
+ protected $type = 'file';
+}
diff --git a/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Messages/Image.php b/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Messages/Image.php
new file mode 100644
index 0000000..982033b
--- /dev/null
+++ b/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Messages/Image.php
@@ -0,0 +1,27 @@
+
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace EasyWeChat\Kernel\Messages;
+
+/**
+ * Class Image.
+ *
+ * @property string $media_id
+ */
+class Image extends Media
+{
+ /**
+ * Messages type.
+ *
+ * @var string
+ */
+ protected $type = 'image';
+}
diff --git a/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Messages/Link.php b/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Messages/Link.php
new file mode 100644
index 0000000..9c126b5
--- /dev/null
+++ b/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Messages/Link.php
@@ -0,0 +1,36 @@
+
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace EasyWeChat\Kernel\Messages;
+
+/**
+ * Class Link.
+ */
+class Link extends Message
+{
+ /**
+ * Messages type.
+ *
+ * @var string
+ */
+ protected $type = 'link';
+
+ /**
+ * Properties.
+ *
+ * @var array
+ */
+ protected $properties = [
+ 'title',
+ 'description',
+ 'url',
+ ];
+}
diff --git a/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Messages/Location.php b/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Messages/Location.php
new file mode 100644
index 0000000..f10351b
--- /dev/null
+++ b/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Messages/Location.php
@@ -0,0 +1,38 @@
+
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace EasyWeChat\Kernel\Messages;
+
+/**
+ * Class Location.
+ */
+class Location extends Message
+{
+ /**
+ * Messages type.
+ *
+ * @var string
+ */
+ protected $type = 'location';
+
+ /**
+ * Properties.
+ *
+ * @var array
+ */
+ protected $properties = [
+ 'latitude',
+ 'longitude',
+ 'scale',
+ 'label',
+ 'precision',
+ ];
+}
diff --git a/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Messages/Media.php b/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Messages/Media.php
new file mode 100644
index 0000000..d8706fe
--- /dev/null
+++ b/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Messages/Media.php
@@ -0,0 +1,70 @@
+
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace EasyWeChat\Kernel\Messages;
+
+use EasyWeChat\Kernel\Contracts\MediaInterface;
+use EasyWeChat\Kernel\Support\Str;
+
+/**
+ * Class Media.
+ */
+class Media extends Message implements MediaInterface
+{
+ /**
+ * Properties.
+ *
+ * @var array
+ */
+ protected $properties = ['media_id'];
+
+ /**
+ * @var array
+ */
+ protected $required = [
+ 'media_id',
+ ];
+
+ /**
+ * MaterialClient constructor.
+ *
+ * @param string $mediaId
+ * @param string $type
+ * @param array $attributes
+ */
+ public function __construct(string $mediaId, $type = null, array $attributes = [])
+ {
+ parent::__construct(array_merge(['media_id' => $mediaId], $attributes));
+
+ !empty($type) && $this->setType($type);
+ }
+
+ /**
+ * @return string
+ *
+ * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
+ */
+ public function getMediaId(): string
+ {
+ $this->checkRequiredAttributes();
+
+ return $this->get('media_id');
+ }
+
+ public function toXmlArray()
+ {
+ return [
+ Str::studly($this->getType()) => [
+ 'MediaId' => $this->get('media_id'),
+ ],
+ ];
+ }
+}
diff --git a/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Messages/Message.php b/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Messages/Message.php
new file mode 100644
index 0000000..0c22aac
--- /dev/null
+++ b/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Messages/Message.php
@@ -0,0 +1,208 @@
+
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace EasyWeChat\Kernel\Messages;
+
+use EasyWeChat\Kernel\Contracts\MessageInterface;
+use EasyWeChat\Kernel\Support\XML;
+use EasyWeChat\Kernel\Traits\HasAttributes;
+use Mockery\Exception\BadMethodCallException;
+
+/**
+ * Class Messages.
+ */
+abstract class Message implements MessageInterface
+{
+ use HasAttributes;
+
+ const TEXT = 2;
+ const IMAGE = 4;
+ const VOICE = 8;
+ const VIDEO = 16;
+ const SHORT_VIDEO = 32;
+ const LOCATION = 64;
+ const LINK = 128;
+ const DEVICE_EVENT = 256;
+ const DEVICE_TEXT = 512;
+ const FILE = 1024;
+ const TEXT_CARD = 2048;
+ const TRANSFER = 4096;
+ const EVENT = 1048576;
+ const MINIPROGRAM_PAGE = 2097152;
+ const ALL = self::TEXT | self::IMAGE | self::VOICE | self::VIDEO | self::SHORT_VIDEO | self::LOCATION | self::LINK
+ | self::DEVICE_EVENT | self::DEVICE_TEXT | self::FILE | self::TEXT_CARD | self::TRANSFER | self::EVENT | self::MINIPROGRAM_PAGE;
+
+ /**
+ * @var string
+ */
+ protected $type;
+
+ /**
+ * @var int
+ */
+ protected $id;
+
+ /**
+ * @var string
+ */
+ protected $to;
+
+ /**
+ * @var string
+ */
+ protected $from;
+
+ /**
+ * @var array
+ */
+ protected $properties = [];
+
+ /**
+ * @var array
+ */
+ protected $jsonAliases = [];
+
+ /**
+ * Message constructor.
+ *
+ * @param array $attributes
+ */
+ public function __construct(array $attributes = [])
+ {
+ $this->setAttributes($attributes);
+ }
+
+ /**
+ * Return type name message.
+ *
+ * @return string
+ */
+ public function getType(): string
+ {
+ return $this->type;
+ }
+
+ /**
+ * @param string $type
+ */
+ public function setType(string $type)
+ {
+ $this->type = $type;
+ }
+
+ /**
+ * Magic getter.
+ *
+ * @param string $property
+ *
+ * @return mixed
+ */
+ public function __get($property)
+ {
+ if (property_exists($this, $property)) {
+ return $this->$property;
+ }
+
+ return $this->getAttribute($property);
+ }
+
+ /**
+ * Magic setter.
+ *
+ * @param string $property
+ * @param mixed $value
+ *
+ * @return Message
+ */
+ public function __set($property, $value)
+ {
+ if (property_exists($this, $property)) {
+ $this->$property = $value;
+ } else {
+ $this->setAttribute($property, $value);
+ }
+
+ return $this;
+ }
+
+ /**
+ * @param array $appends
+ *
+ * @return array
+ */
+ public function transformForJsonRequestWithoutType(array $appends = [])
+ {
+ return $this->transformForJsonRequest($appends, false);
+ }
+
+ /**
+ * @param array $appends
+ * @param bool $withType
+ *
+ * @return array
+ *
+ * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
+ */
+ public function transformForJsonRequest(array $appends = [], $withType = true): array
+ {
+ if (!$withType) {
+ return $this->propertiesToArray([], $this->jsonAliases);
+ }
+ $messageType = $this->getType();
+ $data = array_merge(['msgtype' => $messageType], $appends);
+
+ $data[$messageType] = array_merge($data[$messageType] ?? [], $this->propertiesToArray([], $this->jsonAliases));
+
+ return $data;
+ }
+
+ /**
+ * @param array $appends
+ * @param bool $returnAsArray
+ *
+ * @return string
+ */
+ public function transformToXml(array $appends = [], bool $returnAsArray = false): string
+ {
+ $data = array_merge(['MsgType' => $this->getType()], $this->toXmlArray(), $appends);
+
+ return $returnAsArray ? $data : XML::build($data);
+ }
+
+ /**
+ * @param array $data
+ * @param array $aliases
+ *
+ * @return array
+ *
+ * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
+ */
+ protected function propertiesToArray(array $data, array $aliases = []): array
+ {
+ $this->checkRequiredAttributes();
+
+ foreach ($this->attributes as $property => $value) {
+ if (is_null($value) && !$this->isRequired($property)) {
+ continue;
+ }
+ $alias = array_search($property, $aliases, true);
+
+ $data[$alias ?: $property] = $this->get($property);
+ }
+
+ return $data;
+ }
+
+ public function toXmlArray()
+ {
+ throw new BadMethodCallException(sprintf('Class "%s" cannot support transform to XML message.', __CLASS__));
+ }
+}
diff --git a/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Messages/MiniProgramPage.php b/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Messages/MiniProgramPage.php
new file mode 100644
index 0000000..e4973b1
--- /dev/null
+++ b/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Messages/MiniProgramPage.php
@@ -0,0 +1,31 @@
+
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace EasyWeChat\Kernel\Messages;
+
+/**
+ * Class MiniProgramPage.
+ */
+class MiniProgramPage extends Message
+{
+ protected $type = 'miniprogrampage';
+
+ protected $properties = [
+ 'title',
+ 'appid',
+ 'pagepath',
+ 'thumb_media_id',
+ ];
+
+ protected $required = [
+ 'thumb_media_id', 'appid', 'pagepath',
+ ];
+}
diff --git a/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Messages/Music.php b/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Messages/Music.php
new file mode 100644
index 0000000..85feb76
--- /dev/null
+++ b/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Messages/Music.php
@@ -0,0 +1,73 @@
+
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace EasyWeChat\Kernel\Messages;
+
+/**
+ * Class Music.
+ *
+ * @property string $url
+ * @property string $hq_url
+ * @property string $title
+ * @property string $description
+ * @property string $thumb_media_id
+ * @property string $format
+ */
+class Music extends Message
+{
+ /**
+ * Messages type.
+ *
+ * @var string
+ */
+ protected $type = 'music';
+
+ /**
+ * Properties.
+ *
+ * @var array
+ */
+ protected $properties = [
+ 'title',
+ 'description',
+ 'url',
+ 'hq_url',
+ 'thumb_media_id',
+ 'format',
+ ];
+
+ /**
+ * Aliases of attribute.
+ *
+ * @var array
+ */
+ protected $jsonAliases = [
+ 'musicurl' => 'url',
+ 'hqmusicurl' => 'hq_url',
+ ];
+
+ public function toXmlArray()
+ {
+ $music = [
+ 'Music' => [
+ 'Title' => $this->get('title'),
+ 'Description' => $this->get('description'),
+ 'MusicUrl' => $this->get('url'),
+ 'HQMusicUrl' => $this->get('hq_url'),
+ ],
+ ];
+ if ($thumbMediaId = $this->get('thumb_media_id')) {
+ $music['Music']['ThumbMediaId'] = $thumbMediaId;
+ }
+
+ return $music;
+ }
+}
diff --git a/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Messages/News.php b/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Messages/News.php
new file mode 100644
index 0000000..2ad46e8
--- /dev/null
+++ b/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Messages/News.php
@@ -0,0 +1,73 @@
+
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace EasyWeChat\Kernel\Messages;
+
+/**
+ * Class News.
+ *
+ * @author overtrue
+ */
+class News extends Message
+{
+ /**
+ * @var string
+ */
+ protected $type = 'news';
+
+ /**
+ * @var array
+ */
+ protected $properties = [
+ 'items',
+ ];
+
+ /**
+ * News constructor.
+ *
+ * @param array $items
+ */
+ public function __construct(array $items = [])
+ {
+ parent::__construct(compact('items'));
+ }
+
+ /**
+ * @param array $data
+ * @param array $aliases
+ *
+ * @return array
+ */
+ public function propertiesToArray(array $data, array $aliases = []): array
+ {
+ return ['articles' => array_map(function ($item) {
+ if ($item instanceof NewsItem) {
+ return $item->toJsonArray();
+ }
+ }, $this->get('items'))];
+ }
+
+ public function toXmlArray()
+ {
+ $items = [];
+
+ foreach ($this->get('items') as $item) {
+ if ($item instanceof NewsItem) {
+ $items[] = $item->toXmlArray();
+ }
+ }
+
+ return [
+ 'ArticleCount' => count($items),
+ 'Articles' => $items,
+ ];
+ }
+}
diff --git a/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Messages/NewsItem.php b/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Messages/NewsItem.php
new file mode 100644
index 0000000..50bf336
--- /dev/null
+++ b/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Messages/NewsItem.php
@@ -0,0 +1,57 @@
+
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace EasyWeChat\Kernel\Messages;
+
+/**
+ * Class NewsItem.
+ */
+class NewsItem extends Message
+{
+ /**
+ * Messages type.
+ *
+ * @var string
+ */
+ protected $type = 'news';
+
+ /**
+ * Properties.
+ *
+ * @var array
+ */
+ protected $properties = [
+ 'title',
+ 'description',
+ 'url',
+ 'image',
+ ];
+
+ public function toJsonArray()
+ {
+ return [
+ 'title' => $this->get('title'),
+ 'description' => $this->get('description'),
+ 'url' => $this->get('url'),
+ 'picurl' => $this->get('image'),
+ ];
+ }
+
+ public function toXmlArray()
+ {
+ return [
+ 'Title' => $this->get('title'),
+ 'Description' => $this->get('description'),
+ 'Url' => $this->get('url'),
+ 'PicUrl' => $this->get('image'),
+ ];
+ }
+}
diff --git a/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Messages/Raw.php b/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Messages/Raw.php
new file mode 100644
index 0000000..53f2a78
--- /dev/null
+++ b/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Messages/Raw.php
@@ -0,0 +1,56 @@
+
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace EasyWeChat\Kernel\Messages;
+
+/**
+ * Class Raw.
+ */
+class Raw extends Message
+{
+ /**
+ * @var string
+ */
+ protected $type = 'raw';
+
+ /**
+ * Properties.
+ *
+ * @var array
+ */
+ protected $properties = ['content'];
+
+ /**
+ * Constructor.
+ *
+ * @param string $content
+ */
+ public function __construct(string $content)
+ {
+ parent::__construct(['content' => strval($content)]);
+ }
+
+ /**
+ * @param array $appends
+ * @param bool $withType
+ *
+ * @return array
+ */
+ public function transformForJsonRequest(array $appends = [], $withType = true): array
+ {
+ return json_decode($this->content, true) ?? [];
+ }
+
+ public function __toString()
+ {
+ return $this->get('content') ?? '';
+ }
+}
diff --git a/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Messages/ShortVideo.php b/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Messages/ShortVideo.php
new file mode 100644
index 0000000..1dc1db9
--- /dev/null
+++ b/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Messages/ShortVideo.php
@@ -0,0 +1,30 @@
+
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace EasyWeChat\Kernel\Messages;
+
+/**
+ * Class ShortVideo.
+ *
+ * @property string $title
+ * @property string $media_id
+ * @property string $description
+ * @property string $thumb_media_id
+ */
+class ShortVideo extends Video
+{
+ /**
+ * Messages type.
+ *
+ * @var string
+ */
+ protected $type = 'shortvideo';
+}
diff --git a/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Messages/TaskCard.php b/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Messages/TaskCard.php
new file mode 100644
index 0000000..d02c411
--- /dev/null
+++ b/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Messages/TaskCard.php
@@ -0,0 +1,44 @@
+
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace EasyWeChat\Kernel\Messages;
+
+/**
+ * Class TaskCard.
+ *
+ * @property string $title
+ * @property string $description
+ * @property string $url
+ * @property string $task_id
+ * @property array $btn
+ */
+class TaskCard extends Message
+{
+ /**
+ * Messages type.
+ *
+ * @var string
+ */
+ protected $type = 'taskcard';
+
+ /**
+ * Properties.
+ *
+ * @var array
+ */
+ protected $properties = [
+ 'title',
+ 'description',
+ 'url',
+ 'task_id',
+ 'btn',
+ ];
+}
diff --git a/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Messages/Text.php b/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Messages/Text.php
new file mode 100644
index 0000000..e355743
--- /dev/null
+++ b/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Messages/Text.php
@@ -0,0 +1,54 @@
+
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace EasyWeChat\Kernel\Messages;
+
+/**
+ * Class Text.
+ *
+ * @property string $content
+ */
+class Text extends Message
+{
+ /**
+ * Message type.
+ *
+ * @var string
+ */
+ protected $type = 'text';
+
+ /**
+ * Properties.
+ *
+ * @var array
+ */
+ protected $properties = ['content'];
+
+ /**
+ * Text constructor.
+ *
+ * @param string $content
+ */
+ public function __construct(string $content)
+ {
+ parent::__construct(compact('content'));
+ }
+
+ /**
+ * @return array
+ */
+ public function toXmlArray()
+ {
+ return [
+ 'Content' => $this->get('content'),
+ ];
+ }
+}
diff --git a/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Messages/TextCard.php b/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Messages/TextCard.php
new file mode 100644
index 0000000..edfb7c5
--- /dev/null
+++ b/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Messages/TextCard.php
@@ -0,0 +1,40 @@
+
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace EasyWeChat\Kernel\Messages;
+
+/**
+ * Class Text.
+ *
+ * @property string $title
+ * @property string $description
+ * @property string $url
+ */
+class TextCard extends Message
+{
+ /**
+ * Messages type.
+ *
+ * @var string
+ */
+ protected $type = 'textcard';
+
+ /**
+ * Properties.
+ *
+ * @var array
+ */
+ protected $properties = [
+ 'title',
+ 'description',
+ 'url',
+ ];
+}
diff --git a/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Messages/Transfer.php b/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Messages/Transfer.php
new file mode 100644
index 0000000..ff27d1a
--- /dev/null
+++ b/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Messages/Transfer.php
@@ -0,0 +1,56 @@
+
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace EasyWeChat\Kernel\Messages;
+
+/**
+ * Class Transfer.
+ *
+ * @property string $to
+ * @property string $account
+ */
+class Transfer extends Message
+{
+ /**
+ * Messages type.
+ *
+ * @var string
+ */
+ protected $type = 'transfer_customer_service';
+
+ /**
+ * Properties.
+ *
+ * @var array
+ */
+ protected $properties = [
+ 'account',
+ ];
+
+ /**
+ * Transfer constructor.
+ *
+ * @param string|null $account
+ */
+ public function __construct(string $account = null)
+ {
+ parent::__construct(compact('account'));
+ }
+
+ public function toXmlArray()
+ {
+ return empty($this->get('account')) ? [] : [
+ 'TransInfo' => [
+ 'KfAccount' => $this->get('account'),
+ ],
+ ];
+ }
+}
diff --git a/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Messages/Video.php b/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Messages/Video.php
new file mode 100644
index 0000000..90f72a0
--- /dev/null
+++ b/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Messages/Video.php
@@ -0,0 +1,65 @@
+
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace EasyWeChat\Kernel\Messages;
+
+/**
+ * Class Video.
+ *
+ * @property string $video
+ * @property string $title
+ * @property string $media_id
+ * @property string $description
+ * @property string $thumb_media_id
+ */
+class Video extends Media
+{
+ /**
+ * Messages type.
+ *
+ * @var string
+ */
+ protected $type = 'video';
+
+ /**
+ * Properties.
+ *
+ * @var array
+ */
+ protected $properties = [
+ 'title',
+ 'description',
+ 'media_id',
+ 'thumb_media_id',
+ ];
+
+ /**
+ * Video constructor.
+ *
+ * @param string $mediaId
+ * @param array $attributes
+ */
+ public function __construct(string $mediaId, array $attributes = [])
+ {
+ parent::__construct($mediaId, 'video', $attributes);
+ }
+
+ public function toXmlArray()
+ {
+ return [
+ 'Video' => [
+ 'MediaId' => $this->get('media_id'),
+ 'Title' => $this->get('title'),
+ 'Description' => $this->get('description'),
+ ],
+ ];
+ }
+}
diff --git a/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Messages/Voice.php b/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Messages/Voice.php
new file mode 100644
index 0000000..ff723ea
--- /dev/null
+++ b/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Messages/Voice.php
@@ -0,0 +1,37 @@
+
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace EasyWeChat\Kernel\Messages;
+
+/**
+ * Class Voice.
+ *
+ * @property string $media_id
+ */
+class Voice extends Media
+{
+ /**
+ * Messages type.
+ *
+ * @var string
+ */
+ protected $type = 'voice';
+
+ /**
+ * Properties.
+ *
+ * @var array
+ */
+ protected $properties = [
+ 'media_id',
+ 'recognition',
+ ];
+}
diff --git a/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Providers/ConfigServiceProvider.php b/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Providers/ConfigServiceProvider.php
new file mode 100644
index 0000000..b33f4a1
--- /dev/null
+++ b/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Providers/ConfigServiceProvider.php
@@ -0,0 +1,39 @@
+
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace EasyWeChat\Kernel\Providers;
+
+use EasyWeChat\Kernel\Config;
+use Pimple\Container;
+use Pimple\ServiceProviderInterface;
+
+/**
+ * Class ConfigServiceProvider.
+ *
+ * @author overtrue
+ */
+class ConfigServiceProvider implements ServiceProviderInterface
+{
+ /**
+ * Registers services on the given container.
+ *
+ * This method should only be used to configure services and parameters.
+ * It should not get services.
+ *
+ * @param Container $pimple A container instance
+ */
+ public function register(Container $pimple)
+ {
+ $pimple['config'] = function ($app) {
+ return new Config($app->getConfig());
+ };
+ }
+}
diff --git a/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Providers/EventDispatcherServiceProvider.php b/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Providers/EventDispatcherServiceProvider.php
new file mode 100644
index 0000000..9095cef
--- /dev/null
+++ b/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Providers/EventDispatcherServiceProvider.php
@@ -0,0 +1,47 @@
+
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace EasyWeChat\Kernel\Providers;
+
+use Pimple\Container;
+use Pimple\ServiceProviderInterface;
+use Symfony\Component\EventDispatcher\EventDispatcher;
+
+/**
+ * Class EventDispatcherServiceProvider.
+ *
+ * @author mingyoung
+ */
+class EventDispatcherServiceProvider implements ServiceProviderInterface
+{
+ /**
+ * Registers services on the given container.
+ *
+ * This method should only be used to configure services and parameters.
+ * It should not get services.
+ *
+ * @param Container $pimple A container instance
+ */
+ public function register(Container $pimple)
+ {
+ $pimple['events'] = function ($app) {
+ $dispatcher = new EventDispatcher();
+
+ foreach ($app->config->get('events.listen', []) as $event => $listeners) {
+ foreach ($listeners as $listener) {
+ $dispatcher->addListener($event, $listener);
+ }
+ }
+
+ return $dispatcher;
+ };
+ }
+}
diff --git a/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Providers/ExtensionServiceProvider.php b/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Providers/ExtensionServiceProvider.php
new file mode 100644
index 0000000..23af832
--- /dev/null
+++ b/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Providers/ExtensionServiceProvider.php
@@ -0,0 +1,39 @@
+
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace EasyWeChat\Kernel\Providers;
+
+use EasyWeChatComposer\Extension;
+use Pimple\Container;
+use Pimple\ServiceProviderInterface;
+
+/**
+ * Class ExtensionServiceProvider.
+ *
+ * @author overtrue
+ */
+class ExtensionServiceProvider implements ServiceProviderInterface
+{
+ /**
+ * Registers services on the given container.
+ *
+ * This method should only be used to configure services and parameters.
+ * It should not get services.
+ *
+ * @param Container $pimple A container instance
+ */
+ public function register(Container $pimple)
+ {
+ $pimple['extension'] = function ($app) {
+ return new Extension($app);
+ };
+ }
+}
diff --git a/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Providers/HttpClientServiceProvider.php b/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Providers/HttpClientServiceProvider.php
new file mode 100644
index 0000000..aca7fa9
--- /dev/null
+++ b/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Providers/HttpClientServiceProvider.php
@@ -0,0 +1,39 @@
+
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace EasyWeChat\Kernel\Providers;
+
+use GuzzleHttp\Client;
+use Pimple\Container;
+use Pimple\ServiceProviderInterface;
+
+/**
+ * Class HttpClientServiceProvider.
+ *
+ * @author overtrue
+ */
+class HttpClientServiceProvider implements ServiceProviderInterface
+{
+ /**
+ * Registers services on the given container.
+ *
+ * This method should only be used to configure services and parameters.
+ * It should not get services.
+ *
+ * @param Container $pimple A container instance
+ */
+ public function register(Container $pimple)
+ {
+ $pimple['http_client'] = function ($app) {
+ return new Client($app['config']->get('http', []));
+ };
+ }
+}
diff --git a/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Providers/LogServiceProvider.php b/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Providers/LogServiceProvider.php
new file mode 100644
index 0000000..83498ac
--- /dev/null
+++ b/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Providers/LogServiceProvider.php
@@ -0,0 +1,79 @@
+
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace EasyWeChat\Kernel\Providers;
+
+use EasyWeChat\Kernel\Log\LogManager;
+use Pimple\Container;
+use Pimple\ServiceProviderInterface;
+
+/**
+ * Class LoggingServiceProvider.
+ *
+ * @author overtrue
+ */
+class LogServiceProvider implements ServiceProviderInterface
+{
+ /**
+ * Registers services on the given container.
+ *
+ * This method should only be used to configure services and parameters.
+ * It should not get services.
+ *
+ * @param Container $pimple A container instance
+ */
+ public function register(Container $pimple)
+ {
+ $pimple['logger'] = $pimple['log'] = function ($app) {
+ $config = $this->formatLogConfig($app);
+
+ if (!empty($config)) {
+ $app->rebind('config', $app['config']->merge($config));
+ }
+
+ return new LogManager($app);
+ };
+ }
+
+ public function formatLogConfig($app)
+ {
+ if (!empty($app['config']->get('log.channels'))) {
+ return $app['config']->get('log');
+ }
+
+ if (empty($app['config']->get('log'))) {
+ return [
+ 'log' => [
+ 'default' => 'errorlog',
+ 'channels' => [
+ 'errorlog' => [
+ 'driver' => 'errorlog',
+ 'level' => 'debug',
+ ],
+ ],
+ ],
+ ];
+ }
+
+ return [
+ 'log' => [
+ 'default' => 'single',
+ 'channels' => [
+ 'single' => [
+ 'driver' => 'single',
+ 'path' => $app['config']->get('log.file') ?: \sys_get_temp_dir().'/logs/easywechat.log',
+ 'level' => $app['config']->get('log.level', 'debug'),
+ ],
+ ],
+ ],
+ ];
+ }
+}
diff --git a/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Providers/RequestServiceProvider.php b/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Providers/RequestServiceProvider.php
new file mode 100644
index 0000000..a0b111d
--- /dev/null
+++ b/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Providers/RequestServiceProvider.php
@@ -0,0 +1,39 @@
+
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace EasyWeChat\Kernel\Providers;
+
+use Pimple\Container;
+use Pimple\ServiceProviderInterface;
+use Symfony\Component\HttpFoundation\Request;
+
+/**
+ * Class RequestServiceProvider.
+ *
+ * @author overtrue
+ */
+class RequestServiceProvider implements ServiceProviderInterface
+{
+ /**
+ * Registers services on the given container.
+ *
+ * This method should only be used to configure services and parameters.
+ * It should not get services.
+ *
+ * @param Container $pimple A container instance
+ */
+ public function register(Container $pimple)
+ {
+ $pimple['request'] = function () {
+ return Request::createFromGlobals();
+ };
+ }
+}
diff --git a/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/ServerGuard.php b/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/ServerGuard.php
new file mode 100644
index 0000000..c135e12
--- /dev/null
+++ b/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/ServerGuard.php
@@ -0,0 +1,375 @@
+
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace EasyWeChat\Kernel;
+
+use EasyWeChat\Kernel\Contracts\MessageInterface;
+use EasyWeChat\Kernel\Exceptions\BadRequestException;
+use EasyWeChat\Kernel\Exceptions\InvalidArgumentException;
+use EasyWeChat\Kernel\Messages\Message;
+use EasyWeChat\Kernel\Messages\News;
+use EasyWeChat\Kernel\Messages\NewsItem;
+use EasyWeChat\Kernel\Messages\Raw as RawMessage;
+use EasyWeChat\Kernel\Messages\Text;
+use EasyWeChat\Kernel\Support\XML;
+use EasyWeChat\Kernel\Traits\Observable;
+use EasyWeChat\Kernel\Traits\ResponseCastable;
+use Symfony\Component\HttpFoundation\Response;
+
+/**
+ * Class ServerGuard.
+ *
+ * 1. url 里的 signature 只是将 token+nonce+timestamp 得到的签名,只是用于验证当前请求的,在公众号环境下一直有
+ * 2. 企业号消息发送时是没有的,因为固定为完全模式,所以 url 里不会存在 signature, 只有 msg_signature 用于解密消息的
+ *
+ * @author overtrue
+ */
+class ServerGuard
+{
+ use Observable;
+ use ResponseCastable;
+
+ /**
+ * @var bool
+ */
+ protected $alwaysValidate = false;
+
+ /**
+ * Empty string.
+ */
+ const SUCCESS_EMPTY_RESPONSE = 'success';
+
+ /**
+ * @var array
+ */
+ const MESSAGE_TYPE_MAPPING = [
+ 'text' => Message::TEXT,
+ 'image' => Message::IMAGE,
+ 'voice' => Message::VOICE,
+ 'video' => Message::VIDEO,
+ 'shortvideo' => Message::SHORT_VIDEO,
+ 'location' => Message::LOCATION,
+ 'link' => Message::LINK,
+ 'device_event' => Message::DEVICE_EVENT,
+ 'device_text' => Message::DEVICE_TEXT,
+ 'event' => Message::EVENT,
+ 'file' => Message::FILE,
+ 'miniprogrampage' => Message::MINIPROGRAM_PAGE,
+ ];
+
+ /**
+ * @var \EasyWeChat\Kernel\ServiceContainer
+ */
+ protected $app;
+
+ /**
+ * Constructor.
+ *
+ * @codeCoverageIgnore
+ *
+ * @param \EasyWeChat\Kernel\ServiceContainer $app
+ */
+ public function __construct(ServiceContainer $app)
+ {
+ $this->app = $app;
+
+ foreach ($this->app->extension->observers() as $observer) {
+ call_user_func_array([$this, 'push'], $observer);
+ }
+ }
+
+ /**
+ * Handle and return response.
+ *
+ * @return Response
+ *
+ * @throws BadRequestException
+ * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
+ * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
+ */
+ public function serve(): Response
+ {
+ $this->app['logger']->debug('Request received:', [
+ 'method' => $this->app['request']->getMethod(),
+ 'uri' => $this->app['request']->getUri(),
+ 'content-type' => $this->app['request']->getContentType(),
+ 'content' => $this->app['request']->getContent(),
+ ]);
+
+ $response = $this->validate()->resolve();
+
+ $this->app['logger']->debug('Server response created:', ['content' => $response->getContent()]);
+
+ return $response;
+ }
+
+ /**
+ * @return $this
+ *
+ * @throws \EasyWeChat\Kernel\Exceptions\BadRequestException
+ */
+ public function validate()
+ {
+ if (!$this->alwaysValidate && !$this->isSafeMode()) {
+ return $this;
+ }
+
+ if ($this->app['request']->get('signature') !== $this->signature([
+ $this->getToken(),
+ $this->app['request']->get('timestamp'),
+ $this->app['request']->get('nonce'),
+ ])) {
+ throw new BadRequestException('Invalid request signature.', 400);
+ }
+
+ return $this;
+ }
+
+ /**
+ * Force validate request.
+ *
+ * @return $this
+ */
+ public function forceValidate()
+ {
+ $this->alwaysValidate = true;
+
+ return $this;
+ }
+
+ /**
+ * Get request message.
+ *
+ * @return array|\EasyWeChat\Kernel\Support\Collection|object|string
+ *
+ * @throws BadRequestException
+ * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
+ * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
+ */
+ public function getMessage()
+ {
+ $message = $this->parseMessage($this->app['request']->getContent(false));
+
+ if (!is_array($message) || empty($message)) {
+ throw new BadRequestException('No message received.');
+ }
+
+ if ($this->isSafeMode() && !empty($message['Encrypt'])) {
+ $message = $this->decryptMessage($message);
+
+ // Handle JSON format.
+ $dataSet = json_decode($message, true);
+
+ if ($dataSet && (JSON_ERROR_NONE === json_last_error())) {
+ return $dataSet;
+ }
+
+ $message = XML::parse($message);
+ }
+
+ return $this->detectAndCastResponseToType($message, $this->app->config->get('response_type'));
+ }
+
+ /**
+ * Resolve server request and return the response.
+ *
+ * @return \Symfony\Component\HttpFoundation\Response
+ *
+ * @throws \EasyWeChat\Kernel\Exceptions\BadRequestException
+ * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
+ * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
+ */
+ protected function resolve(): Response
+ {
+ $result = $this->handleRequest();
+
+ if ($this->shouldReturnRawResponse()) {
+ $response = new Response($result['response']);
+ } else {
+ $response = new Response(
+ $this->buildResponse($result['to'], $result['from'], $result['response']),
+ 200,
+ ['Content-Type' => 'application/xml']
+ );
+ }
+
+ $this->app->events->dispatch(new Events\ServerGuardResponseCreated($response));
+
+ return $response;
+ }
+
+ /**
+ * @return string|null
+ */
+ protected function getToken()
+ {
+ return $this->app['config']['token'];
+ }
+
+ /**
+ * @param string $to
+ * @param string $from
+ * @param \EasyWeChat\Kernel\Contracts\MessageInterface|string|int $message
+ *
+ * @return string
+ *
+ * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
+ */
+ public function buildResponse(string $to, string $from, $message)
+ {
+ if (empty($message) || self::SUCCESS_EMPTY_RESPONSE === $message) {
+ return self::SUCCESS_EMPTY_RESPONSE;
+ }
+
+ if ($message instanceof RawMessage) {
+ return $message->get('content', self::SUCCESS_EMPTY_RESPONSE);
+ }
+
+ if (is_string($message) || is_numeric($message)) {
+ $message = new Text((string) $message);
+ }
+
+ if (is_array($message) && reset($message) instanceof NewsItem) {
+ $message = new News($message);
+ }
+
+ if (!($message instanceof Message)) {
+ throw new InvalidArgumentException(sprintf('Invalid Messages type "%s".', gettype($message)));
+ }
+
+ return $this->buildReply($to, $from, $message);
+ }
+
+ /**
+ * Handle request.
+ *
+ * @return array
+ *
+ * @throws \EasyWeChat\Kernel\Exceptions\BadRequestException
+ * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
+ * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
+ */
+ protected function handleRequest(): array
+ {
+ $castedMessage = $this->getMessage();
+
+ $messageArray = $this->detectAndCastResponseToType($castedMessage, 'array');
+
+ $response = $this->dispatch(self::MESSAGE_TYPE_MAPPING[$messageArray['MsgType'] ?? $messageArray['msg_type'] ?? 'text'], $castedMessage);
+
+ return [
+ 'to' => $messageArray['FromUserName'] ?? '',
+ 'from' => $messageArray['ToUserName'] ?? '',
+ 'response' => $response,
+ ];
+ }
+
+ /**
+ * Build reply XML.
+ *
+ * @param string $to
+ * @param string $from
+ * @param \EasyWeChat\Kernel\Contracts\MessageInterface $message
+ *
+ * @return string
+ */
+ protected function buildReply(string $to, string $from, MessageInterface $message): string
+ {
+ $prepends = [
+ 'ToUserName' => $to,
+ 'FromUserName' => $from,
+ 'CreateTime' => time(),
+ 'MsgType' => $message->getType(),
+ ];
+
+ $response = $message->transformToXml($prepends);
+
+ if ($this->isSafeMode()) {
+ $this->app['logger']->debug('Messages safe mode is enabled.');
+ $response = $this->app['encryptor']->encrypt($response);
+ }
+
+ return $response;
+ }
+
+ /**
+ * @param array $params
+ *
+ * @return string
+ */
+ protected function signature(array $params)
+ {
+ sort($params, SORT_STRING);
+
+ return sha1(implode($params));
+ }
+
+ /**
+ * Parse message array from raw php input.
+ *
+ * @param string $content
+ *
+ * @return array
+ *
+ * @throws \EasyWeChat\Kernel\Exceptions\BadRequestException
+ */
+ protected function parseMessage($content)
+ {
+ try {
+ if (0 === stripos($content, '<')) {
+ $content = XML::parse($content);
+ } else {
+ // Handle JSON format.
+ $dataSet = json_decode($content, true);
+ if ($dataSet && (JSON_ERROR_NONE === json_last_error())) {
+ $content = $dataSet;
+ }
+ }
+
+ return (array) $content;
+ } catch (\Exception $e) {
+ throw new BadRequestException(sprintf('Invalid message content:(%s) %s', $e->getCode(), $e->getMessage()), $e->getCode());
+ }
+ }
+
+ /**
+ * Check the request message safe mode.
+ *
+ * @return bool
+ */
+ protected function isSafeMode(): bool
+ {
+ return $this->app['request']->get('signature') && 'aes' === $this->app['request']->get('encrypt_type');
+ }
+
+ /**
+ * @return bool
+ */
+ protected function shouldReturnRawResponse(): bool
+ {
+ return false;
+ }
+
+ /**
+ * @param array $message
+ *
+ * @return mixed
+ */
+ protected function decryptMessage(array $message)
+ {
+ return $message = $this->app['encryptor']->decrypt(
+ $message['Encrypt'],
+ $this->app['request']->get('msg_signature'),
+ $this->app['request']->get('nonce'),
+ $this->app['request']->get('timestamp')
+ );
+ }
+}
diff --git a/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/ServiceContainer.php b/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/ServiceContainer.php
new file mode 100644
index 0000000..af1f35b
--- /dev/null
+++ b/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/ServiceContainer.php
@@ -0,0 +1,167 @@
+
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace EasyWeChat\Kernel;
+
+use EasyWeChat\Kernel\Providers\ConfigServiceProvider;
+use EasyWeChat\Kernel\Providers\EventDispatcherServiceProvider;
+use EasyWeChat\Kernel\Providers\ExtensionServiceProvider;
+use EasyWeChat\Kernel\Providers\HttpClientServiceProvider;
+use EasyWeChat\Kernel\Providers\LogServiceProvider;
+use EasyWeChat\Kernel\Providers\RequestServiceProvider;
+use EasyWeChatComposer\Traits\WithAggregator;
+use Pimple\Container;
+
+/**
+ * Class ServiceContainer.
+ *
+ * @author overtrue
+ *
+ * @property \EasyWeChat\Kernel\Config $config
+ * @property \Symfony\Component\HttpFoundation\Request $request
+ * @property \GuzzleHttp\Client $http_client
+ * @property \Monolog\Logger $logger
+ * @property \Symfony\Component\EventDispatcher\EventDispatcher $events
+ */
+class ServiceContainer extends Container
+{
+ use WithAggregator;
+
+ /**
+ * @var string
+ */
+ protected $id;
+
+ /**
+ * @var array
+ */
+ protected $providers = [];
+
+ /**
+ * @var array
+ */
+ protected $defaultConfig = [];
+
+ /**
+ * @var array
+ */
+ protected $userConfig = [];
+
+ /**
+ * Constructor.
+ *
+ * @param array $config
+ * @param array $prepends
+ * @param string|null $id
+ */
+ public function __construct(array $config = [], array $prepends = [], string $id = null)
+ {
+ $this->registerProviders($this->getProviders());
+
+ parent::__construct($prepends);
+
+ $this->userConfig = $config;
+
+ $this->id = $id;
+
+ $this->aggregate();
+
+ $this->events->dispatch(new Events\ApplicationInitialized($this));
+ }
+
+ /**
+ * @return string
+ */
+ public function getId()
+ {
+ return $this->id ?? $this->id = md5(json_encode($this->userConfig));
+ }
+
+ /**
+ * @return array
+ */
+ public function getConfig()
+ {
+ $base = [
+ // http://docs.guzzlephp.org/en/stable/request-options.html
+ 'http' => [
+ 'timeout' => 30.0,
+ 'base_uri' => 'https://api.weixin.qq.com/',
+ ],
+ ];
+
+ return array_replace_recursive($base, $this->defaultConfig, $this->userConfig);
+ }
+
+ /**
+ * Return all providers.
+ *
+ * @return array
+ */
+ public function getProviders()
+ {
+ return array_merge([
+ ConfigServiceProvider::class,
+ LogServiceProvider::class,
+ RequestServiceProvider::class,
+ HttpClientServiceProvider::class,
+ ExtensionServiceProvider::class,
+ EventDispatcherServiceProvider::class,
+ ], $this->providers);
+ }
+
+ /**
+ * @param string $id
+ * @param mixed $value
+ */
+ public function rebind($id, $value)
+ {
+ $this->offsetUnset($id);
+ $this->offsetSet($id, $value);
+ }
+
+ /**
+ * Magic get access.
+ *
+ * @param string $id
+ *
+ * @return mixed
+ */
+ public function __get($id)
+ {
+ if ($this->shouldDelegate($id)) {
+ return $this->delegateTo($id);
+ }
+
+ return $this->offsetGet($id);
+ }
+
+ /**
+ * Magic set access.
+ *
+ * @param string $id
+ * @param mixed $value
+ */
+ public function __set($id, $value)
+ {
+ $this->offsetSet($id, $value);
+ }
+
+ /**
+ * @param array $providers
+ */
+ public function registerProviders(array $providers)
+ {
+ foreach ($providers as $provider) {
+ parent::register(new $provider());
+ }
+ }
+}
diff --git a/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Support/AES.php b/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Support/AES.php
new file mode 100644
index 0000000..73b1b24
--- /dev/null
+++ b/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Support/AES.php
@@ -0,0 +1,85 @@
+
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace EasyWeChat\Kernel\Support;
+
+/**
+ * Class AES.
+ *
+ * @author overtrue
+ */
+class AES
+{
+ /**
+ * @param string $text
+ * @param string $key
+ * @param string $iv
+ * @param int $option
+ *
+ * @return string
+ */
+ public static function encrypt(string $text, string $key, string $iv, int $option = OPENSSL_RAW_DATA): string
+ {
+ self::validateKey($key);
+ self::validateIv($iv);
+
+ return openssl_encrypt($text, self::getMode($key), $key, $option, $iv);
+ }
+
+ /**
+ * @param string $cipherText
+ * @param string $key
+ * @param string $iv
+ * @param int $option
+ * @param string|null $method
+ *
+ * @return string
+ */
+ public static function decrypt(string $cipherText, string $key, string $iv, int $option = OPENSSL_RAW_DATA, $method = null): string
+ {
+ self::validateKey($key);
+ self::validateIv($iv);
+
+ return openssl_decrypt($cipherText, $method ?: self::getMode($key), $key, $option, $iv);
+ }
+
+ /**
+ * @param string $key
+ *
+ * @return string
+ */
+ public static function getMode($key)
+ {
+ return 'aes-'.(8 * strlen($key)).'-cbc';
+ }
+
+ /**
+ * @param string $key
+ */
+ public static function validateKey(string $key)
+ {
+ if (!in_array(strlen($key), [16, 24, 32], true)) {
+ throw new \InvalidArgumentException(sprintf('Key length must be 16, 24, or 32 bytes; got key len (%s).', strlen($key)));
+ }
+ }
+
+ /**
+ * @param string $iv
+ *
+ * @throws \InvalidArgumentException
+ */
+ public static function validateIv(string $iv)
+ {
+ if (!empty($iv) && 16 !== strlen($iv)) {
+ throw new \InvalidArgumentException('IV length must be 16 bytes.');
+ }
+ }
+}
diff --git a/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Support/Arr.php b/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Support/Arr.php
new file mode 100644
index 0000000..ac34038
--- /dev/null
+++ b/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Support/Arr.php
@@ -0,0 +1,466 @@
+
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace EasyWeChat\Kernel\Support;
+
+/**
+ * Array helper from Illuminate\Support\Arr.
+ */
+class Arr
+{
+ /**
+ * Add an element to an array using "dot" notation if it doesn't exist.
+ *
+ * @param array $array
+ * @param string $key
+ * @param mixed $value
+ *
+ * @return array
+ */
+ public static function add(array $array, $key, $value)
+ {
+ if (is_null(static::get($array, $key))) {
+ static::set($array, $key, $value);
+ }
+
+ return $array;
+ }
+
+ /**
+ * Cross join the given arrays, returning all possible permutations.
+ *
+ * @param array ...$arrays
+ *
+ * @return array
+ */
+ public static function crossJoin(...$arrays)
+ {
+ $results = [[]];
+
+ foreach ($arrays as $index => $array) {
+ $append = [];
+
+ foreach ($results as $product) {
+ foreach ($array as $item) {
+ $product[$index] = $item;
+
+ $append[] = $product;
+ }
+ }
+
+ $results = $append;
+ }
+
+ return $results;
+ }
+
+ /**
+ * Divide an array into two arrays. One with keys and the other with values.
+ *
+ * @param array $array
+ *
+ * @return array
+ */
+ public static function divide(array $array)
+ {
+ return [array_keys($array), array_values($array)];
+ }
+
+ /**
+ * Flatten a multi-dimensional associative array with dots.
+ *
+ * @param array $array
+ * @param string $prepend
+ *
+ * @return array
+ */
+ public static function dot(array $array, $prepend = '')
+ {
+ $results = [];
+
+ foreach ($array as $key => $value) {
+ if (is_array($value) && !empty($value)) {
+ $results = array_merge($results, static::dot($value, $prepend.$key.'.'));
+ } else {
+ $results[$prepend.$key] = $value;
+ }
+ }
+
+ return $results;
+ }
+
+ /**
+ * Get all of the given array except for a specified array of items.
+ *
+ * @param array $array
+ * @param array|string $keys
+ *
+ * @return array
+ */
+ public static function except(array $array, $keys)
+ {
+ static::forget($array, $keys);
+
+ return $array;
+ }
+
+ /**
+ * Determine if the given key exists in the provided array.
+ *
+ * @param array $array
+ * @param string|int $key
+ *
+ * @return bool
+ */
+ public static function exists(array $array, $key)
+ {
+ return array_key_exists($key, $array);
+ }
+
+ /**
+ * Return the first element in an array passing a given truth test.
+ *
+ * @param array $array
+ * @param callable|null $callback
+ * @param mixed $default
+ *
+ * @return mixed
+ */
+ public static function first(array $array, callable $callback = null, $default = null)
+ {
+ if (is_null($callback)) {
+ if (empty($array)) {
+ return $default;
+ }
+
+ foreach ($array as $item) {
+ return $item;
+ }
+ }
+
+ foreach ($array as $key => $value) {
+ if (call_user_func($callback, $value, $key)) {
+ return $value;
+ }
+ }
+
+ return $default;
+ }
+
+ /**
+ * Return the last element in an array passing a given truth test.
+ *
+ * @param array $array
+ * @param callable|null $callback
+ * @param mixed $default
+ *
+ * @return mixed
+ */
+ public static function last(array $array, callable $callback = null, $default = null)
+ {
+ if (is_null($callback)) {
+ return empty($array) ? $default : end($array);
+ }
+
+ return static::first(array_reverse($array, true), $callback, $default);
+ }
+
+ /**
+ * Flatten a multi-dimensional array into a single level.
+ *
+ * @param array $array
+ * @param int $depth
+ *
+ * @return array
+ */
+ public static function flatten(array $array, $depth = INF)
+ {
+ return array_reduce($array, function ($result, $item) use ($depth) {
+ $item = $item instanceof Collection ? $item->all() : $item;
+
+ if (!is_array($item)) {
+ return array_merge($result, [$item]);
+ } elseif (1 === $depth) {
+ return array_merge($result, array_values($item));
+ }
+
+ return array_merge($result, static::flatten($item, $depth - 1));
+ }, []);
+ }
+
+ /**
+ * Remove one or many array items from a given array using "dot" notation.
+ *
+ * @param array $array
+ * @param array|string $keys
+ */
+ public static function forget(array &$array, $keys)
+ {
+ $original = &$array;
+
+ $keys = (array) $keys;
+
+ if (0 === count($keys)) {
+ return;
+ }
+
+ foreach ($keys as $key) {
+ // if the exact key exists in the top-level, remove it
+ if (static::exists($array, $key)) {
+ unset($array[$key]);
+
+ continue;
+ }
+
+ $parts = explode('.', $key);
+
+ // clean up before each pass
+ $array = &$original;
+
+ while (count($parts) > 1) {
+ $part = array_shift($parts);
+
+ if (isset($array[$part]) && is_array($array[$part])) {
+ $array = &$array[$part];
+ } else {
+ continue 2;
+ }
+ }
+
+ unset($array[array_shift($parts)]);
+ }
+ }
+
+ /**
+ * Get an item from an array using "dot" notation.
+ *
+ * @param array $array
+ * @param string $key
+ * @param mixed $default
+ *
+ * @return mixed
+ */
+ public static function get(array $array, $key, $default = null)
+ {
+ if (is_null($key)) {
+ return $array;
+ }
+
+ if (static::exists($array, $key)) {
+ return $array[$key];
+ }
+
+ foreach (explode('.', $key) as $segment) {
+ if (static::exists($array, $segment)) {
+ $array = $array[$segment];
+ } else {
+ return $default;
+ }
+ }
+
+ return $array;
+ }
+
+ /**
+ * Check if an item or items exist in an array using "dot" notation.
+ *
+ * @param array $array
+ * @param string|array $keys
+ *
+ * @return bool
+ */
+ public static function has(array $array, $keys)
+ {
+ if (is_null($keys)) {
+ return false;
+ }
+
+ $keys = (array) $keys;
+
+ if (empty($array)) {
+ return false;
+ }
+
+ if ($keys === []) {
+ return false;
+ }
+
+ foreach ($keys as $key) {
+ $subKeyArray = $array;
+
+ if (static::exists($array, $key)) {
+ continue;
+ }
+
+ foreach (explode('.', $key) as $segment) {
+ if (static::exists($subKeyArray, $segment)) {
+ $subKeyArray = $subKeyArray[$segment];
+ } else {
+ return false;
+ }
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * Determines if an array is associative.
+ *
+ * An array is "associative" if it doesn't have sequential numerical keys beginning with zero.
+ *
+ * @param array $array
+ *
+ * @return bool
+ */
+ public static function isAssoc(array $array)
+ {
+ $keys = array_keys($array);
+
+ return array_keys($keys) !== $keys;
+ }
+
+ /**
+ * Get a subset of the items from the given array.
+ *
+ * @param array $array
+ * @param array|string $keys
+ *
+ * @return array
+ */
+ public static function only(array $array, $keys)
+ {
+ return array_intersect_key($array, array_flip((array) $keys));
+ }
+
+ /**
+ * Push an item onto the beginning of an array.
+ *
+ * @param array $array
+ * @param mixed $value
+ * @param mixed $key
+ *
+ * @return array
+ */
+ public static function prepend(array $array, $value, $key = null)
+ {
+ if (is_null($key)) {
+ array_unshift($array, $value);
+ } else {
+ $array = [$key => $value] + $array;
+ }
+
+ return $array;
+ }
+
+ /**
+ * Get a value from the array, and remove it.
+ *
+ * @param array $array
+ * @param string $key
+ * @param mixed $default
+ *
+ * @return mixed
+ */
+ public static function pull(array &$array, $key, $default = null)
+ {
+ $value = static::get($array, $key, $default);
+
+ static::forget($array, $key);
+
+ return $value;
+ }
+
+ /**
+ * Get a 1 value from an array.
+ *
+ * @param array $array
+ * @param int|null $amount
+ *
+ * @return mixed
+ *
+ * @throws \InvalidArgumentException
+ */
+ public static function random(array $array, int $amount = null)
+ {
+ if (is_null($amount)) {
+ return $array[array_rand($array)];
+ }
+
+ $keys = array_rand($array, $amount);
+
+ $results = [];
+
+ foreach ((array) $keys as $key) {
+ $results[] = $array[$key];
+ }
+
+ return $results;
+ }
+
+ /**
+ * Set an array item to a given value using "dot" notation.
+ *
+ * If no key is given to the method, the entire array will be replaced.
+ *
+ * @param array $array
+ * @param string $key
+ * @param mixed $value
+ *
+ * @return array
+ */
+ public static function set(array &$array, string $key, $value)
+ {
+ $keys = explode('.', $key);
+
+ while (count($keys) > 1) {
+ $key = array_shift($keys);
+
+ // If the key doesn't exist at this depth, we will just create an empty array
+ // to hold the next value, allowing us to create the arrays to hold final
+ // values at the correct depth. Then we'll keep digging into the array.
+ if (!isset($array[$key]) || !is_array($array[$key])) {
+ $array[$key] = [];
+ }
+
+ $array = &$array[$key];
+ }
+
+ $array[array_shift($keys)] = $value;
+
+ return $array;
+ }
+
+ /**
+ * Filter the array using the given callback.
+ *
+ * @param array $array
+ * @param callable $callback
+ *
+ * @return array
+ */
+ public static function where(array $array, callable $callback)
+ {
+ return array_filter($array, $callback, ARRAY_FILTER_USE_BOTH);
+ }
+
+ /**
+ * If the given value is not an array, wrap it in one.
+ *
+ * @param mixed $value
+ *
+ * @return array
+ */
+ public static function wrap($value)
+ {
+ return !is_array($value) ? [$value] : $value;
+ }
+}
diff --git a/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Support/ArrayAccessible.php b/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Support/ArrayAccessible.php
new file mode 100644
index 0000000..72e0b04
--- /dev/null
+++ b/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Support/ArrayAccessible.php
@@ -0,0 +1,66 @@
+
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace EasyWeChat\Kernel\Support;
+
+use ArrayAccess;
+use ArrayIterator;
+use EasyWeChat\Kernel\Contracts\Arrayable;
+use IteratorAggregate;
+
+/**
+ * Class ArrayAccessible.
+ *
+ * @author overtrue
+ */
+class ArrayAccessible implements ArrayAccess, IteratorAggregate, Arrayable
+{
+ private $array;
+
+ public function __construct(array $array = [])
+ {
+ $this->array = $array;
+ }
+
+ public function offsetExists($offset)
+ {
+ return array_key_exists($offset, $this->array);
+ }
+
+ public function offsetGet($offset)
+ {
+ return $this->array[$offset];
+ }
+
+ public function offsetSet($offset, $value)
+ {
+ if (null === $offset) {
+ $this->array[] = $value;
+ } else {
+ $this->array[$offset] = $value;
+ }
+ }
+
+ public function offsetUnset($offset)
+ {
+ unset($this->array[$offset]);
+ }
+
+ public function getIterator()
+ {
+ return new ArrayIterator($this->array);
+ }
+
+ public function toArray()
+ {
+ return $this->array;
+ }
+}
diff --git a/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Support/Collection.php b/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Support/Collection.php
new file mode 100644
index 0000000..adf24ea
--- /dev/null
+++ b/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Support/Collection.php
@@ -0,0 +1,421 @@
+
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace EasyWeChat\Kernel\Support;
+
+use ArrayAccess;
+use ArrayIterator;
+use Countable;
+use EasyWeChat\Kernel\Contracts\Arrayable;
+use IteratorAggregate;
+use JsonSerializable;
+use Serializable;
+
+/**
+ * Class Collection.
+ */
+class Collection implements ArrayAccess, Countable, IteratorAggregate, JsonSerializable, Serializable, Arrayable
+{
+ /**
+ * The collection data.
+ *
+ * @var array
+ */
+ protected $items = [];
+
+ /**
+ * set data.
+ *
+ * @param array $items
+ */
+ public function __construct(array $items = [])
+ {
+ foreach ($items as $key => $value) {
+ $this->set($key, $value);
+ }
+ }
+
+ /**
+ * Return all items.
+ *
+ * @return array
+ */
+ public function all()
+ {
+ return $this->items;
+ }
+
+ /**
+ * Return specific items.
+ *
+ * @param array $keys
+ *
+ * @return \EasyWeChat\Kernel\Support\Collection
+ */
+ public function only(array $keys)
+ {
+ $return = [];
+
+ foreach ($keys as $key) {
+ $value = $this->get($key);
+
+ if (!is_null($value)) {
+ $return[$key] = $value;
+ }
+ }
+
+ return new static($return);
+ }
+
+ /**
+ * Get all items except for those with the specified keys.
+ *
+ * @param mixed $keys
+ *
+ * @return static
+ */
+ public function except($keys)
+ {
+ $keys = is_array($keys) ? $keys : func_get_args();
+
+ return new static(Arr::except($this->items, $keys));
+ }
+
+ /**
+ * Merge data.
+ *
+ * @param Collection|array $items
+ *
+ * @return \EasyWeChat\Kernel\Support\Collection
+ */
+ public function merge($items)
+ {
+ $clone = new static($this->all());
+
+ foreach ($items as $key => $value) {
+ $clone->set($key, $value);
+ }
+
+ return $clone;
+ }
+
+ /**
+ * To determine Whether the specified element exists.
+ *
+ * @param string $key
+ *
+ * @return bool
+ */
+ public function has($key)
+ {
+ return !is_null(Arr::get($this->items, $key));
+ }
+
+ /**
+ * Retrieve the first item.
+ *
+ * @return mixed
+ */
+ public function first()
+ {
+ return reset($this->items);
+ }
+
+ /**
+ * Retrieve the last item.
+ *
+ * @return bool
+ */
+ public function last()
+ {
+ $end = end($this->items);
+
+ reset($this->items);
+
+ return $end;
+ }
+
+ /**
+ * add the item value.
+ *
+ * @param string $key
+ * @param mixed $value
+ */
+ public function add($key, $value)
+ {
+ Arr::set($this->items, $key, $value);
+ }
+
+ /**
+ * Set the item value.
+ *
+ * @param string $key
+ * @param mixed $value
+ */
+ public function set($key, $value)
+ {
+ Arr::set($this->items, $key, $value);
+ }
+
+ /**
+ * Retrieve item from Collection.
+ *
+ * @param string $key
+ * @param mixed $default
+ *
+ * @return mixed
+ */
+ public function get($key, $default = null)
+ {
+ return Arr::get($this->items, $key, $default);
+ }
+
+ /**
+ * Remove item form Collection.
+ *
+ * @param string $key
+ */
+ public function forget($key)
+ {
+ Arr::forget($this->items, $key);
+ }
+
+ /**
+ * Build to array.
+ *
+ * @return array
+ */
+ public function toArray()
+ {
+ return $this->all();
+ }
+
+ /**
+ * Build to json.
+ *
+ * @param int $option
+ *
+ * @return string
+ */
+ public function toJson($option = JSON_UNESCAPED_UNICODE)
+ {
+ return json_encode($this->all(), $option);
+ }
+
+ /**
+ * To string.
+ *
+ * @return string
+ */
+ public function __toString()
+ {
+ return $this->toJson();
+ }
+
+ /**
+ * (PHP 5 >= 5.4.0)
+ * Specify data which should be serialized to JSON.
+ *
+ * @see http://php.net/manual/en/jsonserializable.jsonserialize.php
+ *
+ * @return mixed data which can be serialized by json_encode,
+ * which is a value of any type other than a resource
+ */
+ public function jsonSerialize()
+ {
+ return $this->items;
+ }
+
+ /**
+ * (PHP 5 >= 5.1.0)
+ * String representation of object.
+ *
+ * @see http://php.net/manual/en/serializable.serialize.php
+ *
+ * @return string the string representation of the object or null
+ */
+ public function serialize()
+ {
+ return serialize($this->items);
+ }
+
+ /**
+ * (PHP 5 >= 5.0.0)
+ * Retrieve an external iterator.
+ *
+ * @see http://php.net/manual/en/iteratoraggregate.getiterator.php
+ *
+ * @return \ArrayIterator An instance of an object implementing Iterator or
+ * Traversable
+ */
+ public function getIterator()
+ {
+ return new ArrayIterator($this->items);
+ }
+
+ /**
+ * (PHP 5 >= 5.1.0)
+ * Count elements of an object.
+ *
+ * @see http://php.net/manual/en/countable.count.php
+ *
+ * @return int the custom count as an integer.
+ *
+ *
+ * The return value is cast to an integer
+ */
+ public function count()
+ {
+ return count($this->items);
+ }
+
+ /**
+ * (PHP 5 >= 5.1.0)
+ * Constructs the object.
+ *
+ * @see http://php.net/manual/en/serializable.unserialize.php
+ *
+ * @param string $serialized
+ * The string representation of the object.
+ *
+ *
+ * @return mixed|void
+ */
+ public function unserialize($serialized)
+ {
+ return $this->items = unserialize($serialized);
+ }
+
+ /**
+ * Get a data by key.
+ *
+ * @param string $key
+ *
+ * @return mixed
+ */
+ public function __get($key)
+ {
+ return $this->get($key);
+ }
+
+ /**
+ * Assigns a value to the specified data.
+ *
+ * @param string $key
+ * @param mixed $value
+ */
+ public function __set($key, $value)
+ {
+ $this->set($key, $value);
+ }
+
+ /**
+ * Whether or not an data exists by key.
+ *
+ * @param string $key
+ *
+ * @return bool
+ */
+ public function __isset($key)
+ {
+ return $this->has($key);
+ }
+
+ /**
+ * Unset an data by key.
+ *
+ * @param string $key
+ */
+ public function __unset($key)
+ {
+ $this->forget($key);
+ }
+
+ /**
+ * var_export.
+ *
+ * @return array
+ */
+ public function __set_state()
+ {
+ return $this->all();
+ }
+
+ /**
+ * (PHP 5 >= 5.0.0)
+ * Whether a offset exists.
+ *
+ * @see http://php.net/manual/en/arrayaccess.offsetexists.php
+ *
+ * @param mixed $offset
+ * An offset to check for.
+ *
+ *
+ * @return bool true on success or false on failure.
+ * The return value will be casted to boolean if non-boolean was returned
+ */
+ public function offsetExists($offset)
+ {
+ return $this->has($offset);
+ }
+
+ /**
+ * (PHP 5 >= 5.0.0)
+ * Offset to unset.
+ *
+ * @see http://php.net/manual/en/arrayaccess.offsetunset.php
+ *
+ * @param mixed $offset
+ * The offset to unset.
+ *
+ */
+ public function offsetUnset($offset)
+ {
+ if ($this->offsetExists($offset)) {
+ $this->forget($offset);
+ }
+ }
+
+ /**
+ * (PHP 5 >= 5.0.0)
+ * 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
+ */
+ public function offsetGet($offset)
+ {
+ return $this->offsetExists($offset) ? $this->get($offset) : null;
+ }
+
+ /**
+ * (PHP 5 >= 5.0.0)
+ * 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.
+ *
+ */
+ public function offsetSet($offset, $value)
+ {
+ $this->set($offset, $value);
+ }
+}
diff --git a/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Support/File.php b/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Support/File.php
new file mode 100644
index 0000000..b51b41d
--- /dev/null
+++ b/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Support/File.php
@@ -0,0 +1,135 @@
+
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace EasyWeChat\Kernel\Support;
+
+use finfo;
+
+/**
+ * Class File.
+ */
+class File
+{
+ /**
+ * MIME mapping.
+ *
+ * @var array
+ */
+ protected static $extensionMap = [
+ 'audio/wav' => '.wav',
+ 'audio/x-ms-wma' => '.wma',
+ 'video/x-ms-wmv' => '.wmv',
+ 'video/mp4' => '.mp4',
+ 'audio/mpeg' => '.mp3',
+ 'audio/amr' => '.amr',
+ 'application/vnd.rn-realmedia' => '.rm',
+ 'audio/mid' => '.mid',
+ 'image/bmp' => '.bmp',
+ 'image/gif' => '.gif',
+ 'image/png' => '.png',
+ 'image/tiff' => '.tiff',
+ 'image/jpeg' => '.jpg',
+ 'application/pdf' => '.pdf',
+
+ // 列举更多的文件 mime, 企业号是支持的,公众平台这边之后万一也更新了呢
+ 'application/msword' => '.doc',
+
+ 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' => '.docx',
+ 'application/vnd.openxmlformats-officedocument.wordprocessingml.template' => '.dotx',
+ 'application/vnd.ms-word.document.macroEnabled.12' => '.docm',
+ 'application/vnd.ms-word.template.macroEnabled.12' => '.dotm',
+
+ 'application/vnd.ms-excel' => '.xls',
+
+ 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' => '.xlsx',
+ 'application/vnd.openxmlformats-officedocument.spreadsheetml.template' => '.xltx',
+ 'application/vnd.ms-excel.sheet.macroEnabled.12' => '.xlsm',
+ 'application/vnd.ms-excel.template.macroEnabled.12' => '.xltm',
+ 'application/vnd.ms-excel.addin.macroEnabled.12' => '.xlam',
+ 'application/vnd.ms-excel.sheet.binary.macroEnabled.12' => '.xlsb',
+
+ 'application/vnd.ms-powerpoint' => '.ppt',
+
+ 'application/vnd.openxmlformats-officedocument.presentationml.presentation' => '.pptx',
+ 'application/vnd.openxmlformats-officedocument.presentationml.template' => '.potx',
+ 'application/vnd.openxmlformats-officedocument.presentationml.slideshow' => '.ppsx',
+ 'application/vnd.ms-powerpoint.addin.macroEnabled.12' => '.ppam',
+ ];
+
+ /**
+ * File header signatures.
+ *
+ * @var array
+ */
+ protected static $signatures = [
+ 'ffd8ff' => '.jpg',
+ '424d' => '.bmp',
+ '47494638' => '.gif',
+ '2f55736572732f6f7665' => '.png',
+ '89504e47' => '.png',
+ '494433' => '.mp3',
+ 'fffb' => '.mp3',
+ 'fff3' => '.mp3',
+ '3026b2758e66cf11' => '.wma',
+ '52494646' => '.wav',
+ '57415645' => '.wav',
+ '41564920' => '.avi',
+ '000001ba' => '.mpg',
+ '000001b3' => '.mpg',
+ '2321414d52' => '.amr',
+ '25504446' => '.pdf',
+ ];
+
+ /**
+ * Return steam extension.
+ *
+ * @param string $stream
+ *
+ * @return string|false
+ */
+ public static function getStreamExt($stream)
+ {
+ $ext = self::getExtBySignature($stream);
+
+ try {
+ if (empty($ext) && is_readable($stream)) {
+ $stream = file_get_contents($stream);
+ }
+ } catch (\Exception $e) {
+ }
+
+ $fileInfo = new finfo(FILEINFO_MIME);
+
+ $mime = strstr($fileInfo->buffer($stream), ';', true);
+
+ return isset(self::$extensionMap[$mime]) ? self::$extensionMap[$mime] : $ext;
+ }
+
+ /**
+ * Get file extension by file header signature.
+ *
+ * @param string $stream
+ *
+ * @return string
+ */
+ public static function getExtBySignature($stream)
+ {
+ $prefix = strval(bin2hex(mb_strcut($stream, 0, 10)));
+
+ foreach (self::$signatures as $signature => $extension) {
+ if (0 === strpos($prefix, strval($signature))) {
+ return $extension;
+ }
+ }
+
+ return '';
+ }
+}
diff --git a/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Support/Helpers.php b/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Support/Helpers.php
new file mode 100644
index 0000000..08d4092
--- /dev/null
+++ b/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Support/Helpers.php
@@ -0,0 +1,131 @@
+
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace EasyWeChat\Kernel\Support;
+
+/*
+ * helpers.
+ *
+ * @author overtrue
+ */
+
+/**
+ * Generate a signature.
+ *
+ * @param array $attributes
+ * @param string $key
+ * @param string $encryptMethod
+ *
+ * @return string
+ */
+function generate_sign(array $attributes, $key, $encryptMethod = 'md5')
+{
+ ksort($attributes);
+
+ $attributes['key'] = $key;
+
+ return strtoupper(call_user_func_array($encryptMethod, [urldecode(http_build_query($attributes))]));
+}
+
+/**
+ * @param string $signType
+ * @param string $secretKey
+ *
+ * @return \Closure|string
+ */
+function get_encrypt_method(string $signType, string $secretKey = '')
+{
+ if ('HMAC-SHA256' === $signType) {
+ return function ($str) use ($secretKey) {
+ return hash_hmac('sha256', $str, $secretKey);
+ };
+ }
+
+ return 'md5';
+}
+
+/**
+ * Get client ip.
+ *
+ * @return string
+ */
+function get_client_ip()
+{
+ if (!empty($_SERVER['REMOTE_ADDR'])) {
+ $ip = $_SERVER['REMOTE_ADDR'];
+ } else {
+ // for php-cli(phpunit etc.)
+ $ip = defined('PHPUNIT_RUNNING') ? '127.0.0.1' : gethostbyname(gethostname());
+ }
+
+ return filter_var($ip, FILTER_VALIDATE_IP) ?: '127.0.0.1';
+}
+
+/**
+ * Get current server ip.
+ *
+ * @return string
+ */
+function get_server_ip()
+{
+ if (!empty($_SERVER['SERVER_ADDR'])) {
+ $ip = $_SERVER['SERVER_ADDR'];
+ } elseif (!empty($_SERVER['SERVER_NAME'])) {
+ $ip = gethostbyname($_SERVER['SERVER_NAME']);
+ } else {
+ // for php-cli(phpunit etc.)
+ $ip = defined('PHPUNIT_RUNNING') ? '127.0.0.1' : gethostbyname(gethostname());
+ }
+
+ return filter_var($ip, FILTER_VALIDATE_IP) ?: '127.0.0.1';
+}
+
+/**
+ * Return current url.
+ *
+ * @return string
+ */
+function current_url()
+{
+ $protocol = 'http://';
+
+ if ((!empty($_SERVER['HTTPS']) && 'off' !== $_SERVER['HTTPS']) || ($_SERVER['HTTP_X_FORWARDED_PROTO'] ?? 'http') === 'https') {
+ $protocol = 'https://';
+ }
+
+ return $protocol.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'];
+}
+
+/**
+ * Return random string.
+ *
+ * @param string $length
+ *
+ * @return string
+ */
+function str_random($length)
+{
+ return Str::random($length);
+}
+
+/**
+ * @param string $content
+ * @param string $publicKey
+ *
+ * @return string
+ */
+function rsa_public_encrypt($content, $publicKey)
+{
+ $encrypted = '';
+ openssl_public_encrypt($content, $encrypted, openssl_pkey_get_public($publicKey), OPENSSL_PKCS1_OAEP_PADDING);
+
+ return base64_encode($encrypted);
+}
diff --git a/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Support/Str.php b/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Support/Str.php
new file mode 100644
index 0000000..3a51968
--- /dev/null
+++ b/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Support/Str.php
@@ -0,0 +1,193 @@
+
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace EasyWeChat\Kernel\Support;
+
+use EasyWeChat\Kernel\Exceptions\RuntimeException;
+
+/**
+ * Class Str.
+ */
+class Str
+{
+ /**
+ * The cache of snake-cased words.
+ *
+ * @var array
+ */
+ protected static $snakeCache = [];
+
+ /**
+ * The cache of camel-cased words.
+ *
+ * @var array
+ */
+ protected static $camelCache = [];
+
+ /**
+ * The cache of studly-cased words.
+ *
+ * @var array
+ */
+ protected static $studlyCache = [];
+
+ /**
+ * Convert a value to camel case.
+ *
+ * @param string $value
+ *
+ * @return string
+ */
+ public static function camel($value)
+ {
+ if (isset(static::$camelCache[$value])) {
+ return static::$camelCache[$value];
+ }
+
+ return static::$camelCache[$value] = lcfirst(static::studly($value));
+ }
+
+ /**
+ * Generate a more truly "random" alpha-numeric string.
+ *
+ * @param int $length
+ *
+ * @return string
+ *
+ * @throws \EasyWeChat\Kernel\Exceptions\RuntimeException
+ */
+ public static function random($length = 16)
+ {
+ $string = '';
+
+ while (($len = strlen($string)) < $length) {
+ $size = $length - $len;
+
+ $bytes = static::randomBytes($size);
+
+ $string .= substr(str_replace(['/', '+', '='], '', base64_encode($bytes)), 0, $size);
+ }
+
+ return $string;
+ }
+
+ /**
+ * Generate a more truly "random" bytes.
+ *
+ * @param int $length
+ *
+ * @return string
+ *
+ * @throws RuntimeException
+ *
+ * @codeCoverageIgnore
+ *
+ * @throws \Exception
+ */
+ public static function randomBytes($length = 16)
+ {
+ if (function_exists('random_bytes')) {
+ $bytes = random_bytes($length);
+ } elseif (function_exists('openssl_random_pseudo_bytes')) {
+ $bytes = openssl_random_pseudo_bytes($length, $strong);
+ if (false === $bytes || false === $strong) {
+ throw new RuntimeException('Unable to generate random string.');
+ }
+ } else {
+ throw new RuntimeException('OpenSSL extension is required for PHP 5 users.');
+ }
+
+ return $bytes;
+ }
+
+ /**
+ * Generate a "random" alpha-numeric string.
+ *
+ * Should not be considered sufficient for cryptography, etc.
+ *
+ * @param int $length
+ *
+ * @return string
+ */
+ public static function quickRandom($length = 16)
+ {
+ $pool = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
+
+ return substr(str_shuffle(str_repeat($pool, $length)), 0, $length);
+ }
+
+ /**
+ * Convert the given string to upper-case.
+ *
+ * @param string $value
+ *
+ * @return string
+ */
+ public static function upper($value)
+ {
+ return mb_strtoupper($value);
+ }
+
+ /**
+ * Convert the given string to title case.
+ *
+ * @param string $value
+ *
+ * @return string
+ */
+ public static function title($value)
+ {
+ return mb_convert_case($value, MB_CASE_TITLE, 'UTF-8');
+ }
+
+ /**
+ * Convert a string to snake case.
+ *
+ * @param string $value
+ * @param string $delimiter
+ *
+ * @return string
+ */
+ public static function snake($value, $delimiter = '_')
+ {
+ $key = $value.$delimiter;
+
+ if (isset(static::$snakeCache[$key])) {
+ return static::$snakeCache[$key];
+ }
+
+ if (!ctype_lower($value)) {
+ $value = strtolower(preg_replace('/(.)(?=[A-Z])/', '$1'.$delimiter, $value));
+ }
+
+ return static::$snakeCache[$key] = trim($value, '_');
+ }
+
+ /**
+ * Convert a value to studly caps case.
+ *
+ * @param string $value
+ *
+ * @return string
+ */
+ public static function studly($value)
+ {
+ $key = $value;
+
+ if (isset(static::$studlyCache[$key])) {
+ return static::$studlyCache[$key];
+ }
+
+ $value = ucwords(str_replace(['-', '_'], ' ', $value));
+
+ return static::$studlyCache[$key] = str_replace(' ', '', $value);
+ }
+}
diff --git a/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Support/XML.php b/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Support/XML.php
new file mode 100644
index 0000000..93026e6
--- /dev/null
+++ b/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Support/XML.php
@@ -0,0 +1,167 @@
+
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace EasyWeChat\Kernel\Support;
+
+use SimpleXMLElement;
+
+/**
+ * Class XML.
+ */
+class XML
+{
+ /**
+ * XML to array.
+ *
+ * @param string $xml XML string
+ *
+ * @return array
+ */
+ public static function parse($xml)
+ {
+ $backup = libxml_disable_entity_loader(true);
+
+ $result = self::normalize(simplexml_load_string(self::sanitize($xml), 'SimpleXMLElement', LIBXML_COMPACT | LIBXML_NOCDATA | LIBXML_NOBLANKS));
+
+ libxml_disable_entity_loader($backup);
+
+ return $result;
+ }
+
+ /**
+ * XML encode.
+ *
+ * @param mixed $data
+ * @param string $root
+ * @param string $item
+ * @param string $attr
+ * @param string $id
+ *
+ * @return string
+ */
+ public static function build(
+ $data,
+ $root = 'xml',
+ $item = 'item',
+ $attr = '',
+ $id = 'id'
+ ) {
+ if (is_array($attr)) {
+ $_attr = [];
+
+ foreach ($attr as $key => $value) {
+ $_attr[] = "{$key}=\"{$value}\"";
+ }
+
+ $attr = implode(' ', $_attr);
+ }
+
+ $attr = trim($attr);
+ $attr = empty($attr) ? '' : " {$attr}";
+ $xml = "<{$root}{$attr}>";
+ $xml .= self::data2Xml($data, $item, $id);
+ $xml .= "{$root}>";
+
+ return $xml;
+ }
+
+ /**
+ * Build CDATA.
+ *
+ * @param string $string
+ *
+ * @return string
+ */
+ public static function cdata($string)
+ {
+ return sprintf('', $string);
+ }
+
+ /**
+ * Object to array.
+ *
+ *
+ * @param SimpleXMLElement $obj
+ *
+ * @return array
+ */
+ protected static function normalize($obj)
+ {
+ $result = null;
+
+ if (is_object($obj)) {
+ $obj = (array) $obj;
+ }
+
+ if (is_array($obj)) {
+ foreach ($obj as $key => $value) {
+ $res = self::normalize($value);
+ if (('@attributes' === $key) && ($key)) {
+ $result = $res; // @codeCoverageIgnore
+ } else {
+ $result[$key] = $res;
+ }
+ }
+ } else {
+ $result = $obj;
+ }
+
+ return $result;
+ }
+
+ /**
+ * Array to XML.
+ *
+ * @param array $data
+ * @param string $item
+ * @param string $id
+ *
+ * @return string
+ */
+ protected static function data2Xml($data, $item = 'item', $id = 'id')
+ {
+ $xml = $attr = '';
+
+ foreach ($data as $key => $val) {
+ if (is_numeric($key)) {
+ $id && $attr = " {$id}=\"{$key}\"";
+ $key = $item;
+ }
+
+ $xml .= "<{$key}{$attr}>";
+
+ if ((is_array($val) || is_object($val))) {
+ $xml .= self::data2Xml((array) $val, $item, $id);
+ } else {
+ $xml .= is_numeric($val) ? $val : self::cdata($val);
+ }
+
+ $xml .= "{$key}>";
+ }
+
+ return $xml;
+ }
+
+ /**
+ * Delete invalid characters in XML.
+ *
+ * @see https://www.w3.org/TR/2008/REC-xml-20081126/#charsets - XML charset range
+ * @see http://php.net/manual/en/regexp.reference.escape.php - escape in UTF-8 mode
+ *
+ * @param string $xml
+ *
+ * @return string
+ */
+ public static function sanitize($xml)
+ {
+ return preg_replace('/[^\x{9}\x{A}\x{D}\x{20}-\x{D7FF}\x{E000}-\x{FFFD}\x{10000}-\x{10FFFF}]+/u', '', $xml);
+ }
+}
diff --git a/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Traits/HasAttributes.php b/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Traits/HasAttributes.php
new file mode 100644
index 0000000..238d9e2
--- /dev/null
+++ b/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Traits/HasAttributes.php
@@ -0,0 +1,251 @@
+
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace EasyWeChat\Kernel\Traits;
+
+use EasyWeChat\Kernel\Exceptions\InvalidArgumentException;
+use EasyWeChat\Kernel\Support\Arr;
+use EasyWeChat\Kernel\Support\Str;
+
+/**
+ * Trait Attributes.
+ */
+trait HasAttributes
+{
+ /**
+ * @var array
+ */
+ protected $attributes = [];
+
+ /**
+ * @var bool
+ */
+ protected $snakeable = true;
+
+ /**
+ * Set Attributes.
+ *
+ * @param array $attributes
+ *
+ * @return $this
+ */
+ public function setAttributes(array $attributes = [])
+ {
+ $this->attributes = $attributes;
+
+ return $this;
+ }
+
+ /**
+ * Set attribute.
+ *
+ * @param string $attribute
+ * @param string $value
+ *
+ * @return $this
+ */
+ public function setAttribute($attribute, $value)
+ {
+ Arr::set($this->attributes, $attribute, $value);
+
+ return $this;
+ }
+
+ /**
+ * Get attribute.
+ *
+ * @param string $attribute
+ * @param mixed $default
+ *
+ * @return mixed
+ */
+ public function getAttribute($attribute, $default = null)
+ {
+ return Arr::get($this->attributes, $attribute, $default);
+ }
+
+ /**
+ * @param string $attribute
+ *
+ * @return bool
+ */
+ public function isRequired($attribute)
+ {
+ return in_array($attribute, $this->getRequired(), true);
+ }
+
+ /**
+ * @return array|mixed
+ */
+ public function getRequired()
+ {
+ return property_exists($this, 'required') ? $this->required : [];
+ }
+
+ /**
+ * Set attribute.
+ *
+ * @param string $attribute
+ * @param mixed $value
+ *
+ * @return $this
+ */
+ public function with($attribute, $value)
+ {
+ $this->snakeable && $attribute = Str::snake($attribute);
+
+ $this->setAttribute($attribute, $value);
+
+ return $this;
+ }
+
+ /**
+ * Override parent set() method.
+ *
+ * @param string $attribute
+ * @param mixed $value
+ *
+ * @return $this
+ */
+ public function set($attribute, $value)
+ {
+ $this->setAttribute($attribute, $value);
+
+ return $this;
+ }
+
+ /**
+ * Override parent get() method.
+ *
+ * @param string $attribute
+ * @param mixed $default
+ *
+ * @return mixed
+ */
+ public function get($attribute, $default = null)
+ {
+ return $this->getAttribute($attribute, $default);
+ }
+
+ /**
+ * @param string $key
+ *
+ * @return bool
+ */
+ public function has(string $key)
+ {
+ return Arr::has($this->attributes, $key);
+ }
+
+ /**
+ * @param array $attributes
+ *
+ * @return $this
+ */
+ public function merge(array $attributes)
+ {
+ $this->attributes = array_merge($this->attributes, $attributes);
+
+ return $this;
+ }
+
+ /**
+ * @param array|string $keys
+ *
+ * @return array
+ */
+ public function only($keys)
+ {
+ return Arr::only($this->attributes, $keys);
+ }
+
+ /**
+ * Return all items.
+ *
+ * @return array
+ *
+ * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
+ */
+ public function all()
+ {
+ $this->checkRequiredAttributes();
+
+ return $this->attributes;
+ }
+
+ /**
+ * Magic call.
+ *
+ * @param string $method
+ * @param array $args
+ *
+ * @return $this
+ */
+ public function __call($method, $args)
+ {
+ if (0 === stripos($method, 'with')) {
+ return $this->with(substr($method, 4), array_shift($args));
+ }
+
+ throw new \BadMethodCallException(sprintf('Method "%s" does not exists.', $method));
+ }
+
+ /**
+ * Magic get.
+ *
+ * @param string $property
+ *
+ * @return mixed
+ */
+ public function __get($property)
+ {
+ return $this->get($property);
+ }
+
+ /**
+ * Magic set.
+ *
+ * @param string $property
+ * @param mixed $value
+ *
+ * @return $this
+ */
+ public function __set($property, $value)
+ {
+ return $this->with($property, $value);
+ }
+
+ /**
+ * Whether or not an data exists by key.
+ *
+ * @param string $key
+ *
+ * @return bool
+ */
+ public function __isset($key)
+ {
+ return isset($this->attributes[$key]);
+ }
+
+ /**
+ * Check required attributes.
+ *
+ * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
+ */
+ protected function checkRequiredAttributes()
+ {
+ foreach ($this->getRequired() as $attribute) {
+ if (is_null($this->get($attribute))) {
+ throw new InvalidArgumentException(sprintf('"%s" cannot be empty.', $attribute));
+ }
+ }
+ }
+}
diff --git a/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Traits/HasHttpRequests.php b/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Traits/HasHttpRequests.php
new file mode 100644
index 0000000..9bf0a02
--- /dev/null
+++ b/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Traits/HasHttpRequests.php
@@ -0,0 +1,231 @@
+
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace EasyWeChat\Kernel\Traits;
+
+use GuzzleHttp\Client;
+use GuzzleHttp\ClientInterface;
+use GuzzleHttp\HandlerStack;
+use Psr\Http\Message\ResponseInterface;
+
+/**
+ * Trait HasHttpRequests.
+ *
+ * @author overtrue
+ */
+trait HasHttpRequests
+{
+ use ResponseCastable;
+
+ /**
+ * @var \GuzzleHttp\ClientInterface
+ */
+ protected $httpClient;
+
+ /**
+ * @var array
+ */
+ protected $middlewares = [];
+
+ /**
+ * @var \GuzzleHttp\HandlerStack
+ */
+ protected $handlerStack;
+
+ /**
+ * @var array
+ */
+ protected static $defaults = [
+ 'curl' => [
+ CURLOPT_IPRESOLVE => CURL_IPRESOLVE_V4,
+ ],
+ ];
+
+ /**
+ * Set guzzle default settings.
+ *
+ * @param array $defaults
+ */
+ public static function setDefaultOptions($defaults = [])
+ {
+ self::$defaults = $defaults;
+ }
+
+ /**
+ * Return current guzzle default settings.
+ *
+ * @return array
+ */
+ public static function getDefaultOptions(): array
+ {
+ return self::$defaults;
+ }
+
+ /**
+ * Set GuzzleHttp\Client.
+ *
+ * @param \GuzzleHttp\ClientInterface $httpClient
+ *
+ * @return $this
+ */
+ public function setHttpClient(ClientInterface $httpClient)
+ {
+ $this->httpClient = $httpClient;
+
+ return $this;
+ }
+
+ /**
+ * Return GuzzleHttp\ClientInterface instance.
+ *
+ * @return ClientInterface
+ */
+ public function getHttpClient(): ClientInterface
+ {
+ if (!($this->httpClient instanceof ClientInterface)) {
+ if (property_exists($this, 'app') && $this->app['http_client']) {
+ $this->httpClient = $this->app['http_client'];
+ } else {
+ $this->httpClient = new Client(['handler' => HandlerStack::create($this->getGuzzleHandler())]);
+ }
+ }
+
+ return $this->httpClient;
+ }
+
+ /**
+ * Add a middleware.
+ *
+ * @param callable $middleware
+ * @param string $name
+ *
+ * @return $this
+ */
+ public function pushMiddleware(callable $middleware, string $name = null)
+ {
+ if (!is_null($name)) {
+ $this->middlewares[$name] = $middleware;
+ } else {
+ array_push($this->middlewares, $middleware);
+ }
+
+ return $this;
+ }
+
+ /**
+ * Return all middlewares.
+ *
+ * @return array
+ */
+ public function getMiddlewares(): array
+ {
+ return $this->middlewares;
+ }
+
+ /**
+ * Make a request.
+ *
+ * @param string $url
+ * @param string $method
+ * @param array $options
+ *
+ * @return \Psr\Http\Message\ResponseInterface
+ *
+ * @throws \GuzzleHttp\Exception\GuzzleException
+ */
+ public function request($url, $method = 'GET', $options = []): ResponseInterface
+ {
+ $method = strtoupper($method);
+
+ $options = array_merge(self::$defaults, $options, ['handler' => $this->getHandlerStack()]);
+
+ $options = $this->fixJsonIssue($options);
+
+ if (property_exists($this, 'baseUri') && !is_null($this->baseUri)) {
+ $options['base_uri'] = $this->baseUri;
+ }
+
+ $response = $this->getHttpClient()->request($method, $url, $options);
+ $response->getBody()->rewind();
+
+ return $response;
+ }
+
+ /**
+ * @param \GuzzleHttp\HandlerStack $handlerStack
+ *
+ * @return $this
+ */
+ public function setHandlerStack(HandlerStack $handlerStack)
+ {
+ $this->handlerStack = $handlerStack;
+
+ return $this;
+ }
+
+ /**
+ * Build a handler stack.
+ *
+ * @return \GuzzleHttp\HandlerStack
+ */
+ public function getHandlerStack(): HandlerStack
+ {
+ if ($this->handlerStack) {
+ return $this->handlerStack;
+ }
+
+ $this->handlerStack = HandlerStack::create($this->getGuzzleHandler());
+
+ foreach ($this->middlewares as $name => $middleware) {
+ $this->handlerStack->push($middleware, $name);
+ }
+
+ return $this->handlerStack;
+ }
+
+ /**
+ * @param array $options
+ *
+ * @return array
+ */
+ protected function fixJsonIssue(array $options): array
+ {
+ if (isset($options['json']) && is_array($options['json'])) {
+ $options['headers'] = array_merge($options['headers'] ?? [], ['Content-Type' => 'application/json']);
+
+ if (empty($options['json'])) {
+ $options['body'] = \GuzzleHttp\json_encode($options['json'], JSON_FORCE_OBJECT);
+ } else {
+ $options['body'] = \GuzzleHttp\json_encode($options['json'], JSON_UNESCAPED_UNICODE);
+ }
+
+ unset($options['json']);
+ }
+
+ return $options;
+ }
+
+ /**
+ * Get guzzle handler.
+ *
+ * @return callable
+ */
+ protected function getGuzzleHandler()
+ {
+ if (property_exists($this, 'app') && isset($this->app['guzzle_handler'])) {
+ return is_string($handler = $this->app->raw('guzzle_handler'))
+ ? new $handler()
+ : $handler;
+ }
+
+ return \GuzzleHttp\choose_handler();
+ }
+}
diff --git a/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Traits/InteractsWithCache.php b/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Traits/InteractsWithCache.php
new file mode 100644
index 0000000..fc5182c
--- /dev/null
+++ b/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Traits/InteractsWithCache.php
@@ -0,0 +1,105 @@
+
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace EasyWeChat\Kernel\Traits;
+
+use EasyWeChat\Kernel\Exceptions\InvalidArgumentException;
+use EasyWeChat\Kernel\ServiceContainer;
+use Psr\Cache\CacheItemPoolInterface;
+use Psr\SimpleCache\CacheInterface as SimpleCacheInterface;
+use Symfony\Component\Cache\Adapter\FilesystemAdapter;
+use Symfony\Component\Cache\Psr16Cache;
+use Symfony\Component\Cache\Simple\FilesystemCache;
+
+/**
+ * Trait InteractsWithCache.
+ *
+ * @author overtrue
+ */
+trait InteractsWithCache
+{
+ /**
+ * @var \Psr\SimpleCache\CacheInterface
+ */
+ protected $cache;
+
+ /**
+ * Get cache instance.
+ *
+ * @return \Psr\SimpleCache\CacheInterface
+ *
+ * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
+ */
+ public function getCache()
+ {
+ if ($this->cache) {
+ return $this->cache;
+ }
+
+ if (property_exists($this, 'app') && $this->app instanceof ServiceContainer && isset($this->app['cache'])) {
+ $this->setCache($this->app['cache']);
+
+ // Fix PHPStan error
+ assert($this->cache instanceof \Psr\SimpleCache\CacheInterface);
+
+ return $this->cache;
+ }
+
+ return $this->cache = $this->createDefaultCache();
+ }
+
+ /**
+ * Set cache instance.
+ *
+ * @param \Psr\SimpleCache\CacheInterface|\Psr\Cache\CacheItemPoolInterface $cache
+ *
+ * @return $this
+ *
+ * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
+ */
+ public function setCache($cache)
+ {
+ if (empty(\array_intersect([SimpleCacheInterface::class, CacheItemPoolInterface::class], \class_implements($cache)))) {
+ throw new InvalidArgumentException(\sprintf('The cache instance must implements %s or %s interface.', SimpleCacheInterface::class, CacheItemPoolInterface::class));
+ }
+
+ if ($cache instanceof CacheItemPoolInterface) {
+ if (!$this->isSymfony43()) {
+ throw new InvalidArgumentException(sprintf('The cache instance must implements %s', SimpleCacheInterface::class));
+ }
+ $cache = new Psr16Cache($cache);
+ }
+
+ $this->cache = $cache;
+
+ return $this;
+ }
+
+ /**
+ * @return \Psr\SimpleCache\CacheInterface
+ */
+ protected function createDefaultCache()
+ {
+ if ($this->isSymfony43()) {
+ return new Psr16Cache(new FilesystemAdapter('easywechat', 1500));
+ }
+
+ return new FilesystemCache();
+ }
+
+ /**
+ * @return bool
+ */
+ protected function isSymfony43(): bool
+ {
+ return \class_exists('Symfony\Component\Cache\Psr16Cache');
+ }
+}
diff --git a/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Traits/Observable.php b/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Traits/Observable.php
new file mode 100644
index 0000000..7db03f5
--- /dev/null
+++ b/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Traits/Observable.php
@@ -0,0 +1,273 @@
+
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace EasyWeChat\Kernel\Traits;
+
+use EasyWeChat\Kernel\Clauses\Clause;
+use EasyWeChat\Kernel\Contracts\EventHandlerInterface;
+use EasyWeChat\Kernel\Decorators\FinallyResult;
+use EasyWeChat\Kernel\Decorators\TerminateResult;
+use EasyWeChat\Kernel\Exceptions\InvalidArgumentException;
+use EasyWeChat\Kernel\ServiceContainer;
+
+/**
+ * Trait Observable.
+ *
+ * @author overtrue
+ */
+trait Observable
+{
+ /**
+ * @var array
+ */
+ protected $handlers = [];
+
+ /**
+ * @var array
+ */
+ protected $clauses = [];
+
+ /**
+ * @param \Closure|EventHandlerInterface|callable|string $handler
+ * @param \Closure|EventHandlerInterface|callable|string $condition
+ *
+ * @return \EasyWeChat\Kernel\Clauses\Clause
+ *
+ * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
+ * @throws \ReflectionException
+ */
+ public function push($handler, $condition = '*')
+ {
+ list($handler, $condition) = $this->resolveHandlerAndCondition($handler, $condition);
+
+ if (!isset($this->handlers[$condition])) {
+ $this->handlers[$condition] = [];
+ }
+
+ array_push($this->handlers[$condition], $handler);
+
+ return $this->newClause($handler);
+ }
+
+ /**
+ * @param \Closure|EventHandlerInterface|string $handler
+ * @param \Closure|EventHandlerInterface|string $condition
+ *
+ * @return \EasyWeChat\Kernel\Clauses\Clause
+ *
+ * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
+ * @throws \ReflectionException
+ */
+ public function unshift($handler, $condition = '*')
+ {
+ list($handler, $condition) = $this->resolveHandlerAndCondition($handler, $condition);
+
+ if (!isset($this->handlers[$condition])) {
+ $this->handlers[$condition] = [];
+ }
+
+ array_unshift($this->handlers[$condition], $handler);
+
+ return $this->newClause($handler);
+ }
+
+ /**
+ * @param string $condition
+ * @param \Closure|EventHandlerInterface|string $handler
+ *
+ * @return \EasyWeChat\Kernel\Clauses\Clause
+ *
+ * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
+ * @throws \ReflectionException
+ */
+ public function observe($condition, $handler)
+ {
+ return $this->push($handler, $condition);
+ }
+
+ /**
+ * @param string $condition
+ * @param \Closure|EventHandlerInterface|string $handler
+ *
+ * @return \EasyWeChat\Kernel\Clauses\Clause
+ *
+ * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
+ * @throws \ReflectionException
+ */
+ public function on($condition, $handler)
+ {
+ return $this->push($handler, $condition);
+ }
+
+ /**
+ * @param string|int $event
+ * @param mixed ...$payload
+ *
+ * @return mixed|null
+ */
+ public function dispatch($event, $payload)
+ {
+ return $this->notify($event, $payload);
+ }
+
+ /**
+ * @param string|int $event
+ * @param mixed ...$payload
+ *
+ * @return mixed|null
+ */
+ public function notify($event, $payload)
+ {
+ $result = null;
+
+ foreach ($this->handlers as $condition => $handlers) {
+ if ('*' === $condition || ($condition & $event) === $event) {
+ foreach ($handlers as $handler) {
+ if ($clause = $this->clauses[$this->getHandlerHash($handler)] ?? null) {
+ if ($clause->intercepted($payload)) {
+ continue;
+ }
+ }
+
+ $response = $this->callHandler($handler, $payload);
+
+ switch (true) {
+ case $response instanceof TerminateResult:
+ return $response->content;
+ case true === $response:
+ continue 2;
+ case false === $response:
+ break 2;
+ case !empty($response) && !($result instanceof FinallyResult):
+ $result = $response;
+ }
+ }
+ }
+ }
+
+ return $result instanceof FinallyResult ? $result->content : $result;
+ }
+
+ /**
+ * @return array
+ */
+ public function getHandlers()
+ {
+ return $this->handlers;
+ }
+
+ /**
+ * @param mixed $handler
+ *
+ * @return \EasyWeChat\Kernel\Clauses\Clause
+ */
+ protected function newClause($handler): Clause
+ {
+ return $this->clauses[$this->getHandlerHash($handler)] = new Clause();
+ }
+
+ /**
+ * @param mixed $handler
+ *
+ * @return string
+ */
+ protected function getHandlerHash($handler)
+ {
+ if (is_string($handler)) {
+ return $handler;
+ }
+
+ if (is_array($handler)) {
+ return is_string($handler[0])
+ ? $handler[0].'::'.$handler[1]
+ : get_class($handler[0]).$handler[1];
+ }
+
+ return spl_object_hash($handler);
+ }
+
+ /**
+ * @param callable $handler
+ * @param mixed $payload
+ *
+ * @return mixed
+ */
+ protected function callHandler(callable $handler, $payload)
+ {
+ try {
+ return call_user_func_array($handler, [$payload]);
+ } catch (\Exception $e) {
+ if (property_exists($this, 'app') && $this->app instanceof ServiceContainer) {
+ $this->app['logger']->error($e->getCode().': '.$e->getMessage(), [
+ 'code' => $e->getCode(),
+ 'message' => $e->getMessage(),
+ 'file' => $e->getFile(),
+ 'line' => $e->getLine(),
+ ]);
+ }
+ }
+ }
+
+ /**
+ * @param mixed $handler
+ *
+ * @return \Closure
+ *
+ * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
+ * @throws \ReflectionException
+ */
+ protected function makeClosure($handler)
+ {
+ if (is_callable($handler)) {
+ return $handler;
+ }
+
+ if (is_string($handler) && '*' !== $handler) {
+ if (!class_exists($handler)) {
+ throw new InvalidArgumentException(sprintf('Class "%s" not exists.', $handler));
+ }
+
+ if (!in_array(EventHandlerInterface::class, (new \ReflectionClass($handler))->getInterfaceNames(), true)) {
+ throw new InvalidArgumentException(sprintf('Class "%s" not an instance of "%s".', $handler, EventHandlerInterface::class));
+ }
+
+ return function ($payload) use ($handler) {
+ return (new $handler($this->app ?? null))->handle($payload);
+ };
+ }
+
+ if ($handler instanceof EventHandlerInterface) {
+ return function () use ($handler) {
+ return $handler->handle(...func_get_args());
+ };
+ }
+
+ throw new InvalidArgumentException('No valid handler is found in arguments.');
+ }
+
+ /**
+ * @param mixed $handler
+ * @param mixed $condition
+ *
+ * @return array
+ *
+ * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
+ * @throws \ReflectionException
+ */
+ protected function resolveHandlerAndCondition($handler, $condition): array
+ {
+ if (is_int($handler) || (is_string($handler) && !class_exists($handler))) {
+ list($handler, $condition) = [$condition, $handler];
+ }
+
+ return [$this->makeClosure($handler), $condition];
+ }
+}
diff --git a/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Traits/ResponseCastable.php b/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Traits/ResponseCastable.php
new file mode 100644
index 0000000..5492bd4
--- /dev/null
+++ b/addons/weliam_smartcity/vendor/overtrue/wechat/src/Kernel/Traits/ResponseCastable.php
@@ -0,0 +1,93 @@
+
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace EasyWeChat\Kernel\Traits;
+
+use EasyWeChat\Kernel\Contracts\Arrayable;
+use EasyWeChat\Kernel\Exceptions\InvalidArgumentException;
+use EasyWeChat\Kernel\Exceptions\InvalidConfigException;
+use EasyWeChat\Kernel\Http\Response;
+use EasyWeChat\Kernel\Support\Collection;
+use Psr\Http\Message\ResponseInterface;
+
+/**
+ * Trait ResponseCastable.
+ *
+ * @author overtrue
+ */
+trait ResponseCastable
+{
+ /**
+ * @param \Psr\Http\Message\ResponseInterface $response
+ * @param string|null $type
+ *
+ * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string
+ *
+ * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
+ */
+ protected function castResponseToType(ResponseInterface $response, $type = null)
+ {
+ $response = Response::buildFromPsrResponse($response);
+ $response->getBody()->rewind();
+
+ switch ($type ?? 'array') {
+ case 'collection':
+ return $response->toCollection();
+ case 'array':
+ return $response->toArray();
+ case 'object':
+ return $response->toObject();
+ case 'raw':
+ return $response;
+ default:
+ if (!is_subclass_of($type, Arrayable::class)) {
+ throw new InvalidConfigException(sprintf('Config key "response_type" classname must be an instanceof %s', Arrayable::class));
+ }
+
+ return new $type($response);
+ }
+ }
+
+ /**
+ * @param mixed $response
+ * @param string|null $type
+ *
+ * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string
+ *
+ * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
+ * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
+ */
+ protected function detectAndCastResponseToType($response, $type = null)
+ {
+ switch (true) {
+ case $response instanceof ResponseInterface:
+ $response = Response::buildFromPsrResponse($response);
+
+ break;
+ case $response instanceof Arrayable:
+ $response = new Response(200, [], json_encode($response->toArray()));
+
+ break;
+ case ($response instanceof Collection) || is_array($response) || is_object($response):
+ $response = new Response(200, [], json_encode($response));
+
+ break;
+ case is_scalar($response):
+ $response = new Response(200, [], (string) $response);
+
+ break;
+ default:
+ throw new InvalidArgumentException(sprintf('Unsupported response type "%s"', gettype($response)));
+ }
+
+ return $this->castResponseToType($response, $type);
+ }
+}
diff --git a/addons/weliam_smartcity/vendor/overtrue/wechat/src/MicroMerchant/Application.php b/addons/weliam_smartcity/vendor/overtrue/wechat/src/MicroMerchant/Application.php
new file mode 100644
index 0000000..9bf8196
--- /dev/null
+++ b/addons/weliam_smartcity/vendor/overtrue/wechat/src/MicroMerchant/Application.php
@@ -0,0 +1,171 @@
+
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace EasyWeChat\MicroMerchant;
+
+use EasyWeChat\Kernel\Exceptions\InvalidArgumentException;
+use EasyWeChat\Kernel\ServiceContainer;
+use EasyWeChat\Kernel\Support;
+use EasyWeChat\MicroMerchant\Kernel\Exceptions\InvalidSignException;
+
+/**
+ * Class Application.
+ *
+ * @author liuml
+ *
+ * @property \EasyWeChat\MicroMerchant\Certficates\Client $certficates
+ * @property \EasyWeChat\MicroMerchant\Material\Client $material
+ * @property \EasyWeChat\MicroMerchant\MerchantConfig\Client $merchantConfig
+ * @property \EasyWeChat\MicroMerchant\Withdraw\Client $withdraw
+ * @property \EasyWeChat\MicroMerchant\Media\Client $media
+ *
+ * @method mixed submitApplication(array $params)
+ * @method mixed getStatus(string $applymentId, string $businessCode = '')
+ * @method mixed upgrade(array $params)
+ * @method mixed getUpgradeStatus(string $subMchId = '')
+ */
+class Application extends ServiceContainer
+{
+ /**
+ * @var array
+ */
+ protected $providers = [
+ // Base services
+ Base\ServiceProvider::class,
+ Certficates\ServiceProvider::class,
+ MerchantConfig\ServiceProvider::class,
+ Material\ServiceProvider::class,
+ Withdraw\ServiceProvider::class,
+ Media\ServiceProvider::class,
+ ];
+
+ /**
+ * @var array
+ */
+ protected $defaultConfig = [
+ 'http' => [
+ 'base_uri' => 'https://api.mch.weixin.qq.com/',
+ ],
+ 'log' => [
+ 'default' => 'dev', // 默认使用的 channel,生产环境可以改为下面的 prod
+ 'channels' => [
+ // 测试环境
+ 'dev' => [
+ 'driver' => 'single',
+ 'path' => '/tmp/easywechat.log',
+ 'level' => 'debug',
+ ],
+ // 生产环境
+ 'prod' => [
+ 'driver' => 'daily',
+ 'path' => '/tmp/easywechat.log',
+ 'level' => 'info',
+ ],
+ ],
+ ],
+ ];
+
+ /**
+ * @return string
+ *
+ * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
+ */
+ public function getKey()
+ {
+ $key = $this['config']->key;
+
+ if (empty($key)) {
+ throw new InvalidArgumentException('config key connot be empty.');
+ }
+
+ if (32 !== strlen($key)) {
+ throw new InvalidArgumentException(sprintf("'%s' should be 32 chars length.", $key));
+ }
+
+ return $key;
+ }
+
+ /**
+ * set sub-mch-id and appid.
+ *
+ * @param string $subMchId Identification Number of Small and Micro Businessmen Reported by Service Providers
+ * @param string $appId Public Account ID of Service Provider
+ *
+ * @return $this
+ */
+ public function setSubMchId(string $subMchId, string $appId = '')
+ {
+ $this['config']->set('sub_mch_id', $subMchId);
+ $this['config']->set('appid', $appId);
+
+ return $this;
+ }
+
+ /**
+ * setCertificate.
+ *
+ * @param string $certificate
+ * @param string $serialNo
+ *
+ * @return $this
+ */
+ public function setCertificate(string $certificate, string $serialNo)
+ {
+ $this['config']->set('certificate', $certificate);
+ $this['config']->set('serial_no', $serialNo);
+
+ return $this;
+ }
+
+ /**
+ * Returning true indicates that the verification is successful,
+ * returning false indicates that the signature field does not exist or is empty,
+ * and if the signature verification is wrong, the InvalidSignException will be thrown directly.
+ *
+ * @param array $data
+ *
+ * @return bool
+ *
+ * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
+ * @throws \EasyWeChat\MicroMerchant\Kernel\Exceptions\InvalidSignException
+ */
+ public function verifySignature(array $data)
+ {
+ if (!isset($data['sign']) || empty($data['sign'])) {
+ return false;
+ }
+
+ $sign = $data['sign'];
+ unset($data['sign']);
+
+ $signType = strlen($sign) > 32 ? 'HMAC-SHA256' : 'MD5';
+ $secretKey = $this->getKey();
+
+ $encryptMethod = Support\get_encrypt_method($signType, $secretKey);
+
+ if (Support\generate_sign($data, $secretKey, $encryptMethod) === $sign) {
+ return true;
+ }
+
+ throw new InvalidSignException('return value signature verification error');
+ }
+
+ /**
+ * @param string $name
+ * @param array $arguments
+ *
+ * @return mixed
+ */
+ public function __call($name, $arguments)
+ {
+ return call_user_func_array([$this['base'], $name], $arguments);
+ }
+}
diff --git a/addons/weliam_smartcity/vendor/overtrue/wechat/src/MicroMerchant/Base/Client.php b/addons/weliam_smartcity/vendor/overtrue/wechat/src/MicroMerchant/Base/Client.php
new file mode 100644
index 0000000..ba92756
--- /dev/null
+++ b/addons/weliam_smartcity/vendor/overtrue/wechat/src/MicroMerchant/Base/Client.php
@@ -0,0 +1,126 @@
+
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace EasyWeChat\MicroMerchant\Base;
+
+use EasyWeChat\MicroMerchant\Kernel\BaseClient;
+
+/**
+ * Class Client.
+ *
+ * @author liuml
+ * @DateTime 2019-05-30 14:19
+ */
+class Client extends BaseClient
+{
+ /**
+ * apply to settle in to become a small micro merchant.
+ *
+ * @param array $params
+ *
+ * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string
+ *
+ * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
+ * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
+ * @throws \EasyWeChat\MicroMerchant\Kernel\Exceptions\EncryptException
+ * @throws \GuzzleHttp\Exception\GuzzleException
+ */
+ public function submitApplication(array $params)
+ {
+ $params = $this->processParams(array_merge($params, [
+ 'version' => '3.0',
+ 'cert_sn' => '',
+ 'sign_type' => 'HMAC-SHA256',
+ 'nonce_str' => uniqid('micro'),
+ ]));
+
+ return $this->safeRequest('applyment/micro/submit', $params);
+ }
+
+ /**
+ * query application status.
+ *
+ * @param string $applymentId
+ * @param string $businessCode
+ *
+ * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string
+ *
+ * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
+ * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
+ * @throws \GuzzleHttp\Exception\GuzzleException
+ */
+ public function getStatus(string $applymentId, string $businessCode = '')
+ {
+ if (!empty($applymentId)) {
+ $params = [
+ 'applyment_id' => $applymentId,
+ ];
+ } else {
+ $params = [
+ 'business_code' => $businessCode,
+ ];
+ }
+
+ $params = array_merge($params, [
+ 'version' => '1.0',
+ 'sign_type' => 'HMAC-SHA256',
+ 'nonce_str' => uniqid('micro'),
+ ]);
+
+ return $this->safeRequest('applyment/micro/getstate', $params);
+ }
+
+ /**
+ * merchant upgrade api.
+ *
+ * @param array $params
+ *
+ * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string
+ *
+ * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
+ * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
+ * @throws \EasyWeChat\MicroMerchant\Kernel\Exceptions\EncryptException
+ * @throws \GuzzleHttp\Exception\GuzzleException
+ */
+ public function upgrade(array $params)
+ {
+ $params['sub_mch_id'] = $params['sub_mch_id'] ?? $this->app['config']->sub_mch_id;
+ $params = $this->processParams(array_merge($params, [
+ 'version' => '1.0',
+ 'cert_sn' => '',
+ 'sign_type' => 'HMAC-SHA256',
+ 'nonce_str' => uniqid('micro'),
+ ]));
+
+ return $this->safeRequest('applyment/micro/submitupgrade', $params);
+ }
+
+ /**
+ * get upgrade status.
+ *
+ * @param string $subMchId
+ *
+ * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string
+ *
+ * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
+ * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
+ * @throws \GuzzleHttp\Exception\GuzzleException
+ */
+ public function getUpgradeStatus(string $subMchId = '')
+ {
+ return $this->safeRequest('applyment/micro/getupgradestate', [
+ 'version' => '1.0',
+ 'sign_type' => 'HMAC-SHA256',
+ 'sub_mch_id' => $subMchId ?: $this->app['config']->sub_mch_id,
+ 'nonce_str' => uniqid('micro'),
+ ]);
+ }
+}
diff --git a/addons/weliam_smartcity/vendor/overtrue/wechat/src/MicroMerchant/Base/ServiceProvider.php b/addons/weliam_smartcity/vendor/overtrue/wechat/src/MicroMerchant/Base/ServiceProvider.php
new file mode 100644
index 0000000..db2f056
--- /dev/null
+++ b/addons/weliam_smartcity/vendor/overtrue/wechat/src/MicroMerchant/Base/ServiceProvider.php
@@ -0,0 +1,33 @@
+
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace EasyWeChat\MicroMerchant\Base;
+
+use Pimple\Container;
+use Pimple\ServiceProviderInterface;
+
+/**
+ * Class ServiceProvider.
+ *
+ * @author overtrue
+ */
+class ServiceProvider implements ServiceProviderInterface
+{
+ /**
+ * {@inheritdoc}.
+ */
+ public function register(Container $app)
+ {
+ $app['base'] = function ($app) {
+ return new Client($app);
+ };
+ }
+}
diff --git a/addons/weliam_smartcity/vendor/overtrue/wechat/src/MicroMerchant/Certficates/Client.php b/addons/weliam_smartcity/vendor/overtrue/wechat/src/MicroMerchant/Certficates/Client.php
new file mode 100644
index 0000000..9731703
--- /dev/null
+++ b/addons/weliam_smartcity/vendor/overtrue/wechat/src/MicroMerchant/Certficates/Client.php
@@ -0,0 +1,93 @@
+
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace EasyWeChat\MicroMerchant\Certficates;
+
+use EasyWeChat\Kernel\Exceptions\InvalidArgumentException;
+use EasyWeChat\MicroMerchant\Kernel\BaseClient;
+use EasyWeChat\MicroMerchant\Kernel\Exceptions\InvalidExtensionException;
+
+/**
+ * Class Client.
+ *
+ * @author liuml
+ * @DateTime 2019-05-30 14:19
+ */
+class Client extends BaseClient
+{
+ /**
+ * get certficates.
+ *
+ * @param bool $returnRaw
+ *
+ * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string
+ *
+ * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
+ * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
+ * @throws \EasyWeChat\MicroMerchant\Kernel\Exceptions\InvalidExtensionException
+ * @throws \GuzzleHttp\Exception\GuzzleException
+ */
+ public function get(bool $returnRaw = false)
+ {
+ $params = [
+ 'sign_type' => 'HMAC-SHA256',
+ 'nonce_str' => uniqid('micro'),
+ ];
+
+ if (true === $returnRaw) {
+ return $this->requestRaw('risk/getcertficates', $params);
+ }
+ /** @var array $response */
+ $response = $this->requestArray('risk/getcertficates', $params);
+
+ if ('SUCCESS' !== $response['return_code']) {
+ throw new InvalidArgumentException(sprintf('Failed to get certificate. return_code_msg: "%s" .', $response['return_code'].'('.$response['return_msg'].')'));
+ }
+ if ('SUCCESS' !== $response['result_code']) {
+ throw new InvalidArgumentException(sprintf('Failed to get certificate. result_err_code_des: "%s" .', $response['result_code'].'('.$response['err_code'].'['.$response['err_code_des'].'])'));
+ }
+ $certificates = \GuzzleHttp\json_decode($response['certificates'], true)['data'][0];
+ $ciphertext = $this->decrypt($certificates['encrypt_certificate']);
+ unset($certificates['encrypt_certificate']);
+ $certificates['certificates'] = $ciphertext;
+
+ return $certificates;
+ }
+
+ /**
+ * decrypt ciphertext.
+ *
+ * @param array $encryptCertificate
+ *
+ * @return string
+ *
+ * @throws \EasyWeChat\MicroMerchant\Kernel\Exceptions\InvalidExtensionException
+ */
+ public function decrypt(array $encryptCertificate)
+ {
+ if (false === extension_loaded('sodium')) {
+ throw new InvalidExtensionException('sodium extension is not installed,Reference link https://php.net/manual/zh/book.sodium.php');
+ }
+
+ if (false === sodium_crypto_aead_aes256gcm_is_available()) {
+ throw new InvalidExtensionException('aes256gcm is not currently supported');
+ }
+
+ // sodium_crypto_aead_aes256gcm_decrypt function needs to open libsodium extension.
+ // https://www.php.net/manual/zh/function.sodium-crypto-aead-aes256gcm-decrypt.php
+ return sodium_crypto_aead_aes256gcm_decrypt(
+ base64_decode($encryptCertificate['ciphertext'], true),
+ $encryptCertificate['associated_data'],
+ $encryptCertificate['nonce'],
+ $this->app['config']->apiv3_key
+ );
+ }
+}
diff --git a/addons/weliam_smartcity/vendor/overtrue/wechat/src/MicroMerchant/Certficates/ServiceProvider.php b/addons/weliam_smartcity/vendor/overtrue/wechat/src/MicroMerchant/Certficates/ServiceProvider.php
new file mode 100644
index 0000000..2e88b7e
--- /dev/null
+++ b/addons/weliam_smartcity/vendor/overtrue/wechat/src/MicroMerchant/Certficates/ServiceProvider.php
@@ -0,0 +1,33 @@
+
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace EasyWeChat\MicroMerchant\Certficates;
+
+use Pimple\Container;
+use Pimple\ServiceProviderInterface;
+
+/**
+ * Class ServiceProvider.
+ *
+ * @author overtrue
+ */
+class ServiceProvider implements ServiceProviderInterface
+{
+ /**
+ * {@inheritdoc}.
+ */
+ public function register(Container $app)
+ {
+ $app['certficates'] = function ($app) {
+ return new Client($app);
+ };
+ }
+}
diff --git a/addons/weliam_smartcity/vendor/overtrue/wechat/src/MicroMerchant/Kernel/BaseClient.php b/addons/weliam_smartcity/vendor/overtrue/wechat/src/MicroMerchant/Kernel/BaseClient.php
new file mode 100644
index 0000000..d91b467
--- /dev/null
+++ b/addons/weliam_smartcity/vendor/overtrue/wechat/src/MicroMerchant/Kernel/BaseClient.php
@@ -0,0 +1,256 @@
+
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace EasyWeChat\MicroMerchant\Kernel;
+
+use EasyWeChat\Kernel\Exceptions\InvalidArgumentException;
+use EasyWeChat\Kernel\Support;
+use EasyWeChat\MicroMerchant\Application;
+use EasyWeChat\MicroMerchant\Kernel\Exceptions\EncryptException;
+use EasyWeChat\Payment\Kernel\BaseClient as PaymentBaseClient;
+
+/**
+ * Class BaseClient.
+ *
+ * @author liuml
+ * @DateTime 2019-07-10 12:06
+ */
+class BaseClient extends PaymentBaseClient
+{
+ /**
+ * @var string
+ */
+ protected $certificates;
+
+ /**
+ * BaseClient constructor.
+ *
+ * @param \EasyWeChat\MicroMerchant\Application $app
+ */
+ public function __construct(Application $app)
+ {
+ $this->app = $app;
+
+ $this->setHttpClient($this->app['http_client']);
+ }
+
+ /**
+ * Extra request params.
+ *
+ * @return array
+ */
+ protected function prepends()
+ {
+ return [];
+ }
+
+ /**
+ * httpUpload.
+ *
+ * @param string $url
+ * @param array $files
+ * @param array $form
+ * @param array $query
+ * @param bool $returnResponse
+ *
+ * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string
+ *
+ * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
+ * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
+ * @throws \EasyWeChat\MicroMerchant\Kernel\Exceptions\InvalidSignException
+ * @throws \GuzzleHttp\Exception\GuzzleException
+ */
+ public function httpUpload(string $url, array $files = [], array $form = [], array $query = [], $returnResponse = false)
+ {
+ $multipart = [];
+
+ foreach ($files as $name => $path) {
+ $multipart[] = [
+ 'name' => $name,
+ 'contents' => fopen($path, 'r'),
+ ];
+ }
+
+ $base = [
+ 'mch_id' => $this->app['config']['mch_id'],
+ ];
+
+ $form = array_merge($base, $form);
+
+ $form['sign'] = $this->getSign($form);
+
+ foreach ($form as $name => $contents) {
+ $multipart[] = compact('name', 'contents');
+ }
+
+ $options = [
+ 'query' => $query,
+ 'multipart' => $multipart,
+ 'connect_timeout' => 30,
+ 'timeout' => 30,
+ 'read_timeout' => 30,
+ 'cert' => $this->app['config']->get('cert_path'),
+ 'ssl_key' => $this->app['config']->get('key_path'),
+ ];
+
+ $this->pushMiddleware($this->logMiddleware(), 'log');
+
+ $response = $this->performRequest($url, 'POST', $options);
+
+ $result = $returnResponse ? $response : $this->castResponseToType($response, $this->app->config->get('response_type'));
+ // auto verify signature
+ if ($returnResponse || 'array' !== ($this->app->config->get('response_type') ?? 'array')) {
+ $this->app->verifySignature($this->castResponseToType($response, 'array'));
+ } else {
+ $this->app->verifySignature($result);
+ }
+
+ return $result;
+ }
+
+ /**
+ * request.
+ *
+ * @param string $endpoint
+ * @param array $params
+ * @param string $method
+ * @param array $options
+ * @param bool $returnResponse
+ *
+ * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string
+ *
+ * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
+ * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
+ * @throws \EasyWeChat\MicroMerchant\Kernel\Exceptions\InvalidSignException
+ * @throws \GuzzleHttp\Exception\GuzzleException
+ */
+ protected function request(string $endpoint, array $params = [], $method = 'post', array $options = [], $returnResponse = false)
+ {
+ $base = [
+ 'mch_id' => $this->app['config']['mch_id'],
+ ];
+
+ $params = array_merge($base, $this->prepends(), $params);
+ $params['sign'] = $this->getSign($params);
+ $options = array_merge([
+ 'body' => Support\XML::build($params),
+ ], $options);
+
+ $this->pushMiddleware($this->logMiddleware(), 'log');
+ $response = $this->performRequest($endpoint, $method, $options);
+ $result = $returnResponse ? $response : $this->castResponseToType($response, $this->app->config->get('response_type'));
+ // auto verify signature
+ if ($returnResponse || 'array' !== ($this->app->config->get('response_type') ?? 'array')) {
+ $this->app->verifySignature($this->castResponseToType($response, 'array'));
+ } else {
+ $this->app->verifySignature($result);
+ }
+
+ return $result;
+ }
+
+ /**
+ * processing parameters contain fields that require sensitive information encryption.
+ *
+ * @param array $params
+ *
+ * @return array
+ *
+ * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
+ * @throws \EasyWeChat\MicroMerchant\Kernel\Exceptions\EncryptException
+ */
+ protected function processParams(array $params)
+ {
+ $serial_no = $this->app['config']->get('serial_no');
+ if (null === $serial_no) {
+ throw new InvalidArgumentException('config serial_no connot be empty.');
+ }
+
+ $params['cert_sn'] = $serial_no;
+ $sensitive_fields = $this->getSensitiveFieldsName();
+ foreach ($params as $k => $v) {
+ if (in_array($k, $sensitive_fields, true)) {
+ $params[$k] = $this->encryptSensitiveInformation($v);
+ }
+ }
+
+ return $params;
+ }
+
+ /**
+ * To id card, mobile phone number and other fields sensitive information encryption.
+ *
+ * @param string $string
+ *
+ * @return string
+ *
+ * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
+ * @throws \EasyWeChat\MicroMerchant\Kernel\Exceptions\EncryptException
+ */
+ protected function encryptSensitiveInformation(string $string)
+ {
+ $certificates = $this->app['config']->get('certificate');
+ if (null === $certificates) {
+ throw new InvalidArgumentException('config certificate connot be empty.');
+ }
+
+ $encrypted = '';
+ $publicKeyResource = openssl_get_publickey($certificates);
+ $f = openssl_public_encrypt($string, $encrypted, $publicKeyResource);
+ openssl_free_key($publicKeyResource);
+ if ($f) {
+ return base64_encode($encrypted);
+ }
+
+ throw new EncryptException('Encryption of sensitive information failed');
+ }
+
+ /**
+ * get sensitive fields name.
+ *
+ * @return array
+ */
+ protected function getSensitiveFieldsName()
+ {
+ return [
+ 'id_card_name',
+ 'id_card_number',
+ 'account_name',
+ 'account_number',
+ 'contact',
+ 'contact_phone',
+ 'contact_email',
+ 'legal_person',
+ 'mobile_phone',
+ 'email',
+ ];
+ }
+
+ /**
+ * getSign.
+ *
+ * @param array $params
+ *
+ * @return string
+ *
+ * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
+ */
+ protected function getSign(array $params)
+ {
+ $params = array_filter($params);
+
+ $key = $this->app->getKey();
+
+ $encryptMethod = Support\get_encrypt_method(Support\Arr::get($params, 'sign_type', 'MD5'), $key);
+
+ return Support\generate_sign($params, $key, $encryptMethod);
+ }
+}
diff --git a/addons/weliam_smartcity/vendor/overtrue/wechat/src/MicroMerchant/Kernel/Exceptions/EncryptException.php b/addons/weliam_smartcity/vendor/overtrue/wechat/src/MicroMerchant/Kernel/Exceptions/EncryptException.php
new file mode 100644
index 0000000..dd874ae
--- /dev/null
+++ b/addons/weliam_smartcity/vendor/overtrue/wechat/src/MicroMerchant/Kernel/Exceptions/EncryptException.php
@@ -0,0 +1,23 @@
+
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace EasyWeChat\MicroMerchant\Kernel\Exceptions;
+
+use EasyWeChat\Kernel\Exceptions\Exception;
+
+/**
+ * Class EncryptException.
+ *
+ * @author liuml
+ */
+class EncryptException extends Exception
+{
+}
diff --git a/addons/weliam_smartcity/vendor/overtrue/wechat/src/MicroMerchant/Kernel/Exceptions/InvalidExtensionException.php b/addons/weliam_smartcity/vendor/overtrue/wechat/src/MicroMerchant/Kernel/Exceptions/InvalidExtensionException.php
new file mode 100644
index 0000000..41e21cf
--- /dev/null
+++ b/addons/weliam_smartcity/vendor/overtrue/wechat/src/MicroMerchant/Kernel/Exceptions/InvalidExtensionException.php
@@ -0,0 +1,23 @@
+
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace EasyWeChat\MicroMerchant\Kernel\Exceptions;
+
+use EasyWeChat\Kernel\Exceptions\Exception;
+
+/**
+ * Class InvalidExtensionException.
+ *
+ * @author liuml
+ */
+class InvalidExtensionException extends Exception
+{
+}
diff --git a/addons/weliam_smartcity/vendor/overtrue/wechat/src/MicroMerchant/Kernel/Exceptions/InvalidSignException.php b/addons/weliam_smartcity/vendor/overtrue/wechat/src/MicroMerchant/Kernel/Exceptions/InvalidSignException.php
new file mode 100644
index 0000000..d09d92b
--- /dev/null
+++ b/addons/weliam_smartcity/vendor/overtrue/wechat/src/MicroMerchant/Kernel/Exceptions/InvalidSignException.php
@@ -0,0 +1,23 @@
+
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace EasyWeChat\MicroMerchant\Kernel\Exceptions;
+
+use EasyWeChat\Kernel\Exceptions\Exception;
+
+/**
+ * Class InvalidSignException.
+ *
+ * @author liuml
+ */
+class InvalidSignException extends Exception
+{
+}
diff --git a/addons/weliam_smartcity/vendor/overtrue/wechat/src/MicroMerchant/Material/Client.php b/addons/weliam_smartcity/vendor/overtrue/wechat/src/MicroMerchant/Material/Client.php
new file mode 100644
index 0000000..ee1038a
--- /dev/null
+++ b/addons/weliam_smartcity/vendor/overtrue/wechat/src/MicroMerchant/Material/Client.php
@@ -0,0 +1,73 @@
+
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace EasyWeChat\MicroMerchant\Material;
+
+use EasyWeChat\MicroMerchant\Kernel\BaseClient;
+
+/**
+ * Class Client.
+ *
+ * @author liuml
+ * @DateTime 2019-05-30 14:19
+ */
+class Client extends BaseClient
+{
+ /**
+ * update settlement card.
+ *
+ * @param array $params
+ *
+ * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string
+ *
+ * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
+ * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
+ * @throws \EasyWeChat\MicroMerchant\Kernel\Exceptions\EncryptException
+ * @throws \GuzzleHttp\Exception\GuzzleException
+ */
+ public function setSettlementCard(array $params)
+ {
+ $params['sub_mch_id'] = $params['sub_mch_id'] ?? $this->app['config']->sub_mch_id;
+ $params = $this->processParams(array_merge($params, [
+ 'version' => '1.0',
+ 'cert_sn' => '',
+ 'sign_type' => 'HMAC-SHA256',
+ 'nonce_str' => uniqid('micro'),
+ ]));
+
+ return $this->safeRequest('applyment/micro/modifyarchives', $params);
+ }
+
+ /**
+ * update contact info.
+ *
+ * @param array $params
+ *
+ * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string
+ *
+ * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
+ * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
+ * @throws \EasyWeChat\MicroMerchant\Kernel\Exceptions\EncryptException
+ * @throws \GuzzleHttp\Exception\GuzzleException
+ */
+ public function updateContact(array $params)
+ {
+ $params['sub_mch_id'] = $params['sub_mch_id'] ?? $this->app['config']->sub_mch_id;
+ $params = $this->processParams(array_merge($params, [
+ 'version' => '1.0',
+ 'cert_sn' => '',
+ 'sign_type' => 'HMAC-SHA256',
+ 'nonce_str' => uniqid('micro'),
+ ]));
+
+ return $this->safeRequest('applyment/micro/modifycontactinfo', $params);
+ }
+}
diff --git a/addons/weliam_smartcity/vendor/overtrue/wechat/src/MicroMerchant/Material/ServiceProvider.php b/addons/weliam_smartcity/vendor/overtrue/wechat/src/MicroMerchant/Material/ServiceProvider.php
new file mode 100644
index 0000000..dec5af7
--- /dev/null
+++ b/addons/weliam_smartcity/vendor/overtrue/wechat/src/MicroMerchant/Material/ServiceProvider.php
@@ -0,0 +1,33 @@
+
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace EasyWeChat\MicroMerchant\Material;
+
+use Pimple\Container;
+use Pimple\ServiceProviderInterface;
+
+/**
+ * Class ServiceProvider.
+ *
+ * @author overtrue
+ */
+class ServiceProvider implements ServiceProviderInterface
+{
+ /**
+ * {@inheritdoc}.
+ */
+ public function register(Container $app)
+ {
+ $app['material'] = function ($app) {
+ return new Client($app);
+ };
+ }
+}
diff --git a/addons/weliam_smartcity/vendor/overtrue/wechat/src/MicroMerchant/Media/Client.php b/addons/weliam_smartcity/vendor/overtrue/wechat/src/MicroMerchant/Media/Client.php
new file mode 100644
index 0000000..fde755b
--- /dev/null
+++ b/addons/weliam_smartcity/vendor/overtrue/wechat/src/MicroMerchant/Media/Client.php
@@ -0,0 +1,49 @@
+
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace EasyWeChat\MicroMerchant\Media;
+
+use EasyWeChat\Kernel\Exceptions\InvalidArgumentException;
+use EasyWeChat\MicroMerchant\Kernel\BaseClient;
+
+/**
+ * Class Client.
+ *
+ * @author liuml
+ * @DateTime 2019-06-10 14:50
+ */
+class Client extends BaseClient
+{
+ /**
+ * Upload material.
+ *
+ * @param string $path
+ *
+ * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string
+ *
+ * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
+ * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
+ * @throws \EasyWeChat\MicroMerchant\Kernel\Exceptions\InvalidSignException
+ */
+ public function upload(string $path)
+ {
+ if (!file_exists($path) || !is_readable($path)) {
+ throw new InvalidArgumentException(sprintf("File does not exist, or the file is unreadable: '%s'", $path));
+ }
+
+ $form = [
+ 'media_hash' => strtolower(md5_file($path)),
+ 'sign_type' => 'HMAC-SHA256',
+ ];
+
+ return $this->httpUpload('secapi/mch/uploadmedia', ['media' => $path], $form);
+ }
+}
diff --git a/addons/weliam_smartcity/vendor/overtrue/wechat/src/MicroMerchant/Media/ServiceProvider.php b/addons/weliam_smartcity/vendor/overtrue/wechat/src/MicroMerchant/Media/ServiceProvider.php
new file mode 100644
index 0000000..9d46a84
--- /dev/null
+++ b/addons/weliam_smartcity/vendor/overtrue/wechat/src/MicroMerchant/Media/ServiceProvider.php
@@ -0,0 +1,44 @@
+
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+/**
+ * ServiceProvider.php.
+ *
+ * This file is part of the wechat.
+ *
+ * (c) overtrue
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace EasyWeChat\MicroMerchant\Media;
+
+use Pimple\Container;
+use Pimple\ServiceProviderInterface;
+
+/**
+ * Class ServiceProvider.
+ *
+ * @author overtrue
+ */
+class ServiceProvider implements ServiceProviderInterface
+{
+ /**
+ * {@inheritdoc}.
+ */
+ public function register(Container $app)
+ {
+ $app['media'] = function ($app) {
+ return new Client($app);
+ };
+ }
+}
diff --git a/addons/weliam_smartcity/vendor/overtrue/wechat/src/MicroMerchant/MerchantConfig/Client.php b/addons/weliam_smartcity/vendor/overtrue/wechat/src/MicroMerchant/MerchantConfig/Client.php
new file mode 100644
index 0000000..c8573af
--- /dev/null
+++ b/addons/weliam_smartcity/vendor/overtrue/wechat/src/MicroMerchant/MerchantConfig/Client.php
@@ -0,0 +1,134 @@
+
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace EasyWeChat\MicroMerchant\MerchantConfig;
+
+use EasyWeChat\MicroMerchant\Kernel\BaseClient;
+
+/**
+ * Class Client.
+ *
+ * @author liuml
+ * @DateTime 2019-05-30 14:19
+ */
+class Client extends BaseClient
+{
+ /**
+ * Service providers configure recommendation functions for small and micro businesses.
+ *
+ * @param string $subAppId
+ * @param string $subscribeAppId
+ * @param string $receiptAppId
+ * @param string $subMchId
+ *
+ * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string
+ *
+ * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
+ * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
+ * @throws \GuzzleHttp\Exception\GuzzleException
+ */
+ public function setFollowConfig(string $subAppId, string $subscribeAppId, string $receiptAppId = '', string $subMchId = '')
+ {
+ $params = [
+ 'sub_appid' => $subAppId,
+ 'sub_mch_id' => $subMchId ?: $this->app['config']->sub_mch_id,
+ ];
+
+ if (!empty($subscribeAppId)) {
+ $params['subscribe_appid'] = $subscribeAppId;
+ } else {
+ $params['receipt_appid'] = $receiptAppId;
+ }
+
+ return $this->safeRequest('secapi/mkt/addrecommendconf', array_merge($params, [
+ 'sign_type' => 'HMAC-SHA256',
+ 'nonce_str' => uniqid('micro'),
+ ]));
+ }
+
+ /**
+ * Configure the new payment directory.
+ *
+ * @param string $jsapiPath
+ * @param string $appId
+ * @param string $subMchId
+ *
+ * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string
+ *
+ * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
+ * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
+ */
+ public function addPath(string $jsapiPath, string $appId = '', string $subMchId = '')
+ {
+ return $this->addConfig([
+ 'appid' => $appId ?: $this->app['config']->appid,
+ 'sub_mch_id' => $subMchId ?: $this->app['config']->sub_mch_id,
+ 'jsapi_path' => $jsapiPath,
+ ]);
+ }
+
+ /**
+ * bind appid.
+ *
+ * @param string $subAppId
+ * @param string $appId
+ * @param string $subMchId
+ *
+ * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string
+ *
+ * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
+ * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
+ */
+ public function bindAppId(string $subAppId, string $appId = '', string $subMchId = '')
+ {
+ return $this->addConfig([
+ 'appid' => $appId ?: $this->app['config']->appid,
+ 'sub_mch_id' => $subMchId ?: $this->app['config']->sub_mch_id,
+ 'sub_appid' => $subAppId,
+ ]);
+ }
+
+ /**
+ * add sub dev config.
+ *
+ * @param array $params
+ *
+ * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string
+ *
+ * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
+ * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
+ * @throws \GuzzleHttp\Exception\GuzzleException
+ */
+ private function addConfig(array $params)
+ {
+ return $this->safeRequest('secapi/mch/addsubdevconfig', $params);
+ }
+
+ /**
+ * query Sub Dev Config.
+ *
+ * @param string $subMchId
+ * @param string $appId
+ *
+ * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string
+ *
+ * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
+ * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
+ * @throws \GuzzleHttp\Exception\GuzzleException
+ */
+ public function getConfig(string $subMchId = '', string $appId = '')
+ {
+ return $this->safeRequest('secapi/mch/querysubdevconfig', [
+ 'sub_mch_id' => $subMchId ?: $this->app['config']->sub_mch_id,
+ 'appid' => $appId ?: $this->app['config']->appid,
+ ]);
+ }
+}
diff --git a/addons/weliam_smartcity/vendor/overtrue/wechat/src/MicroMerchant/MerchantConfig/ServiceProvider.php b/addons/weliam_smartcity/vendor/overtrue/wechat/src/MicroMerchant/MerchantConfig/ServiceProvider.php
new file mode 100644
index 0000000..5b78710
--- /dev/null
+++ b/addons/weliam_smartcity/vendor/overtrue/wechat/src/MicroMerchant/MerchantConfig/ServiceProvider.php
@@ -0,0 +1,33 @@
+
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace EasyWeChat\MicroMerchant\MerchantConfig;
+
+use Pimple\Container;
+use Pimple\ServiceProviderInterface;
+
+/**
+ * Class ServiceProvider.
+ *
+ * @author overtrue
+ */
+class ServiceProvider implements ServiceProviderInterface
+{
+ /**
+ * {@inheritdoc}.
+ */
+ public function register(Container $app)
+ {
+ $app['merchantConfig'] = function ($app) {
+ return new Client($app);
+ };
+ }
+}
diff --git a/addons/weliam_smartcity/vendor/overtrue/wechat/src/MicroMerchant/Withdraw/Client.php b/addons/weliam_smartcity/vendor/overtrue/wechat/src/MicroMerchant/Withdraw/Client.php
new file mode 100644
index 0000000..c96c363
--- /dev/null
+++ b/addons/weliam_smartcity/vendor/overtrue/wechat/src/MicroMerchant/Withdraw/Client.php
@@ -0,0 +1,67 @@
+
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace EasyWeChat\MicroMerchant\Withdraw;
+
+use EasyWeChat\MicroMerchant\Kernel\BaseClient;
+
+/**
+ * Class Client.
+ *
+ * @author liuml
+ * @DateTime 2019-05-30 14:19
+ */
+class Client extends BaseClient
+{
+ /**
+ * Query withdrawal status.
+ *
+ * @param string $date
+ * @param string $subMchId
+ *
+ * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string
+ *
+ * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
+ * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
+ * @throws \GuzzleHttp\Exception\GuzzleException
+ */
+ public function queryWithdrawalStatus($date, $subMchId = '')
+ {
+ return $this->safeRequest('fund/queryautowithdrawbydate', [
+ 'date' => $date,
+ 'sign_type' => 'HMAC-SHA256',
+ 'nonce_str' => uniqid('micro'),
+ 'sub_mch_id' => $subMchId ?: $this->app['config']->sub_mch_id,
+ ]);
+ }
+
+ /**
+ * Re-initiation of withdrawal.
+ *
+ * @param string $date
+ * @param string $subMchId
+ *
+ * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string
+ *
+ * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
+ * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
+ * @throws \GuzzleHttp\Exception\GuzzleException
+ */
+ public function requestWithdraw($date, $subMchId = '')
+ {
+ return $this->safeRequest('fund/reautowithdrawbydate', [
+ 'date' => $date,
+ 'sign_type' => 'HMAC-SHA256',
+ 'nonce_str' => uniqid('micro'),
+ 'sub_mch_id' => $subMchId ?: $this->app['config']->sub_mch_id,
+ ]);
+ }
+}
diff --git a/addons/weliam_smartcity/vendor/overtrue/wechat/src/MicroMerchant/Withdraw/ServiceProvider.php b/addons/weliam_smartcity/vendor/overtrue/wechat/src/MicroMerchant/Withdraw/ServiceProvider.php
new file mode 100644
index 0000000..b9c0141
--- /dev/null
+++ b/addons/weliam_smartcity/vendor/overtrue/wechat/src/MicroMerchant/Withdraw/ServiceProvider.php
@@ -0,0 +1,33 @@
+
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace EasyWeChat\MicroMerchant\Withdraw;
+
+use Pimple\Container;
+use Pimple\ServiceProviderInterface;
+
+/**
+ * Class ServiceProvider.
+ *
+ * @author overtrue
+ */
+class ServiceProvider implements ServiceProviderInterface
+{
+ /**
+ * {@inheritdoc}.
+ */
+ public function register(Container $app)
+ {
+ $app['withdraw'] = function ($app) {
+ return new Client($app);
+ };
+ }
+}