diff --git a/app/controllers/spree/paypal_controller.rb b/app/controllers/spree/paypal_controller.rb index 04cb987bc2..0b44ce3763 100644 --- a/app/controllers/spree/paypal_controller.rb +++ b/app/controllers/spree/paypal_controller.rb @@ -40,7 +40,10 @@ module Spree items.reject! do |item| item[:Amount][:value].zero? end - pp_request = provider.build_set_express_checkout(express_checkout_request_details(order, items)) + + pp_request = provider.build_set_express_checkout( + express_checkout_request_details(order, items) + ) begin pp_response = provider.set_express_checkout(pp_request) @@ -66,14 +69,14 @@ module Spree # last chance to interact with the payment process before the money moves... return reset_to_cart unless sufficient_stock? - @order.payments.create!({ - source: Spree::PaypalExpressCheckout.create({ + @order.payments.create!( + source: Spree::PaypalExpressCheckout.create( token: params[:token], payer_id: params[:PayerID] - }), + ), amount: @order.total, payment_method: payment_method - }) + ) @order.next if @order.complete? flash.notice = Spree.t(:order_processed_successfully) @@ -106,8 +109,8 @@ module Spree Number: item.variant.sku, Quantity: item.quantity, Amount: { - currencyID: item.order.currency, - value: item.price + currencyID: item.order.currency, + value: item.price }, ItemCategory: "Physical" } @@ -140,12 +143,11 @@ module Spree end def reset_order_when_complete - if current_order.complete? - flash[:notice] = t(:order_processed_successfully) + return unless current_order.complete? - OrderCompletionReset.new(self, current_order).call - session[:access_token] = current_order.token - end + flash[:notice] = t(:order_processed_successfully) + OrderCompletionReset.new(self, current_order).call + session[:access_token] = current_order.token end def reset_to_cart @@ -174,7 +176,7 @@ module Spree payment_method.provider end - def payment_details items + def payment_details(items) item_sum = items.sum { |i| i[:Quantity] * i[:Amount][:value] } # Would use tax_total here, but it can include "included" taxes as well. # For instance, tax_total would include the 10% GST in Australian stores. diff --git a/app/models/spree/gateway/pay_pal_express.rb b/app/models/spree/gateway/pay_pal_express.rb index 0cb4d38150..357d563264 100644 --- a/app/models/spree/gateway/pay_pal_express.rb +++ b/app/models/spree/gateway/pay_pal_express.rb @@ -1,106 +1,114 @@ +# frozen_string_literal: true + require 'paypal-sdk-merchant' + module Spree - class Gateway::PayPalExpress < Gateway - preference :login, :string - preference :password, :password - preference :signature, :string - preference :server, :string, default: 'sandbox' - preference :solution, :string, default: 'Mark' - preference :landing_page, :string, default: 'Billing' - preference :logourl, :string, default: '' + class Gateway + class PayPalExpress < Gateway + preference :login, :string + preference :password, :password + preference :signature, :string + preference :server, :string, default: 'sandbox' + preference :solution, :string, default: 'Mark' + preference :landing_page, :string, default: 'Billing' + preference :logourl, :string, default: '' - def supports?(source) - true - end - - def provider_class - ::PayPal::SDK::Merchant::API - end - - def provider - ::PayPal::SDK.configure( - :mode => preferred_server.present? ? preferred_server : "sandbox", - :username => preferred_login, - :password => preferred_password, - :signature => preferred_signature) - provider_class.new - end - - def auto_capture? - true - end - - def method_type - 'paypal' - end - - def purchase(amount, express_checkout, gateway_options={}) - pp_details_request = provider.build_get_express_checkout_details({ - :Token => express_checkout.token - }) - pp_details_response = provider.get_express_checkout_details(pp_details_request) - - pp_request = provider.build_do_express_checkout_payment({ - :DoExpressCheckoutPaymentRequestDetails => { - :PaymentAction => "Sale", - :Token => express_checkout.token, - :PayerID => express_checkout.payer_id, - :PaymentDetails => pp_details_response.get_express_checkout_details_response_details.PaymentDetails - } - }) - - pp_response = provider.do_express_checkout_payment(pp_request) - if pp_response.success? - # We need to store the transaction id for the future. - # This is mainly so we can use it later on to refund the payment if the user wishes. - transaction_id = pp_response.do_express_checkout_payment_response_details.payment_info.first.transaction_id - express_checkout.update_column(:transaction_id, transaction_id) - # This is rather hackish, required for payment/processing handle_response code. - Class.new do - def success?; true; end - def authorization; nil; end - end.new - else - class << pp_response - def to_s - errors.map(&:long_message).join(" ") - end - end - pp_response + def supports?(_source) + true end - end - def refund(payment, amount) - refund_type = payment.amount == amount.to_f ? "Full" : "Partial" - refund_transaction = provider.build_refund_transaction({ - :TransactionID => payment.source.transaction_id, - :RefundType => refund_type, - :Amount => { - :currencyID => payment.currency, - :value => amount }, - :RefundSource => "any" }) - refund_transaction_response = provider.refund_transaction(refund_transaction) - if refund_transaction_response.success? - payment.source.update_attributes({ - :refunded_at => Time.now, - :refund_transaction_id => refund_transaction_response.RefundTransactionID, - :state => "refunded", - :refund_type => refund_type - } ) + def provider_class + ::PayPal::SDK::Merchant::API + end - payment.class.create!( - :order => payment.order, - :source => payment, - :payment_method => payment.payment_method, - :amount => amount.to_f.abs * -1, - :response_code => refund_transaction_response.RefundTransactionID, - :state => 'completed' + def provider + ::PayPal::SDK.configure( + mode: preferred_server.presence || "sandbox", + username: preferred_login, + password: preferred_password, + signature: preferred_signature ) + provider_class.new + end + + def auto_capture? + true + end + + def method_type + 'paypal' + end + + def purchase(_amount, express_checkout, _gateway_options = {}) + pp_details_request = provider.build_get_express_checkout_details( + Token: express_checkout.token + ) + pp_details_response = provider.get_express_checkout_details(pp_details_request) + + pp_request = provider.build_do_express_checkout_payment( + DoExpressCheckoutPaymentRequestDetails: { + PaymentAction: "Sale", + Token: express_checkout.token, + PayerID: express_checkout.payer_id, + PaymentDetails: pp_details_response. + get_express_checkout_details_response_details.PaymentDetails + } + ) + + pp_response = provider.do_express_checkout_payment(pp_request) + if pp_response.success? + # We need to store the transaction id for the future. + # This is mainly so we can use it later on to refund the payment if the user wishes. + transaction_id = pp_response.do_express_checkout_payment_response_details. + payment_info.first.transaction_id + express_checkout.update_column(:transaction_id, transaction_id) + # This is rather hackish, required for payment/processing handle_response code. + Class.new do + def success?; true; end + + def authorization; nil; end + end.new + else + class << pp_response + def to_s + errors.map(&:long_message).join(" ") + end + end + pp_response + end + end + + def refund(payment, amount) + refund_type = payment.amount == amount.to_f ? "Full" : "Partial" + refund_transaction = provider.build_refund_transaction( + TransactionID: payment.source.transaction_id, + RefundType: refund_type, + Amount: { + currencyID: payment.currency, + value: amount + }, + RefundSource: "any" + ) + refund_transaction_response = provider.refund_transaction(refund_transaction) + if refund_transaction_response.success? + payment.source.update_attributes( + refunded_at: Time.now, + refund_transaction_id: refund_transaction_response.RefundTransactionID, + state: "refunded", + refund_type: refund_type + ) + + payment.class.create!( + order: payment.order, + source: payment, + payment_method: payment.payment_method, + amount: amount.to_f.abs * -1, + response_code: refund_transaction_response.RefundTransactionID, + state: 'completed' + ) + end + refund_transaction_response end - refund_transaction_response end end end - -# payment.state = 'completed' -# current_order.state = 'complete'