VPS and dedicated server ordering, managed panels, SSO, billing, and launcher integration — forked from hosting infrastructure with server-focused routes and dashboard. Co-authored-by: Cursor <cursoragent@cursor.com>
59 lines
1.6 KiB
PHP
59 lines
1.6 KiB
PHP
<?php
|
|
|
|
namespace App\Exceptions;
|
|
|
|
use RuntimeException;
|
|
|
|
class ContaboApiException extends RuntimeException
|
|
{
|
|
/**
|
|
* @param array<string, mixed>|null $payload
|
|
*/
|
|
public function __construct(
|
|
public readonly int $httpStatus,
|
|
public readonly ?array $payload,
|
|
string $message,
|
|
) {
|
|
parent::__construct($message);
|
|
}
|
|
|
|
public static function fromResponse(int $httpStatus, string $body): self
|
|
{
|
|
$payload = json_decode($body, true);
|
|
$decoded = is_array($payload) ? $payload : null;
|
|
|
|
$apiMessage = '';
|
|
if (is_array($decoded)) {
|
|
$apiMessage = (string) ($decoded['message'] ?? $decoded['error'] ?? $decoded['statusCode']['message'] ?? '');
|
|
}
|
|
|
|
$message = $apiMessage !== ''
|
|
? $apiMessage
|
|
: "Contabo API error (HTTP {$httpStatus})";
|
|
|
|
return new self($httpStatus, $decoded, $message);
|
|
}
|
|
|
|
public function isPaymentRequired(): bool
|
|
{
|
|
if ($this->httpStatus === 402) {
|
|
return true;
|
|
}
|
|
|
|
return self::messageIndicatesPaymentRequired($this->getMessage())
|
|
|| self::messageIndicatesPaymentRequired(json_encode($this->payload) ?: '');
|
|
}
|
|
|
|
public static function messageIndicatesPaymentRequired(string $text): bool
|
|
{
|
|
if ($text === '') {
|
|
return false;
|
|
}
|
|
|
|
return (bool) preg_match(
|
|
'/\b402\b|payment\s+required|insufficient\s+(?:account\s+)?balance|not\s+enough\s+(?:credit|funds)|account\s+balance|additional\s+pay(?:ed|ment)\s+service|out\s+of\s+funds/i',
|
|
$text
|
|
);
|
|
}
|
|
}
|