{"version":3,"sources":["../src/utils/scriptLoader.ts","../src/utils/logger.ts","../src/utils/analytics.ts","../src/utils/errors.ts","../src/utils/verifyTransaction.ts","../src/core/createPaymentEngine.ts","../src/core/usePaymentEngine.ts","../src/utils/keyValidator.ts","../src/core/validateCommonConfig.ts","../src/utils/currency.ts"],"names":["validationError"],"mappings":"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","file":"core.mjs","sourcesContent":["/**\r\n * Loads an external JavaScript script dynamically.\r\n * \r\n * Checks if a script with the given ID already exists to prevent duplicates.\r\n * Scripts are loaded asynchronously to avoid blocking page rendering.\r\n * \r\n * @param src - The URL of the script to load\r\n * @param id - Unique ID for the script element (used for deduplication)\r\n * @returns Promise that resolves to `true` when loaded, or rejects on error\r\n * \r\n * @example\r\n * ```ts\r\n * await loadScript(\"https://cdn.example.com/sdk.js\", \"example-sdk\");\r\n * // SDK is now available on window\r\n * ```\r\n */\r\nexport function loadScript(src: string, id: string): Promise<boolean> {\r\n  // Guard for SSR environments (Next.js server components, Node.js)\r\n  if (typeof document === \"undefined\") {\r\n    return Promise.resolve(false);\r\n  }\r\n\r\n  return new Promise((resolve, reject) => {\r\n    const existingScript = document.getElementById(id) as HTMLScriptElement | null;\r\n\r\n    if (existingScript) {\r\n      // Script already in the DOM — resolve immediately to avoid duplicates.\r\n      // We trust the existing element is either loaded or being loaded elsewhere.\r\n      resolve(true);\r\n      return;\r\n    }\r\n\r\n    const script = document.createElement(\"script\");\r\n    script.id = id;\r\n    script.src = src;\r\n    script.async = true;\r\n\r\n    script.onload = () => {\r\n      script.dataset.loaded = \"true\";\r\n      resolve(true);\r\n    };\r\n\r\n    script.onerror = () => {\r\n      reject(new Error(`Failed to load script: ${src}`));\r\n    };\r\n\r\n    document.body.appendChild(script);\r\n  });\r\n}\r\n","const PREFIX = \"[react-benin-payments]\";\r\n\r\nconst STYLES = {\r\n  info: \"color: #4E6BFF; font-weight: bold;\",\r\n  success: \"color: #0AB67A; font-weight: bold;\",\r\n  error: \"color: #EF4444; font-weight: bold;\",\r\n  warn: \"color: #F59E0B; font-weight: bold;\",\r\n};\r\n\r\n/**\r\n * Creates a styled logger for debug mode.\r\n * \r\n * When enabled, logs are color-coded by level:\r\n * - Info: Blue (#4E6BFF)\r\n * - Success: Green (#0AB67A)\r\n * - Error: Red (#EF4444)\r\n * - Warn: Orange (#F59E0B)\r\n * \r\n * @param enabled - Whether logging is enabled\r\n * @returns Logger object with info, success, error, and warn methods\r\n * \r\n * @example\r\n * ```ts\r\n * const log = createLogger(true);\r\n * log.info(\"Loading SDK...\");\r\n * log.success(\"SDK loaded!\");\r\n * log.error(\"Failed to load\", error);\r\n * ```\r\n */\r\nexport function createLogger(enabled: boolean): Logger {\r\n  return {\r\n    info: (message: string, ...args: unknown[]) => {\r\n      if (enabled) {\r\n        console.log(`%c${PREFIX} ${message}`, STYLES.info, ...args);\r\n      }\r\n    },\r\n    success: (message: string, ...args: unknown[]) => {\r\n      if (enabled) {\r\n        console.log(`%c${PREFIX} ${message}`, STYLES.success, ...args);\r\n      }\r\n    },\r\n    error: (message: string, ...args: unknown[]) => {\r\n      if (enabled) {\r\n        console.error(`%c${PREFIX} ${message}`, STYLES.error, ...args);\r\n      }\r\n    },\r\n    warn: (message: string, ...args: unknown[]) => {\r\n      if (enabled) {\r\n        console.warn(`%c${PREFIX} ${message}`, STYLES.warn, ...args);\r\n      }\r\n    },\r\n  };\r\n}\r\n\r\n/**\r\n * Logger interface with color-coded methods.\r\n */\r\nexport interface Logger {\r\n  /** Log informational message (blue) */\r\n  info: (message: string, ...args: unknown[]) => void;\r\n  /** Log success message (green) */\r\n  success: (message: string, ...args: unknown[]) => void;\r\n  /** Log error message (red) */\r\n  error: (message: string, ...args: unknown[]) => void;\r\n  /** Log warning message (orange) */\r\n  warn: (message: string, ...args: unknown[]) => void;\r\n}\r\n","import type { PaymentProviderId } from \"../core/types\";\r\n\r\nexport type BeninPaymentAnalyticsEventName =\r\n  | \"sdk_load_started\"\r\n  | \"sdk_load_succeeded\"\r\n  | \"sdk_load_failed\"\r\n  | \"payment_validation_failed\"\r\n  | \"payment_pre_validation_started\"\r\n  | \"payment_pre_validation_succeeded\"\r\n  | \"payment_pre_validation_cancelled\"\r\n  | \"payment_pre_validation_failed\"\r\n  | \"payment_open_attempted\"\r\n  | \"payment_opened\"\r\n  | \"payment_completed\"\r\n  | \"payment_failed\"\r\n  | \"payment_closed\"\r\n  | \"payment_verification_started\"\r\n  | \"payment_verification_succeeded\"\r\n  | \"payment_verification_failed\";\r\n\r\nexport interface BeninPaymentAnalyticsEvent {\r\n  name: BeninPaymentAnalyticsEventName;\r\n  /** `\"fedapay\"` / `\"kkiapay\"`, or a custom provider identifier for a driver you wrote yourself. */\r\n  provider: PaymentProviderId;\r\n  amount?: number;\r\n  currency?: string;\r\n  mode: \"mock\" | \"live\";\r\n  transactionId?: string;\r\n  status?: string;\r\n  errorCode?: string;\r\n  errorMessage?: string;\r\n  timestamp: string;\r\n  metadata?: Record<string, unknown>;\r\n}\r\n\r\nexport type BeninPaymentAnalyticsHandler = (\r\n  event: BeninPaymentAnalyticsEvent\r\n) => void | Promise<void>;\r\n\r\nexport function createAnalyticsEmitter(\r\n  handlers: Array<BeninPaymentAnalyticsHandler | undefined>,\r\n  debugLog?: (message: string, ...args: unknown[]) => void\r\n): (event: Omit<BeninPaymentAnalyticsEvent, \"timestamp\">) => void {\r\n  return (event) => {\r\n    const fullEvent: BeninPaymentAnalyticsEvent = {\r\n      ...event,\r\n      timestamp: new Date().toISOString(),\r\n    };\r\n\r\n    handlers.forEach((handler) => {\r\n      if (!handler) return;\r\n\r\n      try {\r\n        void Promise.resolve(handler(fullEvent)).catch((error) => {\r\n          debugLog?.(\"Analytics handler failed\", error);\r\n        });\r\n      } catch (error) {\r\n        debugLog?.(\"Analytics handler failed\", error);\r\n      }\r\n    });\r\n  };\r\n}\r\n","/**\n * A pattern matched against a raw error message, with the user-facing\n * message to show when it matches.\n */\nexport interface ErrorPattern {\n  pattern: RegExp;\n  message: string;\n}\n\n/**\n * Options to fully control `parseError`'s output — pass your own patterns\n * and/or fallback message to translate or reword the built-in French\n * defaults, instead of being stuck with them.\n */\nexport interface ParseErrorOptions {\n  /**\n   * Patterns checked in order; the first match wins. Defaults to\n   * `DEFAULT_ERROR_PATTERNS`. Spread the defaults in if you only want to\n   * add or reorder a few: `{ patterns: [...myPatterns, ...DEFAULT_ERROR_PATTERNS] }`.\n   */\n  patterns?: ErrorPattern[];\n  /** Returned when nothing matches and the error has no usable message. */\n  fallbackMessage?: string;\n}\n\n/**\n * Default error patterns and their French, user-friendly translations.\n * Exported so you can extend rather than fully replace them — see\n * `ParseErrorOptions.patterns`.\n */\nexport const DEFAULT_ERROR_PATTERNS: ErrorPattern[] = [\n  { pattern: /closed|dismissed|cancel/i, message: \"Paiement annulé.\" },\n  { pattern: /insufficient.*(fund|balance)/i, message: \"Solde insuffisant sur votre compte.\" },\n  { pattern: /network|connection|offline/i, message: \"Problème de connexion internet.\" },\n  { pattern: /timeout/i, message: \"La requête a expiré. Veuillez réessayer.\" },\n  { pattern: /invalid.*key/i, message: \"Clé API invalide.\" },\n  { pattern: /invalid.*amount/i, message: \"Montant invalide.\" },\n  { pattern: /unauthorized|401/i, message: \"Accès non autorisé.\" },\n  { pattern: /not.*found|404/i, message: \"Ressource introuvable.\" },\n  { pattern: /server.*error|500/i, message: \"Erreur serveur. Veuillez réessayer.\" },\n];\n\nconst DEFAULT_FALLBACK_MESSAGE = \"Une erreur inconnue est survenue.\";\n\n/**\n * Parses an error and returns a user-friendly message.\n *\n * Defaults to French translations (`DEFAULT_ERROR_PATTERNS`), but you're\n * never stuck with them — pass your own `patterns` and/or `fallbackMessage`\n * to translate or reword every message this library can produce.\n *\n * @param error - The error to parse (can be any type)\n * @param options - Optional custom patterns / fallback message\n * @returns A clean, user-friendly error message\n *\n * @example\n * ```ts\n * parseError(new Error(\"Network connection failed\"));\n * // Returns: \"Problème de connexion internet.\"\n *\n * // Full control — e.g. an English-speaking product:\n * parseError(err, {\n *   patterns: [\n *     { pattern: /closed|dismissed|cancel/i, message: \"Payment cancelled.\" },\n *     { pattern: /network|connection|offline/i, message: \"No internet connection.\" },\n *   ],\n *   fallbackMessage: \"Something went wrong.\",\n * });\n * ```\n */\nexport function parseError(error: unknown, options: ParseErrorOptions = {}): string {\n  const patterns = options.patterns ?? DEFAULT_ERROR_PATTERNS;\n  const fallbackMessage = options.fallbackMessage ?? DEFAULT_FALLBACK_MESSAGE;\n\n  if (!error) {\n    return fallbackMessage;\n  }\n\n  let errorMessage: string;\n\n  if (typeof error === \"string\") {\n    errorMessage = error;\n  } else if (error instanceof Error) {\n    errorMessage = error.message;\n  } else if (typeof error === \"object\" && error !== null) {\n    const errorObj = error as Record<string, unknown>;\n    errorMessage =\n      (errorObj.message as string) ||\n      (errorObj.error as string) ||\n      (errorObj.msg as string) ||\n      JSON.stringify(error);\n  } else {\n    return fallbackMessage;\n  }\n\n  for (const { pattern, message } of patterns) {\n    if (pattern.test(errorMessage)) {\n      return message;\n    }\n  }\n\n  return errorMessage || fallbackMessage;\n}\n\n/**\n * Creates a standardized error object with parsed message.\n *\n * @param error - The raw error\n * @param options - Optional custom patterns / fallback message, forwarded to `parseError`\n * @returns An Error object with a user-friendly message\n */\nexport function createParsedError(error: unknown, options?: ParseErrorOptions): Error {\n  return new Error(parseError(error, options));\n}\n","import type { VerificationConfig, VerificationResponse, VerifyMethod } from \"../types\";\r\nimport type { PaymentProviderId } from \"../core/types\";\r\n\r\n/**\r\n * Payload sent to the verification endpoint.\r\n */\r\nexport interface VerifyPayload {\r\n  /** Transaction ID from the payment provider */\r\n  transactionId: string;\r\n  /** Amount that was charged */\r\n  amount: number;\r\n  /** Payment provider used — `\"fedapay\"` / `\"kkiapay\"`, or a custom driver's identifier */\r\n  provider: PaymentProviderId;\r\n  /** Additional metadata */\r\n  metadata?: Record<string, unknown>;\r\n}\r\n\r\n/**\r\n * Thrown when backend verification fails. `isBackendMessage` tells callers\r\n * whether `message` is text your own `verifyUrl` endpoint returned (and\r\n * should therefore be shown to the user exactly as written) or a generic\r\n * fallback/network message that's safe to run through further translation.\r\n */\r\nexport class VerificationError extends Error {\r\n  constructor(message: string, public readonly isBackendMessage: boolean) {\r\n    super(message);\r\n    this.name = \"VerificationError\";\r\n  }\r\n}\r\n\r\n/**\r\n * Verifies a transaction with the backend.\r\n *\r\n * @param config - Verification configuration\r\n * @param payload - Transaction data to verify\r\n * @returns Verification response from the backend\r\n * @throws {VerificationError} if verification fails or network error occurs\r\n *\r\n * @example\r\n * ```ts\r\n * const result = await verifyTransaction(\r\n *   { verifyUrl: \"/api/verify\", verifyMethod: \"POST\" },\r\n *   { transactionId: \"tx_123\", amount: 5000, provider: \"fedapay\" }\r\n * );\r\n * ```\r\n */\r\nexport async function verifyTransaction(\r\n  config: VerificationConfig,\r\n  payload: VerifyPayload\r\n): Promise<VerificationResponse> {\r\n  if (!config.verifyUrl) {\r\n    throw new Error(\"verifyUrl is required for transaction verification\");\r\n  }\r\n\r\n  const method: VerifyMethod = config.verifyMethod ?? \"POST\";\r\n  const headers: Record<string, string> = {\r\n    \"Content-Type\": \"application/json\",\r\n    ...config.customVerifyHeaders,\r\n  };\r\n\r\n  let url = config.verifyUrl;\r\n  const fetchOptions: RequestInit = {\r\n    method,\r\n    headers,\r\n  };\r\n\r\n  if (method === \"POST\") {\r\n    fetchOptions.body = JSON.stringify(payload);\r\n  } else {\r\n    const params = new URLSearchParams({\r\n      transactionId: payload.transactionId,\r\n      amount: payload.amount.toString(),\r\n      provider: payload.provider,\r\n    });\r\n    url = `${config.verifyUrl}?${params.toString()}`;\r\n  }\r\n\r\n  const response = await fetch(url, fetchOptions);\r\n\r\n  if (!response.ok) {\r\n    let errorMessage = `Verification failed with status ${response.status}`;\r\n    let isBackendMessage = false;\r\n\r\n    try {\r\n      const errorData = await response.json();\r\n      if (errorData.message) {\r\n        errorMessage = errorData.message;\r\n        isBackendMessage = true;\r\n      }\r\n    } catch {\r\n      // Response is not JSON, use default message\r\n    }\r\n\r\n    throw new VerificationError(errorMessage, isBackendMessage);\r\n  }\r\n\r\n  const data = await response.json();\r\n  \r\n  return {\r\n    success: data.success ?? true,\r\n    message: data.message,\r\n    data: data.data ?? data,\r\n  };\r\n}\r\n","import { loadScript } from \"../utils/scriptLoader\";\nimport { createLogger } from \"../utils/logger\";\nimport { createAnalyticsEmitter, type BeninPaymentAnalyticsEvent } from \"../utils/analytics\";\nimport { parseError } from \"../utils/errors\";\nimport { verifyTransaction, VerificationError } from \"../utils/verifyTransaction\";\nimport type { PaymentValidationError } from \"../types/validation\";\nimport type {\n  PaymentDriver,\n  PaymentEngine,\n  PaymentEngineOptions,\n  PaymentEngineState,\n} from \"./types\";\n\ntype AnalyticsEventInput = Omit<BeninPaymentAnalyticsEvent, \"timestamp\" | \"provider\">;\n\n/**\n * Creates a framework-agnostic payment flow controller for a given provider\n * driver. Handles script loading, validation, mock simulation, the optional\n * `onBeforePayment` hook, backend verification and standardized analytics —\n * identically for every provider that implements `PaymentDriver`.\n *\n * This has no dependency on React: `subscribe`/`getState` can be wired into\n * any UI layer. `usePaymentEngine` is the thin React binding used internally\n * by `useFedaPay` / `useKkiaPay`.\n */\nexport function createPaymentEngine<TConfig, TRaw>(\n  driver: PaymentDriver<TConfig, TRaw>,\n  getOptions: () => PaymentEngineOptions<TConfig, TRaw>\n): PaymentEngine<TConfig> {\n  const initialMock = getOptions().isMockMode;\n\n  let state: PaymentEngineState = {\n    loading: !initialMock,\n    scriptLoaded: initialMock,\n    error: null,\n    isVerifying: false,\n    isPreparing: false,\n  };\n  let lastConfig: TConfig | null = null;\n  let destroyed = false;\n  const listeners = new Set<() => void>();\n\n  function getState() {\n    return state;\n  }\n\n  function subscribe(listener: () => void) {\n    listeners.add(listener);\n    return () => listeners.delete(listener);\n  }\n\n  function setState(patch: Partial<PaymentEngineState>) {\n    state = { ...state, ...patch };\n    // The `destroyed` guard is what makes it safe for usePaymentEngine to\n    // swap in a new engine (e.g. when `isMockMode` changes) without\n    // explicitly cancelling this one first: React runs this engine's\n    // `start()` cleanup (which sets `destroyed = true`) before the new\n    // engine's effect runs, so any in-flight promise/timer that resolves\n    // late just updates dead internal state instead of notifying React.\n    if (!destroyed) listeners.forEach((listener) => listener());\n  }\n\n  function getLog() {\n    return createLogger(getOptions().debug ?? false);\n  }\n\n  function emit(event: AnalyticsEventInput, configForExtras: TConfig | undefined) {\n    const options = getOptions();\n    const emitter = createAnalyticsEmitter(\n      [options.globalAnalyticsHandler, options.onAnalyticsEvent],\n      getLog().warn\n    );\n    const extras = driver.getAnalyticsExtras?.(configForExtras) ?? {};\n    emitter({ ...extras, ...event, provider: driver.name });\n  }\n\n  /** Applies a per-code message override (`options.messages`), if configured. */\n  function applyMessageOverride(error: PaymentValidationError): PaymentValidationError {\n    const override = getOptions().messages?.[error.code];\n    return override ? { ...error, message: override } : error;\n  }\n\n  /**\n   * Resolves a user-facing message for a caught technical error (SDK load\n   * failure, network error, thrown SDK exception...). Tries the caller's\n   * `resolveErrorMessage` first, then falls back to `parseError`'s built-in\n   * translations.\n   */\n  function resolveGenericErrorMessage(error: unknown): string {\n    const custom = getOptions().resolveErrorMessage?.(error);\n    return custom !== undefined ? custom : parseError(error);\n  }\n\n  function handleSuccess(raw: TRaw, config?: TConfig) {\n    const options = getOptions();\n    const log = getLog();\n    const resolvedConfig = config ?? (lastConfig as TConfig);\n    const mode: \"mock\" | \"live\" = options.isMockMode ? \"mock\" : \"live\";\n\n    log.success(\"Payment completed by provider\", raw);\n\n    const payload = driver.toVerifyPayload(raw, resolvedConfig);\n    const status = driver.getStatus?.(raw);\n    const verifyUrl = options.verification?.verifyUrl;\n\n    if (!verifyUrl) {\n      emit(\n        { name: \"payment_completed\", amount: payload.amount, mode, transactionId: payload.transactionId, status },\n        resolvedConfig\n      );\n      options.onRawSuccess?.(raw);\n      return;\n    }\n\n    setState({ isVerifying: true });\n    log.info(\"🔐 Verifying transaction with backend...\", { url: verifyUrl });\n    emit(\n      { name: \"payment_verification_started\", amount: payload.amount, mode, transactionId: payload.transactionId },\n      resolvedConfig\n    );\n\n    verifyTransaction(\n      {\n        verifyUrl,\n        verifyMethod: options.verification?.verifyMethod,\n        customVerifyHeaders: options.verification?.customVerifyHeaders,\n      },\n      {\n        transactionId: payload.transactionId,\n        amount: payload.amount,\n        provider: driver.name,\n        metadata: payload.metadata,\n      }\n    )\n      .then((verifyResult) => {\n        setState({ isVerifying: false });\n        log.success(\"🔐 Backend verification successful\", verifyResult);\n        emit(\n          { name: \"payment_verification_succeeded\", amount: payload.amount, mode, transactionId: payload.transactionId },\n          resolvedConfig\n        );\n        emit(\n          { name: \"payment_completed\", amount: payload.amount, mode, transactionId: payload.transactionId, status },\n          resolvedConfig\n        );\n        options.onRawSuccess?.(raw);\n      })\n      .catch((err) => {\n        setState({ isVerifying: false });\n        const verifyError = err instanceof Error ? err : new Error(\"Verification failed\");\n        log.error(\"🔐 Backend verification failed\", verifyError);\n        emit(\n          {\n            name: \"payment_verification_failed\",\n            amount: payload.amount,\n            mode,\n            transactionId: payload.transactionId,\n            errorMessage: verifyError.message,\n          },\n          resolvedConfig\n        );\n        // A message your own verifyUrl endpoint wrote is shown exactly as you\n        // wrote it — only messages WE generated (network failures, a bare\n        // HTTP status with no body) go through translation/resolution.\n        const userMessage =\n          verifyError instanceof VerificationError && verifyError.isBackendMessage\n            ? verifyError.message\n            : resolveGenericErrorMessage(verifyError);\n        options.onValidationError?.(applyMessageOverride({ code: \"SDK_ERROR\", message: userMessage }));\n      });\n  }\n\n  function start(): () => void {\n    const options = getOptions();\n    const log = getLog();\n\n    if (options.isMockMode) {\n      log.info(\"🧪 Running in Mock Mode - No real SDK loaded\");\n      setState({ scriptLoaded: true, loading: false });\n      return () => {\n        destroyed = true;\n      };\n    }\n\n    let cancelled = false;\n    const analyticsConfig = options.getAnalyticsConfig?.();\n\n    log.info(`Loading ${driver.name} SDK...`);\n    emit({ name: \"sdk_load_started\", mode: \"live\", amount: driver.getAmount(analyticsConfig) }, analyticsConfig);\n\n    loadScript(driver.scriptUrl, driver.scriptId)\n      .then(() => {\n        if (cancelled) return;\n        setState({ scriptLoaded: true, loading: false });\n        log.success(`${driver.name} SDK loaded successfully`);\n        emit(\n          { name: \"sdk_load_succeeded\", mode: \"live\", amount: driver.getAmount(analyticsConfig) },\n          analyticsConfig\n        );\n      })\n      .catch((err) => {\n        if (cancelled) return;\n        const friendlyMessage = resolveGenericErrorMessage(err);\n        setState({ error: new Error(friendlyMessage), loading: false });\n        log.error(`Failed to load ${driver.name} SDK`, err);\n        emit(\n          {\n            name: \"sdk_load_failed\",\n            mode: \"live\",\n            amount: driver.getAmount(analyticsConfig),\n            errorMessage: friendlyMessage,\n          },\n          analyticsConfig\n        );\n      });\n\n    return () => {\n      cancelled = true;\n      destroyed = true;\n    };\n  }\n\n  async function runOpen(config: TConfig) {\n    const options = getOptions();\n    const log = getLog();\n    const isMockMode = options.isMockMode;\n    const mode: \"mock\" | \"live\" = isMockMode ? \"mock\" : \"live\";\n\n    if (state.isPreparing) {\n      log.warn(\"Payment pre-validation already in progress\");\n      return;\n    }\n\n    log.info(`Opening ${driver.name} dialog...`, { config, isMockMode });\n\n    driver.logEnvironmentWarnings?.(config, { isMockMode, environmentWarnings: options.environmentWarnings });\n\n    const validationError = driver.validate(config, { isMockMode });\n    if (validationError) {\n      log.error(`Validation failed: ${validationError.message}`);\n      emit(\n        {\n          name: \"payment_validation_failed\",\n          amount: driver.getAmount(config),\n          mode,\n          errorCode: validationError.code,\n          errorMessage: validationError.message,\n        },\n        config\n      );\n      options.onValidationError?.(applyMessageOverride(validationError));\n      return;\n    }\n\n    emit({ name: \"payment_open_attempted\", amount: driver.getAmount(config), mode }, config);\n\n    if (options.onBeforePayment) {\n      try {\n        setState({ isPreparing: true });\n        emit({ name: \"payment_pre_validation_started\", amount: driver.getAmount(config), mode }, config);\n        const shouldContinue = await options.onBeforePayment();\n        if (shouldContinue === false) {\n          log.info(\"Payment opening cancelled by onBeforePayment\");\n          emit({ name: \"payment_pre_validation_cancelled\", amount: driver.getAmount(config), mode }, config);\n          return;\n        }\n        emit({ name: \"payment_pre_validation_succeeded\", amount: driver.getAmount(config), mode }, config);\n      } catch (err) {\n        const preValidationError = err instanceof Error ? err : new Error(\"Payment pre-validation failed\");\n        setState({ error: preValidationError });\n        log.error(\"onBeforePayment failed\", preValidationError);\n        emit(\n          {\n            name: \"payment_pre_validation_failed\",\n            amount: driver.getAmount(config),\n            mode,\n            errorMessage: preValidationError.message,\n          },\n          config\n        );\n        options.onValidationError?.(\n          applyMessageOverride({ code: \"PRE_VALIDATION_FAILED\", message: preValidationError.message })\n        );\n        return;\n      } finally {\n        setState({ isPreparing: false });\n      }\n    }\n\n    if (isMockMode) {\n      log.info(\"🧪 Simulating payment...\");\n      emit({ name: \"payment_opened\", amount: driver.getAmount(config), mode: \"mock\" }, config);\n      setTimeout(() => {\n        const mockResponse = driver.buildMockSuccess(config);\n        log.success(\"🧪 Mock Payment Successful\", mockResponse);\n        handleSuccess(mockResponse, config);\n      }, 1000);\n      return;\n    }\n\n    if (!state.scriptLoaded || !driver.isSdkReady()) {\n      const validationError = {\n        code: \"SDK_NOT_LOADED\" as const,\n        message: `${driver.name} SDK not loaded. Please wait for the script to load.`,\n      };\n      log.error(\"SDK not loaded. Cannot open dialog.\");\n      emit(\n        {\n          name: \"payment_validation_failed\",\n          amount: driver.getAmount(config),\n          mode: \"live\",\n          errorCode: validationError.code,\n          errorMessage: validationError.message,\n        },\n        config\n      );\n      options.onValidationError?.(applyMessageOverride(validationError));\n      return;\n    }\n\n    try {\n      driver.open(\n        config,\n        {\n          onSuccess: (raw) => handleSuccess(raw, config),\n          onFailure: (raw) => getOptions().onRawFailure?.(raw),\n          onClose: () => getOptions().onClose?.(),\n        },\n        {\n          log,\n          isMockMode,\n          emit: (partial) => emit({ amount: driver.getAmount(config), mode: \"live\", ...partial }, config),\n        }\n      );\n\n      log.success(`${driver.name} dialog opened successfully`);\n      emit({ name: \"payment_opened\", amount: driver.getAmount(config), mode: \"live\" }, config);\n    } catch (err) {\n      log.error(`Failed to open ${driver.name} dialog`, err);\n      const sdkError = err instanceof Error ? err : new Error(`Failed to open ${driver.name} dialog`);\n      setState({ error: sdkError });\n      emit(\n        {\n          name: \"payment_failed\",\n          amount: driver.getAmount(config),\n          mode: \"live\",\n          errorCode: \"SDK_ERROR\",\n          errorMessage: sdkError.message,\n        },\n        config\n      );\n      options.onValidationError?.(\n        applyMessageOverride({ code: \"SDK_ERROR\", message: resolveGenericErrorMessage(sdkError) })\n      );\n    }\n  }\n\n  function open(config: TConfig) {\n    lastConfig = config;\n    void runOpen(config);\n  }\n\n  return { getState, subscribe, start, open };\n}\n","\"use client\";\n\nimport { useEffect, useMemo, useRef, useState } from \"react\";\nimport { createPaymentEngine } from \"./createPaymentEngine\";\nimport type { PaymentDriver, PaymentEngineOptions, PaymentEngineState } from \"./types\";\n\n/**\n * React binding for `createPaymentEngine`. Owns one engine instance per\n * hook call (recreated only if the driver or mock-mode flag changes),\n * subscribes to its state, and starts its background lifecycle\n * (script loading, persistent SDK listeners) for the component's lifetime.\n *\n * `getOptions` is called fresh on every render, so callbacks and config\n * values it returns are always up to date without needing to be listed in\n * any dependency array.\n */\nexport function usePaymentEngine<TConfig, TRaw>(\n  driver: PaymentDriver<TConfig, TRaw>,\n  getOptions: () => PaymentEngineOptions<TConfig, TRaw>\n): [PaymentEngineState, (config: TConfig) => void] {\n  const getOptionsRef = useRef(getOptions);\n  getOptionsRef.current = getOptions;\n\n  const isMockMode = getOptions().isMockMode;\n\n  const engine = useMemo(\n    () => createPaymentEngine(driver, () => getOptionsRef.current()),\n    // Recreated only when the driver identity or the mock flag changes —\n    // mirrors the original hooks re-running their script-loading effect then.\n    // eslint-disable-next-line react-hooks/exhaustive-deps\n    [driver, isMockMode]\n  );\n\n  const [state, setState] = useState<PaymentEngineState>(() => engine.getState());\n\n  useEffect(() => {\n    setState(engine.getState());\n    const unsubscribe = engine.subscribe(() => setState(engine.getState()));\n    const stop = engine.start();\n    return () => {\n      unsubscribe();\n      stop();\n    };\n  }, [engine]);\n\n  return [state, engine.open];\n}\n","/**\n * Overrides the wording of the dev-time console warnings emitted by\n * `validateKeyEnvironment`/`logSandboxMode`. Every field is optional — any\n * warning you don't override keeps its default English text.\n */\nexport interface EnvironmentWarningMessages {\n  /** Shown when a live key is used while sandbox mode is on. Receives the provider name (e.g. \"FedaPay\"). */\n  liveKeyInSandbox?: (provider: string) => string;\n  /** Shown when a test/sandbox key is used while sandbox mode is off. Receives the provider name. */\n  testKeyInProduction?: (provider: string) => string;\n  /** Shown once whenever sandbox mode is active. Receives the provider name. */\n  sandboxModeActive?: (provider: string) => string;\n}\n\n/**\n * Validates API key consistency with sandbox mode.\n * Warns developers about potential misconfigurations.\n *\n * @param key - The API public key\n * @param sandbox - Whether sandbox mode is enabled\n * @param provider - The payment provider name (for logging)\n * @param messages - Optional overrides for the warning text\n */\nexport function validateKeyEnvironment(\n  key: string,\n  sandbox: boolean,\n  provider: \"FedaPay\" | \"KKiaPay\",\n  messages?: EnvironmentWarningMessages\n): void {\n  if (!key) return;\n\n  const isLiveKey = key.startsWith(\"pk_live_\") || key.startsWith(\"pk_live\");\n  const isTestKey =\n    key.startsWith(\"pk_test_\") ||\n    key.startsWith(\"pk_sandbox_\") ||\n    key.startsWith(\"pk_sandbox\");\n\n  if (sandbox && isLiveKey) {\n    console.warn(\n      messages?.liveKeyInSandbox?.(provider) ??\n        `⚠️ [react-benin-payments] ${provider}: You are in Sandbox mode but using a LIVE key! This may cause unexpected charges.`\n    );\n  }\n\n  if (!sandbox && isTestKey) {\n    console.warn(\n      messages?.testKeyInProduction?.(provider) ??\n        `⚠️ [react-benin-payments] ${provider}: You are in Production mode but using a TEST key! Payments will not be processed.`\n    );\n  }\n}\n\n/**\n * Logs sandbox mode warning if enabled.\n *\n * @param sandbox - Whether sandbox mode is enabled\n * @param provider - The payment provider name\n * @param messages - Optional overrides for the warning text\n */\nexport function logSandboxMode(\n  sandbox: boolean,\n  provider: \"FedaPay\" | \"KKiaPay\",\n  messages?: EnvironmentWarningMessages\n): void {\n  if (sandbox) {\n    console.log(\n      messages?.sandboxModeActive?.(provider) ??\n        `⚠️ [react-benin-payments] ${provider}: Running in Sandbox Mode - No real transactions will be processed.`\n    );\n  }\n}\n","import type { PaymentValidationError } from \"../types/validation\";\n\n/**\n * The most common `PaymentDriver.validate` shape: a required public key\n * (unless in mock mode) and a positive amount. Both built-in drivers\n * (FedaPay, KKiaPay) use this — reach for it in a custom driver too instead\n * of re-implementing the same two checks.\n *\n * @example\n * ```ts\n * validate: (config, { isMockMode }) =>\n *   validatePublicKeyAndAmount(config.apiKey, config.amount, isMockMode),\n * ```\n */\nexport function validatePublicKeyAndAmount(\n  publicKey: string | undefined,\n  amount: number | undefined,\n  isMockMode: boolean\n): PaymentValidationError | null {\n  if (!isMockMode && (!publicKey || publicKey.trim() === \"\")) {\n    return {\n      code: \"MISSING_PUBLIC_KEY\",\n      message: \"Missing Public Key. Provide it via config or BeninPaymentProvider.\",\n    };\n  }\n  if (!amount || amount <= 0) {\n    return { code: \"INVALID_AMOUNT\", message: \"Invalid amount. Amount must be greater than 0.\" };\n  }\n  return null;\n}\n","import type { Currency } from \"../types\";\r\n\r\n/**\r\n * Formats an amount in XOF (West African CFA Franc).\r\n * \r\n * @param amount - The amount to format\r\n * @returns Formatted string with FCFA suffix (e.g., \"5 000 FCFA\")\r\n * \r\n * @example\r\n * ```ts\r\n * formatXOF(5000);    // \"5 000 FCFA\"\r\n * formatXOF(1500000); // \"1 500 000 FCFA\"\r\n * formatXOF(0);       // \"0 FCFA\"\r\n * ```\r\n */\r\nexport function formatXOF(amount: number): string {\r\n  const formatted = new Intl.NumberFormat(\"fr-FR\", {\r\n    style: \"decimal\",\r\n    minimumFractionDigits: 0,\r\n    maximumFractionDigits: 0,\r\n  }).format(amount);\r\n\r\n  return `${formatted} FCFA`;\r\n}\r\n\r\n/**\r\n * Formats an amount in the specified currency.\r\n * \r\n * @param amount - The amount to format\r\n * @param currency - The currency code (XOF, USD, EUR)\r\n * @returns Formatted string with currency symbol\r\n * \r\n * @example\r\n * ```ts\r\n * formatCurrency(5000, \"XOF\");  // \"5 000 FCFA\"\r\n * formatCurrency(100, \"USD\");   // \"$100.00\"\r\n * formatCurrency(100, \"EUR\");   // \"100,00 €\"\r\n * ```\r\n */\r\nexport function formatCurrency(amount: number, currency: Currency): string {\r\n  switch (currency) {\r\n    case \"XOF\":\r\n      return formatXOF(amount);\r\n    case \"USD\":\r\n      return new Intl.NumberFormat(\"en-US\", {\r\n        style: \"currency\",\r\n        currency: \"USD\",\r\n      }).format(amount);\r\n    case \"EUR\":\r\n      return new Intl.NumberFormat(\"fr-FR\", {\r\n        style: \"currency\",\r\n        currency: \"EUR\",\r\n      }).format(amount);\r\n    default:\r\n      return `${amount} ${currency}`;\r\n  }\r\n}\r\n\r\n/**\r\n * Generates a mock transaction ID for testing.\r\n * \r\n * @returns A unique mock transaction ID\r\n */\r\nexport function generateMockTransactionId(): string {\r\n  const timestamp = Date.now().toString(36);\r\n  const random = Math.random().toString(36).substring(2, 8);\r\n  return `mock_tx_${timestamp}_${random}`;\r\n}\r\n"]}