Tratamento de Erros
Guia completo para entender e tratar erros da API DiviPay.
Códigos de Status HTTP
| Código | Significado | Descrição |
|---|---|---|
| 200 | OK | Requisição bem-sucedida (GET) |
| 201 | Created | Recurso criado com sucesso (POST) |
| 400 | Bad Request | Dados inválidos na requisição |
| 401 | Unauthorized | Credenciais inválidas |
| 403 | Forbidden | Token inválido ou sem permissão |
| 404 | Not Found | Recurso não encontrado |
| 412 | Precondition Failed | Pré-condição não atendida |
| 422 | Unprocessable Entity | Validação de negócio falhou |
| 429 | Too Many Requests | Rate limit excedido |
| 500 | Internal Server Error | Erro interno do servidor |
| 503 | Service Unavailable | Serviço temporariamente indisponível |
Formato de Erro
Todos os erros seguem o mesmo formato:
json
{
"statusCode": 400,
"message": "Validation failed",
"error": "Bad Request",
"errors": [
"amount must be a positive number",
"client.document must be a valid CPF or CNPJ"
]
}Erros Comuns
401 Unauthorized
Causa: Credenciais inválidas ou API não habilitada.
json
{
"statusCode": 401,
"message": "Unauthorized",
"error": "Invalid credentials"
}Solução:
- Verifique
client_ideclient_secret - Confirme que a API está habilitada no painel
- Verifique se não há espaços extras
403 Forbidden
Causa: Token inválido, expirado ou sem permissão.
json
{
"statusCode": 403,
"message": "Forbidden"
}Solução:
- Renove o token
- Verifique se o token está correto
- Confirme que o token não expirou
400 Bad Request
Causa: Dados inválidos na requisição.
json
{
"statusCode": 400,
"message": "Validation failed",
"errors": [
"amount must be a positive number",
"description is required"
]
}Solução:
- Valide todos os campos obrigatórios
- Verifique tipos de dados
- Confirme formato dos valores
404 Not Found
Causa: Recurso não encontrado.
json
{
"statusCode": 404,
"message": "Charge not found",
"error": "Not Found"
}Solução:
- Verifique se o ID está correto
- Confirme que o recurso existe
- Verifique permissões de acesso
412 Precondition Failed
Causa: Operação não permitida no estado atual.
json
{
"statusCode": 412,
"message": "Cannot cancel a paid charge",
"error": "Precondition Failed"
}Solução:
- Verifique o status do recurso
- Confirme se a operação é permitida
- Consulte a documentação da operação
429 Too Many Requests
Causa: Rate limit excedido.
json
{
"statusCode": 429,
"message": "Too many requests",
"error": "Rate limit exceeded",
"retryAfter": 60
}Solução:
- Aguarde o tempo indicado em
retryAfter - Implemente backoff exponencial
- Reduza frequência de requisições
Tratamento de Erros
JavaScript
javascript
class DiviPayError extends Error {
constructor(statusCode, message, errors = []) {
super(message);
this.name = 'DiviPayError';
this.statusCode = statusCode;
this.errors = errors;
}
}
async function makeRequest(endpoint, options) {
try {
const response = await fetch(endpoint, options);
if (!response.ok) {
const error = await response.json();
throw new DiviPayError(
error.statusCode,
error.message,
error.errors
);
}
return await response.json();
} catch (error) {
if (error instanceof DiviPayError) {
// Erro da API
console.error('API Error:', error.message);
console.error('Status:', error.statusCode);
console.error('Details:', error.errors);
// Tratar por tipo
switch (error.statusCode) {
case 401:
// Reautenticar
await authenticate();
return makeRequest(endpoint, options);
case 429:
// Aguardar e tentar novamente
await sleep(60000);
return makeRequest(endpoint, options);
case 500:
case 503:
// Tentar novamente com backoff
return retryWithBackoff(() => makeRequest(endpoint, options));
default:
throw error;
}
} else {
// Erro de rede ou outro
console.error('Network Error:', error);
throw error;
}
}
}
// Retry com backoff exponencial
async function retryWithBackoff(fn, maxRetries = 3) {
for (let i = 0; i < maxRetries; i++) {
try {
return await fn();
} catch (error) {
if (i === maxRetries - 1) throw error;
const delay = Math.pow(2, i) * 1000;
console.log(`Retry ${i + 1}/${maxRetries} after ${delay}ms`);
await sleep(delay);
}
}
}
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}PHP
php
<?php
class DiviPayException extends Exception {
private $statusCode;
private $errors;
public function __construct($statusCode, $message, $errors = []) {
parent::__construct($message);
$this->statusCode = $statusCode;
$this->errors = $errors;
}
public function getStatusCode() {
return $this->statusCode;
}
public function getErrors() {
return $this->errors;
}
}
function makeRequest($endpoint, $method = 'GET', $data = null) {
$ch = curl_init($endpoint);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method);
if ($data) {
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']);
}
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
$data = json_decode($response, true);
if ($httpCode < 200 || $httpCode >= 300) {
throw new DiviPayException(
$data['statusCode'] ?? $httpCode,
$data['message'] ?? 'Unknown error',
$data['errors'] ?? []
);
}
return $data;
}
// Uso com tratamento
try {
$charge = makeRequest('/api/charge/pix', 'POST', $chargeData);
echo "Cobrança criada: " . $charge['id'];
} catch (DiviPayException $e) {
error_log("API Error: " . $e->getMessage());
error_log("Status: " . $e->getStatusCode());
error_log("Errors: " . json_encode($e->getErrors()));
switch ($e->getStatusCode()) {
case 401:
// Reautenticar
authenticate();
break;
case 400:
// Mostrar erros de validação
foreach ($e->getErrors() as $error) {
echo "Erro: $error\n";
}
break;
default:
throw $e;
}
}
?>Python
python
class DiviPayError(Exception):
def __init__(self, status_code, message, errors=None):
super().__init__(message)
self.status_code = status_code
self.errors = errors or []
def make_request(endpoint, method='GET', data=None):
try:
if method == 'GET':
response = requests.get(endpoint)
elif method == 'POST':
response = requests.post(endpoint, json=data)
elif method == 'PUT':
response = requests.put(endpoint, json=data)
elif method == 'DELETE':
response = requests.delete(endpoint)
if response.status_code < 200 or response.status_code >= 300:
error_data = response.json()
raise DiviPayError(
error_data.get('statusCode', response.status_code),
error_data.get('message', 'Unknown error'),
error_data.get('errors', [])
)
return response.json()
except DiviPayError as e:
print(f'API Error: {e}')
print(f'Status: {e.status_code}')
print(f'Errors: {e.errors}')
if e.status_code == 401:
# Reautenticar
authenticate()
return make_request(endpoint, method, data)
elif e.status_code == 429:
# Aguardar e tentar novamente
time.sleep(60)
return make_request(endpoint, method, data)
else:
raise
# Uso
try:
charge = make_request('/api/charge/pix', 'POST', charge_data)
print(f'Cobrança criada: {charge["id"]}')
except DiviPayError as e:
print(f'Erro ao criar cobrança: {e}')Validação de Dados
Antes de Enviar
javascript
function validateChargeData(data) {
const errors = [];
if (!data.amount || data.amount <= 0) {
errors.push('Amount must be positive');
}
if (!data.description || data.description.length > 25) {
errors.push('Description is required (max 25 chars)');
}
if (!data.client?.document || !isValidCPF(data.client.document)) {
errors.push('Valid CPF/CNPJ is required');
}
if (!data.client?.email || !isValidEmail(data.client.email)) {
errors.push('Valid email is required');
}
if (errors.length > 0) {
throw new Error(`Validation failed:\n${errors.join('\n')}`);
}
}
// Uso
try {
validateChargeData(chargeData);
const charge = await createCharge(chargeData);
} catch (error) {
console.error('Validation error:', error.message);
}Logging de Erros
javascript
function logError(error, context = {}) {
const errorLog = {
timestamp: new Date().toISOString(),
error: {
name: error.name,
message: error.message,
statusCode: error.statusCode,
errors: error.errors,
stack: error.stack
},
context
};
// Em produção, enviar para serviço de logging
if (process.env.NODE_ENV === 'production') {
sendToLoggingService(errorLog);
} else {
console.error(JSON.stringify(errorLog, null, 2));
}
}
// Uso
try {
await createCharge(data);
} catch (error) {
logError(error, {
operation: 'createCharge',
userId: user.id,
chargeData: data
});
}Monitoramento
javascript
class ErrorMonitor {
constructor() {
this.errors = [];
}
track(error) {
this.errors.push({
timestamp: Date.now(),
statusCode: error.statusCode,
message: error.message
});
// Limpar erros antigos (> 1 hora)
const oneHourAgo = Date.now() - 60 * 60 * 1000;
this.errors = this.errors.filter(e => e.timestamp > oneHourAgo);
// Alertar se muitos erros
if (this.errors.length > 10) {
this.sendAlert('High error rate detected');
}
}
sendAlert(message) {
console.error('🚨 ALERT:', message);
// Enviar para sistema de alertas
}
}
const monitor = new ErrorMonitor();
// Uso
try {
await createCharge(data);
} catch (error) {
monitor.track(error);
throw error;
}