Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
07a3d3d
Attempt to bump dependency graph to use with Solidus 2
PeteTheSadPanda Jun 19, 2018
304c9bf
Formatting
PeteTheSadPanda Jun 19, 2018
36c6e0e
Update migrations to inerhit from ActiveRecord::Migration[5.0]
PeteTheSadPanda Jun 19, 2018
1836a81
Install migration from solidus_paypal_express instead of spree_paypal…
PeteTheSadPanda Jun 19, 2018
a034f83
#before_filter -> #before_action
PeteTheSadPanda Jun 26, 2018
aeb0491
Update Spree::Gateway::PayPalExpress to adhere to deprecation warning…
PeteTheSadPanda Jul 26, 2018
5c161af
[PayPal issue] Error when trying to cancel merch store order
PeteTheSadPanda Jul 16, 2019
3a6df61
Merge pull request #1 from Printavo/piotr/support_cancel_via_solidus
neelk07 Jul 24, 2019
dbf9b76
Rails 6 changes namely to conform to new zeitwerk file loader
PeteTheSadPanda Sep 6, 2019
0de1934
Move shim needed to handle refunds via Solidus to this plugin from Pr…
PeteTheSadPanda Sep 28, 2019
f0fd545
Remove refund_transaction_type extension and move it back to Printavo
PeteTheSadPanda Oct 2, 2019
b1ed003
Use system's cert authority instead of out-of-date Paypal file (#3)
flickgradley Sep 1, 2020
c9f9fb4
Replace load and require with autoload friendly require_dependency an…
PeteTheSadPanda Sep 6, 2020
ee47919
Update loading of decorators to the more modern approach of using Sol…
PeteTheSadPanda Jan 16, 2021
df290dc
Require paypal-sdk-merchant when loading all requires for the plugin …
PeteTheSadPanda Feb 1, 2021
635679a
Enforce convert usage of deprecated #update_attributes on AR children…
PeteTheSadPanda Aug 8, 2021
a8db8f3
Rails 7: allow_other_host on paypal redirect
PKostovic Apr 21, 2026
a4990e0
remove extra close paren
PKostovic Apr 21, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 0 additions & 19 deletions app/controllers/spree/admin/payments_controller_decorator.rb

This file was deleted.

4 changes: 2 additions & 2 deletions app/controllers/spree/admin/paypal_payments_controller.rb
Original file line number Diff line number Diff line change
@@ -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" })
Expand All @@ -12,4 +12,4 @@ def load_order
@order = Spree::Order.where(number: params[:order_id]).first
end
end
end
end
2 changes: 1 addition & 1 deletion app/controllers/spree/paypal_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
Original file line number Diff line number Diff line change
@@ -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
176 changes: 88 additions & 88 deletions app/models/spree/gateway/pay_pal_express.rb
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -23,59 +22,63 @@ 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

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
Expand All @@ -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
Expand All @@ -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(
Expand All @@ -172,27 +172,27 @@ 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)
response =
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

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
Expand Down Expand Up @@ -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
Expand All @@ -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)
Expand Down
Original file line number Diff line number Diff line change
@@ -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
Expand Down
Original file line number Diff line number Diff line change
@@ -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
Expand Down
Original file line number Diff line number Diff line change
@@ -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
Expand Down
Original file line number Diff line number Diff line change
@@ -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
Expand Down
2 changes: 1 addition & 1 deletion db/migrate/20140117051315_rename_payment_methods.rb
Original file line number Diff line number Diff line change
@@ -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'
Expand Down
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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
Expand Down
1 change: 1 addition & 0 deletions lib/solidus_paypal_express.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@
require 'solidus_paypal_express/version'
require 'solidus_paypal_express/engine'
require 'sass/rails'
require 'paypal-sdk-merchant'
Loading