Below my full file, besides the changes above everything else is the same. Store Credits working fine with only these small tweaks to express and payment details method
# app/controllers/spree/paypal_controller_decorator.rb
Spree::PaypalController.class_eval do
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 order.using_store_credit?
items << {
Name: "Store Credits",
Quantity: 1,
Amount: {
currencyID: order.currency,
value: 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 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
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
end
Thank you for detailing this solution! I just spent about an hour looking into how to monkey patch a fix in and it is good to see that my solution matches yours!
You just need to edit the item_sum to consider the applied store credits (current_order.total_applied_store_credit)
https://github.com/spree-contrib/better_spree_paypal_express/blob/962a789738b59f440bf44ea22e64b65cc2572535/app/controllers/spree/paypal_controller.rb#L117
And add and item with the store credit discount after adding items for all other adjustments https://github.com/spree-contrib/better_spree_paypal_express/blob/4f9a187d31d96be8a616cbb5318cc3e2a713f056/app/controllers/spree/paypal_controller.rb#L28
Below my full file, besides the changes above everything else is the same. Store Credits working fine with only these small tweaks to express and payment details method