withStatus(500); } $certPath = dirname(__DIR__) . DIRECTORY_SEPARATOR . '319245319-320109623_PROD.cer'; $keyPath = dirname(__DIR__) . DIRECTORY_SEPARATOR . '319245319-320109623_PROD.key'; if (!file_exists($certPath) || !file_exists($keyPath)) { return ResponseLib::sendFail('Client certificate or key not found', ['cert' => $certPath, 'key' => $keyPath], 'E_INTERNAL')->withStatus(500); } // Send grant_type + client credentials in body in the same order as the working curl $postFields = 'grant_type=' . ($grantType); $ch = curl_init($b3Url); curl_setopt($ch, CURLOPT_POST, true); $headers = [ 'Content-Type: application/x-www-form-urlencoded', 'Accept: application/json', ]; curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); curl_setopt($ch, CURLOPT_POSTFIELDS, $postFields); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); // mTLS client certificate curl_setopt($ch, CURLOPT_SSLCERT, $certPath); curl_setopt($ch, CURLOPT_SSLCERTTYPE, 'PEM'); curl_setopt($ch, CURLOPT_SSLKEY, $keyPath); curl_setopt($ch, CURLOPT_SSLKEYTYPE, 'PEM'); if ($certPass) { curl_setopt($ch, CURLOPT_SSLKEYPASSWD, $certPass); } // Keep verification enabled (recommended) curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2); $responseBody = curl_exec($ch); $curlErrNo = curl_errno($ch); $curlErr = curl_error($ch); $httpCode = (int) curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch); if ($curlErrNo !== 0) { return ResponseLib::sendFail('cURL error during B3 token request', ['error' => $curlErr, 'code' => $curlErrNo], 'E_EXTERNAL')->withStatus(502); } $decoded = json_decode($responseBody, true); if ($decoded === null) { // Not a JSON body; return raw text for troubleshooting return Response::json(['raw' => $responseBody, 'status' => $httpCode])->withStatus($httpCode ?: 502); } return Response::json($decoded)->withStatus($httpCode ?: 200); } }