Petit intermède technique
UPDATE : nous discutons actuellement de ce code sur le groupe de discussions railsfrance (il contient des suggestions intéressants d’amélioration du code que je n’ai pas encore eu le temps d’intégrer)
Comme j’ai eu récemment affaire au paiement électronique du Crédit Mutuel/CIC et qu’ils ne fournissent pas d’implémentation de référence pour Ruby/Ruby on Rails, mais qu’ils fournissent par contre un certain nombre d’implémentations de référence (PHP, Python, Java, C++, etc), qu’on peut d’ailleurs retrouver ici, j’ai du re-implémenter ce qu’il me manquait pour Rails. Voici donc le code que j’ai écrit.
Disclaimer habituel :
// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// 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.
Code utilisé dans le controller (code à insérer par exemple dans votre application.rb) :
def show @tpe = "608..."# numéro de TPE du comerçant @date = Time.now.strftime("%d/%m/%Y:%H:%M:%S") @montant = "345.25EUR" @reference = "PIPO" @texte_libre = "" @version = "1.2open" @lgue = "FR" @societe = "nomsociete" @data = @tpe + "*" + @date + "*" + @montant + "*" + @reference + "*" + @texte_libre + "*" + @version + "*" + @lgue + "*" + @societe + "*" @mac = hmac(@data) end def confirm @tpe = params[:TPE] @date = params[:date] @montant = params[:montant] @reference = params[:reference] @mac = params[:MAC] @texte_libre = params['texte-libre'] @code_retour = params['code-retour'] @retour_plus = params['retourPLUS'] @mac = params[:MAC] @data = "#{@retour_plus}" @data += "#{@tpe}+" @data += "#{@date}+" @data += "#{@montant}+" @data += "#{@reference}+" @data += "#{@texte_libre}+" @data += "1.2open+" @data += "#{@code_retour}+" if @mac.downcase == hmac(@data) @result = @code_retour + @retour_plus @receipt = "OK" else @result = 'None' @receipt = "Document Falsifie" end render :text => "Version:1\n#{@receipt}\n#{Time.now.strftime("%d/%m/%Y:%H:%M:%S")}" end protected require 'digest/sha1' require 'openssl' def hmac(data) pass = ""; k1 = [Digest::SHA1.hexdigest(pass)].pack("H*"); l1 = k1.length key = "b9..." # clé extraite grâce à extract2HmacSha1.html fourni par le Crédit Mutuel k2 = [key].pack("H*") l2 = k2.length #if (l1 > l2) # k2 = k2.ljust(l1, chr(0x00)) #elsif (l2 > l1) # k1 = k1.ljust(l2, chr(0x00)) #end xor_res = k1 ^ k2 hmac_sha1(xor_res, data).downcase end def hmac_sha1(key, data) OpenSSL::HMAC.hexdigest(OpenSSL::Digest::Digest.new("sha1"), key, data) end
La méthode “show” va afficher le formulaire de paiement, tandis que la méthode “confirm” est l’url de confirmation de paiement (utilisée par le serveur de la banque).
Vous remarquerez que j’utilise l’opérateur ^ entre deux chaînes de caractères (xor entre deux chaînes). Celui-ci n’existe pas de base dans Ruby mais voici une petite implémentation :
class String def ^(other) raise ArgumentError, "Can't bitwise-XOR a String with a non-String" \ unless other.kind_of? String raise ArgumentError, "Can't bitwise-XOR strings of different length" \ unless self.length == other.length result = (0..self.length-1).collect { |i| self[i] ^ other[i] } result.pack("C*") end end
Finalement, la vue correspondant à la méthode “show” ressemblerait à ceci :
<% form_tag "https://ssl.paiement.cic-banques.fr/test/paiement.cgi" do -%> <%= hidden_field_tag 'version', @version %> <%= hidden_field_tag 'TPE', @tpe %> <%= hidden_field_tag 'date', @date %> <%= hidden_field_tag 'montant', @montant %> <%= hidden_field_tag 'reference', @reference %> <%= hidden_field_tag 'MAC', @mac %> <%= hidden_field_tag 'url_retour', "http://www.google.fr" %> <%= hidden_field_tag 'url_retour_ok', "http://www.google.fr" %> <%= hidden_field_tag 'url_retour_err', "http://www.google.fr" %> <%= hidden_field_tag 'lgue', @lgue %> <%= hidden_field_tag 'societe', @societe %> <%= hidden_field_tag 'text-libre', @texte_libre %> <%= submit_tag 'payer' %> <% end -%>
J’attends vos éventuels commentaires et suggestions.
Filed under: rails, ruby | Leave a Comment
No Responses Yet to “Petit intermède technique”