Auth.php 4.3 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. $response = HttpClient::post($url, $payload);
  54. return $this->parseResponse($response);
  55. }
  56. /**
  57. * 取消授权
  58. *
  59. * 用户不再使用滴滴平台发单,取消授权后token失效,后续再使用需要重新授权
  60. *
  61. * @param string $accessToken 授权token
  62. * @return array ['success' => bool, 'result' => int, 'error' => string]
  63. */
  64. public function cancelAuth($accessToken)
  65. {
  66. // 实例化 Didi 类传入 token,buildRequestPayload 会自动处理 token
  67. $didi = new Didi($accessToken);
  68. // 入参说明无业务参数
  69. $payload = $didi->buildRequestPayload(self::API_CANCEL_AUTH, []);
  70. $url = $didi->getApiUrl(self::API_CANCEL_AUTH);
  71. $response = HttpClient::post($url, $payload);
  72. return $this->parseResponse($response);
  73. }
  74. /**
  75. * 解析 API 响应
  76. *
  77. * @param array $response
  78. * @return array
  79. */
  80. protected function parseResponse($response)
  81. {
  82. // 检查 HttpClient 返回的错误结构
  83. if (isset($response['code']) && isset($response['body']) && !isset($response['errno'])) {
  84. return [
  85. 'success' => false,
  86. 'error' => 'HTTP Request Failed: ' . ($response['error'] ?? $response['body']),
  87. 'code' => $response['code']
  88. ];
  89. }
  90. // 检查滴滴业务错误码 (errno)
  91. if (isset($response['errno'])) {
  92. if ($response['errno'] != 0) {
  93. return [
  94. 'success' => false,
  95. 'error' => $response['errmsg'] ?? 'Unknown API error',
  96. 'errno' => $response['errno']
  97. ];
  98. }
  99. $data = $response['data'] ?? [];
  100. // 构造统一返回格式
  101. $result = [
  102. 'success' => true,
  103. 'data' => $data,
  104. ];
  105. // 提取关键字段到顶层,方便调用
  106. if (isset($data['authUrl'])) {
  107. $result['authUrl'] = $data['authUrl'];
  108. }
  109. if (isset($data['result'])) {
  110. $result['result'] = $data['result'];
  111. }
  112. return $result;
  113. }
  114. // 未知格式
  115. return [
  116. 'success' => false,
  117. 'error' => 'Invalid response format',
  118. 'raw' => $response
  119. ];
  120. }
  121. }