将每月推荐折扣应用于订阅费

时间:2015-10-22 21:13:16

标签: ruby-on-rails scheduled-tasks subscription webhooks chargify

功能说明:
所以我有一个基于订阅的网站,有两个计划:每月和每年。每月订阅按月收取月费,而每年订阅则收取每年10个月的一次性累积费用。 (29美元/月和290美元/年)

对于每个被推荐的活跃会员(最多100%),我每个月都有10%的定期推荐折扣。因此,如果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每个月都不会发送Plan个网络挂钩,这意味着不能每次扣除10%的Bob订阅费用。这个年度用户的有效推荐月份。

我想把Bob的计划价格设定为比标准价格低10%,而不是每个月调整余额。但是,这需要9个不同的计划,因为计划价格直接引用Chargify上的price对象,该对象指向其90%_monthly_plan属性。这意味着需要80%_monthly_plan# 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 等等,这些都存在于Chargify服务器上。这看起来过于复杂,如果引起其他问题,我也不会感到惊讶。我现在甚至没有考虑过。

我目前的(不满意的)解决方案:
因此,我决定只在我的服务器上创建一个调度程序,该调度程序在每年用户注册时创建,并且每个月都会触发。

我正在使用rufus-scheduler。需要注意的一件重要事项 - 重新启动服务器时会破坏计划,因此我创建了计划记录,初始化程序会遍历这些记录,并在每次服务器重新启动时创建这些计划。

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

初始化程序:

public function report(\Exception $e)
{
    if ($e instanceof \Exception) {

        $debugSetting = Config::get('app.debug');

        Config::set('app.debug', true);
        if (ExceptionHandler::isHttpException($e)) {
            $content = ExceptionHandler::toIlluminateResponse(ExceptionHandler::renderHttpException($e), $e);
        } else {
            $content = ExceptionHandler::toIlluminateResponse(ExceptionHandler::convertExceptionToResponse($e), $e);
        }

        Config::set('app.debug', $debugSetting);

        $data['content'] = (!isset($content->original)) ? $e->getMessage() : $content->original;

        Mail::queue('errors.emails.error', $data, function ($m) {
            $m->to('email@email.com', 'Server Message')->subject('Error');
        });
    }

    return parent::report($e);
}

我真的很讨厌使用这种方法,因为它看起来不是很干净。当我试图以较短的间隔运行它时,它已经搞砸了我的本地服务器。

我还考虑过使用rake任务和/或Grunt来执行此操作,但我对这些内容的知识非常有限,而且我不确定它们是否一定是更容易/更好的解决方案。

有什么想法吗?

1 个答案:

答案 0 :(得分:0)

一种选择可能是使用Bob的订阅上的upcoming_renewal_notice webhook作为触发器来查看他在年度计划中提出的推荐数量,并应用任何其他折扣。

https://docs.chargify.com/webhooks upcoming_renewal_notice - 订阅设置为在​​3天内续订