TaobaoProvider.php 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  1. <?php
  2. /*
  3. * This file is part of the overtrue/socialite.
  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 Overtrue\Socialite\Providers;
  11. use Overtrue\Socialite\AccessTokenInterface;
  12. use Overtrue\Socialite\ProviderInterface;
  13. use Overtrue\Socialite\User;
  14. /**
  15. * Class TaobaoProvider.
  16. *
  17. * @author mechono <haodouliu@gmail.com>
  18. *
  19. * @see https://open.taobao.com/doc.htm?docId=102635&docType=1&source=search [Taobao - OAuth 2.0 授权登录]
  20. */
  21. class TaobaoProvider extends AbstractProvider implements ProviderInterface
  22. {
  23. /**
  24. * The base url of Taobao API.
  25. *
  26. * @var string
  27. */
  28. protected $baseUrl = 'https://oauth.taobao.com';
  29. /**
  30. * Taobao API service URL address.
  31. *
  32. * @var string
  33. */
  34. protected $gatewayUrl = 'https://eco.taobao.com/router/rest';
  35. /**
  36. * The API version for the request.
  37. *
  38. * @var string
  39. */
  40. protected $version = '2.0';
  41. /**
  42. * @var string
  43. */
  44. protected $format = 'json';
  45. /**
  46. * @var string
  47. */
  48. protected $signMethod = 'md5';
  49. /**
  50. * Web 对应 PC 端(淘宝 logo )浏览器页面样式;Tmall 对应天猫的浏览器页面样式;Wap 对应无线端的浏览器页面样式。
  51. */
  52. protected $view = 'web';
  53. /**
  54. * The scopes being requested.
  55. *
  56. * @var array
  57. */
  58. protected $scopes = ['user_info'];
  59. /**
  60. * Get the authentication URL for the provider.
  61. *
  62. * @param string $state
  63. *
  64. * @return string
  65. */
  66. protected function getAuthUrl($state)
  67. {
  68. return $this->buildAuthUrlFromBase($this->baseUrl.'/authorize', $state);
  69. }
  70. /**
  71. * 获取授权码接口参数.
  72. *
  73. * @param string|null $state
  74. *
  75. * @return array
  76. */
  77. public function getCodeFields($state = null)
  78. {
  79. $fields = [
  80. 'client_id' => $this->getConfig()->get('client_id'),
  81. 'redirect_uri' => $this->redirectUrl,
  82. 'view' => $this->view,
  83. 'response_type' => 'code',
  84. ];
  85. if ($this->usesState()) {
  86. $fields['state'] = $state;
  87. }
  88. return $fields;
  89. }
  90. /**
  91. * Get the token URL for the provider.
  92. *
  93. * @return string
  94. */
  95. protected function getTokenUrl()
  96. {
  97. return $this->baseUrl.'/token';
  98. }
  99. /**
  100. * Get the Post fields for the token request.
  101. *
  102. * @param string $code
  103. *
  104. * @return array
  105. */
  106. protected function getTokenFields($code)
  107. {
  108. return parent::getTokenFields($code) + ['grant_type' => 'authorization_code', 'view' => $this->view];
  109. }
  110. /**
  111. * Get the access token for the given code.
  112. *
  113. * @param string $code
  114. *
  115. * @return \Overtrue\Socialite\AccessToken
  116. */
  117. public function getAccessToken($code)
  118. {
  119. $response = $this->getHttpClient()->post($this->getTokenUrl(), [
  120. 'query' => $this->getTokenFields($code),
  121. ]);
  122. return $this->parseAccessToken($response->getBody()->getContents());
  123. }
  124. /**
  125. * Get the access token from the token response body.
  126. *
  127. * @param string $body
  128. *
  129. * @return \Overtrue\Socialite\AccessToken
  130. */
  131. public function parseAccessToken($body)
  132. {
  133. return parent::parseAccessToken($body);
  134. }
  135. /**
  136. * Get the raw user for the given access token.
  137. *
  138. * @param \Overtrue\Socialite\AccessTokenInterface $token
  139. *
  140. * @return array
  141. */
  142. protected function getUserByToken(AccessTokenInterface $token)
  143. {
  144. $response = $this->getHttpClient()->post($this->getUserInfoUrl($this->gatewayUrl, $token));
  145. return json_decode($response->getBody(), true);
  146. }
  147. /**
  148. * Map the raw user array to a Socialite User instance.
  149. *
  150. * @param array $user
  151. *
  152. * @return \Overtrue\Socialite\User
  153. */
  154. protected function mapUserToObject(array $user)
  155. {
  156. return new User([
  157. 'id' => $this->arrayItem($user, 'open_id'),
  158. 'nickname' => $this->arrayItem($user, 'nick'),
  159. 'name' => $this->arrayItem($user, 'nick'),
  160. 'avatar' => $this->arrayItem($user, 'avatar'),
  161. ]);
  162. }
  163. /**
  164. * @param $params
  165. *
  166. * @return string
  167. */
  168. protected function generateSign($params)
  169. {
  170. ksort($params);
  171. $stringToBeSigned = $this->getConfig()->get('client_secret');
  172. foreach ($params as $k => $v) {
  173. if (!is_array($v) && '@' != substr($v, 0, 1)) {
  174. $stringToBeSigned .= "$k$v";
  175. }
  176. }
  177. $stringToBeSigned .= $this->getConfig()->get('client_secret');
  178. return strtoupper(md5($stringToBeSigned));
  179. }
  180. /**
  181. * @param \Overtrue\Socialite\AccessTokenInterface $token
  182. * @param array $apiFields
  183. *
  184. * @return array
  185. */
  186. protected function getPublicFields(AccessTokenInterface $token, array $apiFields = [])
  187. {
  188. $fields = [
  189. 'app_key' => $this->getConfig()->get('client_id'),
  190. 'sign_method' => $this->signMethod,
  191. 'session' => $token->getToken(),
  192. 'timestamp' => date('Y-m-d H:i:s'),
  193. 'v' => $this->version,
  194. 'format' => $this->format,
  195. ];
  196. $fields = array_merge($apiFields, $fields);
  197. $fields['sign'] = $this->generateSign($fields);
  198. return $fields;
  199. }
  200. /**
  201. * {@inheritdoc}.
  202. */
  203. protected function getUserInfoUrl($url, AccessTokenInterface $token)
  204. {
  205. $apiFields = ['method' => 'taobao.miniapp.userInfo.get'];
  206. $query = http_build_query($this->getPublicFields($token, $apiFields), '', '&', $this->encodingType);
  207. return $url.'?'.$query;
  208. }
  209. }