@pagosrd/azul 0.0.0-stage → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +156 -2
- package/dist/index.cjs +817 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +380 -0
- package/dist/index.d.ts +380 -0
- package/dist/index.js +773 -0
- package/dist/index.js.map +1 -0
- package/package.json +61 -3
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/client.ts","../src/config.ts","../src/errors.ts","../src/money.ts","../src/payment-page.ts","../src/validation.ts","../src/response.ts","../src/transport.ts","../src/redact.ts"],"sourcesContent":["import { randomUUID } from \"node:crypto\";\nimport { resolveConfig, type AzulClientConfig, type ResolvedConfig } from \"./config.js\";\nimport { AzulConfigError, AzulValidationError } from \"./errors.js\";\nimport { centsToAzul, itbisToAzul } from \"./money.js\";\nimport { buildPaymentPage, type PaymentPageInput, type PaymentPageRequest } from \"./payment-page.js\";\nimport { interpretResponse, type AzulResult } from \"./response.js\";\nimport { AzulTransport } from \"./transport.js\";\nimport * as v from \"./validation.js\";\n\n/** Resultado de verifyPayment: la transacción encontrada o `found: false`. */\nexport type VerifyPaymentResult = ({ found: true } & AzulResult) | { found: false; customOrderId: string; raw: Record<string, unknown> };\n\n/** Datos comunes de las operaciones que mueven dinero. */\ninterface OrderFields {\n /** Monto TOTAL en centavos, ITBIS incluido. 150050 = RD$1,500.50. */\n amount: number;\n /** ITBIS en centavos. Omítelo o usa 0 si está exento. */\n itbis?: number;\n /** Número de orden del comercio (máx. 15 caracteres). */\n orderNumber: string;\n /**\n * Identificador único tuyo (máx. 75). Si no lo pasas, el SDK genera uno.\n * Guárdalo: es lo que permite consultar el resultado con verifyPayment si\n * la conexión se cae a mitad de la operación.\n */\n customOrderId?: string;\n /** Nombre alterno que aparece en el estado de cuenta del cliente (máx. 25). */\n altMerchantName?: string;\n /** \"1\" para forzar sin 3D Secure. Úsalo solo si AZUL lo autorizó para tu comercio. */\n forceNo3DS?: boolean;\n}\n\nexport interface CardSaleInput extends OrderFields {\n cardNumber: string;\n /** \"YYYYMM\", \"MM/YY\" o \"MM/YYYY\". */\n expiration: string;\n cvc: string;\n /** Guarda la tarjeta en DataVault y devuelve un token reutilizable. */\n saveToDataVault?: boolean;\n}\n\nexport interface TokenSaleInput extends OrderFields {\n dataVaultToken: string;\n cvc?: string;\n}\n\nexport interface CaptureInput {\n /** AzulOrderId de la pre-autorización (hold). */\n azulOrderId: string;\n /** Monto a capturar en centavos (puede ser menor que el retenido). */\n amount: number;\n itbis?: number;\n}\n\nexport interface RefundInput {\n /** AzulOrderId de la venta original. */\n azulOrderId: string;\n amount: number;\n itbis?: number;\n orderNumber: string;\n customOrderId?: string;\n}\n\nexport interface DataVaultCreateInput {\n cardNumber: string;\n expiration: string;\n cvc: string;\n}\n\nexport interface DataVaultResult {\n status: \"approved\" | \"declined\";\n dataVaultToken: string | undefined;\n /** Número enmascarado que devuelve AZUL, por ejemplo \"411111******1111\". */\n maskedCardNumber: string | undefined;\n brand: string | undefined;\n /** Vencimiento del token, \"YYYYMM\". */\n expiration: string | undefined;\n hasCvv: boolean;\n isoCode: string | undefined;\n message: string | undefined;\n errorDescription: string | undefined;\n raw: Record<string, unknown>;\n}\n\n/**\n * Cliente para los webservices de AZUL.\n *\n * ```ts\n * const azul = new AzulClient({\n * environment: \"pruebas\",\n * merchantId: process.env.AZUL_MERCHANT_ID!,\n * auth1: process.env.AZUL_AUTH1!,\n * auth2: process.env.AZUL_AUTH2!,\n * certificate: process.env.AZUL_CERT_PEM!,\n * privateKey: process.env.AZUL_KEY_PEM!,\n * });\n * ```\n */\nexport class AzulClient {\n private readonly config: ResolvedConfig;\n private readonly transport: AzulTransport;\n\n constructor(config: AzulClientConfig) {\n this.config = resolveConfig(config);\n this.transport = new AzulTransport(this.config);\n }\n\n /** Cierra las conexiones abiertas. Llámalo al apagar tu servidor. */\n async close(): Promise<void> {\n await this.transport.close();\n }\n\n // ---------------------------------------------------------------- ventas\n\n /**\n * Venta directa con datos de tarjeta.\n *\n * OJO: recibir el número de tarjeta en tu servidor te pone dentro del\n * alcance de PCI DSS. Si puedes, usa la Página de Pagos (paymentPage) o\n * cobra con un token de DataVault (tokenSale).\n */\n async sale(input: CardSaleInput): Promise<AzulResult> {\n return this.cardTransaction(\"Sale\", input);\n }\n\n /** Pre-autorización: retiene el monto sin cobrarlo. Captúralo luego con capture(). */\n async hold(input: CardSaleInput): Promise<AzulResult> {\n return this.cardTransaction(\"Hold\", input);\n }\n\n /** Venta con una tarjeta guardada en DataVault. */\n async tokenSale(input: TokenSaleInput): Promise<AzulResult> {\n const order = this.orderFields(input);\n const payload = {\n ...this.base(),\n ...order.fields,\n TrxType: \"Sale\",\n PosInputMode: \"E-Commerce\",\n CardNumber: \"\",\n Expiration: \"\",\n DataVaultToken: v.dataVaultToken(input.dataVaultToken),\n ...(input.cvc ? { CVC: v.cvc(input.cvc) } : {}),\n };\n const data = await this.transport.send(payload, {\n operation: \"\",\n name: \"tokenSale\",\n idempotent: false,\n customOrderId: order.customOrderId,\n });\n return interpretResponse(data, order.customOrderId);\n }\n\n // ------------------------------------------------- después de la venta\n\n /** Captura (total o parcial) una pre-autorización hecha con hold(). */\n async capture(input: CaptureInput): Promise<AzulResult> {\n const payload = {\n ...this.base(),\n AzulOrderId: v.azulOrderId(input.azulOrderId),\n Amount: centsToAzul(input.amount, \"amount\"),\n Itbis: itbisToAzul(input.itbis),\n };\n const data = await this.transport.send(payload, { operation: \"ProcessPost\", name: \"capture\", idempotent: false });\n return interpretResponse(data);\n }\n\n /** Anula una transacción del mismo día (antes del cierre de lote). */\n async void(input: { azulOrderId: string }): Promise<AzulResult> {\n const payload = { ...this.base(), AzulOrderId: v.azulOrderId(input.azulOrderId) };\n const data = await this.transport.send(payload, { operation: \"ProcessVoid\", name: \"void\", idempotent: false });\n return interpretResponse(data);\n }\n\n /** Reembolsa (total o parcialmente) una venta ya liquidada. */\n async refund(input: RefundInput): Promise<AzulResult> {\n const customOrderId = this.customOrderId(input.customOrderId);\n const payload = {\n ...this.base(),\n TrxType: \"Refund\",\n PosInputMode: \"E-Commerce\",\n AzulOrderId: v.azulOrderId(input.azulOrderId),\n Amount: centsToAzul(input.amount, \"amount\"),\n Itbis: itbisToAzul(input.itbis),\n OrderNumber: v.maxText(input.orderNumber, \"orderNumber\", 15, { required: true }),\n CustomOrderId: customOrderId,\n };\n const data = await this.transport.send(payload, {\n operation: \"\",\n name: \"refund\",\n idempotent: false,\n customOrderId,\n });\n return interpretResponse(data, customOrderId);\n }\n\n /**\n * Consulta el estado de una transacción hecha por la API (ProcessPayment) por\n * su customOrderId. Es la forma correcta de salir de la duda después de un\n * AzulAmbiguousError. Si hay varias con el mismo id, AZUL devuelve la última.\n * Si no existe, AZUL responde Found=false y aquí se devuelve `{ found: false }`.\n */\n async verifyPayment(input: { customOrderId: string }): Promise<VerifyPaymentResult> {\n const customOrderId = v.maxText(input.customOrderId, \"customOrderId\", 75, { required: true })!;\n const data = await this.transport.send(\n { ...this.base(), CustomOrderId: customOrderId },\n { operation: \"VerifyPayment\", name: \"verifyPayment\", idempotent: true, customOrderId },\n );\n const found = data.Found;\n if ((found === false || found === \"false\" || found === \"False\") && data.ResponseCode !== \"Error\") {\n return { found: false, customOrderId, raw: data };\n }\n return { found: true, ...interpretResponse(data, customOrderId) };\n }\n\n // ------------------------------------------------------------- DataVault\n\n readonly dataVault = {\n /** Guarda una tarjeta y devuelve un token reutilizable. */\n create: async (input: DataVaultCreateInput): Promise<DataVaultResult> => {\n const payload = {\n ...this.base(),\n TrxType: \"CREATE\",\n CardNumber: v.cardNumber(input.cardNumber),\n Expiration: v.expiration(input.expiration),\n CVC: v.cvc(input.cvc),\n };\n const data = await this.transport.send(payload, {\n operation: \"ProcessDatavault\",\n name: \"dataVault.create\",\n idempotent: false,\n });\n return toDataVaultResult(data);\n },\n /** Elimina un token de DataVault. */\n delete: async (input: { dataVaultToken: string }): Promise<DataVaultResult> => {\n const payload = { ...this.base(), TrxType: \"DELETE\", DataVaultToken: v.dataVaultToken(input.dataVaultToken) };\n const data = await this.transport.send(payload, {\n operation: \"ProcessDatavault\",\n name: \"dataVault.delete\",\n idempotent: true,\n });\n return toDataVaultResult(data);\n },\n };\n\n // ------------------------------------------------------- Página de Pagos\n\n /**\n * Prepara el formulario para redirigir al cliente a la Página de Pagos de\n * AZUL. Con esta vía tu servidor nunca ve el número de tarjeta.\n */\n paymentPage(input: PaymentPageInput): PaymentPageRequest {\n if (!this.config.paymentPage) {\n throw new AzulConfigError(\"Para usar la Página de Pagos configura paymentPage: { authKey, merchantName, merchantType }.\");\n }\n return buildPaymentPage(input, {\n merchantId: this.config.merchantId,\n url: this.config.paymentPageUrl,\n ...this.config.paymentPage,\n });\n }\n\n // -------------------------------------------------------------- internos\n\n private base(): { Channel: string; Store: string } {\n return { Channel: this.config.channel, Store: this.config.merchantId };\n }\n\n private customOrderId(value: string | undefined): string {\n return v.maxText(value, \"customOrderId\", 75) ?? randomUUID();\n }\n\n private orderFields(input: OrderFields) {\n const customOrderId = this.customOrderId(input.customOrderId);\n const fields: Record<string, string> = {\n Amount: centsToAzul(input.amount, \"amount\"),\n Itbis: itbisToAzul(input.itbis),\n OrderNumber: v.maxText(input.orderNumber, \"orderNumber\", 15, { required: true })!,\n CustomOrderId: customOrderId,\n };\n const alt = v.maxText(input.altMerchantName, \"altMerchantName\", 25);\n if (alt) fields.AltMerchantName = alt;\n if (input.forceNo3DS) fields.ForceNo3DS = \"1\";\n if (input.itbis !== undefined && input.itbis > input.amount) {\n throw new AzulValidationError(\"itbis no puede ser mayor que amount: amount es el total con ITBIS incluido.\", [\"itbis\"]);\n }\n return { customOrderId, fields };\n }\n\n private async cardTransaction(trxType: \"Sale\" | \"Hold\", input: CardSaleInput): Promise<AzulResult> {\n const order = this.orderFields(input);\n const payload = {\n ...this.base(),\n ...order.fields,\n TrxType: trxType,\n PosInputMode: \"E-Commerce\",\n CardNumber: v.cardNumber(input.cardNumber),\n Expiration: v.expiration(input.expiration),\n CVC: v.cvc(input.cvc),\n SaveToDataVault: input.saveToDataVault ? \"1\" : \"0\",\n };\n const data = await this.transport.send(payload, {\n operation: \"\",\n name: trxType === \"Sale\" ? \"sale\" : \"hold\",\n idempotent: false,\n customOrderId: order.customOrderId,\n });\n return interpretResponse(data, order.customOrderId);\n }\n}\n\nfunction toDataVaultResult(data: Record<string, unknown>): DataVaultResult {\n const s = (k: string) => (typeof data[k] === \"string\" && data[k] !== \"\" ? (data[k] as string) : undefined);\n const result = interpretResponse(data);\n return {\n status: result.status === \"approved\" ? \"approved\" : \"declined\",\n dataVaultToken: s(\"DataVaultToken\"),\n maskedCardNumber: s(\"CardNumber\"),\n brand: s(\"DataVaultBrand\"),\n expiration: s(\"DataVaultExpiration\"),\n hasCvv: data.HasCVV === true || data.HasCVV === \"true\",\n isoCode: result.isoCode,\n message: result.message,\n errorDescription: result.errorDescription,\n raw: data,\n };\n}\n","import { z } from \"zod\";\nimport type { Dispatcher } from \"undici\";\nimport { AzulConfigError } from \"./errors.js\";\n\nexport type AzulEnvironment = \"pruebas\" | \"produccion\";\n\n/**\n * URLs de AZUL según los documentos técnicos oficiales 2026 (Página de Pago e\n * Integración vía API). La URL alterna de producción viene de `pyazul` (MIT):\n * PENDIENTE DE VERIFICAR, el manual menciona un sitio secundario sin dar la URL.\n */\nexport const AZUL_URLS = {\n pruebas: {\n webservices: \"https://pruebas.azul.com.do/webservices/JSON/Default.aspx\",\n paymentPage: \"https://pruebas.azul.com.do/PaymentPage/\",\n },\n produccion: {\n webservices: \"https://pagos.azul.com.do/webservices/JSON/Default.aspx\",\n webservicesAlterna: \"https://contpagos.azul.com.do/Webservices/JSON/default.aspx\",\n paymentPage: \"https://pagos.azul.com.do/PaymentPage/Default.aspx\",\n },\n} as const;\n\nexport interface AzulPaymentPageConfig {\n /** Llave privada de la Página de Pagos (\"AuthKey\"), entregada por AZUL. */\n authKey: string;\n /** Nombre del comercio que se muestra en la Página de Pagos. */\n merchantName: string;\n /** Tipo de comercio, según lo asigna AZUL. */\n merchantType: string;\n /** Reemplaza el cálculo del AuthHash (por defecto, el del manual oficial: `defaultPaymentPageHash`). */\n hashFn?: (fields: Record<string, string>, authKey: string) => string;\n}\n\n/** Datos de una solicitud o respuesta, ya sin datos de tarjeta, para logs. */\nexport interface AzulRedactedEvent {\n operation: string;\n url: string;\n payload: Record<string, unknown>;\n}\n\nexport interface AzulClientConfig {\n /** Merchant ID (MID) del comercio, se envía como \"Store\". */\n merchantId: string;\n /** Credencial \"Auth1\" del comercio. */\n auth1: string;\n /** Credencial \"Auth2\" del comercio. */\n auth2: string;\n /** Certificado de cliente en formato PEM (contenido, no ruta). */\n certificate: string | Buffer;\n /** Llave privada del certificado en formato PEM (contenido, no ruta). */\n privateKey: string | Buffer;\n environment: AzulEnvironment;\n /** Canal de la transacción. Por defecto \"EC\" (e-commerce). */\n channel?: string;\n /** Tiempo máximo por solicitud en milisegundos. Por defecto 30000. */\n timeoutMs?: number;\n /** Reemplaza las URLs de los webservices (útil para pruebas o un proxy propio). */\n urls?: { webservices?: string; webservicesAlterna?: string };\n /** Requerido solo si vas a usar la Página de Pagos. */\n paymentPage?: AzulPaymentPageConfig;\n /**\n * Dispatcher de undici a usar. Si lo pasas, el SDK NO configura el\n * certificado de cliente por ti. Pensado para pruebas (MockAgent) o proxies.\n */\n dispatcher?: Dispatcher;\n /** Se llama antes de cada solicitud con el payload ya censurado. Útil para logs. */\n onRequest?: (event: AzulRedactedEvent) => void;\n /** Se llama con cada respuesta de AZUL, censurada. */\n onResponse?: (event: AzulRedactedEvent) => void;\n}\n\nconst nonEmpty = (field: string) => z.string({ error: `${field} es requerido` }).trim().min(1, `${field} no puede estar vacío`);\nconst pem = (field: string) =>\n z.union([z.string(), z.instanceof(Buffer)]).refine((v) => String(v).includes(\"-----BEGIN\"), {\n message: `${field} debe ser el contenido PEM (empieza con \"-----BEGIN\"), no una ruta de archivo`,\n });\n\nconst configSchema = z.object({\n merchantId: nonEmpty(\"merchantId\").max(11, \"merchantId tiene un máximo de 11 caracteres\"),\n auth1: nonEmpty(\"auth1\"),\n auth2: nonEmpty(\"auth2\"),\n environment: z.enum([\"pruebas\", \"produccion\"], { error: 'environment debe ser \"pruebas\" o \"produccion\"' }),\n channel: z.string().max(3).optional(),\n timeoutMs: z.number().int().positive().max(120_000).optional(),\n paymentPage: z\n .object({ authKey: nonEmpty(\"paymentPage.authKey\"), merchantName: nonEmpty(\"paymentPage.merchantName\"), merchantType: nonEmpty(\"paymentPage.merchantType\") })\n .optional(),\n});\n\nexport interface ResolvedConfig extends AzulClientConfig {\n channel: string;\n timeoutMs: number;\n webservicesUrl: string;\n webservicesAlternaUrl: string | undefined;\n paymentPageUrl: string;\n}\n\nexport function resolveConfig(input: AzulClientConfig): ResolvedConfig {\n const parsed = configSchema.safeParse(input);\n const issues = parsed.success ? [] : parsed.error.issues.map((i) => i.message);\n // El certificado solo es obligatorio si el SDK va a crear su propia conexión.\n if (!input.dispatcher) {\n for (const [field, value] of [[\"certificate\", input.certificate], [\"privateKey\", input.privateKey]] as const) {\n const check = pem(field).safeParse(value);\n if (!check.success) issues.push(...check.error.issues.map((i) => i.message));\n }\n }\n if (issues.length > 0) {\n throw new AzulConfigError(`Configuración de AZUL inválida: ${issues.join(\"; \")}`);\n }\n\n const env = input.environment;\n const urls = AZUL_URLS[env];\n return {\n ...input,\n channel: input.channel ?? \"EC\",\n timeoutMs: input.timeoutMs ?? 30_000,\n webservicesUrl: input.urls?.webservices ?? urls.webservices,\n webservicesAlternaUrl:\n input.urls?.webservicesAlterna ?? (env === \"produccion\" ? AZUL_URLS.produccion.webservicesAlterna : undefined),\n paymentPageUrl: urls.paymentPage,\n };\n}\n","/**\n * Errores del SDK.\n *\n * Regla de diseño: un pago DECLINADO no es una excepción. Una declinación es una\n * respuesta normal del banco y se devuelve como `status: \"declined\"`.\n * Las excepciones se reservan para cosas que el código que llama debe manejar\n * de forma distinta: configuración inválida, datos inválidos, fallas del\n * sistema de AZUL y, sobre todo, resultados AMBIGUOS (no sabemos si se cobró).\n */\n\nexport class AzulError extends Error {\n override readonly name: string = \"AzulError\";\n constructor(message: string, options?: { cause?: unknown }) {\n super(message, options);\n }\n}\n\n/** La configuración del cliente es inválida (credenciales, certificado, ambiente). */\nexport class AzulConfigError extends AzulError {\n override readonly name = \"AzulConfigError\";\n}\n\n/** Los datos de la operación son inválidos. No se envió nada a AZUL. */\nexport class AzulValidationError extends AzulError {\n override readonly name = \"AzulValidationError\";\n readonly issues: string[];\n constructor(message: string, issues: string[] = []) {\n super(message);\n this.issues = issues;\n }\n}\n\n/**\n * AZUL respondió, pero con un error de sistema (ResponseCode \"Error\",\n * errores SGS de gateway o ErrorMessage). La operación NO fue aprobada.\n */\nexport class AzulResponseError extends AzulError {\n override readonly name = \"AzulResponseError\";\n readonly response: Record<string, unknown>;\n constructor(message: string, response: Record<string, unknown>) {\n super(message);\n this.response = response;\n }\n}\n\n/** AZUL respondió con un código HTTP de error y la operación es segura de tratar como no ejecutada. */\nexport class AzulHttpError extends AzulError {\n override readonly name = \"AzulHttpError\";\n readonly statusCode: number;\n readonly body: string;\n constructor(message: string, statusCode: number, body: string) {\n super(message);\n this.statusCode = statusCode;\n this.body = body;\n }\n}\n\n/**\n * La solicitud pudo haber llegado a AZUL, pero no recibimos una respuesta\n * confiable (timeout de lectura, conexión cortada, HTTP 5xx, JSON inválido).\n *\n * NO reintentes a ciegas una operación que mueve dinero: podrías cobrar dos\n * veces. Consulta el estado con `verifyPayment({ customOrderId })` y decide.\n */\nexport class AzulAmbiguousError extends AzulError {\n override readonly name = \"AzulAmbiguousError\";\n readonly customOrderId: string | undefined;\n constructor(message: string, customOrderId: string | undefined, options?: { cause?: unknown }) {\n super(message, options);\n this.customOrderId = customOrderId;\n }\n}\n","import { AzulValidationError } from \"./errors.js\";\n\n/**\n * AZUL trabaja con montos en CENTAVOS, enviados como texto de dígitos.\n * Este SDK acepta solo enteros de centavos para que nunca haya errores de\n * redondeo por usar decimales de punto flotante.\n */\n\nconst MAX_CENTS = 999_999_999_999; // 12 dígitos, el máximo que acepta AZUL.\n\n/** Valida un monto en centavos y lo devuelve como texto para AZUL. */\nexport function centsToAzul(value: number, field: string, options: { allowZero?: boolean } = {}): string {\n if (!Number.isSafeInteger(value)) {\n throw new AzulValidationError(\n `${field} debe ser un entero de centavos (por ejemplo 150050 para RD$1,500.50). Recibido: ${String(value)}`,\n [field],\n );\n }\n if (value < 0) {\n throw new AzulValidationError(`${field} no puede ser negativo.`, [field]);\n }\n if (value === 0 && !options.allowZero) {\n throw new AzulValidationError(`${field} debe ser mayor que cero.`, [field]);\n }\n if (value > MAX_CENTS) {\n throw new AzulValidationError(`${field} excede el máximo de 12 dígitos que acepta AZUL.`, [field]);\n }\n return String(value);\n}\n\n/** ITBIS en el formato de AZUL: un ITBIS de cero se envía como \"000\". */\nexport function itbisToAzul(value: number | undefined): string {\n if (value === undefined || value === 0) return \"000\";\n return centsToAzul(value, \"itbis\");\n}\n\n/**\n * Convierte un monto escrito en pesos a centavos SIN pasar por punto flotante.\n *\n * toCents(\"1,500.50\") === 150050\n * toCents(\"1500\") === 150000\n * toCents(1500.5) === 150050\n */\nexport function toCents(amount: string | number): number {\n const text = typeof amount === \"number\" ? amount.toString() : amount;\n const noSymbol = text.trim().replace(/^RD\\$\\s*/i, \"\");\n // La coma SOLO como separador de miles (\"1,500.50\"); \"1500,50\" se rechaza por ambiguo.\n if (noSymbol.includes(\",\") && !/^\\d{1,3}(,\\d{3})+(\\.\\d{1,2})?$/.test(noSymbol)) {\n throw new AzulValidationError(`Monto ambiguo: \"${text}\". Usa punto para los decimales y coma solo para los miles.`, [\"amount\"]);\n }\n const cleaned = noSymbol.replace(/,/g, \"\");\n const match = /^(\\d+)(?:\\.(\\d{1,2}))?$/.exec(cleaned);\n if (!match) {\n throw new AzulValidationError(\n `Monto inválido: \"${text}\". Usa como máximo 2 decimales, por ejemplo \"1,500.50\".`,\n [\"amount\"],\n );\n }\n const pesos = match[1] ?? \"0\";\n const decimals = (match[2] ?? \"\").padEnd(2, \"0\");\n const cents = Number(pesos) * 100 + Number(decimals);\n if (!Number.isSafeInteger(cents)) {\n throw new AzulValidationError(`Monto demasiado grande: \"${text}\".`, [\"amount\"]);\n }\n return cents;\n}\n","import { createHmac, timingSafeEqual } from \"node:crypto\";\nimport { AzulValidationError } from \"./errors.js\";\nimport { centsToAzul } from \"./money.js\";\nimport * as v from \"./validation.js\";\n\nexport interface PaymentPageInput {\n /** Monto TOTAL en centavos, ITBIS incluido. */\n amount: number;\n /** ITBIS en centavos. 0 u omitido si está exento. */\n itbis?: number;\n /** Número de orden único del comercio (máx. 15). */\n orderNumber: string;\n /** URL https a la que AZUL devuelve al cliente si el pago se aprueba. */\n approvedUrl: string;\n /** URL https si el pago se declina (se envía como \"DeclinedUrl\"). */\n declineUrl: string;\n /** URL https si el cliente cancela. */\n cancelUrl: string;\n /** Idioma de la página. Por defecto \"ES\". */\n locale?: \"ES\" | \"EN\";\n /** Mostrar el resultado en la página de AZUL antes de volver. Por defecto true. */\n showTransactionResult?: boolean;\n /** Hasta dos campos personalizados que se muestran al cliente. */\n customFields?: [CustomField?, CustomField?];\n /** Nombre alterno en el estado de cuenta (máx. 25; letras, números, espacios, punto y coma). */\n altMerchantName?: string;\n /** Guardar la tarjeta en DataVault. */\n saveToDataVault?: boolean;\n}\n\nexport interface CustomField {\n label: string;\n value: string;\n}\n\nexport interface PaymentPageRequest {\n /** URL a la que se envía el formulario por POST. */\n url: string;\n /** Campos del formulario, ya con el AuthHash calculado. */\n fields: Record<string, string>;\n /** HTML listo para devolver al navegador; se envía solo al cargar. */\n html: string;\n}\n\n/**\n * Campos del requerimiento que entran en el AuthHash, en el orden exacto del\n * \"Documento técnico - Página de Pago AZUL 2026\" (sección \"Manejo de\n * autenticación\"), confirmado con el ejemplo de cálculo que AZUL nos envió.\n */\nexport const PAYMENT_PAGE_HASH_FIELDS = [\n \"MerchantId\",\n \"MerchantName\",\n \"MerchantType\",\n \"CurrencyCode\",\n \"OrderNumber\",\n \"Amount\",\n \"ITBIS\",\n \"ApprovedUrl\",\n \"DeclinedUrl\",\n \"CancelUrl\",\n \"UseCustomField1\",\n \"CustomField1Label\",\n \"CustomField1Value\",\n \"UseCustomField2\",\n \"CustomField2Label\",\n \"CustomField2Value\",\n] as const;\n\n/** Campos del retorno a ApprovedUrl/DeclinedUrl que entran en su AuthHash, en orden. */\nexport const PAYMENT_PAGE_RESPONSE_HASH_FIELDS = [\n \"OrderNumber\",\n \"Amount\",\n \"AuthorizationCode\",\n \"DateTime\",\n \"ResponseCode\",\n \"IsoCode\",\n \"ResponseMessage\",\n \"ErrorDescription\",\n \"RRN\",\n] as const;\n\n/**\n * AuthHash del requerimiento: HMAC-SHA512 con la AuthKey como llave sobre los\n * campos concatenados más la AuthKey al final, en hexadecimal. AZUL acepta la\n * cadena en UTF-8 o en UTF-16LE; usamos UTF-8, que es lo que reproduce el\n * ejemplo oficial.\n */\nexport function defaultPaymentPageHash(fields: Record<string, string>, authKey: string): string {\n const text = PAYMENT_PAGE_HASH_FIELDS.map((k) => fields[k] ?? \"\").join(\"\") + authKey;\n return createHmac(\"sha512\", authKey).update(text, \"utf8\").digest(\"hex\");\n}\n\n/**\n * AuthHash que AZUL manda en el retorno: HMAC-SHA512 con la AuthKey como llave\n * sobre OrderNumber + Amount + AuthorizationCode + DateTime + ResponseCode +\n * IsoCode + ResponseMessage + ErrorDescription + RRN + AuthKey, con la cadena\n * en UTF-16LE (\"Unicode\"), según el manual.\n */\nexport function paymentPageResponseHash(params: Record<string, string | undefined>, authKey: string): string {\n const text = PAYMENT_PAGE_RESPONSE_HASH_FIELDS.map((k) => params[k] ?? \"\").join(\"\") + authKey;\n return createHmac(\"sha512\", authKey).update(Buffer.from(text, \"utf16le\")).digest(\"hex\");\n}\n\n/**\n * Verifica que un retorno de la Página de Pagos lo generó AZUL. Devuelve false\n * si falta el AuthHash o no coincide. Compara en tiempo constante.\n * OJO: el hash no cubre AzulOrderId, CardNumber ni ITBIS; esos valores vienen\n * del navegador y no deben usarse para mover dinero sin otra confirmación.\n */\nexport function verifyPaymentPageResponse(params: Record<string, string | undefined>, authKey: string): boolean {\n const received = (params.AuthHash ?? \"\").trim().toLowerCase();\n if (!/^[0-9a-f]{128}$/.test(received)) return false;\n const expected = paymentPageResponseHash(params, authKey);\n return timingSafeEqual(Buffer.from(received, \"hex\"), Buffer.from(expected, \"hex\"));\n}\n\nexport interface PaymentPageMerchant {\n merchantId: string;\n merchantName: string;\n merchantType: string;\n authKey: string;\n url: string;\n hashFn?: (fields: Record<string, string>, authKey: string) => string;\n}\n\nexport function buildPaymentPage(input: PaymentPageInput, merchant: PaymentPageMerchant): PaymentPageRequest {\n const amount = centsToAzul(input.amount, \"amount\");\n const itbis = input.itbis ? centsToAzul(input.itbis, \"itbis\", { allowZero: true }) : \"000\";\n if (input.itbis !== undefined && input.itbis > input.amount) {\n throw new AzulValidationError(\"itbis no puede ser mayor que amount.\", [\"itbis\"]);\n }\n const orderNumber = v.maxText(input.orderNumber, \"orderNumber\", 15, { required: true })!;\n\n const alt = v.maxText(input.altMerchantName, \"altMerchantName\", 25);\n if (alt && !/^[a-zA-Z0-9\\s.,]*$/.test(alt)) {\n throw new AzulValidationError(\"altMerchantName solo admite letras sin acento, números, espacios, punto y coma.\", [\"altMerchantName\"]);\n }\n\n const [cf1, cf2] = input.customFields ?? [];\n const fields: Record<string, string> = {\n TrxType: \"Sale\",\n MerchantId: merchant.merchantId,\n MerchantName: merchant.merchantName,\n MerchantType: merchant.merchantType,\n CurrencyCode: \"$\",\n OrderNumber: orderNumber,\n Amount: amount,\n ITBIS: itbis,\n ApprovedUrl: v.httpsUrl(input.approvedUrl, \"approvedUrl\"),\n DeclinedUrl: v.httpsUrl(input.declineUrl, \"declineUrl\"),\n CancelUrl: v.httpsUrl(input.cancelUrl, \"cancelUrl\"),\n UseCustomField1: cf1 ? \"1\" : \"0\",\n CustomField1Label: cf1?.label ?? \"\",\n CustomField1Value: cf1?.value ?? \"\",\n UseCustomField2: cf2 ? \"1\" : \"0\",\n CustomField2Label: cf2?.label ?? \"\",\n CustomField2Value: cf2?.value ?? \"\",\n ShowTransactionResult: input.showTransactionResult === false ? \"0\" : \"1\",\n Locale: input.locale ?? \"ES\",\n };\n if (alt) fields.AltMerchantName = alt;\n if (input.saveToDataVault) fields.SaveToDataVault = \"1\";\n\n fields.AuthHash = (merchant.hashFn ?? defaultPaymentPageHash)(fields, merchant.authKey);\n\n return { url: merchant.url, fields, html: renderAutoSubmitForm(merchant.url, fields) };\n}\n\nconst HTML_ESCAPES: Record<string, string> = { \"&\": \"&\", \"<\": \"<\", \">\": \">\", '\"': \""\", \"'\": \"'\" };\n\n/** Escapa texto para HTML. pyazul NO escapa los valores; aquí sí, para evitar inyección de HTML. */\nexport function escapeHtml(value: string): string {\n return value.replace(/[&<>\"']/g, (c) => HTML_ESCAPES[c]!);\n}\n\nfunction renderAutoSubmitForm(url: string, fields: Record<string, string>): string {\n const inputs = Object.entries(fields)\n .map(([name, value]) => ` <input type=\"hidden\" name=\"${escapeHtml(name)}\" value=\"${escapeHtml(value)}\">`)\n .join(\"\\n\");\n return `<!doctype html>\n<html lang=\"es\">\n<head><meta charset=\"utf-8\"><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\"><title>Redirigiendo al pago seguro</title></head>\n<body>\n <form id=\"azul-payment\" method=\"post\" action=\"${escapeHtml(url)}\">\n${inputs}\n <noscript><button type=\"submit\">Continuar al pago</button></noscript>\n </form>\n <script>document.getElementById(\"azul-payment\").submit();</script>\n</body>\n</html>`;\n}\n","import { AzulValidationError } from \"./errors.js\";\n\n/** Algoritmo de Luhn: detecta errores de digitación en números de tarjeta. */\nexport function passesLuhn(digits: string): boolean {\n let sum = 0;\n let double = false;\n for (let i = digits.length - 1; i >= 0; i--) {\n let d = digits.charCodeAt(i) - 48;\n if (double) {\n d *= 2;\n if (d > 9) d -= 9;\n }\n sum += d;\n double = !double;\n }\n return sum % 10 === 0;\n}\n\nexport function cardNumber(value: string): string {\n const digits = String(value).replace(/[\\s-]/g, \"\");\n if (!/^\\d{12,19}$/.test(digits)) {\n throw new AzulValidationError(\"cardNumber debe tener entre 12 y 19 dígitos.\", [\"cardNumber\"]);\n }\n if (!passesLuhn(digits)) {\n throw new AzulValidationError(\"cardNumber no es un número de tarjeta válido (falla la verificación de Luhn).\", [\"cardNumber\"]);\n }\n return digits;\n}\n\n/** Acepta \"YYYYMM\", \"MM/YY\" o \"MM/YYYY\" y devuelve \"YYYYMM\", que es lo que pide AZUL. */\nexport function expiration(value: string): string {\n const v = String(value).trim();\n let year: number;\n let month: number;\n let m: RegExpExecArray | null;\n if ((m = /^(\\d{4})(\\d{2})$/.exec(v))) {\n year = Number(m[1]);\n month = Number(m[2]);\n } else if ((m = /^(\\d{1,2})\\s*\\/\\s*(\\d{2}|\\d{4})$/.exec(v))) {\n month = Number(m[1]);\n year = Number(m[2]!.length === 2 ? `20${m[2]}` : m[2]);\n } else {\n throw new AzulValidationError('expiration debe tener el formato \"YYYYMM\", \"MM/YY\" o \"MM/YYYY\".', [\"expiration\"]);\n }\n if (month < 1 || month > 12) {\n throw new AzulValidationError(\"expiration tiene un mes inválido.\", [\"expiration\"]);\n }\n return `${year}${String(month).padStart(2, \"0\")}`;\n}\n\nexport function cvc(value: string): string {\n const v = String(value).trim();\n if (!/^\\d{3,4}$/.test(v)) {\n throw new AzulValidationError(\"cvc debe tener 3 o 4 dígitos.\", [\"cvc\"]);\n }\n return v;\n}\n\nexport function maxText(value: string | undefined, field: string, max: number, options: { required?: boolean } = {}): string | undefined {\n if (value === undefined || value === \"\") {\n if (options.required) throw new AzulValidationError(`${field} es requerido.`, [field]);\n return undefined;\n }\n if (value.length > max) {\n throw new AzulValidationError(`${field} admite como máximo ${max} caracteres (tiene ${value.length}).`, [field]);\n }\n return value;\n}\n\nexport function azulOrderId(value: string): string {\n const v = String(value ?? \"\").trim();\n if (!/^\\d+$/.test(v)) {\n throw new AzulValidationError(\"azulOrderId debe ser el identificador numérico que devolvió AZUL.\", [\"azulOrderId\"]);\n }\n return v;\n}\n\nexport function dataVaultToken(value: string): string {\n const v = String(value ?? \"\").trim();\n if (!/^[A-Fa-f0-9-]{30,40}$/.test(v)) {\n throw new AzulValidationError(\"dataVaultToken no tiene el formato de un token de DataVault.\", [\"dataVaultToken\"]);\n }\n return v;\n}\n\nexport function httpsUrl(value: string, field: string): string {\n let url: URL;\n try {\n url = new URL(value);\n } catch {\n throw new AzulValidationError(`${field} debe ser una URL válida.`, [field]);\n }\n if (url.protocol !== \"https:\") {\n throw new AzulValidationError(`${field} debe usar https://.`, [field]);\n }\n return value;\n}\n","import { AzulResponseError } from \"./errors.js\";\n\nexport type AzulStatus = \"approved\" | \"declined\" | \"requires_3ds\";\n\n/** Respuesta normalizada de una operación con AZUL. */\nexport interface AzulResult {\n /** approved = aprobada, declined = declinada por el banco o por reglas, requires_3ds = falta autenticación 3D Secure. */\n status: AzulStatus;\n /** \"ISO8583\" en transacciones procesadas. */\n responseCode: string | undefined;\n /** \"00\" = aprobada. Cualquier otro código es una declinación. */\n isoCode: string | undefined;\n /** Mensaje de AZUL, por ejemplo \"APROBADA\". */\n message: string | undefined;\n /** Detalle del error o de la declinación, si lo hay. */\n errorDescription: string | undefined;\n authorizationCode: string | undefined;\n /** Identificador de AZUL. Lo necesitas para capturar, anular o reembolsar. */\n azulOrderId: string | undefined;\n /** Número de referencia de la red (RRN), útil para conciliación. */\n rrn: string | undefined;\n /** Token de DataVault, si se pidió guardar la tarjeta. */\n dataVaultToken: string | undefined;\n /** Identificador propio con el que puedes consultar la transacción con verifyPayment. */\n customOrderId: string | undefined;\n /** Respuesta original de AZUL (sin datos de tarjeta completos). */\n raw: Record<string, unknown>;\n}\n\nconst SYSTEM_GATEWAY_ERRORS = [\n \"timeout\",\n \"not been processed\",\n \"Internal Server Error\",\n \"Unauthorized\",\n \"Server Unavailable\",\n \"SSL/TLS\",\n \"connection\",\n];\n\nconst str = (v: unknown): string | undefined => (typeof v === \"string\" && v !== \"\" ? v : undefined);\n\n/**\n * Interpreta la respuesta de los webservices de AZUL.\n * La lógica sigue el comportamiento documentado en `pyazul` (MIT):\n * - ResponseCode \"Error\" -> error de sistema (excepción)\n * - ResponseCode \"ISO8583\" + \"00\" -> aprobada\n * - IsoCode \"3D\" / \"3D2METHOD\" -> requiere 3D Secure\n * - Otro IsoCode -> declinada (NO es excepción)\n * - ErrorDescription con \"SGS-\" -> error de gateway (excepción) o declinación por regla\n * - ErrorMessage -> error de API (excepción)\n */\nexport function interpretResponse(data: Record<string, unknown>, customOrderId?: string): AzulResult {\n const responseCode = str(data.ResponseCode);\n const isoCode = str(data.IsoCode);\n const message = str(data.ResponseMessage);\n const errorDescription = str(data.ErrorDescription);\n\n const build = (status: AzulStatus): AzulResult => ({\n status,\n responseCode,\n isoCode,\n message,\n errorDescription,\n authorizationCode: str(data.AuthorizationCode),\n azulOrderId: str(data.AzulOrderId),\n rrn: str(data.RRN),\n dataVaultToken: str(data.DataVaultToken),\n customOrderId: str(data.CustomOrderId) ?? customOrderId,\n raw: data,\n });\n\n if (responseCode === \"Error\") {\n throw new AzulResponseError(`Error de sistema de AZUL: ${errorDescription ?? \"sin descripción\"}`, data);\n }\n\n if (responseCode === \"ISO8583\") {\n if (isoCode === \"00\") return build(\"approved\");\n if (isoCode === \"3D\" || isoCode === \"3D2METHOD\") return build(\"requires_3ds\");\n return build(\"declined\");\n }\n\n if (errorDescription?.includes(\"SGS-\")) {\n if (SYSTEM_GATEWAY_ERRORS.some((e) => errorDescription.includes(e))) {\n throw new AzulResponseError(`Error de gateway de AZUL: ${errorDescription}`, data);\n }\n return build(\"declined\");\n }\n\n const errorMessage = str(data.ErrorMessage);\n if (errorMessage) {\n throw new AzulResponseError(`Error de API de AZUL: ${errorMessage}`, data);\n }\n\n // Respuestas como las de DataVault traen IsoCode sin ResponseCode.\n if (isoCode === \"00\") return build(\"approved\");\n if (isoCode) return build(\"declined\");\n\n throw new AzulResponseError(\"Respuesta de AZUL con estructura desconocida\", data);\n}\n","import { Agent, request, type Dispatcher } from \"undici\";\nimport type { ResolvedConfig } from \"./config.js\";\nimport { AzulAmbiguousError, AzulError, AzulHttpError } from \"./errors.js\";\nimport { redact } from \"./redact.js\";\n\n/**\n * Errores que ocurren ANTES de que la solicitud llegue a AZUL (no se pudo\n * resolver el nombre, conectar o negociar TLS). En estos casos es seguro\n * intentar con la URL alterna, incluso para operaciones que mueven dinero.\n */\nconst CONNECT_PHASE_CODES = new Set([\n \"ECONNREFUSED\",\n \"ENOTFOUND\",\n \"EAI_AGAIN\",\n \"EHOSTUNREACH\",\n \"ENETUNREACH\",\n \"UND_ERR_CONNECT_TIMEOUT\",\n]);\n\nfunction errorCode(err: unknown): string | undefined {\n if (err && typeof err === \"object\") {\n const code = (err as { code?: unknown }).code;\n if (typeof code === \"string\") return code;\n const cause = (err as { cause?: unknown }).cause;\n if (cause && cause !== err) return errorCode(cause);\n }\n return undefined;\n}\n\nexport function isConnectPhaseError(err: unknown): boolean {\n const code = errorCode(err);\n return code !== undefined && CONNECT_PHASE_CODES.has(code);\n}\n\nexport interface SendOptions {\n /** Operación de AZUL que va en el query string, por ejemplo \"ProcessVoid\". Vacío para venta/hold/reembolso. */\n operation: string;\n /** Nombre legible para logs y errores. */\n name: string;\n /**\n * true solo para operaciones de consulta. Una operación idempotente se\n * reintenta en la URL alterna incluso ante fallas ambiguas.\n */\n idempotent: boolean;\n customOrderId?: string;\n}\n\nexport class AzulTransport {\n private readonly dispatcher: Dispatcher;\n private readonly ownsDispatcher: boolean;\n\n constructor(private readonly config: ResolvedConfig) {\n if (config.dispatcher) {\n this.dispatcher = config.dispatcher;\n this.ownsDispatcher = false;\n } else {\n this.dispatcher = new Agent({\n connect: {\n cert: config.certificate,\n key: config.privateKey,\n timeout: Math.min(10_000, config.timeoutMs),\n },\n });\n this.ownsDispatcher = true;\n }\n }\n\n async close(): Promise<void> {\n if (this.ownsDispatcher) await this.dispatcher.close();\n }\n\n async send(payload: Record<string, unknown>, options: SendOptions): Promise<Record<string, unknown>> {\n const urls = [this.config.webservicesUrl];\n if (this.config.webservicesAlternaUrl) urls.push(this.config.webservicesAlternaUrl);\n\n let lastError: unknown;\n for (let i = 0; i < urls.length; i++) {\n const base = urls[i]!;\n const url = options.operation ? `${base}?${options.operation}` : base;\n const hasFallback = i < urls.length - 1;\n\n this.config.onRequest?.({ operation: options.name, url, payload: redact(payload) });\n\n let statusCode: number;\n let text: string;\n try {\n const res = await request(url, {\n method: \"POST\",\n dispatcher: this.dispatcher,\n headers: {\n \"content-type\": \"application/json\",\n Auth1: this.config.auth1,\n Auth2: this.config.auth2,\n },\n body: JSON.stringify(payload),\n headersTimeout: this.config.timeoutMs,\n bodyTimeout: this.config.timeoutMs,\n });\n statusCode = res.statusCode;\n text = await res.body.text();\n } catch (err) {\n lastError = err;\n if (isConnectPhaseError(err)) {\n if (hasFallback) continue;\n throw new AzulError(`No se pudo conectar con AZUL (${options.name}). La solicitud no se envió.`, { cause: err });\n }\n if (options.idempotent && hasFallback) continue;\n throw this.ambiguous(options, `fallo de red después de enviar la solicitud (${errorCode(err) ?? \"desconocido\"})`, err);\n }\n\n if (statusCode >= 500) {\n lastError = new AzulHttpError(`HTTP ${statusCode}`, statusCode, text);\n if (options.idempotent && hasFallback) continue;\n throw this.ambiguous(options, `AZUL respondió HTTP ${statusCode}`, lastError);\n }\n if (statusCode >= 400) {\n throw new AzulHttpError(`AZUL rechazó la solicitud ${options.name} con HTTP ${statusCode}`, statusCode, text);\n }\n\n let data: unknown;\n try {\n data = JSON.parse(text);\n } catch (err) {\n if (options.idempotent && hasFallback) {\n lastError = err;\n continue;\n }\n throw this.ambiguous(options, \"AZUL devolvió una respuesta que no es JSON válido\", err);\n }\n if (!data || typeof data !== \"object\" || Array.isArray(data)) {\n throw this.ambiguous(options, \"AZUL devolvió una respuesta vacía o con formato inesperado\", undefined);\n }\n const record = data as Record<string, unknown>;\n this.config.onResponse?.({ operation: options.name, url, payload: redact(record) });\n return record;\n }\n\n // Solo se llega aquí si todas las URLs fallaron en operaciones reintentables.\n if (isConnectPhaseError(lastError)) {\n throw new AzulError(`No se pudo conectar con AZUL (${options.name}). La solicitud no se envió.`, { cause: lastError });\n }\n throw this.ambiguous(options, \"todas las URLs de AZUL fallaron\", lastError);\n }\n\n private ambiguous(options: SendOptions, reason: string, cause: unknown): AzulAmbiguousError {\n const hint = options.customOrderId\n ? ` Consulta el estado con verifyPayment({ customOrderId: \"${options.customOrderId}\" }) antes de reintentar.`\n : \" Verifica el estado en el portal de AZUL antes de reintentar.\";\n return new AzulAmbiguousError(\n `Resultado desconocido para ${options.name}: ${reason}. Es posible que AZUL sí la haya procesado.${hint}`,\n options.customOrderId,\n { cause },\n );\n }\n}\n","/**\n * Censura de datos sensibles para logs. Nunca registres un número de tarjeta\n * completo ni un CVC: eso te mete de lleno en el alcance de PCI DSS.\n */\n\nconst DROP = new Set([\"CVC\", \"Auth1\", \"Auth2\"]);\nconst MASK_PAN = new Set([\"CardNumber\"]);\nconst MASK_PARTIAL = new Set([\"DataVaultToken\"]);\n\nexport function maskPan(pan: string): string {\n const digits = pan.replace(/\\D/g, \"\");\n if (digits.length < 10) return digits.length === 0 ? \"\" : \"****\";\n return `${digits.slice(0, 6)}${\"*\".repeat(digits.length - 10)}${digits.slice(-4)}`;\n}\n\nexport function redact(payload: Record<string, unknown>): Record<string, unknown> {\n const out: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(payload)) {\n if (DROP.has(key)) {\n if (value !== undefined && value !== \"\") out[key] = \"[censurado]\";\n continue;\n }\n if (MASK_PAN.has(key) && typeof value === \"string\") {\n out[key] = maskPan(value);\n continue;\n }\n if (MASK_PARTIAL.has(key) && typeof value === \"string\" && value.length > 8) {\n out[key] = `${value.slice(0, 4)}…${value.slice(-4)}`;\n continue;\n }\n out[key] = value;\n }\n return out;\n}\n"],"mappings":"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","names":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,64 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pagosrd/azul",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "SDK no oficial en TypeScript para la pasarela de pagos AZUL (República Dominicana): Página de Pago con AuthHash y verificación del retorno, ventas, reembolsos, DataVault y VerifyPayment.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"author": "Cristian Encarnación",
|
|
7
|
+
"type": "module",
|
|
8
|
+
"main": "./dist/index.cjs",
|
|
9
|
+
"module": "./dist/index.js",
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"exports": {
|
|
12
|
+
".": {
|
|
13
|
+
"import": {
|
|
14
|
+
"types": "./dist/index.d.ts",
|
|
15
|
+
"default": "./dist/index.js"
|
|
16
|
+
},
|
|
17
|
+
"require": {
|
|
18
|
+
"types": "./dist/index.d.cts",
|
|
19
|
+
"default": "./dist/index.cjs"
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
"files": [
|
|
24
|
+
"dist",
|
|
25
|
+
"README.md",
|
|
26
|
+
"LICENSE"
|
|
27
|
+
],
|
|
28
|
+
"keywords": [
|
|
29
|
+
"azul",
|
|
30
|
+
"azul-dominicana",
|
|
31
|
+
"datavault",
|
|
32
|
+
"dominican-republic",
|
|
33
|
+
"pagina-de-pago",
|
|
34
|
+
"pagos",
|
|
35
|
+
"payment-gateway",
|
|
36
|
+
"payment-page",
|
|
37
|
+
"payments",
|
|
38
|
+
"republica-dominicana",
|
|
39
|
+
"typescript"
|
|
40
|
+
],
|
|
41
|
+
"engines": {
|
|
42
|
+
"node": ">=20"
|
|
43
|
+
},
|
|
44
|
+
"sideEffects": false,
|
|
45
|
+
"dependencies": {
|
|
46
|
+
"undici": "^7.30.1",
|
|
47
|
+
"zod": "^4.6.7"
|
|
48
|
+
},
|
|
49
|
+
"devDependencies": {
|
|
50
|
+
"@types/node": "^22.20.5",
|
|
51
|
+
"tsup": "^8.5.1",
|
|
52
|
+
"typescript": "^5.9.3",
|
|
53
|
+
"vitest": "^5.0.5"
|
|
54
|
+
},
|
|
55
|
+
"publishConfig": {
|
|
56
|
+
"access": "public"
|
|
57
|
+
},
|
|
58
|
+
"homepage": "https://pagosrd.com",
|
|
59
|
+
"scripts": {
|
|
60
|
+
"build": "tsup",
|
|
61
|
+
"test": "vitest run",
|
|
62
|
+
"typecheck": "tsc --noEmit"
|
|
63
|
+
}
|
|
6
64
|
}
|