fix(pagos): permitir pagar plan actual trial_expired y soportar planes >$10k via Preference
- Expone subscription trial_expired en /despachos/me/plan e incluye planPrice. - Para Business Control/Enterprise (>$10k) genera pago anual único con MP Preference en lugar de preapproval recurrente; el webhook activa 1 año de suscripción. - Muestra CTA de pago en UI cuando la suscripción está trial/trial_expired. - Agrega campo mp_preference_id a subscriptions y mejora mensajes de error MP.
This commit is contained in:
@@ -25,6 +25,9 @@ const preApprovalClient = new PreApproval(config);
|
||||
const paymentClient = new MPPayment(config);
|
||||
const preferenceClient = new Preference(config);
|
||||
|
||||
/** Límite de la API legacy de preapproval de MercadoPago para MXN. */
|
||||
export const MP_PREAPPROVAL_MAX_AMOUNT = 10000;
|
||||
|
||||
/**
|
||||
* Fallback público para `back_url` cuando `FRONTEND_URL` apunta a localhost.
|
||||
* MercadoPago rechaza URLs `http://localhost...` o cualquier dominio no
|
||||
@@ -227,6 +230,51 @@ export async function createProrationPreference(params: {
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Crea una Preference (checkout de pago único) para el pago anual de una
|
||||
* suscripción. Se usa cuando el monto supera el límite de preapproval ($10k).
|
||||
* external_reference = `subscription:{tenantId}:{subscriptionId}` para que el
|
||||
* webhook active el período anual al aprobarse.
|
||||
*/
|
||||
export async function createSubscriptionPreference(params: {
|
||||
tenantId: string;
|
||||
subscriptionId: string;
|
||||
plan: string;
|
||||
amount: number;
|
||||
payerEmail: string;
|
||||
}): Promise<{ preferenceId: string; checkoutUrl: string }> {
|
||||
if (!env.MP_ACCESS_TOKEN) {
|
||||
throw new Error('MercadoPago no está configurado (falta MP_ACCESS_TOKEN en .env).');
|
||||
}
|
||||
|
||||
const response = await preferenceClient.create({
|
||||
body: {
|
||||
items: [
|
||||
{
|
||||
id: `subscription-${params.subscriptionId}`,
|
||||
title: `Horux360 - Plan ${params.plan} - Año completo`,
|
||||
quantity: 1,
|
||||
unit_price: params.amount,
|
||||
currency_id: 'MXN',
|
||||
},
|
||||
],
|
||||
payer: { email: resolvePayerEmail(params.payerEmail) },
|
||||
external_reference: `subscription:${params.tenantId}:${params.subscriptionId}`,
|
||||
back_urls: {
|
||||
success: `${backUrlBase()}/configuracion/suscripcion?subscription=success`,
|
||||
failure: `${backUrlBase()}/configuracion/suscripcion?subscription=failure`,
|
||||
pending: `${backUrlBase()}/configuracion/suscripcion?subscription=pending`,
|
||||
},
|
||||
auto_return: 'approved',
|
||||
},
|
||||
});
|
||||
|
||||
return {
|
||||
preferenceId: response.id!,
|
||||
checkoutUrl: response.init_point!,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Crea una Preference (checkout de pago único) para comprar un paquete de
|
||||
* timbres adicionales. external_reference = `timbres-pack:${paymentId}` para
|
||||
|
||||
Reference in New Issue
Block a user