2014-03-13 137 views
4

我期待为贝宝定期宝石设置付款暂停(按照钢轨投射)。我不确定是否需要设置IPN,因为在该文档中没有提及它。我目前的代码不采取任何行动。贝宝定期宝石 - 暂停付款

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

如果有人有时间资助我,这将是伟大的!

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

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?" } %> 

回答

5

这PaypalPayment是一种包装的贝宝经常性宝石。因此,此类中的所有方法都只是准备并委托给PayPal :: Recurring,这就是为什么所有方法都只是调用实例化和传递操作的'process'方法。

因此,暂停/取消您只需要为每个操作添加一个方法。正如文件指出,你需要做到这一点的取消

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

因此,对于你PaypalPayment类它是这样的:

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

所以你的模型subscription.rb

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

而且控制器susbcription_controller.rb

def suspend 
    current_user.suspend_paypal 
end 

关于IPN,如果用户通过您的网站暂停,我不认为它是必要的,但是由于用户可能通过PayPal直接取消它,您必须处理此情况,以便用户不停止付款,而是保持活动订阅。

+0

我在印象中应该在控制器中完成批量工作,但是您已经完成了模型中的大部分工作。这就是说我收到一个错误'[{:code =>“11551”,:messages => [“请求中缺少配置文件ID”,“请求中缺少配置文件ID”]}]'不识别来自'process:suspend,:profile_id => @ subscription.paypal_recurring_profile_token'行的id。我更新了我的代码。 –

+1

在栏杆中,他们有一句话叫“瘦瘦的控制器,胖胖的模特”,所以通常你需要模型上的大部分工作。关于错误,请确保您在订阅时拥有了profile_id,如果有,请尝试像下面这样调用:'ppr = PayPal :: Recurring.new(:profile_id =>“SOME_PROFILE_ID_HERE”); PPR。暂停“ – gabrielrios

+0

该问题是由于Stripe与PayPal的集成。配置文件ID未被识别,因为用户有一个订阅正在运行Stripe。一旦我删除它,错误消失。感谢所有的帮助! –