Anankke/SSPanel-UIM · error · App\Services\Gateway\Cryptomus\RequestBuilderException

curl_error($curl)

Error message

curl_error($curl)

What it means

This exception is thrown when the cURL call to the Cryptomus API fails at the transport level: curl_exec() returned false, so no HTTP response was ever received. The exception message is the raw libcurl error string (e.g. "Could not resolve host: api.cryptomus.com", "Connection timed out", "SSL certificate problem") and the code is curl_getinfo(CURLINFO_HTTP_CODE), which is 0 because the request never completed. Note that RequestBuilder sets no CURLOPT_CONNECTTIMEOUT/CURLOPT_TIMEOUT, so a hung connection only ends when PHP's max_execution_time aborts the script.

Source

Thrown at src/Services/Gateway/Cryptomus/RequestBuilder.php:57

            'sign: ' . md5(base64_encode($body) . $this->secretKey),
        ];

        curl_setopt_array(
            $curl,
            [
                CURLOPT_URL => $url,
                CURLOPT_HTTPHEADER => $headers,
                CURLOPT_POST => 1,
                CURLOPT_POSTFIELDS => $body,
                CURLOPT_RETURNTRANSFER => 1,
            ],
        );

        $response = curl_exec($curl);
        $responseCode = curl_getinfo($curl, CURLINFO_HTTP_CODE);

        if ($response === false) {
            throw new RequestBuilderException(curl_error($curl), $responseCode, $uri);
        }

        if ($response !== '') {
            $json = json_decode($response, true);
            if ($json === null) {
                throw new RequestBuilderException(json_last_error_msg(), $responseCode, $uri);
            }

            if ($responseCode !== 200 || ($json['state'] !== null && $json['state'] !== 0)) {
                if (isset($json['message']) && $json['message'] !== '') {
                    throw new RequestBuilderException($json['message'], $responseCode, $uri);
                }

                if (isset($json['errors']) && $json['errors'] !== []) {
                    throw new RequestBuilderException('Validation error', $responseCode, $uri, $json['errors']);
                }
            }

View on GitHub (pinned to d55a607191)

Solutions

  1. From the same host, run: curl -v https://api.cryptomus.com/payment-services to confirm whether the failure is DNS, TCP, or TLS — the exception message mirrors this output.
  2. If the error mentions SSL certificates, set curl.cainfo / openssl.cafile in php.ini to an up-to-date cacert.pem (https://curl.se/ca/).
  3. Ensure the environment allows outbound HTTPS to api.cryptomus.com (firewall/egress rules, DNS resolver working, proxy env vars correct or unset if unused).
  4. Add CURLOPT_CONNECTTIMEOUT and CURLOPT_TIMEOUT to the curl_setopt_array call so network hangs fail fast instead of burning max_execution_time.
  5. Retry with backoff on exception code 0 — transport failures are frequently transient.

Example fix

// before
curl_setopt_array($curl, [
    CURLOPT_URL => $url,
    CURLOPT_HTTPHEADER => $headers,
    CURLOPT_POST => 1,
    CURLOPT_POSTFIELDS => $body,
    CURLOPT_RETURNTRANSFER => 1,
]);

// after
curl_setopt_array($curl, [
    CURLOPT_URL => $url,
    CURLOPT_HTTPHEADER => $headers,
    CURLOPT_POST => 1,
    CURLOPT_POSTFIELDS => $body,
    CURLOPT_RETURNTRANSFER => 1,
    CURLOPT_CONNECTTIMEOUT => 5,
    CURLOPT_TIMEOUT => 30,
]);
// caller:
try {
    $rb->sendRequest('v1/payment', $data);
} catch (RequestBuilderException $e) {
    if ($e->getCode() === 0) { /* transport failure: retry with backoff */ }
}
Defensive patterns

Strategy: retry

Validate before calling

// Before constructing RequestBuilder, fail fast on obviously bad config
$secretKey = trim((string) config('cryptomus_key'));
$merchantUuid = trim((string) config('cryptomus_uuid'));
if ($secretKey === '' || $merchantUuid === '') {
    throw new InvalidArgumentException('Cryptomus secret key / merchant UUID not configured');
}
// Optional cheap connectivity probe (skips the full payment call)
if (gethostbyname('api.cryptomus.com') === 'api.cryptomus.com') {
    throw new RuntimeException('Cannot resolve api.cryptomus.com — check DNS/egress');
}

Try / catch

try {
    $result = $rb->sendRequest('v1/payment', $data);
} catch (App\Services\Gateway\Cryptomus\RequestBuilderException $e) {
    if ($e->getCode() === 0) {
        // transport-level curl failure ($e->getMessage() is the curl_error string)
        // safe to retry with exponential backoff: 1s, 2s, 4s
        return retryWithBackoff(fn () => $rb->sendRequest('v1/payment', $data), 3);
    }
    throw $e; // real API response — do not blind-retry
}

Prevention

When it happens

Trigger: sendRequest() POSTing to https://api.cryptomus.com/<uri> when: DNS for api.cryptomus.com cannot be resolved; the host or an intermediate firewall drops the TCP connection (timed out / connection refused); TLS negotiation fails (missing/outdated CA bundle on old PHP/cURL builds, e.g. "SSL certificate problem: unable to get local issuer certificate"); the server runs in an environment with no outbound internet (local dev, CI container, restricted production egress); a misconfigured HTTPS proxy env var (http_proxy/HTTPS_PROXY) makes curl dial the wrong host.

Common situations: Panel deployed on a VPS/hosting box with blocked outbound traffic to crypto-related domains; localhost/CI testing without network access; PHP 7.x with an outdated cacert.pem (CRYPTOMus requires TLS to api.cryptomus.com); IPv6-preferring hosts where AAAA lookup fails; corporate proxy not configured into curl.

Related errors


AI-assisted analysis of Anankke/SSPanel-UIM@d55a607191 (2026-08-21). Data as JSON: /api/errors/389e3415545e83c0. Report an issue: GitHub.