Comment remplacer son système de paiement Allopass par PayPal
En juillet j'ai reçu un mail de Mobiyo (la société qui a racheté Allopass) m'informant que désormais, les comptes Allopass qui généraient moins de 100 € par mois se verraient facturer 30 € de frais « au titre de frais de gestion de compte »… ou comment virer sans ménagement les petits comptes… (cf mon chapitre sur le sujet dans mon article sur l'affiliation) j'ai dû me mettre d'urgence à la recherche d'une nouvelle solution de micropaiement pour les soumissions premium sur mes annuaires de référencement.
Après un rapide passage en revue des solutions alternatives (YouPass, Rentabiliweb, Dedipass…), je me suis dit que le paiement par téléphone ou SMS n'était pas forcément essentiel. Par ailleurs, je n'avais pas envie de rempiler pour une solution qui se goinfrerait la moitié de mes gains et les garderait prisonniers tant que je n'aurais pas atteint un certain seuil, monstrueusement élevé. D'où l'idée de remplacer Allopass par une solution PayPal (solution que j'utilise déjà pour les donations à l'Encyclopédie de l'Eurodance).
L'ennui, c'est que les solutions PayPal sont multiples, leur documentation est pauvre et passablement indigeste, quand on ne tombe pas carrément sur des pages 404. Il n'y a qu'à voir les nombre de topics et de demandes d'aide qui fleurissent sur le net.
Mon besoin était le suivant :
- l'utilisateur clique sur un bouton pour accéder à la solution de paiement,
- il règle avec sa CB ou son compte PayPal,
- il est redirigé, en cas de succès, sur le formulaire de soumission premium.
Hélas, la solution la plus connue, le bouton PayPal, permet juste la redirection vers une page de remerciements. Il n'y a aucune donnée renvoyée, donc aucun moyen de vérifier que l'utilisateur s'est bien acquitté du montant demandé et n'essaie pas d'afficher directement la page.
Et malheureusement, le service client PayPal n'est plus ce qu'il était. Quant au service technique, il doit être débordé… Il m'a fallu attendre une semaine, m'énerver, tempêter (et développer ma propre solution, un bricolo à base de sessions et de document.referrer pour tester la provenance du retour…) pour enfin recevoir un mail d'un technicien de chez PayPal.
La solution se présente sous la forme de la librairie checkout.js. L'utilisateur reste sur le site du marchand, le formulaire de paiement s'ouvrant dans un popup. PayPal renvoie la réponse du paiement via javascript. A nous, en cas de transaction complétée, de rediriger vers la page voulue.
Le principe
PayPal Checkout est présentée comme une solution qui propose aux clients une expérience de checkout simplifiée et sécurisée qui leur permet de rester sur le site (ou l'application mobile) durant tout le processus de paiement.
Le principe en un schéma (repiqué sur la documentation PayPal) :
Concrètement, au clic sur le bouton jaune, la page d'appel (celle qui affichait le bouton) s'assombrit.
… Tandis que s'ouvre un popup
L'utilisateur remplit le formulaire avec ses identifiants PayPal ou choisit de régler par CB en cliquant sur « Payer sans ouvrir de compte ». Si la transaction est couronnée de succès, le popup se referme et la page d'appel redirige vers la page proposant le service premium. Pendant ce temps, vous recevez un email de service@paypal.fr intitulé « Avis de réception d'un paiement ».
La page de démo de la solution se trouve ici. La documentation du Checkout se trouve là .
Les prérequis
Votre compte Paypal doit être premier ou business.
Seuls les comptes premier et business peuvent accepter des paiements par carte bancaire.
Vous devez avoir créé un compte développeur
Rendez-vous à cette adresse pour accéder à votre compte développeur, auquel vous vous connecterez avec les mêmes identifiants que votre compte Paypal habituel. Ce compte développeur vous donne accès à la sandbox, le seul moyen d'effectuer des tests. Vous aller ajouter deux profils de test à votre sandbox : un compte vendeur et un (ou plusieurs) compte client. Attention ensuite à ne pas vous emmêler les pinceaux entre les différents comptes…
Vous pourrez ensuite vous connecter à ces comptes via la sandbox.
Vous devez créer une app pour pouvoir accéder à l'API REST
Cette étape est nécessaire pour générer un jeu d'identifiants PayPal, que vous renseignerez dans le code javascript que vous insérerez sur votre page.
Cliquer sur le bouton « Create App » et laissez-vous guider.
Vous trouverez la clé de test sous Client ID dans l'onglet Sandbox (les onglets permettant de basculer de l'un à l'autre sont en haut à droite, on passe facilement à côté la première fois).
La clé secrète ne nous servira pas.
La clé de prod (celle que vous utiliserez quand vos tests seront OK, pour de vraies transactions) se trouve, elle, sous l'onglet Live.
Mise en place du code
Sur la page qui va afficher le bouton Paypal, insérer un appel au script de paiement :
<script src="https://www.paypalobjects.com/api/checkout.js"></script>
Créer le div qui va accueillir le bouton :
<div id="paypal-button-container"></div>
Coller le code javascript vers le bas de la page, avant la balise fermante </body>. Ceci est le code de base tel qu'il est proposé à titre d'exemple par PayPal. J'ai seulement traduit les commentaires. Pour trouver les clés à saisir dans client { }, voir paragraphe précédent…
<script>
paypal.Button.render({
env: 'sandbox', // sandbox | production
// Identifiants PayPal a remplacer par les votres
// Pour creer une app PayPal : https://developer.paypal.com/developer/applications/create
client: {
sandbox: 'AZDxjDScFpQtjWTOUtWKbyN_bDt4OgqaF4eYXXXXXXXXXX-XXXXXXXXXXXXXXXXXXXXXXXXXXXXX', // le cle de test
production: 'AXKaIX3IU17XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX-XXXXXXXXXXXXXXXXXXXXXXXXXXXXX' // la cle live
},
// Affiche le bouton 'Payer' dans le flux de checkout
commit: true,
// payment() appelee quand le bouton est clique
payment: function(data, actions) {
// Effectue un appel à l'API REST afin de creer le paiement
return actions.payment.create({
payment: {
transactions: [
{
amount: { total: '0.01', currency: 'USD' }
}
]
}
});
},
// appel a onAuthorize() lorsque le client approuve le paiement
onAuthorize: function(data, actions) {
// Appel a l'API REST pour executer le paiement
return actions.payment.execute().then(function(data) {
window.alert('Payment Complete!');
});
}
}, '#paypal-button-container');
</script>
Adaptation du code
Changer le style du bouton
Il est possible de styler le bouton : coins arrondis, responsive, coloris…
style: {
label: 'pay',
size: 'responsive', // small | medium | large | responsive
shape: 'rect', // pill | rect
color: 'gold' // gold | blue | silver | black
},
Ne pas demander l'adresse postale de l'utilisateur
Dans le cas d'un service en ligne, l'adresse postale n'est pas nécessaire. On utilise le paramètre experience
experience: {
input_fields: {
no_shipping: 1
}
}
Préciser le tarif et l'unité
Adapter les paramètres dans le return actions.payment.create(). Par exemple, si on veut facturer la soumission premium 2,49€
amount: { total: '2.49', currency: 'EUR' }
Attention au caractère séparateur des décimales, c'est un point et non une virgule.
Vérifications et redirection vers la page suivante
Le code est à placer à l'intérieur de return actions.payment.execute().then(function(data) {}, à la place du window.alert(‘Payment Complete!'); que ne va servir qu'au début, pour vérifier que tout va bien.
A l'aide d'un appel en ajax, on peut :
- stocker en base certains éléments renvoyés par PayPal (date et heure de transaction, id de la transaction, state, montant…)
- mettre ces éléments en session
- ou les deux
Puis, effectuer un document.location.href() pour renvoyer l'utilisateur sur la page de retour.
Au niveau de cette page de retour, ces éléments transmis seront alors vérifiés : par exemple, rechercher dans la base un enregistrement portant l'id précédemment stocké en session ou passé en paramètre d'URL. Si PayPal ne transmet pas le statut « approved » (voir plus bas) et/ou si on ne retrouve pas la variable de session, c'est que l'utilisateur triche en essayant de charger directement la page retour.
Si l'utilisateur est effectivement en train de tricher, on peut alors rediriger l'utilisateur vers une page d'erreur. Sinon, il peut profiter du contenu de la page (formulaire de soumission premium, contenu payant…).
A vous de développer votre propre stratégie… Blindez bien, il ne faut jamais sous-estimer la créativité de l'adversaire !
Le fonctionnement en détail
L'acheteur choisit de payer avec PayPal.
Notre site envoie une requête API à PayPal appelée /v1/payments/payment (documentation)
PayPal répond à cette requête API en fournissant un « token » paymentID qui commence par PAY-……). Ce token identifie le panier de la transaction. A ce stade, la transaction n'est pas encore effectuée. Voici un exemple des données renvoyées :
intent:"sale" orderID:"EC-8RF69079BF099861R" payerID:"WSDHZWX3ET6RG" paymentID:"PAY-3VA737665T2180410LNUZZ2A" paymentToken:"EC-8RF69079BF099861R" returnUrl: "https://www.sandbox.paypal.com/?paymentId=PAY-3VA737665T2180410LNUZZ2A&token=EC-8RF69079BF099861R&PayerID=WSDHZWX3ET6RG"
Notre site utilise ce token pour rediriger l'acheteur vers la page de paiement PayPal, via l'URL fournie par approval_url de la réponse de PayPal (il ouvre cette page via un popup) :
« https://api.paypal.com/v1/payments//cgi-bin/webscr?cmd=_express-checkout&token=EC-….. »
L'acheteur choisit sa solution de paiement et clique sur « Payer ».
Notre site exécute alors la requête API « /v1/payments/payment/{payment_id}/execute » (voir documentation) , {payment_id} étant l'ID commençant par PAY-…
Voici un exemple des données renvoyées par PayPal :
cart: "4RP68406U8034772F" create_time: "2018-08-08T12:29:03Z" id: "PAY-9SA54375HB1271843LNVODDY" intent: "sale" payer: payer_info: Object { email: "client-test-paypal@yahoo.fr" first_name: "Client" middle_name: "Client" last_name: "TestFR" payer_id: "QMWBKBWXN5NUW" payment_method: "paypal" status: "VERIFIED" state: "approved" transactions: (1) […] 0: amount: total: "2.49", currency: "EUR", details: {} related_resources: (1) […] sale: amount: Object { total: "2.49", currency: "EUR", details: {…} } create_time: "2018-08-08T12:29:01Z" id: "77S60786XS407821N" parent_payment: "PAY-9SA54375HB1271843LNVODDY" payment_mode: "INSTANT_TRANSFER" protection_eligibility: "ELIGIBLE" state: "completed" update_time: "2018-08-08T12:29:01Z"
En cas de problème au niveau des clés (par exemple, utilisation d'une clé de prod alors que vous avez précisé la valeur ‘sandbox' pour env), le popup ne s'ouvrira pas au clic sur le bouton PayPal.
En conclusion, ce fut long et difficile à mettre en place, mais au moins l'argent est immédiatement disponible. Si vous voulez essayer en conditions réelles, pourquoi ne pas en profiter pour soumettre votre site en premium sur mon annuaire ?
Cette solution, tout en javascript, fonctionne également sous Free puisqu'elle ne fait pas appel à des fonctions php, qui sont interdites par l'hébergeur.
Il est conseillé de réaliser un test en conditions réelles. Malheureusement, même si vous annulez ensuite la transaction, les frais prélevés par Paypal (3,4% + 0,25€) ne sont pas remboursés…