module Adyen::Form

The Adyen::Form module contains all functionality that is used to send payment requests to the Adyen payment system, using either a HTML form (see {Adyen::Form.hidden_fields}) or a HTTP redirect (see {Adyen::Form.redirect_url}).

Moreover, this module contains the method {Adyen::Form.redirect_signature_check} to check the request, that is made to your website after the visitor has made his payment on the Adyen system, for genuinity.

You can use different skins in Adyen to define different payment environments. You can register these skins under a custom name in the module. The other methods will automatically use this information (i.e. the skin code and the shared secret) if it is available. Otherwise, you have to provide it yourself for every method call you make. See {Adyen::Configuration#register_form_skin} for more information.

@see Adyen::Configuration#register_form_skin @see Adyen::Form.hidden_fields @see Adyen::Form.redirect_url @see Adyen::Form.redirect_signature_check

Constants

ACTION_DOMAIN

The DOMAIN of the Adyen payment system that still requires the current Adyen enviroment.

ACTION_URL

The URL of the Adyen payment system that still requires the current domain and payment flow to be filled.

Public Instance Methods

calculate_billing_address_signature(parameters, shared_secret = nil) click to toggle source

Calculates the billing address request signature for the given billing address parameters.

This signature is used by Adyen to check whether the request is genuinely originating from you. The resulting signature should be included in the billing address request parameters as the billingAddressSig parameter; the shared secret should of course not be included.

@param [Hash] parameters The billing address parameters for which to calculate

the billing address request signature.

@param [String] shared_secret The shared secret to use for this signature.

It should correspond with the skin_code parameter. This parameter can be
left out if the shared_secret is included as key in the parameters.

@return [String] The signature of the billing address request @raise [ArgumentError] Thrown if shared_secret is empty

    # File lib/adyen/form.rb
303 def calculate_billing_address_signature(parameters, shared_secret = nil)
304   shared_secret ||= parameters.delete(:shared_secret)
305   raise ArgumentError, "Cannot calculate billing address request signature with empty shared_secret" if shared_secret.to_s.empty?
306   Adyen::Util.hmac_base64(shared_secret, calculate_billing_address_signature_string(parameters[:billing_address]))
307 end
calculate_billing_address_signature_string(parameters) click to toggle source

Generates the string that is used to calculate the request signature. This signature is used by Adyen to check whether the request is genuinely originating from you. @param [Hash] parameters The parameters that will be included in the billing address request. @return [String] The string for which the siganture is calculated.

    # File lib/adyen/form.rb
273 def calculate_billing_address_signature_string(parameters)
274   %w(street house_number_or_name city postal_code state_or_province country).map do |key|
275     parameters[key.to_sym]
276   end.join
277 end
calculate_delivery_address_signature(parameters, shared_secret = nil) click to toggle source

Calculates the delivery address request signature for the given delivery address parameters.

This signature is used by Adyen to check whether the request is genuinely originating from you. The resulting signature should be included in the delivery address request parameters as the deliveryAddressSig parameter; the shared secret should of course not be included.

@param [Hash] parameters The delivery address parameters for which to calculate

the delivery address request signature.

@param [String] shared_secret The shared secret to use for this signature.

It should correspond with the skin_code parameter. This parameter can be
left out if the shared_secret is included as key in the parameters.

@return [String] The signature of the delivery address request @raise [ArgumentError] Thrown if shared_secret is empty

    # File lib/adyen/form.rb
323 def calculate_delivery_address_signature(parameters, shared_secret = nil)
324   shared_secret ||= parameters.delete(:shared_secret)
325   raise ArgumentError, "Cannot calculate delivery address request signature with empty shared_secret" if shared_secret.to_s.empty?
326   Adyen::Util.hmac_base64(shared_secret, calculate_delivery_address_signature_string(parameters[:delivery_address]))
327 end
calculate_delivery_address_signature_string(parameters) click to toggle source

Generates the string that is used to calculate the request signature. This signature is used by Adyen to check whether the request is genuinely originating from you. @param [Hash] parameters The parameters that will be included in the delivery address request. @return [String] The string for which the siganture is calculated.

    # File lib/adyen/form.rb
283 def calculate_delivery_address_signature_string(parameters)
284   %w(street house_number_or_name city postal_code state_or_province country).map do |key|
285     parameters[key.to_sym]
286   end.join
287 end
calculate_open_invoice_signature(parameters, shared_secret = nil) click to toggle source
    # File lib/adyen/form.rb
349 def calculate_open_invoice_signature(parameters, shared_secret = nil)
350   shared_secret ||= parameters.delete(:shared_secret)
351   raise ArgumentError, "Cannot calculate open invoice request signature with empty shared_secret" if shared_secret.to_s.empty?
352   merchant_sig = calculate_signature(parameters, shared_secret)
353   Adyen::Util.hmac_base64(shared_secret, calculate_open_invoice_signature_string(merchant_sig, parameters[:openinvoicedata]))
354 end
calculate_open_invoice_signature_string(merchant_sig, parameters) click to toggle source
    # File lib/adyen/form.rb
343 def calculate_open_invoice_signature_string(merchant_sig, parameters)
344   flattened = Adyen::Util.flatten(:merchant_sig => merchant_sig, :openinvoicedata => parameters)
345   pairs = flattened.to_a.sort
346   pairs.transpose.map { |it| it.join(':') }.join('|')
347 end
calculate_shopper_signature(parameters, shared_secret = nil) click to toggle source
    # File lib/adyen/form.rb
337 def calculate_shopper_signature(parameters, shared_secret = nil)
338   shared_secret ||= parameters.delete(:shared_secret)
339   raise ArgumentError, "Cannot calculate shopper request signature with empty shared_secret" if shared_secret.to_s.empty?
340   Adyen::Util.hmac_base64(shared_secret, calculate_shopper_signature_string(parameters[:shopper]))
341 end
calculate_shopper_signature_string(parameters) click to toggle source

shopperSig: shopper.firstName + shopper.infix + shopper.lastName + shopper.gender + shopper.dateOfBirthDayOfMonth + shopper.dateOfBirthMonth + shopper.dateOfBirthYear + shopper.telephoneNumber (Note that you can send only shopper.firstName and shopper.lastName if you like. Do NOT include shopperSocialSecurityNumber in the shopperSig!)

    # File lib/adyen/form.rb
331 def calculate_shopper_signature_string(parameters)
332   %w(first_name infix last_name gender date_of_birth_day_of_month date_of_birth_month date_of_birth_year telephone_number).map do |key|
333     parameters[key.to_sym]
334   end.join
335 end
calculate_signature(parameters, shared_secret = nil) click to toggle source

Calculates the payment request signature for the given payment parameters.

This signature is used by Adyen to check whether the request is genuinely originating from you. The resulting signature should be included in the payment request parameters as the merchantSig parameter; the shared secret should of course not be included.

@param [Hash] parameters The payment parameters for which to calculate

the payment request signature.

@param [String] shared_secret The shared secret to use for this signature.

It should correspond with the skin_code parameter. This parameter can be
left out if the shared_secret is included as key in the parameters.

@return [String] The signature of the payment request @raise [ArgumentError] Thrown if shared_secret is empty

    # File lib/adyen/form.rb
263 def calculate_signature(parameters, shared_secret = nil)
264   shared_secret ||= parameters.delete(:shared_secret)
265   raise ArgumentError, "Cannot calculate payment request signature with empty shared_secret" if shared_secret.to_s.empty?
266   Adyen::Util.hmac_base64(shared_secret, calculate_signature_string(parameters))
267 end
calculate_signature_string(parameters) click to toggle source

Generates the string that is used to calculate the request signature. This signature is used by Adyen to check whether the request is genuinely originating from you. @param [Hash] parameters The parameters that will be included in the payment request. @return [String] The string for which the siganture is calculated.

    # File lib/adyen/form.rb
236 def calculate_signature_string(parameters)
237   merchant_sig_string = ""
238   merchant_sig_string << parameters[:payment_amount].to_s       << parameters[:currency_code].to_s         <<
239                          parameters[:ship_before_date].to_s     << parameters[:merchant_reference].to_s    <<
240                          parameters[:skin_code].to_s            << parameters[:merchant_account].to_s      <<
241                          parameters[:session_validity].to_s     << parameters[:shopper_email].to_s         <<
242                          parameters[:shopper_reference].to_s    << parameters[:recurring_contract].to_s    <<
243                          parameters[:allowed_methods].to_s      << parameters[:blocked_methods].to_s       <<
244                          parameters[:shopper_statement].to_s    << parameters[:merchant_return_data].to_s  <<
245                          parameters[:billing_address_type].to_s << parameters[:delivery_address_type].to_s <<
246                          parameters[:shopper_type].to_s         << parameters[:offset].to_s
247 end
do_parameter_transformations!(parameters = {}) click to toggle source

Transforms the payment parameters hash to be in the correct format. It will also include the Adyen::Configuration#default_form_params hash. Finally, switches the :skin parameter out for the :skin_code and :shared_secret parameter using the list of registered skins.

@private @param [Hash] parameters The payment parameters hash to transform

   # File lib/adyen/form.rb
80 def do_parameter_transformations!(parameters = {})
81   parameters.replace(Adyen.configuration.default_form_params.merge(parameters))
82 
83   if parameters[:skin]
84     skin = Adyen.configuration.form_skin_by_name(parameters.delete(:skin))
85     parameters[:skin_code]     ||= skin[:skin_code]
86     parameters[:shared_secret] ||= skin[:shared_secret]
87     parameters.merge!(skin[:default_form_params])
88   end
89 
90   parameters[:recurring_contract] = 'RECURRING' if parameters.delete(:recurring) == true
91   parameters[:order_data]         = Adyen::Util.gzip_base64(parameters.delete(:order_data_raw)) if parameters[:order_data_raw]
92   parameters[:ship_before_date]   = Adyen::Util.format_date(parameters[:ship_before_date])
93   parameters[:session_validity]   = Adyen::Util.format_timestamp(parameters[:session_validity])
94 end
domain(environment = nil) click to toggle source

Returns the DOMAIN of the Adyen payment system, adjusted for an Adyen environment.

@param [String] environment The Adyen environment to use. This parameter can be

left out, in which case the 'current' environment will be used.

@return [String] The domain of the Adyen payment system that can be used

for payment forms or redirects.

@see Adyen::Form.environment @see Adyen::Form.redirect_url

   # File lib/adyen/form.rb
48 def domain(environment = nil)
49   environment  ||= Adyen.configuration.environment
50   Adyen.configuration.payment_flow_domain || ACTION_DOMAIN % [environment.to_s]
51 end
flat_payment_parameters(parameters = {}) click to toggle source

Transforms and flattens payment parameters to be in the correct format which is understood and accepted by adyen

@param [Hash] parameters The payment parameters. The parameters set in the

{Adyen::Configuration#default_form_params} hash will be included automatically.

@return [Hash] The payment parameters flatten, with camelized and prefixed key, stringified value

    # File lib/adyen/form.rb
145 def flat_payment_parameters(parameters = {})
146   Adyen::Util.flatten(payment_parameters(parameters))
147 end
hidden_fields(parameters = {}) click to toggle source

Returns a HTML snippet of hidden INPUT tags with the provided payment parameters. The snippet can be included in a payment form that POSTs to the Adyen payment system.

The payment parameters that are provided to this method will be merged with the {Adyen::Configuration#default_form_params} hash. The default parameter values will be overrided if another value is provided to this method.

You do not have to provide the :merchant_sig parameter: it will be calculated automatically if you provide either a registered skin name as the :skin parameter or provide both the :skin_code and :shared_secret parameters.

@example

<% form_tag(Adyen::Form.url) do %>
  <%= Adyen::Form.hidden_fields(:skin => :my_skin, :currency_code => 'USD',
        :payment_amount => 1000, ...) %>
  <%= submit_tag("Pay invoice")
<% end %>

@param [Hash] parameters The payment parameters to include in the payment request. @return [String] An HTML snippet that can be included in a form that POSTs to the

Adyen payment system.
    # File lib/adyen/form.rb
218 def hidden_fields(parameters = {})
219 
220   # Generate a hidden input tag per parameter, join them by newlines.
221   form_str = flat_payment_parameters(parameters).map { |key, value|
222     "<input type=\"hidden\" name=\"#{CGI.escapeHTML(key)}\" value=\"#{CGI.escapeHTML(value)}\" />"
223   }.join("\n")
224 
225   form_str.respond_to?(:html_safe) ? form_str.html_safe : form_str
226 end
payment_methods_url(parameters = {}) click to toggle source

@see Adyen::Form.redirect_url

Returns an absolute URL very similar to the one returned by Adyen::Form.redirect_url except that it uses the directory.shtml call which returns a list of all available payment methods

@param [Hash] parameters The payment parameters to include in the payment request. @return [String] An absolute URL to redirect to the Adyen payment system.

    # File lib/adyen/form.rb
191 def payment_methods_url(parameters = {})
192   url(nil, :directory) + '?' + flat_payment_parameters(parameters).map { |(k, v)|
193     "#{k}=#{CGI.escape(v)}"
194   }.join('&')
195 end
payment_parameters(parameters = {}, shared_secret = nil) click to toggle source

Transforms the payment parameters to be in the correct format and calculates the merchant signature parameter. It also does some basic health checks on the parameters hash.

@param [Hash] parameters The payment parameters. The parameters set in the

{Adyen::Configuration#default_form_params} hash will be included automatically.

@param [String] shared_secret The shared secret that should be used to calculate

the payment request signature. This parameter can be left if the skin that is
used is registered (see {Adyen::Configuration#register_form_skin}), or if the
shared secret is provided as the +:shared_secret+ parameter.

@return [Hash] The payment parameters with the :merchant_signature parameter set. @raise [ArgumentError] Thrown if some parameter health check fails.

    # File lib/adyen/form.rb
107 def payment_parameters(parameters = {}, shared_secret = nil)
108   raise ArgumentError, "Cannot generate form: parameters should be a hash!" unless parameters.is_a?(Hash)
109   do_parameter_transformations!(parameters)
110 
111   raise ArgumentError, "Cannot generate form: :currency code attribute not found!"         unless parameters[:currency_code]
112   raise ArgumentError, "Cannot generate form: :payment_amount code attribute not found!"   unless parameters[:payment_amount]
113   raise ArgumentError, "Cannot generate form: :merchant_account attribute not found!"      unless parameters[:merchant_account]
114   raise ArgumentError, "Cannot generate form: :skin_code attribute not found!"             unless parameters[:skin_code]
115 
116   # Calculate the merchant signature using the shared secret.
117   shared_secret ||= parameters.delete(:shared_secret)
118   raise ArgumentError, "Cannot calculate payment request signature without shared secret!" unless shared_secret
119   parameters[:merchant_sig] = calculate_signature(parameters, shared_secret)
120 
121   if parameters[:billing_address]
122     parameters[:billing_address_sig] = calculate_billing_address_signature(parameters, shared_secret)
123   end
124 
125   if parameters[:delivery_address]
126     parameters[:delivery_address_sig] = calculate_delivery_address_signature(parameters, shared_secret)
127   end
128 
129   if parameters[:shopper]
130     parameters[:shopper_sig] = calculate_shopper_signature(parameters, shared_secret)
131   end
132 
133   if parameters[:openinvoicedata]
134     parameters[:openinvoicedata][:sig] = calculate_open_invoice_signature(parameters, shared_secret)
135   end
136 
137   return parameters
138 end
redirect_signature(params, shared_secret = nil) click to toggle source

Computes the redirect signature using the request parameters, so that the redirect can be checked for forgery.

@param [Hash] params A hash of HTTP GET parameters for the redirect request. @param [String] shared_secret The shared secret for the Adyen skin that was used for

the original payment form. You can leave this out of the skin is registered
using the {Adyen::Form.register_skin} method.

@return [String] The redirect signature @raise [ArgumentError] Thrown if shared_secret is empty

    # File lib/adyen/form.rb
377 def redirect_signature(params, shared_secret = nil)
378   shared_secret ||= Adyen.configuration.form_skin_shared_secret_by_code(params['skinCode'])
379   raise ArgumentError, "Cannot compute redirect signature with empty shared_secret" if shared_secret.to_s.empty?
380   Adyen::Util.hmac_base64(shared_secret, redirect_signature_string(params))
381 end
redirect_signature_check(params, shared_secret = nil) click to toggle source

Checks the redirect signature for this request by calcultating the signature from the provided parameters, and comparing it to the signature provided in the merchantSig parameter.

If this method returns false, the request could be a forgery and should not be handled. Therefore, you should include this check in a before_filter, and raise an error of the signature check fails.

@example

class PaymentsController < ApplicationController
  before_filter :check_signature, :only => [:return_from_adyen]

  def return_from_adyen
    @invoice = Invoice.find(params[:merchantReference])
    @invoice.set_paid! if params[:authResult] == 'AUTHORISED'
  end

  private

  def check_signature
    raise "Forgery!" unless Adyen::Form.redirect_signature_check(params)
  end
end

@param [Hash] params params A hash of HTTP GET parameters for the redirect request. This

should include the +:merchantSig+ parameter, which contains the signature.

@param [String] shared_secret The shared secret for the Adyen skin that was used for

the original payment form. You can leave this out of the skin is registered
using the {Adyen::Configuration#register_form_skin} method.

@return [true, false] Returns true only if the signature in the parameters is correct.

    # File lib/adyen/form.rb
413 def redirect_signature_check(params, shared_secret = nil)
414   raise ArgumentError, "params should be a Hash" unless params.is_a?(Hash)
415   raise ArgumentError, "params should contain :merchantSig" unless params.key?('merchantSig')
416   params['merchantSig'] == redirect_signature(params, shared_secret)
417 end
redirect_signature_string(params) click to toggle source

Generates the string for which the redirect signature is calculated, using the request paramaters. @param [Hash] params A hash of HTTP GET parameters for the redirect request. @return [String] The signature string.

    # File lib/adyen/form.rb
363 def redirect_signature_string(params)
364   params['authResult'].to_s + params['pspReference'].to_s + params['merchantReference'].to_s +
365     params['skinCode'].to_s + params['merchantReturnData'].to_s
366 end
redirect_url(parameters = {}) click to toggle source

Returns an absolute URL to the Adyen payment system, with the payment parameters included as GET parameters in the URL. The URL also depends on the current Adyen enviroment.

The payment parameters that are provided to this method will be merged with the {Adyen::Configuration#default_form_params} hash. The default parameter values will be overrided if another value is provided to this method.

You do not have to provide the :merchant_sig parameter: it will be calculated automatically if you provide either a registered skin name as the :skin parameter or provide both the :skin_code and :shared_secret parameters.

Note that Internet Explorer has a maximum length for URLs it can handle (2083 characters). Make sure that the URL is not longer than this limit if you want your site to work in IE.

@example

def pay
  # Genarate a URL to redirect to Adyen's payment system.
  adyen_url = Adyen::Form.redirect_url(:skin => :my_skin, :currency_code => 'USD',
        :payment_amount => 1000, merchant_account => 'MyMerchant', ... )

  respond_to do |format|
    format.html { redirect_to(adyen_url) }
  end
end

@param [Hash] parameters The payment parameters to include in the payment request. @return [String] An absolute URL to redirect to the Adyen payment system.

    # File lib/adyen/form.rb
177 def redirect_url(parameters = {})
178   url + '?' + flat_payment_parameters(parameters).map { |(k, v)|
179     "#{k}=#{CGI.escape(v)}"
180   }.join('&')
181 end
url(environment = nil, payment_flow = nil) click to toggle source

Returns the URL of the Adyen payment system, adjusted for an Adyen environment.

@param [String] environment The Adyen environment to use. This parameter can be

left out, in which case the 'current' environment will be used.

@param [String] payment_flow The Adyen payment type to use. This parameter can be

left out, in which case the default payment type will be used.

@return [String] The absolute URL of the Adyen payment system that can be used

for payment forms or redirects.

@see Adyen::Form.environment @see Adyen::Form.domain @see Adyen::Form.redirect_url

   # File lib/adyen/form.rb
64 def url(environment = nil, payment_flow = nil)
65   payment_flow ||= Adyen.configuration.payment_flow
66   Adyen::Form::ACTION_URL % [domain(environment), payment_flow.to_s]
67 end