Guide d'intégration (dépréciée)
Cette section décrit la manière d'implémenter les échanges entre le navigateur, le serveur marchand et la plateforme de paiement pendant la vérification de la carte.
1. Initier une demande de vérification de carte
Appelez le Web Service PCI/Charge/VerifyPaymentMethod en utilisant les champs ci-dessous :
NIVEAU | NOM | DESCRIPTION | REQUIS |
---|---|---|---|
1 | currency | Code (ISO 4217 alpha3) de la devise du paiement. | Oui |
1 | orderId | Référence de la commande. | Non |
1 | customer | Objet contenant les données de l'acheteur. | Oui |
2 | Adresse e-mail de l'acheteur. | Oui | |
1 | paymentForms | Objet contenant les données de la carte. | Oui |
2 | paymentMethodType | Type du moyen de paiement. Doit être valorisé à CARD. | Oui |
2 | pan | Numéro de carte. | Oui |
2 | expiryMonth | Mois d'expiration de la carte. | Oui |
2 | expiryYear | Année d'expiration de la carte. | Oui |
2 | securityCode | Code de sécurité de la carte (CVV ou 4DBC). | Non |
1 | device | Objet décrivant les informations du navigateur nécessaires à l'authentification du porteur. | Oui |
2 | deviceType | Type d'équipement sur lequel s'effectue le paiement. Valeur possible :
| Oui |
2 | acceptHeader | Contenu exact du header HTTP "accept" tel qu'envoyé par le navigateur de l'acheteur. | Oui |
2 | userAgent | Contenu exact de l'entête HTTP "user-agent" envoyé par le navigateur. Obtenue du navigateur client via la propriété navigator.userAgent. Doit être tronqué si la valeur dépasse 2048 caractères. | Oui |
2 | ip | Adresse IP (V4 ou V6) du navigateur telle que renvoyée dans les entêtes HTTP par le navigateur. | Non |
2 | javaEnabled | Booléen qui représente la capacité du navigateur à exécuter du Java. Obtenue du navigateur client via la propriété navigator.javaEnabled(). Valeurs possibles :"true" ou "false". | Oui |
2 | language | Chaîne de caractère indiquant la langue du navigateur. Obtenue du navigateur client via la propriété navigator.language. Exemples : "en", "en-US", "de", "fr". | Oui |
2 | colorDepth | Valeur représentant la profondeur de la palette de couleurs utilisée par l'équipement pour afficher les images, en bits par pixel. Obtenue du navigateur client via la propriété screen.colorDepth. | Oui |
2 | screenHeight | La hauteur totale de l'écran de l'équipement en pixels. Obtenue du navigateur client via la propriété screen.height. | Oui |
2 | screenWidth | La largeur totale de l'écran de l'équipement en pixels. Obtenue du navigateur client via la propriété screen.width. | Oui |
2 | timeZoneOffset | Différence de temps entre le temps UTC et le temps local du navigateur client, en minutes. Sa valeur est de -120 pour un utilisateur dans le fuseau horaire UTC+2 et de 570 pour le fuseau horaire UTC−09:30. | Oui |
D'autres champs facultatifs sont disponibles. Retrouvez la description des champs dans notre playground.
Exemple de requête
{ "currency": "EUR", "orderId":"myOrderId", "paymentForms": [ { "paymentMethodType": "CARD", "pan": "4970100000000014", "brand": "VISA", "expiryMonth": "02", "expiryYear": "22", "securityCode": "123" } ], "customer": { "email": "sample@example.com" }, "device": { "deviceType": "BROWSER", "acceptHeader": "application/json", "ip": "89.249.65.28", "javaEnabled": true, "language": "en", "colorDepth": "1", "screenHeight": 1024, "screenWidth": 768, "timezoneOffset": 0, "userAgent": "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:47.0) Gecko/20100101 Firefox/47.0" } }
/** * I initialize the PHP SDK */ require_once __DIR__ . '/vendor/autoload.php'; require_once __DIR__ . '/keys.php'; require_once __DIR__ . '/helpers.php'; /** * Initialize the SDK * see keys.php */ $client = new Lyra\Client(); /** * I create a formToken */ $store = array("amount" => 250, "currency" => "EUR", "orderId" => uniqid("MyOrderId"), "customer" => array( "email" => "sample@example.com" )); $response = $client->post("V4/Charge/CreatePayment", $store); /* I check if there are some errors */ if ($response['status'] != 'SUCCESS') { /* an error occurs, I throw an exception */ display_error($response); $error = $response['answer']; throw new Exception("error " . $error['errorCode'] . ": " . $error['errorMessage'] ); } /* everything is fine, I extract the formToken */ $formToken = $response["answer"]["formToken"]; ?>
La suite du processus dépend de la présence d'un objet AuthenticationInstruction dans la réponse :
- si la réponse contient un objet AuthenticationInstruction, vous devez traiter l'instruction pour procéder à l'authentification du porteur.
- si la réponse contient un objet Payment, le processus est terminé.
2. Traitement des instructions
La réponse à l'appel au service PCI/Charge/VerifyPaymentMethod contient un objet AuthenticationInstruction
:
- si la réponse contient une instruction
CHALLENGE
, vous créez une iFrame **visible** pour afficher la page d'authentification. - si la réponse contient une instruction
FINGERPRINT
, vous créez une iFrame **invisible** pour afficher la page d'exécution du code JavaScript de l'ACS.
2.1. Création de l'iFrame
Quel que soit le type d'instruction reçue (CHALLENGE
ou FINGERPRINT
), vous devez construire une iFrame en utilisant les données reçues dans l'objet target
.
Exemples de données transmises en fonction du type d'instruction
Instruction "CHALLENGE" | "target":{ "element":"IFRAME", "visible":true, "width":500, "height":600, "_type":"V4/Charge/Authenticate/InstructionTarget" } |
Instruction "FINGERPRINT" (3DS Method) | "target":{ "element":"IFRAME", "visible":false, "_type":"V4/Charge/Authenticate/InstructionTarget" } |
2.2. Soumission du formulaire de demande d'authentification
Une fois l'iFrame créée, utilisez les données reçues dans l'objet http
pour permettre :
- soit l'affichage de la page d'authentification de l'émetteur du moyen de paiement, pour une instruction de type
CHALLENGE
, - soit l'exécution du code JavaScript de l'ACS de l'émetteur de moyen de paiement, pour une instruction de type
FINGERPRINT
.
Exemples de données transmises dans l'objet http :
Challenge 3DS2 | "http":{ "method":"POST", "url":"https://acs.sg.com/v2/creq", "body":{ "creq":"eyJ0aHJlZURTU2Vy...", "threeDSSessionData":"H4sIAAAAAAAAAC2OyZK..." }, "_type":"V4/Charge/Authenticate/HttpRequest" }, |
Fingerprint | "http":{ "method":"POST", "url":"https://acs.sg.com/v2/3dsMethod", "body":{ "threeDSMethodData":"eyJ0aHJlZURzTW..." }, "_type":"V4/Charge/Authenticate/HttpRequest" }, |
Exemple d'implémentation JavaScript
function createInstructionIframe(instruction) { // Get instruction container element container = document.getElementById('instructionContainer'); // Clean instruction container container.innerHTML = ''; // Create iframe element var iframe = document.createElement('iframe'); iframe.id = 'instructionIframe'; iframe.name = 'instructionIframe'; iframe.src = 'about:blank'; iframe.style.width = instruction.value.target.width+"px"; iframe.style.height = instruction.value.target.height+"px"; iframe.style.visibility = instruction.value.target.visible ? 'visible' : 'hidden'; // Handle timeout if(instruction.value.timeout){ setTimeout(() => { const instructionResultTimeout = { eventName: 'LYRA_AUTH_INSTRUCTION_RESULT', value: { name: instruction.value.name, value: 'TIMEOUT', protocol: { name: instruction.protocol.name, version: instruction.protocol.version, network: instruction.protocol.network, challengePreference: instruction.protocol.challengePreference, simulation: instruction.protocol.simulation }, }, }; window.postMessage(JSON.stringify(instructionResultTimeout), '*'); }, instruction.value.timeout * 1000); } // Add iframe to container container.appendChild(iframe); // Create form to post var form = document.createElement('form'); form.id = 'instructionForm'; form.name = 'instructionForm'; form.target = 'instructionIframe'; form.method = instruction.value.http.method; form.action = instruction.value.http.url; form.style = 'visibility: hidden'; // Create form body Object.keys(instruction.value.http.body).forEach(function (name) { form.innerHTML += '<input name="' + name + '" value="' + instruction.value.http.body[name] + '">'; }); var body = document.createElement('form'); // Add form to container container.appendChild(form); // Triger form submit form.submit(); }
Exemple d'appel de la fonction createInstructionIframe en PHP
//Call the PCI/Charge/VerifyPaymentMethod method $obj = verifypaymentmethod($data); if ($obj['answer']['_type']== 'V4/AuthenticationResponseData'){ $response= $obj['answer']; //Test if anwser contains an instruction if($response['value']['_type'] == 'V4/Charge/Authenticate/AuthenticationInstruction'){ $_SESSION['operationSessionId'] = $response['operationSessionId']; //create an iFrame to proceed to the payer authentication echo '<script>window.onload = function(){ var instruction =JSON.parse(\''. json_encode($response) .'\'); createInstructionIframe(instruction);}</script>'; } }
3. Mise en place d'un listener d'événement
Après authentification du porteur du moyen de paiement ou après exécution du 3DS Method, le navigateur du client transmet une réponse sous forme d'événement JavaScript.
Utilisez le code suivant pour capter l'événement :
window.addEventListener('message', function (messageEvent) { var data = messageEvent.data; try { var messageData = JSON.parse(data); if (messageData.eventName === 'LYRA_AUTH_INSTRUCTION_RESULT') { try { // callback call with messageData.value content container = document.getElementById('instructionContainer'); var form = document.createElement('form'); form.method = 'POST'; form.action = "https://myhost.com/payment/authentication/result.php"; form.style = 'visibility: hidden'; form.innerHTML += "<input name='messageData' value='" + data + "'>"; var body = document.createElement('form'); container.appendChild(form); form.submit(); } catch (err) { // error callback call } finally { // always close the iFrame/popin container = document.getElementById('instructionContainer'); container.remove(); } } } catch (err) { // process eventual exceptions during callbacks } }, false);
Exemples d'événements "LYRA_AUTH_INSTRUCTION_RESULT"
après une authentification Challenge 3DS2 |
|
après exécution du code 3DS Method de l'ACS (authentification 3DS2) |
|
en cas de timeout durant un challenge (3DS2) |
|
4. Gestion des événements "LYRA_AUTH_INSTRUCTION_RESULT"
Lorsqu'un événement LYRA_AUTH_INSTRUCTION_RESULT
est reçu, appelez le Web Service PCI/Charge/VerifyPaymentMethod afin de décoder son contenu.
Utilisez les champs suivants dans votre requête :
NOM | DESCRIPTION | requis |
---|---|---|
operationSessionId | Identifiant de la requête d'authentification fourni dans la réponse à l'appel initial. | Oui |
instructionResult | Objet contenant le détail de l'instruction reçu dans l'événement JavaScript "LYRA_AUTH_INSTRUCTION_RESULT". | Oui |
Exemple de requête
{ "instructionResult": { "name" : "CHALLENGE", "value": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c", "protocol" : { "name" : "THREEDS", "network": "VISA", "version" : "2.0.2", "challengePreference": "NO_PREFERENCE", "simulation": false } }, "operationSessionId": "c7f9c8711d994aa5818f886dc995e9eb" }
/** * I initialize the PHP SDK */ require_once __DIR__ . '/vendor/autoload.php'; require_once __DIR__ . '/keys.php'; require_once __DIR__ . '/helpers.php'; /** * Initialize the SDK * see keys.php */ $client = new Lyra\Client(); /** * I create a formToken */ $store = array("amount" => 250, "currency" => "EUR", "orderId" => uniqid("MyOrderId"), "customer" => array( "email" => "sample@example.com" )); $response = $client->post("V4/Charge/CreatePayment", $store); /* I check if there are some errors */ if ($response['status'] != 'SUCCESS') { /* an error occurs, I throw an exception */ display_error($response); $error = $response['answer']; throw new Exception("error " . $error['errorCode'] . ": " . $error['errorMessage'] ); } /* everything is fine, I extract the formToken */ $formToken = $response["answer"]["formToken"]; ?>
AuthenticationInstruction
dans la
réponse :
* La réponse contient un objet AuthenticationInstruction
: vous devez traiter l'instruction pour continuer le processus d'authentification du porteur.
* La réponse contient un objet Payment
: le procesus est terminé.
5. URL de notification à la fin du paiement
A la fin de l'opération, vous recevrez une IPN uniquement si la réponse à l'appel initial est de type AuthenticationInstruction.
Lorsque la réponse à l'appel initial est de type Payment, il vous suffit d'analyser son contenu pour obtenir le résultat de la création de l'alias.
C'est le cas notamment :
- lorsque la carte ou le marchand n'est pas enrôlé 3D Secure,
- si vous avez désactivé l'authentification du porteur,
- si l'authentification du porteur se fait sans interaction et sans 3DS Method.
Pour plus d'informations sur le fonctionnement ou la configuration des règles de notification, consultez le chapitre Analyse de l'IPN (URL de notification).
6. Analyse du résultat final
La réponse contient un objet Payment décrivant le détail de la vérification (résultat de la demande de renseignement, résultat de l'authentification du porteur, etc...).
Consultez la description de l'objet Payment depuis notre playground.