Пользователь не может повторно купить подписку после отмены

У меня возникла странная проблема с подписчиком.

У него нет активных подписок в разделе «Оплата»;

В Stripe статус показан как отменённый;

image

но он не может оформить подписку заново — система пишет, что товар уже приобретён;

image

Возможно, я что-то настроил неправильно?

Похоже, у вас неправильно настроена конечная точка веб-хука. Когда период подписки истекает, Stripe отправляет веб-хук, который плагин использует для удаления членства в группе и исключения пользователя из списка существующих клиентов по этому продукту (что позволяет пользователю совершить покупку снова).

Вам необходимо убедиться, что это настроено в соответствии с инструкциями из оригинального поста здесь: Discourse Subscriptions

Один из способов подтвердить это на вашем сервере:

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

Обязательно замените <username> на реальное имя пользователя.

Если subscription возвращает [], значит, есть другая проблема. Но если возвращается значение, это, скорее всего, подтверждает отсутствие веб-хука.

Чтобы удалить запись DiscourseSubscriptions::Subscription, чтобы пользователь мог снова приобрести продукт:

Убедитесь, что subscription содержит только одно значение, выполнив subscription.count. Если возвращаемое значение больше 1, вам придется немного глубже изучить ситуацию, чтобы убедиться, что вы удаляете правильный экземпляр подписки. Если вы удалите не тот, данные о подписках окажутся в несогласованном состоянии, что, вероятно, приведет к некорректному поведению.

После того как вы подтвердите, что есть только одна подписка, вы можете выполнить:

subscription.destroy_all

Имейте в виду, что subscription — это значение, возвращенное из первоначального набора запросов, которые мы выполнили в консоли Rails.

Надеюсь, это поможет!

Спасибо, @justin.

• Перешел к последней строке с подпиской и выполнил её. Получил следующее:

NoMethodError: undefined method customer_id' for #<DiscourseSubscriptions::Customer::ActiveRecord_Relation:0x000055be473772f0> from /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’

• Проверил вебхуки Stripe — они направлены на https://./s/hooks.

• События, отправленные на вебхук:

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

• В логе вебхуков Stripe есть одна запись от даты настройки, которая, похоже, указывает на регистрацию поддерживаемых событий.

• У меня есть запись события в Stripe о отмене подписки, но.. в строке записи сказано (по сути) «[подписка была отменена]», однако при переходе к событию указано, что тип события — customer.subscription.deleted, что, как я заметил, отсутствует в моем списке событий вебхуков.

Может ли это быть проблемой?

Похоже, что строка должна быть DiscourseSubscriptions::Subscription вместо ::Customer. Попробуйте это и посмотрите, что получится!

[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: не определен метод customer_id' для #<DiscourseSubscriptions::Subscription::ActiveRecord_Relation:0x000055ec51164ca0> из /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’

Извините, я неправильно понял, где это происходит.

Попробуйте вместо этого:

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

Ах..

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

Как вы думаете, не связано ли отсутствие данных о подписке с тем, что событие customer.subscription.deleted отсутствует?

Есть ли что-то, что мне стоит изучить дальше на данном этапе?

Меня особенно интересует причина, по которой на странице подписки отображается статус «куплено», в то время как в разделе активных подписок нет активных подписок. Возможно, в базе данных есть какое-то другое место, где хранится информация о подписке, которая может быть очищена или пуста в разделе активных подписок, но при этом где-то булево значение «куплено» всё ещё установлено в true? Или что-то в этом роде?

Есть ли ещё что-то, что можно попробовать здесь?

Убедитесь, что в Stripe покупка полностью отменена и не находится в ожидании отмены в конце периода. Вы также можете перейти в раздел Администрирование → Плагины → Подписки Discourse → Подписки и найти имя пользователя. Если у него там указана подписка, вы можете отменить её немедленно.

Без дальнейшего изучения вашего экземпляра Discourse я не уверен, чем ещё могу помочь.

Да, это не отображается как активное ни в разделе подписок в области плагина, ни в Stripe. Единственное, что указывает на то, что что-то всё ещё активно, — это если пользователь заходит на страницу подписки, он видит маленькую зелёную галочку «Куплено» и ссылку «Перейти к биллингу».

image

Если я перехожу в биллинг как указанный пользователь, там ничего нет;

Так что мой вопрос: что в базе данных вызывает появление этой зелёной галочки и можно ли её убрать?

Если этот список включает идентификатор продукта Stripe, как указано здесь:

то фронтенд отобразит его как купленный. Возможно, вам потребуется поискать в консоли с помощью этих запросов, чтобы выяснить, где он находится. Я почти уверен, что запись всё ещё там присутствует.

Хорошо, я знаю, что воскрешаю эту тему, но 1) проблема до сих пор не решена, и 2) у меня наконец-то нашлось время снова в этом разобраться… Оказалось, я был идиотом, который не мог следовать инструкциям. Вот как я понял, что я дилетант, и почему теперь готов решить эту проблему (с некоторой помощью).

В итоге я экспортировал из Stripe CSV-файл со всеми отмененными аккаунтами. Я сосредоточился на том самом пользователе Discourse, упомянутом выше в этой теме: он был подписчиком, отменил подписку, но не мог оформить новую, потому что страница подписки показывала статус «куплено», хотя на странице активных подписок ничего не отображалось. В данных CSV его запись имела статус «canceled» со следующими данными:

  • id (sub_JNWejdDo4qhLG5)
  • customer_id (cus_JmiMoqZNTzUNxt)
  • user_id (id пользователя Discourse 4981)

Затем я подключился к контейнеру приложения, зашел в консоль Ruby и начал копаться. Сначала я поискал его customer_id в DiscourseSubscriptions::Customer и нашел его.

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

Далее я поискал в DiscourseSubscriptions::Subscription, есть ли у этого пользователя какие-либо подписки, и оказалось, что да, есть;

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

Итак, похоже, я могу просто удалить эту запись о подписке и исправить всё… для этого пользователя. Дело в том, что у каждого отмененного пользователя, которого я проверил в своем CSV-экспорте, в системе все еще оставались активные подписки. Очевидно, где-то существует разрыв между вебхуком Stripe и плагином подписок… Я просто не знаю где и как.

  • Во-первых: как безопасно удалить данные записи о подписке для конкретного пользователя? Объясните мне, как пятилетнему… Я нахожусь в приглашении консоли Ruby… Как убедиться, что удаляются только данные подписки целевого пользователя, а не всех пользователей?

  • Во-вторых: как устранить неполадки в механизме вебхука отмены подписки?

Ваша помощь очень ценна!

ОБНОВЛЕНИЕ:

Хорошо, я продвинулся немного дальше… Мне удалось разобраться, как использовать .delete_by, чтобы удалить только данные подписки для целевого пользователя;

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

Однако запись клиента все еще имеет связанный product_id;

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

Это означает, что они все еще видят зеленую галочку и не могут оформить подписку заново… Поэтому я применил «destroy_all» к объекту Customer… и это сработало! Но, конечно, только для этого пользователя..

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

Теперь дело сводится только к диагностике того, почему вебхук Stripe для отмененных подписок не работает.