Annuler une initiation de paiement 

➤ Cas d'usage

Cette méthode permet au PISP d'annuler une demande d'initiation de paiement déjà enregistrée:

  • Pour un SCT différé, à condition que le paiement n'ait pas encore été exécuté et que sa date d’exécution n’est pas atteinte (i.e. date d’exécution prévue au moins à J+1 par rapport à la date de demande d’annulation).
  • Pour un SCT permanent, à condition que la date de l’échéance courante du paiement n'ait pas encore été atteinte (requestedExecutionDate recalculée à chaque fois qu’une échéance du paiement a été traitée) et que sa date de fin (endDate) n’a pas été atteinte (i.e. date d’exécution prévue au moins à J+1 par rapport à la date de demande d’annulation).

Autrement dit, cet appel permet d'envoyer à la banque (ASPSP) d'un client une demande d'annulation d'un paiement qui a été initié avec la méthode POST /payment-requests (voir la rubrique "Cas d'usage" > "Initier un paiement") et qui n'est pas encore échu.

Seule l’annulation d'un paiement SCT différé ou d'un SCT permanent unique en euros est possible.

Réciproquement un virement SCT qui a été initié via l’API DSP2 PISP (quelle que soit la version) est annulable uniquement via l’API DSP2 PISP. Autrement dit, on ne peut pas annuler sur l’application internet de la banque (Cyber) ou sur l’application mobile de la banque, un virement SCT qui a été initialisé via DSP2. 

 

➤ Prérequis

Pour procéder à cette requête il est nécessaire de remplir les prérequis d’éligibilité pour le rôle TPP "PISP" (voir la rubrique "Eligibilité"), et d'avoir récupéré le jeton d'accès OAUTH2 (voir la rubrique "Vue d'ensemble" > "Récupérer un jeton").

Le TPP a déjà envoyé une requête DSP2 API PISP en version 1.4.2 qui a été enregistrée par l'ASPSP et à laquelle l'ASPSP a répondu avec un lien de localisation vers la demande de paiement / virement sauvegardée.

Corollaire : Pour annuler une initiation de paiement qui a été initiée par l’API DSP2 en version 1.4.0, il convient d’utiliser une requête DSP2 PISP en version 1.4.0 également (i.e. PUT /stet/psd2/v1/payment-requests/{resourceId}).

 

➤ Requête PUT

 Le point d'entrée dépendra du code établissement.

Vous devez insérer la même valeur des paramètres <cdetab> et <banque> que celle utilisée pour le jeton d'accès.

Pour rappel, la liste de nos établissements et les valeurs possibles des <cdetab> et <banque> sont précisées dans la rubrique "Limitations".

Voici un extrait de cette liste :

Code établissement <cdetab>Nom de l'établissementNom abrégé<banque>
13807 B.P Grand Ouest BPGO banquepopulaire
10548 Banque de Savoie BQSAV banque-de-savoie
40978 Banque Palatine BPAL palatine

Comme en mode test, le bon référentiel client est adressable via un "endpoint" au format www.<cdetab>.live.api.89c3.com ou www.<cdetab>.live.api.<banque>.fr

Pour exemple, nous avons donc comme URL de production :

 

➤ Paramètres obligatoires ou facultatifs du body requis pour l'appel de ce service

Paramètre obligatoire paymentRequestResourceId : identifiant de la requête d'initiation de paiement pour laquelle on souhaite annuler le virement.

La structure du body et les champs obligatoires sont décrits dans la norme STET. Le Tiers de Paiement peut et doit récupérer les informations de son virement avec la méthode GET /stet/psd2/v1.4.2/payment-requests/{paymentRequestResourceId} afin de vérifier que le paiement est à un statut annulable. 

Pour savoir si un virement est éligible, les informations suivantes doivent être valorisées dans la requête comme suit :

  • La donnée paymentInformationStatus doit avoir l'une des valeurs : ACTC/ACCP/ACSP
  • La donnée transactionStatus (au niveau de la transaction dans l’objet creditTransferTransaction) doit avoir la valeur : PDNG (si paymentInformationStatus = ACSP), sinon il ne doit pas être renseigné
  • La donnée serviceLevel doit être renseigné à SEPA (seule les virements SEPA différés sont annulables)
  • La donnée currency doit être renseignée à EUR => les virements internationaux en devise ne sont pas disponibles
  • La requête doit contenir un seul paiement
  • La donnée frequency ne doit être alimentée que pour les virements permanents.
  • La donnée localInstrument ne doit pas être valorisée, seuls les SCT étant acceptés pour l'annulation
  • La donnée requestedExecutionDate doit être dans le futur : à minima à J+1

Spécificités pour les virements unitaires

  • La donnée numberOfTransactions est à 1 pour un virement unitaire => la requête doit contenir le virement unitaire transmis dans la requête d’initiation de paiement d’origine.

Spécificités pour les virements multiples (cette fonctionnalité sera disponible en février 2023)

  • La donnée numberOfTransactions est comprise entre 2 et 50 au plus pour un virement multiple => la requête doit contenir le virement multiple transmis dans la requête d’initiation de paiement d’origine.
  • L’annulation d’un virement multiple annule tous les virements unitaires qu’il contient.

 

Pour permettre à la banque de comprendre que la requête est une demande d'annulation d'une initiation de paiement, certaines informations doivent être modifiées dans la requête comme suit (API DSP2 STET_V1.4.2.17 Part 3 Interaction Examples p.23) :

  • La donnée transactionStatus(au niveau de la transaction dans l’objet creditTransferTransaction) doit être positionnée à "CANC" (Annulé)
  • La donnée paymentInformationStatus doit avoir la valeur "CANC" (Annulé).
  • La donnée statusReasonInformation  (au niveau de la transaction dans l’objet creditTransferTransaction) doit être positionnée avec l'une des valeurs suivantes :
statusReasonInformationSignification
DS02 Annulation à la demande du client 
DUPL Annulation à la demande du PISP en cas de doublon par rapport à un paiement/virement précédent
FRAD Annulation à la demande du PISP si l'origine du paiement/virement est frauduleux
TECH Annulation à la demande du PISP pour un problème technique de son côté
  • Il faut également enlever toute la partie _links
  • Pour finir il faut supprimer l'intitulé du parent "paymentRequest": {" ainsi que l’accolade fermante en bas du flux "}"

Les autres données de la requête doivent être identiques à celles récupérées avec la méthode GET.

 

➤ Résultat retourné

A la soumission de la requête, et si toutes les données sont correctement formatées, une réponse (HTPP 200) vous sera retournée. Cette réponse contiendra le resourceId du paiement, ainsi que le mode d'authentification SCA Redirect (seul mode disponible), l'URL de consentement en fonction de la banque du payeur (urlconsent_approval_URL) et le non rejeu.

Remarques :

  • La donnée paymentRequestResourceId, essentielle pour pouvoir annuler un paiement, est incluse en tant que paramètre dans l'URL de consentement "consentApproval" renvoyée lors de l’initiation de paiement.
  • Idem pour le non rejeu : c'est le paramètre nonce dans l'URL de consentement.

 

 Codes erreur

Type d'erreur

Code HTTP
Libellé
Motif
Générique, mauvaise structure 400 Bad request error code : FF01
message : RJCT
Mauvais format du BIC 400 Bad request error code : FF01
message : RJCT
error : le champ creditorAgent.bicFi bicFi-Code allocated to a financial institution by the ISO 9362 Registration Authority as described in ISO 9362
Mauvais format du serviceLevel 400 Bad request  error code : FF01
message : RJCT
error : value not one of declared Enum instance names: [SEPA, NURG]
Mauvais format, chargeBearer autre que SLEV 400 Bad request error code: FF01
message: RJCT
error: value not one of declared Enum instance names: [SLEV]
Mauvais format du schemeName 400 Bad request error code: FF01
message : RJCT
error : le champ creditor.privateId.schemeName schemeName-Possible values BANK,COID,SREN,DSRET,NIDN,OAUT,CPAN
Mauvais format du purpose 400 Bad request error code: FF01
message: RJCT
error: value not one of declared Enum instance names: [TRPT, CASH, CPKC, ACCT, COMC]
Mauvais format du categoryPurpose 400 Bad request error code: FF01
message: RJCT
error: value not one of declared Enum instance names: [CASH, DVPM]
Mauvais jeton d'accès, problème d'authentification 403 Forbidden  
Request resource inconnu 404 Not Found  
Mauvaise requête ou requête hors périmètre autorisé 405 Method not allowed  
Message générique 500 Internal server error  

➤ Exemple

Requête :

PUT /stet/psd2/v1.4.2/payment-requests/00000032fa-159127166900013807464584 

 

Body de Demande d'annulation v1.4.2 

{
    "resourceId": "00000032fa-159127166900013807464584",
    "paymentInformationId": "azertyui",
    "creationDateTime": "2020-06-04T13:54:29.148+02:00",
    "numberOfTransactions": 1,
    "initiatingParty": {
        "name": "Pisp Name",
        "postalAddress": {
            "country": "FR",
            "addressLine": [
                "512 rue Reaumur",
                "75512 PARIS"
            ]
        },
        "organisationId": {
            "identification": "12FR5",
            "schemeName": "COID",
            "issuer": "ACPR"
        },
        "privateId": null
    },
    "paymentTypeInformation": {
        "instructionPriority": null,
        "serviceLevel": "SEPA",
        "localInstrument": null,
        "categoryPurpose": "DVPM"
    },
    "debtor": {
        "name": "Customer Name",
        "postalAddress": {
            "country": "FR",
            "addressLine": [
                "512 rue Leclerc",
                "94512 Charenton-le-Pont"
            ]
        },
        "organisationId": null,
        "privateId": {
            "identification": "D8183250I0",
            "schemeName": "BANK",
            "issuer": "BICXYYTT512"
        }
    },
    "debtorAccount": {
        "iban": "FR7613685749843054784158595",
        "other": null
    },
    "debtorAgent": {
        "bicFi": "CCBPFRPP512",
        "clearingSystemMemberId": {
            "clearingSystemId": "clearingSystemId",
            "memberId": "memberId"
        },
        "name": "Cpy Name",
        "postalAddress": {
            "country": "FR",
            "addressLine": [
                "512 rue De Gaulle",
                "85000 LRSY"
            ]
        }
    },
    "beneficiary": {
        "id": null,
        "isTrusted": null,
        "creditorAgent": {
            "bicFi": "CCBPFRPP512",
            "clearingSystemMemberId": {
                "clearingSystemId": "clearingSystemId",
                "memberId": "memberId!"
            },
            "name": "Creditor Name",
            "postalAddress": {
                "country": "FR",
                "addressLine": [
                    "512 rue de la primaube",
                    "12512 RODEZ"
                ]
            }
        },
        "creditor": {
            "name": "Amazon SA",
            "postalAddress": {
                "country": "FR",
                "addressLine": [
                    "512 avenue Maupassant",
                    "75512 PARIS"
                ]
            },
            "organisationId": {
                "identification": "852126790",
                "schemeName": "BANK",
                "issuer": "FR"
            },
            "privateId": null
        },
        "creditorAccount": {
            "iban": "FR7613825002000400000041717",
            "other": null
        }
    },
    "ultimateCreditor": null,
    "purpose": "COMC",
    "chargeBearer": "SLEV",
    "paymentInformationStatus": "ACSP",
    "statusReasonInformation": null,
    "fundsAvailability": null,
    "booking": null,
    "requestedExecutionDate": "2020-06-04T13:54:29.148+02:00",
    "creditTransferTransaction": [
        {
            "paymentId": {
                "resourceId": "00000032fa-159127166900113807942902",
                "instructionId": "instructionId 1591271669",
                "endToEndId": "endToEndId 1591271669"
            },
            "requestedExecutionDate": null,
            "endDate": null,
            "executionRule": null,
            "frequency": null,
            "instructedAmount": {
                "currency": "EUR",
                "amount": "2.12"
            },
            "beneficiary": null,
            "ultimateCreditor": null,
            "regulatoryReportingCodes": [],
            "remittanceInformation": [
                "remittanceInformation01"
            ],
            "transactionStatus": "RJCT",
            "statusReasonInformation": "DS02"
        }
    ],
    "supplementaryData": {
        "acceptedAuthenticationApproach": [
            "REDIRECT"
        ],
        "appliedAuthenticationApproach": "REDIRECT",
        "scaHint": "scaExemption",
        "successfulReportUrl": "https://www.successful.fr",
        "unsuccessfulReportUrl": "https://www.unsuccessful.fr"
    }
}

 

Résultat :

Status code : 200

 

Body de la réponse :

{
    "appliedAuthenticationApproach": "REDIRECT",
    "_links": {
        "consentApproval": {
            "href": "https://www.13807.live.api.89c3.com/89C3api/accreditation/v1.4.2/cancellation?paymentRequestResourceId=00000032fa-159127166900013807464584&nonce=RFxE0ywQmzW0Z68xJloN&creditorName=QW1hem9uIFNB&creditorAccount=RlI3NjEzODI1MDAyMDAwNDAwMDAwMDQxNzE3&amount=Mi4xMg%3D%3D¤cy=RVVS&successfulReportUrl=aHR0cHM6Ly93d3cuYXBpLjg5YzMuY29tLmZy&unsuccessfulReportUrl=aHR0cHM6Ly93d3cuYXBpLjg5YzMuY29tLmZyL25vdXMtY29udGFjdGVy&debtorAccount=RlI3NjEzODA3MDA4MDQzMDAxOTY1NDA1MTU4&privateId=RDgxODMyNTBJMA%3D%3D&requestedExecutionDate=MjAyMC0wNi0yNFQwOTowMTozMy44NTQrMDI6MDA%3D&method=UFVU",
            "templated": true
        }
    }
}