@criapix/saas-assinaturas-client
Version:
SDK JavaScript/TypeScript para o AssinaturasService - Sistema de gestão de assinaturas SaaS com processamento de pagamentos de faturas (cartão, PIX, débito), gerenciamento de métodos de pagamento, pagamentos recorrentes e análise de falhas de pagamento
233 lines (201 loc) • 7.59 kB
text/typescript
/**
* Helper class for payment failure analysis and retry logic.
* Provides utilities to analyze payment failures and provide user-friendly feedback.
*/
export class PaymentFailureHelper {
/**
* Determines if a payment can be retried based on the failure code/reason.
* @param failureCode - The failure code returned by the payment gateway
* @param failureReason - The failure reason/message
* @returns True if the payment can be retried, false otherwise
*/
static canRetryPayment(failureCode?: string | null, failureReason?: string | null): boolean {
if (!failureCode && !failureReason) {
return true; // No specific error, can retry
}
const code = (failureCode || '').toLowerCase();
const reason = (failureReason || '').toLowerCase();
// NON-RETRYABLE errors
const nonRetryable = [
'invalid_card',
'card_disabled',
'expired_card',
'invalid_cvv',
'invalid_parameter',
'duplicated',
'authentication_required',
'card_error', // Generic card error
'stolen_card',
'lost_card',
'fraud',
'security_code_invalid',
];
if (nonRetryable.some((nr) => code.includes(nr) || reason.includes(nr))) {
return false;
}
// RETRYABLE errors
const retryable = [
'insufficient_funds',
'timeout',
'gateway_error',
'processing_error',
'temporary',
'try_again',
'issuer_unavailable',
'network_error',
'amount_limit_exceeded', // Can retry after some time
];
if (retryable.some((r) => code.includes(r) || reason.includes(r))) {
return true;
}
// Default: allow retry for unknown errors
return true;
}
/**
* Gets a suggested action based on the failure code/reason.
* @param failureCode - The failure code returned by the payment gateway
* @param failureReason - The failure reason/message
* @param canRetry - Whether the payment can be retried
* @returns A user-friendly suggested action message
*/
static getSuggestedAction(
failureCode?: string | null,
failureReason?: string | null,
canRetry?: boolean
): string {
const code = (failureCode || '').toLowerCase();
const reason = (failureReason || '').toLowerCase();
// Card issues - need update
if (
code.includes('invalid_card') ||
code.includes('expired_card') ||
code.includes('card_disabled') ||
reason.includes('cartão inválido') ||
reason.includes('cartão vencido')
) {
return 'Atualize seu método de pagamento com um cartão válido';
}
if (code.includes('stolen_card') || code.includes('lost_card') || code.includes('fraud')) {
return 'Entre em contato com sua instituição financeira ou use outro cartão';
}
if (code.includes('invalid_cvv') || code.includes('security_code_invalid')) {
return 'Verifique o código de segurança (CVV) do seu cartão e tente novamente';
}
// Insufficient funds
if (
code.includes('insufficient_funds') ||
reason.includes('saldo insuficiente') ||
reason.includes('fundos insuficientes')
) {
return 'Verifique o saldo disponível ou aguarde a próxima tentativa automática';
}
// Limit exceeded
if (code.includes('amount_limit_exceeded') || reason.includes('limite excedido')) {
return 'O valor excede o limite do cartão. Aguarde alguns dias e tentaremos novamente';
}
// Temporary/Gateway errors
if (
code.includes('timeout') ||
code.includes('gateway_error') ||
code.includes('processing_error') ||
code.includes('issuer_unavailable') ||
code.includes('network_error')
) {
return 'Erro temporário. Tentaremos processar o pagamento novamente em breve';
}
// Authentication required
if (code.includes('authentication_required')) {
return 'Seu banco requer autenticação adicional. Use outro método de pagamento';
}
// Generic messages
if (!canRetry) {
return 'Atualize seu método de pagamento para continuar';
}
return 'Tentaremos processar o pagamento novamente automaticamente';
}
/**
* Extracts a user-friendly failure reason from code/message.
* @param failureCode - The failure code returned by the payment gateway
* @param failureReason - The failure reason/message
* @param errorMessage - Additional error message
* @returns A user-friendly error message in Portuguese
*/
static getUserFriendlyReason(
failureCode?: string | null,
failureReason?: string | null,
errorMessage?: string | null
): string {
const code = (failureCode || '').toLowerCase();
const reason = (failureReason || '').toLowerCase();
// Map common error codes to user-friendly messages
if (code.includes('insufficient_funds') || reason.includes('saldo insuficiente')) {
return 'Saldo insuficiente no cartão';
}
if (code.includes('expired_card') || reason.includes('cartão vencido')) {
return 'Cartão expirado';
}
if (code.includes('invalid_card') || reason.includes('cartão inválido')) {
return 'Cartão inválido';
}
if (code.includes('invalid_cvv') || code.includes('security_code_invalid')) {
return 'Código de segurança (CVV) inválido';
}
if (code.includes('stolen_card') || code.includes('lost_card')) {
return 'Cartão bloqueado pela instituição financeira';
}
if (code.includes('fraud')) {
return 'Transação negada por suspeita de fraude';
}
if (code.includes('timeout') || code.includes('gateway_error')) {
return 'Erro temporário ao processar pagamento';
}
if (code.includes('amount_limit_exceeded') || reason.includes('limite excedido')) {
return 'Valor excede o limite do cartão';
}
if (code.includes('authentication_required')) {
return 'Autenticação adicional necessária';
}
if (code.includes('issuer_unavailable')) {
return 'Banco emissor temporariamente indisponível';
}
// Return the failure reason if available, otherwise error message
return failureReason || errorMessage || 'Falha ao processar pagamento';
}
}
/**
* Convenience function to check if a payment can be retried
* @param failureCode - The failure code
* @param failureReason - The failure reason
* @returns true if the payment can be retried
*/
export function canRetryPayment(failureCode?: string | null, failureReason?: string | null): boolean {
return PaymentFailureHelper.canRetryPayment(failureCode, failureReason);
}
/**
* Convenience function to get suggested action for a payment failure
* @param failureCode - The failure code
* @param failureReason - The failure reason
* @param canRetry - Whether the payment can be retried
* @returns User-friendly suggested action
*/
export function getSuggestedAction(
failureCode?: string | null,
failureReason?: string | null,
canRetry?: boolean
): string {
return PaymentFailureHelper.getSuggestedAction(failureCode, failureReason, canRetry);
}
/**
* Convenience function to get user-friendly failure reason
* @param failureCode - The failure code
* @param failureReason - The failure reason
* @param errorMessage - Additional error message
* @returns User-friendly error message
*/
export function getUserFriendlyReason(
failureCode?: string | null,
failureReason?: string | null,
errorMessage?: string | null
): string {
return PaymentFailureHelper.getUserFriendlyReason(failureCode, failureReason, errorMessage);
}