Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Void and Cancel methods added. They use a "refund" to accomplish thei… #180

Closed
Closed
Changes from all commits
Commits
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
67 changes: 62 additions & 5 deletions app/models/spree/gateway/pay_pal_express.rb
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,62 @@ def auto_capture?
def method_type
'paypal'
end

# This is rather hackish, required for payment/processing handle_response code.
def empty_success
Class.new do
def success?; true; end
def authorization; nil; end
end.new
end

#this is essentially the refund method below except the creation of the refund transaction
#as that will count doubly towards the "credited" amount
def void(response_code, gateway_options={})
payment = Spree::Payment.find_by_response_code(response_code)
amount = payment.credit_allowed

#in case a partially refunded payment gets cancelled/voided, we don't want to act on the refunded payments
if amount.to_f > 0

# Process the refund
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
})
empty_success
else
class << refund_transaction_response
def to_s
errors.map(&:long_message).join(" ")
end
end
refund_transaction_response
end
end

empty_success

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This appears to return successfully even if the refund transaction fails. Is that the intended behavior?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Likely not, but frankly I haven't touched this code since so I'm not even sure either way. You're going to have to test it out and see what happens.

end

#cancellations also work for a partially refunded payment
def cancel(response_code)
void(response_code, {})
end

def purchase(amount, express_checkout, gateway_options={})
pp_details_request = provider.build_get_express_checkout_details({
Expand All @@ -55,11 +111,12 @@ def purchase(amount, express_checkout, gateway_options={})
# 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

#"order_id: The Order’s number attribute, plus the identifier for each payment, generated when the payment is first created"
payment = Spree::Payment.find_by_number(gateway_options[:order_id].split('-').last)
payment.update_attribute(:response_code, transaction_id)

empty_success
else
class << pp_response
def to_s
Expand Down