Show user subscription as cancelled after billing period

匿名 (未验证) 提交于 2019-12-03 10:24:21

问题:

I am using Stripe for my subscriptions and I have it set so when a user cancels their subscription (to turn off automatic renewal) it will keep the subscription active until the end of the billing period on Stripe.

The action works via Stripe, but how can I setup so that the cancelled column in my database takes the same affect? Currently if the user clicks on the cancel subscription link it will mark their cancelled column to 1. I would like for it to not mark as cancelled until the end of their billing period so the user can continue have access to the website until their final billing day (I have autorenwal turned on)

I have read txdavidtx suggestion. What he suggests would mark all Users as cancelled at the end of their billing period. That method would not fit with what I am looking to accomplish.

I have subscriptions set to autorenew. I would need a cancel action created that would only mark the current_user as cancelled at the end of their billing period.

For example:

User A signs up for the monthly subscription on September 27. User A decides on December 15 they want to cancel their subscription. User A still has 12 days left in their subscription. User A clicks on the cancel link. User A has autorenew and subscription cancelled in their PayPal or Stripe account. Inside my database their cancelled attribute value will not change until those 12 days have finished (December 27).

If someone can assist that would be great.

Subscriptions controller:

  def new     plan = Plan.find(params[:plan_id])     @subscription = plan.subscriptions.build     render layout: 'new_application'     if params[:PayerID]       @subscription.paypal_customer_token = params[:PayerID]       @subscription.paypal_payment_token = params[:token]       @subscription.email = @subscription.paypal.checkout_details.email     end   end    def create     @subscription = Subscription.new(params[:subscription])     if @subscription.save_with_payment       redirect_to @subscription, :notice => "Thank you for subscribing!"     else       render :new     end   end    def show     @subscription = Subscription.find(params[:id])     render layout: 'new_application'   end    def paypal_checkout     plan = Plan.find(params[:plan_id])     subscription = plan.subscriptions.build     redirect_to subscription.paypal.checkout_url(       return_url: new_subscription_url(:plan_id => plan.id),       cancel_url: root_url     )   end      def updatesubscription       @user = current_user       @customer = Stripe::Customer.retrieve(@user.subscription.stripe_customer_token)       if @user.subscription.plan_id == 12       @customer.update_subscription(:plan => "1", :prorate => true)       current_user.subscription.update_attributes(:plan_id => 1)       flash.alert = 'Your subscription has been changed to monthly!'       redirect_to root_url     elsif @user.subscription.plan_id == 1       @customer.update_subscription(:plan => "12", :prorate => true)       current_user.subscription.update_attributes(:plan_id => 12)      current_user.save!       flash.alert = 'Your subscription has been changed to annually!'       redirect_to root_url     end      end       def cancelsubscription        @user = current_user          @customer = Stripe::Customer.retrieve(@user.subscription.stripe_customer_token)          @customer.cancel_subscription(:at_period_end => true)           current_user.subscription.update_attributes(:cancelled => 1)          current_user.save!          flash.alert = 'Your subscription has been cancelled successfully!'          redirect_to root_url        end         def showcard          @user = current_user          Stripe::Customer.retrieve(@user.subscription.stripe_customer_token).cards.all()        end             def suspend              @user = current_user              @user.subscription.suspend_paypal              current_user.subscription.update_attributes(:cancelled => 1)                flash.alert = 'Billing has been suspended!'                 redirect_to root_url            end             def reactivate              @user = current_user              @user.subscription.reactivate_paypal              current_user.subscription.update_attributes(:cancelled => nil)                flash.alert = 'Billing has been activated!'                 redirect_to root_url            end                  def edit_card                  @user = current_user                end                 def update_card                  @user = current_user                  card_info = {                    name:    params[:name],                    number:    params[:number],                    exp_month: params[:date][:month],                    exp_year:  params[:date][:year],                    cvc:       params[:cvc]                  }                  if @user.subscription.update_card(@subscriber, card_info)                    flash.alert = 'Saved. Your card information has been updated.'                    redirect_to root_url                  else                    flash.alert = 'Stripe reported an error while updating your card. Please try again.'                    redirect_to root_url                  end                end end 

回答1:

I think the easiest way is to use stripe webhooks, where as soon as the subscription ends stripe will ping your system with a customer.subscription.deleted event and at that point you should just cancel the user subscription.

The setup is really easy.

  1. You just go to your settings page and add a webhook url and then stripe will start sending you system events.
  2. Then Create a stripe events controller which will parse stripe events in the backend.
  3. Detect the user and cancel his subscription with at_period_end params true

     customer = Stripe::Customer.retrieve("cus_3R1W8PG2DmsmM9") customer.subscriptions.retrieve("sub_3R3PlB2YlJe84a").delete(:at_period_end => true 

A customer.subscription.updated event is immediately triggered if you cancel a subscription at the end of the billing period instead, reflecting the change in the subscription’s cancel_at_period_end value. When the subscription is actually canceled at the end of the period, a customer.subscription.deleted event will occur. Stripe Doc

4- Then Setup your callback controller and detect subscription deleted

<pre> class StripeEventsController    skip_before_filter  :verify_authenticity_token    def catch     object = params[:data][:object]     case params[:type]     when "customer.subscription.deleted"      customer = object[:id]      user = User.find_by_stripe_id(customer)      user.subscription.update_attributes(cancelled: "1")     end   end 

end



回答2:

I would suggest one of two things.

First option:

Add a :cancellation_date attribute then create a helper method in your application controller that checks for the date of cancellation at sign in. If they're over their subscription end date, have your :subscription set itself to "1".

# application_controller.rb def my_helper   if current_user.has_cancelled?     redirect_to registration_path   end end  # user.rb although better to have the subscription do it instead def has_cancelled?   if cancellation_date.present? && cancellation_date > (paid_on + 30)     subscription.update_attributes(cancelled: "1")     return true   else     return false   end end 

Second option:

Use a background job like sucker_punch or sidekiq to run every morning and set expired subscriptions to "1".



回答3:

Bad planning IMO:

Your subscription seems to be based on days remaining. So you just need to ensure that days remaining are not 0 when asking for user_is_subscripted.

current_user.subscription_expired?  def subscription_expired?   days == 0 end 

Create a column: subscription days, and each time your user renews the subscription, add 30 days to the count. Each day run a script that reduces the subscription day in that column by 1. This way you don't need to take in account dates.

Also:

if subscription_expired? and autorenewal?   renew_subscription(days) end  def renew_subscription(days)   #paypal magic   current_user.subscription_days += days end 

And when asking for expiration day:

 def expiration_day    Time.now + current_user.subscription_days.days  end 


回答4:

Problem

You need to updated the cancelled column of your user at then end of their trial- not when they actually cancel it.

Solution

Kimooz almost had it right. You're going to use a Stripe Webhook and I'll explain what you need to do in order to achieve what you want.

First, if I understand correctly you want to mimic what happens in Stripe. Basically, you want your database cancelled column to remain false on the user until the user has expired all their time. This means if your user clicks 'Cancel', nothing changes in cancelled column until ALL time has expired, at which point it should then be set to true.

So, cancel your users account with Stripe like you normally would when the user clicks cancel. The only thing different about your users Stripe::Subscription object at this point is that the property cancel_at_period_end gets set to true. The subscription.status property remains active until all the time has expired. Your user record remains the same until ALL time has expired.

Then, set up a Stripe Controller to handle the webhooks. It may seem like a pain to go through this process but this is the proper way to achieve the solution.

IMPORTANT

You need to parse the webhooks at this point for the customer.subscription.updated event NOT the customer.subscription.deleted event. Stripe will only update your customers subscription.

Stripe will not delete your customers subscription if you cancel it

... it will only update the status of the subscription if you cancel it. This means the subscription and the information associated it remains persisted with Stripe and it still belongs to your user if they were to renew it later.

Okay, so.. say your user cancels on Dec. 15, but their subscription ends Dec. 31. Stripe will send two events to your webhook.

  • Dec. 15: This event will be a customer.subscription.updated event that will tell you that cancel_at_period_end property has been updated to true. (the status property remains unchanged and active)

  • Dec. 31.: This event will be a customer.subscription.updated event that will tell you that the status property has changed from active to cancelled.

When the second event is sent your Stripe Webhook, you now can parse the event and change the cancelled status in your own database since all time has expired.



回答5:

The easiest solution to this is, for the method to check if the user still has access, check that the next recurring date is in the future.

This allows you to mark canceled as 1 instantly.



标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!