L'utilisateur ne peut pas racheter un produit par abonnement après l'avoir annulé

J’ai un problème étrange avec un abonné.

Il n’a aucune souscription active dans la section Facturation ;

Dans Stripe, elle apparaît comme annulée ;

image

pourtant, il ne peut pas se réabonner… le système indique qu’il a déjà acheté ;

image

Ai-je configuré quelque chose incorrectement ?

1 « J'aime »

Cela ressemble à une configuration incorrecte de votre point de terminaison de webhook. Lorsque la période d’abonnement prend fin, Stripe envoie un webhook que le plugin utilise pour supprimer l’appartenance au groupe et retirer l’utilisateur en tant que client existant pour ce produit (ce qui permet à l’utilisateur d’acheter à nouveau).

Vous devez vous assurer que cela est configuré conformément au sujet original (OP) ici : Discourse Subscriptions

Une méthode pour confirmer depuis votre serveur :

./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)

N’oubliez pas de remplacer <username> par le véritable nom d’utilisateur de l’utilisateur.

Si subscription retourne [], un autre problème est en cours. Mais si elle retourne une valeur, cela confirme probablement le webhook manquant.

Pour supprimer l’entrée DiscourseSubscriptions::Subscription afin que l’utilisateur puisse acheter à nouveau le produit :

Assurez-vous que subscription ne contient qu’une seule valeur en exécutant subscription.count. Si la valeur retournée est supérieure à 1, vous devrez faire un peu plus d’investigation pour vous assurer de supprimer la bonne instance d’abonnement. Si vous supprimez la mauvaise, vos données d’abonnement seront dans un état incohérent et entraîneront probablement des comportements étranges.

Une fois confirmé qu’il n’y a qu’un seul abonnement, vous pouvez exécuter :

subscription.destroy_all

Gardez à l’esprit que subscription est la valeur retournée par l’ensemble initial de requêtes que nous avons exécutées dans la console Rails.

J’espère que cela vous aidera !

2 « J'aime »

Merci @justin

• Je suis arrivé à la dernière ligne de la souscription et je l’ai exécutée… cela a renvoyé ceci :

\u003e NoMethodError: méthode customer_id' non définie pour #\u003cDiscourseSubscriptions::Customer::ActiveRecord_Relation:0x000055be473772f0\u003e\n\u003e depuis /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’

• J’ai vérifié les webhooks Stripe et ils pointent vers https://\u003csite\u003e.\u003ctld\u003e/s/hooks

• Événements envoyés au webhook ;

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

• Le journal des webhooks Stripe contient une entrée depuis la date de configuration qui semble établir les événements pris en charge.

• J’ai une entrée d’événement dans Stripe correspondant à l’annulation d’une souscription, mais… l’entrée de la ligne indique (en substance) « [la souscription a été annulée] », alors que lorsque je clique sur l’événement, il indique que le type d’événement est customer.subscription.deleted … ce que je remarque n’est pas listé dans ma liste d’événements de webhook.

Est-ce que ce qui précède pourrait être le problème ?

1 « J'aime »

Il semble que la ligne devrait être DiscourseSubscriptions::Subscription au lieu de ::Customer. Essayez cela et voyez ce que vous obtenez !

1 « J'aime »

[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: la méthode customer_id n’est pas définie pour #DiscourseSubscriptions::Subscription::ActiveRecord_Relation:0x000055ec51164ca0
depuis /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 « J'aime »

Désolé, j’ai mal compris où cela se produisait.

Essayez plutôt ceci :

./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 « J'aime »

Ah..

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

1 « J'aime »

Pensez-vous que l’absence de données d’abonnement ait un lien avec le fait que l’événement customer.subscription.deleted manque ?

Y a-t-il autre chose que je devrais explorer à ce stade ?

Je suis particulièrement intéressé par la raison pour laquelle la page d’abonnement affiche « acheté » alors que la section des abonnements actifs n’en affiche aucun. Existe-t-il un autre endroit dans la base de données où les informations d’abonnement sont stockées, qui pourrait être vidé ou vide dans la section des abonnements actifs, mais où un booléen « acheté » reste néanmoins défini sur true quelque part… ou quelque chose de similaire ?

1 « J'aime »

Y a-t-il autre chose à essayer ici ?

1 « J'aime »

Assurez-vous que dans Stripe, l’achat est bien annulé et non en attente d’annulation à la fin de la période. Vous pouvez également consulter la section Admin → Plugins → Discourse Subscriptions → Subscriptions et rechercher le nom d’utilisateur de cette personne. Si une souscription y est répertoriée, vous pouvez l’annuler immédiatement.

Sans examiner davantage votre instance Discourse, je ne suis pas certain de pouvoir vous aider davantage.

1 « J'aime »

oui, ce n’est pas actif dans les abonnements de la section du plugin, et pas non plus sur Stripe. La seule chose qui indique qu’un abonnement est toujours actif est que, si l’utilisateur accède à la page d’abonnement, il voit une petite coche verte « acheté » et un lien « aller à la facturation ».

image

Si j’accède à la facturation en tant que l’utilisateur concerné, rien ne s’affiche :

Ma question est donc : quel élément de la base de données déclenche cette coche verte et peut-elle être effacée ?

Si cette liste inclut l’ID du produit Stripe comme indiqué ici :

Alors l’interface utilisateur l’affichera comme acheté. Vous devrez peut-être explorer la console avec ces requêtes pour savoir où il se trouve. Je garantis presque qu’il reste encore un enregistrement là-bas.

1 « J'aime »

Ok, je sais que je déterre ce fil de discussion, mais 1) cela continue de ne pas être résolu, et 2) j’ai trouvé le temps de m’y replonger… il s’avère que j’étais un idiot qui ne savait pas suivre les instructions. C’est ainsi que j’ai découvert que j’étais un imbécile, et pourquoi je suis maintenant prêt à résoudre ce problème (avec un peu d’aide).

Ce que j’ai fini par faire, c’est exporter un CSV de Stripe de tous les comptes annulés. Je me suis concentré sur l’utilisateur de Discourse mentionné ci-dessus dans ce fil de discussion, qui était un abonné, s’était désabonné, mais ne pouvait pas se réabonner car la page d’abonnement s’affichait comme “acheté” alors que sa page d’abonnements actifs n’affichait aucun abonnement. Dans les données CSV, son enregistrement était indiqué comme “annulé” avec les données suivantes ;

  • id (sub_JNWejdDo4qhLG5)
  • customer_id (cus_JmiMoqZNTzUNxt)
  • user_id (id utilisateur Discourse 4981)

Ensuite, je me suis attaché au conteneur de l’application, je suis allé dans la console Ruby et j’ai commencé à explorer. D’abord, j’ai recherché son ID client dans DiscourseSubscriptions::Customer et je l’ai trouvé.

[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>]

Ensuite, j’ai recherché dans DiscourseSubscriptions::Subscription pour voir si cet utilisateur avait des abonnements et il s’avère que oui, il en avait ;

[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>]

Donc, il semble que je puisse simplement supprimer cet enregistrement d’abonnement et tout réparer… pour cet utilisateur. Le fait est que chaque utilisateur annulé que j’ai vérifié dans mon exportation CSV avait encore des abonnements restants dans le système. Il y a évidemment une déconnexion quelque part entre le webhook Stripe et le plugin d’abonnement… je ne sais juste pas où / comment.

  • Premièrement ; comment supprimer en toute sécurité l’enregistrement de l’abonnement pour un utilisateur particulier ? Expliquez-le-moi comme si j’avais 5 ans… Je suis à l’invite de la console Ruby… comment puis-je m’assurer que seules les données d’abonnement de l’utilisateur cible sont supprimées et que je ne supprime pas les données d’abonnement de tout le monde ?

  • Deuxièmement, comment dépanner le mécanisme du webhook d’annulation d’abonnement ?

Toute votre aide est très appréciée !

MISE À JOUR :

Ok, j’ai avancé un peu… j’ai réussi à trier comment utiliser .delete_by pour ne supprimer que les données d’abonnement de l’utilisateur cible ;

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

Cependant, l’enregistrement client a toujours un product_id associé ;

[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>]

Cela signifie qu’ils voient toujours la coche verte et ne peuvent pas se réabonner… j’ai donc appliqué le “destroy_all” à l’objet Customer… et cela a fonctionné ! Mais seulement pour cet utilisateur, bien sûr…

[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>]

Il ne reste donc plus qu’à diagnostiquer pourquoi le webhook Stripe pour les abonnements annulés ne fonctionne pas.