Utilisation de l’IPN (URL de notification)

IPN signifie Instant Payment Notification. Quand une transaction est créée ou que son statut change, nos serveurs lancent une IPN en appelant une URL de notification située sur vos serveurs. Cela vous permet d’être notifié en temps réel des changements intervenus sur une transaction.

Pour plus d’informations générales sur les IPNs, vous pouvez consulter l’article suivant: IPN: généralités

Une IPN est le seul moyen d’être notifié dans les cas suivants :

  • La connexion internet de l’acheteur est coupée
  • L’acheteur ferme son navigateur au cours du paiement
  • Une transaction est refusée

Il est donc impératif d’intégrer les IPN !

Fonctionnement

Lorsque l’acheteur valide le paiement, une transaction est créée. Nos serveurs vont tenter de joindre vos serveurs pour transmettre toutes les informations concernant la transaction.

Étape Déscription
1 L’acheteur a cliqué sur le bouton payer: soumission du formulaire depuis le navigateur de l’acheteur vers nos serveurs. Cet appel est effectué automatiquement par notre client JavaScript
2 Une fois la transaction traitée, nous effectuons un appel depuis nos serveurs vers une URL que vous avez déternimé. L’objet transaction complet sera envoyé pour vous permettre de mettre à jour votre système d’information avant le retour navigateur. C’est l’IPN (Instant Payment Notification).
3 Nos serveurs renvoient le résultat du paiement au client JavaScript
4 Le client JavaScript POSTe le formulaire de paiement sur vos serveurs

L’étape 3 a lieu seulement après que vos serveurs ont répondu (le temps d’attente maximum est de 30 secondes). Cela vous permet de mettre à jour votre système d’information avant que l’acheteur ne soit redirigé sur votre page de confirmation d’achat.

Définir l’URL dans le Back Office Expert

Pour activer la notification :

  • 1: Connectez vous sur : https://secure.lyra.com/portal/
  • 2: Rendez-vous sur le menu suivant : Paramétrage > Règles de notifications.
  • 3: Effectuez un clic-droit sur URL de notification à la fin du paiement
  • 4: Sélectionnez Gérer la règle
  • 5: Entrez les URL de notification dans la zone URL de notification de l’API formulaire V1, V2 pour TEST et PRODUCTION
  • 6: Entrez les URL de notification dans la zone API REST: URL de notification de l’API Krypton pour TEST et PRODUCTION
  • 7: Saisissez votre adresse e-mail dans Adresse(s) e-mail à avertir en cas d’échec
  • 8: Pour spécifier plusieurs adresses e-mail, séparez-les par un point virgule
  • 9: Sauvegardez les modifications

Si le serveur cible de l’IPN est hors ligne, un e-mail vous sera envoyé à l’adresse définie à l’étape 7.

Cet e-mail contient :

  • Le code d’erreur HTTP retourné par votre serveur
  • Des éléments d’analyse
  • L’explication sur les conséquences de l’erreur
  • Les instructions pour relancer l’IPN (à travers le Back Office Expert)

Définir l’URL dynamiquement

Lors de la création du formToken, vous pouvez définir l’URL cible de l’IPN dynamiquement avec le paramètre ipnTargetUrl:

{
    "amount": 990,
    "currency": "EUR",
    "ipnTargetUrl": "https://my.super.site/ipn"
}

Utilisation de l’IPN

L’IPN est envoyé sur vos serveurs en utilisant la même procédure que le client JavaScript. Cela vous permet d’utiliser un code similaire pour traiter la réponse:

  • Les données sont envoyées sous forme de formulaire (content-type: x-www-form-urlencoded),
  • Les paramètres qui contiennent les données sont les mêmes.

Les différences sont:

  • kr-answer contient les objets transactions complets,
  • la signature contenue dans kr-hash est calculée de façon différente.

L’IPN est envoyée en POST de la façon suivante sur vos serveurs:

kr-hash=c3c0323c748fdb7c2d24bd39ada99663526236828efa795193bebfdea022fe58
kr-hash-algorithm=sha256_hmac
kr-hash-key=password
kr-answer-type=V4/Payment
kr-answer={"shopId":"33148340","orderCycle":"CLOSED",(...)}

Les 4 paramètres POST correspondent à :

Paramètre Description
kr-hash Hash de l’objet JSON stocké dans kr-answer. Il permet de vérifier l’authenticité de la réponse
kr-hash-algorithm Algorithme utilisé pour calculer le hash
kr-hash-key Clé utilisée pour signer kr-answer. Peut valoir hmac_sha256 (retour navigateur) ou password (cas IPN).
kr-answer-type Type de l’objet JSON contenu dans kr-answer
kr-answer Objet contenant les objets transactions complets encodés en JSON

Avant d’entrer dans le détail du contenu de kr-answer, nous devons vérifier s’il est valide.

Vérifier la signature IPN (hash)

Afin de détecter les fraudes potentielles, vous devez vérifier l’authenticité du champ kr-answer.

Le champ kr-hash contient le hash de kr-answer généré avec le mot de passe (qui commence par testpassword_* ou prodpassword_*).

Pour vérifier la validité de la signature avec nos SDKs :

/* Check the signature using password */

if (!$client->checkHash()) {
    //something wrong, probably a fraud ....
    signature_error($formAnswer['kr-answer']['transactions'][0]['uuid'], $hashKey, 
                    $client->getLastCalculatedHash(), $_POST['kr-hash']);
    throw new Exception('invalid signature');
}

Une fois la signature vérifiée, vous pouvez récupérer les informations liées à la transaction ainsi:

/* Retrieve the IPN content */
$rawAnswer = $client->getParsedFormAnswer();
$formAnswer = $rawAnswer['kr-answer'];

/* Retrieve the transaction id from the IPN data */
$transaction = $formAnswer['transactions'][0];

/* get some parameters from the answer */
$orderStatus = $formAnswer['orderStatus'];
$orderId = $answer = $formAnswer['orderDetails']['orderId'];
$transactionUuid = $transaction['uuid'];

Voir la section suivante pour plus de détails.

Exemple d’implémentation de la vérification du hash en PHP :

    /**
     * check kr-answer object signature
     */
    public function checkHash($key=NULL)
    {
        $supportedHashAlgorithm = array('sha256_hmac');

        /* check if the hash algorithm is supported */
        if (!in_array($_POST['kr-hash-algorithm'],  $supportedHashAlgorithm)) {
            throw new LyraException("hash algorithm not supported:" . $_POST['kr-hash-algorithm'] .". Update your SDK");
        }

        /* on some servers, / can be escaped */
        $krAnswer = str_replace('\/', '/', $_POST['kr-answer']);

        /* if key is not defined, we use kr-hash-key POST parameter to choose it */
        if (is_null($key)) {
            if ($_POST['kr-hash-key'] == "sha256_hmac") {
                $key = $this->_hashKey;
            } elseif ($_POST['kr-hash-key'] == "password") {
                $key = $this->_password;
            } else {
                throw new LyraException("invalid kr-hash-key POST parameter");
            }
        }
    
        $calculatedHash = hash_hmac('sha256', $krAnswer, $key);
        $this->_lastCalculatedHash = $calculatedHash;

        /* return true if calculated hash and sent hash are the same */
        return ($calculatedHash == $_POST['kr-hash']);
    }
}

Le choix de la clé doit être basé sur la valeur de kr-hash-key:

kr-hash-key Clé utilisée Description
hmac_sha256 clé HMAC SHA256 Données reçues lors du retour navigateur. On utilise la clé SHA256 pour vérifier la valeur de kr-hash
password Mot de passe Données reçues via l’IPN (appel serveur à serveur). On utilise le mot de passe pour vérifier la valeur de kr-hash

L’objet transaction

L’objet transaction est contenu dans le paramètre POST kr-answer. Il est encodé en JSON:

Le paramètre kr-answer contient les informations sur l’état de la session de paiement :

{
    "shopId": "69876357",
    "orderCycle": "CLOSED",
    "orderStatus": "PAID",
    "serverDate": "2018-09-27T14:02:17+00:00",
    "orderDetails": (...)
    "customer": (...)
    },
    "transactions": [{
        "shopId": "69876357",
        "uuid": "5b158f084502428499b2d34ad074df05",
        "amount": 990,
        (...)
        "_type": "V4/PaymentTransaction"
    }],
    "_type": "V4/Payment"
}

Vous pouvez utiliser n’importe quelle fonction stantard pour y accéder, ou via notre SDK:

/* Retrieve the IPN content */
$rawAnswer = $client->getParsedFormAnswer();
$formAnswer = $rawAnswer['kr-answer'];

/* Retrieve the transaction id from the IPN data */
$transaction = $formAnswer['transactions'][0];

/* get some parameters from the answer */
$orderStatus = $formAnswer['orderStatus'];
$orderId = $answer = $formAnswer['orderDetails']['orderId'];
$transactionUuid = $transaction['uuid'];

Cycle de vie d’une transaction

Pour comprendre la signification des champs status et detailedStatus, rendez-vous ici: Référence de status

Restrictions serveur marchand

En cas de restriction mise en place du côté du site marchand, il faudra autoriser la plage d’adresses IP 194.50.38.0/24.

Les notifications sont envoyées depuis une adresse IP comprise dans la plage 194.50.38.0/24 en mode Test et en mode Production.