Service de création d'alias PCI
Ce service de création d'alias permet aux marchands PCI-DSS de créer un alias en passant les informations de cartes dans la requête.
Dans le cadre de la DSP2, il est obligatoire d'authentifier le porteur de la carte via le protocole 3D Secure. Le service authentifie le porteur de carte et renvoie les informations d'authentification à la fin du processus.
Principe général
Ce WS permet la création d'un alias de la carte envoyé dans la requête. Il sera alors possible d'utiliser cet alias lors de paiement futur sans avoir à saisir de nouveau les informations de la carte de l'acheteur.
Pour cela, l'appel au web service PCI/Charge/CreateToken déclenche une transaction de vérification. Comme dit précédemment, dans le cadre de la DSP2, il est obligatoire d'authentifier le porteur via le protocole 3D Secure. Le déroulement du scénario est donc le suivant:
- Appel du web service PCI/Charge/CreateToken
- La réponse peut être de 2 types:
- AuthenticationResponseData: Cette réponse indique qu'il est nécessaire de procéder à l'authentification du porteur. Vous devrez alors rappeler le même PCI/Charge/CreateToken avec le résultat de l'instruction pour l'authentification 3D Secure.
- Charge/Payment: Cette réponse indique la fin de la vérification et la création de l'alias. Il est alors possible de vérifier le résultat dans la réponse.
L'authentification occupant une place importante dans ce web service, son fonctionnement a été détaillé ci-dessous:
Déroulement de l'authentification
Le service adopte un principe de fonctionnement qui fait abstraction du protocole sous-jacent pour permettre une intégration unique, et non pas une intégration par protocole.
La cinématique générique d'une authentification complète peut être décomposée en plusieurs étapes:
- un appel initial au service PCI/Charge/CreateToken avec une réponse de type AuthenticationResult ou AuthenticationInstruction.
- si le retour est de type AuthenticationInstruction, c'est une opération qu'il convient de réaliser côté marchand :
- création d'une iFrame visible ou invisible
- dans l'iFrame, redirection du navigateur vers la cible avec un formulaire qui suit la définition présente dans l'instruction
- interaction éventuelle avec le porteur de carte, ou le navigateur
- page de retour du serveur distant qui émettra un événement JavaScript contenant le résultat de l'instruction
- interception du résultat de l'instruction sous forme d'événement JavaScript dans la page parente
- nouvel appel au service PCI/Charge/CreateToken avec le résultat signé de l'instruction obtenu via le navigateur
- le service PCI/Charge/CreateToken renvoie alors à nouveau soit une instruction soit un résultat
- si le retour est de type AuthenticationResult, alors celui-ci contiendra le résultat d'authentification final et le processus est terminé.
Diagramme détaillé
Le diagramme suivant détaille un scénario générique de paiement avec une authentification: l'appel initial au service, une instruction, une interaction, un résultat final d'authentification et la fin du paiement.
Client
Navigateur
iFrame
Serveur Marchand
Serveur de la Plateforme de paiement
Serveur distant (ex: ACS)
Nous allons détailler les différentes étapes d'intégration dans les paragraphes suivants.
Intégration | Etapes |
---|---|
Actions à réaliser côté serveur marchand | étapes 3, 4, 16 et 17 |
Actions à réaliser côté JavaScript | étapes 5, 6, 7 et 15 |
Etape 1 et 2: Initiation (paiement ou ajout de carte)
Une action de paiement ou un enregistrement de carte à été initié et nécessite une authentification. Le service PCI/Charge/CreateToken est donc prêt à être appelé.
Etape 3: Appel du service PCI/Charge/CreateToken
La requête initiale permet de transmettre les données nécessaires à l'authentification.
Parmi ces données, il est nécessaire de renseigner certaines informations relatives au navigateur ou à l'équipement mobile du client dans l'objet device.
Ces informations sont pour la plus part techniques et doivent être récupérées depuis le navigateur ou le mobile (en JavaScript par exemple).
L'objectif étant de faciliter l'identification du client (adresse IP) et de son support de paiement (taille du navigateur) pour permettre un processus d'authentification plus adapté.
Consultez la documentation d'intégration du service PCI/Charge/CreateToken pour plus d'informations sur ce champ.
Ci-dessous un exemple décrivant la requête initiale:
{ "currency": "EUR", "orderId":"myOrderId", "paymentForms": [ { "paymentMethodType": "CARD", "pan": "4970100000000014", "brand": "VISA", "expiryMonth": "02", "expiryYear": "27", "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"]; ?>
Etape 4: Réponse complète avec une instruction
La réponse contiendra une instruction sous la forme suivante (dans cet exemple il s'agit d'une authentification 3DS v1 (déprécié)):
{ "answer": { "id": "c82794e9-9c20-44a8-9297-b70e1e7c4006", "operationSessionId": "c7f9c8711d994aa5818f886dc995e9eb", "protocol": { "name": "THREEDS", "network": "VISA", "version": "1.0.2", "challengePreference":"NO_PREFERENCE", "simulation":false, "_type": "V4/PCI/Charge/Authenticate/Protocol" }, "value": { "instructionType": "FORM", "name": "CHALLENGE", "timeout" : "15", "target": { "element": "IFRAME", "visible": true, "width": 400, "height": 400, "_type": "V4/PCI/Charge/Authenticate/InstructionTarget" }, "http": { "method": "POST", "url": "https://acs.sg.com/1.0.2", "headers": { "Accept": "text/html" }, "body": { "termUrl": "https://pass.sample-acs.net/v1/notify/threeds/v1/pares", "MD": "eJwljEmSokAAAL8yd2O6imLVCA+oINAKCLLekALZd2ggePz0dF/ylJnEB/xAG8GQLLcRiKRoZgtWnHtkwniZfw2qontZg4mvIv2SrOOGIMERCDJ/CHSg2QMkNpqEcNt/52iDEP1/bdVYFFsyDM0BgKIOgyKp++HAQQ6CKcD93yZYyqgawK/4A6VlbYPzWv0OZu3Gj04+rf6LMlQP8db81Tm7JXBxyrM3cKIYaV7GedZVQdLkWAo6W+ufqbUMjQxLQvkUIG8k384FpmsJfG2fQ0qzI3rulyLFqkPMYD9No8B48rkcrmI59ar3Yk29l6k8EQJPDlc9p+OqPzuxhul33WZx2TvmyNBxswb2U9OmCHFhelH8WI6e3nV2xVACYrHwadbjVpKbxxjWjywfgi7EK3ZWGTMnsSl2baxnlWKWhmXuqpOXX2JBhDDUebZccWyNOagnJHKm+kgz//4OF8oyrWig5hIAw1LL7jNTTkiw76DgJDl2VXKxGc4h0O1W9e4k1b4LPeRfzsh6H4//ANdloIQ=", "paReq": "eJxVUslu2zAQ/RVBd5mLLZk2RgzSBlkOCYLGPqSXgss4VmNJDkkHdr4+pKosPXHezPDN4xvC2bHdZa/ofNN3dc4mNM+wM71tuqc6X68uC5FnPqjOql3fYZ2f0OdnElZbh3jxgObgUMIteq+eMGtsnf8RSghqDS0st7yY0WpeaKNZoamwrFpQzSvMJdyf/8IXCeNoGSdPOJAPGCmd2aouSFDm5cfNnWTVdC6AjAhadDcXkvHprKyA/EPQqRblrRpu2hX6AGRIgekPXXAnyUsK5APAwe3kNoS9XxLSjrcmpm+BpAqQLw33hxT5yHRsrFRv9vlxuq0e//6+Ut3O6XV4sFeXpb5e10BSB1gVUHLKBOO0yhhflvMlZUCGPKg2SZDllEY5I4B9mnH+vfI9A9FpFzdzkotkwycCPO7jYmJHdO8zBovexBeMx5f8n9fJUBOSdxsurFa0VJrPNqg0ZTjb2LnhJU8+D02JvoleMUEXA38CQBINGTdIxu3H6L9f8Q7HNMYj" }, "_type": "V4/PCI/Charge/Authenticate/HttpRequest" }, "_type": "V4/PCI/Charge/Authenticate/AuthenticationInstruction" }, "_type": "V4/AuthenticationResponseData" } }
Le contenu se décompose en :
Objet | Fonction |
---|---|
id | Identifiant unique de la transaction d'authentification en cours. |
operationSessionId | Identifiant de session unique de l'opération en cours. Il devra être retransmis à chaque nouvel appel. |
protocol | Indique quel protocole sera effectivement appliqué lors de l'authentification. |
value | Représente le résultat de l'authentification ou l'instruction à suivre. Si value est de type AuthenticationInstruction, il s'agit d'une instruction à exécuter, s'il est de type AuthenticationResult, il s'agit du résultat de l'authentification. |
Etape 5 : Préparation de la page de gestion de l'instruction
Si une instruction à été retournée lors de l'étape précédente, la page à afficher lors de cette étape doit permettre :
- la mise en place d'un listener sur le type d'événement renvoyé par l'iFrame, qui déclenchera un POST vers le serveur marchand avec le résultat d'instruction (cf.étape 15).
- la création d'iFrame masquée ou visible (cf.étapes 6 et 7).
Etape 6 : Création de l'iFrame
L'instruction reçue lors de l'étape 4 est donc comme suit:
{ "instructionType": "FORM", "name": "CHALLENGE", "timeout" : "15", "target": { "element": "IFRAME", "visible": true, "width": 400, "height": 400, "_type": "V4/PCI/Charge/Authenticate/InstructionTarget" }, "http": { "method": "POST", "url": "https://acs.sg.com/1.0.2", "headers": { "Accept": "text/html" }, "body": { "termUrl": "https://pass.sample-acs.net/v1/notify/threeds/v1/pares", "MD": "eJwljEmSokAAAL8yd2O6imLVCA+oINAKCLLekALZd2ggePz0dF/ylJnEB/xAG8GQLLcRiKRoZgtWnHtkwniZfw2qontZg4mvIv2SrOOGIMERCDJ/CHSg2QMkNpqEcNt/52iDEP1/bdVYFFsyDM0BgKIOgyKp++HAQQ6CKcD93yZYyqgawK/4A6VlbYPzWv0OZu3Gj04+rf6LMlQP8db81Tm7JXBxyrM3cKIYaV7GedZVQdLkWAo6W+ufqbUMjQxLQvkUIG8k384FpmsJfG2fQ0qzI3rulyLFqkPMYD9No8B48rkcrmI59ar3Yk29l6k8EQJPDlc9p+OqPzuxhul33WZx2TvmyNBxswb2U9OmCHFhelH8WI6e3nV2xVACYrHwadbjVpKbxxjWjywfgi7EK3ZWGTMnsSl2baxnlWKWhmXuqpOXX2JBhDDUebZccWyNOagnJHKm+kgz//4OF8oyrWig5hIAw1LL7jNTTkiw76DgJDl2VXKxGc4h0O1W9e4k1b4LPeRfzsh6H4//ANdloIQ=", "paReq": "eJxVUslu2zAQ/RVBd5mLLZk2RgzSBlkOCYLGPqSXgss4VmNJDkkHdr4+pKosPXHezPDN4xvC2bHdZa/ofNN3dc4mNM+wM71tuqc6X68uC5FnPqjOql3fYZ2f0OdnElZbh3jxgObgUMIteq+eMGtsnf8RSghqDS0st7yY0WpeaKNZoamwrFpQzSvMJdyf/8IXCeNoGSdPOJAPGCmd2aouSFDm5cfNnWTVdC6AjAhadDcXkvHprKyA/EPQqRblrRpu2hX6AGRIgekPXXAnyUsK5APAwe3kNoS9XxLSjrcmpm+BpAqQLw33hxT5yHRsrFRv9vlxuq0e//6+Ut3O6XV4sFeXpb5e10BSB1gVUHLKBOO0yhhflvMlZUCGPKg2SZDllEY5I4B9mnH+vfI9A9FpFzdzkotkwycCPO7jYmJHdO8zBovexBeMx5f8n9fJUBOSdxsurFa0VJrPNqg0ZTjb2LnhJU8+D02JvoleMUEXA38CQBINGTdIxu3H6L9f8Q7HNMYj" }, "_type": "V4/PCI/Charge/Authenticate/HttpRequest" }, "_type": "V4/PCI/Charge/Authenticate/AuthenticationInstruction" }
Les différentes propriétés de l'iFrame à créer se trouvent dans l'élément target:
"target": { "element": "IFRAME", "visible": true, "width": 400, "height": 400 }
Si elle doit être visible (attribut value.target.visible à true), alors créer l'iFrame avec ces paramètres (largeur selon width et hauteur selon height) et la montrer, sinon créer une iframe masquée.
Gestion du timeout d'affichage de l'iframe
Il est également nécessaire de gérer la durée d'affichage maximum de l'iframe si l'attribut value.timeout est présent dans l'instruction (timeout définit en seconde). Pour se faire il faudra permettre le déclenchement d'un événement de type LYRA_AUTH_INSTRUCTION_RESULT valorisé comme suit:
{ eventName: 'LYRA_AUTH_INSTRUCTION_RESULT', value: { name: "Add here the instruction name you have received in the answer", value: 'TIMEOUT', protocol: "Add here the protocol object you have received in the answer" } }
Exemple d'implémentation :
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(); }
Etape 7 : Soumission du formulaire
Une fois l'iFrame créée, il faut la remplir avec un formulaire en suivant les instructions de la balise 'http':
"http": { "method": "POST", "url": "https://acs.sg.com/1.0.2", "headers": { "Accept": "text/html" }, "body": { "termUrl": "https://pass.sample-acs.net/v1/notify/threeds/v1/pares", "MD": "eJwljEmSokAAAL8yd2O6imLVCA+oINAKCLLekALZd2ggePz0dF/ylJnEB/xAG8GQLLcRiKRoZgtWnHtkwniZfw2qontZg4mvIv2SrOOGIMERCDJ/CHSg2QMkNpqEcNt/52iDEP1/bdVYFFsyDM0BgKIOgyKp++HAQQ6CKcD93yZYyqgawK/4A6VlbYPzWv0OZu3Gj04+rf6LMlQP8db81Tm7JXBxyrM3cKIYaV7GedZVQdLkWAo6W+ufqbUMjQxLQvkUIG8k384FpmsJfG2fQ0qzI3rulyLFqkPMYD9No8B48rkcrmI59ar3Yk29l6k8EQJPDlc9p+OqPzuxhul33WZx2TvmyNBxswb2U9OmCHFhelH8WI6e3nV2xVACYrHwadbjVpKbxxjWjywfgi7EK3ZWGTMnsSl2baxnlWKWhmXuqpOXX2JBhDDUebZccWyNOagnJHKm+kgz//4OF8oyrWig5hIAw1LL7jNTTkiw76DgJDl2VXKxGc4h0O1W9e4k1b4LPeRfzsh6H4//ANdloIQ=", "paReq": "eJxVUslu2zAQ/RVBd5mLLZk2RgzSBlkOCYLGPqSXgss4VmNJDkkHdr4+pKosPXHezPDN4xvC2bHdZa/ofNN3dc4mNM+wM71tuqc6X68uC5FnPqjOql3fYZ2f0OdnElZbh3jxgObgUMIteq+eMGtsnf8RSghqDS0st7yY0WpeaKNZoamwrFpQzSvMJdyf/8IXCeNoGSdPOJAPGCmd2aouSFDm5cfNnWTVdC6AjAhadDcXkvHprKyA/EPQqRblrRpu2hX6AGRIgekPXXAnyUsK5APAwe3kNoS9XxLSjrcmpm+BpAqQLw33hxT5yHRsrFRv9vlxuq0e//6+Ut3O6XV4sFeXpb5e10BSB1gVUHLKBOO0yhhflvMlZUCGPKg2SZDllEY5I4B9mnH+vfI9A9FpFzdzkotkwycCPO7jYmJHdO8zBovexBeMx5f8n9fJUBOSdxsurFa0VJrPNqg0ZTjb2LnhJU8+D02JvoleMUEXA38CQBINGTdIxu3H6L9f8Q7HNMYj" }, "_type": "V4/PCI/Charge/Authenticate/HttpRequest" }
- la propriété method indique le verbe HTTP à associer au formulaire
- url indique vers quel serveur doit pointer l'action du formulaire
- les entêtes de la requête http dans headers
- les paramètres du formulaire dans body (ici par exemple termUrl, MD et paReq)
Une fois le formulaire généré et placé dans l'iFrame, il ne reste plus qu'à déclencher la soumission au chargement de la page.
Dans le cas où le timeout paramétré dans le code de création de l'iframe se déclenche, l'événement de type LYRA_AUTH_INSTRUCTION_RESULT sera capté par le listener dont les détails sont décrits à l'étape 15. Cela permettra la poursuite du processus et d'avoir un résultat final.
Etapes 8 à 14 : Authentification de l'utilisateur
Une fois le formulaire posté, le code de la banque émettrice va prendre la main sur le processus afin de permettre l'authentification sécurisée (silencieuse ou interactive). A la fin de cette étape, l'événement LYRA_AUTH_INSTRUCTION_RESULT sera émis depuis l'iFrame afin d'indiquer la fin du processus. Exemple:
{ "eventName": "LYRA_AUTH_INSTRUCTION_RESULT", "value" : { "value": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c", "name": "CHALLENGE", "protocol": { "name": "THREEDS", "version": "2.1.0", "network": "VISA", "challengePreference" : "NO_PREFERENCE", "simulation": "false" } } }
Etape 15 : Récupération de l'événement JavaScript émis à l'étape 14
Afin d'interpréter l'événemment LYRA_AUTH_INSTRUCTION_RESULT, il est nécessaire de mettre en place un listener sur la page principale. Ce dernier doit être capable de parser du code JSON et peut être écrit ainsi:
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);
Il convient ensuite de renvoyer ces informations vers le serveur marchand.
Etape 16 : Renvoi au serveur marchand du résultat d'instruction
Une fois le résultat d'instruction récupéré côté serveur marchand, il doit être renvoyé via un nouvel appel au service PCI/Charge/CreateToken. La requête devra contenir l'objet instructionResult ainsi que l'identifiant de session operationSessionId, reçu dans la réponse de l'étape 4:
{ "instructionResult": { "name" : "CHALLENGE", "value": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c", "protocol" : { "name" : "THREEDS", "network": "VISA", "version" : "1.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"]; ?>
Etape 17 : Réception de la réponse du serveur de la plateforme de paiement
Tout comme à l'étape 4, le serveur marchand reçoit une nouvelle réponse, qui peut soit être finale (AuthenticationResult), soit demander une nouvelle instruction (AuthenticationInstruction). Dans ce dernier cas, le flux reprend à l’étape 5. Voici l'exemple d'un message final:
{ "answer": { "shopId": "33148340", "orderCycle": "CLOSED", "orderStatus": "PAID", "serverDate": "2020-03-23T14:31:14+00:00", "orderDetails": { "orderTotalAmount": 0, "orderEffectiveAmount": 0, "orderCurrency": "EUR", "mode": "TEST", "orderId": "myOrder" }, "customer": { "billingDetails": { "address": null, "category": null, "cellPhoneNumber": null, "city": null, "country": null, "district": null, "firstName": null, "identityCode": null, "language": "FR", "lastName": null, "phoneNumber": null, "state": null, "streetNumber": null, "title": null, "zipCode": null }, "email": "sample@example.com", "reference": null, "shippingDetails": { "address": null, "address2": null, "category": null, "city": null, "country": null, "deliveryCompanyName": null, "district": null, "firstName": null, "identityCode": null, "lastName": null, "legalName": null, "phoneNumber": null, "shippingMethod": null, "shippingSpeed": null, "state": null, "streetNumber": null, "zipCode": null }, "extraDetails": { "browserAccept": null, "fingerPrintId": null, "ipAddress": "10.33.160.29", "browserUserAgent": "PostmanRuntime/7.23.0" }, "shoppingCart": { "insuranceAmount": null, "shippingAmount": null, "taxAmount": null, "cartItemInfo": null } }, "transactions": [ { "shopId": "33148340", "uuid": "ca83e404cd134bef95dff577927d2e09", "amount": 0, "currency": "EUR", "paymentMethodType": "CARD", "paymentMethodToken": null, "status": "PAID", "detailedStatus": "ACCEPTED", "operationType": "VERIFICATION", "effectiveStrongAuthentication": "DISABLED", "creationDate": "2020-03-23T14:31:13+00:00", "errorCode": null, "errorMessage": null, "detailedErrorCode": null, "detailedErrorMessage": null, "metadata": null, "transactionDetails": { "liabilityShift": "NO", "effectiveAmount": 0, "effectiveCurrency": "EUR", "creationContext": "VERIFICATION", "cardDetails": { "paymentSource": "EC", "manualValidation": "NO", "expectedCaptureDate": null, "effectiveBrand": "VISA", "pan": "497010XXXXXX0055", "expiryMonth": 11, "expiryYear": 2021, "country": "FR", "issuerCode": 17807, "issuerName": "BP Occitane", "effectiveProductCode": null, "legacyTransId": "923865", "legacyTransDate": "2020-03-23T14:31:13+00:00", "paymentMethodSource": "TOKEN", "authorizationResponse": { "amount": null, "currency": null, "authorizationDate": null, "authorizationNumber": null, "authorizationResult": null, "authorizationMode": "MARK" }, "captureResponse": { "refundAmount": null, "captureDate": null, "captureFileNumber": null, "refundCurrency": null }, "threeDSResponse": { "authenticationResultData": { "transactionCondition": null, "enrolled": null, "status": null, "eci": null, "xid": null, "cavvAlgorithm": null, "cavv": null, "signValid": null, "brand": null } }, "authenticationResponse": { "id": "451d6c8b-8ba9-4a10-854f-34308e5cff3b", "operationSessionId": "c7f9c8711d994aa5818f886dc995e9eb", "protocol": { "name": "THREEDS", "network": "VISA", "version": "1.0.2", "challengePreference": "NO_PREFERENCE", "simulation": false }, "value": { "authenticationType": "CHALLENGE", "authenticationId": { "authenticationIdType":"xid", "value":"c82794e99c2044a89297b70e1e7c4006" }, "authenticationValue": { "authenticationValueType": "CAVV", "value": "FsXD4Ox0VEI2MseoR0VhN5pX952I" }, "status": "SUCCESS", "commerceIndicator": "05", "extension": { "enrolled": "Y", "algorithm": "2", "signatureValid": true }, "reason": { "_type": "V4/PCI/Charge/Authenticate/AuthenticationResultReason" } } }, "installmentNumber": null, "installmentCode": null, "markAuthorizationResponse": { "amount": 0, "currency": "EUR", "authorizationDate": "2020-03-23T14:31:13+00:00", "authorizationNumber": "3fefaa", "authorizationResult": "0" }, "cardHolderName": null, "identityDocumentNumber": null, "identityDocumentType": null }, "parentTransactionUuid": null, "mid": "1549425", "sequenceNumber": 1, "taxAmount": null, "preTaxAmount": null, "taxRate": null, "externalTransactionId": null, "_type": "V4/TransactionDetails" } } ] } }
Etape 18 : Poursuite des opérations par le Serveur marchand
Si la réponse précédente est un résultat final, la création de l'alias est terminée.
Annexes
Exemple de cinématique : Authentification 3DS v2 avec authentification sur l'ACS
- un appel initial au service PCI/Charge/CreateToken avec une carte enrôlée 3DS v2
- un retour avec une instruction FINGERPRINT (3DS Method)
- une redirection vers l'ACS dans l'iFrame invisible, chargement et exécution du code JavaScript de fingerprint de l'ACS
- une retour via le navigateur avec un résultat d'instruction
- un nouvel appel au service PCI/Charge/CreateToken en transmettant ce résultat
- un retour du serveur de la plateforme de paiement avec une nouvelle instruction CHALLENGE de redirection vers l'ACS avec un CReq (iFrame visible)
- l'instruction a lieu (redirection vers l'ACS avec un Creq et interaction utilisateur)
- le retour via le navigateur est un résultat d'instruction : nouvel appel au service PCI/Charge/CreateToken en transmettant ce résultat
- le retour du serveur est le résultat final d'authentification
Glossaire
3DS Method | Code JavaScript de l'ACS exécuté dans le navigateur de l'acheteur à des fins de fingerprinting. |
3DS Requestor | Demandeur lors d'une authentification 3DS, généralement le marchand ou sa passerelle de paiement. |
3DS Server | Serveur 3DS. Composant du domaine du 3DS Requestor qui démarre le processus 3DS v2 et communique avec le DS ou l'ACS lors de l'authentification de transactions. Il facilite l'interaction entre le 3DS Requestor et le DS. |
ACS | Access Control Server. Composant qui vérifie si l'authentification est disponible pour un numéro de carte et authentifie des transactions spécifiques. |
Application 3DS Requestor | Application sur dispositif mobile de l'acheteur qui peut traiter une transaction 3DS grâce à l'usage du SDK 3DS. L'application est possible grâce à l'intégration avec le SDK 3DS. |
Challenge | Phase d'authentification interactive entre l'acheteur et sa banque (ACS). |
CReq | Message 3DS v2 de demande d'authentification du porteur de carte, envoyé à l'ACS. |
DS | Directory Server. Composant qui maintient la liste d'intervalles de cartes pour lesquels une authentification peut être disponible et qui permet aux MPIs / 3DS Servers / ACS de communiquer entre eux lors des authentifications. |
Fingerprinting | Littéralement "prise d'empreinte". Identification de manière unique de l'acheteur grâce à des informations du navigateur. |
SDK 3DS | Kit de développement 3D Secure. Composant software inclus dans une Application 3DS Requestor. |
IAN | Notification de serveur à serveur qui permet d'obtenir le résultat de l'authentification (Instant Authentification Notification). |
operationUrl | Url transmise à la méthode d'initialisation du script d'authentification kr-authenticate.js . |
operationSessionId | Identifiant unique de la session d'authentification. |
Liste des protocoles supportés
PROTOCOLE | VERSION |
---|---|
3D Secure | 2.1.0 |
3D Secure | 2.2.0 |
Cartes de test
La page de référence des cartes de test se trouve ici.