SDK PHP
Instale cobrebase/cobrebase, crie cliente e assinatura com idempotency_key, paginação com all(), webhooks com Webhook::constructEvent e helpers de sandbox.
Instalar
Pacote Composer: cobrebase/cobrebase. PHP 8.2 ou superior. Namespace CobreBase, classe CobreBase. A chave fica no servidor.
composer require cobrebase/cobrebaseIniciar o cliente
cb_test_ é sandbox, cb_live_ é produção. Sem base_url, o cliente chama https://api.cobrebase.com.br.
<?php
require 'vendor/autoload.php';
use CobreBase\CobreBase;
$cb = new CobreBase(getenv('COBREBASE_API_KEY') ?: '');
// Desenvolvimento local (Compose)
$cbLocal = new CobreBase([
'api_key' => getenv('COBREBASE_API_KEY') ?: '',
'base_url' => 'http://localhost:18000',
]);Dinheiro é inteiro em centavos (R$ 10,00 = 1000).
Cliente e assinatura
Todo POST envia Idempotency-Key. Passe idempotency_key no segundo argumento. Rede, 429 e 5xx repetem com a mesma chave.
$customer = $cb->customers->create([
'name' => 'Acme Tecnologia',
'email' => '[email protected]',
], ['idempotency_key' => 'customer-acme-42']);
$subscription = $cb->subscriptions->create([
'customer_id' => $customer['id'],
'items' => [
['price_id' => 'price_...', 'quantity' => 1],
],
], ['idempotency_key' => 'sub-acme-42']);Listagem e paginação
Listas são { data, links, meta }. page começa em 1 e limit vai até 100. all() percorre as páginas:
foreach ($cb->customers->all() as $customer) {
// $customer['id']
}Webhook no body cru
Webhook::constructEvent exige o body cru, antes do json_decode.
<?php
use CobreBase\Webhook;
use CobreBase\WebhookSignatureError;
$payload = file_get_contents('php://input');
$header = $_SERVER['HTTP_COBREBASE_SIGNATURE'] ?? null;
try {
$event = Webhook::constructEvent(
$payload,
$header,
getenv('COBREBASE_WEBHOOK_SECRET') ?: '',
);
} catch (WebhookSignatureError $error) {
http_response_code(400);
exit;
}
if ($event['type'] === 'invoice.paid') {
$invoice = $event['data']['object'];
}Detalhes: documentação de webhooks.
Sandbox: testHelpers e testClocks
Só com cb_test_. Com chave live a API responde 403. Em failPayment o code é string; em payLate, days_late é int.
$cb->testHelpers->confirmPayment('pay_...');
$cb->testHelpers->failPayment('pay_...', 'card_declined');
$cb->testHelpers->expirePayment('pay_...');
$cb->testHelpers->payLate('pay_...', 3);
$cb->testHelpers->fixture('invoice.paid', ['method' => 'pix']);
$clock = $cb->testClocks->create(['frozen_time' => 1700000000]);
$advanced = $cb->testClocks->advance($clock['id'], [
'frozen_time' => 1700086400,
]);
if (($advanced['status'] ?? '') === 'advancing') {
$cb->testClocks->waitUntilReady($clock['id']);
}Erros
Erros sobem como CobreBaseError: status, type, apiCode, getMessage(), param. O código da API está em apiCode porque Exception::$code no PHP é int.
use CobreBase\CobreBaseError;
try {
$cb->customers->create(
['name' => 'Acme'],
['idempotency_key' => 'customer-acme'],
);
} catch (CobreBaseError $error) {
// $error->status, $error->type, $error->apiCode, $error->getMessage(), $error->param
}Contrato HTTP: https://api.cobrebase.com.br/docs.