fix: handle network errors and non-JSON SMS responses as 400 not 500
Catch fetch network errors and non-JSON response bodies to prevent unhandled exceptions from becoming opaque 500s. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 4.6
parent
5c3e3c4bc8
commit
a067e5d260
@@ -26,28 +26,36 @@ export class SmsService {
|
|||||||
|
|
||||||
async send(numero: string, mensaje: string): Promise<{ ok: boolean; id?: string }> {
|
async send(numero: string, mensaje: string): Promise<{ ok: boolean; id?: string }> {
|
||||||
const config = await this.getConfig();
|
const config = await this.getConfig();
|
||||||
if (!config?.api_key) throw new BadRequestException('SMS API key no configurada');
|
if (!config?.api_key) {
|
||||||
|
this.logger.error('SMS API key no configurada en settings');
|
||||||
|
throw new BadRequestException('SMS no configurado. Configure la API key en el panel de administración.');
|
||||||
|
}
|
||||||
|
|
||||||
// El proveedor espera el número sin + (ej: 573001234567)
|
|
||||||
const normalizedNumero = numero.startsWith('+') ? numero.slice(1) : numero;
|
const normalizedNumero = numero.startsWith('+') ? numero.slice(1) : numero;
|
||||||
|
|
||||||
const res = await fetch(SMS_ENDPOINT, {
|
let res: Response;
|
||||||
method: 'POST',
|
try {
|
||||||
headers: {
|
res = await fetch(SMS_ENDPOINT, {
|
||||||
'Content-Type': 'application/json',
|
method: 'POST',
|
||||||
Authorization: `Bearer ${config.api_key}`,
|
headers: {
|
||||||
},
|
'Content-Type': 'application/json',
|
||||||
body: JSON.stringify({ numero: normalizedNumero, mensaje }),
|
Authorization: `Bearer ${config.api_key}`,
|
||||||
});
|
},
|
||||||
|
body: JSON.stringify({ numero: normalizedNumero, mensaje }),
|
||||||
|
});
|
||||||
|
} catch (networkErr) {
|
||||||
|
this.logger.error(`Error de red al conectar con proveedor SMS: ${networkErr}`);
|
||||||
|
throw new BadRequestException('No se pudo conectar con el proveedor de SMS. Intenta de nuevo.');
|
||||||
|
}
|
||||||
|
|
||||||
if (!res.ok) {
|
if (!res.ok) {
|
||||||
const err = await res.json().catch(() => ({ error: res.statusText }));
|
const err = await res.json().catch(() => ({ error: res.statusText }));
|
||||||
this.logger.error(`SMS error ${res.status}: ${JSON.stringify(err)}`);
|
this.logger.error(`SMS error ${res.status}: ${JSON.stringify(err)}`);
|
||||||
throw new BadRequestException(err.error || `Error al enviar SMS: ${res.status}`);
|
throw new BadRequestException(err?.error || err?.message || `Error al enviar SMS: ${res.status}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
const result = await res.json();
|
const result = await res.json().catch(() => ({ ok: true }));
|
||||||
this.logger.log(`SMS enviado a ${numero}`);
|
this.logger.log(`SMS enviado a ${normalizedNumero}`);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user