Convoca Gateway
Guía para administradores: pasarela de pagos con Redsys (tarjeta, Bizum y transferencia).
Manual para la junta directiva (sin conocimientos técnicos)¶
Esta página es la referencia técnica del plugin. Para el día a día hay un manual en tres partes, en castellano y con capturas:
1. Introducción¶
Convoca Gateway procesa pagos a través de Redsys (Sermepa), el TPV virtual más usado en España. Permite:
- Cobrar cuotas de socio, donaciones e inscripciones de pago.
- Generar enlaces de pago únicos para compartir por email o WhatsApp.
- Recibir la confirmación del TPV de forma asíncrona (notificación servidor a servidor) y síncrona (retorno del navegador).
- Emitir pagos desde el propio sitio con un formulario público.
Versión: 2.12.1 · Requiere: WordPress 6.4+, PHP 8.1+ y convoca-core activo. El plugin se aborta al activarse si no detecta Convoca\Core\Utils.
El plugin no almacena datos bancarios del pagador: la tarjeta se introduce siempre en la página segura de Redsys.
2. Requisitos¶
| Requisito | Valor |
|---|---|
| WordPress | 6.4 o superior (testado hasta 7.1) |
| PHP | 8.1 o superior |
| Dependencia | Plugin convoca-core activo |
| Extensión PHP | OpenSSL (necesaria para la firma SHA-256) |
| Cuenta Redsys | TPV virtual con FUC, terminal y clave secreta |
3. Instalación¶
- Asegúrate de que Convoca Core está activo.
- Sube la carpeta
convoca-gatewaya/wp-content/plugins/. - Activa el plugin desde Plugins.
- Configura Redsys en Pagos → Configuración.
4. Configuración de Redsys¶
Ve a Pagos → Configuración (pestaña General).

| Campo | Descripción |
|---|---|
| FUC (Código comercio) | Número de comercio Redsys (9 dígitos) |
| FUC Bizum | Código de comercio para Bizum. Si se rellena, habilita el pago por Bizum |
| Terminal | Número de terminal (por defecto 001, 1–3 dígitos) |
| Clave secreta (SHA-256) | Clave de firma proporcionada por el banco (mínimo 16 caracteres) |
| Entorno | Test (sandbox) o Producción |
Además hay secciones para transferencia bancaria (IBAN, titular, instrucciones), páginas de pago y notificaciones por email.
4.1 Clave secreta cifrada¶
La clave secreta se guarda cifrada con AES-256-CBC en la base de datos (prefijo enc:). Si cambias las sales de WordPress (AUTH_SALT), la clave dejará de descifrarse: el plugin muestra un aviso en el admin y bloquea los pagos hasta que vuelvas a introducirla.
4.2 Credenciales por constante (opcional)¶
Puedes definir las credenciales en wp-config.php en lugar de guardarlas en la base de datos. Si una constante está definida, el campo correspondiente aparece deshabilitado:
define( 'CONVOCA_GATEWAY_SECRET_KEY', '...' );
define( 'CONVOCA_GATEWAY_MERCHANT_CODE', '...' );
define( 'CONVOCA_GATEWAY_BIZUM_MERCHANT_CODE', '...' );
4.3 URL de notificación en Redsys¶
Configura en el panel de tu comercio Redsys la URL de notificación:
El endpoint real registrado por el plugin es
POST /wp-json/convoca-gateway/v1/notify(espacio de nombresconvoca-gateway/v1, ruta/notify). No usesconvoca-gateway/v1/notificacionni otras variantes.
4.4 Datos fiscales de la entidad¶
En Pagos → Configuración → General, al final, hay tres campos cuyo único destino es la cabecera del recibo:
| Campo | Descripción |
|---|---|
| Nombre de la entidad | Razón social que figura como emisora. Si se deja vacío se usa el nombre del sitio |
| CIF / NIF | Ej. G-12345678 |
| Domicilio fiscal | Dirección social de la entidad |
Rellénalos antes de emitir el primer recibo
Sin estos datos el recibo sale sin emisor: el pagador ve el importe y el concepto, pero no a quién le ha pagado. Y en los donativos el documento pierde parte de su valor como justificante.
5. Páginas de pago y shortcodes¶
El plugin expone tres shortcodes:
| Shortcode | Función |
|---|---|
[convoca_pago] |
Página de pago: formulario manual + selección de método + redirección a Redsys |
[convoca_pago_ok] |
Página de pago correcto (procesa el retorno síncrono) |
[convoca_pago_ko] |
Página de pago fallido/cancelado |
Créalas como páginas normales e indica su ID en Pagos → Configuración → Páginas de pago (payment_page_id, ok_page_id, ko_page_id).
- Si no configuras ninguna página, el plugin usa los fallbacks
/pago/(pago),/pago-completado/y/pago-error/(retorno). - El diagnóstico (pestaña Estado) ofrece un botón Reparar que crea automáticamente las páginas
pago-completadoypago-errorcon el shortcode correcto.
5.1 Formulario manual¶
Cuando se visita [convoca_pago] sin parámetros, se muestra el formulario "Emitir Pago Nuevo", también en dos pantallas: primero el método de pago (las mismas tarjetas grandes que en el enlace de donativo) y después el importe, el concepto y el email. Al enviarlo se genera un enlace de pago con el método ya elegido y sin caducidad, y se redirige directamente al pago por ese método, sin volver a preguntarlo.
El selector de método es un componente único (render_method_picker() en includes/Payment_Handler.php) que comparten el enlace de pago, el formulario manual y el enlace de donativo, con su CSS en methods_css(): un solo sitio define qué métodos hay (enabled_methods()) y cómo se ven.
6. Generador de enlaces de pago¶
En Pagos → Generar Enlace puedes crear un enlace de pago para enviarlo a quien quieras.
| Campo | Descripción |
|---|---|
| Cantidad (€) | Importe (mínimo 0,50 €). Déjala vacía para crear un enlace de donativo de importe libre (ver 6.1) |
| Concepto | Descripción del pago (máx. 125 caracteres) |
| Método de pago | Cualquiera, Tarjeta, Bizum o Transferencia (solo si hay IBAN configurado) |
| Email destinatario | Pre-rellena el email en el formulario de pago |
| Parámetros personalizados | Clave=Valor por línea; se muestran como datos informativos |
| Fecha de caducidad | Fecha de vencimiento, o casilla "no caduca nunca" |
La caducidad por defecto es 7 días. El enlace generado usa un token HMAC persistente (convoca_gateway_persistent_salt), de modo que no se rompe si cambian las sales de WordPress.
El listado de enlaces generados está en Pagos → Enlaces de Pago (Pedido, Concepto, Importe, Método,
Origen, Email destinatario, Activo, Caducidad y Generado). La columna Activo distingue Activo,
Caducado y cuántos cobros ha emitido el enlace: un enlace no se gasta, así que no tiene «estado
de pago» propio.
6.3 Enlaces de cuota e inscripción: se cierran al cobrarse¶
Los enlaces que emiten Convoca Members y Convoca Enroll —el de la cuota de un socio o el de una inscripción— existen para cobrar una sola cosa. Así que, en cuanto su pago se confirma correctamente, el enlace queda cerrado: deja de admitir pagos y tampoco se puede generar otro nuevo para el mismo pago. Quien lo abra después ve un aviso de que ese enlace ya se ha cobrado, con la fecha.
Si el intento es erróneo —el banco rechaza o el pago se queda a medias—, el enlace no se cierra: sigue vivo para volver a intentarlo.
Dos matices que conviene tener claros:
- El cierre no es una caducidad. Un enlace caduca por su fecha (7 días por defecto, o «no caduca nunca» si se marca así); el cierre por cobro es un estado distinto y solo lo aplican los enlaces de cuota e inscripción.
- Los enlaces de donativo y los generados a mano en Pagos → Generar Enlace no se cierran al usarse: siguen vivos y solo caducan si tienen fecha, como hasta ahora.
6.2 Editar o eliminar un enlace¶
Cada fila del listado tiene Editar y Eliminar (también se puede seleccionar varios y usar la acción en bloque Eliminar).
Editar lleva a una pantalla donde se cambian el concepto, el importe, el método, la caducidad y el email de notificación:
- Dejar el importe vacío convierte el enlace en enlace de donativo (importe libre); poner un importe lo devuelve a enlace normal.
- La dirección del enlace no cambia: el token (
_convoca_link_key) no se toca, así que lo que ya esté publicado sigue funcionando.
Eliminar pide confirmación en una pantalla que lista lo que se va a borrar. El borrado es definitivo y queda anotado en el diario del plugin. Los pagos hechos desde ese enlace no se borran: son registros independientes y la pantalla lo avisa.
6.1 Enlaces de donativo (importe libre)¶
Si al generar el enlace se deja la Cantidad vacía, se crea un enlace de donativo: un enlace reutilizable —no lo consume un pago y no caduca— pensado para publicarse y que cualquiera pueda aportar. El concepto por defecto es «Donativo».
Quien quiera aportar lo hace en dos pantallas:
- Primero el método de pago, con tres tarjetas grandes: tarjeta y Bizum en paralelo y transferencia debajo, a lo ancho. Solo aparecen los métodos que estén configurados.
- Después el importe y el email (opcional). Arriba se recuerda el método elegido, con un enlace «Cambiar método» para volver sin perder lo tecleado.
| Campo | Detalle |
|---|---|
| Método | Tarjeta, Bizum o transferencia, según lo que esté configurado |
| Importe (€) | Lo decide quien dona (mínimo 0,50 €) |
| Email para el recibo | Opcional: si lo indica, recibe el recibo de su aportación |
Cada aportación crea su propio registro de pago, con su orden de Redsys, su estado y su recibo
propios, marcado como donación y enlazado al enlace del que nace (_convoca_origin = donativo,
_convoca_origin_id = ID del enlace). Así el enlace sirve para muchas aportaciones y la contabilidad
y los recibos quedan por donativo, no por enlace.
Del enlace de donativo se guarda la marca _convoca_open_amount y en Pagos → Enlaces de Pago su
importe aparece como Importe libre.
Nota de desarrollo: el HTML va sin saltos entre etiquetas¶
Los bloques de pago se generan con las etiquetas pegadas (compact_html()): WordPress pasa el contenido de la página por wpautop y un salto de línea entre dos etiquetas se convierte en un <br>. En una rejilla CSS ese <br> es un hijo de más y desmonta la maquetación — las tarjetas salían apiladas en páginas con el editor clásico, mientras que en las de bloques se veían bien. Cualquier bloque nuevo que use rejilla debe pasar por el mismo filtro.
Caducidad y regeneración de enlaces¶
La gestión de la caducidad vive en el include Link_Expiry.php. Los enlaces de pago enviados por email tienen una caducidad por defecto de 7 días (opción convoca_gateway_link_expiry_days).
| Ajuste | Clave | Descripción |
|---|---|---|
| Días de caducidad | convoca_gateway_link_expiry_days |
Caducidad por defecto de los enlaces (7 días) |
| Horas de preaviso | convoca_gateway_link_expiry_notice_hours |
Antelación del aviso previo a la caducidad (24 h) |
Un cron diario (convoca_gateway_expiry_notice) envía un aviso 24 horas antes de la caducidad. Cuando un enlace caduca, la página de pago muestra un botón «Solicitar nuevo enlace» que regenera la meta _convoca_expires_at manteniendo el mismo pago (order id) y reenvía el email (Link_Expiry::regenerate_link).
6.3 Uso del enlace: emite un cobro, no se gasta¶
Un enlace es una plantilla: no se convierte en el cobro al usarse. Cada vez que alguien lo usa,
se crea un registro de pago propio con el origen Cobro con enlace, que aparece en
Pagos → Todos los Pagos con su pedido, su importe y su método.
- Un enlace puede emitir uno o más cobros, mientras no haya caducado ni se haya eliminado.
- El enlace conserva su estado, su caducidad y su dirección: se puede seguir compartiendo. La columna de estado del listado muestra cuántos cobros ha emitido.
- El cobro se emite al enviar el formulario del método de pago, no al abrir la página: una visita (o un rastreador) no deja registros sueltos.
- Al pagar, quien aporta va a la pantalla del cobro emitido, no a la del enlace: así la referencia de la transferencia y el pago con tarjeta corresponden al cobro correcto.
- Borrar el enlace no borra los cobros que ha emitido (la pantalla de confirmación lo indica).
7. Panel de pagos¶
En Pagos → Todos los Pagos se listan los cobros.

- Columnas: Pedido, Importe, Método, Estado, Origen, Fecha.
- Filtros por estado, método y origen (actividades, socio/a, donaciones), y buscador por ID de pedido.
- Ordenación por fecha e importe.
- Cada fila tiene la acción Eliminar, y la acción en bloque permite borrar varios a la vez.
Un pago es un pago y un enlace es un enlace
Los enlaces de pago (plantillas que se generan para cobrar) no aparecen en este listado: su sitio es Pagos → Enlaces de Pago. Así no se confunden con un pago pendiente al seleccionar filas para borrar.
Los cobros hechos desde un enlace sí se listan aquí, porque son cobros: cada uso de un
enlace emite su propio registro de pago (Cobro con enlace), las aportaciones de un enlace
de donativo emiten el suyo (Donación) y el formulario de pago el suyo (Formulario web).
- Origen:
Inscripción,Socio/a,Donación,Formulario web,Cobro con enlace.
7.1 Eliminar un pago¶
Se puede eliminar cualquier pago, sea cual sea su estado. Al pulsar Eliminar (o al aplicar la acción en bloque) no se borra nada todavía: aparece una pantalla de confirmación con la lista de registros y, por cada uno, lo que conviene saber antes de borrarlo:
| Aviso | Cuándo aparece |
|---|---|
| Está marcado como PAGADO: cuenta en los informes de ingresos | El pago está en estado paid |
| Tiene recibo emitido (D-2026-001) | Se le generó justificante, con su número |
| Cobrado el … | Tiene fecha de cobro |
| Las N aportaciones hechas con estos enlaces se conservan | Al borrar enlaces de donativo con aportaciones |
Solo el botón «Sí, eliminar» (formulario firmado con nonce) ejecuta el borrado, que es definitivo —no va a la papelera— y deja rastro en el diario (Gateway/Delete). Quién puede borrar: quien tenga la capacidad convoca_manage_payments o sea administrador del sitio.
7.2 Estados del pago¶
| Estado | Significado |
|---|---|
pending |
Pendiente de confirmación |
paid |
Pagado (autorizado por Redsys) |
failed |
Fallido |
refunded |
Reembolsado (marcado manualmente) |
7.3 Detalle del pago¶
Al pulsar sobre un pedido se abre la vista de detalle con:
- Datos completos: importe, método, origen, descripción, código de autorización y respuesta Redsys; en caso de fallo, el código de error legible (
Redsys_Client::get_response_message). - Justificante de pago (si el pagador lo subió por transferencia).
- Registro de eventos (logs) asociados al pago.
- Acciones: Reenviar email de confirmación (solo pagado), Confirmar Pago Manual (para transferencias recibidas), Marcar como Reembolsado.
8. Métodos de pago¶
| Método | Disponible si | Comportamiento |
|---|---|---|
| Tarjeta | Siempre (si hay FUC y clave) | Redirección al TPV de Redsys |
| Bizum | FUC Bizum configurado |
Pago instantáneo con móvil |
| Transferencia | IBAN configurado |
Muestra IBAN y concepto; permite subir justificante |
La página pública muestra la selección de método (💳 Tarjeta, 📱 Bizum, 🍀 Transferencia) con el método sugerido destacado.
8.1 Transferencia bancaria¶
Cuando el pagador elige transferencia, ve el IBAN, el titular y el concepto (ID de pedido) que debe indicar. Puede adjuntar un justificante (PDF, JPG o PNG, máximo 5 MB). El pago queda pendiente hasta que un administrador lo confirme con Confirmar Pago Manual.
9. Flujo de pago y confirmación¶
El pago se confirma por dos vías independientes e idempotentes:
9.1 Notificación asíncrona (servidor a servidor)¶
Tras cada transacción, Redsys llama al endpoint REST POST /wp-json/convoca-gateway/v1/notify. El plugin:
- Valida la IP de origen (rangos de Redsys
195.76.9.0/24y direcciones conocidas; en entornos no productivos también acepta127.0.0.1/::1). Rechaza cualquier otra IP. - Verifica la firma HMAC-SHA256 de
Ds_Signature. Si es inválida, registra el intento en el log con elDs_Orderdecodificado para trazabilidad (v2.6.6). - Localiza y bloquea el pago por
order_id(FOR UPDATE) para evitar condiciones de carrera. - Si ya estaba pagado, ignora la notificación duplicada.
- Valida la integridad financiera: el importe (
Ds_Amount), la moneda (978) y el código de comercio deben coincidir con lo esperado para ese pago. - Marca
paidsolo siDs_Response === '0000'(autorización de compra); en caso contrario,failed. - Guarda la respuesta y el código de autorización de Redsys.
- Dispara el hook
convoca_gateway_payment_completed(oconvoca_gateway_payment_failed). - Responde con el texto plano
OK, como espera Redsys.
Un cortafuegos por delante puede cortar el aviso
El aviso lo manda un cliente Java (Java/1.8.0_441), sin cabeceras de navegador. Los cortafuegos que
aplican Browser Integrity Check —Cloudflare, entre otros— lo bloquean antes de que llegue a
WordPress: desde fuera parece que Redsys no avisa y el pago se queda pendiente para siempre.
Comprobación rápida: pide a alguien de fuera que haga POST a la URL de notificación. Si responde
403 y en los registros de Redsys figura como avisada, el aviso lo está cortando el cortafuegos:
deja esa ruta exenta de retos y comprobaciones, sin abrir nada más del sitio.
9.2 Retorno síncrono (navegador) — E2E-5¶
El aviso del servidor es la vía principal y la que hay que vigilar: es la que cobra el pago aunque el
pagador cierre el navegador antes de volver al sitio. La página [convoca_pago_ok] procesa además el
retorno del navegador en el momento, como red de seguridad:
- Si el pago aún no está confirmado y la URL trae
Ds_MerchantParameters, se llama aprocess_return(). process_return()verifica la firma HMAC (sin restricción de IP, porque la IP del navegador es arbitraria), localiza el pago, valida importe y comercio, aplica el estado y dispara los mismos hooks.- Es idempotente: si el pago ya estaba
paid, no vuelve a procesarse (evita duplicar hooks y correos).
Esto garantiza que la confirmación no dependa exclusivamente de que la notificación asíncrona llegue.
Retorno TPV → /pago-ok/?Ds_MerchantParameters=…&Ds_Signature=… → [convoca_pago_ok] procesa en el momento
9.3 Verificación de firma¶
- Versión de firma: HMAC_SHA256_V1 (por defecto) y HMAC_SHA256_V2 soportadas. El algoritmo no lo decide el input del atacante: solo se acepta la versión configurada por el comercio (
signature_version). Ds_MerchantParameterses Base64 (con soporte base64url) de un JSON con los camposDs_Order,Ds_Amount,Ds_Currency,Ds_MerchantCode, etc.
10. Webhook REST (referencia técnica)¶
| Propiedad | Valor |
|---|---|
| Método | POST |
| Endpoint | /wp-json/convoca-gateway/v1/notify |
| Autenticación | Ninguna (exige Redsys); la seguridad se valida por IP + firma HMAC |
| Rate limit | 30 notificaciones/minuto por IP |
| Límite de payload | 16 KB |
| Respuesta correcta | OK (200) |
11. Hooks y funciones públicas¶
11.1 Acciones (events)¶
| Hook | Argumentos | Cuándo se dispara |
|---|---|---|
convoca_gateway_payment_completed |
$pago_id, $origin, $origin_id, $meta |
Pago confirmado (asíncrono o síncrono) |
convoca_gateway_payment_failed |
$pago_id, $response_code |
Pago denegado |
convoca_gateway_payment_refunded |
$pago_id |
Marcar como reembolsado manualmente |
convoca_gateway_resend_email |
$pago_id |
Reenviar email de confirmación |
También se disparan los hooks heredados
convoca_payment_completedyconvoca_payment_failed(víaConvoca\Core\Utils::do_action). Enroll confirma inscripciones y Members activa membresías escuchando estos hooks.
11.2 Filtros¶
| Filtro | Descripción |
|---|---|
convoca_gateway_bank_entity |
Nombre de la entidad bancaria mostrado en la nota de seguridad |
convoca_gateway_redsys_allowed_ips |
Ampliar la lista de IPs permitidas de Redsys |
convoca_gateway_receipt_payer_name |
Nombre del pagador impreso en el recibo ($pago_id); útil cuando el pago lo hizo una entidad o una persona distinta del titular |
11.3 Funciones públicas¶
convoca_gateway_create_payment( array $args ): array|\WP_Error— crea un pago y devuelve['pago_id' => int, 'payment_url' => string]. Argumentos:amount_cents(en céntimos),method(tarjeta/bizum),origin(enroll/members),origin_id,product_desc(máx. 125),tokenize(para pago recurrente).convoca_get_gateway_settings(): array— devuelve los ajustes guardados.
11.4 Pagos de cuota e inscripción (otros plugins)¶
convoca_gateway_create_payment() (y Payment_Handler::create_payment()) es la puerta que usan
convoca-members y convoca-enroll: cuando alguien se da de alta pagando la cuota o se inscribe a
una actividad de pago, el plugin crea el registro de pago y recibe su URL de pago.
| Qué | Cómo |
|---|---|
| Importe y concepto | Los pone el plugin: cuota (CUOTA <plan>), renovación (RENOVACIÓN …), inscripción (Aportación para <actividad>) |
| Origen | members o enroll → en el listado de pagos se leen como Socio/a o Inscripción, con filtro |
| Correo de contacto | El plugin entrega el correo del alta o la inscripción (payer_email): sirve para el recibo y para el aviso de caducidad |
| URL de pago | Con token y caducidad configurable (ajuste Caducidad por defecto, 7 días) — el método se elige en la misma pantalla de pago |
| Un solo uso | Al completarse el pago, la URL deja de servir: la página avisa de que ya está cobrado |
Estos pagos no son plantillas: viven en Pagos → Todos los Pagos (no en Enlaces de Pago) y se pueden eliminar como cualquier otro, con su pantalla de confirmación.
12. Correos automáticos¶
En Pagos → Configuración → pestaña Correos:
- Habilitar confirmación de pago (checkbox) y nombre del remitente.
- Plantillas editables de asunto y cuerpo para éxito y fallo, con variables:
| Variable | Valor |
|---|---|
{importe} |
Importe formateado |
{metodo} |
Método de pago |
{fecha} |
Fecha del pago |
{producto} |
Concepto/origen |
{enlace_pago} |
URL del enlace de pago |
{enlace_inscripcion} |
URL de la inscripción (si aplica) |
{recibo_url} |
URL del recibo o justificante del pago |
El correo se envía al email del pagador (_convoca_payer_email), solo si la confirmación está habilitada.
En los donativos, el email que deja quien aporta se guarda como email del pagador y el recibo se envía
siempre que lo haya, sin depender de ese checkbox (marca _convoca_receipt_always): el donante espera
su justificante. El campo «Email de notificación» del formulario de pago viaja con el método elegido, de
modo que también en los enlaces normales se puede enviar el recibo si la confirmación está habilitada.
Recibo automático de cuotas e inscripciones (PRO)¶
Al cobrarse una cuota o una inscripción se envía el recibo a quien paga, al correo que dejó al apuntarse. Tiene su propio interruptor en Pagos → Configuración → Correos (activado por defecto) y es una funcionalidad PRO: sin licencia, estos pagos siguen rigiéndose por el aviso general de confirmaciones.
Los donativos mantienen su comportamiento de siempre: el recibo sale al donante siempre que haya dejado correo, sin depender de ningún interruptor.
Recordatorio de pago sin terminar¶
Si el pagador deja su correo y el pago se queda a medias, a la media hora se le manda un recordatorio con un botón para terminarlo. La comprobación corre cada cuarto de hora, así que el aviso sale entre los 30 y los 45 minutos siguientes.
| Situación | Qué hace |
|---|---|
| El pago dejó de estar pendiente | No envía nada |
| No hay correo del pagador | No envía nada: no hay a quién |
| El enlace ya caducó | No envía nada: el botón del mensaje ya no serviría |
| Ya se avisó una vez | No repite: el aviso sale una sola vez por pago |
El texto usa la plantilla de recordatorio con sus valores por defecto, y en ella funciona la variable
{enlace_pago} (que respeta la caducidad del enlace). Hoy se cambia desde los ajustes
(email_pending_subject y email_pending_body), no desde la interfaz: los campos de la pestaña
Correos cubren las plantillas de éxito y de fallo.
Error de TPV y reintento¶
Cuando Redsys rechaza la operación, el pagador recibe un email con un motivo legible («Tu banco rechazó la operación» o el texto del mapa de códigos de Redsys, junto al código numérico). El estado del pago queda failed.
Desde la página de pago hay un botón «Reintentar pago» que genera un nuevo enlace para el mismo pago. El detalle del pago en admin muestra el código de error (vía Redsys_Client::get_response_message).
13. Dashboard¶
El widget "Resumen de Pagos Convoca" aparece en el Escritorio de WordPress (para usuarios con convoca_view_payments):
- Total cobrado este mes, pagos hoy y pagos este mes.
- Uso de métodos (tarjeta vs Bizum).
- Evolución de los últimos 7 días.
Pagos sin terminar¶
El Escritorio incluye además el widget «Convoca · Pagos sin terminar» (solo para administradores), que responde a una pregunta concreta: ¿alguien empezó a pagar y no terminó?
Un pago cuenta como sin terminar cuando lleva más de 30 minutos empezado y el banco no ha respondido nada —ni bien ni mal—. Muestra hasta ocho, con el concepto, el importe, el método, la fecha y si hay correo dejado, y cada uno enlaza a su detalle.
Un enlace caducado no se esconde
Justo entonces es cuando hay que mirarlo: un pago con el enlace caducado y sin respuesta del banco ya no se va a cobrar solo. Para eso está el aviso, no para ocultarlo.
Si el widget aparece vacío, no significa que no haya habido pagos: significa que todos terminaron, que es lo normal.
La misma regla, desde la consola
\Convoca\Gateway\Pending_Payments::stuck_ids() devuelve los IDs de esos pagos. Es la única
definición de «pago a medias»: la comparten el widget y el recordatorio por correo, para que nunca digan
cosas distintas.
14. Diagnóstico y reparación¶
La pestaña Estado (Pagos → Configuración) ejecuta 8 comprobaciones, con botón de reparación automática:
| Chequeo | Reparación disponible |
|---|---|
| Modo de entorno / clave | — |
| Código de comercio (FUC) | — |
| Terminal | Fijar 001 |
| Páginas de retorno (OK/KO) | Crear pago-completado y pago-error |
| Métodos offline (transferencia) | — |
| PHP | — |
| OpenSSL | — |
| Base de datos (tabla de logs) | — |
El resultado se cachea 1 hora; el botón Forzar comprobación lo recalcula.
15. Seguridad¶
- Firma HMAC-SHA256 obligatoria en notificaciones y retornos.
- Validación de IP en el webhook (rangos Redsys + lista filtrable).
- Rate limit (30/min/IP) y límite de payload (16 KB) anti-DoS.
- Integridad financiera: importe, moneda y comercio deben coincidir con el pago esperado.
is_approvedestricto: soloDs_Response === '0000'marca pagado (no todo el rango 0–99).- Clave secreta cifrada en reposo (AES-256-CBC).
- Bloqueo de fila (
FOR UPDATE) contra condiciones de carrera y notificaciones duplicadas. - Protección anti inyección CSV (prefija
=,+,-,@). - Justificantes: validación de tipo MIME real y renombrado con UUID contra path traversal; el directorio de subidas se protege contra ejecución de scripts.
16. Exportación CSV¶
En Pagos → Todos los Pagos → Exportar CSV:
- Columnas:
ID, ID Pedido, Importe (€), Método, Estado, Origen, Email Usuario, Fecha Creación, Fecha Pago. - Separador
;, con BOM UTF-8 para compatibilidad con Excel. - Máximo 5.000 registros por exportación.
- Requiere la capacidad
convoca_view_payments.
17. Gutenberg¶
Además de los shortcodes, el plugin registra tres bloques (categoría convoca-gateway):
| Bloque | Uso |
|---|---|
convoca-gateway/pagina-pago |
Página de pago (selección de método + TPV) |
convoca-gateway/pago-ok |
Confirmación de pago correcto |
convoca-gateway/pago-ko |
Pago fallido/cancelado |
18. Problemas comunes¶
| Problema | Causa probable | Solución |
|---|---|---|
| "Firma no válida" en el log | Clave secreta incorrecta o cambiada | Revisa la clave SHA-256; Redsys distingue mayúsculas |
| Pago en TPV pero sigue "Pendiente" | La notificación asíncrona no llegó (frecuente en test) | El retorno síncrono en pago-ok lo confirma; si no, usa Confirmar Pago Manual |
| Enlace de pago no funciona | Ya pagado o caducado | Comprueba el estado en Enlaces de Pago |
| Modo pruebas | Entorno Test |
Usa la tarjeta de prueba 4548 8120 4940 0004 (CVV 123, caducidad 12/34) |
| Aviso de clave no descifrable | Cambiaste las sales de WordPress | Vuelve a introducir la clave secreta en Configuración |
| 403 al ver Pagos | Falta la capacidad convoca_view_payments |
Asigna la capacidad al rol correspondiente (la define convoca-core) |
19. Recibos y justificantes de pago¶
Cada pago completado genera automáticamente su recibo: Receipt_Generator.php le asigna número y
Receipt_View.php lo sirve. Va enlazado desde el email de confirmación y su número figura en el listado de
pagos.
El recibo es un documento propio, no una página dentro del tema: se sirve aparte, sin cabecera, menú ni pie del sitio, con sus propios márgenes de impresión, para que se imprima o se guarde en PDF tal cual. Incluye los datos de la entidad, los del pagador, el método de pago, la referencia, la fecha con la marca «Pagado», el importe destacado y, en los donativos, el texto de la Ley 49/2002.
| Característica | Detalle |
|---|---|
| Numeración | Anual automática (_convoca_receipt_number): AÑO-NNN (2026-037), con un contador por año |
| Acceso | /pago/?convoca_gateway_pago=ID&convoca_gateway_recibo=1&convoca_gateway_receipt_key=… |
| Clave | Token de capacidad: cada pago tiene la suya y solo abre ese recibo |
| Impresión | Imprimir → Guardar como PDF desde el navegador |
La clave no se comparte de más
Da acceso a ese recibo y a ninguno más, pero da acceso: trátala como el documento mismo.
Justificante de donación¶
Los pagos marcados como donación (meta _convoca_es_donacion) generan en su lugar un justificante de donación
con texto fiscal (Ley 49/2002) y numeración de serie separada (D-AÑO-NNN). Se marcan solos cuando nacen de un
enlace de donativo, y también se pueden marcar a mano con el checkbox del detalle del pago en admin.
Los datos de la asociación que aparecen en recibos y justificantes se configuran en Ajustes (ver §4.4 Datos fiscales de la entidad):
| Ajuste | Clave |
|---|---|
| Nombre de la asociación | org_name |
| CIF | org_cif |
| Dirección | org_address |
20. Calidad y pruebas¶
- PHPStan nivel 5 sin baseline (deuda estática a cero).
- PHPCS limpio (WordPress Coding Standards).
- Plugin Check (PCP) 0 errores en la preparación para WordPress.org.
- Cobertura con PHPUnit (tests de firma, notificación,
verify_notificationcon versión fija, base64url, payload vacío, caducidad, recordatorio, pagos sin terminar, recibo, etc.). - La notificación confirmada se comprueba de punta a punta, incluido el protocolo de la transacción:
que la última sentencia sea
COMMIT. Sin eso, el cambio se pierde al cerrar la conexión y el fallo es invisible (el plugin respondeOKy el pago sigue pendiente).