Comment intégrer Canonical

Découvrez comment le pilote PSS Canonical vous permet de connecter un fournisseur de services de paiement à B2CORE en implémentant un contrat d’API de dépôt standard, y compris la configuration côté B2CORE, les webhooks, le polling et le cycle de vie du statut des dépôts.

Le pilote Canonical vous permet de connecter un fournisseur de services de paiement (PSP) de votre choix à B2CORE via PSS, même lorsque B2CORE ne propose pas encore de pilote dédié pour ce fournisseur.

Pourquoi utiliser le pilote Canonical

La plupart des systèmes de paiement dans B2CORE reposent sur un pilote dédié conçu spécifiquement pour un fournisseur. Le pilote Canonical adopte une approche différente : il définit un contrat d’API unique et standard — l’API Canonical Deposit — que tout fournisseur peut implémenter. B2CORE gère alors l’authentification, le flux de démarrage du dépôt, le polling, les webhooks et le cycle de vie des statuts de manière uniforme, quel que soit le fournisseur derrière le contrat.

Le pilote Canonical est utile lorsque vous souhaitez :

  • Connecter un PSP privilégié ou interne qui ne dispose pas de pilote B2CORE dédié, sans attendre un développement personnalisé.
  • Réduire le délai de mise sur le marché en demandant à votre fournisseur d’implémenter un contrat documenté et stable plutôt qu’une intégration sur mesure.
  • Conserver un contrôle total sur la partie fournisseur, tandis que B2CORE gère le flux de travail des dépôts de son côté.

Le pilote Canonical prend actuellement en charge les flux de dépôt. Pour proposer des dépôts via votre fournisseur, celui-ci doit implémenter l’API Canonical Deposit décrite dans la spécification OpenAPI ci-dessous et respecter les exigences comportementales de cette page.

Spécification OpenAPI

L’API Canonical Deposit est définie dans la spécification OpenAPI suivante, qui couvre l’authentification, les schémas de requête et de réponse, les points de terminaison et les codes de statut. Téléchargez-la pour examiner le contrat complet que votre fournisseur doit implémenter :

canonical-deposit-api.yaml

Le reste de cette page décrit les exigences comportementales, la configuration côté B2CORE et les décisions de conception que la spécification ne peut pas exprimer. Lisez les deux ensemble pour obtenir une vue complète de l’intégration.

Identifiants du pilote B2CORE

Ces champs sont configurés côté B2CORE (Back Office) et utilisés pour s’authentifier auprès de l’API du PSP. Consultez la spécification OpenAPI pour connaître tous les détails relatifs à la génération et à la vérification des jetons JWT.

ChampDescription
URL de base de l’APIURL HTTPS de base de l’API du PSP.
ID d’applicationIdentifiant marchand unique. Utilisé comme revendication sub dans le JWT.
Secret de l’applicationClé secrète pour la signature HMAC-SHA256. Encodée en Base64 URL, 32 octets (43 caractères). Jamais envoyée dans les requêtes — utilisée uniquement pour signer les jetons.

Champs de configuration du pilote B2CORE

Ces champs sont configurés côté B2CORE (Back Office) et contrôlent le comportement du pilote. Ils ne font pas partie de l’API destinée au PSP.

Paramètres globaux (globalParam1, globalParam2, globalParam3)

Trois champs de chaîne au niveau de la configuration, envoyés avec chaque requête authentifiée au PSP.

  • Pour les points de terminaison POST, ils sont inclus dans le corps de requête JSON.
  • Pour les points de terminaison GET, ils sont inclus comme paramètres de requête.

Ils représentent des valeurs spécifiques au PSP telles que l’ID marchand, le canal ou l’ID de projet. La sémantique exacte dépend de l’implémentation du PSP. L’administrateur B2CORE les renseigne lors de la configuration.

Champs obligatoires (lecture seule)

Type : Sélection multiple

Sélectionne les champs d’informations utilisateur affichés dans le formulaire de paiement en lecture seule (non modifiables).

Les champs sélectionnés doivent déjà être configurés et enregistrés dans le profil B2CORE de l’utilisateur. Si un champ sélectionné est absent du profil, la génération du formulaire de paiement échoue avec une erreur de champs manquants — l’utilisateur ne peut pas continuer tant que les données ne sont pas renseignées dans son profil B2CORE.

Les champs sélectionnés, ainsi que les champs provenant des Champs obligatoires (modifiables), déterminent quelles données utilisateur sont réellement renseignées dans l’objet startDepositUserInfo envoyé au PSP dans la requête POST /api/v1/deposits. Les champs qui ne sont sélectionnés dans aucune des deux listes sont masqués dans le formulaire et peuvent être envoyés avec des valeurs vides.

Champs obligatoires (modifiables)

Type : Sélection multiple

Sélectionne les champs d’informations utilisateur affichés dans le formulaire de paiement comme modifiables. L’utilisateur peut renseigner ou modifier ces champs directement dans le formulaire de paiement. Contrairement aux Champs obligatoires (lecture seule), ces champs n’ont pas besoin d’être préconfigurés dans le profil B2CORE de l’utilisateur.

Règle de priorité : Si un champ est sélectionné à la fois dans Champs obligatoires (lecture seule) et Champs obligatoires (modifiables), il est affiché en lecture seule. Le paramètre lecture seule est toujours prioritaire.

Comportement de l’e-mail : L’e-mail est toujours affiché dans le formulaire de paiement et toujours envoyé dans startDepositUserInfo, qu’il soit ou non sélectionné dans l’une des listes. La configuration contrôle uniquement son affichage :

E-mail sélectionné dansComportement
Aucune des listesAffiché comme champ modifiable
Champs obligatoires (modifiables)Affiché comme champ modifiable
Champs obligatoires (lecture seule)Affiché comme champ en lecture seule (valeur du profil B2CORE)
Les deux listesAffiché comme champ en lecture seule (la lecture seule est prioritaire)

Délai de synchronisation par défaut

Type : Sélection
Par défaut : 4h

Durée maximale après la création d’un dépôt pendant laquelle B2CORE interroge le statut du dépôt. Après ce délai :

  • StatusSyncInProgress → le dépôt passe à unexpected.
  • StatusSyncUnexpected → le dépôt passe à unexpected.

Le statut unexpected nécessite une investigation manuelle de l’administrateur via LifecycleService.

Échec autorisé au démarrage

Type : Booléen (actuellement codé en dur sur yes, aucun choix)

Détermine s’il est sûr de marquer un dépôt comme failed (terminal) lorsque la requête de démarrage rencontre une erreur inattendue.

  • yes — si le PSP renvoie une erreur lors du démarrage du dépôt et que B2CORE est certain que le dépôt n’a pas été créé côté PSP (par exemple, B2CORE n’a jamais reçu d’URL de redirection), le dépôt peut être passé en toute sécurité à failed. Le client n’a perdu aucun argent.
  • no — même en cas d’erreur, le dépôt passe à in_progress avec un ID externe non vérifié et est interrogé, car le PSP pourrait avoir créé le dépôt malgré l’erreur.

Actuellement, toujours yes. Dans le cas typique, sans URL de redirection, le client ne peut pas finaliser la page de paiement du PSP ; le dépôt ne peut donc pas réussir.

Attendre le webhook avant le polling

Type : Booléen (actuellement codé en dur sur yes, aucun choix)

Contrôle si B2CORE attend une notification webhook avant de commencer à interroger GET /api/v1/deposits/{externalID}.

ValeurComportement
yesAprès le démarrage du dépôt, B2CORE attend jusqu’à 5 minutes un webhook avant de commencer le polling. Si aucun webhook n’arrive dans les 5 minutes, B2CORE passe au polling standard.
noB2CORE commence le polling immédiatement selon la planification standard de backoff.

Justification : De nombreux PSP envoient rapidement une notification webhook lorsque le statut du dépôt change. Attendre le webhook avant le polling réduit le nombre d’appels API inutiles, ce qui aide à respecter les limites de débit. Le délai d’expiration de 5 minutes garantit la progression même si le webhook est retardé ou perdu.

Flux de test de la configuration

Lorsqu’un administrateur clique sur Tester la configuration dans B2CORE :

1. B2CORE generates a one-time JWT signed with appSecret
2. B2CORE → POST /api/v1/configuration/test (with Bearer JWT + globalParams)
3. If response status = "available" → test result: "available"
4. If response status = "failed" → test result: "failed" (with error from PSP)
5. If unexpected error (5xx, timeout, and similar) → test result: "unexpected"

La méthode de test de la configuration est la seule méthode pour laquelle tout problème d’identifiants doit renvoyer non pas 401 Unauthorized, mais 200 OK avec un corps de réponse.

Les valeurs code et description sont affichées à l’administrateur B2CORE ; renvoyez donc des données propres et non sensibles.

Conception du système de webhooks

Deux canaux de webhook

B2CORE prend en charge deux canaux de webhook par dépôt :

CanalEnregistrementDescription
AutomatiqueVia notificationURL dans la requête POST /api/v1/depositsToujours actif. B2CORE génère l’URL et la transmet au PSP.
Configurable par l’administrateurDéfini par l’administrateur dans le Back Office B2COREFacultatif. L’administrateur peut configurer une URL de webhook distincte vers laquelle le PSP envoie les notifications (par exemple, enregistrée dans le panneau d’administration du PSP).

Les deux canaux alimentent le même gestionnaire de webhooks B2CORE → magasin driver_transit → pipeline d’optimisation du poller.

Webhook comme optimisation du polling

Le webhook n’est pas la source de vérité. C’est une optimisation qui réduit les requêtes de polling inutiles.

PSP → B2CORE webhook handler → driver_transit (key-value store) → poller

Fonctionnement :

  1. Lorsqu’un webhook arrive, B2CORE enregistre un indicateur dans driver_transit associé à externalID.
  2. Le poller vérifie driver_transit avant d’effectuer un appel API :
    • Si un indicateur webhook existe pour externalID, B2CORE appelle immédiatement GET /api/v1/deposits/{externalID}.
    • Si aucun indicateur n’existe et que moins de 5 minutes se sont écoulées, B2CORE attend (voir Attendre le webhook avant le polling).
    • Si aucun indicateur n’existe et que plus de 5 minutes se sont écoulées, B2CORE poursuit avec le polling standard.
  3. Lorsque le dépôt atteint un statut terminal (succès ou échec), l’entrée driver_transit est supprimée.

Charge utile du webhook

La charge utile du webhook est minimale (voir le rappel webhook sous POST /api/v1/deposits dans la spécification OpenAPI) :

{
  "externalID": "550e8400-e29b-41d4-a716-446655440000",
  "status": "success"
}

La charge utile contient les champs suivants :

  • externalID — correspond à l’UUID de la requête POST /api/v1/deposits.
  • status — l’une des valeurs "success", "failed" ou "unprocessable".

Le webhook doit être envoyé uniquement lorsque le dépôt passe à un statut terminal.

Flux de démarrage du dépôt

Requête de démarrage

B2CORE initie un dépôt en appelant POST /api/v1/deposits.

La requête inclut un champ returnURL — une URL de page frontend B2CORE vers laquelle rediriger l’utilisateur après son interaction avec la page du PSP. Il ne s’agit pas d’un webhook — c’est uniquement une redirection du navigateur.

Pour tous les autres détails, consultez la spécification OpenAPI.

Correspondance des résultats de démarrage

La réponse du PSP correspond à une action B2CORE comme suit :

Réponse du PSPAction B2CORE
Le PSP renvoie une URL de redirectionPasser à in_progress
2xx avec une violation de la spécification (par exemple, aucune URL de redirection)Passer à failed
HTTP 4xx / 5xx / délai d’expiration / erreur réseauPasser à failed

Tous les scénarios d’échec aboutissent à failed (et non à unexpected) car Échec autorisé au démarrage est défini sur yes (voir Échec autorisé au démarrage) : sans URL de redirection valide, l’utilisateur final ne peut pas interagir avec la page de paiement du PSP ; aucun argent ne peut donc être perdu.

Flux de redirection

Lors d’un démarrage réussi, B2CORE reçoit une URL de redirection et envoie l’utilisateur final vers la page de paiement du PSP :

sequenceDiagram
    participant B as B2CORE
    participant P as PSP
    participant U as End user

    B->>P: POST /api/v1/deposits
    P-->>B: 200 OK<br/>action.type: "redirect"<br/>action.redirect.url: "..."
    B->>U: Redirect end user to PSP payment page
    U->>P: Open PSP payment page
    U->>P: Complete payment
    P-->>U: Redirect to returnURL
    U->>B: Land on B2CORE "in progress" page
  • Le returnURL ramène l’utilisateur vers une page frontend B2CORE indiquant que le dépôt est en cours de traitement.
  • Après le démarrage, B2CORE lance le flux de polling et de webhook (voir Polling et synchronisation des statuts).
  • Actuellement, "redirect" est le seul type d’action pris en charge.

Polling et synchronisation des statuts

Planification du backoff de polling

B2CORE utilise un backoff progressif pour interroger GET /api/v1/deposits/{externalID} :

Temps écoulé depuis le démarrage du dépôtIntervalle de polling
0–15 minutesToutes les 1 minute
15–60 minutesToutes les 3 minutes
1–3 heuresToutes les 5 minutes
3–5 heuresToutes les 10 minutes
5+ heuresToutes les 15 minutes

Gestion du délai

Délai par défaut : 4 heures après la création du dépôt (configurable, voir Délai de synchronisation par défaut).

Lorsque le délai est dépassé, les statuts intermédiaires sont résolus comme suit :

Dernier résultat du pollingAction B2CORE
inProgressPasser à unexpected
Erreur réseau, 5xx, erreur d’analyse et similairePasser à unexpected

Le statut unexpected arrête le polling automatique et nécessite une action manuelle de l’administrateur via LifecycleService de B2CORE.

Logique d’attente du webhook

Lorsque Attendre le webhook avant le polling est défini sur yes (valeur par défaut actuelle, voir Attendre le webhook avant le polling) :

flowchart TD
    A["t=0min: deposit created, redirect URL returned<br/>Poller scheduled but WAITS for webhook"] --> B{Webhook received<br/>before t=5min?}
    B -- yes --> C["Immediately poll<br/>GET /api/v1/deposits/{externalID}"]
    B -- "no (t=5min elapsed)" --> D["Begin standard polling<br/>(1-minute intervals initially)"]
    C --> E[Continue with standard<br/>polling backoff]
    D --> E
    E --> F[Continue until terminal status<br/>or deadline]

Correspondance des résultats du polling

Chaque résultat de polling provenant de GET /api/v1/deposits/{externalID} correspond à une action interne B2CORE :

Statut de réponse du PSPAction B2CORE
"inProgress" + délai non dépasséContinuer le polling (nouvelle tentative)
"inProgress" + délai dépasséPasser à unexpected
"success"Passer à success, arrêter le polling. Enregistrer finalAmount et finalCurrencyCode
"failed"Passer à failed, arrêter le polling. Enregistrer reason
"unprocessable"Passer à unexpected, arrêter le polling. Enregistrer reason. Nécessite une investigation de l’administrateur
HTTP 5xx / délai d’expiration / erreur d’analyseTraiter comme une tentative de polling unexpected. Continuer le polling si le délai n’est pas dépassé
HTTP 404 avec X-Safe-To-Fail-After-SecondsContinuer le polling. Après la durée indiquée plus une marge de sécurité (5 minutes), si toujours 404, passer à failed avec la raison "deposit redirect URL is expired"
HTTP 404 sans l’en-têteContinuer le polling. Attendre que le dépôt apparaisse côté PSP ou que le délai de synchronisation soit dépassé

Cycle de vie des statuts de dépôt

Cette section décrit les statuts de dépôt B2CORE. Pour la correspondance entre les statuts de réponse du PSP et les statuts B2CORE, consultez Correspondance des résultats de démarrage et Correspondance des résultats du polling.

Diagramme complet des statuts

flowchart TD
    created[created]
    post["POST /api/v1/deposits"]
    failed1[failed]
    inProgress1[in_progress]
    unexpected1[unexpected]
    poll["GET /api/v1/deposits/{externalID}<br/>(polling)"]
    retryIP["(in_progress)<br/>(retry)"]
    retryUX["(unexpected)<br/>(retry)"]
    success[success]
    failed2[failed]
    unprocessable["(unprocessable)<br/>(stop polling)"]
    inProgress2[in_progress]

    created --> post
    post --> failed1
    post --> inProgress1

    inProgress1 --> poll
    poll --> retryIP
    poll --> retryUX
    poll --> success
    poll --> failed2
    poll --> unprocessable

    retryIP --> inProgress2
    retryUX --> inProgress2
    unprocessable --> unexpected1
    unexpected1 -->|Manual recovery| inProgress2

Récupération depuis le statut unexpected

Un administrateur peut effectuer ces transitions manuelles via LifecycleService :

TransitionQuand l’utiliser
unexpectedin_progressRéessayer le polling (par exemple, après la résolution d’une panne du PSP)
unexpectedsuccessUniquement si la dernière tentative de polling était unprocessable et que l’administrateur confirme le succès
unexpectedfailedL’administrateur confirme que le dépôt a échoué

Définitions des statuts de dépôt

Le tableau suivant définit chaque statut de dépôt B2CORE :

StatutSignification métier
in_progressLe dépôt est en cours de traitement. Couvre tous les états intermédiaires : virement bancaire en attente, vérification 3DS en cours, attente d’un examen manuel côté PSP, client interagissant avec la page de paiement du PSP et situations similaires. Il s’agit d’un statut non terminal — B2CORE continue le polling.
successLe courtier a reçu l’argent du client. Le PSP a confirmé que les fonds ont été crédités. Les champs finalAmount et finalCurrencyCode reflètent le montant et la devise réellement reçus, qui peuvent différer de la demande initiale en raison de frais ou d’une conversion.
failedLe dépôt n’a pas abouti. Le client n’a pas perdu d’argent et le courtier n’a pas reçu de fonds. Exemples : carte refusée, virement bancaire rejeté, utilisateur ayant annulé sur la page du PSP ou lien de redirection expiré.
unexpectedLe dépôt n’a pas pu être résolu automatiquement et nécessite une action manuelle de l’administrateur via B2CORE (voir Récupération depuis le statut unexpected) ; le polling automatique a été arrêté. Ce statut est utilisé lors d’un dépassement de délai pendant in_progress, ou lorsque le PSP signale unprocessable.

Moment de création du dépôt

Les PSP suivent l’un des deux modèles de création de dépôt :

ModèleComportementImpact sur le polling
Création immédiateLe PSP crée l’enregistrement du dépôt lors de POST /api/v1/deposits.GET /api/v1/deposits/{externalID} renvoie un résultat immédiatement après le démarrage.
Création différéeLe PSP crée l’enregistrement du dépôt uniquement après que l’utilisateur final a terminé la page de paiement du PSP.GET /api/v1/deposits/{externalID} renvoie 404 Not Found tant que l’utilisateur n’a pas terminé la page.

Pour la création différée, le PSP devrait renvoyer l’en-tête X-Safe-To-Fail-After-Seconds avec la réponse 404. Cet en-tête indique à B2CORE combien de temps le lien de redirection est valide. Après redirect_time + header_value + safety_margin, si le dépôt est toujours en 404, B2CORE le marque comme failed avec la raison "deposit redirect URL is expired".

Si l’en-tête est absent, B2CORE continue le polling jusqu’à ce que le dépôt apparaisse ou que le délai de synchronisation (4 heures par défaut) soit dépassé, auquel cas le dépôt passe à unexpected.

Exigences comportementales

Traçage distribué

Toutes les requêtes HTTP de B2CORE vers le PSP incluent des en-têtes de traçage standard conformément à la spécification W3C Trace Context :

  • traceparent — contient l’ID de trace, l’ID de span parent et les indicateurs de trace.
  • tracestate — données de trace spécifiques au fournisseur.

Les implémentations PSP devraient propager ces en-têtes à leurs services en aval afin de permettre une observabilité de bout en bout.

Verrouillage de la devise sur la page de paiement PSP

Lorsque la réponse de démarrage du dépôt inclut une redirection vers une page de paiement PSP :

  • La page PSP ne doit pas permettre à l’utilisateur final de modifier le currencyCode vers une devise analogue, équivalente ou alternative.
  • La devise affichée sur la page PSP doit correspondre exactement à celle envoyée dans la requête de démarrage du dépôt.
  • Si la page PSP permet la sélection de devise, la devise doit être présélectionnée et verrouillée.

Recommandation de liste blanche d’IP

Bien que cela ne soit pas exigé par la spécification API, il est fortement recommandé aux implémentations PSP de configurer une liste blanche d’IP de leur côté. Cela fournit une couche de sécurité supplémentaire au-delà de l’authentification JWT, en limitant l’accès API aux adresses IP B2CORE connues.

Pour rendre le pilote Canonical disponible dans votre environnement, veuillez contacter votre gestionnaire de compte. Indiquez précisément comment et à quelles fins vous prévoyez d’utiliser le pilote Canonical afin que nous puissions organiser l’accès en conséquence.

Dernière mise à jour le

Sur cette page