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

Already on GitHub? Sign in to your account

Ability to supply custom "RAW" options #30

Closed
weppos opened this Issue May 25, 2012 · 3 comments

Comments

Projects
None yet
4 participants

weppos commented May 25, 2012

Hi, first of all thank you very much for creating and releasing this library.

I have been working to integrate the library into a project where we want to use PayPal. The project uses both PayPal instant payment and PayPal payment authorization and here comes the problem.

Currently, the paypal-express library doesn't support PayPal authorization, nor it provides authorization, void and capture methods. Moreover, integrating such feature at runtime or in a fork requires a lot of monkey patching because it's impossible to supply custom attributes on the fly to existing methods.

My proposal is to relax the method PayPal::Express::Request definitions in order to allow arbitrary parameters to be supplied at runtime.

Let me show you an example.

https://github.com/nov/paypal-express/blob/master/lib/paypal/express/request.rb#L42-52

Here's the current checkout! method.

def checkout!(token, payer_id, payment_requests)
  params = {
    :TOKEN => token,
    :PAYERID => payer_id
  }
  Array(payment_requests).each_with_index do |payment_request, index|
    params.merge! payment_request.to_params(index)
  end
  response = self.request :DoExpressCheckoutPayment, params
  Response.new response
end

In order to introduce the Authorization, I should be able to pass the PAYMENTREQUEST_0_PAYMENTACTION option and set it to Authorization or Order. But this is just an example, there is a number of additional fields I might want to supply to the :DoExpressCheckoutPayment call such as GIFTMESSAGE, BUTTONSOURCE, ...

PS. I know that PAYMENTREQUEST_0_PAYMENTACTION can be supplied using the Paypal::Payment::Request, but this is just an example.

My proposal is to change the method definition to something like

def checkout!(token, payer_id, payment_requests, options = {})
  params = {
    :TOKEN => token,
    :PAYERID => payer_id
  }

  merge_request_params(params, payment_requests)
  merge_optional_params(params, options)

  response = self.request :DoExpressCheckoutPayment, params
  Response.new response
end

private

def merge_request_params(params, payment_requests)
  Array(payment_requests).each_with_index do |payment_request, index|
    params.merge! payment_request.to_params(index)
  end
end

def merge_optional_params(params, options)
  options.each do |key, value|
    params.merge! key.upcase => value
  end
end


@request.checkout!(..., ..., [payment_request], :GIFTMESSAGE => "My personal gift to you.")

You already provide the options argument in some methods, however the options are filtered and custom values not mapped internally into the method are discarded. An other solution can be to pass an additional attribute so that options (currently reserved for ruby-oriented options) are not mixed with custom options.

The options value can be filtered or validated even further, but I believe that leaving the responsibility to the programmer can be a reasonable solution.

What do you think?

I agree

Owner

nov commented Feb 2, 2013

Did this change solve this issue?
#43

@nov nov closed this Apr 22, 2013

Here's how we are doing it: Storenvy#3

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment