Qué dice GoCardless
| Reason | Tipo | Texto de GoCardless |
|---|---|---|
retry_failed | invalid_state | Payment could not be retried. |
La documentación del reintento (POST /payments/{id}/actions/retry) da las reglas: el pago se reintenta si su mandato está activo, la API devuelve retry_failed si el pago no ha fallado y «Payments can be retried up to 3 times.». Como con todos los errores invalid_state, GoCardless pide avisar a quien usa el sistema y no dejar que reintente. El conector anota en su código que un cuarto reintento recibió también retry_failed en el sandbox de GoCardless.

Por qué sale
Según la documentación, retry_failed llega cuando el pago no ha fallado, y el conector lo vio también al pedir un cuarto reintento. Con un mandato que ya no está activo, la documentación no dice qué error llega: el conector espera retry_failed o mandate_is_inactive y trata los dos igual.
Lo de un pago que no está fallido abarca más de lo que parece. Un cobro pendiente o confirmado no ha fallado, y uno devuelto (charged_back) tampoco: el dinero llegó y el banco del cliente lo retiró después. Según la documentación de GoCardless, cualquiera de ellos recibiría retry_failed.
Con el límite de reintentos, lo que confunde es Success+. Cuando Success+ reintenta un pago, GoCardless manda un evento resubmission_requested, igual que con cualquier otro reintento. El conector suma uno por cada evento de esos, venga de Success+ o de un reintento pedido desde Odoo, y anota en su código que el límite de 3 de GoCardless incluye los de Success+. Como cada cobro que manda el conector pide retry_if_possible, con Success+ activado es fácil que parte de ese cupo ya esté gastado cuando miras la factura.
Lo que ves en Odoo con el conector
La transacción se abre desde la factura, con el botón «Transacción de pago» de arriba; el menú de transacciones solo sale en modo desarrollador, y en Odoo 20 no existe. El botón «Reintentar el cobro» de la transacción solo aparece cuando el conector aceptaría el reintento: lo controla un campo calculado con la misma regla que comprueba el servidor al pulsarlo. Si la regla dice que no, el botón no sale y su motivo no llega a la pantalla. Lo que ves es el estado de la transacción y su grupo GoCardless:
| Situación | Lo que ves en la transacción |
|---|---|
| Success+ lo va a reintentar | Estado «Pendiente», la casilla «Success+ reintentará» marcada y, en «Mensaje», «GoCardless no pudo cobrar este pago (…). Success+ lo reintentará automáticamente; no hay que hacer nada.». Sin botón. |
| Fallido, sin Success+, con menos de 3 reintentos y el mandato activo | Estado «Error» y el botón «Reintentar el cobro». |
| Ya van 3 reintentos | Estado «Error» y «Reintentos de GoCardless» a 3. Sin botón. |
| El mandato está archivado | Estado «Error»; en el contacto, la nota del mandato y la actividad «Mandato de GoCardless perdido». Sin botón. |
| Pendiente o confirmado | Sin botón. |
| Devuelto, por ejemplo con MD06 | Estado «Error», aunque el mandato siga activo. Sin botón: en GoCardless el pago está en charged_back, no en failed. |
Al pulsar el botón, Odoo pide confirmar: «GoCardless intentará cobrar de nuevo este pago, lo que puede tener una comisión. ¿Continuar?». Si GoCardless acepta, la transacción pasa a pendiente con «Reintento solicitado. GoCardless confirmará la nueva fecha de cargo.». Cuando llega el evento resubmission_requested, el conector suma el reintento y escribe la fecha: «GoCardless volverá a cobrar este pago el … (reintento solicitado, reintento 1 de 3).». Al pulsar no suma nada, y así cada reintento cuenta una sola vez.
Lo que llega con los eventos lo escribe el conector sin nadie delante: el mensaje de Success+ de la tabla, la nueva fecha de cargo y, si el mandato murió por un evento, la nota y la actividad del contacto. En una base de datos creada en castellano salen así; en una creada en inglés y pasada después a castellano salen en inglés: «GoCardless could not collect this payment (…). Success+ will retry it automatically; there is nothing to do.», «GoCardless will collect this payment again on … (retry requested, retry 1 of 3).» y «GoCardless mandate lost». Lo que sale de pulsar el botón va en tu idioma.

Si GoCardless contesta retry_failed
Si aun así la API contesta retry_failed o mandate_is_inactive, el conector consulta el mandato antes de enseñar nada:
- Si el mandato está muerto, lo archiva y lo dice en la transacción: «El mandato de GoCardless del cliente está en estado …, así que no se puede cobrar. Pide al cliente un mandato nuevo.».
- Si sigue activo, enseña el error de GoCardless tal cual: «GoCardless rechazó la solicitud.» y debajo el mensaje de la API, con su reason y el
request_id.
Con un cobro devuelto ya no se llega aquí: desde la versión 1.1.4, el conector no ofrece el botón si el pago no está en failed en GoCardless, y un devuelto está en charged_back.
Qué hacer
- Si el botón no sale, mira el estado de la transacción, «Success+ reintentará» y «Reintentos de GoCardless»: una de las situaciones de la tabla lo explica.
- Si van 3 reintentos, habla con el cliente: el conector ya no pide otro.
- Si el mandato está archivado, pide uno nuevo y cobra con él.
- En un cobro devuelto no hay botón: habla antes con el cliente y, si procede, vuelve a cobrar la factura con un cobro nuevo.
¿Cada reintento cuesta dinero?
Puede. El botón lo avisa antes de mandar nada, y el conector no lo ofrece mientras Success+ va a reintentar el cobro, porque un reintento a mano solo añadiría una comisión. Las tarifas concretas dependen de tu contrato con GoCardless.
¿Puedo reintentar un cobro devuelto por el cliente?
Con este botón, no: el conector no lo ofrece en un cobro devuelto, porque GoCardless solo reintenta pagos fallidos y un devuelto no lo es. Una devolución, como un MD06, se resuelve hablando con el cliente y, si procede, con un cobro nuevo.
Con nuestro conector
En Odoo 17, 18, 19 y 20 el conector cuenta los reintentos con los eventos de GoCardless y solo enseña el botón cuando su regla lo permite: no con Success+ en marcha, ni con 3 reintentos, ni con el mandato archivado. Si aun así llega retry_failed, mira el mandato antes de enseñarte el error.
Sigue leyendo
Comprobado en el código del conector (versión 17.0, 18.0, 19.0 y 20.0) y en las fuentes enlazadas
Fuentes
- docs.gocardless.com/docs/api-reference/payment
- docs.gocardless.com/docs/api-reference/responses-and-errors
- Código del módulo: flexigo_payment_gocardless: const.py, línea 119 en 17.0 (d203ee6), 18.0 (e2ab18b), 19.0 (ce7f5a3) y 20.0 (688d86b)
- docs.gocardless.com/docs/optimise/reduced-failed-payments-with-success-plus
- Código del módulo: flexigo_payment_gocardless: models/payment_transaction.py, línea 680 en 17.0 (d203ee6), línea 680 en 18.0 (e2ab18b), línea 679 en 19.0 (ce7f5a3) y línea 703 en 20.0 (688d86b)
- Código del módulo: flexigo_payment_gocardless: models/payment_transaction.py, línea 449 en 17.0 (d203ee6), línea 449 en 18.0 (e2ab18b), línea 448 en 19.0 (ce7f5a3) y línea 463 en 20.0 (688d86b)
- Código del módulo: flexigo_payment_gocardless: const.py, línea 122 en 17.0 (d203ee6), 18.0 (e2ab18b), 19.0 (ce7f5a3) y 20.0 (688d86b)
- Código del módulo: flexigo_payment_gocardless: models/payment_transaction.py, línea 260 en 17.0 (d203ee6), línea 260 en 18.0 (e2ab18b), línea 260 en 19.0 (ce7f5a3) y línea 271 en 20.0 (688d86b)
- Código del módulo: flexigo_payment_gocardless: views/payment_transaction_views.xml, línea 13 en 17.0 (d203ee6), 18.0 (e2ab18b), 19.0 (ce7f5a3) y 20.0 (688d86b)
- Código del módulo: flexigo_payment_gocardless: models/payment_transaction.py, línea 63 en 17.0 (d203ee6), 18.0 (e2ab18b), 19.0 (ce7f5a3) y 20.0 (688d86b)
- Código del módulo: flexigo_payment_gocardless: models/payment_transaction.py, línea 418 en 17.0 (d203ee6), línea 418 en 18.0 (e2ab18b), línea 417 en 19.0 (ce7f5a3) y línea 432 en 20.0 (688d86b)
- Código del módulo: flexigo_payment_gocardless: views/payment_transaction_views.xml, línea 27 en 17.0 (d203ee6), 18.0 (e2ab18b), 19.0 (ce7f5a3) y 20.0 (688d86b)
- Código del módulo: flexigo_payment_gocardless: views/payment_transaction_views.xml, línea 28 en 17.0 (d203ee6), 18.0 (e2ab18b), 19.0 (ce7f5a3) y 20.0 (688d86b)
- github.com/odoo/odoo/blob/20.0/addons/payment/views/payment_transaction_views.xml
- github.com/odoo/odoo/blob/20.0/addons/payment/i18n/es.po
- Código del módulo: flexigo_payment_gocardless: models/payment_transaction.py, línea 729 en 17.0 (d203ee6), línea 729 en 18.0 (e2ab18b), línea 728 en 19.0 (ce7f5a3) y línea 752 en 20.0 (688d86b)
- Código del módulo: flexigo_payment_gocardless: models/payment_transaction.py, línea 713 en 17.0 (d203ee6), línea 713 en 18.0 (e2ab18b), línea 712 en 19.0 (ce7f5a3) y línea 736 en 20.0 (688d86b)
- Código del módulo: flexigo_payment_gocardless: models/payment_transaction.py, línea 430 en 17.0 (d203ee6), línea 430 en 18.0 (e2ab18b), línea 429 en 19.0 (ce7f5a3) y línea 444 en 20.0 (688d86b)
- Código del módulo: flexigo_payment_gocardless: models/payment_transaction.py, línea 437 en 17.0 (d203ee6), línea 437 en 18.0 (e2ab18b), línea 436 en 19.0 (ce7f5a3) y línea 451 en 20.0 (688d86b)
- Código del módulo: flexigo_payment_gocardless: models/payment_transaction.py, línea 442 en 17.0 (d203ee6), línea 442 en 18.0 (e2ab18b), línea 441 en 19.0 (ce7f5a3) y línea 456 en 20.0 (688d86b)
- Código del módulo: flexigo_payment_gocardless: models/payment_transaction.py, línea 435 en 17.0 (d203ee6), línea 435 en 18.0 (e2ab18b), línea 434 en 19.0 (ce7f5a3) y línea 449 en 20.0 (688d86b)
- Código del módulo: flexigo_payment_gocardless: models/payment_token.py, línea 131 en 17.0 (d203ee6), línea 131 en 18.0 (e2ab18b), línea 131 en 19.0 (ce7f5a3) y línea 130 en 20.0 (688d86b)
- Código del módulo: flexigo_payment_gocardless: models/payment_transaction.py, línea 469 en 17.0 (d203ee6), línea 469 en 18.0 (e2ab18b), línea 468 en 19.0 (ce7f5a3) y línea 487 en 20.0 (688d86b)
- Código del módulo: flexigo_payment_gocardless: models/payment_transaction.py, línea 321 en 17.0 (d203ee6), línea 321 en 18.0 (e2ab18b), línea 321 en 19.0 (ce7f5a3) y línea 332 en 20.0 (688d86b)
- Código del módulo: flexigo_payment_gocardless: models/payment_provider.py, línea 397 en 17.0 (d203ee6), 18.0 (e2ab18b), 19.0 (ce7f5a3) y 20.0 (688d86b)
- Código del módulo: flexigo_payment_gocardless: models/payment_provider.py, línea 462 en 17.0 (d203ee6), 18.0 (e2ab18b), 19.0 (ce7f5a3) y 20.0 (688d86b)
- Código del módulo: flexigo_payment_gocardless: models/payment_transaction.py, línea 484 en 17.0 (d203ee6), línea 484 en 18.0 (e2ab18b), línea 483 en 19.0 (ce7f5a3) y línea 502 en 20.0 (688d86b)
- Código del módulo: flexigo_payment_gocardless: models/payment_transaction.py, línea 683 en 17.0 (d203ee6), línea 683 en 18.0 (e2ab18b), línea 682 en 19.0 (ce7f5a3) y línea 706 en 20.0 (688d86b)
- Código del módulo: flexigo_payment_gocardless: i18n/es.po, línea 1092 en 17.0 (d203ee6), línea 1092 en 18.0 (e2ab18b), línea 1092 en 19.0 (ce7f5a3) y línea 1113 en 20.0 (688d86b)
- Código del módulo: flexigo_payment_gocardless: i18n/es.po, línea 618 en 17.0 (d203ee6), línea 618 en 18.0 (e2ab18b), línea 618 en 19.0 (ce7f5a3) y línea 623 en 20.0 (688d86b)
- Código del módulo: flexigo_payment_gocardless: i18n/es.po, línea 1141 en 17.0 (d203ee6), línea 1141 en 18.0 (e2ab18b), línea 1141 en 19.0 (ce7f5a3) y línea 1152 en 20.0 (688d86b)
- Código del módulo: flexigo_payment_gocardless: i18n/es.po, línea 432 en 17.0 (d203ee6), línea 432 en 18.0 (e2ab18b), línea 432 en 19.0 (ce7f5a3) y línea 437 en 20.0 (688d86b)
- Código del módulo: flexigo_payment_gocardless: i18n/es.po, línea 464 en 17.0 (d203ee6), línea 464 en 18.0 (e2ab18b), línea 464 en 19.0 (ce7f5a3) y línea 469 en 20.0 (688d86b)
- Código del módulo: flexigo_payment_gocardless: i18n/es.po, línea 1163 en 17.0 (d203ee6), línea 1163 en 18.0 (e2ab18b), línea 1163 en 19.0 (ce7f5a3) y línea 1174 en 20.0 (688d86b)
- Código del módulo: flexigo_payment_gocardless: i18n/es.po, línea 527 en 17.0 (d203ee6), línea 527 en 18.0 (e2ab18b), línea 527 en 19.0 (ce7f5a3) y línea 532 en 20.0 (688d86b)
- Código del módulo: flexigo_payment_gocardless: i18n/es.po, línea 1098 en 17.0 (d203ee6), línea 1098 en 18.0 (e2ab18b), línea 1098 en 19.0 (ce7f5a3) y línea 1119 en 20.0 (688d86b)
- Código del módulo: flexigo_payment_gocardless: i18n/es.po, línea 609 en 17.0 (d203ee6), línea 609 en 18.0 (e2ab18b), línea 609 en 19.0 (ce7f5a3) y línea 614 en 20.0 (688d86b)
- Código del módulo: flexigo_payment_gocardless: i18n/es.po, línea 1617 en 17.0 (d203ee6), línea 1617 en 18.0 (e2ab18b), línea 1617 en 19.0 (ce7f5a3) y línea 1628 en 20.0 (688d86b)
- Código del módulo: flexigo_payment_gocardless: i18n/es.po, línea 1343 en 17.0 (d203ee6), línea 1343 en 18.0 (e2ab18b), línea 1343 en 19.0 (ce7f5a3) y línea 1354 en 20.0 (688d86b)
- Código del módulo: flexigo_payment_gocardless: i18n/es.po, línea 560 en 17.0 (d203ee6), línea 560 en 18.0 (e2ab18b), línea 560 en 19.0 (ce7f5a3) y línea 565 en 20.0 (688d86b)
- Código del módulo: flexigo_payment_gocardless: __manifest__.py, línea 31 en 17.0 (d203ee6), 18.0 (e2ab18b), 19.0 (ce7f5a3) y 20.0 (688d86b)
- docs.gocardless.com/docs/api-reference/events/payment
- github.com/odoo/odoo/blob/17.0/odoo/http.py
- github.com/odoo/odoo/blob/20.0/addons/account_payment/views/account_move_views.xml
