구독을 취소한 후 사용자가 구독 상품을 재구매할 수 없습니다

구독자 관련해서 좀 특이한 문제가 생겼습니다.

Billing(결제) 섹션에 활성 구독이 없는데;

Stripe에서는 취소된 상태로 표시되고;

image

그런데 다시 구독을 신청하면 이미 구매한 항목이라고 합니다;

image

제가 무언가를 잘못 설정한 건가요?

웹훅 엔드포인트가 올바르게 구성되지 않은 것 같습니다. 구독 기간이 종료되면 Stripe가 웹훅을 보내고, 플러그인은 이를 사용하여 그룹 멤버십을 제거하고 해당 제품에서 기존 고객으로 등록된 사용자를 해제합니다(이렇게 하면 사용자가 다시 구매할 수 있습니다).

아래 OP(원문 게시글)에서 안내한 대로 설정이 제대로 되어 있는지 확인해야 합니다: 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.count를 실행하여 subscription에 값이 하나만 있는지 확인하십시오. 반환된 값이 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 으로 나와 있습니다. 그런데 이 유형은 제 웹훅 이벤트 목록에 나열되어 있지 않다는 점을 발견했습니다.

위 사항이 문제의 원인일 수 있을까요?

해당 줄은 ::Customer 대신 DiscourseSubscriptions::Subscription이어야 할 것 같습니다. 그렇게 수정해 보시고 어떤 결과가 나오는지 확인해 보세요!

[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: #DiscourseSubscriptions::Subscription::ActiveRecord_Relation:0x000055ec51164ca0의 customer_id' 메서드가 정의되지 않았습니다 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’

죄송합니다. 어디서 문제가 발생했는지 잘못 이해했습니다.

대신 이렇게 시도해 보세요:

./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 Subscriptions → Subscriptions 영역에서 해당 사용자의 사용자 이름을 찾을 수도 있습니다. 만약 해당 사용자의 구독이 목록에 표시되어 있다면, 즉시 취소할 수 있습니다.

Discourse 인스턴스에 대해 더 자세히 살펴볼 수 없는 한, 더 이상 도움을 드리기 어렵습니다.

네, 플러그인 영역의 구독에서 비활성 상태이고, Stripe에서도 비활성 상태입니다.. 아직 활성 상태임을 나타내는 유일한 것은 사용자가 구독 페이지에 접속하면 작은 초록색 “구입됨” 체크 표시와 "결제 관리로 이동"이 보이는 것입니다.

image

해당 사용자로 결제 관리 페이지에 들어가도 아무것도 나오지 않습니다;

따라서 제 질문은 - 데이터베이스에서 그 초록색 체크 표시를 트리거하는 것이 무엇이며, 삭제할 수 있는지입니다.

여기서 언급된 대로 이 목록에 Stripe 제품 ID가 포함되어 있다면:

프론트엔드에서는 해당 항목이 구매된 것으로 표시됩니다. 위치를 파악하려면 이러한 쿼리를 사용하여 콘솔을 살펴볼 필요가 있을 수 있습니다. 거의 확실하지만, 아직 해당 레코드가 어딘가에 남아 있을 것입니다.

자, 이 스레드를 다시 끄집어내는 게 될 줄은 몰랐는데, 1) 이 문제가 여전히 해결되지 않고 있고, 2) 다시 시간을 내어 살펴봤더니 결국 지시를 따르지 못하는 바보였다는 걸 알게 되었습니다. 제가 무지하다는 사실을 깨달은 과정과, 이제 (조금의 도움만 있다면) 이 문제를 해결할 준비가 된 이유를 공유합니다.

결국 저는 Stripe에서 모든 취소된 계정의 CSV를 내보냈습니다. 이 스레드에서 앞서 언급된 Discourse 사용자를 집중적으로 살펴봤는데, 이 사용자는 구독자였으나 구독을 취소했고, 이후 다시 구독하려고 했을 때 활성 구독 페이지에는 구독 내역이 없었음에도 구독 페이지에 "구독 완료(purchased)"라고 표시되어 다시 구독할 수 없었습니다. CSV 데이터에서 이 사용자의 기록은 "canceled"로 표시되어 있었고, 다음과 같은 데이터를 가지고 있었습니다.

  • id (sub_JNWejdDo4qhLG5)
  • customer_id (cus_JmiMoqZNTzUNxt)
  • user_id (discourse user id 4981)

이후 앱 컨테이너에 접속해 Ruby 콘솔로 들어가서 이것저것 확인해 봤습니다. 먼저 DiscourseSubscriptions::Customer에서 해당 고객의 ID를 검색했고, 찾아냈습니다.

[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 웹훅과 구독 플러그인 사이에 어딘가에서 연결이 끊겨 있는 것 같습니다. 다만 어디서, 어떻게 끊겨 있는지는 모르겠습니다.

  • 첫째; 특정 사용자의 구독 기록 데이터를 안전하게 삭제하는 방법은 무엇인가요? 마치 5살 아이에게 설명하듯 자세히 알려주세요. 저는 현재 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>]

이것은 여전히 녹색 체크 표시를 보고 있고 다시 구독할 수 없다는 뜻입니다. 그래서 Customer 객체에 "destroy_all"을 적용해 봤고, 성공했습니다! 물론 해당 사용자에게만 적용되었지만요.

[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 웹훅이 작동하지 않는 이유를 진단하는 것입니다.