-
Notifications
You must be signed in to change notification settings - Fork 269
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
Paypal receives full amount when there are multiple payments on order #190
Comments
Update: just using What I'm going to try instead is to calculate an order total that takes other (valid) payments into account when creating its total. |
Okay so I have this working, basically when it has other valid payments on the order it calculates the new total using
|
You also need to adjust the order.total in the confirm action, so that the payment recorded in spree tallies with that on Paypal |
This is my full file to get paypal_express to work with store credit Spree::PaypalController.class_eval do
# rubocop:disable Metrics/AbcSize
# rubocop:disable Metrics/CyclomaticComplexity
# rubocop:disable Metrics/MethodLength
# rubocop:disable Metrics/PerceivedComplexity
def express
order = current_order || raise(ActiveRecord::RecordNotFound)
items = order.line_items.map(&method(:line_item))
additional_adjustments = order.all_adjustments.additional
tax_adjustments = additional_adjustments.tax
shipping_adjustments = additional_adjustments.shipping
additional_adjustments.eligible.each do |adjustment|
# Because PayPal doesn't accept $0 items at all. See #10
# https://cms.paypal.com/uk/cgi-bin/?cmd=_render-content&content_ID=developer/e_howto_api_ECCustomizing
# "It can be a positive or negative value but not zero."
next if adjustment.amount.zero?
next if tax_adjustments.include?(adjustment) || shipping_adjustments.include?(adjustment)
items << {
Name: adjustment.label,
Quantity: 1,
Amount: {
currencyID: order.currency,
value: adjustment.amount
}
}
end
if current_order.using_store_credit?
items << {
Name: "Store Credits",
Quantity: 1,
Amount: {
currencyID: current_order.currency,
value: current_order.total_applied_store_credit * -1
}
}
end
pp_request = provider.build_set_express_checkout(express_checkout_request_details(order, items))
begin
pp_response = provider.set_express_checkout(pp_request)
if pp_response.success?
redirect_to provider.express_checkout_url(pp_response, useraction: 'commit')
else
flash[:error] = Spree.t('flash.generic_error', scope: 'paypal',
reasons: pp_response.errors.map(&:long_message).join(" "))
redirect_to checkout_state_path(:payment)
end
rescue SocketError
flash[:error] = Spree.t('flash.connection_failed', scope: 'paypal')
redirect_to checkout_state_path(:payment)
end
end
def confirm
order = current_order || raise(ActiveRecord::RecordNotFound)
order.payments.create!(
source: Spree::PaypalExpressCheckout.create(
token: params[:token],
payer_id: params[:PayerID]
),
amount: current_order.using_store_credit? ? order.total - order.total_applied_store_credit : order.total,
payment_method: payment_method
)
order.next
if order.complete?
flash.notice = Spree.t(:order_processed_successfully)
flash[:order_completed] = true
session[:order_id] = nil
redirect_to completion_route(order)
else
redirect_to checkout_state_path(order.state)
end
end
# rubocop:enable Metrics/AbcSize
# rubocop:enable Metrics/CyclomaticComplexity
# rubocop:enable Metrics/MethodLength
# rubocop:enable Metrics/PerceivedComplexity
# rubocop:disable Metrics/MethodLength
def payment_details(items)
# This retrieves the cost of shipping after promotions are applied
# For example, if shippng costs $10, and is free with a promotion, shipment_sum is now $10
shipment_sum = current_order.shipments.map(&:discounted_cost).sum
# This calculates the item sum based upon what is in the order total, but not for shipping
# or tax. This is the easiest way to determine what the items should cost, as that
# functionality doesn't currently exist in Spree core
item_sum = current_order.total - shipment_sum - current_order.additional_tax_total -
current_order.total_applied_store_credit
# # Applying store credit to deduct from the order total
# item_sum = item_sum - current_order.payments.where(payment_method_id: 8).sum(&:amount)
if item_sum.zero?
# Paypal does not support no items or a zero dollar ItemTotal
# This results in the order summary being simply "Current purchase"
{
OrderTotal: {
currencyID: current_order.currency,
value: current_order.total
}
}
else
{
OrderTotal: {
currencyID: current_order.currency,
value: current_order.total - current_order.total_applied_store_credit
},
ItemTotal: {
currencyID: current_order.currency,
value: item_sum
},
ShippingTotal: {
currencyID: current_order.currency,
value: shipment_sum,
},
TaxTotal: {
currencyID: current_order.currency,
value: current_order.additional_tax_total
},
ShipToAddress: address_options,
PaymentDetailsItem: items,
ShippingMethod: "Shipping Method Name Goes Here",
PaymentAction: "Sale"
}
end
end
# rubocop:enable Metrics/MethodLength
end |
So I got here via quite a roundabout route. The long and short of it is I wanted paypal to receive a correct total when I had already applied a payment (in this case a gift card).
I am somewhat cheating in my solution, because in order to update the outstanding_balance I need to first process the gift card. I believe store_credit also has the ability to do a partial deduction so this might apply there too?
My current solution is to replace the payment_details function in
app/controllers/spree/paypal_controller.rb
with one that usesoutstanding_balance
.This may not work if store credit amount doesn't process until the order state == complete. In that case maybe it would be better to manually add up uncaptured payment amounts (from methods that aren't the current payment method) and use that instead?
The text was updated successfully, but these errors were encountered: