O que diz a GoCardless
| Reason | Tipo | Texto da GoCardless |
|---|---|---|
retry_failed | invalid_state | Payment could not be retried. |
A documentação da nova tentativa (POST /payments/{id}/actions/retry) dá as regras: o pagamento é tentado de novo se o seu mandato estiver ativo, a API devolve retry_failed se o pagamento não falhou e «Payments can be retried up to 3 times.». Como em todos os erros invalid_state, a GoCardless pede para avisar quem utiliza o sistema e não o deixar tentar de novo. O conector anota no seu código que uma quarta tentativa também recebeu retry_failed no sandbox da GoCardless.

Porque aparece
Segundo a documentação, retry_failed surge quando o pagamento não falhou, e o conector viu-o também ao pedir uma quarta tentativa. Com um mandato que já não está ativo, a documentação não diz que erro chega: o conector espera retry_failed ou mandate_is_inactive e trata os dois da mesma forma.
O caso de um pagamento que não está falhado abrange mais do que parece. Uma cobrança pendente ou confirmada não falhou, e uma devolvida (charged_back) também não: o dinheiro chegou e o banco do cliente retirou-o depois. Segundo a documentação da GoCardless, qualquer uma delas receberia retry_failed.
Com o limite de tentativas, o que confunde é o Success+. Quando o Success+ tenta cobrar novamente um pagamento, a GoCardless envia um evento resubmission_requested, tal como em qualquer outra nova tentativa. O conector soma uma por cada um desses eventos, venha do Success+ ou de uma nova tentativa pedida a partir do Odoo, e anota no seu código que o limite de 3 da GoCardless inclui as do Success+. Como cada cobrança que o conector envia pede retry_if_possible, com o Success+ ativado é fácil que parte dessa quota já esteja gasta quando consulta a fatura.
O que vê no Odoo com o conector
A transação abre-se a partir da fatura, com o botão «Transação de Pagamento» na parte de cima; o menu de transações só aparece em modo de programador e, no Odoo 20, não existe. O botão «Tentar cobrar novamente» da transação só aparece quando o conector aceitaria a nova tentativa: é controlado por um campo calculado com a mesma regra que o servidor verifica ao carregar. Se a regra diz que não, o botão não aparece e o seu motivo não chega ao ecrã. O que vê é o estado da transação e o seu grupo GoCardless:
| Situação | O que vê na transação |
|---|---|
| O Success+ vai tentar novamente | Estado «Pendente», a caixa «O Success+ vai tentar novamente» marcada e, em «Mensagem», «A GoCardless não conseguiu cobrar este pagamento (…). O Success+ vai tentar novamente de forma automática; não é preciso fazer nada.». Sem botão. |
| Falhado, sem Success+, com menos de 3 tentativas e o mandato ativo | Estado «Erro» e o botão «Tentar cobrar novamente». |
| Já vão 3 tentativas | Estado «Erro» e «Novas tentativas da GoCardless» a 3. Sem botão. |
| O mandato está arquivado | Estado «Erro»; no contacto, a nota do mandato e a atividade «Mandato da GoCardless perdido». Sem botão. |
| Pendente ou confirmado | Sem botão. |
| Devolvido, por exemplo com MD06 | Estado «Erro», mesmo que o mandato continue ativo. Sem botão: na GoCardless o pagamento está em charged_back, não em failed. |
Ao carregar no botão, o Odoo pede confirmação: «A GoCardless vai tentar cobrar novamente este pagamento, o que pode ter uma comissão. Continuar?». Se a GoCardless aceitar, a transação passa a pendente com «Nova tentativa pedida. A GoCardless vai confirmar a nova data de débito.». Quando chega o evento resubmission_requested, o conector soma a tentativa e escreve a data: «A GoCardless vai cobrar novamente este pagamento em … (nova tentativa pedida, tentativa 1 de 3).». Ao carregar não soma nada, e assim cada tentativa conta uma só vez.
O que chega com os eventos é escrito pelo conector sem ninguém à frente: a mensagem do Success+ da tabela, a nova data de débito e, se o mandato morreu por causa de um evento, a nota e a atividade do contacto. Estes textos saem no idioma de quem lança a cobrança; se for uma ação agendada, como a renovação de uma subscrição, são escritos sem ninguém à frente: numa base de dados criada em português saem assim, e numa criada em inglês e passada depois para português, em 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).» e «GoCardless mandate lost». O que sai de carregar no botão vai no seu idioma.

Se a GoCardless responder retry_failed
Se mesmo assim a API responder retry_failed ou mandate_is_inactive, o conector consulta o mandato antes de mostrar o que quer que seja:
- Se o mandato estiver morto, arquiva-o e diz-o na transação: «O mandato GoCardless do cliente está no estado …, pelo que não pode ser cobrado. Peça ao cliente um novo mandato.».
- Se continuar ativo, mostra o erro da GoCardless tal como vem: «A GoCardless rejeitou o pedido.» e, por baixo, a mensagem da API, com o seu reason e o
request_id.
Com uma cobrança devolvida já não se chega aqui: desde a versão 1.1.4, o conector não oferece o botão se o pagamento não estiver em failed na GoCardless, e um devolvido está em charged_back.
O que fazer
- Se o botão não aparece, veja o estado da transação, «O Success+ vai tentar novamente» e «Novas tentativas da GoCardless»: uma das situações da tabela explica-o.
- Se já vão 3 tentativas, fale com o cliente: o conector já não pede outra.
- Se o mandato está arquivado, peça um novo e cobre com ele.
- Numa cobrança devolvida não há botão: fale primeiro com o cliente e, se for caso disso, volte a cobrar a fatura com uma nova cobrança.
Cada nova tentativa custa dinheiro?
Pode. O botão avisa-o antes de enviar o que quer que seja, e o conector não o oferece enquanto o Success+ vai tentar cobrar novamente, porque uma tentativa manual só acrescentaria uma comissão. As tarifas concretas dependem do seu contrato com a GoCardless.
Posso tentar cobrar novamente uma cobrança devolvida pelo cliente?
Com este botão, não: o conector não o oferece numa cobrança devolvida, porque a GoCardless só tenta de novo pagamentos falhados e um devolvido não o é. Uma devolução, como um MD06, resolve-se falando com o cliente e, se for caso disso, com uma nova cobrança.
Com o nosso conector
No Odoo 17, 18, 19 e 20, o conector conta as tentativas com os eventos da GoCardless e só mostra o botão quando a sua regra o permite: não com o Success+ em curso, nem com 3 tentativas, nem com o mandato arquivado. Se mesmo assim chegar retry_failed, consulta o mandato antes de lhe mostrar o erro.
Continue a ler
Verificado no código do conector (versão 17.0, 18.0, 19.0 e 20.0) e nas fontes indicadas
Fontes
- docs.gocardless.com/docs/api-reference/payment
- docs.gocardless.com/docs/api-reference/responses-and-errors
- Código do módulo: flexigo_payment_gocardless: const.py, linha 119 em 17.0 (d203ee6), 18.0 (e2ab18b), 19.0 (ce7f5a3) e 20.0 (688d86b)
- docs.gocardless.com/docs/optimise/reduced-failed-payments-with-success-plus
- Código do módulo: flexigo_payment_gocardless: models/payment_transaction.py, linha 680 em 17.0 (d203ee6), linha 680 em 18.0 (e2ab18b), linha 679 em 19.0 (ce7f5a3) e linha 703 em 20.0 (688d86b)
- Código do módulo: flexigo_payment_gocardless: models/payment_transaction.py, linha 449 em 17.0 (d203ee6), linha 449 em 18.0 (e2ab18b), linha 448 em 19.0 (ce7f5a3) e linha 463 em 20.0 (688d86b)
- Código do módulo: flexigo_payment_gocardless: const.py, linha 122 em 17.0 (d203ee6), 18.0 (e2ab18b), 19.0 (ce7f5a3) e 20.0 (688d86b)
- Código do módulo: flexigo_payment_gocardless: models/payment_transaction.py, linha 260 em 17.0 (d203ee6), linha 260 em 18.0 (e2ab18b), linha 260 em 19.0 (ce7f5a3) e linha 271 em 20.0 (688d86b)
- Código do módulo: flexigo_payment_gocardless: views/payment_transaction_views.xml, linha 13 em 17.0 (d203ee6), 18.0 (e2ab18b), 19.0 (ce7f5a3) e 20.0 (688d86b)
- Código do módulo: flexigo_payment_gocardless: models/payment_transaction.py, linha 63 em 17.0 (d203ee6), 18.0 (e2ab18b), 19.0 (ce7f5a3) e 20.0 (688d86b)
- Código do módulo: flexigo_payment_gocardless: models/payment_transaction.py, linha 418 em 17.0 (d203ee6), linha 418 em 18.0 (e2ab18b), linha 417 em 19.0 (ce7f5a3) e linha 432 em 20.0 (688d86b)
- Código do módulo: flexigo_payment_gocardless: views/payment_transaction_views.xml, linha 27 em 17.0 (d203ee6), 18.0 (e2ab18b), 19.0 (ce7f5a3) e 20.0 (688d86b)
- Código do módulo: flexigo_payment_gocardless: views/payment_transaction_views.xml, linha 28 em 17.0 (d203ee6), 18.0 (e2ab18b), 19.0 (ce7f5a3) e 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/pt.po
- Código do módulo: flexigo_payment_gocardless: models/payment_transaction.py, linha 729 em 17.0 (d203ee6), linha 729 em 18.0 (e2ab18b), linha 728 em 19.0 (ce7f5a3) e linha 752 em 20.0 (688d86b)
- Código do módulo: flexigo_payment_gocardless: models/payment_transaction.py, linha 713 em 17.0 (d203ee6), linha 713 em 18.0 (e2ab18b), linha 712 em 19.0 (ce7f5a3) e linha 736 em 20.0 (688d86b)
- Código do módulo: flexigo_payment_gocardless: models/payment_transaction.py, linha 430 em 17.0 (d203ee6), linha 430 em 18.0 (e2ab18b), linha 429 em 19.0 (ce7f5a3) e linha 444 em 20.0 (688d86b)
- Código do módulo: flexigo_payment_gocardless: models/payment_transaction.py, linha 437 em 17.0 (d203ee6), linha 437 em 18.0 (e2ab18b), linha 436 em 19.0 (ce7f5a3) e linha 451 em 20.0 (688d86b)
- Código do módulo: flexigo_payment_gocardless: models/payment_transaction.py, linha 442 em 17.0 (d203ee6), linha 442 em 18.0 (e2ab18b), linha 441 em 19.0 (ce7f5a3) e linha 456 em 20.0 (688d86b)
- Código do módulo: flexigo_payment_gocardless: models/payment_transaction.py, linha 435 em 17.0 (d203ee6), linha 435 em 18.0 (e2ab18b), linha 434 em 19.0 (ce7f5a3) e linha 449 em 20.0 (688d86b)
- Código do módulo: flexigo_payment_gocardless: models/payment_token.py, linha 131 em 17.0 (d203ee6), linha 131 em 18.0 (e2ab18b), linha 131 em 19.0 (ce7f5a3) e linha 130 em 20.0 (688d86b)
- Código do módulo: flexigo_payment_gocardless: models/payment_transaction.py, linha 469 em 17.0 (d203ee6), linha 469 em 18.0 (e2ab18b), linha 468 em 19.0 (ce7f5a3) e linha 487 em 20.0 (688d86b)
- Código do módulo: flexigo_payment_gocardless: models/payment_transaction.py, linha 321 em 17.0 (d203ee6), linha 321 em 18.0 (e2ab18b), linha 321 em 19.0 (ce7f5a3) e linha 332 em 20.0 (688d86b)
- Código do módulo: flexigo_payment_gocardless: models/payment_provider.py, linha 397 em 17.0 (d203ee6), 18.0 (e2ab18b), 19.0 (ce7f5a3) e 20.0 (688d86b)
- Código do módulo: flexigo_payment_gocardless: models/payment_provider.py, linha 462 em 17.0 (d203ee6), 18.0 (e2ab18b), 19.0 (ce7f5a3) e 20.0 (688d86b)
- Código do módulo: flexigo_payment_gocardless: models/payment_transaction.py, linha 484 em 17.0 (d203ee6), linha 484 em 18.0 (e2ab18b), linha 483 em 19.0 (ce7f5a3) e linha 502 em 20.0 (688d86b)
- Código do módulo: flexigo_payment_gocardless: models/payment_transaction.py, linha 683 em 17.0 (d203ee6), linha 683 em 18.0 (e2ab18b), linha 682 em 19.0 (ce7f5a3) e linha 706 em 20.0 (688d86b)
- Código do módulo: flexigo_payment_gocardless: i18n/pt.po, linha 1091 em 17.0 (d203ee6), linha 1091 em 18.0 (e2ab18b), linha 1091 em 19.0 (ce7f5a3) e linha 1113 em 20.0 (688d86b)
- Código do módulo: flexigo_payment_gocardless: i18n/pt.po, linha 617 em 17.0 (d203ee6), linha 617 em 18.0 (e2ab18b), linha 617 em 19.0 (ce7f5a3) e linha 623 em 20.0 (688d86b)
- Código do módulo: flexigo_payment_gocardless: i18n/pt.po, linha 1142 em 17.0 (d203ee6), linha 1142 em 18.0 (e2ab18b), linha 1142 em 19.0 (ce7f5a3) e linha 1154 em 20.0 (688d86b)
- Código do módulo: flexigo_payment_gocardless: i18n/pt.po, linha 429 em 17.0 (d203ee6), linha 429 em 18.0 (e2ab18b), linha 429 em 19.0 (ce7f5a3) e linha 435 em 20.0 (688d86b)
- Código do módulo: flexigo_payment_gocardless: i18n/pt.po, linha 462 em 17.0 (d203ee6), linha 462 em 18.0 (e2ab18b), linha 462 em 19.0 (ce7f5a3) e linha 468 em 20.0 (688d86b)
- Código do módulo: flexigo_payment_gocardless: i18n/pt.po, linha 1164 em 17.0 (d203ee6), linha 1164 em 18.0 (e2ab18b), linha 1164 em 19.0 (ce7f5a3) e linha 1176 em 20.0 (688d86b)
- Código do módulo: flexigo_payment_gocardless: i18n/pt.po, linha 525 em 17.0 (d203ee6), linha 525 em 18.0 (e2ab18b), linha 525 em 19.0 (ce7f5a3) e linha 531 em 20.0 (688d86b)
- Código do módulo: flexigo_payment_gocardless: i18n/pt.po, linha 1097 em 17.0 (d203ee6), linha 1097 em 18.0 (e2ab18b), linha 1097 em 19.0 (ce7f5a3) e linha 1119 em 20.0 (688d86b)
- Código do módulo: flexigo_payment_gocardless: i18n/pt.po, linha 608 em 17.0 (d203ee6), linha 608 em 18.0 (e2ab18b), linha 608 em 19.0 (ce7f5a3) e linha 614 em 20.0 (688d86b)
- Código do módulo: flexigo_payment_gocardless: i18n/pt.po, linha 1617 em 17.0 (d203ee6), linha 1617 em 18.0 (e2ab18b), linha 1617 em 19.0 (ce7f5a3) e linha 1629 em 20.0 (688d86b)
- Código do módulo: flexigo_payment_gocardless: i18n/pt.po, linha 1346 em 17.0 (d203ee6), linha 1346 em 18.0 (e2ab18b), linha 1346 em 19.0 (ce7f5a3) e linha 1358 em 20.0 (688d86b)
- Código do módulo: flexigo_payment_gocardless: i18n/pt.po, linha 558 em 17.0 (d203ee6), linha 558 em 18.0 (e2ab18b), linha 558 em 19.0 (ce7f5a3) e linha 564 em 20.0 (688d86b)
- Código do módulo: flexigo_payment_gocardless: __manifest__.py, linha 31 em 17.0 (d203ee6), 18.0 (e2ab18b), 19.0 (ce7f5a3) e 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
