From e77eb75f078ad02b49cdaf1ad8717a61462a7e95 Mon Sep 17 00:00:00 2001 From: Guillaume DOTT Date: Wed, 9 Apr 2014 14:24:13 +0200 Subject: [PATCH] Move Config attributes to a separate class This allows to modify the target URL, the environment or any attribute for a specific TPE or use default config. --- README.markdown | 7 +++-- lib/paiement_cic.rb | 52 +++++++++------------------------ lib/paiement_cic/config.rb | 44 ++++++++++++++++++++++++++++ lib/paiement_cic/form_helper.rb | 4 +-- lib/paiement_cic/tpe.rb | 26 ++++++++--------- 5 files changed, 76 insertions(+), 57 deletions(-) create mode 100644 lib/paiement_cic/config.rb diff --git a/README.markdown b/README.markdown index 455dfcc..9021028 100644 --- a/README.markdown +++ b/README.markdown @@ -16,7 +16,7 @@ It's a Ruby on Rails port of the connexion kits published by the bank. ### in an initializer (`config/initializers/paiement_cic.rb`) : ```ruby -PaiementCic.configure do |config| +PaiementCic.default_config.configure do |config| # here the hmac key calculated with the js calculator given by CIC config.hmac_key = "########################################" # Here the TPE number @@ -32,19 +32,20 @@ PaiementCic.configure do |config| end ``` -You can also specify `hmac_key`, `tpe` and `societe` when initializing `PaiementCic::TPE` and with `paiement_cic_hidden_fields` helper by passing an hash. +You can also specify different attributes when initializing `PaiementCic::TPE` and with `paiement_cic_hidden_fields` helper by passing an hash. ```ruby { hmac_key: "########################################", tpe: "#######", societe: "xxxxxxxxxxxxx", + env: :test, } ``` ### in the payment by card view : ``` -- form_tag PaiementCic.target_url do +- form_tag PaiementCic.default_config.target_url do = paiement_cic_hidden_fields(@order.reference, @order.amount, mail: 'email@example.com', url_retour: edit_order_url(order), url_retour_ok: bank_ok_order_transaction_url(order_transaction), url_retour_err: bank_err_order_transaction_url(order_transaction)) = submit_tag "Accéder au site de la banque", :style => "font-weight: bold;" = image_tag "reassuring_pictograms.jpg", :alt => "Pictogrammes rassurants", :style => "width: 157px;" diff --git a/lib/paiement_cic.rb b/lib/paiement_cic.rb index 7fd18d6..921624c 100644 --- a/lib/paiement_cic.rb +++ b/lib/paiement_cic.rb @@ -1,3 +1,4 @@ +require 'paiement_cic/config' require 'paiement_cic/tpe' require 'paiement_cic/railtie' if defined?(Rails) @@ -31,50 +32,23 @@ module PaiementCic DEFAULT_BANK = :cm DEFAULT_ENV = :test - class << self - attr_accessor :hmac_key, :tpe, :societe - attr_writer :target_url + def self.default_config + @@default_config ||= PaiementCic::Config.new + end - def configure(&block) - yield(self) if block_given? + def self.hmac_sha1(key, data) + length = 64 + + if (key.length > length) + key = [Digest::SHA1.hexdigest(key)].pack("H*") end - def bank - @bank || DEFAULT_BANK - end + key = key.ljust(length, 0.chr) - def bank=(value) - raise UnknownBankError unless END_POINTS.keys.include?(value.to_sym) - @bank = value - end + k_ipad = key ^ ''.ljust(length, 54.chr) + k_opad = key ^ ''.ljust(length, 92.chr) - def env - @env || DEFAULT_ENV - end - - def env=(value) - raise UnknownEnvError unless END_POINTS.first.last.include?(value.to_sym) - @env = value - end - - def target_url - @target_url || END_POINTS[self.bank][self.env] - end - - def hmac_sha1(key, data) - length = 64 - - if (key.length > length) - key = [Digest::SHA1.hexdigest(key)].pack("H*") - end - - key = key.ljust(length, 0.chr) - - k_ipad = key ^ ''.ljust(length, 54.chr) - k_opad = key ^ ''.ljust(length, 92.chr) - - Digest::SHA1.hexdigest(k_opad + [Digest::SHA1.hexdigest(k_ipad + data)].pack("H*")) - end + Digest::SHA1.hexdigest(k_opad + [Digest::SHA1.hexdigest(k_ipad + data)].pack("H*")) end class UnknownBankError < Exception; end diff --git a/lib/paiement_cic/config.rb b/lib/paiement_cic/config.rb new file mode 100644 index 0000000..99d1232 --- /dev/null +++ b/lib/paiement_cic/config.rb @@ -0,0 +1,44 @@ +module PaiementCic + class Config + attr_accessor :hmac_key, :tpe, :societe + attr_writer :target_url + + def initialize(attributes = {}, &block) + if block_given? + configure(&block) + else + attributes.each do |name, value| + setter = "#{name}=" + next unless respond_to?(setter) + send(setter, value) + end + end + end + + def configure(&block) + yield self + end + + def bank + @bank || DEFAULT_BANK + end + + def bank=(value) + raise UnknownBankError unless END_POINTS.keys.include?(value.to_sym) + @bank = value + end + + def env + @env || DEFAULT_ENV + end + + def env=(value) + raise UnknownEnvError unless END_POINTS.first.last.include?(value.to_sym) + @env = value + end + + def target_url + @target_url || END_POINTS[self.bank][self.env] + end + end +end diff --git a/lib/paiement_cic/form_helper.rb b/lib/paiement_cic/form_helper.rb index 7b8efb9..5d2f1a8 100644 --- a/lib/paiement_cic/form_helper.rb +++ b/lib/paiement_cic/form_helper.rb @@ -1,9 +1,9 @@ module PaiementCic::FormHelper def paiement_cic_hidden_fields(reference, price, options = {}) oMac = PaiementCic::TPE.new(options) - oa = oMac.config(reference, price, options) + oa = oMac.attributes(reference, price, options) - chaineMAC = oMac.computeHMACSHA1(oa.values.join('*')) + chaineMAC = oMac.compute_hmac_sha1(oa.values.join('*')) url_retour = options[:url_retour] url_retour_ok = options[:url_retour_ok] diff --git a/lib/paiement_cic/tpe.rb b/lib/paiement_cic/tpe.rb index da5af34..0c73729 100644 --- a/lib/paiement_cic/tpe.rb +++ b/lib/paiement_cic/tpe.rb @@ -1,23 +1,22 @@ module PaiementCic class TPE - attr_accessor :hmac_key, :tpe, :societe + attr_accessor :config - def initialize(options = {}) - self.hmac_key = options[:hmac_key] || PaiementCic.hmac_key - self.tpe = options[:tpe] || PaiementCic.tpe - self.societe = options[:societe] || PaiementCic.societe + def initialize(options = nil) + self.config = options.nil? ? PaiementCic.default_config : + PaiementCic::Config.new(options) end - def config(reference, amount_in_cents, options = {}) + def attributes(reference, amount_in_cents, options = {}) { - 'TPE' => tpe, + 'TPE' => config.tpe, 'date' => Time.now.strftime(PaiementCic::DATE_FORMAT), 'montant' => ("%.2f" % amount_in_cents) + "EUR", 'reference' => reference.to_s, 'texte-libre' => '', 'version' => PaiementCic::API_VERSION, 'lgue' => 'FR', - 'societe' => societe, + 'societe' => config.societe, 'mail' => options[:mail].to_s, 'nbrech' => options[:nbrech].to_s, 'dateech1' => options[:dateech1].to_s, @@ -34,7 +33,7 @@ module PaiementCic def mac_string params [ - tpe, params["date"], params['montant'], params['reference'], params['texte-libre'], + config.tpe, params['date'], params['montant'], params['reference'], params['texte-libre'], PaiementCic::API_VERSION, params['code-retour'], params['cvx'], params['vld'], params['brand'], params['status3ds'], params['numauto'], params['motifrefus'], params['originecb'], params['bincb'], params['hpancb'], params['ipclient'], params['originetr'], @@ -48,20 +47,21 @@ module PaiementCic # Check if the HMAC matches the HMAC of the data string def valid_hmac?(mac_string, sent_mac) - computeHMACSHA1(mac_string) == sent_mac.downcase + compute_hmac_sha1(mac_string) == sent_mac.downcase end # Return the HMAC for a data string - def computeHMACSHA1(data) + def compute_hmac_sha1(data) PaiementCic.hmac_sha1(usable_key, data).downcase end + alias_method :computeHMACSHA1, :compute_hmac_sha1 private # Return the key to be used in the hmac function def usable_key - hex_string_key = hmac_key[0..37] - hex_final = hmac_key[38..40] + "00"; + hex_string_key = config.hmac_key[0..37] + hex_final = config.hmac_key[38..40] + "00"; cca0 = hex_final[0].ord