Extrait | ||
---|---|---|
|
...
todo : |
refaire les schema
|
...
|
...
Contenu :
Sommaire | ||||
---|---|---|---|---|
|
Introduction
Objet du document
Ce document décrit la procédure d’intégration de la solution de paiement sécurisé en ligne Payline en mode API DIRECT dans votre site commerçant.
Public visé
Ce document est destiné aux commerçants et intégrateurs qui souhaitent utiliser le mode d’intégration « API DIRECT » la solution de paiement Payline.
Liste des documents de référence
Nos documents sont disponibles sur notre site internet www.payline.com ou sur simple demande auprès de notre service
...
support.
...
Avertissement
Ce document est la propriété exclusive de Monext. Toute reproduction intégrale ou partielle, toute utilisation par des tiers, ou toute communication à des tiers, sans accord préalable écrit de Monext est illicite.
Monext®, marque communautaire et internationale propriété exclusive de Monext Ltd et/ou des sociétés du groupe.
Payline®, marque nationale et internationale propriété exclusive de Monext et/ou des sociétés du groupe.
Contacts
...
Prérequis et précautions
Périmètre applicable
...
Inclusion d'extrait Contactez le support Monext Online Contactez le support Monext Online nopanel true
Principe général
Présentation
Le commerçant récupère les données carte sur la page récapitulative de commande hébergée sur ses serveurs. Ce mode permet l’exécution de la demande d’autorisation en mode synchrone ou asynchrone (via stockage temporaire du CVV), l’usage des fonctionnalités de portefeuille. Le commerçant devra se mettre en conformité PCI-DSS.
...
Sécurité
La collecte des données de paiement par le site marchand implique un risque plus élevé pour le commerçant. Ce mode d’intégration nécessite donc une application rigoureuse des standards de sécurité.
En outre, deux éléments importants sont à mettre en œuvre par le marchand :
...
- La page de collecte des données de paiement ne doit stocker (fichiers logs, …) à aucun moment les informations « numéro de carte » et « CVV » saisies par l’acheteur. Ces données seront transmis à Payline au travers des
...
- appels webservices ;
...
- Le numéro de commande fourni lors de l’appel à la fonction getToken doit être bien retrouvé à l’identique lors de l’analyse de la réponse. Ce contrôle garantit que les données n’ont pas été détournées dans le but de procéder à un autre paiement que celui prévu initialement.
Prérequis techniques
Pour les serveurs PHP les exemples de code fonctionnent :
- Avec la bibliothèque gzdecode.php. qui est optionnelle jusqu’à la version 5.4.0 (disponible en standard pour les versions supérieures) ;
- Avec les modules mcrypt et php_soap
...
- . Ils doivent être à activer.
Pour les serveurs J2E, afin de pouvoir accéder aux fonctions de chiffrement avec des clés supérieures à 128 bits, il faut installer le package Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy (http://www.oracle.com/technetwork/java/javase/downloads/jce-7-download-432124.html).
Description fonctionnelle
Cinématique d’un paiement simple
Voici les étapes principales d’un paiement avec cette nouvelle interface :
- L’acheteur valide son panier, le navigateur envoie une requête http sur le serveur commerçant ;
- Le serveur commerçant :
- génère une référence unique de commande ;
- chiffre avec sa clé d’accès la chaine composée de la référence commande et du numéro de contrat ;
- construit et renvoie le formulaire au navigateur ;
- L’acheteur saisit et valide ses données (paiement, adresse de facturation, etc…) ;
- Le serveur commerçant appelle le WS Payline « doAuthorization » avec les données de paiement ;
- Le WS Payline « doAuthorization » :
- appelle la banque du commerçant pour réaliser une demande d’autorisation ;
- réalise les contrôles anti-fraude ;
- retourne le résultat au commerçant.
Figure 1 : Cinématique d’un paiement simple (sans 3DS)
Extrait | ||
---|---|---|
| ||
Cinématique d’un paiement 3DSecure V1Voici les étapes principales pour un paiement 3DSecure :
Figure 2 : Cinématique d’un paiement simple avec 3DSecure |
Extrait | ||
---|---|---|
| ||
Cinématique d’un paiement 3DSecure V1 déclenché par le module anti-fraudeVoici les étapes principales pour un paiement 3DSecure déclenché par le module anti-fraude :
|
...
Le traitement reprend à partir de l’étape 6 de la cinématique 3DS précédente :
Figure 3 : Cinématique d’un paiement avec 3DSecure déclenché par le module LCLF |
Cinématique d’un paiement 3DSecure V2
Veuillez consulter l'intégration ici : Direct Interface - Authentication and Authorization
Cinématique d’enregistrement d’une carte dans un portefeuille
...
Dans ce scénario, aucun paiement n’est réalisé.
Lorsque l’acheteur valide :
- Le navigateur de l’acheteur envoie les données de la carte à Payline (sur le module des pages Web de paiement)
...
- .
...
- Le navigateur retourne ces données au serveur
...
- commerçant.
- Le serveur
...
- commerçant appelle le WS Payline « createWallet ».
- Le WS
...
- Payline « createWallet » envoie une demande d’autorisation pour scoring à la banque du commerçant (ex : autorisation à 1 euro ou demande d'information selon la banque).
Figure 4 : Cinématique d’un enregistrement de carte dans le portefeuille Payline
Cinématique d’un second paiement
...
Dans cette cinématique, le commerçant a conservé au préalable le PAN de la carte et la date d’expiration dans sa base de données lors du premier paiement. La page de paiement affiche les cartes associées à ce compte acheteur.
Le commerçant a la possibilité de collecter le CVV auprès de son acheteur et le fournir lors de l’appel « doAuthorization » ou d’effectuer une transaction sans CVV.
Lorsque l’acheteur valide la commande :
- Le serveur commerçant :
- recherche le numéro de la carte associé au client ;
- appelle WS Payline « doAuthorization » avec la carte, avec ou sans CVV et un code action 120 ou 121.
- Le WS Payline « doAuthorization » envoie une autorisation à la banque du commerçant.
Implémentation
API webservice
Les webservices Payline ont évolué de façon à être compatible avec le paiement en mode Direct.
- doAuthorization
- createWallet
- updateWallet
- verifyAuthentication
- verifyEnrollment
- doCredit
- doDebit
Exemples d’implémentation
Trois étapes sont nécessaires :
...
Préparation de la page de collecte des données carte
Avant de présenter la page à ses acheteurs, le commerçant doit préparer les éléments qui serviront à envoyer la demande de token à Payline :
- Préparer un hash de sa clé d’accès Payline (méthode SHA-256) ;
- Affecter une référence de commande unique au panier de l’acheteur ;
- Récupérer les informations de son compte Payline : identifiant commerçant et numéro de contrat sur lequel va porter le paiement ;
- Chiffrer ces données ;
- Générer le formulaire de paiement présenté à l’acheteur en incluant les données chiffrées à l’étape précédente.
À noter que la chaîne de caractères chiffrée (obtenue à l’étape 5) doit être encodée en base64url (cf. https://fr.wikipedia.org/wiki/Base64#base64url).
Code serveur PHP
Préparer un hash de la clé d’accès :
Bloc de code | ||||
---|---|---|---|---|
| ||||
$aes256Key = hash("SHA256", $accessKey, true); |
La donnée accessKey représente la clé d’accès du commerçant
Pour chiffrer les données, il faut d’abord concaténer les données avant de chiffrer la chaine de caractères obtenue :
Bloc de code | ||||
---|---|---|---|---|
| ||||
messageUtf8 = utf8_encode($merchantId.";".$orderRef.";".$contractNumber);
$crypted crypted = getEncrypt($messageUtf8, $aes256Key);
function getEncrypt($message, $key){
$block = mcrypt_get_block_size('rijndael_128', 'ecb');
$pad = $block - (strlen($message) % $block);
$message .= str_repeat(chr($pad), $pad);
return base64_url_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $message, MCRYPT_MODE_ECB));
} |
Avec :
merchantId : identifiant Payline du commerçant
orderRef : référence unique de la commande en cours
contractNumber : numéro de contrat Payline sur lequel va porter le paiement.
Code serveur J2E
Préparer un hash de la clé d’accès :
Bloc de code | ||||
---|---|---|---|---|
| ||||
MessageDigest sha = MessageDigest.getInstance("SHA-256");
aes256Key = sha.digest(accessKey.getBytes("UTF-8")); |
La donnée accessKey représente la clé d’accès du commerçant.
Chiffrer les données. Il faut d’abord concaténer les données avant de chiffrer la chaîne de caractères obtenue :
Bloc de code | ||||
---|---|---|---|---|
| ||||
byte[] msgUtf8 = (merchantId+orderRef+ContractNumber).getBytes("UTF-8");
SecretKeySpec secretKeySpec = new SecretKeySpec(accessKeyBytes, "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec);
byte[] ciphered = cipher.doFinal(msgUtf8);
String crypted = Base64.encodeBase64URLSafeString(ciphered); |
Avec :
merchantId : identifiant Payline du commerçant ;
orderRef : référence unique de la commande en cours ;
contractNumber : numéro de contrat Payline sur lequel va porter le paiement.
...
Page de paiement
La page de paiement doit implémenter un fonctionnement qui garantit que le numéro de carte saisit par l’acheteur ne sera jamais stocké (ni par le navigateur de l’acheteur, ni par le serveur web du commerçant).
L’appel à la fonction getToken() peut se faire en mode AJAX cross-domain ou via une requête http post (fournir une URL de retour dans ce cas).
En retour un traitement côté serveur web commerçant doit être appelé afin de prendre en compte la réponse et retourner la page adéquate à l’acheteur (ticket/confirmation de paiement ou page d’erreur selon les cas).
Exemple de script d’appel AJAX :
Bloc de code | ||||
---|---|---|---|---|
| ||||
<script src="http://code.jquery.com/jquery-1.10.1.min.js"></script>
<script>
// Requête AJAX pour appeler la fonction getToken de Payline
$(document).ready( function () {
$("#paymentForm").submit( function() { // à la soumission du formulaire
jQuery.support.cors = true; // activer les requêtes ajax cross-domain
$.ajax( {
type: "POST",
url: "https://homologation-webpayment.payline.com/webpayment/getToken",
data: "data="+$("#data").val() + "&accessKeyRef=" +
$("#accessKeyRef").val() + "&cardNumber=" + $("#cardNumber").val() +
"&cardExpirationDate=" + $("#cardExpirationDate").val() +
"&cardCvx=" + $("#cardCvx").val(),
success: function(msg){ // si l'appel a bien fonctionné
$.ajax({ // fonction permettant de faire de l'ajax
type: "POST", // methode de transmission au site marchand
url: "paymentAjax.php", // traitement serveur (appel local)
data: "resultPayline="
success: function(result){ // si l'appel a bien fonctionné
// traitement du résultat OK (afficher les parametres dans cet exemple)
var divMsg = $(result);
divMsg.hide();
$("#result").append(divMsg);
divMsg.slideDown();
}
});
},
error:function (xhr, status, error){
console.log("Erreur lors de l'appel de Payline : " + xhr.responseText + " (" + status + " - " + error + ")");
}
});
return false; // pour rester sur la même page à la soumission du formulaire
});
});
</script> |
Exemple utilisable dans un formulaire du type :
Bloc de code | ||||
---|---|---|---|---|
| ||||
<form id="paymentForm" action="#" method="post">
<input type="hidden" name="data" id="data" size='255' value="<?php echo $crypted ?>" />
<input type="hidden" name="accessKeyRef" id="accessKeyRef" value="<?php echo $accessKeyRef ?>" />
<label for="">Numéro de carte</label>
<input type="text" name="cardNumber" id="cardNumber"/>
<label for="">Date d'expiration</label>
<input type="text" name="cardExpirationDate" id="cardExpirationDate"/>
<label for="">Cryptogramme</label>
<input type="text" name="cardCvx" id="cardCvx"/>
<br/>
<input type="submit" class="btn btn-primary" value="Payer" />
</form> |
Avec :
crypted : données chiffrées préparées à l’étape précédente
accessKeyRef : référence de la clé d’accès commerçant
...
Traitement de la réponse
La réponse contient des données qu’il faut déchiffrer et décompresser, le tout étant codé en base64url.
La chaine peut ensuite être découpée pour récupérer les valeurs séparées par les points-virgules.
Une fois cette étape effectuée, il est possible de procéder à toute opération sur la carte au travers de l’API Webservice Payline.
Généralement le marchand va effectuer une demande d’autorisation à Payline (avec token carte, date d’expiration et CVV virtuel) ou bien une vérification d’enrôlement 3DSecure.
Pour plus d’information sur l’API webservice, vous pouvez consulter la documentation associée.
Serveur PHP
Déchiffrer les données reçues :
Bloc de code | ||||
---|---|---|---|---|
| ||||
$zippedData = getDecrypt($data, $aes256Key);
function getDecrypt($message, $key){
$message = base64_url_decode($message);
$message = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, $message, MCRYPT_MODE_ECB);
$block = mcrypt_get_block_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_ECB);
$len = strlen($message);
$pad = ord($message[$len-1]);
return substr($message, 0, $len-$pad);
} |
La donnée data représente la valeur du paramètre ($_POST['data']) reçu en retour (cas où l’appel ne retourne pas une erreur).
Décompresser les données :
Bloc de code | ||||
---|---|---|---|---|
| ||||
$uncompressedData = gzdecode($zippedData); |
Découper le résultat pour récupérer le résultat de l’appel :
Bloc de code | ||||
---|---|---|---|---|
| ||||
$paylineDataResponse=explode(';', $uncompressedData);
$cardToken = $paylineDataResponse[0];
$cardExpirationDate = $paylineDataResponse[1];
$cardVirtualCVV = $paylineDataResponse[2];
$orderReference = $paylineDataResponse[3];
… |
Serveur J2E
Déchiffrer les données reçues :
Bloc de code | ||||
---|---|---|---|---|
| ||||
byte[] decryptedMessage = new byte[0];
zippedData = AESEncryption.decrypt(aes256Key, data);
public static final byte[] decrypt(final String key, final String message) {
byte[] decrypt = new byte[0];
MessageDigest sha = MessageDigest.getInstance("SHA-256");
keyBytes = sha.digest(key.getBytes("UTF-8"));
SecretKeySpec secretKeySpec = new SecretKeySpec(keyBytes, "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.DECRYPT_MODE, secretKeySpec);
decrypt = cipher.doFinal(Base64.decodeBase64(message.getBytes("UTF-8")));
return finalDecrypt;
} |
La donnée data représente la valeur du paramètre (request.getParameter("data")) reçu en retour (cas où l’appel ne retourne pas une erreur).
Décompresser les données :
Bloc de code | ||||
---|---|---|---|---|
| ||||
final StringBuffer outStr = new StringBuffer();
final ByteArrayInputStream gzipedStr = new ByteArrayInputStream(zippedData);
final GZIPInputStream gis = new GZIPInputStream(gzipedStr);
final BufferedReader bf = new BufferedReader(new InputStreamReader(gis));
String line;
while ((line = bf.readLine()) != null) {
outStr.append(line);
}
gis.close();
String uncompressedData = outStr.toString(); |
Découper le résultat pour récupérer le résultat de l’appel :
...
language | java |
---|---|
theme | Eclipse |
...