true, CURLOPT_RETURNTRANSFER => true, CURLOPT_FOLLOWLOCATION => false, CURLOPT_CONNECTTIMEOUT => 5, CURLOPT_TIMEOUT => 15, CURLOPT_HTTPHEADER => [ 'Authorization: Bearer ' . $apiKey, 'Content-Type: application/json', 'Idempotency-Key: ' . $operationKey, ], CURLOPT_POSTFIELDS => json_encode(['amountCents' => 10000, 'description' => 'Pedido 000001'], JSON_THROW_ON_ERROR), ]); $raw = curl_exec($curl); $status = (int) curl_getinfo($curl, CURLINFO_RESPONSE_CODE); curl_close($curl); if ($raw === false) { throw new RuntimeException('Resultado sem confirmação. Preserve o mesmo corpo e a chave persistida; consulte a operação antes de tentar novamente.'); } try { $result = json_decode($raw, true, 512, JSON_THROW_ON_ERROR); } catch (JsonException) { throw new RuntimeException('Resposta sem confirmação válida. Preserve a chave e consulte o mesmo pedido.'); } if ($status < 200 || $status >= 300) { // Registre código e requestId; não registre o bearer nem os dados de pagadores. $detail = is_array($result) && is_array($result['error'] ?? null) ? $result['error'] : []; throw new RuntimeException('HTTP ' . $status . ' / ' . ($detail['code'] ?? 'HTTP_ERROR') . ' / requestId: ' . ($detail['requestId'] ?? 'indisponivel')); } if (!is_array($result) || !is_string($result['id'] ?? null) || trim($result['id']) === '' || !is_string($result['status'] ?? null) || $result['status'] === '' || ($result['amountCents'] ?? null) !== 10000) { throw new RuntimeException('Resposta sem confirmação válida. Preserve a chave e consulte o mesmo pedido.'); } // Persista $result['id'] junto da chave do pedido no seu banco. // $result['qrCode'] contém o Pix copia e cola, pagável no ambiente real. echo json_encode(array_intersect_key($result, array_flip(['id', 'status', 'amountCents', 'feeCents', 'netCents'])), JSON_THROW_ON_ERROR) . PHP_EOL;