Показать подписку пользователя как отмененную после расчетного периода
Я использую Stripe для своих подписок, и я установил его так, что, когда пользователь отменяет свою подписку (чтобы отключить автоматическое продление), он сохраняет подписку активной до конца биллингового периода в Stripe.
Действие работает через Stripe, но как я могу настроить так, чтобы cancelled
колонка в моей базе данных оказывает такое же влияние? В настоящее время, если пользователь нажимает на ссылку отмены подписки, он помечает их cancelled
столбец к 1
, Я бы хотел, чтобы он не помечался как отмененный до конца расчетного периода, чтобы пользователь мог продолжать иметь доступ к веб-сайту до последнего расчетного дня (у меня включен autorenwal)
Я прочитал предложение txdavidtx. То, что он предлагает, помечает всех пользователей как отмененных в конце их платежного периода. Этот метод не соответствовал бы тому, чего я хочу достичь.
У меня подписки настроены на автообновление. Мне нужен cancel
созданное действие, которое только отметит current_user
как отменено в конце их расчетного периода.
Например:
Пользователь A подписывается на ежемесячную подписку 27 сентября. Пользователь A решает 15 декабря, что он хочет отменить свою подписку. У пользователя А еще осталось 12 дней в подписке. Пользователь А нажимает на cancel
ссылка на сайт. У пользователя A автоматическое продление и подписка отменена в его учетной записи PayPal или Stripe. Внутри моей базы данных их cancelled
Значение атрибута не изменится до тех пор, пока эти 12 дней не закончатся (27 декабря).
Если кто-то может помочь, это было бы здорово.
Контроллер подписок:
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
5 ответов
Я думаю, что самый простой способ - это использовать полосовые веб-зацепки, где, как только заканчивается подписка, полоса будет пинговать вашу систему с событием customer.subscription.deleted, и в этот момент вам нужно просто отменить подписку пользователя.
Настройка действительно проста.
- Вы просто заходите на страницу настроек и добавляете URL-адрес веб-крючка, и полоса начинает отправлять вам системные события.
- Затем создайте контроллер событий полосы, который будет анализировать события полосы в серверной части.
Определите пользователя и отмените его подписку с параметром at_period_end true
customer = Stripe:: Customer.retrieve ("cus_3R1W8PG2DmsmM9") customer.subscription.retrieve("sub_3R3PlB2YlJe84a").delete(:at_period_end => true
Событие customer.subscription.updated немедленно запускается, если вместо этого вы отменяете подписку в конце расчетного периода, отражая изменение значения cancel_at_period_end подписки. Когда подписка фактически отменяется в конце периода, происходит событие customer.subscription.deleted. Полоса док
4- Затем настройте контроллер обратного вызова и определите, что подписка удалена.
<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
конец
проблема
Вам необходимо обновить отмененный столбец вашего пользователя в конце пробного периода, а не в тот момент, когда он фактически отменит его.
Решение
Kimooz почти был прав. Вы собираетесь использовать Stripe Webhook, и я объясню, что вам нужно сделать, чтобы добиться того, чего вы хотите.
Во-первых, если я правильно понимаю, вы хотите подражать тому, что происходит в Stripe. По сути, вы хотите, чтобы столбец отмененных баз данных оставался ложным для пользователя до тех пор, пока срок его действия не истечет. Это означает, что если пользователь нажимает кнопку "Отмена", в отмененном столбце ничего не изменится, пока не истечет ВСЕ время, после чего оно должно быть установлено в значение "истина".
Поэтому отмените учетную запись пользователя с помощью Stripe, как обычно, когда пользователь нажимает кнопку "Отмена". Единственное, что отличается от ваших пользователей Stripe::Subscription объект на этом этапе, это то, что свойство cancel_at_period_end
получает значение true. subscription.status
собственность остается active
пока все время не истекло. Ваша пользовательская запись остается неизменной, пока ВСЕ время не истекло.
Затем настройте Stripe Controller для работы с веб-крючками. Может показаться, что пройти через этот процесс - боль, но это правильный способ достижения решения.
ВАЖНЫЙ
Вам нужно разобрать веб-хуки в этот момент для customer.subscription.updated
событие НЕ customer.subscription.deleted
событие. Stripe обновит подписку только ваших клиентов.
Stripe не удалит подписку ваших клиентов, если вы отмените ее
... он только обновит статус подписки, если вы отмените ее. Это означает, что подписка и связанная с ней информация остаются в Stripe, и она по-прежнему принадлежит вашему пользователю, если он будет продлевать ее позже.
Итак, скажем, ваш пользователь отменяет подписку 15 декабря, но его подписка заканчивается 31 декабря. Stripe отправит два события вашему webhook.
15 декабря: это событие будет
customer.subscription.updated
событие, которое скажет вам, чтоcancel_at_period_end
свойство было обновлено доtrue
, (status
собственность остается неизменной иactive
)31 декабря.: Это событие будет
customer.subscription.updated
событие, которое скажет вам, чтоstatus
свойство изменилось сactive
вcancelled
,
Когда второе событие отправлено на ваш Stripe Webhook, теперь вы можете проанализировать событие и изменить cancelled
статус в вашей собственной базе данных, так как все время истекло.
Я хотел бы предложить одну из двух вещей.
Первый вариант:
Добавьте атрибут:cancellation_date, затем создайте вспомогательный метод в контроллере приложения, который проверяет дату отмены при входе в систему. Если они превышают дату окончания подписки, установите для вашей подписки: 1 значение "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
Второй вариант:
Используйте фоновое задание, такое как sucker_punch или sidekiq, чтобы запускать каждое утро и установите истекшие подписки на "1".
Самым простым решением для этого является метод проверки того, есть ли у пользователя доступ, проверить, не наступит ли следующая повторяющаяся дата.
Это позволяет вам пометить canceled
как 1
мгновенно.
Плохое планирование ИМО:
Кажется, ваша подписка основана на оставшихся днях. Так что вам просто нужно убедиться, что оставшиеся дни не равны 0 при запросе user_is_subscripted.
current_user.subscription_expired?
def subscription_expired?
days == 0
end
Создайте столбец: дни подписки, и каждый раз, когда ваш пользователь продлевает подписку, добавляйте к счету 30 дней. Каждый день запускайте скрипт, который сокращает день подписки в этом столбце на 1. Таким образом, вам не нужно учитывать даты.
Также:
if subscription_expired? and autorenewal?
renew_subscription(days)
end
def renew_subscription(days)
#paypal magic
current_user.subscription_days += days
end
И при запросе срока годности:
def expiration_day
Time.now + current_user.subscription_days.days
end