$details Details. * @param bool $retryable Retryable. */ public function __construct( private string $errorCode, string $message, private int $status, private array $details = array(), private bool $retryable = false ) { parent::__construct( $message ); } /** * Preserve Cloud error distinctions without changing the local envelope. * * @param int $status HTTP status. * @param array|null $data Cloud envelope. */ public static function fromCloudResponse( int $status, ?array $data ): self { $error = is_array( $data['error'] ?? null ) ? $data['error'] : array(); $code = is_string( $error['code'] ?? null ) ? $error['code'] : ''; $details = $code !== '' ? array( 'cloud_error_code' => $code ) : array(); $retry = $error['details']['retry_after_seconds'] ?? null; if ( is_int( $retry ) && $retry >= 0 ) { $details['retry_after_seconds'] = $retry; } if ( $code === 'affilun_cloud_rate_limited' ) { return new self( $code, 'affilun Cloud is temporarily rate limited.', 429, $details, true ); } if ( $code === 'affilun_cloud_invalid_request' || $status === 400 || $status === 422 ) { return new self( 'affilun_validation_failed', 'Check the affilun Cloud request input.', 422, $details ); } if ( $code === 'affilun_cloud_plan_required' || $status === 402 ) { return new self( 'affilun_cloud_plan_required', 'affilun Cloud plan upgrade is required.', 402, $details ); } if ( in_array( $code, array( 'affilun_cloud_quota_exhausted', 'affilun_cloud_cost_quota_exhausted' ), true ) || $status === 429 ) { return new self( 'affilun_cloud_quota_exhausted', 'affilun Cloud quota exhausted.', 429, $details, true ); } if ( $code === 'affilun_cloud_timestamp_out_of_window' ) { return new self( $code, 'Check the WordPress server clock.', 401, $details ); } if ( $code === 'affilun_cloud_key_revoked' ) { return new self( $code, 'The affilun Cloud API key has been revoked.', 403, $details ); } if ( $status === 401 || $status === 403 ) { return new self( 'affilun_cloud_site_mismatch', 'affilun Cloud site verification failed.', 403, $details ); } if ( $code === 'affilun_cloud_replay_detected' ) { return new self( $code, 'Retry with a new affilun Cloud request.', 409, $details, true ); } if ( $code === 'affilun_cloud_invalid_response' ) { return new self( $code, 'affilun Cloud returned an invalid response.', 503, $details, true ); } return new self( 'affilun_cloud_unavailable', 'affilun Cloud is unavailable.', 503, $details, $status === 0 || $status >= 500 ); } /** * Stable error code. */ public function errorCode(): string { return $this->errorCode; } /** * HTTP status. */ public function status(): int { return $this->status; } /** @return array */ public function details(): array { return $this->details; } /** * Whether retry may succeed. */ public function retryable(): bool { return $this->retryable; } }