Paypal Recurring Gem - 暂停付款

Posted

技术标签:

【中文标题】Paypal Recurring Gem - 暂停付款【英文标题】:Paypal Recurring Gem - suspend payment 【发布时间】:2014-04-18 11:53:37 【问题描述】:

我希望为 paypal 经常性 gem 设置付款暂停(跟随轨道演员)。我不确定是否需要设置 IPN,因为 gem 的文档中没有提到它。我目前拥有的代码不执行任何操作。

我在模型中定义了取消重复,但我不确定如何完成代码,因为我很难理解这一切是如何工作的。其他人已经问过这个问题,但没有答案。

如果有人有时间为我提供资产,那就太好了!

问题是如何暂停/取消用户的定期付款。

Paypal_payment.rb:

   def initialize(subscription)
      @subscription = subscription
    end

    def checkout_details
      process :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.zone.now
    end

    def suspend
        process :suspend, :profile_id => @subscription.paypal_recurring_profile_token
    end

  private

    def process(action, options = )
      options = options.reverse_merge(
        token: @subscription.paypal_payment_token,
        payer_id: @subscription.paypal_customer_token,
        description: @subscription.plan.name,
        amount: @subscription.plan.price,
        currency: "USD"
      )
      response = PayPal::Recurring.new(options).send(action)
      raise response.errors.inspect if response.errors.present?
      response
    end
  end

订阅控制器:

  def new
    plan = Plan.find(params[:plan_id])
    @subscription = plan.subscriptions.build
    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])
  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)
      @customer.update_subscription(:plan => "1", :prorate => true)
     current_user.save!
      flash.alert = 'Your subscription has been updated!'
      redirect_to root_url
     end

     def cancelsubscription
       @user = current_user
         @customer = Stripe::Customer.retrieve(@user.subscription.stripe_customer_token)
         @customer.cancel_subscription()
         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 changecard
           @user = current_user       
           @customer = Stripe::Customer.retrieve(@user.subscription.stripe_customer_token)

             card = @customer.cards.create(
               :card => @user.subscription.stripe_customer_token
             )

             @customer.default_card = card
             @customer.save
           end

           def suspend
             @user = current_user
             @user.subscription.suspend_paypal
           end


         def updatebilling
             @user = current_user
             customer = Stripe::Customer.retrieve(@user.subscription.stripe_customer_token)
             customer.cards.retrieve("#@user.subscription.stripe_card_id").delete()
             customer.cards.create(
                   card: 
                   number: params[:user][:scardnumber],
                   exp_month: params[:user][:sexp_month],
                   exp_year: params[:user][:sexp_year],
                   cvc: params[:user][:scvc],
                   name: params[:user][:sname],
                   address_line1: params[:user][:sbilling_address1],
                   address_line2: params[:user][:sbilling_address2],
                   address_city: params[:user][:saddress_city],
                   address_zip: params[:user][:saddress_zip],
                   address_state: params[:user][:saddress_state],
                   address_country: params[:user][:saddress_country]
                   
                 )
                 if customer.save!
                   @user.stripe_card_id = customer.active_card.id
                   @user.save!
                   flash.alert = 'Billing information updated successfully!'
                   redirect_to root_url
                 else
                   flash.alert = 'Stripe error'
                   redirect_to root_url
                 end
               end
end

订阅模式:

  belongs_to :plan
  belongs_to :subscription
  belongs_to :user

  validates_presence_of :plan_id
  validates_presence_of :email

  attr_accessor :stripe_card_token, :paypal_payment_token

  def save_with_payment
    if valid?
      if paypal_payment_token.present?
        save_with_paypal_payment
      else
        save_with_stripe_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 save_with_stripe_payment
    customer = Stripe::Customer.create(description: email, plan: plan_id, card: stripe_card_token)
    self.stripe_customer_token = customer.id
    save!
  rescue Stripe::InvalidRequestError => e
    logger.error "Stripe error while creating customer: #e.message"
    errors.add :base, "There was a problem with your credit card."
    false
  end

  def payment_provided?
    stripe_card_token.present? || paypal_payment_token.present?
  end

  def suspend_paypal
    paypal.suspend
    self.status = "canceled"
    save
  end
end

路线:

  get "subscriptions/cancelsubscription"
  get "subscriptions/updatesubscription"
  get "subscriptions/changecard"
  get "subscriptions/suspend"
  get "subscriptions/updatebilling"

  resources :charges
  resources :subscriptions
  resources :plans
  get 'paypal/checkout', to: 'subscriptions#paypal_checkout'

查看:

<%= link_to "Suspend paypal", subscriptions_suspend_path, :data =>  :confirm => "Are you sure?"  %>

【问题讨论】:

【参考方案1】:

此 PaypalPayment 是 paypal-recurring gem 的一种包装。因此,此类中的所有方法都只是准备并委托给 PayPal::Recurring,这就是为什么所有方法都只是调用实例化并传递操作的“流程”方法。

因此,对于暂停/取消,您只需为每个操作添加一个方法。正如文档所述,您需要这样做才能取消

ppr = PayPal::Recurring.new(:profile_id => "I-VCEL6TRG35CU")
ppr.suspend

所以对于您的 PaypalPayment 类,它看起来像这样:

def suspend
    process :suspend, :profile_id => @subscription.paypal_recurring_profile_token
end

所以你的模型订阅.rb

def suspend_paypal
  paypal.suspend
  self.status = "canceled"
  save
end

还有控制器 susbcription_controller.rb

def suspend
  current_user.suspend_paypal
end

关于 IPN,如果用户通过您的网站暂停,我认为没有必要,但由于用户可能会直接通过贝宝取消它,您必须处理这种情况,以便用户不要停止支付,而是保持活跃订阅。

【讨论】:

我的印象是大部分工作应该在控制器中完成,但是你已经在模型中完成了大部分工作。话虽如此,我收到了一个错误[:code=&gt;"11551", :messages=&gt;["Profile Id is missing from the request", "Profile Id is missing from the request"]],所以它无法识别来自process :suspend, :profile_id =&gt; @subscription.paypal_recurring_profile_token 行的id。我更新了我的代码。 在 Rails 中他们有一句话“瘦控制器,胖模型”,所以通常你需要模型的大部分工作。关于错误,请确保您在订阅中拥有 profile_id,如果有,请尝试像这样直接调用:ppr = PayPal::Recurring.new(:profile_id =&gt; "SOME_PROFILE_ID_HERE"); ppr.suspend 问题是由于 Stripe 与 PayPal 的集成造成的。无法识别配置文件 ID,因为用户有一个使用 Stripe 运行的订阅。一旦我删除它,错误就会消失。感谢大家的帮助! 此外,我得到的唯一错误是 NoMethodError undefined method status='`。对于self.status = "canceled" 行。我会修复它并在此处发布解决方案,以帮助需要此帮助的其他人。 该状态行更多是关于如何定义订阅已取消的示例,因此只需添加此列即可解决此问题

以上是关于Paypal Recurring Gem - 暂停付款的主要内容,如果未能解决你的问题,请参考以下文章

recurring_select gem:jquery 在我的配置中不起作用

收款时Paypal Recurring Payment API CALL

Paypal recurring_payment_skipped 条件

Paypal Recurring Profile:如何每小时运行一次?

Paypal Recurring api 用于查找下一次定期付款

PayPal Payflow Recurring Billing:重新激活个人资料