Switch from Selenium+Firefox to Poltergeist+Phantomjs and speed up your test suite

Posted by & filed under La technique, Ruby on Rails.

Selenium is a great tool for integration testing but it has two major drawbacks :

  • it relies on Firefox engine, so every time Firefox updates, you have to cross your finger and praise your test suite will still be usable
  • it is f**** slow

Solve those 2 problems in just a few minutes, switch to phantomjs ! Phantomjs is a headless browser that uses a webkit engine, just grab the binary according to your plateform here. In my case (ubuntu 64 bits) , I installed it on my system this way :

$ tar jxvf  phantomjs-1.9.0-linux-x86_64.tar.bz2
$ sudo ln -s /home/guillaume/phantomjs-1.9.0-linux-x86_64/bin/phantomjs /usr/sbin/phantomjs

What just really matters here is that the binary should be accessible from your PATH.

Second step, for Rails users, install poltergeist to use phantomjs from your app :

# Gemfile
gem 'poltergeist'

…and then “bundle install”.  You also have to change slightly your Rspec settings  :

# spec/spec_helper.rb
# Before :
require 'selenium-webdriver'
Capybara.default_driver = :selenium
# Change to :
require 'capybara/poltergeist'
Capybara.javascript_driver = :poltergeist

Ok, easy enough ? That’ll all ! Enjoy your integration tests :

# Selenium
Finished in 35.52 seconds
14 examples, 0 failures
# Phantomjs
Finished in 18.47 seconds
14 examples, 0 failures

Yes, almost 2x faster :-)

Paperclip caching and clean URLs or DragonFly on the fly image resizing ? Get the best of both worlds !

Posted by & filed under Ruby on Rails.

When it came across image manipulation using Rails, I had to make a choice : Paperclip to handle high traffic/popular websites, and DragonFly for privates, more confidential but also more evolutive applications.

Let’s start with an example :

# Paperclip typical image URL
/system/pictures/877/thumbnail/my_thumbnail_image_name.jpg?1352719049

# DragonFly image URL
/media/BAhbB1sHOgZmIjIyMDEyLzA5LzE0LzE3XzI0XzA0XzMyMl9BdXLDqWxpZV9DSEFVVkVBVS5KUEdbCDoGcDoKdGh1bWIiCjUweDUw

Paperclip resizes the image on upload, then store the thumbnail on the file system, whereas DragonFly only upload the original image, as is, then resizes the image on each page load. Well… I don’t like any of those two solutions.

Paperclip drawback : imagine you have a long time living and popular website, with thousands of cool members/users who have each uploaded their avatar. This avatar is stored in 3 sizes, say : original, 200×200 pixels and 50×50 pixels. Cool, and now what happens after 2/3 years of success, when the client redesign the whole website and the designer asks for avatars in 100×100 pixels ? Hu ?! You’re good to dive into obscurs shell scripts using ImageMagick on the command line… Nightmare.

DragonFly drawback : each time you call an image, you call the DragonFly Gem. Ok, it has an internal caching system, but it _is_ slow. Plus you can forget Google Image indexation and search engine optimization with such an ugly URL (and good luck to convince your client it “doesn’t matter”…)

I was stuck between those 2 solutions and their respective drawbacks… until I found an amazing very simple solution reading between the lines of the (excellent) DragonFly documentation : the “to_file” method ! It only took me a couple of hours to write this helper that ensure the file exists on the filesystem, and only if not, call DragonFly to handle the resize and cache the thumbnail where it is expected to be. Everything is done at the view level, and the helper can also take any argument you would want to see in an img tag (yes, data attributes too).

‘Want some examples ?

# HAML template
= thumbnail_tag user.avatar, '100x100'

# client side HTML 
<img src='/images/user_avatar.jpg' width='100px' height='100px' alt="user_avatar" />

More tricky

# HAML template
= thumbnail_tag product.image, '200x50', :alt => "such a nice product name", :data => {:do =>'some_action', :trigger =>'that'}

# client side HTML 
<img src='/products/small/product_image_file_name.jpg' width='200px' height='50px' alt="such a nice product name" data-do='some_action' data-trigger='that' />

You will find all code, tests, installation instructions and usage on the github repo.

SCSS vs Sass vs CSS : mon humble avis

Posted by & filed under La technique.

Cela fait maintenant un an que j’ai commencé à m’intéresser à Sass et aux pré-processeurs CSS en général. Au début, c’est forcément “whaoooo”. 1 an plus tard, je suis plus critique sur la chose. Petit rappel des bidules en questions :

#CSS

ul.main-list {
  margin-left: 20px;
 }

ul.main-list li {
  list-style-type: square;
  display: block;
  border: 1px solid red;
  border-radius: 5px; 
  -moz-border-radius: 5px; 
  -webkit-border-radius: 5px; 
}

ul.main-list li a {
  color: #fff;
  text-decoration: none;
}

#SCSS

$color: $fff;

ul.main-list {
  margin-left: 20px;
  li {
    list-style-type: square;
    display: block;
    border: 1px solid red;
    @include border-radius(5);
    a {
      color: $color;
      text-decoration: none;
    }
  }
}

#Sass

$color: $fff

ul.main-list
  margin-left: 20px
  li 
    list-style-type: square
    display: block
    border: 1px solid red
    @include border-radius(5)
    a 
      color: $color
      text-decoration: none

 

Cooool, on peut donc utiliser des variables ($color dans l’exemple), et même des “fonctions” (= “mixins”) permettant de rassembler les vendor préfix dans un seul fichier ! Dorénavant, si le client veut changer la couleur des polices on a qu’à le changer à un seule et unique endroit ! Avec l’asset pipeline de Rails, on peut même proprement séparer chaque partie (menus, widgets, navbar…) et tout hierarchiser !

Fantastique, donc, sauf que… sauf que dans la vraie vie ça se passe comme ça :

#CSS

  • J’ouvre l’éditeur de chrome (ou firebug) : 1 sec
  • Je fais une recherche sur l’expression “main-menu” : 1 sec
  • Je modifie le style de ma liste… oups, j’ai du mal fermer une accolade, tout part en vrille… voila, c’est ici : 10 sec
  • clic droit, “save” : 1 sec

==> Total : 13 secondes

 

#SCSS

  • J’ouvre mon éditeur de texte et je cherche mon fichier… : 5 sec
  • Ha non, c’est pas dans “lists.scss”, mais dans “menus.scss” : 5 sec
  • Je modifie le style de ma liste, je reviens dans le navigateur pour faire un refresh : 10 sec
  • Flute, ça compile pas j’ai mal fermé une accolade. Retour, recherche… : 10 sec
  • Refresh qui va jusqu’au bout. J’ai Twitter Bootstrap et une appli conséquente dans les assets, c’est long : 10 sec

==> Total : 40 secondes

 

#Sass

  • J’ouvre mon éditeur de texte et je cherche mon fichier… : 5 sec
  • Ha non, c’est pas dans “lists.sass”, mais dans “menus.sass” : 5 sec
  • Je modifie le style de ma liste : 10 sec
  • Refresh du browser. J’ai Twitter Bootstrap et une appli conséquente dans les assets, c’est long : 10 sec

==> Total : 30 secondes

Voila, tout est dit. Au minimum vous allez diviser votre productivité par 3. Juste une petite mention spéciale pour Sass qui permet vraiment une lisibilité inégalée, mais bon… à quel coût. C’est un exemple un peu caricatural mais l’idée est là, et totalement non discutable : rien ne peut aller plus vite pour éditer une CSS que l’éditeur du Browser. Faire un refresh à chaque modif, c’est aller droit dans le mur. D’autant que Rails n’est pas le truc le plus rapide qui soit, et que des dizaines d’assets à loader (si vous avez bien réparti vos fichiers) ça prend un max de temps. TROP de temps.

Alors ok, après, on va me dire : “oui mais le jour ou le client voudra changer la couleur de police…”. Certes, “le jour où”. Le grand cimetière des applis oubliés qui n’ont jamais vu de clients est rempli de code écrit pour “le jour où”. Sauf que ce jour n’est jamais arrivé. D’ailleurs, il n’arrive _jamais_ dans la vraie vie. Le client valide une maquette : vous l’intégrez. Point.

Et puis même…admettons. Vous êtes tombé sur un perfectionniste de la dernière heure qui vous demande de modifier un arrondi sur les angles de trois boutons, alors que la maquette est déja validée et intégrée (admettons). Franchement, ça va vous prendre moins de 3 minutes de le faire à la main, en le changeant pour chaque préfixe vendeur. Certes, ça va être casse pied et pas valorisant, mais ce sera fait et bien fait en 3 minutes. 3 minutes, ce n’est vraiment rien par rapport à tout ce que vous allez gagner comme temps en ne passant pas par un preprocesseur, et je le répète, il ne s’agit que d’un cas __hypothétique__.

Par ailleurs, tout coder dans un fichier en pur CSS ne veut pas forcément dire “crade” ! Rien n’empêche de clairement sectionner le code, et vous tenir à certaines conventions. On peut aussi “émuler” les mixins, en créant une class “rounded”, par exemple, que vous utiliserez pour arrondir les coins sur les blocs ou boutons avec un simple “class=’my-div rounded’”. Simple, efficace, propre… et productif.

Enfin bref, vous l’aurez compris, mon avis après un an d’utilisation est plus que mitigé : les préprocesseurs CSS, c’est juste parfait pour produire un très joli code bien organisé (IMHO, les fichiers Sass sont hyper lisibles. J’adore). C’est bien mais le cout en productivité est énorme. Maintenant, si votre impératif c’est de livrer des tonnes de features dans le vrai monde des clients pressés dont le budget est limité : rien ne vaut UNE bonne vieille CSS qu’on édite directement dans le Browser.

Cas particulier : votre projet est Open Source et/ou clairement destiné à être repris par d’autres. Soyez sympa envers ceux qui vont reprendre votre oeuvre : même si vous codez d’abord tout dans une seule CSS, dans un deuxième temps, prennez quelques minutes pour splitter les fichiers et les basculer en Sass (grâce à l’excellent CSS to Sass par exemple). Mais là on parle d’une appli clairement faite, par nature, pour que le code soit modifié. Rien à voir donc avec le cas général ou le code est destiné à rentrer en production le plus vite possible et ne plus bouger pendant des mois, voire des années.

Gérer correctement les accents avec Ruby, Rails et upcase

Posted by & filed under Ruby on Rails.

C’est assez étonnant d’avoir encore ce genre de problème de nos jours, mais Ruby (même 1.9.3), ne gère toujours pas correctement les passages de caractères accentués en majuscule. Explication :

> puts "café".upcase
CAFé

Pas terrible, hein ? Une solution est d’utiliser la Gem unicode_utils et de surcharger la class String pour pouvoir l’utiliser de façon transparente.

Commencez par install la Gem en l’ajoutant au Gemfile puis bundle install (comme d’habitude)

Ensuite, créez le fichier suivant :

require "unicode_utils/upcase"

class String

  def upcase
    UnicodeUtils.upcase(self)
  end

end

Sauvegardez le tout dans “/config/initializers/string_upcase_patch.rb”

Voila, c’est tout. Maintenant, quand vous faites un upcase sur une chaine contenant des caractères accentués, vous avez bien :

"café".upcase
#=> CAFÉ

Espérons que tout ça sera prochainement intégré directement dans Ruby

Passer tous les produits en HT avec Prestashop

Posted by & filed under PHP.

Je Post plus rien depuis des lustres, mais bon, je me dis que ce petit truc avec Prestashop peut toujours servir à quelqu’un…

Prenons le cas suivant : vous avez un client qui était en SARL, SA… bref, qui avait des prix en HT dans le BO avec une TVA à 19%, et des prix publics TTC en front-end.

Maintenant, votre client décide de passer en auto-entrepreneur, il ne souhaite pas changer ses prix en front-end, et veut simplement que les prix de vente HT deviennent des prix TTC, avec une TVA à 0. Vu ?

En une ligne de SQL

UPDATE ps_product SET price = (price*1.196), id_tax=0;

Bon, bien sur, toujours un backup de la base au cas où…

Un premier avis sur Spree (plateforme Ecommerce pour Ruby on Rails)

Posted by & filed under Ruby on Rails.

Depuis bientôt trois ans que je pratique quotidiennement Ruby on Rails, il est toujours resté pour moi une problématique encore non résolue : “et pour le E-Commerce, on fait comment ?”. Je dois bien le dire, pour l’instant : “je fais comme je peux”. En clair : Prestashop pour les grosses boutiques, et Rails maison pour les boutiques plus modestes mais avec des besoins très particuliers (produits sur mesures, système de promo. avancé…). Quoi qu’il en soit, la conclusion -à ce jour- n’a pas changé : IL FAUT UN MAGENTO EN RAILS.

J’ai bien essayé ForgeOS, en son temps, mais il s’est depuis perdu dans une plateforme beaucoup trop généraliste. Je cherche un sabre laser du E-Commerce, pas un couteau Suisse. Il y a eu aussi substruct… mais là encore, c’est plus “un CMS avec un panier” qu’autre chose, peu de monde semble d’ailleurs avoir suivi.

Nous voila donc fin 2011, et j’apprends que Spree vient de lever 1,5 Million USD, le site Web est tout beau tout neuf et il semble y avoir une communauté derrière. Cool. J’essaye la demo en ligne… allez, je l’installe, et je vois ce qu’il y a dedans…

  • Rails 3.1.1, HAML, SASS/LESS, JQuery. On est vraiment dans ce qui se fait de mieux. En tout cas dans le mainstream de la communauté Rails
  • 55 tables dans la BDD… seulement ??! Pour situer, Prestashop est autour de 135 tables “out of the box”, et Magento 218. Bon, ok, ça ne veut pas dire grand chose. Moui, mais bon… quand même, 55 tables, ça “tend quand même à signifier” (notez les guillemets, svp) que pas mal de features seront en add-on, ou bien tout simplement absentes par rapport aux deux autres poids lourds du secteur sus-nommés.
  • Hooo, y’a une API ! Bon signe, ça prouve qu’on est proche des besoins des grosses boutiques.
  • La doc. Ou plutôt : LA doc. Rien à redire concernant ce qu’on trouve sur le site, propre, net, précis (en Anglais, ça va de soit). Ok, mais _ailleurs_ ? Les tutos ? Les Blogs posts ?! Ben… pas grand chose. Quelques bribes éparses sur des forums, à prendre avec des pincettes tellement Spree semble avoir changé ces dernières années mois. “On est dans le cutting edge, man !”. En clair : va falloir s’accrocher.

L’installation se déroule facilement, puisque… toute l’application est contenue dans des Gems. Autant le dire franchement : je n’aime pas du tout cette approche (que j’ai déja vu ailleurs :-/). Les Gems, à mon sens (et sauf erreur de ma part, j’ai lu DHH dire la même chose) sont là pour étendre des fonctionnalités à l’échelle de Ruby. Perso, je ne suis vraiment pas fan de ce genre de chose, qui a vite tendance à ajouter de la “magie” (on ne sait plus où se fait quoi et comment). Concrétement, après installation, vous vous retrouvez donc avec une application… vide, puisque tout est dans des Gems.

Ok, bon, admettons, commençons à modifier une vue ou deux pour se mettre en jambes : que dit la doc ? Qu’il faut créer d’autres Gems pour y mettre sa customisation, même au niveau des simples vues :-/ Donc, si je suis bien tout ça : mon appli est, et restera vide. En fait, Spree, c’est un Framework de Gems, quoi… Plus sérieusement, je trouve que Spree est “une application Ruby qui utilise Rails”, ce qui n’a rien à voir avec “une application Rails” classique dans laquelle on retrouve vite ses marques. Là, il va falloir suivre.

Là dessus, j’ai levé la tête du guidon et suis parti à la recherche de boutiques déja montées avec Spree : quelques “something went wrong” (si si) et quelques customisations de vues vraiment simplettes plus tard, j’ai décidé de laisser Spree dans un coin de mon /var/www, et d’y revenir dans quelques mois. Peut-être. Ou plutôt : j’espère.

Ce Post ne représente que ma modeste opinion après quelques heures de survol rapide de Spree. Si vous arrivez à me convaincre de m’accrocher encore un peu avec cette appli, libre à vous d’exposer vos arguments en commentaire, je n’attends que ça ;-)

Rulu 2011 : la communauté Ruby (on Rails) Européenne vaut vraiment le détour

Posted by & filed under Ruby on Rails, Y'a pas que le boulot....

Un p’tit peu de retard dans la restranscription de RULU, la conf’ Ruby (on Rails) Lyonnaise qui a eu lieu le Week-end du 25/26 Juin, mais je tenais à laisser une trace quelque part de cet évenement. Oui, évenement, on peut le dire.

Tout d’abord : la qualité des intervenants

Sven Fuchs (I18n de Rails) Hampton Catlin (Monsieur Sass, HAML), Nick Sutterer (Apotomo, Cells)… j’en passe, et des meilleurs, comme le dit l’expression. J’étais franchement impressionné par le niveau des speakers, surtout pour une première.

Ensuite : la qualité et la diversité des Talks

J’avoue qu’au début, j’avais un peu peur d’être laché par des talks trop orientés technique et “high level”. Il n’en fut rien, chaque intervenant prenant soin de rendre son talk réellement vivant, accessible, d’une part. Certains talks étant carrément dans le registre “social”, d’autre part (Joshua Wehner par exemple, sur le thème de la nécessaire diversité, pour l’instant absente du milieu Geek).
En bref, je n’ai absolument pas été perdu par d’éventuelles envolées lyriques de techniciens autistes. Bien au contraire même, y compris quand certains thèmes étaient bien épais (le Http Streaming, notamment), j’ai trouvé les intervenants remarquables part leur sens de la pédagogie et de l’écoute.

Ne pas oublier : l’organisation

Un grand bravo à tout le Staff, qui a fait un travail de Titan en très (très !) peu de temps. La participation de l’INSA fut aussi à noter (les locaux étaient juste parfaits). Franck, Damien, Vincent, Camille, Jean Michel (voui, j’en oublie, ne m’en voulez pas)… Vraiment, du bon boulot.

Finalement : la communauté Ruby Européeenne

Un aspect particulièrement intéressant dans ce genre d’évenement à taille humaine (environ 100 personnes), ce sont les échanges ; et de ce côté là c’était aussi, vraiment, un bon moment ! Toulouse, Nantes, Paris, Nice… mais aussi Allemagne, Pays Bas, Suisse ou Angleterre… en ce qui me concerne, j’ai toujours beaucoup de plaisir à m’ouvrir à d’autres points de vue, sortir de mon trop petit monde habituel.
Un dernier petit point que j’ai aussi beaucoup aimé, conséquence directe du milieu dans lequel Rails est le plus utilisé : la communauté regroupe un grand nombre de gens ayant lancé leur business. Beaucoup de “Start-uper” donc, et de nombreux échanges sur comment monter sa boite dans le Net.

Enfin, et je concluerais sur ce point qui ne cesse de m’épater : la communauté Ruby(on Rails) est vraiment une communauté de gens ouverts, intelligents et agréables. Techniquement exigeants, qui ont tous des Macs et ne parlent qu’Anglais, certes, mais des gens qui valent le coup d’être connu. Des gens qui ne se la racontent absolument pas et sont toujours prêt à vous donner un petit coup de main.

Si ça vous tente, et même si vous n’êtes pas (encore) dans la techno pour le moment, passez donc boire une bière (ou deux) au prochain apéro Ruby à Lyon : ce mardi 12 juillet à l’Antre Autre, lyon 1er !

Redimensionnez vos images à la volée avec Ruby on Rails

Posted by & filed under Ruby on Rails.

J’ai re-factorisé et modifié en profondeur la syntaxe d’appel de mon bon vieux plugin Thumbnailer. Certes, vous pouvez déja redimensionner les images lors de l’Upload avec paperclip, mais thumbnailer vous permet d’aller encore plus loin :

  • Resize à la volé au niveau de la vue
  • Calcul automatique des proportions
  • Gestion automatique du cache, les images ne sont traitées qu’une seule fois par RMagick
  • Possibilité d’appel en “remote”, redimensionnez vos images depuis votre client en JS !

Niveau utilisation, on ne peut pas faire plus simple :

# View
<%= thumbnailer :src=>'/images/my_image.jpg', :width=>'200' %>

Et le plugin se charge tout seul de vous générer une image de 200 pixels de large, qui est mise en cache dans ‘/cache/images/200xauto/my_image.jpg’. La vue finale affichant un tag img comme celui-ci :

<img src='/cache/images/200xauto/my_image.jpg?1305495323' width='200' alt='my_image' />

Tous les attributs possibles d’une balise img sont reconnus, y compris les évenements JavaScript. L’attribut ‘alt’, si il n’est pas spécifié, sera automatiquement généré à partir du nom de fichier. Vous noterez aussi que le nom de fichier est suffixé par un timestamp, permettant au cache client side de gérer une image différente mais portant le même nom de fichier, tout comme le ‘image_tag’ original de Rails.

En bonus, avec le paramètre “remote”, l’appel de l’image peut aussi se faire directement depuis le paramètre ‘src’ du tag img :

# View
<%= thumbnailer :src=>'/images/my_image.jpg', :width=>'200', :remote=>true %>

# Final output
<img src='/thumbnailer/200xauto/images/my_image.jpg' width='200' alt='my_image' />

Effet de bord sympathique, vous disposez maintenant d’une simple URL pour appeler une image de n’importe quelle dimension depuis votre client en Javascript, genre :

$('my_image').src='http://my_domain.com/thumbnailer/200xauto/images/my_image.jpg';
alert("Look ! The image has been resized !");

Ca fait maintenant 2 ans que j’utilise ces features dans tous mes projets. Au début c’était une collection de helpers, de routes et de controllers, puis j’ai pris un peu de temps pour packager tout ça dans un plugin. Je pense maintenant que cette nouvelle version est plus clean et efficace, mais je vous laisse vous faire votre avis là dessus. Comme d’habitude, si vous avez des remarques, laissez un commentaire…

Vous faites quoi le 25/26 Juin ?

Posted by & filed under Ruby on Rails, Y'a pas que le boulot....

Le Week-end du 25/26 Juin se déroulera Ruby Lugdunum, la conf. Lyonnaise autour de Ruby on Rails ! Au programme sont d’ors et déja confirmé Sven Fuchs (Rails Core contributor) et Konstantin Haase (l’un des principaux Developpeur de Sinatra). Il y aura aussi d’autres conf autour de Rubynius, “Solid” application concepts…

L’évenement devrait logiquement se faire sur le Campus de la Doua, et l’ambiance promet d’être -comme toujours avec la communauté Ruby- sérieuse mais sans prise de tête (si si, c’est possible).

Tous les détails sont sur Rulu.eu, et pour rester au courant des préparatifs, le mieux est de s’abonner au compte Twitter.

SIPS/ATOS et Ruby on Rails avec le plugin ‘atos’

Posted by & filed under Ruby on Rails.

Après Paybox, je me suis dernièrement interessé à SIPS/ATOS, poids lourd du paiement ligne hexagonal. Derrière une apparente complexité, le principe est en fait assez simple :

  • L’acheteur valide son panier, un controller récupère les paramètres (prix, id du panier…), les envoie dans un binaire qui crypte le tout et renvoie un formulaire HTML avec 3 (ou +) logos de carte de crédit au sein du site marchand
  • L’acheteur choisi la carte de crédit appropriée et part sur le site de la banque
  • Une fois les numéros de carte validés sur le site de la banque, celui-ci répond au marchand “dans le dos du navigateur” (c’est l’auto-response) via une chaine cryptée
  • un controller récupère l’auto response et la passe à nouveau dans un binaire afin d’en obtenir un tableau associatif

Ne trouvant rien de simple qui me convienne, j’ai codé un petit plugin qui permet de faire tout ça dans Rails très facilement. Dans une console à la racine de votre appli :

script/plugin install git@github.com:gbarillot/atos.git

Ensuite, déposez les fichiers fournis par la banque dans /lib/atos. Le répertoire lib doit ressembler à ça :

/mon_appli
  /lib
    /atos
      /bin
        request
        request_2.4.18_2.96
        ....
      /param
        certif.fr.014295303911111
        parmcom.014295303911111
        parmcom.sherlocks
        pathfile

Petites remarques : le numéro “014295303911111″ en suffixe correspond au marchant_id de test, et “sherlocks” correspond au fait que je passe par LCL. Si vous passez par la Société Générale, vous aurez “parmcom.sogenactif”. Je préfère vraiment le “conventions over configuration”, mais vous pouvez aussi passer les chemins vers vos fichiers au niveau de l’instanciation de la classe Atos. Ca rajoute juste une étape :

atos = Atos.new(
  :root_dir=>'/path/to/your/main/dir'
)
.... et ensuite :
@request = atos.request(
  :merchant_id=>'014295303911111',
  :amount=>'1500', 
  :customer_id=>session[:customer_id],
  :automatic_response_url=>"http://mon_site.com/payment/validate",
  :normal_return_url=>"http://mon_site.com/payment/fr/confirm",
  :cancel_return_url=>"http://mon_site.com"
)

Tant que nous sommes dans le paramétrage des fichiers, déposez aussi le répertoire “logos” et contenant les logos des cartes dans un répertoire public de votre appli (par exemple /public/images/logos). Prenez aussi soin de renseigner le fichier “/lib/atos/param/pathfile” avec tous les chemins __en absolu__ vers les différents répertoires que nous venons de créer

Ok, maintenant que tout est en place, on va pouvoir commencer à faire tourner tout ça. Récuperez l’action de l’acheteur lorsqu’il valide son panier via l’URL de votre choix, et générons la requête. Depuis le controller :

@request = Atos.new.request(
  :merchant_id=>'014295303911111',
  :amount=>'1500', 
  :customer_id=>session[:customer_id],
  :automatic_response_url=>"http://mon_site.com/payment/validate",
  :normal_return_url=>"http://mon_site.com/payment/fr/confirm",
  :cancel_return_url=>"http://mon_site.com"
)

render :template=>'payment/call_request'

Si tout se passe bien, nous récupérons dans @request un formulaire HTML avec les logos des cartes, ainsi qu’une variable “DATA” dans un champ “hidden” contenant l’intégralité de notre requête cryptée, il n’y a plus qu’à l’afficher dans le template (ici avec HAML) :

%span
  = "Sélectionnez votre type de carte :"
%br
= @request

———— L’acheteur clic sur un des logos de carte et se rend sur le site de la banque. Celle-ci va maintenant nous répondre ———————

On récupère l’auto-response sur une URL à l’écoute en POST (je vous laisse créer la route de votre choix, dans mon exemple, c’est /payement/fr/validate). Il n’y a que 2 lignes à ajouter dans le controller approprié :

      
response = Atos.new.response(datas)

response[:response_code] # 00 => transaction réussie
...

Et hop, on obtiens un joli Hash avec toutes les variables de réponse disponibles dans l’API (voir le “dictionnaire des données” fourni avec l’API pour tous les détails). Maintenant, à vous de traiter cette réponse selon que le paiement a été accepté ou refusé, puis de valider l’achat dans la Base…

 

Quelques petits détails :

  • les 6 paramètres que j’utilise dans mon exemple au niveau de la requête sont les seuls à être requis par le plugin, mais vous pouvez tout à fait envoyer tous les paramètres stipulés dans le “dictionnaire des données”, rajoutez simplement les couples “clef/valeur” dans le hash de la requête.
  • Par défaut la langue et la devise utilisés sont “fr/euro”, mais vous pouvez surcharger avec ceux de votre choix au moment de l’instanciation de la classe Atos.
  • Les URL de retour (normal/cancel) sont envoyées par POST, n’oubliez donc pas d’écouter aussi en POST les routes correspondantes
  • C’est idiot mais ne pas oublier de lever la protection CSRF pour l’auto response (par rapport à mon exemple, ce serait “protect_from_forgery :except=>:validate”). Sans quoi l’auto-response ne sera jamais recevable par votre controller. C’est c** mais ça m’a couté 30mn d’arrachage de cheveux :-/.

Vous pouvez m’envoyer un Mail si vous avez des problèmes, je ne garantie rien, mais j’essaierai de répondre.