Saltar para o conteúdo principal
GoCardless API · invalid_state · 409

GoCardless 409 idempotent_creation_conflict: a cobrança já existia

Este erro assusta mais do que deveria. A GoCardless responde 409 idempotent_creation_conflict quando recebe pela segunda vez um pedido de criação com uma chave de idempotência já utilizada. Bem aplicado, é exatamente o que impede cobrar duas vezes o mesmo recibo.

FlexigoTech · Responsável: Víctor Gómez · Atualizado em 6 de novembro de 2026

O essencial

Módulo
GoCardless
Versões
Odoo 17, 18, 19 e 20
Verificado
no código do conector, versão 17.0, 18.0, 19.0 e 20.0 · nas fontes indicadas no fim
Leitura
3 min

O que diz a GoCardless

ReasonTipoHTTPTexto de GoCardless
idempotent_creation_conflictinvalid_state409A resource already exists for the supplied idempotency key.

A página de limites da GoCardless completa-o: se já existir um recurso com essa chave, a resposta é um 409 com links.conflicting_resource_id, que assinala o recurso já criado. As chaves podem ter até 128 caracteres e a GoCardless guarda-as durante pelo menos 30 dias.

Cartão do erro idempotent_creation_conflict da GoCardless
O reason, o código HTTP 409 e o texto com que a GoCardless o documenta.

O problema que resolve

Um pedido pode demorar: a GoCardless corta os que ultrapassam 29 segundos, e a rede pode cortar antes. Se o Odoo pede uma cobrança e não recebe resposta, não sabe se a GoCardless a criou. Repetir o pedido sem mais é perigoso; a própria documentação da GoCardless avisa que repetir sem chave de idempotência após um tempo limite esgotado pode cobrar o mesmo pagamento duas vezes.

Com chave, a segunda tentativa não cria nada: se a primeira chegou, a GoCardless responde com este 409 e o identificador da cobrança que já existe.

Como o conector o usa

O conector envia uma chave de idempotência em cada pedido que cria uma cobrança, um reembolso, uma nova tentativa ou o pedido do mandato. A chave não é aleatória. Calcula-se com a operação, a transação do Odoo e o identificador da base de dados, de modo que:

  • repetir a mesma cobrança envia exatamente a mesma chave;
  • uma cópia da base para testes não colide com a de produção, mesmo que as duas emitam a mesma fatura.

Quando chega o 409, o conector lê conflicting_resource_id, pede esse recurso à GoCardless e adota-o como resposta. Para si não há erro: a transação fica associada à cobrança que já existia, e a fatura segue o seu curso normal.

Quando a GoCardless não responde

Se o pedido ficar sem resposta, o conector repete-o uma vez com a mesma chave. Sem chave, não repete nada. Se também não houver resposta, avisa sem dar a cobrança por perdida: «A GoCardless não respondeu, por isso ainda não se sabe se aceitou o pedido. Será enviado novamente, em segurança, dentro de uma hora.». A transação fica pendente, não em erro, porque em erro o Odoo poderia gerar outra cobrança com outra referência e outra chave.

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 ou o reenvio do próprio conector, 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 did not answer, so it is not known yet whether it took the request. It will be sent again, safely, within the hour.».

Esquema: o que a GoCardless responde com um 409 e o que o Odoo faz com o conector
Esquema feito a partir do código do conector (17.0, 18.0, 19.0 e 20.0) e da documentação da GoCardless; o que está riscado é o que o 409 evita.

O que fazer

Com o conector, normalmente nada: o 409 resolve-se sozinho. Se o vir noutro programa ligado à mesma conta da GoCardless, verifique duas coisas. A primeira, que não esteja a reutilizar uma chave para operações diferentes. A segunda, que o recurso de conflicting_resource_id seja o que esperava: se for, a nova tentativa funcionou como deve. Se não for, guarde o request_id da resposta: a GoCardless pede que o inclua ao contactar o seu suporte, e o conector acrescenta-o às suas mensagens de erro.

Um 409 significa que o cliente pagou duas vezes?

Pelo contrário. Significa que a GoCardless recusou criar a segunda cobrança porque a chave já tinha uma. O cliente paga uma única vez.

O que acontece se se alterar a referência da transação?

Muda a chave, e a GoCardless trata-o como uma cobrança nova. Por isso o conector deixa pendente, e não em erro, uma cobrança sem resposta: assim não se cria outra com outra referência.

Com o nosso conector

No Odoo 17, 18, 19 e 20 o conector aplica a regra que a GoCardless pede para não cobrar duas vezes: chave fixa por operação, repetição apenas com a mesma chave e adoção do recurso existente quando chega o 409.

Continue a ler

Erro mandate_is_inactive da GoCardless ao criar uma cobrança a partir do OdooA GoCardless responde mandate_is_inactive ao criar um pagamento com um mandato cancelado, falhado ou expirado. Porquê e como o conector o resolve no Odoo.Erro retry_failed da GoCardless ao tentar cobrar novamente a partir do OdooA GoCardless responde retry_failed se o pagamento não falhou ou já não admite novas tentativas. Eis quando surge o botão «Tentar cobrar novamente» no Odoo.Webhook do GoCardless: 498 Token Invalid, 204 e a assinatura Webhook-SignatureO GoCardless pede 498 se a Webhook-Signature não coincidir e 204 se não reconhecer o evento. O que responde o Odoo 17, 18, 19 e 20 e porque no 20 é um 401.
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/limits
  • 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_provider.py, linha 352 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 68 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 391 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 357 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 373 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 299 em 17.0 (d203ee6), linha 299 em 18.0 (e2ab18b), linha 299 em 19.0 (ce7f5a3) e linha 310 em 20.0 (688d86b)
  • Código do módulo: flexigo_payment_gocardless: i18n/pt.po, linha 476 em 17.0 (d203ee6), linha 476 em 18.0 (e2ab18b), linha 476 em 19.0 (ce7f5a3) e linha 482 em 20.0 (688d86b)
  • Código do módulo: flexigo_payment_gocardless: i18n/pt.po, linha 30 em 17.0 (d203ee6), 18.0 (e2ab18b), 19.0 (ce7f5a3) e 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/responses-and-errors
  • Código do módulo: flexigo_payment_gocardless: models/payment_transaction.py, linha 123 em 17.0 (d203ee6), linha 123 em 18.0 (e2ab18b), linha 123 em 19.0 (ce7f5a3) e linha 126 em 20.0 (688d86b)
  • Código do módulo: flexigo_payment_gocardless: models/payment_transaction.py, linha 247 em 17.0 (d203ee6), linha 247 em 18.0 (e2ab18b), linha 247 em 19.0 (ce7f5a3) e linha 258 em 20.0 (688d86b)
  • github.com/odoo/odoo/blob/17.0/odoo/http.py