ExternalApiException.php 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. <?php
  2. namespace App\Module\Transfer\Exceptions;
  3. /**
  4. * 外部API异常
  5. */
  6. class ExternalApiException extends TransferException
  7. {
  8. private string $apiUrl;
  9. private string $method;
  10. private array $requestData;
  11. private ?array $responseData;
  12. private int $httpStatus;
  13. public function __construct(
  14. string $apiUrl,
  15. string $method,
  16. array $requestData = [],
  17. ?array $responseData = null,
  18. int $httpStatus = 0,
  19. string $message = '外部API调用失败'
  20. ) {
  21. $this->apiUrl = $apiUrl;
  22. $this->method = $method;
  23. $this->requestData = $requestData;
  24. $this->responseData = $responseData;
  25. $this->httpStatus = $httpStatus;
  26. $context = [
  27. 'api_url' => $apiUrl,
  28. 'method' => $method,
  29. 'request_data' => $requestData,
  30. 'response_data' => $responseData,
  31. 'http_status' => $httpStatus,
  32. ];
  33. parent::__construct($message, 2001, null, $context);
  34. }
  35. /**
  36. * 获取API URL
  37. */
  38. public function getApiUrl(): string
  39. {
  40. return $this->apiUrl;
  41. }
  42. /**
  43. * 获取请求方法
  44. */
  45. public function getMethod(): string
  46. {
  47. return $this->method;
  48. }
  49. /**
  50. * 获取请求数据
  51. */
  52. public function getRequestData(): array
  53. {
  54. return $this->requestData;
  55. }
  56. /**
  57. * 获取响应数据
  58. */
  59. public function getResponseData(): ?array
  60. {
  61. return $this->responseData;
  62. }
  63. /**
  64. * 获取HTTP状态码
  65. */
  66. public function getHttpStatus(): int
  67. {
  68. return $this->httpStatus;
  69. }
  70. /**
  71. * 判断是否为网络错误
  72. */
  73. public function isNetworkError(): bool
  74. {
  75. return $this->httpStatus === 0 || $this->httpStatus >= 500;
  76. }
  77. /**
  78. * 判断是否为客户端错误
  79. */
  80. public function isClientError(): bool
  81. {
  82. return $this->httpStatus >= 400 && $this->httpStatus < 500;
  83. }
  84. /**
  85. * 判断是否为服务器错误
  86. */
  87. public function isServerError(): bool
  88. {
  89. return $this->httpStatus >= 500;
  90. }
  91. /**
  92. * 判断是否可以重试
  93. */
  94. public function isRetryable(): bool
  95. {
  96. // 网络错误和服务器错误可以重试
  97. return $this->isNetworkError() || $this->isServerError();
  98. }
  99. /**
  100. * 获取详细错误信息
  101. */
  102. public function getDetailedMessage(): string
  103. {
  104. $message = sprintf(
  105. '外部API调用失败: %s %s (HTTP %d)',
  106. $this->method,
  107. $this->apiUrl,
  108. $this->httpStatus
  109. );
  110. if ($this->responseData) {
  111. $responseMessage = $this->responseData['message'] ?? $this->responseData['error'] ?? '';
  112. if ($responseMessage) {
  113. $message .= ' - ' . $responseMessage;
  114. }
  115. }
  116. return $message;
  117. }
  118. /**
  119. * 创建网络超时异常
  120. */
  121. public static function timeout(string $apiUrl, string $method, array $requestData = []): self
  122. {
  123. return new self(
  124. $apiUrl,
  125. $method,
  126. $requestData,
  127. null,
  128. 0,
  129. '外部API调用超时'
  130. );
  131. }
  132. /**
  133. * 创建HTTP错误异常
  134. */
  135. public static function httpError(
  136. string $apiUrl,
  137. string $method,
  138. int $httpStatus,
  139. array $requestData = [],
  140. ?array $responseData = null
  141. ): self {
  142. $message = "外部API返回HTTP错误: {$httpStatus}";
  143. return new self(
  144. $apiUrl,
  145. $method,
  146. $requestData,
  147. $responseData,
  148. $httpStatus,
  149. $message
  150. );
  151. }
  152. /**
  153. * 创建响应格式错误异常
  154. */
  155. public static function invalidResponse(
  156. string $apiUrl,
  157. string $method,
  158. array $requestData = [],
  159. ?array $responseData = null
  160. ): self {
  161. return new self(
  162. $apiUrl,
  163. $method,
  164. $requestData,
  165. $responseData,
  166. 200,
  167. '外部API响应格式无效'
  168. );
  169. }
  170. }