diff --git a/.gitignore b/.gitignore
index c111b33..4aa6afc 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1,3 @@
+Gemfile.lock
*.gem
+.*.swp
diff --git a/Gemfile b/Gemfile
new file mode 100644
index 0000000..fa75df1
--- /dev/null
+++ b/Gemfile
@@ -0,0 +1,3 @@
+source 'https://rubygems.org'
+
+gemspec
diff --git a/init.rb b/init.rb
deleted file mode 100644
index 3ae6e16..0000000
--- a/init.rb
+++ /dev/null
@@ -1,2 +0,0 @@
-require "paiement_cic"
-require "paiement_cic/form_helper"
diff --git a/lib/paiement_cic.rb b/lib/paiement_cic.rb
index 3dc5766..d4c7bec 100644
--- a/lib/paiement_cic.rb
+++ b/lib/paiement_cic.rb
@@ -1,8 +1,9 @@
+require 'paiement_cic/tpe'
+require 'paiement_cic/railtie' if defined?(Rails)
+
require 'digest/sha1'
-require 'openssl'
class String
-
def ^(other)
raise ArgumentError, "Can't bitwise-XOR a String with a non-String" \
unless other.kind_of? String
@@ -13,102 +14,35 @@ class String
end
end
-class PaiementCic
- autoload :FormHelper, "paiement_cic/form_helper"
+module PaiementCic
+ API_VERSION = "3.0"
+ DATE_FORMAT = "%d/%m/%Y:%H:%M:%S"
- @@version = "3.0" # clé extraite grâce à extract2HmacSha1.html fourni par le Crédit Mutuel
- cattr_accessor :version
+ class << self
+ attr_accessor :hmac_key, :tpe, :societe, :env
+ attr_writer :target_url
- @@hmac_key = "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ" # clé extraite grâce à extract2HmacSha1.html fourni par le Crédit Mutuel
- cattr_accessor :hmac_key
-
- @@target_url = "https://paiement.creditmutuel.fr/test/paiement.cgi" # "https://ssl.paiement.cic-banques.fr/paiement.cgi"
- cattr_accessor :target_url
-
- @@tpe = "123456"
- cattr_accessor :tpe
-
- @@societe = "masociete"
- cattr_accessor :societe
-
- @@url_ok = ""
- cattr_accessor :url_ok
-
- def self.date_format
- "%d/%m/%Y:%H:%M:%S"
- end
-
- def self.config(amount_in_cents, reference)
- oa = ActiveSupport::OrderedHash.new
- oa["version"] = "3.0"
- oa["TPE"] = tpe
- oa["date"] = Time.now.strftime(date_format)
- oa["montant"] = ("%.2f" % amount_in_cents) + "EUR"
- oa["reference"] = reference
- oa["texte-libre"] = ""
- oa["lgue"] = "FR"
- oa["societe"] = societe
- oa["mail"] = ""
- oa
- end
-
- def self.mac_string params
- hmac_key = PaiementCic.new
- mac_string = [hmac_key.tpe, params["date"], params['montant'], params['reference'], params['texte-libre'], hmac_key.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'], params['veres'], params['pares']].join('*') + "*"
- end
-
- def self.verify_hmac params
- hmac_key = PaiementCic.new
- mac_string = [hmac_key.tpe, params["date"], params['montant'], params['reference'], params['texte-libre'], hmac_key.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'], params['veres'], params['pares']].join('*') + "*"
-
- hmac_key.valid_hmac?(mac_string, params['MAC'])
- end
-
- # Check if the HMAC matches the HMAC of the data string
- def valid_hmac?(mac_string, sent_mac)
- computeHMACSHA1(mac_string) == sent_mac.downcase
- end
-
- # Return the HMAC for a data string
- def computeHMACSHA1(data)
- hmac_sha1(usable_key(self), data).downcase
- end
-
- def hmac_sha1(key, data)
- length = 64
-
- if (key.length > length)
- key = [Digest::SHA1.hexdigest(key)].pack("H*")
+ def configure(&block)
+ yield(self) if block_given?
end
- key = key.ljust(length, 0.chr)
- ipad = ''.ljust(length, 54.chr)
- opad = ''.ljust(length, 92.chr)
-
- k_ipad = key ^ ipad
- k_opad = key ^ opad
-
- #Digest::SHA1.hexdigest(k_opad + [Digest::SHA1.hexdigest(k_ipad + sData)].pack("H*"))
- OpenSSL::HMAC.hexdigest(OpenSSL::Digest::Digest.new("sha1"), key, data)
- end
-
- private
- # Return the key to be used in the hmac function
- def usable_key(payement)
-
- hex_string_key = payement.hmac_key[0..37]
- hex_final = payement.hmac_key[38..40] + "00";
-
- cca0 = hex_final[0].ord
-
- if cca0 > 70 && cca0 < 97
- hex_string_key += (cca0 - 23).chr + hex_final[1..2]
- elsif hex_final[1..2] == "M"
- hex_string_key += hex_final[0..1] + "0"
- else
- hex_string_key += hex_final[0..2]
+ def target_url
+ @target_url ||= (env == 'production' ? '' : "https://paiement.creditmutuel.fr/test/paiement.cgi") # "https://ssl.paiement.cic-banques.fr/paiement.cgi"
end
- [hex_string_key].pack("H*")
+ 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
end
end
diff --git a/lib/paiement_cic/form_helper.rb b/lib/paiement_cic/form_helper.rb
index 429a433..7b8efb9 100644
--- a/lib/paiement_cic/form_helper.rb
+++ b/lib/paiement_cic/form_helper.rb
@@ -1,32 +1,23 @@
-## refactor this
module PaiementCic::FormHelper
- def paiement_cic_hidden_fields(order, price, order_transaction, options = {})
- oa = PaiementCic.config(price, order_transaction.reference)
+ def paiement_cic_hidden_fields(reference, price, options = {})
+ oMac = PaiementCic::TPE.new(options)
+ oa = oMac.config(reference, price, options)
- oMac = PaiementCic.new
- sDate = Time.now.strftime("%d/%m/%Y:%H:%M:%S")
- chaine = [oMac.tpe, sDate, oa["montant"], oa["reference"].to_s, oa["texte-libre"], oMac.version, "FR", oMac.societe, "", "", "", "", "", "", "", "", "", "", ""].join("*")
- chaineMAC = oMac.computeHMACSHA1(chaine)
+ chaineMAC = oMac.computeHMACSHA1(oa.values.join('*'))
- url_retour = options[:url_retour] || bank_callback_order_transactions_url
- url_retour_ok = options[:url_retour_ok] || bank_callback_order_transactions_url(order)
- url_retour_err = options[:url_retour_err] || bank_err_order_transaction_url(order)
+ url_retour = options[:url_retour]
+ url_retour_ok = options[:url_retour_ok]
+ url_retour_err = options[:url_retour_err]
- html = '
-
-
-
-
-
-
-
-
-
-
-
-
- '
+ html = hidden_field_tag('MAC', chaineMAC)
+ html << hidden_field_tag('url_retour', url_retour)
+ html << hidden_field_tag('url_retour_ok', url_retour_ok)
+ html << hidden_field_tag('url_retour_err', url_retour_err)
- html.respond_to?(:html_safe) ? html.html_safe : html
+ oa.each do |k,v|
+ html << hidden_field_tag(k, v) unless v.empty?
+ end
+
+ html
end
end
diff --git a/lib/paiement_cic/railtie.rb b/lib/paiement_cic/railtie.rb
new file mode 100644
index 0000000..966bb23
--- /dev/null
+++ b/lib/paiement_cic/railtie.rb
@@ -0,0 +1,9 @@
+require 'paiement_cic/form_helper'
+
+module PaiementCic
+ class Railtie < Rails::Railtie
+ initializer "paiement_cic.form_helpers" do
+ ActionView::Base.send :include, FormHelper
+ end
+ end
+end
diff --git a/lib/paiement_cic/tpe.rb b/lib/paiement_cic/tpe.rb
new file mode 100644
index 0000000..da5af34
--- /dev/null
+++ b/lib/paiement_cic/tpe.rb
@@ -0,0 +1,79 @@
+module PaiementCic
+ class TPE
+ attr_accessor :hmac_key, :tpe, :societe
+
+ def initialize(options = {})
+ self.hmac_key = options[:hmac_key] || PaiementCic.hmac_key
+ self.tpe = options[:tpe] || PaiementCic.tpe
+ self.societe = options[:societe] || PaiementCic.societe
+ end
+
+ def config(reference, amount_in_cents, options = {})
+ {
+ 'TPE' => 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,
+ 'mail' => options[:mail].to_s,
+ 'nbrech' => options[:nbrech].to_s,
+ 'dateech1' => options[:dateech1].to_s,
+ 'montantech1' => options[:montantech1].to_s,
+ 'dateech2' => options[:dateech2].to_s,
+ 'montantech2' => options[:montantech2].to_s,
+ 'dateech3' => options[:dateech3].to_s,
+ 'montantech3' => options[:montantech3].to_s,
+ 'dateech4' => options[:dateech4].to_s,
+ 'montantech4' => options[:montantech4].to_s,
+ 'options' => options[:options].to_s
+ }
+ end
+
+ def mac_string params
+ [
+ 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'],
+ params['veres'], params['pares']
+ ].join('*') + "*"
+ end
+
+ def verify_hmac params
+ params.has_key?('MAC') && valid_hmac?(mac_string(params), params['MAC'])
+ end
+
+ # Check if the HMAC matches the HMAC of the data string
+ def valid_hmac?(mac_string, sent_mac)
+ computeHMACSHA1(mac_string) == sent_mac.downcase
+ end
+
+ # Return the HMAC for a data string
+ def computeHMACSHA1(data)
+ PaiementCic.hmac_sha1(usable_key, data).downcase
+ end
+
+ 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";
+
+ cca0 = hex_final[0].ord
+
+ if cca0 > 70 && cca0 < 97
+ hex_string_key += (cca0 - 23).chr + hex_final[1..2]
+ elsif hex_final[1..2] == "M"
+ hex_string_key += hex_final[0..1] + "0"
+ else
+ hex_string_key += hex_final[0..2]
+ end
+
+ [hex_string_key].pack("H*")
+ end
+ end
+end
diff --git a/lib/paiement_cic/version.rb b/lib/paiement_cic/version.rb
index e477294..354be3c 100644
--- a/lib/paiement_cic/version.rb
+++ b/lib/paiement_cic/version.rb
@@ -1,3 +1,3 @@
-class PaiementCic
+module PaiementCic
VERSION = "0.2"
end
diff --git a/paiement_cic.gemspec b/paiement_cic.gemspec
index bf33c84..cdc77e7 100644
--- a/paiement_cic.gemspec
+++ b/paiement_cic.gemspec
@@ -1,12 +1,13 @@
# encoding: utf-8
-$:.push File.expand_path("../lib", __FILE__)
+lib = File.expand_path('../lib', __FILE__)
+$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
require "paiement_cic/version"
Gem::Specification.new do |s|
s.name = "paiement_cic"
s.version = PaiementCic::VERSION
s.platform = Gem::Platform::RUBY
- s.authors = ["Novelys Team"]
+ s.authors = ["Novelys Team", "La Fourmi Immo"]
s.homepage = "https://github.com/novelys/paiementcic"
s.summary = %q{CIC / Crédit Mutuel credit card payment toolbox}
s.description = %q{Paiement CIC is a gem to ease credit card payment with the CIC / Crédit Mutuel banks system. It's a Ruby on Rails port of the connexion kits published by the bank.}