Auth.php 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  1. <?php
  2. namespace common\components\delivery\platform\shunfeng;
  3. use common\components\delivery\helpers\HttpClient;
  4. use Yii;
  5. class Auth
  6. {
  7. // 授权端点
  8. const AUTHORIZE_URL = 'https://openic.sf-express.com/artascope/cx/receipt/getpage/product/artascope/page/storeBinding';
  9. const TOKEN_URL = '';
  10. protected $appKey;//appId
  11. protected $appSecret;
  12. protected $redirectUri;
  13. protected $isSandbox;
  14. /**
  15. * 初始化授权类
  16. * 根据环境获取配置信息
  17. */
  18. public function __construct()
  19. {
  20. $isProduction = getenv('YII_ENV') == 'production';
  21. if ($isProduction) {
  22. $this->appKey = 1594082399;
  23. $this->appSecret = '9025c4f5ad93e8e08e947f02d0cde652';
  24. } else {
  25. $this->appKey = 1741530942;
  26. $this->appSecret = '07b3f83d19a4a9f89322976c936faf92';
  27. }
  28. // 根据环境设置沙箱标志
  29. $this->isSandbox = !$isProduction;
  30. }
  31. /**
  32. * 设置重定向URI
  33. * 需要进行URLEncode编码
  34. *
  35. * @param string $redirectUri 重定向地址
  36. */
  37. public function setRedirectUri($redirectUri)
  38. {
  39. $this->redirectUri = $redirectUri;
  40. return $this;
  41. }
  42. /**
  43. * 生成授权URL
  44. * 用户需要通过浏览器访问此URL进行授权
  45. *
  46. * @param string $redirectUri 重定向地址(回调地址)
  47. * @return string 授权URL
  48. */
  49. public function generateAuthUrl($mainId)
  50. {
  51. $params = [
  52. 'dev_id' => $this->appKey,
  53. 'out_shop_id' => $mainId,
  54. ];
  55. // 构建URL
  56. $queryString = http_build_query($params);
  57. return self::AUTHORIZE_URL . '?' . $queryString;
  58. }
  59. /**
  60. * 获取AccessToken
  61. * 使用授权码换取令牌
  62. *
  63. * 文档:/oauth/token (GET请求)
  64. * 入参:grant_type, client_id, code, isSandbox
  65. * 出参:access_token, refresh_token, expires_in
  66. *
  67. * @param string $code 授权码(来自授权页面重定向)
  68. * @return array 返回格式:['success' => true/false, 'access_token' => '', 'refresh_token' => '', 'expires_in' => 0, 'error' => '']
  69. */
  70. public function getAccessToken($code)
  71. {
  72. $params = [
  73. 'grant_type' => '',
  74. 'client_id' => $this->appKey,
  75. 'code' => $code,
  76. 'isSandbox' => $this->isSandbox ? 'true' : 'false',
  77. ];
  78. $response = HttpClient::get(self::TOKEN_URL, $params);
  79. Yii::info("[HuoLalaAuthGetToken] Response: " . json_encode($response));
  80. return $this->parseResponse($response);
  81. }
  82. /**
  83. * 刷新AccessToken
  84. * 使用刷新令牌获取新的AccessToken
  85. *
  86. * 文档:/oauth/token (GET请求)
  87. * 入参:grant_type, client_id, refresh_token, isSandbox
  88. * 出参:access_token, refresh_token, expires_in
  89. *
  90. * @param string $refreshToken 刷新令牌
  91. * @return array 返回格式:['success' => true/false, 'access_token' => '', 'refresh_token' => '', 'expires_in' => 0, 'error' => '']
  92. */
  93. public function refreshAccessToken($refreshToken)
  94. {
  95. $params = [
  96. 'grant_type' => '',
  97. 'client_id' => $this->appKey,
  98. 'refresh_token' => $refreshToken,
  99. 'isSandbox' => $this->isSandbox ? 'true' : 'false',
  100. ];
  101. $response = HttpClient::get(self::TOKEN_URL, $params);
  102. Yii::info("[HuoLalaAuthRefreshToken] Response: " . json_encode($response));
  103. return $this->parseResponse($response);
  104. }
  105. /**
  106. * 解析API响应
  107. *
  108. * 货拉拉 API 返回格式:
  109. * {
  110. * "ret": 0,
  111. * "msg": "success",
  112. * "data": {
  113. * "auth_mobile": "17168665598",
  114. * "access_token": "a3207b6b5ad04249ad1dbf6a9824dbea",
  115. * "refresh_token": "4ccbbab0e9e443159c518d1d10741ad",
  116. * "auth_end_time": "2020-06-07 15:35:08"
  117. * }
  118. * }
  119. *
  120. * @param array $response HTTP响应
  121. * @return array 标准化的响应格式
  122. */
  123. protected function parseResponse($response)
  124. {
  125. // 检查 ret 字段(0 表示成功)
  126. if (!isset($response['ret'])) {
  127. return [
  128. 'success' => false,
  129. 'error' => $response['msg'] ?? '响应格式错误,缺少 ret 字段',
  130. ];
  131. }
  132. // 如果 ret 不等于 0,表示请求失败
  133. if ($response['ret'] != 0) {
  134. return [
  135. 'success' => false,
  136. 'error' => $response['msg'] ?? 'API返回异常',
  137. 'ret' => $response['ret'],
  138. ];
  139. }
  140. // 提取 data 字段中的数据
  141. $data = $response['data'] ?? [];
  142. // 检查是否包含必需的token信息
  143. if (empty($data['access_token'])) {
  144. return [
  145. 'success' => false,
  146. 'error' => $response['msg'] ?? '未获取到 access_token',
  147. ];
  148. }
  149. // 成功响应
  150. return [
  151. 'success' => true,
  152. 'access_token' => $data['access_token'] ?? '',
  153. 'refresh_token' => $data['refresh_token'] ?? '',
  154. 'auth_mobile' => $data['auth_mobile'] ?? '',
  155. 'auth_end_time' => $data['auth_end_time'] ?? '',
  156. ];
  157. }
  158. /**
  159. * 获取AppKey
  160. *
  161. * @return string
  162. */
  163. public function getAppKey()
  164. {
  165. return $this->appKey;
  166. }
  167. /**
  168. * 获取AppSecret
  169. *
  170. * @return string
  171. */
  172. public function getAppSecret()
  173. {
  174. return $this->appSecret;
  175. }
  176. /**
  177. * 获取是否为沙箱环境
  178. *
  179. * @return bool
  180. */
  181. public function isSandbox()
  182. {
  183. return $this->isSandbox;
  184. }
  185. }