Auth.php 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. <?php
  2. namespace common\components\delivery\platform\didi;
  3. use common\components\delivery\helpers\HttpClient;
  4. use Yii;
  5. /**
  6. * 滴滴商户授权
  7. *
  8. * 文档参考:
  9. * 获取授权链接:/gateway?api=freight.open.platform.channel.standard.authUrl
  10. * 取消授权:/gateway?api=freight.open.platform.channel.standard.cancelAuth
  11. */
  12. class Auth
  13. {
  14. // API 接口名称
  15. const API_AUTH_URL = 'freight.open.platform.channel.standard.authUrl';
  16. const API_CANCEL_AUTH = 'freight.open.platform.channel.standard.cancelAuth';
  17. /**
  18. * 获取授权页面链接
  19. *
  20. * 用户发单前,需要先进行授权绑定账号,获取此链接跳转到滴滴h5页面进行授权
  21. *
  22. * @param string $thirdUid 接入方用户id
  23. * @param string $cityId 城市id(国标码,市级别)。与lat/lng二选一传递
  24. * @param string $lat 纬度
  25. * @param string $lng 经度
  26. * @return array ['success' => bool, 'authUrl' => string, 'error' => string]
  27. */
  28. public function getAuthUrl($thirdUid, $cityId = '', $lat = '', $lng = '')
  29. {
  30. // 此接口不需要传token参数
  31. $didi = new Didi();
  32. // 校验:城市编码与经纬度二选一
  33. if (empty($cityId) && (empty($lat) || empty($lng))) {
  34. return [
  35. 'success' => false,
  36. 'error' => '参数错误:城市编码(cityId)与经纬度(lat,lng)必须二选一传递'
  37. ];
  38. }
  39. $params = [
  40. 'thirdUid' => (string)$thirdUid,
  41. ];
  42. if ($cityId) {
  43. $params['cityId'] = (string)$cityId;
  44. }
  45. if ($lat) {
  46. $params['lat'] = (float)$lat;
  47. }
  48. if ($lng) {
  49. $params['lng'] = (float)$lng;
  50. }
  51. $payload = $didi->buildRequestPayload($params);
  52. $url = $didi->getApiUrl(self::API_AUTH_URL);
  53. $headers = ["Content-Type" => "application/x-www-form-urlencoded"];
  54. $response = HttpClient::post($url, $payload, $headers);
  55. return $this->parseResponse($response);
  56. }
  57. /**
  58. * 取消授权
  59. *
  60. * 用户不再使用滴滴平台发单,取消授权后token失效,后续再使用需要重新授权
  61. *
  62. * @param string $accessToken 授权token
  63. * @return array ['success' => bool, 'result' => int, 'error' => string]
  64. */
  65. public function cancelAuth($accessToken)
  66. {
  67. // 实例化 Didi 类传入 token,buildRequestPayload 会自动处理 token
  68. $didi = new Didi($accessToken);
  69. // 入参说明无业务参数
  70. $payload = $didi->buildRequestPayload(self::API_CANCEL_AUTH, []);
  71. $url = $didi->getApiUrl(self::API_CANCEL_AUTH);
  72. $headers = ["Content-Type" => "application/x-www-form-urlencoded"];
  73. $response = HttpClient::post($url, $payload, $headers);
  74. return $this->parseResponse($response);
  75. }
  76. /**
  77. * 解析 API 响应
  78. *
  79. * @param array $response
  80. * @return array
  81. */
  82. protected function parseResponse($response)
  83. {
  84. // 检查 HttpClient 返回的错误结构
  85. if (isset($response['code']) && isset($response['body']) && !isset($response['errno'])) {
  86. return [
  87. 'success' => false,
  88. 'error' => 'HTTP Request Failed: ' . ($response['error'] ?? $response['body']),
  89. 'code' => $response['code']
  90. ];
  91. }
  92. // 检查滴滴业务错误码 (errno)
  93. if (isset($response['errno'])) {
  94. if ($response['errno'] != 0) {
  95. return [
  96. 'success' => false,
  97. 'error' => $response['errmsg'] ?? 'Unknown API error',
  98. 'errno' => $response['errno']
  99. ];
  100. }
  101. $data = $response['data'] ?? [];
  102. // 构造统一返回格式
  103. $result = [
  104. 'success' => true,
  105. 'data' => $data,
  106. ];
  107. // 提取关键字段到顶层,方便调用
  108. if (isset($data['authUrl'])) {
  109. $result['authUrl'] = $data['authUrl'];
  110. }
  111. if (isset($data['result'])) {
  112. $result['result'] = $data['result'];
  113. }
  114. return $result;
  115. }
  116. // 未知格式
  117. return [
  118. 'success' => false,
  119. 'error' => 'Invalid response format',
  120. 'raw' => $response
  121. ];
  122. }
  123. }