贝宝经常性宝石和试用期

Posted

技术标签:

【中文标题】贝宝经常性宝石和试用期【英文标题】:paypal recurring gem & trial period 【发布时间】:2012-09-30 16:48:23 【问题描述】:

我按照 Rails Casts EP289 实施了 paypal 循环。 http://railscasts.com/episodes/289-paypal-recurring-billing?view=asciicast

正常流程可以正常工作,但是当我尝试实施试用期时,我遇到了一些问题。它在第一次计费时收取试用金额和循环计费金额的总和。 (我只想收取试用费)

我通过互联网进行了检查,但到目前为止我无法弄清楚如何做到这一点。 正确实施这一点我缺少什么?

下面是代码。

paypal_payment.rb

class PaypalPayment
  def initialize(subscription)
    @subscription = subscription
    @price = Price.find_by_currency_code_and_plan_id("JPY", @subscription.plan.id)
  end

  def checkout_details
    PayPal::Recurring.new(token: @subscription.paypal_payment_token).checkout_details
  end

  def checkout_url(options)
    process(:checkout, options).checkout_url
  end

  def make_recurring
    process :request_payment
    process :create_recurring_profile, period: :monthly, frequency: 1, start_at: Time.now + 1.month
  end

private

  def process(action, options = )
    options = options.reverse_merge(
      token: @subscription.paypal_payment_token,
      payer_id: @subscription.paypal_customer_token,
      item_name: @subscription.plan.name,
      item_amount: @price.amount.to_i,
      description: "Something"
      amount: @price.amount.to_i,
      outstanding: :next_billing,
      trial_amount: @price.initial_amount.to_i,
      trial_period: :monthly,
      trial_frequency: 1,
      trial_length: 1,
      currency: @price.currency_code,
      locale: "ja_JP"
    )
    response = PayPal::Recurring.new(options).send(action)
    raise response.errors.inspect if response.errors.present?
    response
  end
end

订阅.rb

class Subscription < ActiveRecord::Base
  belongs_to :plan
  belongs_to :student
  has_many :transactions, :class_name => "SubscriptionTransaction"
  validates_presence_of :plan_id
  validates_presence_of :student_id
  attr_accessor :paypal_payment_token
  attr_accessible :paypal_customer_token, :paypal_recurring_profile_token, :plan_id, :student_id, :paypal_payment_token

  def save_with_payment
    if valid?
      if payment_provided?
        save_with_paypal_payment
      end
    end
  end

  def paypal
    PaypalPayment.new(self)
  end

  def save_with_paypal_payment
    response = paypal.make_recurring
    self.paypal_recurring_profile_token = response.profile_id
    save!
  end

  def payment_provided?
    paypal_payment_token.present?
  end
end

subscriptions_controller.rb

require 'time'
class SubscriptionsController < ApplicationController
  before_filter :authenticate_user!, :is_student?

  def index
    @title = I18n.t "subscriptions.index.title"
    @student = Student.find_by_id(current_user.profile_id)
    if @student.is_trial == true
      redirect_to 'new'
    end
    @subscription = @student.subscription
    @plan = @subscription.plan
    Time.zone = "Tokyo"
    @date = Time.now.in_time_zone.to_date
    @total_lesson_times = Lesson.find_all_by_student_id(@student.id).size
    @lastm_lesson_times = Lesson.where("student_id = :student_id AND lesson_day >= :start_date AND lesson_day <= :end_date",
      :student_id => @student.id, :start_date => @date.beginning_of_month()-1.month, :end_date => @date.end_of_month()-1.month).size

    @thism_lesson_times = Lesson.where("student_id = :student_id AND lesson_day >= :start_date AND lesson_day <= :end_date",
        :student_id => @student.id, :start_date => @date.beginning_of_month(), :end_date => @date.end_of_month()).size
  end

  def new
    @title = I18n.t "subscriptions.new.title"
    @plans = Plan.all
    @student = Student.find_by_id(current_user.profile_id)
    if @student.is_trial == false && @student.is_active == false
      redirect_to 'index'
    end
    @subscription = Subscription.new
    @date = Time.now.in_time_zone.to_date
    @total_lesson_times = Lesson.find_all_by_student_id(@student.id).size
    @lastm_lesson_times = Lesson.where("student_id = :student_id AND lesson_day >= :start_date AND lesson_day <= :end_date",
      :student_id => @student.id, :start_date => @date.beginning_of_month()-1.month, :end_date => @date.end_of_month()-1.month).size

    @thism_lesson_times = Lesson.where("student_id = :student_id AND lesson_day >= :start_date AND lesson_day <= :end_date",
        :student_id => @student.id, :start_date => @date.beginning_of_month(), :end_date => @date.end_of_month()).size
  end

  def modify

  end

  def cancel
    student = Student.find(current_user.profile_id)
    @subscription = student.subscription
    ppr = PayPal::Recurring.new(:profile_id => @subscription.paypal_recurring_profile_token)
    response = ppr.suspend
    if response.success?
      student.update_attributes(:is_active => false)
      flash[:notice] = I18n.t "subscriptions.cancel.notice_flash"
      redirect_to root_path
    end
  end

  def reactivate
    student = Student.find_by_id(current_user.profile_id)
    @subscription = student.subscription
    ppr = PayPal::Recurring.new(:profile_id => @subscription.paypal_recurring_profile_token)
    response = ppr.reactivate
    if response.success?
      student.update_attributes(:is_active => true)
      flash[:success] = I18n.t "subscriptions.reactivate.success_flash"
      redirect_to root_path
    end
  end

  def paypal_checkout
    plan = Plan.find(params[:plan_id])
    student = Student.find(current_user.profile_id)
    subscription = plan.subscriptions.build
    redirect_to subscription.paypal.checkout_url(
      return_url: subscriptions_confirm_url(:plan_id => plan.id),
      cancel_url: new_subscription_url
    )
  end  

  def confirm
    @plan = Plan.find(params[:plan_id])
    @student = Student.find(current_user.profile_id)
    @subscription = @plan.subscriptions.build
    if params[:PayerID]
      @subscription.student_id = @student.id
      @subscription.paypal_customer_token = params[:PayerID]
      @subscription.paypal_payment_token = params[:token]
    end
  end

  def complete
    student = Student.find(current_user.profile_id)
    Time.zone = student.user.time_zone
    current_time = Time.now.in_time_zone
    current_date = current_time.to_date
    @subscription = Subscription.new(
      :plan_id => params[:subscription][:plan_id],
      :student_id => params[:subscription][:student_id],
      :paypal_customer_token => params[:subscription][:paypal_customer_token],
      :paypal_payment_token => params[:subscription][:paypal_payment_token]
    )
    if @subscription.save_with_payment
      student.update_attributes(:is_active => true, :is_trial => false, :expiration_date => current_date + 1.month - 1.day)
      redirect_to root_path, :notice => (I18n.t "subscriptions.complete.success_flash")
    else
      flash[:notice] = I18n.t "error_flash"
      redirect_to new_subscription_path
    end
  end

  private
  def is_student?
    if current_user.profile_type != "Student"
      flash[:notice] = I18n.t "is_student_notice_flash"
      redirect_to root_path
    end
  end
end

【问题讨论】:

您是否尝试过在选项中设置 start_at 是否会产生影响? 我尝试了 start_at = Time.now 并得到了结果,现在尝试 start_at = Time.now + 1.month。似乎所有交易都将在 1 个月后开始,即使支付试用期。 我自己解决了这个问题,谢谢你的评论。 为什么不分享解决方案?我和其他人会发现它很有用 我在问题顶部添加了答案。 【参考方案1】:

(在问题编辑中回答。转换为社区 wiki 答案。参见What is the appropriate action when the answer to a question is added to the question itself?)

OP 写道:

我自己解决了这个问题。问题出在paypal_payment.rb

  def make_recurring
    process :request_payment
    process :create_recurring_profile, period: :monthly, frequency: 1, start_at: Time.now + 1.month
  end

因为process :request_payment 部分。除了定期付款的费用外,它还会向用户收取费用。

【讨论】:

以上是关于贝宝经常性宝石和试用期的主要内容,如果未能解决你的问题,请参考以下文章

贝宝试用定期付款未开始

如何将贝宝经常性宝石与 Spree 集成

使用贝宝定期计费提供免费订阅时间(非试用)

贝宝定期付款和贝宝专业版

Paypal 经常性:立即收取试用金额?

前八个月的 Paypal 定期资料费用试用金额