Credenciales del banco a salvo
Tu clave de Yappy vive cifrada en nuestro servidor. Nunca llega a tu web ni al navegador de tu cliente.
DexaPay · integración
No necesitas servidor. Tu web abre el pago de DexaPay con el total del carrito, el cliente confirma en su Yappy y la plata entra directo a tu Yappy Comercial.
La ruta corta
En tu portal pegas el ID de comercio, tu dominio y la clave secreta que te da Banco General. Quedan cifradas.
Te damos el script con tu clave pública. Funciona solo desde tu dominio registrado y los que agregues.
Cada botón lleva el total del carrito en data-amount. Al tocarlo se abre el pago seguro.
Vuelve ?dexapay=… con el monto pagado, firmado. Verifícalo o revisa el pago en tu portal.
El botón
Cambia dxa_pub_TU_CLAVE_PUBLICA por la de tu portal. La clave pública puede estar a la vista: solo abre pagos desde tus dominios autorizados, con tope por pago y por hora.
Un elemento vacío con data-dexapay recibe el botón con nuestro estilo. Si pones tu propio texto o tu propio botón, se respeta.
<!-- 1. Una vez, en cualquier página de tu web -->
<script src="https://dexapanama.com/dexapay.js"
data-key="dxa_pub_TU_CLAVE_PUBLICA" async></script>
<!-- 2. Donde quieras cobrar: pon el total del carrito -->
<button data-dexapay
data-amount="24.50"
data-reference="PEDIDO-1001"
data-concept="Pedido 1001">
Pagar con Yappy
</button>// Si tu carrito calcula el total con JavaScript:
document.querySelector("#pagar").addEventListener("click", () => {
DexaPay.pagar({
amount: carrito.total, // número, en balboas
reference: carrito.pedidoId, // tu id del pedido
concept: "Pedido " + carrito.pedidoId,
}).catch((e) => alert(e.message));
});Antes de despachar
El total sale de tu web, así que alguien podría cambiarlo en su propio navegador antes de pagar. Por eso, al terminar, tu página recibe ?dexapay=… con el monto, la referencia y el estado, firmados con tu clave de verificación (la ves en tu portal).
amt con el total del pedido y ref con su id.st es PAID.// Node: verifica la confirmación que vuelve en ?dexapay=…
import { createHmac, timingSafeEqual } from "node:crypto";
export function verificarDexaPay(token, claveVerificacion) {
const [payload, firma] = String(token).split(".");
const esperada = createHmac("sha256", claveVerificacion).update(payload).digest("hex");
if (!firma || firma.length !== esperada.length ||
!timingSafeEqual(Buffer.from(firma), Buffer.from(esperada))) return null;
return JSON.parse(Buffer.from(payload, "base64url").toString("utf8"));
// → { sid, oid, ref, amt, st, iat }
}
const pago = verificarDexaPay(req.query.dexapay, process.env.DEXAPAY_VERIFICACION);
if (pago?.st === "PAID" && pago.ref === pedido.id && pago.amt === pedido.total) {
await marcarPedidoPagado(pedido.id);
}<?php // PHP: misma verificación
function verificarDexaPay(string $token, string $clave): ?array {
[$payload, $firma] = array_pad(explode('.', $token, 2), 2, '');
$esperada = hash_hmac('sha256', $payload, $clave);
if (!hash_equals($esperada, $firma)) return null;
$json = base64_decode(strtr($payload, '-_', '+/'));
return json_decode($json, true); // sid, oid, ref, amt, st, iat
}
$pago = verificarDexaPay($_GET['dexapay'] ?? '', getenv('DEXAPAY_VERIFICACION'));
if ($pago && $pago['st'] === 'PAID' && $pago['ref'] === $pedido['id']
&& (float) $pago['amt'] === (float) $pedido['total']) {
marcarPedidoPagado($pedido['id']);
}Seguro por diseño
Tu clave de Yappy vive cifrada en nuestro servidor. Nunca llega a tu web ni al navegador de tu cliente.
El botón abre pagos únicamente en los sitios que autorizas, y el checkout no se puede incrustar en sitios ajenos.
El estado lo confirma Banco General a nuestro servidor con su firma. Una URL de regreso por sí sola no confirma nada.
Antes de activar
DEXA es proveedor técnico del pago. No es banco ni custodia tu dinero, y no vende tus productos.
Avanzado · API con servidor
Con la API, tu servidor fija el total desde tu base de datos y crea la sesión con tu clave secreta (dxa_live_…), que se genera en el portal. También puedes recibir un webhook firmado o mostrar el pago en un iframe autorizado.
// En tu servidor: el total sale de tu base de datos, no del navegador.
const pedido = await buscarPedidoAutorizado(idPedido, usuarioActual);
const r = await fetch("https://dexapanama.com/api/dexapay/v1/sessions", {
method: "POST",
headers: {
Authorization: "Bearer " + process.env.DEXAPAY_API_KEY,
"Content-Type": "application/json",
},
body: JSON.stringify({
amount: pedido.total,
reference: pedido.id,
concept: "Pedido " + pedido.id,
successUrl: "https://tutienda.com/gracias",
}),
});
const sesion = await r.json();
// Manda a tu cliente a sesion.checkoutUrl.
// Al volver, consulta GET /api/dexapay/v1/sessions/{sessionId} con tu clave.¿Usas un agente de IA?
Selecciona tu tecnología y copia un prompt listo para tu agente de programación. Nunca entregues secretos por chat.
Quiero integrar el botón de DexaPay en mi proyecto Next.js / Node.js para cobrar por Yappy.
Actúa como mi agente de programación y guíame paso a paso. No inventes endpoints ni pidas secretos por este chat.
Contexto obligatorio:
- Las credenciales bancarias de Yappy se guardan una sola vez en el Portal DexaPay. Nunca las solicites ni las pongas en mi código.
- Mi servidor crea sesiones con POST https://dexapanama.com/api/dexapay/v1/sessions y la clave DEXAPAY_API_KEY guardada como secreto de servidor.
- El mínimo para una sesión es amount, reference y concept. currency PAB es opcional.
- DexaPay devuelve checkoutUrl. El botón solo abre esa dirección en la misma pestaña.
- El importe debe salir del pedido consultado y validado en el servidor Next.js / Node.js. No confíes en un total enviado por JavaScript, formulario o query string.
- successUrl, cancelUrl, iframe y webhook firmado son opciones avanzadas. La confirmación de pago se consulta desde servidor usando la API autenticada.
- Guarda sessionId, orderId, reference y transactionId. No marques pagado por volver a la tienda.
Tareas:
1. Revisa cómo autentica usuarios y cómo almacena pedidos este proyecto; no inventes funciones para obtener el precio.
2. Crea un endpoint de servidor que reciba el ID del pedido, lo autorice para el usuario actual y lea el total desde la base de datos del proyecto.
3. Desde ese endpoint, crea una sesión DexaPay y devuelve únicamente checkoutUrl al navegador.
4. Añade un botón que redirija a checkoutUrl y muestre errores entendibles.
5. Implementa una ruta de retorno que consulte el estado autenticado de la sesión antes de actualizar el pedido.
6. Guarda la API key solo en el almacén de secretos del servidor. No imprimas claves ni datos personales en logs.
7. Añade pruebas para pedido ajeno, total manipulado, error de DexaPay y pago aún pendiente. No realices cargos reales.
Si no puedes verificar que el pedido pertenece al usuario actual, detente y explícame qué falta antes de crear el pago.Empieza hoy
Con Yappy Comercial activo, haces el alta desde tu portal. La activación la aprobamos nosotros, después de revisar tus datos.
Comenzar alta