功能描述:
所以我有一个基于订阅的网站,有两个计划:每月和每年。按月订阅每月收取月费,而按年订阅每年收取一次性累计10个月的费用。($29/月及$290/年)
对于每个被推荐的活跃会员,我每个月都有10%的重复推荐折扣(最多100%)。因此,如果Bob在10月份注册了每月订阅,并且在接下来的一个月里有5个人注册,那么他应该累计获得50%的折扣。这将适用于他11月份的订阅费,当月的订阅费为14.50美元。但假设他的一个推荐人在11月取消了。这将使他12月的折扣降低10%,这将使他获得40%的折扣,加上4个活跃的推荐,12月的折扣为17.40美元。
工作代码的例子:
如果Bob的每一个推荐都是每月一次,那么使用webhooks就相当简单了。如果连接到该付款的用户是Bob的推荐人之一,则每次成功付款时都会从Bob的当前余额中扣除一笔金额。
# Webhooks Controller
def payment_success
referred_user = User.find_by_customer_id(@subscription.customer.reference)
if referring_user = User.find_by_affiliate_code(referred_user.referral_code)
balance = referring_user.subscription.balance_in_cents
referring_user.subscription.adjustment({"amount_in_cents"=>"-290","memo"=>"Balance adjusted for referring #{referred_user.email}. Payment for referral was successful."})
referring_user.subscription.save
end
head :ok
end
这会向Chargify(我正在使用的支付处理器)发送一个请求,以相应地调整余额。
我真正的问题是:
但是,当Bob的推荐人之一是年度用户时,情况就不那么简单了。
由于年度订阅是一次性付款,payment_success
webhooks不是每个月都通过,这意味着Bob订阅的10%不能每月从该年度用户的活跃推荐中扣除。
我想让Bob的计划价格比标准价格低10%,而不是每个月调整余额。但是,这将需要9个不同的计划,因为计划价格直接引用Chargify上的Plan
对象,该对象指向其price
属性。这意味着需要一个90%_monthly_plan
、一个80%_monthly_plan
等等,它们都驻留在Chargify服务器上。这似乎过于复杂了,如果它引起了我现在甚至没有考虑到的其他问题,我也不会感到惊讶。
我当前的(不满意的)解决方案:
因此,我决定在服务器上创建一个调度器,该调度器是在年度用户注册时创建的,并且每个月触发一次。
我使用rufus-scheduler。需要注意的重要一点是——当服务器重新启动时,计划将被销毁,因此我创建了计划记录,并且每次服务器重新启动时,初始化器都会遍历这些记录并创建这些计划。
# modified Webhooks Controller
def payment_success
referred_user = User.find_by_customer_id(@subscription.customer.reference)
if referring_user = User.find_by_affiliate_code(referred_user.referral_code)
balance = referring_user.subscription.balance_in_cents
referring_user.subscription.adjustment({"amount_in_cents"=>"-290","memo"=>"Balance adjusted for referring #{referred_user.email}. Payment for referral was successful."})
referring_user.subscription.save
if @subscription.product.handle == 'yearly'
schedule = ReferralSchedule.create(
type_of: "yearly discount",
referred_user_id: referred_user.id,
referring_user_id: referring_user.id,
time_to_execute: "30.41d"
)
ReferralScheduler::create_yearly_discounts_schedule(schedule)
end
end
head :ok
end
和处理时间表创建的模块:
module ReferralScheduler
def self.create_yearly_discounts_schedule(schedule)
referred_user = User.find(schedule.referred_user_id)
referring_user = User.find(schedule.referring_user_id)
# first_date is calculated to be the first date in the future, that the scheduler should run.
first_date = Time.now + (30.41-(DateTime.now - schedule.created_at.to_datetime).fdiv(30.41)%1*30.41).days
scheduler = Rufus::Scheduler.new
scheduler.every schedule.time_to_execute, first: first_date , last_at: (schedule.created_at+12.months) do
if referring_user && referred_user.subscription_status == :active
balance = referring_user.subscription.balance_in_cents
referring_user.subscription.adjustment({"amount_in_cents"=>"-290","memo"=>"Balance adjusted for referring #{referred_user.email}. Referral is still active."})
referring_user.subscription.save
end
end
scheduler.at (schedule.created_at+12.months) do
schedule.destroy!
end
end
end
和初始化式:
require 'rufus-scheduler'
ReferralSchedule.where(type_of: "yearly discount").each do |schedule|
ReferralScheduler::create_yearly_discounts_schedule(schedule)
end
我真的很讨厌使用这种方法,因为它看起来不太干净。当我试图以更短的间隔运行它时,它也已经把我的本地服务器搞砸了。
我也考虑过使用rake任务和/或Grunt来执行这个任务,但是我对这些任务的了解非常有限,我不确定它们是否一定是更容易/更好的解决方案。
任何想法?
一种选择可能是使用Bob订阅的upcoming_renewal_notice
webhook作为触发器,查看他在年度计划中做了多少推荐,并应用任何额外的折扣。
https://docs.chargify.com/webhooksupcoming_renewal_notice
- 3天内续订的订阅集