diff --git a/app/controllers/spree/admin/payments_controller_decorator.rb b/app/controllers/spree/admin/payments_controller_decorator.rb deleted file mode 100644 index 04b9fc5..0000000 --- a/app/controllers/spree/admin/payments_controller_decorator.rb +++ /dev/null @@ -1,19 +0,0 @@ -Spree::Admin::PaymentsController.class_eval do - def paypal_refund - if request.get? - if @payment.source.state == 'refunded' - flash[:error] = Spree.t(:already_refunded, scope: 'paypal') - redirect_to admin_order_payment_path(@order, @payment) - end - elsif request.post? - response = @payment.payment_method.refund(@payment, params[:refund_amount]) - if response.success? - flash[:success] = Spree.t(:refund_successful, scope: 'paypal') - redirect_to admin_order_payments_path(@order) - else - flash.now[:error] = Spree.t(:refund_unsuccessful, scope: 'paypal') + " (#{response.errors.first.long_message})" - render - end - end - end -end \ No newline at end of file diff --git a/app/controllers/spree/admin/paypal_payments_controller.rb b/app/controllers/spree/admin/paypal_payments_controller.rb index c8f3f09..f63374c 100644 --- a/app/controllers/spree/admin/paypal_payments_controller.rb +++ b/app/controllers/spree/admin/paypal_payments_controller.rb @@ -1,6 +1,6 @@ module Spree class Admin::PaypalPaymentsController < Spree::Admin::BaseController - before_filter :load_order + before_action :load_order def index @payments = @order.payments.includes(:payment_method).where(spree_payment_methods: { type: "Spree::Gateway::PayPalExpress" }) @@ -12,4 +12,4 @@ def load_order @order = Spree::Order.where(number: params[:order_id]).first end end -end \ No newline at end of file +end diff --git a/app/controllers/spree/paypal_controller.rb b/app/controllers/spree/paypal_controller.rb index 0d426e0..d6b713e 100755 --- a/app/controllers/spree/paypal_controller.rb +++ b/app/controllers/spree/paypal_controller.rb @@ -35,7 +35,7 @@ def express pp_response = provider.set_express_checkout(pp_request) if pp_response.success? redirect_to payment_method. - express_checkout_url(pp_response, useraction: 'commit') + express_checkout_url(pp_response, useraction: 'commit', allow_other_host: true) else flash[:error] = Spree.t('flash.generic_error', scope: 'paypal', reasons: pp_response.errors.map(&:long_message).join(" ")) redirect_to checkout_state_path(:payment) diff --git a/app/decorators/controllers/spree/admin/payments_controller_decorator.rb b/app/decorators/controllers/spree/admin/payments_controller_decorator.rb new file mode 100644 index 0000000..993d8d8 --- /dev/null +++ b/app/decorators/controllers/spree/admin/payments_controller_decorator.rb @@ -0,0 +1,25 @@ +module Spree + module Admin + module PaymentsControllerDecorator + def paypal_refund + if request.get? + if @payment.source.state == 'refunded' + flash[:error] = Spree.t(:already_refunded, scope: 'paypal') + redirect_to admin_order_payment_path(@order, @payment) + end + elsif request.post? + response = @payment.payment_method.refund(@payment, params[:refund_amount]) + if response.success? + flash[:success] = Spree.t(:refund_successful, scope: 'paypal') + redirect_to admin_order_payments_path(@order) + else + flash.now[:error] = Spree.t(:refund_unsuccessful, scope: 'paypal') + " (#{response.errors.first.long_message})" + render + end + end + end + + Spree::Admin::PaymentsController.prepend(self) + end + end +end diff --git a/app/models/spree/gateway/pay_pal_express.rb b/app/models/spree/gateway/pay_pal_express.rb index c6021e1..0830793 100644 --- a/app/models/spree/gateway/pay_pal_express.rb +++ b/app/models/spree/gateway/pay_pal_express.rb @@ -1,6 +1,5 @@ -require 'paypal-sdk-merchant' module Spree - class Gateway::PayPalExpress < Gateway + class Gateway::PayPalExpress < Spree::PaymentMethod preference :use_new_layout, :boolean, default: true preference :login, :string preference :password, :string @@ -23,12 +22,16 @@ def provider mode: preferred_server.present? ? preferred_server : "sandbox", username: preferred_login, password: preferred_password, - signature: preferred_signature) + signature: preferred_signature, + + # Deliberately set ca_file to nil so the system's Cert Authority is used, + # instead of the bundled paypal.crt file which is out-of-date due to: + # https://www.paypal.com/va/smarthelp/article/discontinue-use-of-verisign-g5-root-certificates-ts2240 + ssl_options: { ca_file: nil }) provider_class.new end def auto_capture? - #false true end @@ -36,46 +39,46 @@ 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 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 + # amount :: float # express_checkout :: Spree::PaypalExpressCheckout # gateway_options :: hash @@ -97,36 +100,33 @@ def capture(amount_cents, authorization, currency:, **_options) do_capture(amount_cents, authorization, currency) 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 - + def try_void(payment) + refund(payment, payment.amount) + 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( + { refunded_at: Time.now, + refund_transaction_id: refund_transaction_response.RefundTransactionID, + state: "refunded", + refund_type: refund_type + }) + end + + refund_transaction_response + end + def credit(credit_cents, transaction_id, originator:, **_options) payment = originator.payment amount = credit_cents / 100.0 @@ -144,12 +144,12 @@ def credit(credit_cents, transaction_id, originator:, **_options) refund_transaction_response = provider.refund_transaction(refund_transaction) if refund_transaction_response.success? - payment.source.update_attributes( + payment.source.update( { refunded_at: Time.now, refund_transaction_id: refund_transaction_response.RefundTransactionID, state: "refunded", refund_type: refund_type - }) + }) end build_response( @@ -172,7 +172,7 @@ def express_checkout_url(pp_response, extra_params={}) "https://www.#{server_domain}paypal.com/cgi-bin/webscr?" + "cmd=_express-checkout&force_sa=true&" end + - URI.encode_www_form(params) + URI.encode_www_form(params) end def do_authorize(token, payer_id) @@ -180,7 +180,7 @@ def do_authorize(token, payer_id) self. provider. do_express_checkout_payment( - checkout_payment_params(token, payer_id)) + checkout_payment_params(token, payer_id)) build_response(response, authorization_transaction_id(response)) end @@ -188,11 +188,11 @@ def do_authorize(token, payer_id) def do_capture(amount_cents, authorization, currency) response = provider. do_capture( - provider.build_do_capture( - amount: amount_cents / 100.0, - authorization_id: authorization, - complete_type: "Complete", - currencycode: options[:currency])) + provider.build_do_capture( + amount: amount_cents / 100.0, + authorization_id: authorization, + complete_type: "Complete", + currencycode: options[:currency])) build_response(response, capture_transaction_id(response)) end @@ -224,7 +224,7 @@ def payment_details(token) self. provider. get_express_checkout_details( - checkout_details_params(token)). + checkout_details_params(token)). get_express_checkout_details_response_details. PaymentDetails end @@ -233,10 +233,10 @@ def checkout_payment_params(token, payer_id) self. provider. build_do_express_checkout_payment( - build_checkout_payment_params( - token, - payer_id, - payment_details(token))) + build_checkout_payment_params( + token, + payer_id, + payment_details(token))) end def checkout_details_params(token) diff --git a/db/migrate/20130723042610_create_spree_paypal_express_checkouts.rb b/db/migrate/20130723042610_create_spree_paypal_express_checkouts.rb index 08e889f..39d0e66 100644 --- a/db/migrate/20130723042610_create_spree_paypal_express_checkouts.rb +++ b/db/migrate/20130723042610_create_spree_paypal_express_checkouts.rb @@ -1,4 +1,4 @@ -class CreateSpreePaypalExpressCheckouts < ActiveRecord::Migration +class CreateSpreePaypalExpressCheckouts < ActiveRecord::Migration[5.0] def change create_table :spree_paypal_express_checkouts do |t| t.string :token diff --git a/db/migrate/20130808030836_add_transaction_id_to_spree_paypal_express_checkouts.rb b/db/migrate/20130808030836_add_transaction_id_to_spree_paypal_express_checkouts.rb index 859f1c3..cd56227 100644 --- a/db/migrate/20130808030836_add_transaction_id_to_spree_paypal_express_checkouts.rb +++ b/db/migrate/20130808030836_add_transaction_id_to_spree_paypal_express_checkouts.rb @@ -1,4 +1,4 @@ -class AddTransactionIdToSpreePaypalExpressCheckouts < ActiveRecord::Migration +class AddTransactionIdToSpreePaypalExpressCheckouts < ActiveRecord::Migration[5.0] def change add_column :spree_paypal_express_checkouts, :transaction_id, :string add_index :spree_paypal_express_checkouts, :transaction_id diff --git a/db/migrate/20130809013846_add_state_to_spree_paypal_express_checkouts.rb b/db/migrate/20130809013846_add_state_to_spree_paypal_express_checkouts.rb index a975ce8..0bfcff8 100644 --- a/db/migrate/20130809013846_add_state_to_spree_paypal_express_checkouts.rb +++ b/db/migrate/20130809013846_add_state_to_spree_paypal_express_checkouts.rb @@ -1,4 +1,4 @@ -class AddStateToSpreePaypalExpressCheckouts < ActiveRecord::Migration +class AddStateToSpreePaypalExpressCheckouts < ActiveRecord::Migration[5.0] def change add_column :spree_paypal_express_checkouts, :state, :string, default: "complete" end diff --git a/db/migrate/20130809014319_add_refunded_fields_to_spree_paypal_express_checkouts.rb b/db/migrate/20130809014319_add_refunded_fields_to_spree_paypal_express_checkouts.rb index 5dceb86..867f41b 100644 --- a/db/migrate/20130809014319_add_refunded_fields_to_spree_paypal_express_checkouts.rb +++ b/db/migrate/20130809014319_add_refunded_fields_to_spree_paypal_express_checkouts.rb @@ -1,4 +1,4 @@ -class AddRefundedFieldsToSpreePaypalExpressCheckouts < ActiveRecord::Migration +class AddRefundedFieldsToSpreePaypalExpressCheckouts < ActiveRecord::Migration[5.0] def change add_column :spree_paypal_express_checkouts, :refund_transaction_id, :string add_column :spree_paypal_express_checkouts, :refunded_at, :datetime diff --git a/db/migrate/20140117051315_rename_payment_methods.rb b/db/migrate/20140117051315_rename_payment_methods.rb index 41d551d..3a8de0a 100644 --- a/db/migrate/20140117051315_rename_payment_methods.rb +++ b/db/migrate/20140117051315_rename_payment_methods.rb @@ -1,4 +1,4 @@ -class RenamePaymentMethods < ActiveRecord::Migration +class RenamePaymentMethods < ActiveRecord::Migration[5.0] def up execute <<-SQL update spree_payment_methods set type = 'Spree::Gateway::PayPalExpress' WHERE type = 'Spree::BillingIntegration::PaypalExpress' diff --git a/lib/generators/spree_paypal_express/install/install_generator.rb b/lib/generators/spree_paypal_express/install/install_generator.rb index 7ab6e5c..b132b25 100644 --- a/lib/generators/spree_paypal_express/install/install_generator.rb +++ b/lib/generators/spree_paypal_express/install/install_generator.rb @@ -1,7 +1,6 @@ module SpreePaypalExpress module Generators class InstallGenerator < Rails::Generators::Base - class_option :auto_run_migrations, type: :boolean, default: false def add_javascripts @@ -20,7 +19,7 @@ def add_stylesheets end def add_migrations - run 'bundle exec rake railties:install:migrations FROM=spree_paypal_express' + run 'bundle exec rake railties:install:migrations FROM=solidus_paypal_express' end def run_migrations diff --git a/lib/solidus_paypal_express.rb b/lib/solidus_paypal_express.rb index 456d242..8e3eddb 100644 --- a/lib/solidus_paypal_express.rb +++ b/lib/solidus_paypal_express.rb @@ -2,3 +2,4 @@ require 'solidus_paypal_express/version' require 'solidus_paypal_express/engine' require 'sass/rails' +require 'paypal-sdk-merchant' diff --git a/lib/solidus_paypal_express/engine.rb b/lib/solidus_paypal_express/engine.rb index 07605ce..eb6bc6a 100644 --- a/lib/solidus_paypal_express/engine.rb +++ b/lib/solidus_paypal_express/engine.rb @@ -1,5 +1,7 @@ module SolidusPayPalExpress class Engine < Rails::Engine + include SolidusSupport::EngineExtensions + require 'spree/core' isolate_namespace Spree engine_name 'solidus_paypal_express' @@ -11,16 +13,8 @@ class Engine < Rails::Engine g.test_framework :rspec end - def self.activate - Dir.glob(File.join(File.dirname(__FILE__), '../../app/**/*_decorator*.rb')) do |c| - Rails.configuration.cache_classes ? require(c) : load(c) - end - end - - config.to_prepare &method(:activate).to_proc - initializer "spree.paypal_express.payment_methods", after: "spree.register.payment_methods" do |app| - app.config.spree.payment_methods << Spree::Gateway::PayPalExpress + app.config.spree.payment_methods << "Spree::Gateway::PayPalExpress" end end end diff --git a/solidus_paypal_express.gemspec b/solidus_paypal_express.gemspec index 85afc22..02c2d84 100644 --- a/solidus_paypal_express.gemspec +++ b/solidus_paypal_express.gemspec @@ -22,12 +22,13 @@ Gem::Specification.new do |s| s.require_path = 'lib' s.requirements << 'none' - s.add_dependency 'solidus_core', '>= 1.4' + s.add_dependency 'solidus_core', ['>= 1.4', '< 3'] + s.add_dependency 'solidus_support' s.add_dependency 'paypal-sdk-merchant', '1.117.2' - - s.add_development_dependency 'solidus', '>= 1.3' - s.add_development_dependency 'solidus_auth_devise', '>= 1.6' - s.add_development_dependency 'solidus_sample', '>= 1.0' + + s.add_development_dependency 'solidus', ['>= 1.3', '< 3'] + s.add_development_dependency 'solidus_auth_devise', ['>= 1.6', '< 3'] + s.add_development_dependency 'solidus_sample', ['>= 1.0', '< 3'] s.add_development_dependency 'coffee-rails' s.add_development_dependency 'show_me_the_cookies', '~> 3.0.0'