DouYin.php 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. <?php
  2. namespace Overtrue\Socialite\Providers;
  3. use Overtrue\Socialite\Exceptions\AuthorizeFailedException;
  4. use Overtrue\Socialite\Exceptions\InvalidArgumentException;
  5. use Overtrue\Socialite\User;
  6. /**
  7. * @see http://open.douyin.com/platform
  8. * @see https://open.douyin.com/platform/doc/OpenAPI-overview
  9. */
  10. class DouYin extends Base
  11. {
  12. public const NAME = 'douyin';
  13. protected string $baseUrl = 'https://open.douyin.com';
  14. protected array $scopes = ['user_info'];
  15. protected ?string $openId;
  16. protected function getAuthUrl(): string
  17. {
  18. return $this->buildAuthUrlFromBase($this->baseUrl . '/platform/oauth/connect/');
  19. }
  20. /**
  21. * @return array
  22. */
  23. public function getCodeFields(): array
  24. {
  25. return [
  26. 'client_key' => $this->getClientId(),
  27. 'redirect_uri' => $this->redirectUrl,
  28. 'scope' => $this->formatScopes($this->scopes, $this->scopeSeparator),
  29. 'response_type' => 'code',
  30. ];
  31. }
  32. protected function getTokenUrl(): string
  33. {
  34. return $this->baseUrl . '/oauth/access_token/';
  35. }
  36. /**
  37. * @param string $code
  38. *
  39. * @return array
  40. * @throws \Overtrue\Socialite\Exceptions\AuthorizeFailedException
  41. * @throws \GuzzleHttp\Exception\GuzzleException
  42. *
  43. */
  44. public function tokenFromCode($code): array
  45. {
  46. $response = $this->getHttpClient()->get(
  47. $this->getTokenUrl(),
  48. [
  49. 'query' => $this->getTokenFields($code),
  50. ]
  51. );
  52. $body = \json_decode($response->getBody()->getContents(), true) ?? [];
  53. if (empty($body['data']) || $body['data']['error_code'] != 0) {
  54. throw new AuthorizeFailedException('Invalid token response', $body);
  55. }
  56. $this->withOpenId($body['data']['open_id']);
  57. return $this->normalizeAccessTokenResponse($body['data']);
  58. }
  59. /**
  60. * @param string $code
  61. *
  62. * @return array
  63. */
  64. protected function getTokenFields($code): array
  65. {
  66. return [
  67. 'client_key' => $this->getClientId(),
  68. 'client_secret' => $this->getClientSecret(),
  69. 'code' => $code,
  70. 'grant_type' => 'authorization_code',
  71. ];
  72. }
  73. /**
  74. * @param string $token
  75. *
  76. * @return array
  77. * @throws \Overtrue\Socialite\Exceptions\InvalidArgumentException
  78. * @throws \GuzzleHttp\Exception\GuzzleException
  79. *
  80. */
  81. protected function getUserByToken(string $token): array
  82. {
  83. $userUrl = $this->baseUrl . '/oauth/userinfo/';
  84. if (empty($this->openId)) {
  85. throw new InvalidArgumentException('please set open_id before your query.');
  86. }
  87. $response = $this->getHttpClient()->get(
  88. $userUrl,
  89. [
  90. 'query' => [
  91. 'access_token' => $token,
  92. 'open_id' => $this->openId,
  93. ],
  94. ]
  95. );
  96. $body = \json_decode($response->getBody()->getContents(), true);
  97. return $body['data'] ?? [];
  98. }
  99. /**
  100. * @param array $user
  101. *
  102. * @return \Overtrue\Socialite\User
  103. */
  104. protected function mapUserToObject(array $user): User
  105. {
  106. return new User(
  107. [
  108. 'id' => $user['open_id'] ?? null,
  109. 'name' => $user['nickname'] ?? null,
  110. 'nickname' => $user['nickname'] ?? null,
  111. 'avatar' => $user['avatar'] ?? null,
  112. 'email' => $user['email'] ?? null,
  113. ]
  114. );
  115. }
  116. public function withOpenId(string $openId): self
  117. {
  118. $this->openId = $openId;
  119. return $this;
  120. }
  121. }