Configuración de pagos — y el único paso que pierde dinero en silencio
Las credenciales de pago son solo del lado del servidor: viven en .env en tu máquina y nunca en la
base de datos, nunca en un formulario, nunca en este admin. Eso es deliberado. Lo que sigue es dónde va cada valor
—y el único paso que es fácil de pasar por alto y caro de pasar por alto—.
El paso que cuesta dinero si te lo saltas
La mayoría de los métodos de pago indonesios son asíncronos. Un comprador elige una cuenta virtual, una cartera electrónica, o paga en un punto de venta minorista, y luego cierra la pestaña. Puede terminar de pagar una hora más tarde, desde su app bancaria, en un dispositivo diferente. Nada de eso regresa jamás a tu sitio web.
Así que la compra se completa cuando el proveedor llama a tu servidor —un webhook— y por nada más.
Si esa llamada nunca llega:
- el dinero del comprador te llega,
- su licencia nunca se emite,
- el pedido queda en "pending",
- y nada en ningún sitio dice por qué.
Este no es un caso límite raro. En los métodos indonesios es la ruta normal.
Dónde obtiene su URL cada proveedor
| Proveedor | URL del webhook | Quién la configura |
|---|---|---|
| Xendit | https://yourdomain/webhooks/xendit |
tú, a mano, una vez |
| PayPal | (ninguna) | no hace falta: se completa al regresar |
PayPal se completa cuando el comprador regresa, así que no necesita ningún webhook en absoluto. Xendit es el que te necesita: mira más abajo.
Xendit es el que te necesita. Su callback de "invoice paid" es a nivel de cuenta, no por factura, así que se configura una vez en el propio panel de Xendit.
Xendit, clic a clic
- Inicia sesión en dashboard.xendit.co.
- Settings → Developers → Webhooks.
- Bajo Invoices paid, pega la URL que tu página de admin muestra para Xendit
(
https://yourdomain/webhooks/xendit). - Guarda, y copia el webhook verification token que se muestra en la misma página.
- Pon ese token en el
.envde tu servidor comoXENDIT_CALLBACK_TOKEN, junto aXENDIT_SECRET_KEY. - Reinicia el sitio para que se lean los nuevos valores.
Ambas mitades son necesarias. La URL sin el token significa que las entregas llegan y se rechazan; el token sin la URL significa que no llega nada en absoluto.
Demostrar que realmente funciona
No confíes en el "ya lo pegué". Abre Admin → Settings → Payment webhooks. Informa de lo que ha llegado genuinamente a tu servidor:
| Qué dice | Qué significa | Qué hacer |
|---|---|---|
| Never received | Nunca ha llegado nada de este proveedor | La URL falta o es incorrecta en el panel del proveedor |
| Not matching | Las entregas llegan pero no nombran ningún pedido tuyo | La URL apunta hacia ti desde una cuenta diferente del proveedor a la que usa la tienda |
| Working | Al menos una entrega coincidió con un pedido real | Nada: está conectado |
Los contadores solo se mueven para las llamadas que llevan las propias credenciales del proveedor, así que una sonda aleatoria desde internet nunca puede hacer que una pasarela sin configurar parezca saludable.
Pruébalo de principio a fin antes de aceptar dinero real. El panel de Xendit tiene un botón "test webhook" en la
misma página; úsalo, y luego recarga la ficha de admin. Si sigue diciendo Never received, la URL es incorrecta:
revisa si hay un error tipográfico, un https:// faltante o una barra final.
Las credenciales en sí
Hay dos maneras de configurarlas. Ambas mantienen el secreto fuera de la vista: ninguna muestra jamás un valor guardado.
Desde la página de admin (recomendado)
Admin → Settings → Payment gateway credentials. Introduce el PayPal Client ID + Secret (y el
interruptor sandbox/live) y la Xendit Secret Key + Callback token. Se guardan cifrados en el
servidor; los campos son de solo escritura, así que una vez guardados nunca se vuelven a mostrar: la página solo indica
Configured / Not set. Deja un campo en blanco para dejarlo sin cambios; usa Remove stored credentials para
borrar uno.
Configuración de una sola vez: genera la clave que los cifra, mantenida separada de la clave de la app para que un
volcado de la base de datos y una fuga del .env sean cada uno inútiles por su cuenta:
php artisan store:secrets-key # writes STORE_SECRETS_KEY to .env — then BACK IT UP off the server
php artisan config:clear
Perder STORE_SECRETS_KEY hace que las credenciales guardadas queden ilegibles (bastaría con volver a introducirlas).
O desde .env (alternativa)
Si lo prefieres, configúralas en .env en el servidor y luego reinicia. Los valores de la página de admin tienen prioridad
cuando ambos están presentes.
# Xendit
XENDIT_SECRET_KEY=...
XENDIT_CALLBACK_TOKEN=... # from Settings → Developers → Webhooks
# PayPal
PAYPAL_CLIENT_ID=...
PAYPAL_SECRET=...
PAYPAL_ENV=sandbox # or: live
Una pasarela sin credenciales simplemente queda desactivada: no hay nada más que habilitar.
Si tu servidor está detrás de un proxy o firewall
La ruta del webhook es una URL pública, de servidor a servidor. No tiene inicio de sesión, por necesidad: el proveedor no puede iniciar sesión como tú. En su lugar está protegida por la propia firma o token del proveedor, una relectura autoritativa del estado del pago directamente desde el proveedor, y un límite de tasa.
Eso significa que POST /webhooks/* debe ser alcanzable desde la internet pública. Si lo bloqueas, o pones el
sitio entero detrás de una lista blanca de IPs, los pagos asíncronos dejan de cumplirse, con exactamente el mismo
síntoma silencioso que no haber configurado nunca la URL.