import type { PaymentProvider, WebhookEvent } from '../core/provider.interface.js'; export type ProviderName = 'chargily' | 'stripe' | 'satim' | 'paypal' | 'manual' | 'slickpay' | 'guiddini' | 'coinbase' | 'nowpayments' | 'paystack' | 'mollie'; /** Liste exhaustive des noms de provider supportés. À étendre dans ce * module quand un nouveau provider est ajouté → tous les consumers * bénéficient automatiquement. */ export declare const KNOWN_PROVIDERS: readonly ProviderName[]; /** Type-guard runtime — vrai si `name` est un ProviderName valide. */ export declare function isKnownProvider(name: string): name is ProviderName; /** * Mapping currency → provider par défaut. Couvre les principaux cas : * DZD → Chargily *(Algérie)*, autres → Stripe *(international)*. * Pour CIB-only Algérie sans Chargily, override en caller via le * paramètre `fallback` de `pickProviderByCurrency`. */ export declare const CURRENCY_TO_PROVIDER: Readonly>; /** * Choisit le provider à utiliser pour une currency donnée. * * @param currency Code ISO 4217 (insensible à la casse) * @param fallback Provider à utiliser si la currency n'est pas mappée (default 'stripe') */ export declare function pickProviderByCurrency(currency: string | null | undefined, fallback?: ProviderName): { name: ProviderName; provider: PaymentProvider; }; /** * Sélectionne le header signature attendu pour chaque provider. * Headers normalisés en lowercase (Headers.get est case-insensitive). */ export declare function pickSignatureHeader(headers: Headers | Record, providerName: ProviderName): string; /** * Instancie un PaymentProvider à partir de son nom (lit env via le constructor). * Utile pour le webhook handler qui n'a pas besoin de connaître la config. */ export declare function getProviderByName(name: ProviderName): PaymentProvider; export interface HandleProviderWebhookArgs { /** Body brut de la requête (req.text() avant parse). Crucial : signature * computed sur les bytes exacts envoyés par le provider. */ body: string; /** Headers de la requête HTTP. */ headers: Headers | Record; /** Nom du provider. */ providerName: ProviderName; } export type HandleProviderWebhookResult = { ok: true; event: WebhookEvent; } | { ok: false; reason: 'bad_signature' | 'malformed' | 'unknown_provider'; error: string; }; /** * Vérifie le webhook reçu d'un provider de paiement et retourne l'event * normalisé. La logique métier (créer une Subscription, marquer une * Registration, etc.) reste à la charge du caller. * * @example * const r = await handleProviderWebhook({ * body: await req.text(), * headers: req.headers, * providerName: 'chargily', * }) * if (!r.ok) return NextResponse.json({ error: r.error }, { status: 400 }) * if (isPaidEvent(r.event)) { * // ... mettre à jour DB métier ... * } */ export declare function handleProviderWebhook(args: HandleProviderWebhookArgs): Promise; /** * Vrai si l'event indique un paiement ENCAISSÉ. * * ── ⚠️ POURQUOI LE TYPE NE SUFFIT PAS ─────────────────────────────────────── * `checkout.session.completed` signifie « le client a terminé le tunnel », **pas** « l'argent est * arrivé ». Pour les moyens à règlement différé (SEPA, virement), Stripe l'envoie avec * `payment_status: 'unpaid'`, puis `checkout.session.async_payment_succeeded` quand les fonds * arrivent réellement — parfois plusieurs jours après. * * Se fier au seul type faisait donc partir le plat en cuisine **avant que le paiement ne soit * confirmé**, et l'écart n'apparaissait qu'au rapprochement. Défaut relevé le 19/08/2026. * * ── LA RÈGLE : NE CONTREDIRE QUE SUR AVEU EXPLICITE ───────────────────────── * On ne refuse que si le payload **dit lui-même** que le paiement n'est pas acquis. Les * fournisseurs qui n'envoient pas ce champ (Chargily, SATIM, PayPal) sont donc inchangés — exiger * un champ qu'ils n'émettent pas rejetterait des paiements authentiques. * * ⚠️ Le fournisseur Stripe **renomme** `checkout.session.completed` en `payment.success` avant * d'arriver ici : le contrôle porte sur les DONNÉES, pas sur le nom, et reste donc valable. */ export declare function isPaidEvent(event: WebhookEvent): boolean; /** Vrai si l'event indique un échec ou une annulation de paiement. */ export declare function isFailedEvent(event: WebhookEvent): boolean; /** * Vrai si l'event indique une CONTESTATION (chargeback). * * ── POURQUOI UN STATUT À PART ─────────────────────────────────────────────── * Une contestation n'est **ni un échec ni un remboursement**, et les confondre coûte cher : * · sous `failed`, on croirait que le client n'a jamais payé — alors qu'il a payé, consommé, * puis réclamé ; le plat est parti, et la marchandise ne revient pas ; * · sous `refunded`, on croirait avoir remboursé de son plein gré — alors qu'un TIERS a repris * l'argent, avec des frais, et qu'il existe un délai pour se défendre. * * Le distinguer est ce qui permet de compter les contestations, qui est le seul chiffre que * regarde un acquéreur. */ export declare function isDisputedEvent(event: WebhookEvent): boolean; /** Vrai si l'event indique un remboursement. */ export declare function isRefundedEvent(event: WebhookEvent): boolean; /** * Extrait l'`orderId` (= clef de matching côté app, ex: registrationId) * depuis le payload event, peu importe le provider. Cherche dans plusieurs * positions usuelles. */ export declare function extractOrderId(event: WebhookEvent): string | null; //# sourceMappingURL=webhook-helpers.d.ts.map