Usuário não consegue recomprar um produto de assinatura após cancelar

Tenho um problema estranho surgido aqui com um assinante.

Eles não têm assinaturas ativas na seção de Cobrança;

No Stripe, aparece como cancelado;

image

mas eles não conseguem reassinar… diz que já foi comprado;

image

Configurei algo incorretamente?

1 curtida

Parece que seu endpoint de webhook pode estar configurado incorretamente. Quando o período da assinatura termina, o Stripe envia um webhook que o plugin usa para remover a associação ao grupo e remover o usuário como cliente existente desse produto (o que permite que o usuário compre novamente).

Você precisará garantir que isso esteja configurado conforme o OP aqui: Discourse Subscriptions

Uma maneira de confirmar isso do seu servidor:

./launcher enter app
rails c
u = User.find_by_username(<username>)
c = DiscourseSubscriptions::Customer.where(user_id: u.id)
subscription = DiscourseSubscriptions::Subscription.where(customer_id: c.customer_id)

Lembre-se de substituir <username> pelo nome de usuário real do usuário.

Se subscription retornar [], há outro problema em andamento. Mas se retornar um valor, isso provavelmente confirma o webhook ausente.

Para excluir a entrada DiscourseSubscriptions::Subscription para que o usuário possa comprar o produto novamente:

Certifique-se de que subscription tenha apenas um valor executando subscription.count. Se o valor retornado for maior que 1, você precisará investigar um pouco mais para garantir que está excluindo a instância de assinatura correta. Se você excluir a errada, os dados de suas assinaturas ficarão em um estado inconsistente e provavelmente gerarão comportamentos estranhos.

Depois de confirmar que há apenas uma assinatura, você pode executar:

subscription.destroy_all

Lembre-se de que subscription é o valor retornado do conjunto inicial de consultas que executamos no console do Rails.

Espero que isso ajude!

2 curtidas

Obrigado, @justin

• Cheguei à última linha de assinatura e a executei… retornou isso;

NoMethodError: método indefinido customer_id' para #<DiscourseSubscriptions::Customer::ActiveRecord_Relation:0x000055be473772f0> de /var/www/discourse/vendor/bundle/ruby/2.7.0/gems/activerecord-6.1.3.2/lib/active_record/relation/delegation.rb:110:in method_missing’

• Verifiquei os webhooks do Stripe e eles estão apontados para https://./s/hooks

• Eventos enviados para o webhook;

  • subscription_schedule.updated
    
  • subscription_schedule.expiring
    
  • subscription_schedule.created
    
  • subscription_schedule.canceled
    

• O log de webhook do Stripe tem uma entrada da data de configuração que parece estar estabelecendo os eventos suportados.

• Tenho uma entrada de evento no Stripe que é um cancelamento de assinatura, mas… a entrada da linha diz (efetivamente) “[a assinatura foi cancelada]”, no entanto, quando entro no evento, diz que o tipo de evento é customer.subscription.deleted … o que notei não estar listado na minha lista de eventos de webhook.

O acima poderia ser o problema?

1 curtida

Parece que a linha deve ser DiscourseSubscriptions::Subscription em vez de ::Customer. Tente isso e veja o que você obtém!

1 curtida

[2] pry(main)> c = DiscourseSubscriptions::Subscription.where(user_id: u.id)
=> #DiscourseSubscriptions::Subscription::ActiveRecord_Relation:0x8020
[3] pry(main)> subscription = DiscourseSubscriptions::Subscription.where(customer_id: c.customer_id)
NoMethodError: método customer_id' não definido para #<DiscourseSubscriptions::Subscription::ActiveRecord_Relation:0x000055ec51164ca0> de /var/www/discourse/vendor/bundle/ruby/2.7.0/gems/activerecord-6.1.3.2/lib/active_record/relation/delegation.rb:110:in method_missing’

1 curtida

Desculpe, eu entendi mal onde isso estava acontecendo.

Tente isso em vez disso:

./launcher enter app
rails c
u = User.find_by_username(<username>)
c = DiscourseSubscriptions::Customer.find_by(user_id: u.id)
subscription = DiscourseSubscriptions::Subscription.where(customer_id: c[:customer_id])
1 curtida

Ah..

[3] pry(main)> subscription = DiscourseSubscriptions::Subscription.where(customer_id: c[:customer_id])
=>

1 curtida

Você acha que a falta de dados de assinatura tem alguma relação com o evento customer.subscription.deleted estar ausente?

Há algo que eu deva explorar agora?

Estou particularmente interessado em entender por que a página de assinatura exibe “comprado”, enquanto a seção de assinaturas ativas não mostra nenhuma assinatura ativa. Existe algum outro local no banco de dados onde as informações de assinatura são armazenadas, que possa estar limpo ou vazio na seção de assinaturas ativas, mas onde um booleano “comprado” ainda esteja definido como verdadeiro em algum lugar… ou algo assim?

1 curtida

Há mais alguma coisa que possamos tentar aqui?

1 curtida

Certifique-se de que, no Stripe, a compra esteja totalmente cancelada e não aguardando o cancelamento ao final do período. Você também pode verificar na área Admin → Plugins → Discourse Subscriptions → Subscriptions e procurar pelo nome de usuário desse usuário. Se houver uma assinatura listada para ele, você pode cancelá-la imediatamente.

Sem analisar mais a fundo sua instância do Discourse, não tenho certeza de quanto mais posso ajudar.

1 curtida

Sim, não está ativo em assinaturas na área do plugin, e também não no Stripe. A única coisa que indica que algo ainda está ativo é quando o usuário vai para a página de assinatura: ele vê um pequeno ícone de marca de seleção verde com a palavra “comprado” e a opção “ir para faturamento”.

image

Se eu acessar o faturamento como o usuário em questão, não há nada;

Então, minha pergunta é: o que no banco de dados dispara essa marca de seleção verde e é possível limpá-la?

Se esta lista incluir o ID do produto do Stripe, conforme mostrado aqui:

Então o front-end irá exibi-lo como comprado. Você pode precisar explorar o console com essas consultas para descobrir onde ele está localizado. Tenho quase certeza de que ainda há um registro por lá.

1 curtida

Ok, sei que estou ressuscitando este tópico, mas 1) isso continua sem solução e 2) encontrei tempo para investigar isso novamente… Acontece que eu era um idiota que não conseguia seguir as instruções. É assim que descobri que sou um bobo e por que agora estou pronto para resolver isso (com alguma ajuda).

O que acabei fazendo foi exportar um CSV do Stripe de todas as contas canceladas. Concentrei-me no mesmo usuário do Discourse referenciado acima neste tópico, que era assinante, havia cancelado, mas depois não conseguia se reinscrever porque a página de assinatura mostrava como “comprada”, embora sua página de assinaturas ativas não mostrasse nenhuma assinatura. Nos dados do CSV, o registro dele mostrava como “cancelado” com os seguintes dados;

  • id (sub_JNWejdDo4qhLG5)
  • customer_id (cus_JmiMoqZNTzUNxt)
  • user_id (id do usuário do Discourse 4981)

Então, anexei ao contêiner do aplicativo, entrei no console Ruby e comecei a investigar. Primeiro, procurei o ID do cliente em DiscourseSubscriptions::Customer e o encontrei.

[3] pry(main)> DiscourseSubscriptions::Customer.where(customer_id: 'cus_JNWeiIWTs6YOwQ')
=> [#<DiscourseSubscriptions::Customer:0x000055db2d48eb40
  id: 16,
  customer_id: "cus_JNWeiIWTs6YOwQ",
  product_id: "prod_JJbwYnKz0T5Z9h",
  user_id: 3256,
  created_at: Tue, 27 Apr 2021 07:45:07.455275000 UTC +00:00,
  updated_at: Tue, 27 Apr 2021 07:45:07.455275000 UTC +00:00>]

Em seguida, procurei em DiscourseSubscriptions::Subscription para ver se este usuário tinha alguma assinatura e, surpreendentemente, sim, ele tinha;

[1] pry(main)> DiscourseSubscriptions::Subscription.where(external_id: 'sub_JNWejdDo4qhLG5')
=> [#<DiscourseSubscriptions::Subscription:0x000055854e1e1620
  id: 16,
  customer_id: 16,
  external_id: "sub_JNWejdDo4qhLG5",
  created_at: Tue, 27 Apr 2021 07:45:07.459681000 UTC +00:00,
  updated_at: Tue, 27 Apr 2021 07:45:07.459681000 UTC +00:00>]

Portanto, parece que posso simplesmente remover este registro de assinatura e corrigir tudo… para este usuário. O fato é que todo usuário cancelado que verifiquei em minha exportação CSV ainda tinha assinaturas restantes no sistema. Obviamente, há uma desconexão de alguma forma / em algum lugar entre o webhook do Stripe e o plugin de assinatura… Eu só não sei onde / como.

  • Primeiro; como removo com segurança o registro de assinatura de um usuário específico? Explique como se eu tivesse 5 anos. Estou no prompt do console Ruby… como garanto que apenas os dados de assinatura do usuário alvo sejam removidos e eu não apague os dados de assinatura de todos?

  • Segundo, como soluciono o mecanismo de webhook de cancelamento de assinatura?

Toda a sua ajuda é muito apreciada!

ATUALIZAÇÃO:

Ok, avancei um pouco mais… Consegui descobrir como usar .delete_by para remover apenas os dados de assinatura do usuário alvo;

[1] pry(main)> DiscourseSubscriptions::Subscription.delete_by(external_id: 'sub_JNWejdDo4qhLG5')
[2] pry(main)> DiscourseSubscriptions::Subscription.where(external_id: 'sub_JNWejdDo4qhLG5')
=> []

No entanto, o registro do cliente ainda tem um product_id associado;

[3] pry(main)> DiscourseSubscriptions::Customer.where(customer_id: 'cus_JNWeiIWTs6YOwQ')
=> [#<DiscourseSubscriptions::Customer:0x0000560ec18e4948
  id: 16,
  customer_id: "cus_JNWeiIWTs6YOwQ",
  product_id: "prod_JJbwYnKz0T5Z9h",
  user_id: 3256,
  created_at: Tue, 27 Apr 2021 07:45:07.455275000 UTC +00:00,
  updated_at: Tue, 27 Apr 2021 07:45:07.455275000 UTC +00:00>]

Isso significa que eles ainda veem o visto verde e não conseguem se reinscrever… então apliquei o “destroy_all” ao objeto Customer… e funcionou! Mas apenas para aquele usuário, é claro…

[4] pry(main)> DiscourseSubscriptions::Customer.where(customer_id: 'cus_JNWeiIWTs6YOwQ').destroy_all
=> [#<DiscourseSubscriptions::Customer:0x0000560ec19770e0
  id: 16,
  customer_id: "cus_JNWeiIWTs6YOwQ",
  product_id: "prod_JJbwYnKz0T5Z9h",
  user_id: 3256,
  created_at: Tue, 27 Apr 2021 07:45:07.455275000 UTC +00:00,
  updated_at: Tue, 27 Apr 2021 07:45:07.455275000 UTC +00:00>]

Então, agora resta apenas diagnosticar por que o webhook do Stripe para assinaturas canceladas não está funcionando.