Module: Adyen::Form
Overview
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 hidden_fields) or a HTTP redirect (see redirect_url).
Moreover, this module contains the method 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 Configuration#register_form_skin for more information.
Constant Summary collapse
- ACTION_DOMAIN =
The DOMAIN of the Adyen payment system that still requires the current Adyen enviroment.
"%s.adyen.com"
- ACTION_URL =
The URL of the Adyen payment system that still requires the current domain and payment flow to be filled.
"https://%s/hpp/%s.shtml"
Instance Method Summary collapse
-
#calculate_billing_address_signature(parameters, shared_secret = nil) ⇒ String
Calculates the billing address request signature for the given billing address parameters.
-
#calculate_billing_address_signature_string(parameters) ⇒ String
Generates the string that is used to calculate the request signature.
-
#calculate_delivery_address_signature(parameters, shared_secret = nil) ⇒ String
Calculates the delivery address request signature for the given delivery address parameters.
-
#calculate_delivery_address_signature_string(parameters) ⇒ String
Generates the string that is used to calculate the request signature.
- #calculate_open_invoice_signature(parameters, shared_secret = nil) ⇒ Object
- #calculate_open_invoice_signature_string(merchant_sig, parameters) ⇒ Object
- #calculate_shopper_signature(parameters, shared_secret = nil) ⇒ Object
-
#calculate_shopper_signature_string(parameters) ⇒ Object
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!).
-
#calculate_signature(parameters, shared_secret = nil) ⇒ String
Calculates the payment request signature for the given payment parameters.
-
#calculate_signature_string(parameters) ⇒ String
Generates the string that is used to calculate the request signature.
-
#do_parameter_transformations!(parameters = {}) ⇒ Object
Transforms the payment parameters hash to be in the correct format.
-
#domain(environment = nil) ⇒ String
Returns the DOMAIN of the Adyen payment system, adjusted for an Adyen environment.
-
#flat_payment_parameters(parameters = {}) ⇒ Hash
Transforms and flattens payment parameters to be in the correct format which is understood and accepted by adyen.
-
#hidden_fields(parameters = {}) ⇒ String
Returns a HTML snippet of hidden INPUT tags with the provided payment parameters.
-
#payment_methods_url(parameters = {}) ⇒ String
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.
-
#payment_parameters(parameters = {}, shared_secret = nil) ⇒ Hash
Transforms the payment parameters to be in the correct format and calculates the merchant signature parameter.
-
#redirect_signature(params, shared_secret = nil) ⇒ String
Computes the redirect signature using the request parameters, so that the redirect can be checked for forgery.
-
#redirect_signature_check(params, shared_secret = nil) ⇒ true, false
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. -
#redirect_signature_string(params) ⇒ String
Generates the string for which the redirect signature is calculated, using the request paramaters.
-
#redirect_url(parameters = {}) ⇒ String
Returns an absolute URL to the Adyen payment system, with the payment parameters included as GET parameters in the URL.
-
#url(environment = nil, payment_flow = nil) ⇒ String
Returns the URL of the Adyen payment system, adjusted for an Adyen environment.
Instance Method Details
#calculate_billing_address_signature(parameters, shared_secret = nil) ⇒ String
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.
303 304 305 306 307 |
# File 'lib/adyen/form.rb', line 303 def calculate_billing_address_signature(parameters, shared_secret = nil) shared_secret ||= parameters.delete(:shared_secret) raise ArgumentError, "Cannot calculate billing address request signature with empty shared_secret" if shared_secret.to_s.empty? Adyen::Util.hmac_base64(shared_secret, calculate_billing_address_signature_string(parameters[:billing_address])) end |
#calculate_billing_address_signature_string(parameters) ⇒ String
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.
273 274 275 276 277 |
# File 'lib/adyen/form.rb', line 273 def calculate_billing_address_signature_string(parameters) %w(street house_number_or_name city postal_code state_or_province country).map do |key| parameters[key.to_sym] end.join end |
#calculate_delivery_address_signature(parameters, shared_secret = nil) ⇒ String
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.
323 324 325 326 327 |
# File 'lib/adyen/form.rb', line 323 def calculate_delivery_address_signature(parameters, shared_secret = nil) shared_secret ||= parameters.delete(:shared_secret) raise ArgumentError, "Cannot calculate delivery address request signature with empty shared_secret" if shared_secret.to_s.empty? Adyen::Util.hmac_base64(shared_secret, calculate_delivery_address_signature_string(parameters[:delivery_address])) end |
#calculate_delivery_address_signature_string(parameters) ⇒ String
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.
283 284 285 286 287 |
# File 'lib/adyen/form.rb', line 283 def calculate_delivery_address_signature_string(parameters) %w(street house_number_or_name city postal_code state_or_province country).map do |key| parameters[key.to_sym] end.join end |
#calculate_open_invoice_signature(parameters, shared_secret = nil) ⇒ Object
349 350 351 352 353 354 |
# File 'lib/adyen/form.rb', line 349 def calculate_open_invoice_signature(parameters, shared_secret = nil) shared_secret ||= parameters.delete(:shared_secret) raise ArgumentError, "Cannot calculate open invoice request signature with empty shared_secret" if shared_secret.to_s.empty? merchant_sig = calculate_signature(parameters, shared_secret) Adyen::Util.hmac_base64(shared_secret, calculate_open_invoice_signature_string(merchant_sig, parameters[:openinvoicedata])) end |
#calculate_open_invoice_signature_string(merchant_sig, parameters) ⇒ Object
343 344 345 346 347 |
# File 'lib/adyen/form.rb', line 343 def calculate_open_invoice_signature_string(merchant_sig, parameters) flattened = Adyen::Util.flatten(:merchant_sig => merchant_sig, :openinvoicedata => parameters) pairs = flattened.to_a.sort pairs.transpose.map { |it| it.join(':') }.join('|') end |
#calculate_shopper_signature(parameters, shared_secret = nil) ⇒ Object
337 338 339 340 341 |
# File 'lib/adyen/form.rb', line 337 def calculate_shopper_signature(parameters, shared_secret = nil) shared_secret ||= parameters.delete(:shared_secret) raise ArgumentError, "Cannot calculate shopper request signature with empty shared_secret" if shared_secret.to_s.empty? Adyen::Util.hmac_base64(shared_secret, calculate_shopper_signature_string(parameters[:shopper])) end |
#calculate_shopper_signature_string(parameters) ⇒ Object
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!)
331 332 333 334 335 |
# File 'lib/adyen/form.rb', line 331 def calculate_shopper_signature_string(parameters) %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| parameters[key.to_sym] end.join end |
#calculate_signature(parameters, shared_secret = nil) ⇒ String
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.
263 264 265 266 267 |
# File 'lib/adyen/form.rb', line 263 def calculate_signature(parameters, shared_secret = nil) shared_secret ||= parameters.delete(:shared_secret) raise ArgumentError, "Cannot calculate payment request signature with empty shared_secret" if shared_secret.to_s.empty? Adyen::Util.hmac_base64(shared_secret, calculate_signature_string(parameters)) end |
#calculate_signature_string(parameters) ⇒ String
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.
236 237 238 239 240 241 242 243 244 245 246 247 |
# File 'lib/adyen/form.rb', line 236 def calculate_signature_string(parameters) merchant_sig_string = "" merchant_sig_string << parameters[:payment_amount].to_s << parameters[:currency_code].to_s << parameters[:ship_before_date].to_s << parameters[:merchant_reference].to_s << parameters[:skin_code].to_s << parameters[:merchant_account].to_s << parameters[:session_validity].to_s << parameters[:shopper_email].to_s << parameters[:shopper_reference].to_s << parameters[:recurring_contract].to_s << parameters[:allowed_methods].to_s << parameters[:blocked_methods].to_s << parameters[:shopper_statement].to_s << parameters[:merchant_return_data].to_s << parameters[:billing_address_type].to_s << parameters[:delivery_address_type].to_s << parameters[:shopper_type].to_s << parameters[:offset].to_s end |
#do_parameter_transformations!(parameters = {}) ⇒ Object
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.
80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 |
# File 'lib/adyen/form.rb', line 80 def do_parameter_transformations!(parameters = {}) parameters.replace(Adyen.configuration.default_form_params.merge(parameters)) if parameters[:skin] skin = Adyen.configuration.form_skin_by_name(parameters.delete(:skin)) parameters[:skin_code] ||= skin[:skin_code] parameters[:shared_secret] ||= skin[:shared_secret] parameters.merge!(skin[:default_form_params]) end parameters[:recurring_contract] = 'RECURRING' if parameters.delete(:recurring) == true parameters[:order_data] = Adyen::Util.gzip_base64(parameters.delete(:order_data_raw)) if parameters[:order_data_raw] parameters[:ship_before_date] = Adyen::Util.format_date(parameters[:ship_before_date]) parameters[:session_validity] = Adyen::Util.(parameters[:session_validity]) end |
#domain(environment = nil) ⇒ String
Returns the DOMAIN of the Adyen payment system, adjusted for an Adyen environment.
48 49 50 51 |
# File 'lib/adyen/form.rb', line 48 def domain(environment = nil) environment ||= Adyen.configuration.environment Adyen.configuration.payment_flow_domain || ACTION_DOMAIN % [environment.to_s] end |
#flat_payment_parameters(parameters = {}) ⇒ Hash
Transforms and flattens payment parameters to be in the correct format which is understood and accepted by adyen
145 146 147 |
# File 'lib/adyen/form.rb', line 145 def flat_payment_parameters(parameters = {}) Adyen::Util.flatten(payment_parameters(parameters)) end |
#hidden_fields(parameters = {}) ⇒ String
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 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.
218 219 220 221 222 223 224 225 226 |
# File 'lib/adyen/form.rb', line 218 def hidden_fields(parameters = {}) # Generate a hidden input tag per parameter, join them by newlines. form_str = flat_payment_parameters(parameters).map { |key, value| "<input type=\"hidden\" name=\"#{CGI.escapeHTML(key)}\" value=\"#{CGI.escapeHTML(value)}\" />" }.join("\n") form_str.respond_to?(:html_safe) ? form_str.html_safe : form_str end |
#payment_methods_url(parameters = {}) ⇒ String
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
191 192 193 194 195 |
# File 'lib/adyen/form.rb', line 191 def payment_methods_url(parameters = {}) url(nil, :directory) + '?' + flat_payment_parameters(parameters).map { |(k, v)| "#{k}=#{CGI.escape(v)}" }.join('&') end |
#payment_parameters(parameters = {}, shared_secret = nil) ⇒ Hash
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.
107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 |
# File 'lib/adyen/form.rb', line 107 def payment_parameters(parameters = {}, shared_secret = nil) raise ArgumentError, "Cannot generate form: parameters should be a hash!" unless parameters.is_a?(Hash) do_parameter_transformations!(parameters) raise ArgumentError, "Cannot generate form: :currency code attribute not found!" unless parameters[:currency_code] raise ArgumentError, "Cannot generate form: :payment_amount code attribute not found!" unless parameters[:payment_amount] raise ArgumentError, "Cannot generate form: :merchant_account attribute not found!" unless parameters[:merchant_account] raise ArgumentError, "Cannot generate form: :skin_code attribute not found!" unless parameters[:skin_code] # Calculate the merchant signature using the shared secret. shared_secret ||= parameters.delete(:shared_secret) raise ArgumentError, "Cannot calculate payment request signature without shared secret!" unless shared_secret parameters[:merchant_sig] = calculate_signature(parameters, shared_secret) if parameters[:billing_address] parameters[:billing_address_sig] = calculate_billing_address_signature(parameters, shared_secret) end if parameters[:delivery_address] parameters[:delivery_address_sig] = calculate_delivery_address_signature(parameters, shared_secret) end if parameters[:shopper] parameters[:shopper_sig] = calculate_shopper_signature(parameters, shared_secret) end if parameters[:openinvoicedata] parameters[:openinvoicedata][:sig] = calculate_open_invoice_signature(parameters, shared_secret) end return parameters end |
#redirect_signature(params, shared_secret = nil) ⇒ String
Computes the redirect signature using the request parameters, so that the redirect can be checked for forgery.
377 378 379 380 381 |
# File 'lib/adyen/form.rb', line 377 def redirect_signature(params, shared_secret = nil) shared_secret ||= Adyen.configuration.form_skin_shared_secret_by_code(params['skinCode']) raise ArgumentError, "Cannot compute redirect signature with empty shared_secret" if shared_secret.to_s.empty? Adyen::Util.hmac_base64(shared_secret, redirect_signature_string(params)) end |
#redirect_signature_check(params, shared_secret = nil) ⇒ true, false
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.
413 414 415 416 417 |
# File 'lib/adyen/form.rb', line 413 def redirect_signature_check(params, shared_secret = nil) raise ArgumentError, "params should be a Hash" unless params.is_a?(Hash) raise ArgumentError, "params should contain :merchantSig" unless params.key?('merchantSig') params['merchantSig'] == redirect_signature(params, shared_secret) end |
#redirect_signature_string(params) ⇒ String
Generates the string for which the redirect signature is calculated, using the request paramaters.
363 364 365 366 |
# File 'lib/adyen/form.rb', line 363 def redirect_signature_string(params) params['authResult'].to_s + params['pspReference'].to_s + params['merchantReference'].to_s + params['skinCode'].to_s + params['merchantReturnData'].to_s end |
#redirect_url(parameters = {}) ⇒ String
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 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.
177 178 179 180 181 |
# File 'lib/adyen/form.rb', line 177 def redirect_url(parameters = {}) url + '?' + flat_payment_parameters(parameters).map { |(k, v)| "#{k}=#{CGI.escape(v)}" }.join('&') end |
#url(environment = nil, payment_flow = nil) ⇒ String
Returns the URL of the Adyen payment system, adjusted for an Adyen environment.
64 65 66 67 |
# File 'lib/adyen/form.rb', line 64 def url(environment = nil, payment_flow = nil) payment_flow ||= Adyen.configuration.payment_flow Adyen::Form::ACTION_URL % [domain(environment), payment_flow.to_s] end |