# ModĂšles de transaction - Transfert
API Tiers de Mojaloop
# Table des matiĂšres
- Préface
1.1 Conventions utilisées dans ce document
1.2 Informations sur la version du document
1.3 Références - Introduction
2.1 Spécification de l'API Tiers - Transferts
3.1 Découverte
3.2 Accord
3.3 Transfert - Demande de statut de TransactionRequest
- Conditions dâerreur
5.1 Recherche de Bénéficiaire Incorrecte
5.2 Mauvaise demande de transaction tierce
5.3 Ăchec API FSPIOP aval
5.4 Challenge signé invalide
5.5 Expiration de la demande de transaction tierce - Annexe
6.1 Dérivation du challenge
# 1. Préface
Cette section contient des informations sur l'utilisation de ce document.
# 1.1. Conventions utilisées dans ce document
Les conventions suivantes sont utilisées dans ce document pour identifier les types d'informations spécifiés.
| Type dâinformation | Convention | Exemple |
|---|---|---|
| ĂlĂ©ments de lâAPI, comme les ressources | Gras | /authorization |
| Variables | Italique entre chevrons | {ID} |
| Termes du glossaire | Italique à la premiÚre occurrence ; défini dans le Glossaire | Le but de l'API est de permettre les transactions financiÚres interopérables entre un Payeur (un payeur de fonds électroniques dans une transaction de paiement) situé dans un FSP (une entité qui fournit un service financier numérique à un utilisateur final) et un Bénéficiaire (un destinataire de fonds électroniques dans une transaction de paiement) situé dans un autre FSP. |
| Documents de rĂ©fĂ©rence | Italique | Les informations utilisateur ne devraient, en gĂ©nĂ©ral, pas ĂȘtre utilisĂ©es par les dĂ©ploiements d'API ; les mesures de sĂ©curitĂ© dĂ©taillĂ©es dans Signature API et Chiffrement API devraient ĂȘtre utilisĂ©es Ă la place. |
# 1.2. Informations sur la version du document
| Version | Date | Description des modifications |
|---|---|---|
| 1.0 | 2021-10-03 | Version initiale |
# 1.3. Références
Les références suivantes sont utilisées dans cette spécification :
| Référence | Description | Version | Lien |
|---|---|---|---|
| RĂ©f. 1 | Open API pour l'interopĂ©rabilitĂ© FSP | 1.1 | DĂ©finition dâAPI v1.1 (opens new window) |
# 2. Introduction
Ce document prĂ©sente les modĂšles de transaction pris en charge par l'API Tiers en lien avec l'initiation d'une demande de transaction (Transaction Request) provenant dâun PISP.
La conception de lâAPI et le style architectural de cette API sont basĂ©s sur la Section 3 (opens new window) de la RĂ©f. 1 ci-dessus.
# 2.1 Spécification de l'API Tiers
La spĂ©cification de lâAPI Tiers Mojaloop inclut les documents suivants:
- ModÚles de données
- ModĂšles de transaction - Liaison
- ModĂšles de transaction - Transfert
- DĂ©finition de l'API ouverte tierce partie â DFSP
- DĂ©finition de l'API ouverte tierce partie â PISP
# 3. Transferts
Les transferts sont divisés en sections séparées :
Découverte : Le PISP recherche le bénéficiaire auquel envoyer des fonds
Accord : Le PISP confirme le bĂ©nĂ©ficiaire, et recherche les conditions de la transaction. Si l'Utilisateur accepte les conditions de la transaction, il signe la transaction avec le justificatif Ă©tabli lors du flux dâAPI de liaison
Transfert : Le DFSP du payeur initie la transaction et informe le PISP du résultat de celle-ci.
# 3.1 Découverte
Dans cette phase, un utilisateur saisit l'identifiant de l'utilisateur à qui il souhaite envoyer des fonds. Le PISP exécute un appel GET /parties/{Type}/{ID}** (ou GET /parties/{Type}/{ID}/{SubId}) et attend un callback du switch Mojaloop. Section 6.3 (opens new window) de la Réf. 1 décrit la ressource /parties en détail.
Si la demande GET /parties/{Type}/{ID} réussit, le PISP recevra un callback PUT /parties du switch Mojaloop. Le PISP confirme alors le bénéficiaire avec son utilisateur.
Si le PISP reçoit un callback PUT /parties/{Type}/{ID}/error (ou PUT /parties/{Type}/{ID}/{SubId}/error), il doit afficher lâerreur pertinente Ă l'utilisateur.
# 3.2 Accord
# 3.2.1 Demande de transaction tierce
AprĂšs avoir confirmĂ© les dĂ©tails du bĂ©nĂ©ficiaire avec son utilisateur, le PISP demande Ă l'utilisateur de saisir le montant Ă envoyer au bĂ©nĂ©ficiaire, et sâil souhaite que le bĂ©nĂ©ficiaire reçoive ce montant, ou qu'il souhaite envoyer ce montant (champ amountType).
Si l'utilisateur a associé plus d'un compte avec l'application PISP, le PISP peut lui demander de choisir un compte source pour le virement. Une fois la source de fonds confirmée, le PISP peut déterminer :
- le
FSPIOP-Destinationcomme le DFSP avec lequel le compte de l'utilisateur est associé - Le champ
payerdu corps de la requĂȘte POST /thirdpartyRequests/transactions.partyIdTypeestTHIRD_PARTY_LINK,fspIdest le fspId du DFSP qui a Ă©mis la liaison, etpartyIdentifierest lâaccountIdspĂ©cifiĂ© dans le corps POST /consents#scopes.
Voir Octroi du consentement pour plus dâinformations.
Le PISP génÚre ensuite un transactionRequestId aléatoire de type UUID (voir RFC 4122 UUID (opens new window)).
Lors de la réception de l'appel POST /thirdpartyRequests/transactions du PISP, le DFSP effectue certaines validations telles que :
- Déterminer que l'identifiant
payerexiste, et a bien été émis par ce DFSP au PISP spécifié dansFSPIOP-Source. - Confirmer que le
Consentementidentifié parpayerexiste et est valide. - Confirmer que le compte de l'utilisateur est actif et a suffisamment de fonds pour effectuer la transaction.
- Toute autre validation que le DFSP souhaite effectuer.
Si cette validation rĂ©ussit, le DFSP gĂ©nĂšre un transactionId unique pour la demande, et appelle PUT /thirdpartyRequests/transactions/{ID} avec ce transactionId et lâĂ©tat transactionRequestState Ă RECEIVED.
Cet appel informe le PISP que la demande de transaction tierce a été acceptée, et l'informe du transactionId final à suivre ultérieurement.
Si la validation Ă©choue, le DFSP doit envoyer un appel PUT /thirdpartyRequests/transactions/{ID}/error au PISP, contenant un message dâerreur expliquant lâĂ©chec. Voir Codes erreurs pour plus dâinformations.
# 3.2.2 Demande dâautorisation tierce
Le DFSP payeur (câest-Ă -dire, lâinstitution envoyant des fonds Ă la demande du PISP) peut alors Ă©mettre une demande de devis (POST /quotes) au DFSP bĂ©nĂ©ficiaire (lâinstitution recevant les fonds). AprĂšs rĂ©ception du callback PUT /quotes/{ID} du DFSP bĂ©nĂ©ficiaire, le DFSP payeur doit confirmer les dĂ©tails de la transaction auprĂšs du PISP.
Il utilise lâappel dâAPI POST /thirdpartyRequests/authorizations. Le corps de la requĂȘte contient les champs suivants :
transactionRequestIdâ l'identifiant original de POST /thirdpartyRequests/transactions. UtilisĂ© par le PISP pour corrĂ©ler une demande dâautorisation Ă une demande de transaction tierce.authorizationRequestIdâ un UUID alĂ©atoire gĂ©nĂ©rĂ© par le DFSP pour identifier cette demande dâautorisation tiercechallengeâ le challenge est uneBinaryStringqui sera signĂ© par la clĂ© privĂ©e sur l'appareil de l'utilisateur. Bien qu'il puisse s'agir d'une chaĂźne alĂ©atoire, il est recommandĂ© quâelle soit dĂ©rivĂ©e Ă partir de quelque chose de significatif pour les acteurs de la transaction, qui ne puisse ĂȘtre prĂ©dit Ă lâavance par le PISP. Voir Section 4.1 pour un exemple de dĂ©rivation du challenge.transactionTypeâ le champtransactionTypede la demande initiale POST /thirdpartyRequests/transactions
# 3.2.3 Autorisation signée
Une fois la requĂȘte POST /thirdpartyRequests/authorizations reçue du DFSP Payeur, le PISP prĂ©sente les conditions de la transaction Ă l'utilisateur, et lui demande s'il souhaite la poursuivre.
Les rĂ©sultats de la demande d'autorisation sont retournĂ©s au DFSP via PUT /thirdpartyRequests/authorizations/{ID}, oĂč
{ID} est le authorizationRequestId.
Si lâutilisateur rejette la transaction, la charge utile envoyĂ©e dans PUT /thirdpartyRequests/authorizations/{ID} est :
{
"responseType": "REJECTED"
}
Si lâutilisateur accepte la transaction, la charge utile dĂ©pend du credentialType du Consent.credential :
Si
FIDO, le PISP demande Ă lâutilisateur de complĂ©ter le flux FIDO Assertion (opens new window) pour signer le challenge. LesignedPayload.fidoSignedPayloadest leFIDOPublicKeyCredentialAssertionrenvoyĂ© suite au processus FIDO. Voir 3.2.3.1 Signature du challenge FIDOSi
GENERIC, la clĂ© privĂ©e créée lors du processus dâenregistrement du credential est utilisĂ©e pour signer le challenge. Voir 3.2.3.2 Signature du challenge avec un credential GENERIC
# 3.2.3.1 Signature du challenge FIDO
Pour un credentialType FIDO, le PISP demande Ă lâutilisateur de complĂ©ter le flux FIDO Assertion (opens new window) pour signer le challenge. Le champ signedPayload.value est le PublicKeyCredential (opens new window) renvoyĂ© du processus FIDO Assertion, oĂč les ArrayBuffer sont encodĂ©s en chaĂźnes base64 utf-8. Le PublicKeyCredential est la rĂ©ponse aussi bien pour lâattestation que pour lâassertion FIDO, nous dĂ©finissons lâinterface suivante : FIDOPublicKeyCredentialAssertion :
FIDOPublicKeyCredentialAssertion {
"id": "string",
"rawId": "string - base64 encodé utf-8",
"response": {
"authenticatorData": "string - base64 encodé utf-8",
"clientDataJSON": "string - base64 encodé utf-8",
"signature": "string - base64 encodé utf-8",
"userHandle": "string - base64 encodé utf-8"
},
"type": "public-key"
}
Le payload final du PUT /thirdpartyRequests/authorizations/{ID} sera ainsi :
{
"responseType": "ACCEPTED",
"signedPayload": {
"signedPayloadType": "FIDO",
"fidoSignedPayload": FIDOPublicKeyCredentialAssertion
}
}
# 3.2.3.2 Signature du challenge avec un credential GENERIC
Pour un credential GENERIC, le PISP effectue les étapes suivantes :
- Ătant donnĂ© les entrĂ©es :
challenge(authorizationRequest.challenge) sous forme de chaßne base64 encodée utf-8privatekey(stockée par le PISP lors de la création du credential), chaßne base64 encodée utf-8- SHA256() est une fonction de hachage à sens unique, voir RFC6234 (opens new window)
- sign(data, key) est une fonction de signature prenant des données et une clé privée pour produire une signature
- Soit
challengeHashle résultat de la fonction SHA256() appliquée auchallenge - Soit
signaturele rĂ©sultat de la fonction sign() appliquĂ©e ĂchallengeHashetprivateKey
La réponse du PISP au DFSP utilise alors cette signature comme champ signedPayload.genericSignedPayload :
Le payload final du PUT /thirdpartyRequests/authorizations/{ID} est alors :
{
"responseType": "ACCEPTED",
"signedPayload": {
"signedPayloadType": "GENERIC",
"genericSignedPayload": "signature encodée utf-8 base64"
}
}
# 3.2.4 Validation de lâautorisation
Note : Si le DFSP utilise un service dâautorisation auto-hĂ©bergĂ©, cette Ă©tape peut ĂȘtre sautĂ©e.
Le DFSP doit maintenant vérifier que le challenge a bien été signé, et par la clé privée correspondant à la clé publique attachée à l'objet Consent.
Le DFSP utilise l'appel dâAPI POST /thirdpartyRequests/verifications, dont le corps est composĂ© de :
verificationRequestIdâ Un UUID créé par le DFSP pour identifier cette vĂ©rification.challengeâ Le mĂȘme challenge envoyĂ© au PISP dans 3.2.2 Demande dâautorisation tierceconsentIdâ Lâidentifiant du Consent qui contient la clĂ© publique credential Ă utiliser pour vĂ©rifier cette transaction.signedPayloadTypeâ Le type de SignedPayload, selon le type dâidentifiant enregistrĂ© par le PISPfidoValueougenericValueâ Le champ correspondant du corps de la requĂȘte PUT /thirdpartyRequests/authorizations du PISP. Le DFSP doit rechercher leconsentIddâaprĂšs les dĂ©tails dupayerde laThirdpartyTransactionRequest.
# 3.3 Transfert
AprĂšs validation du challenge signĂ©, le DFSP peut lancer une transaction Mojaloop standard via lâAPI FSPIOP.
AprĂšs avoir reçu lâappel PUT /transfers/{ID} du switch, le DFSP recherche le ThirdpartyTransactionRequestId du transfert donnĂ© puis envoie un appel PATCH /thirdpartyRequests/transactions/{ID} au PISP.
Une fois ce callback reçu, le PISP sait que le transfert est réussi et peut en informer son utilisateur.
# 4. Demander le statut de la TransactionRequest
Un PISP peut effectuer un GET /thirdpartyRequests/transactions/{ID} pour obtenir le statut dâune demande de transaction.
Le PISP effectue un GET /thirdpartyRequests/transactions/{ID}
Le switch valide la demande et répond par
202 AcceptedLe switch recherche lâendpoint pour
dfspapour la transférer à DFSP ADFSPA valide la demande et répond avec
202 AcceptedLe DFSP recherche la demande de transaction via son
transactionRequestId- Si elle est introuvable, il appelle PUT /thirdpartyRequests/transactions/{ID}/error vers le switch, avec un message dâerreur pertinent
Le DFSP vĂ©rifie que l'entĂȘte
FSPIOP-Sourcecorrespond Ă celui dâorigine du POST /thirdpartyRequests/transactions- Sinon il appelle PUT /thirdpartyRequests/transactions/{ID}/error vers le switch, avec un message d'erreur pertinent
Le DFSP appelle PUT /thirdpartyRequests/transactions/{ID} avec le corps suivant :
{ transactionRequestState: TransactionRequestState }OĂč
transactionIdest lâidentifiant de transaction gĂ©nĂ©rĂ© par le DFSP, etTransactionRequestStateestRECEIVED,PENDING,ACCEPTED,REJECTED, comme dĂ©fini dans 7.5.10 TransactionRequestState (opens new window) de la DĂ©finition dâAPILe switch valide la demande et rĂ©pond avec
200 OKLe switch recherche lâendpoint pour
pispaet transmet au PISPLe PISP valide la demande et répond avec
200 OK
# 5. Conditions dâerreur
AprÚs que le PISP a initié la demande de transaction tierce via POST /thirdpartyRequests/transactions, le DFSP doit envoyer soit un PUT /thirdpartyRequests/transactions/{ID}/error soit un callback PATCH /thirdpartyRequests/transactions/{ID} pour informer le PISP du statut final.
- PATCH /thirdpartyRequests/transactions/{ID} est utilisĂ© pour informer le PISP du statut final. Il peut sâagir soit dâun rejet par lâutilisateur, soit dâune approbation ayant abouti Ă un transfert rĂ©ussi.
- PUT /thirdpartyRequests/transactions/{ID}/error informe le PISP en cas dâĂ©chec de la demande.
- Si le PISP ne reçoit aucun de ces callbacks avant lâexpiration
expirationspĂ©cifiĂ©e dans la requĂȘte POST /thirdpartyRequests/transactions, il peut considĂ©rer la demande comme Ă©chouĂ©e et en informer son utilisateur.
# 5.1 Recherche de bénéficiaire infructueuse
Quand le PISP effectue une recherche de bénéficiaire (GET /parties/{Type}/{ID}), il peut recevoir le callback PUT /parties/{Type}/{ID}/error.
Voir 6.3.4 Parties Error Callbacks (opens new window) de la DĂ©finition dâAPI FSPIOP pour plus dâinformations sur ce callback dâerreur.
Dans ce cas, le PISP peut vouloir afficher un message dâerreur Ă lâutilisateur, en lâinvitant Ă essayer avec un autre identifiant ou plus tard.
# 5.2 Mauvaise demande de transaction tierce
Quand le DFSP reçoit le POST /thirdpartyRequests/transactions du PISP, les erreurs suivantes peuvent se produire :
- Le
payer.partyIdTypeoupayer.partyIdentifierest invalide ou pas lié à un consentement valide connu du DFSP - Le compte utilisateur identifié par
payer.partyIdentifiern'a pas assez de fonds - La devise précisée dans
amount.currencynâest pas prise en charge par le compte de lâutilisateur payee.partyIdInfo.fspIdnâest pas dĂ©fini â il sâagit dâune propriĂ©tĂ© optionnelle, mais le fspId bĂ©nĂ©ficiaire sera requis pour adresser correctement la demande de devis- Tout autre contrĂŽle ou vĂ©rification cĂŽtĂ© DFSP Ă©choue
Dans ce cas, le DFSP doit informer le PISP de lâĂ©chec en envoyant un callback PUT /thirdpartyRequests/transactions/{ID}/error.
Le PISP peut alors informer son utilisateur de lâĂ©chec, et proposer de relancer une demande sâil le souhaite.
# 5.3 Ăchec API FSPIOP aval
Le DFSP peut ne pas vouloir, ou ne pas ĂȘtre en mesure, dâexposer des dĂ©tails sur les Ă©checs API FSPIOP aval au PISP.
Par exemple, avant dâĂ©mettre un POST /thirdpartyRequests/authorizations au PISP, si le POST /quotes avec le FSP bĂ©nĂ©ficiaire Ă©choue, le DFSP envoie un callback PUT /thirdpartyRequests/transactions/{ID}/error au PISP.
Un autre exemple : si la requĂȘte POST /transfers Ă©choue :
# 5.4 Challenge signé invalide
AprĂšs rĂ©ception dâun POST /thirdpartyRequests/authorizations du DFSP, le PISP demande Ă l'utilisateur de signer le challenge via le justificatif enregistrĂ© lors du flux de liaison de comptes.
Le challenge signé est retourné au DFSP via PUT /thirdpartyRequest/authorizations/{ID}.
Le DFSP :
- Valide lui-mĂȘme le challenge signĂ©
- Ou interroge le Auth-Service via thirdpartyRequests/verifications pour vérifier la signature contre la clé publique enregistrée dans le Consent.
Si le challenge signé est invalide, le DFSP appelle alors PUT /thirdpartyRequests/transactions/{ID}/error vers le PISP.
# Cas 1 : DFSP se charge de vérifier le challenge
# Cas 2 : DFSP utilise le Auth-Service hébergé par le hub pour vérifier le challenge signé contre le credential enregistré.
# 5.5 Expiration de la demande de transaction tierce
Si le PISP ne reçoit aucun des callbacks ci-dessus avant la date dâexpiration expiration dĂ©finie dans POST /thirdpartyRequests/transactions, il peut considĂ©rer la demande comme Ă©chouĂ©e et en informer immĂ©diatement l'utilisateur.
# 6. Annexe
# 6.1 Dérivation du challenge
- Soit
quotela valeur du corps de la rĂ©ponse de lâappel PUT /quotes/{ID}_ - La fonction
CJSON()est lâimplĂ©mentation du JSON Canonical vers une chaĂźne, conforme Ă RFC-8785 - Canonical JSON format (opens new window) - La fonction
SHA256()est la fonction de hachage SHA-256, conforme à RFC-6234 (opens new window) - Le DFSP doit générer la valeur
jsonStringen appliquantCJSON(quote) - Le
challengeest la valeur deSHA256(jsonString)
