modifications to support version 3

3.0
Toutie 2009-12-21 11:24:45 +01:00
parent 8cb1aff141
commit d9c53853ed
4 changed files with 155 additions and 56 deletions

View File

@ -18,3 +18,66 @@ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#==============================================================================
#
# "Open source" kit for P@iement CM-CIC(TM).
# Integration sample in a merchant site for Ruby
#
# Author : Euro-Information/e-Commerce (contact: centrecom@e-i.com)
# Version : 1.0
# Date : 01/01/2009
#
# Copyright: (c) 2009 Euro-Information. All rights reserved.
#
#==============================================================================
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
- Redistributions of source code must retain the above copyright
notice and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice and the following disclaimer in the documentation and/or
other materials provided with the distribution.
- Neither the name of Euro-Information nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Note: Euro-Information does not provide person-to-person technical
support for tryout of CM-CIC P@iement examples. We do however
welcome your feedback which can be sent to <centrecom@e-i.com>.
#------------------------------------------------------------------------------
This software uses RSA Data Security, Inc. MD5 Message-Digest Algorithm.
License to copy and use this software is granted provided that it is
identified as the "RSA Data Security, Inc. MD5 Message-Digest
Algorithm" in all material mentioning or referencing this software or
this function.
License is also granted to make and use derivative works provided that
such works are identified as "derived from the RSA Data Security,
Inc. MD5 Message-Digest Algorithm" in all material mentioning or
referencing the derived work.
RSA Data Security, Inc. makes no representations concerning either the
merchantability of this software or the suitability of this software
for any particular purpose. It is provided "as is" without express or
implied warranty of any kind.
These notices must be retained in any copies of any part of this
documentation and/or software.
#==============================================================================

View File

@ -1,6 +1,6 @@
# Paiement CIC
Paiement CIC is a plugin to ease credit card payment with the CIC / Crédit Mutuel banks system.
Paiement CIC is a plugin to ease credit card payment with the CIC / Crédit Mutuel banks system version 3.0.
It's a Ruby on Rails port of the connexion kits published by the bank.
* The Plugin [site](http://github.com/novelys/cicpayment)
@ -24,11 +24,11 @@ script/plugin install git://github.com/novelys/paiementcic.git
### in development.rb :
PaiementCic.target_url = "https://ssl.paiement.cic-banques.fr/test/paiement.cgi"
PaiementCic.target_url = "https://ssl.paiement.cic-banques.fr/test/paiement.cgi" # or https://paiement.creditmutuel.fr/test/paiement.cgi
### in production.rb :
PaiementCic.target_url = "https://ssl.paiement.cic-banques.fr/paiement.cgi"
PaiementCic.target_url = "https://ssl.paiement.cic-banques.fr/paiement.cgi" # or https://paiement.creditmutuel.fr/paiement.cgi
### in order controller :
@ -71,15 +71,15 @@ script/plugin install git://github.com/novelys/paiementcic.git
order_transaction.update_attribute :success, true
receipt = "OK"
receipt = "0"
else
order.transaction_declined!
order.update_attribute :description, "Document Falsifie."
order_transaction.update_attribute :success, false
receipt = "Document Falsifie"
receipt = "1\n#{PaiementCic.mac_string}"
end
render :text => "Version: 1\n#{receipt}\n"
render :text => "Pragma: no-cache\nContent-type: text/plain\n\nversion=2\ncdr=#{receipt}"
end
def bank_ok

View File

@ -14,10 +14,13 @@ class String
end
class PaiementCic
@@version = "3.0" # clé extraite grâce à extract2HmacSha1.html fourni par le Crédit Mutuel
cattr_accessor :version
@@hmac_key = "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ" # clé extraite grâce à extract2HmacSha1.html fourni par le Crédit Mutuel
cattr_accessor :hmac_key
@@target_url = "https://ssl.paiement.cic-banques.fr/test/paiement.cgi" # "https://ssl.paiement.cic-banques.fr/paiement.cgi"
@@target_url = "https://paiement.creditmutuel.fr/test/paiement.cgi" # "https://ssl.paiement.cic-banques.fr/paiement.cgi"
cattr_accessor :target_url
@@tpe = "123456"
@ -26,61 +29,84 @@ class PaiementCic
@@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/100.0)) + "EUR"
oa["montant"] = ("%.2f" % amount_in_cents) + "EUR"
oa["reference"] = reference
oa["texte-libre"] = ""
oa["version"] = "1.2open"
oa["lgue"] = "FR"
oa["societe"] = societe
oa["mail"] = ""
oa
end
def self.calculate_hmac(ordered_hash)
data = ordered_hash.values.join("*") + "*"
hmac(data)
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
tpe = params[:TPE]
date = params[:date]
montant = params[:montant]
reference = params[:reference]
mac = params[:MAC].downcase
texte_libre = params['texte-libre']
code_retour = params['code-retour']
retour_plus = params['retourPLUS']
version = "1.2open"
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('*') + "*"
data = retour_plus + [tpe, date, montant, reference, texte_libre, version, code_retour].join("+") + "+"
mac == hmac(data)
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 self.hmac(data)
pass = "";
k1 = [Digest::SHA1.hexdigest(pass)].pack("H*");
l1 = k1.length
def hmac_sha1(key, data)
length = 64
k2 = [hmac_key].pack("H*")
l2 = k2.length
if (l1 > l2)
k2 = k2.ljust(l1, 0.chr)
elsif (l2 > l1)
k1 = k1.ljust(l2, 0.chr)
end
xor_res = k1 ^ k2
hmac_sha1(xor_res, data).downcase
end
if (key.length > length)
key = [Digest::SHA1.hexdigest(key)].pack("H*")
end
def self.hmac_sha1(key, data)
OpenSSL::HMAC.hexdigest(OpenSSL::Digest::Digest.new("sha1"), key, data)
end
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]
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

View File

@ -1,17 +1,27 @@
## refactor this
module PaiementCicHelper
def paiement_cic_hidden_fields(order, order_transaction, options = {})
oa = PaiementCic.config(order.amount, order_transaction.reference)
def paiement_cic_hidden_fields(order, price, order_transaction, options = {})
oa = PaiementCic.config(price, order_transaction.reference)
hsh = oa.dup
hsh["url_retour"] = options[:url_retour] || edit_order_url(order)
hsh["url_retour_ok"] = options[:url_retour_ok] || bank_ok_order_transaction_url(order_transaction)
hsh["url_retour_err"] = options[:url_retour_err] || bank_err_order_transaction_url(order_transaction)
hsh["MAC"] = PaiementCic.calculate_hmac(oa)
res = "\n"
hsh.each{|key, value|
res << hidden_field_tag(key, value) << "\n"
}
res
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)
html = '
<input type="hidden" name="version" id="version" value="' + oa["version"] + '" />
<input type="hidden" name="TPE" id="TPE" value="' + oa["TPE"] + '" />
<input type="hidden" name="date" id="date" value="' + oa["date"] + '" />
<input type="hidden" name="montant" id="montant" value="' + oa["montant"] + '" />
<input type="hidden" name="reference" id="reference" value="' + oa["reference"].to_s + '" />
<input type="hidden" name="MAC" id="MAC" value="' + chaineMAC + '" />
<input type="hidden" name="url_retour" id="url_retour" value="' + bank_callback_order_transactions_url + '" />
<input type="hidden" name="url_retour_ok" id="url_retour_ok" value="' + bank_ok_order_transaction_url(order) + '" />
<input type="hidden" name="url_retour_err" id="url_retour_err" value="' + bank_err_order_transaction_url(order) + '" />
<input type="hidden" name="lgue" id="lgue" value="' + oa["lgue"] + '" />
<input type="hidden" name="societe" id="societe" value="' + oa["societe"] + '" />
<input type="hidden" name="texte-libre" id="texte-libre" value="' + oa["texte-libre"] + '" />
<input type="hidden" name="mail" id="mail" value="''" />'
html
end
end