Application.php 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. <?php
  2. /*
  3. * This file is part of the overtrue/wechat.
  4. *
  5. * (c) overtrue <i@overtrue.me>
  6. *
  7. * This source file is subject to the MIT license that is bundled
  8. * with this source code in the file LICENSE.
  9. */
  10. namespace EasyWeChat\OpenPlatform;
  11. use EasyWeChat\Kernel\ServiceContainer;
  12. use EasyWeChat\MiniProgram\Encryptor;
  13. use EasyWeChat\OpenPlatform\Authorizer\Auth\AccessToken;
  14. use EasyWeChat\OpenPlatform\Authorizer\MiniProgram\Application as MiniProgram;
  15. use EasyWeChat\OpenPlatform\Authorizer\MiniProgram\Auth\Client;
  16. use EasyWeChat\OpenPlatform\Authorizer\OfficialAccount\Account\Client as AccountClient;
  17. use EasyWeChat\OpenPlatform\Authorizer\OfficialAccount\Application as OfficialAccount;
  18. use EasyWeChat\OpenPlatform\Authorizer\OfficialAccount\OAuth\ComponentDelegate;
  19. use EasyWeChat\OpenPlatform\Authorizer\Server\Guard;
  20. /**
  21. * Class Application.
  22. *
  23. * @property \EasyWeChat\OpenPlatform\Server\Guard $server
  24. * @property \EasyWeChat\OpenPlatform\Auth\AccessToken $access_token
  25. * @property \EasyWeChat\OpenPlatform\CodeTemplate\Client $code_template
  26. * @property \EasyWeChat\OpenPlatform\Component\Client $component
  27. *
  28. * @method mixed handleAuthorize(string $authCode = null)
  29. * @method mixed getAuthorizer(string $appId)
  30. * @method mixed getAuthorizerOption(string $appId, string $name)
  31. * @method mixed setAuthorizerOption(string $appId, string $name, string $value)
  32. * @method mixed getAuthorizers(int $offset = 0, int $count = 500)
  33. * @method mixed createPreAuthorizationCode()
  34. */
  35. class Application extends ServiceContainer
  36. {
  37. /**
  38. * @var array
  39. */
  40. protected $providers = [
  41. Auth\ServiceProvider::class,
  42. Base\ServiceProvider::class,
  43. Server\ServiceProvider::class,
  44. CodeTemplate\ServiceProvider::class,
  45. Component\ServiceProvider::class,
  46. ];
  47. /**
  48. * @var array
  49. */
  50. protected $defaultConfig = [
  51. 'http' => [
  52. 'timeout' => 5.0,
  53. 'base_uri' => 'https://api.weixin.qq.com/',
  54. ],
  55. ];
  56. /**
  57. * Creates the officialAccount application.
  58. *
  59. * @param string $appId
  60. * @param string|null $refreshToken
  61. * @param \EasyWeChat\OpenPlatform\Authorizer\Auth\AccessToken|null $accessToken
  62. *
  63. * @return \EasyWeChat\OpenPlatform\Authorizer\OfficialAccount\Application
  64. */
  65. public function officialAccount(string $appId, string $refreshToken = null, AccessToken $accessToken = null): OfficialAccount
  66. {
  67. $application = new OfficialAccount($this->getAuthorizerConfig($appId, $refreshToken), $this->getReplaceServices($accessToken) + [
  68. 'encryptor' => $this['encryptor'],
  69. 'account' => function ($app) {
  70. return new AccountClient($app, $this);
  71. },
  72. ]);
  73. $application->extend('oauth', function ($socialite) {
  74. /* @var \Overtrue\Socialite\Providers\WeChatProvider $socialite */
  75. return $socialite->component(new ComponentDelegate($this));
  76. });
  77. return $application;
  78. }
  79. /**
  80. * Creates the miniProgram application.
  81. *
  82. * @param string $appId
  83. * @param string|null $refreshToken
  84. * @param \EasyWeChat\OpenPlatform\Authorizer\Auth\AccessToken|null $accessToken
  85. *
  86. * @return \EasyWeChat\OpenPlatform\Authorizer\MiniProgram\Application
  87. */
  88. public function miniProgram(string $appId, string $refreshToken = null, AccessToken $accessToken = null): MiniProgram
  89. {
  90. return new MiniProgram($this->getAuthorizerConfig($appId, $refreshToken), $this->getReplaceServices($accessToken) + [
  91. 'encryptor' => function () {
  92. return new Encryptor($this['config']['app_id'], $this['config']['token'], $this['config']['aes_key']);
  93. },
  94. 'auth' => function ($app) {
  95. return new Client($app, $this);
  96. },
  97. ]);
  98. }
  99. /**
  100. * Return the pre-authorization login page url.
  101. *
  102. * @param string $callbackUrl
  103. * @param string|array|null $optional
  104. *
  105. * @return string
  106. */
  107. public function getPreAuthorizationUrl(string $callbackUrl, $optional = []): string
  108. {
  109. // 兼容旧版 API 设计
  110. if (\is_string($optional)) {
  111. $optional = [
  112. 'pre_auth_code' => $optional,
  113. ];
  114. } else {
  115. $optional['pre_auth_code'] = $this->createPreAuthorizationCode()['pre_auth_code'];
  116. }
  117. $queries = \array_merge($optional, [
  118. 'component_appid' => $this['config']['app_id'],
  119. 'redirect_uri' => $callbackUrl,
  120. ]);
  121. return 'https://mp.weixin.qq.com/cgi-bin/componentloginpage?'.http_build_query($queries);
  122. }
  123. /**
  124. * Return the pre-authorization login page url (mobile).
  125. *
  126. * @param string $callbackUrl
  127. * @param string|array|null $optional
  128. *
  129. * @return string
  130. */
  131. public function getMobilePreAuthorizationUrl(string $callbackUrl, $optional = []): string
  132. {
  133. // 兼容旧版 API 设计
  134. if (\is_string($optional)) {
  135. $optional = [
  136. 'pre_auth_code' => $optional,
  137. ];
  138. } else {
  139. $optional['pre_auth_code'] = $this->createPreAuthorizationCode()['pre_auth_code'];
  140. }
  141. $queries = \array_merge($optional, [
  142. 'component_appid' => $this['config']['app_id'],
  143. 'redirect_uri' => $callbackUrl,
  144. 'action' => 'bindcomponent',
  145. 'no_scan' => 1,
  146. ]);
  147. return 'https://mp.weixin.qq.com/safe/bindcomponent?'.http_build_query($queries).'#wechat_redirect';
  148. }
  149. /**
  150. * @param string $appId
  151. * @param string|null $refreshToken
  152. *
  153. * @return array
  154. */
  155. protected function getAuthorizerConfig(string $appId, string $refreshToken = null): array
  156. {
  157. return $this['config']->merge([
  158. 'component_app_id' => $this['config']['app_id'],
  159. 'app_id' => $appId,
  160. 'refresh_token' => $refreshToken,
  161. ])->toArray();
  162. }
  163. /**
  164. * @param \EasyWeChat\OpenPlatform\Authorizer\Auth\AccessToken|null $accessToken
  165. *
  166. * @return array
  167. */
  168. protected function getReplaceServices(AccessToken $accessToken = null): array
  169. {
  170. $services = [
  171. 'access_token' => $accessToken ?: function ($app) {
  172. return new AccessToken($app, $this);
  173. },
  174. 'server' => function ($app) {
  175. return new Guard($app);
  176. },
  177. ];
  178. foreach (['cache', 'http_client', 'log', 'logger', 'request'] as $reuse) {
  179. if (isset($this[$reuse])) {
  180. $services[$reuse] = $this[$reuse];
  181. }
  182. }
  183. return $services;
  184. }
  185. /**
  186. * Handle dynamic calls.
  187. *
  188. * @param string $method
  189. * @param array $args
  190. *
  191. * @return mixed
  192. */
  193. public function __call($method, $args)
  194. {
  195. return $this->base->$method(...$args);
  196. }
  197. }