solidusio / solidus_paypal_commerce_platform

💳 Integrate Solidus with Paypal Commerce Platform
https://developer.paypal.com/docs/platforms/
BSD 3-Clause "New" or "Revised" License
17 stars 24 forks source link

gateway.rb does not allow for nil auto-capture #116

Closed clark-upserv closed 1 year ago

clark-upserv commented 3 years ago

Pull Request: https://github.com/upserv-io/solidus_paypal_commerce_platform/compare/master...fix-nil-auto-capture file: app/models/solidus_paypal_commerce_platform/gateway.rb method: create_order code:

    def create_order(order, auto_capture)
      intent = auto_capture ? "CAPTURE" : "AUTHORIZE"
      request = OrdersCreateRequest.new
      paypal_order = SolidusPaypalCommercePlatform::PaypalOrder.new(order)
      request.request_body paypal_order.to_json(intent)
      @client.execute(request)
    end

issue: If, in the admin panel, the Auto Capture for PayPal is set to Use app default (see photo below), then there is possibility for errors.

image explanation: This is because the first line in the create_order method (intent = auto_capture ? "CAPTURE" : "AUTHORIZE") assumes that the auto_capture argument will either be true or false when in reality it can be true, false, or nil (if nil then we should be using Spree::Config.auto_capture).

nuanced error: If, in the admin panel, the Auto Capture for PayPal is set to Use app default and the app default (Spree::Config.auto_capture) is set to true, then the create_order method (in its current form) will send "AUTHORIZE" to PayPal when really is should be sending "CAPTURE" to PayPal. So PayPal will authorize but will not capture. This causes a payment error during payment checkout which I am assuming is because solidus is expecting PayPal to capture, but PayPal did not.

suggested solution (see below or view pull request here):

    def create_order(order, auto_capture)
      auto_capture = Spree::Config.auto_capture if auto_capture.nil? # New line of code
      intent = auto_capture ? "CAPTURE" : "AUTHORIZE"
      request = OrdersCreateRequest.new
      paypal_order = SolidusPaypalCommercePlatform::PaypalOrder.new(order)
      request.request_body paypal_order.to_json(intent)
      @client.execute(request)
    end

NOTE for this to work, the javascript_sdk_url method in payment_method.rb file (app/models/solidus_paypal_commerce_platform/payment_method.rb) needs to be updated as well:

    def javascript_sdk_url(order: nil, currency: nil)
      auto_capture = Spree::Config.auto_capture if auto_capture.nil? # New line of code
      # Both instance and class respond to checkout_steps.
      step_names = order ? order.checkout_steps : ::Spree::Order.checkout_steps.keys

      commit_immediately = step_names.include? "confirm"

      parameters = {
        'client-id': client_id,
        intent: auto_capture ? "capture" : "authorize",
        commit: commit_immediately ? "false" : "true",
        components: options[:display_credit_messaging] ? "buttons,messages" : "buttons",
        currency: currency
      }

      "https://www.paypal.com/sdk/js?#{parameters.to_query}"
    end
stale[bot] commented 3 years ago

This issue has been automatically marked as stale because it has not had recent activity. It might be closed if no further activity occurs. Thank you for your contributions.

kennyadsl commented 1 year ago

Hello @clark-upserv! I know it has been a long time but I managed to take a look at the issue and I submitted another possible solution to this as a PR: https://github.com/solidusio/solidus_paypal_commerce_platform/pull/185. Let me know your thoughts and thanks for submitting the issue!

This fix will be included in the next release!

kennyadsl commented 1 year ago

Fix released in 0.7.0 and 1.0.0.beta3.