Cancelar Cobrança
Cancela uma cobrança antes do pagamento ser realizado.
IMPORTANTE
O cancelamento só é possível antes do pagamento. Após o pagamento, use Estornar.
DELETE /api/charge/
Cancela uma cobrança genérica (Link de Pagamento).
Endpoint
DELETE https://api.divipay.com.br/api/charge/{chargeId}Headers
| Header | Valor | Obrigatório |
|---|---|---|
| Authorization | Bearer | Sim |
Path Parameters
| Parâmetro | Tipo | Descrição |
|---|---|---|
| chargeId | string | ID da cobrança |
Exemplo de Requisição
bash
curl -X DELETE https://api.divipay.com.br/api/charge/cob_abc123 \
-H "Authorization: Bearer SEU_TOKEN"javascript
const response = await fetch(
'https://api.divipay.com.br/api/charge/cob_abc123',
{
method: 'DELETE',
headers: {
'Authorization': 'Bearer SEU_TOKEN'
}
}
);
const result = await response.json();python
import requests
response = requests.delete(
'https://api.divipay.com.br/api/charge/cob_abc123',
headers={
'Authorization': 'Bearer SEU_TOKEN'
}
)
result = response.json()Resposta de Sucesso
Status: 200 OK
json
{
"id": "cob_abc123",
"status": "CANCELED",
"message": "Charge canceled successfully"
}DELETE /api/charge/{chargeId}/pix
Cancela uma cobrança Pix específica.
Endpoint
DELETE https://api.divipay.com.br/api/charge/{chargeId}/pixExemplo de Requisição
bash
curl -X DELETE https://api.divipay.com.br/api/charge/cob_abc123/pix \
-H "Authorization: Bearer SEU_TOKEN"Resposta
json
{
"id": "cob_abc123",
"status": "CANCELED",
"canceledAt": "2024-11-04T15:45:00.000Z"
}Exemplo de Uso
Cancelar Cobrança
javascript
async function cancelCharge(chargeId) {
try {
const response = await fetch(
`https://api.divipay.com.br/api/charge/${chargeId}`,
{
method: 'DELETE',
headers: {
'Authorization': `Bearer ${token}`
}
}
);
if (!response.ok) {
const error = await response.json();
throw new Error(error.message);
}
const result = await response.json();
console.log('✅ Cobrança cancelada:', result.id);
return result;
} catch (error) {
console.error('❌ Erro ao cancelar:', error.message);
throw error;
}
}
// Uso
await cancelCharge('cob_abc123');Cancelar com Verificação
javascript
async function safeCancelCharge(chargeId) {
try {
// 1. Verificar status atual
const charge = await fetch(
`https://api.divipay.com.br/api/charge/${chargeId}`,
{
headers: { 'Authorization': `Bearer ${token}` }
}
).then(r => r.json());
// 2. Verificar se pode cancelar
if (charge.status === 'PAID') {
throw new Error('Cobrança já foi paga. Use estorno.');
}
if (charge.status === 'CANCELED') {
console.log('Cobrança já está cancelada');
return charge;
}
if (charge.status === 'EXPIRED') {
console.log('Cobrança já expirou');
return charge;
}
// 3. Cancelar
const response = await fetch(
`https://api.divipay.com.br/api/charge/${chargeId}`,
{
method: 'DELETE',
headers: { 'Authorization': `Bearer ${token}` }
}
);
const result = await response.json();
console.log('✅ Cobrança cancelada com sucesso');
return result;
} catch (error) {
console.error('❌ Erro:', error.message);
throw error;
}
}Cancelar Pedido Completo
javascript
async function cancelOrder(orderId) {
try {
// 1. Buscar cobrança no banco
const order = await db.orders.findUnique({
where: { id: orderId },
include: { charge: true }
});
if (!order.charge) {
throw new Error('Pedido sem cobrança associada');
}
// 2. Cancelar cobrança na DiviPay
await cancelCharge(order.charge.chargeId);
// 3. Atualizar banco de dados
await db.orders.update({
where: { id: orderId },
data: {
status: 'CANCELED',
canceledAt: new Date()
}
});
// 4. Notificar cliente
await sendCancellationEmail(order.customer.email, orderId);
console.log(`✅ Pedido ${orderId} cancelado`);
} catch (error) {
console.error('❌ Erro ao cancelar pedido:', error);
throw error;
}
}Cancelamento em Lote
javascript
async function cancelMultipleCharges(chargeIds) {
const results = {
success: [],
failed: []
};
for (const chargeId of chargeIds) {
try {
await cancelCharge(chargeId);
results.success.push(chargeId);
} catch (error) {
results.failed.push({
chargeId,
error: error.message
});
}
}
console.log(`✅ Canceladas: ${results.success.length}`);
console.log(`❌ Falharam: ${results.failed.length}`);
return results;
}
// Uso
const results = await cancelMultipleCharges([
'cob_abc123',
'cob_def456',
'cob_ghi789'
]);Interface de Cancelamento
javascript
// React Component
function CancelChargeButton({ chargeId, onCancel }) {
const [loading, setLoading] = useState(false);
const [error, setError] = useState(null);
async function handleCancel() {
if (!confirm('Tem certeza que deseja cancelar esta cobrança?')) {
return;
}
setLoading(true);
setError(null);
try {
await cancelCharge(chargeId);
alert('Cobrança cancelada com sucesso!');
onCancel?.();
} catch (err) {
setError(err.message);
alert('Erro ao cancelar: ' + err.message);
} finally {
setLoading(false);
}
}
return (
<div>
<button
onClick={handleCancel}
disabled={loading}
style={{
backgroundColor: 'red',
color: 'white',
padding: '10px 20px',
border: 'none',
borderRadius: '5px',
cursor: loading ? 'not-allowed' : 'pointer'
}}
>
{loading ? 'Cancelando...' : 'Cancelar Cobrança'}
</button>
{error && <p style={{ color: 'red' }}>{error}</p>}
</div>
);
}Webhook
Quando uma cobrança é cancelada, você recebe:
json
{
"event": "charge.canceled",
"chargeId": "cob_abc123",
"referenceId": "pedido-123",
"amount": 100.00,
"canceledAt": "2024-11-04T15:45:00.000Z",
"status": "CANCELED",
"reason": "Cancelado pelo vendedor"
}Respostas de Erro
412 Precondition Failed
Cobrança já foi paga.
json
{
"statusCode": 412,
"message": "Cannot cancel a paid charge",
"error": "Precondition Failed"
}Solução: Use Estornar para cobranças pagas.
404 Not Found
Cobrança não encontrada.
json
{
"statusCode": 404,
"message": "Charge not found",
"error": "Not Found"
}403 Forbidden
Sem permissão para cancelar.
json
{
"statusCode": 403,
"message": "Forbidden"
}Casos de Uso
1. Cliente Desistiu da Compra
javascript
async function handleCustomerCancellation(orderId, reason) {
try {
await cancelOrder(orderId);
await db.cancellations.create({
data: {
orderId,
reason,
canceledBy: 'CUSTOMER',
canceledAt: new Date()
}
});
console.log('Pedido cancelado pelo cliente');
} catch (error) {
console.error('Erro:', error);
}
}2. Produto Fora de Estoque
javascript
async function handleOutOfStock(orderId) {
try {
await cancelOrder(orderId);
await sendEmail({
to: order.customer.email,
subject: 'Pedido Cancelado - Produto Indisponível',
body: 'Infelizmente o produto está fora de estoque...'
});
console.log('Pedido cancelado por falta de estoque');
} catch (error) {
console.error('Erro:', error);
}
}3. Cancelamento Automático por Timeout
javascript
async function cancelExpiredCharges() {
const expiredCharges = await db.charges.findMany({
where: {
status: 'PENDING',
createdAt: {
lt: new Date(Date.now() - 24 * 60 * 60 * 1000) // 24h atrás
}
}
});
for (const charge of expiredCharges) {
try {
await cancelCharge(charge.chargeId);
console.log(`Cobrança ${charge.chargeId} cancelada por timeout`);
} catch (error) {
console.error(`Erro ao cancelar ${charge.chargeId}:`, error);
}
}
}
// Executar diariamente
setInterval(cancelExpiredCharges, 24 * 60 * 60 * 1000);Boas Práticas
1. Sempre Verificar Status
javascript
// ✅ BOM
const charge = await getCharge(chargeId);
if (charge.status === 'PENDING') {
await cancelCharge(chargeId);
}
// ❌ RUIM
await cancelCharge(chargeId); // Pode falhar se já foi pago2. Registrar Motivo
javascript
await db.charges.update({
where: { id: chargeId },
data: {
status: 'CANCELED',
cancelReason: 'Cliente desistiu',
canceledBy: userId,
canceledAt: new Date()
}
});3. Notificar Cliente
javascript
async function cancelWithNotification(chargeId, reason) {
const charge = await cancelCharge(chargeId);
await sendEmail({
to: charge.customer.email,
subject: 'Cobrança Cancelada',
body: `Sua cobrança foi cancelada. Motivo: ${reason}`
});
}4. Tratamento de Erros
javascript
try {
await cancelCharge(chargeId);
} catch (error) {
if (error.message.includes('paid')) {
console.log('Use estorno para cobranças pagas');
} else if (error.message.includes('not found')) {
console.log('Cobrança não existe');
} else {
console.error('Erro desconhecido:', error);
}
}