简体   繁体   中英

Ruby on Rails Paypal REST API guest checkout

I'm trying to debug a Rails app from another developer. Keep in mind that I have very little experience with both Ruby and Rails. The goal is to allow users to pay with they credit card when they go to the PayPal payment page without the need to do registration.

The actual code in model/shopping-card.rb is:

include PayPal::SDK::REST

class ShoppingCart
  def initialize(session)
    @session = session
    @session["delivery"] ||= "shipping"
    @session[:coupon] ||= {"token" => nil, "discount" => nil}
    @session[:shopping_cart] ||= []
  end

  def delivery=(v)
    @session["delivery"] = v
  end

  def delivery
    @session["delivery"]
  end

  def should_add_shipping_costs?
    @session["delivery"] == "shipping"
  end

  def cart
    @session[:shopping_cart]
  end

  def discount
    val = @session["coupon"]["discount"]
    if val.nil?
      nil
    else
      val.to_f
    end
  end

  def token
    @session["coupon"]["token"]
  end

  def coupon=(c)
    @session["coupon"]["token"] = c.try("token")
    @session["coupon"]["discount"] = c.try("discount")
  end

  def subtotal_discount
    subtotal.to_f / 100 * discount.to_f
  end

  def subtotal_after_discount
    [(subtotal.to_f - subtotal_discount), 0].max
  end

  def subtotal_after_discount_with_vat
    subtotal_after_discount + subtotal_after_discount / 100 * 21
  end

  def add(product, quantity)
    quantity = quantity.to_i

    index = cart.find_index do |item|
      item["id"] == product.id
    end

    # Not in chart
    if index.nil?
     item = product.to_cart
     item[:quantity] = quantity
     cart << item
    else
      item = cart[index]
      item["quantity"] = item["quantity"].to_i + quantity
    end
  end

  def remove(id)
    cart.delete_if do |item|
      item["id"].to_s == id.to_s
    end
  end

  def clear
    cart.clear
  end

  def each(&block)
    cart.each(&block)
  end

  def each_with_index(&block)
    cart.each_with_index(&block)
  end

  def empty?
    cart.empty?
  end

  def to_paypal
    f = cart.map do |item|
      {
        name: item["name"],
        price: "%.2f" % item["price_or_promo"],
        quantity: item["quantity"],
        currency: "EUR",
      }
    end
    f
  end

  def subtotal
    amount = 0
    each do |item|
      amount += item["price_or_promo"].to_f * item["quantity"].to_i
    end
    "%.2f" % amount
  end

  def total_iva
    subtotal.to_f * 0.21
  end

  def total_for(user)
    t = subtotal_after_discount.to_f + total_iva + surcharge_for(user)
    if self.should_add_shipping_costs?
      t + shipping_cost
    else
      t
    end
  end


  def surcharge_for(user)
    user.surcharge ? subtotal.to_f * 0.052 : 0
  end

  def shipping_cost
    total = 0
    each do |item|
      total += (item['shipping'].to_f * item['quantity'].to_i)
    end
    total
  end

  def create_payment(description, user)
    payment = Payment.new({
      :intent => :sale,
      :payer => {
        :payment_method => :paypal
      },

      :redirect_urls => {
        :return_url => ENV['PAYPAL_RETURN_URL'],
        :cancel_url => ENV['PAYPAL_CANCEL_URL']
      },

      :transactions => [{
        :item_list => {
          :items => {
            :name => description,
            :price => "%.2f" % total_for(user),
            :quantity => 1,
            :currency => "EUR"
          }
        },

        :amount => {
          :total => "%.2f" % total_for(user),
          :currency => "EUR"
        },


        :description => description
      }],
    })

    if payment.create
      @session[:payment_id] = payment.id
    end

    payment
  end

  def build_order
    order = Order.new(user_id: @session[:user_id])
    each do |item|
      order.operations << Operation.new(
        product_id: item["id"],
        quantity: item["quantity"].to_i
      )
    end

    order
  end

  def complete_payment(params)
    payment = Payment.find(@session[:payment_id])
    if payment.execute(payer_id: params[:PayerID])
      build_order.save!
      @session[:payment] = nil
      @session[:coupon] = nil
      clear
    end

    if(coupon = Coupon.find_by(token: token))
      coupon.used = true
      coupon.save!
    end
    payment
  end

end

and in controllers/payment-controller.rb

include PayPal::SDK::REST

class PaymentsController < ApplicationController
  def checkout
    @payment = shopping_cart.create_payment("Cultius Purchase", current_user)
    if @payment.success?
      redirect_to @payment.links.find{|v| v.method == "REDIRECT" }.href
    else
      logger.error "Error while creating payment:"
      logger.error @payment.error.inspect
    end
  end

  def success
    shopping_cart.complete_payment(params)
  end
end

So finally, speaking with PP the credit card option hast to be enabled checking an option on your PP account settings. Even do this option is only for 'elegible buyers'.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM