Les flux MangoPay
Les flux MangoPay
MangoPay est l'établissement de paiement qui héberge les « portefeuilles » (wallets) où transite l'argent. Trois opérations suffisent à tout comprendre : PayIn (l'argent entre), Transfer (l'argent se répartit), PayOut (l'argent sort vers une vraie banque).
L'architecture des comptes
Chaque organisation (société acheteuse ou vendeuse) possède un MangopayAccount qui regroupe :
| Élément | Rôle |
|---|---|
payerAccount (catégorie PAYER) | Le compte « acheteur » : utilisateur MangoPay + wallet(s) où arrivent ses paiements (un wallet par shop dans le format multi-shop). |
ownerAccount (catégorie OWNER) | Le compte « vendeur » : utilisateur MangoPay + wallet(s) où arrive sa part des ventes. |
| auctioneerWalletId | Wallet dédié au mode commissaire-priseur. |
| virtualAccount | L'IBAN virtuel de l'acheteur : un vrai IBAN, personnel, sur lequel il peut virer depuis sa banque. Statuts : PENDING, ACTIVE, BLOCKED, CLOSED. |
| recipients | Les IBAN de destination enregistrés (et validés par authentification forte) pour les reversements : owner (vendeur) et auctioneer. Statuts : PENDING, ACTIVE, CANCELED, DEACTIVATED. |
| kyc | Les documents d'identification (voir section KYC). |
Côté plateforme, le shop possède ses wallets techniques (config meta.secure.mangopay) : platformCourtageCommissionWallet (commissions de courtage et frais acheteur), platformCPCommissionWallet (commissions commissaire-priseur), platformVatCautionWallet (caution TVA), et platformBankAccount (le compte bancaire réel de la plateforme).
Les utilisateurs MangoPay sont typés : NATURAL (personne physique) ou LEGAL (personne morale : BUSINESS, ORGANIZATION, SOLETRADER, PARTNERSHIP).
mangopay/src/models/mangopayAccounts.js (table mangopay_accounts) ; logique métier : mangopay/src/domain/MangopayAccount.js (dont getWalletId(account, shopShortId) qui résout wallet historique vs multi-shop) ; constantes : mangopay/src/resources/mangopayConstants.js et auctelia-models/src/schemas/Constants/Mangopay.js. Mapping métier : contrats SELLER_* → OWNER, contrats BUYER_* → PAYER.1. PayIn — l'argent entre
Deux moyens de paiement (PAYMENT_TYPES) :
| 💳 CARD (carte) | 🏦 BANK_WIRE (virement) | |
|---|---|---|
| Comment | L'acheteur clique sur l'URL de paiement (3-D Secure). Cartes CB/Visa/Mastercard/Amex/Maestro. | L'acheteur vire sur son IBAN virtuel personnel. |
| Rapprochement | Certain : la PaymentRequest liait déjà les factures au paiement (matchBankMovement avec les invoiceShortIds). | Quasi-automatique : l'IBAN virtuel identifie l'acheteur (findByWalletId → organisation), puis autoMatchBankMovement par montant/date. |
| Webhook | PAYIN_NORMAL_SUCCEEDED → création du mouvement bancaire IN (statut NEW) avec la trace MangoPay (indexedMeta.mangopay.payinId, wallet crédité, wire reference) → rapprochement → facture PAID. | (idem carte : même webhook) |
POST /mangopay/events, dispatchés par mangopay/src/helpers/events/EventRegistry.js. Traitement payin : mangopay/src/services/payin/PayinEventService.js ; construction du mouvement : mangopay/src/helpers/payments/buildBankMovementFromTransaction.js (communication = StatementDescriptor pour la carte, Tag/WireReference pour le virement).2. Transfer — l'argent se répartit
Une fois la vente confirmée et la commission validée, des transferts déplacent l'argent du wallet de l'acheteur vers les bons destinataires. Les types (TransferTypes) :
| Type | De → Vers | Quoi |
|---|---|---|
PAY_IN_BROKERAGE | Wallet acheteur → wallet vendeur | La part du vendeur (vente en courtage) |
PAY_IN_AUCTIONEER | Wallet acheteur → wallet commissaire-priseur | La vente en mode commissaire-priseur |
COMMISSION | Wallet acheteur → wallet plateforme | La commission de courtage |
BUYER_FEES | Wallet acheteur → wallet plateforme | Les frais acheteur |
VAT_CAUTION | (réservé) | Caution TVA — prévu, non utilisé actuellement |
- L'acheteur paie 13 915 € (10 000 + 2 100 de TVA + 1 500 de frais + 315 de TVA sur frais) → tout arrive dans son wallet.
- Transfer
PAY_IN_BROKERAGE: la part vendeur part vers le wallet du vendeur. - Transfers
BUYER_FEESetCOMMISSION: frais acheteur et commission partent vers le wallet plateforme. - Le vendeur touchera au final prix de vente TTC − commission TTC (déduction des frais).
Au webhook TRANSFER_NORMAL_SUCCEEDED, le système : marque le mouvement d'origine SETTLED, crée automatiquement le mouvement OUT du reversement et enchaîne directement sur le PayOut (voir ci-dessous). En cas de TRANSFER_NORMAL_FAILED : mouvement REJECTED, pas de payout, intervention manuelle.
mangopay/src/services/transfer/TransferService.js — create({shopShortId, transferType, debitedOrganisationShortId, creditedOrganisationShortId, amount, bankMovementShortId}) ; résolution du wallet crédité dans _resolveCreditedWalletId() (COMMISSION/BUYER_FEES → wallet plateforme ; AUCTIONEER → auctioneerWalletId ; sinon wallet owner du vendeur). Webhooks : mangopay/src/services/transfer/TransferEventService.js. Déclencheur côté book-keeper : soumission des mouvements de commission (book-keeper/src/services/bankMovements/movementCommissionsMangopay.js, routage Ponto/MangoPay dans bankMovementSubmit.js selon le payInMode).3. PayOut — l'argent sort vers une vraie banque
Le payout vide le wallet vers un IBAN réel, préalablement enregistré et validé (recipient). Les types (PayoutTypes) :
| Type | De → Vers | Déclenché par |
|---|---|---|
PAY_OUT_BROKERAGE | Wallet vendeur → IBAN du vendeur | Suite du transfer PAY_IN_BROKERAGE |
PAY_OUT_AUCTIONEER | Wallet CP → IBAN du commissaire-priseur | Suite du transfer PAY_IN_AUCTIONEER |
PAY_OUT_SHOP | Wallet plateforme → compte bancaire plateforme | Suite des transfers COMMISSION/BUYER_FEES |
Le cycle, suivi par webhooks : PAYOUT_NORMAL_CREATED (mouvement EXPORTED) → PAYOUT_NORMAL_SUCCEEDED (mouvement SETTLED + les factures liées sont soldées via settleRelatedInvoices : la commission et les factures associées passent SETTLED) — ou PAYOUT_NORMAL_FAILED (mouvement REJECTED, erreur tracée, re-soumission possible après correction).
PayoutService.resubmit()).mangopay/src/services/payout/PayoutService.js (création : DebitedWalletId + BankAccountId = recipient + BankWireRef ; auteur = shop.platformUserId) et PayoutEventService.js (webhooks). Audit : table mangopay_payouts. La traçabilité complète vit dans le Tag JSON de chaque opération MangoPay (bankMovementShortId, transferId, transferType…).KYC / KYB : la conformité qui peut tout bloquer
| Qui | Documents requis |
|---|---|
| Acheteur (PAYER) | Pièce d'identité (+ justificatif d'adresse au-delà de certains seuils) |
| Vendeur personne physique | Pièce d'identité + justificatif d'adresse |
| Vendeur société (KYB) | Identité du représentant légal + extrait d'immatriculation (KBIS/équivalent) + statuts + déclaration des bénéficiaires effectifs (UBO) |
Statuts KYC : N_A, MISSING, IN_VALIDATION, OK, TO_MODIFY, REFUSED, OUTDATED, RENEWAL_REQUIRED. Statuts de compte vendeur : ACTIVE ✅, et les bloquants CREATED/SCA_NOK (authentification forte non complétée), PENDING_DATA, KYC_NOK, COMPANY_NUMBER_NOK, BLOCKED, CLOSED. Deux modes de collecte existent : hosted (parcours hébergé MangoPay avec session de vérification d'identité) ou api (documents poussés par la plateforme).
scaUrl envoyé au vendeur). Tant qu'elle n'est pas faite : pas de transfer ni de payout possible.Récapitulatif des webhooks MangoPay traités
- Payins :
PAYIN_NORMAL_CREATED / SUCCEEDED / FAILED→ PayinEventService. - Transfers :
TRANSFER_NORMAL_CREATED / SUCCEEDED / FAILED→ TransferEventService (+ enchaînement payout). - Payouts :
PAYOUT_NORMAL_CREATED / SUCCEEDED / FAILED→ PayoutEventService (+ settle des factures). - Refunds :
PAYIN_REFUND_CREATED / SUCCEEDED / FAILED,TRANSFER_REFUND_CREATED / SUCCEEDED / FAILED→ remboursements (voir chapitre suivant).
Tables d'audit : mangopay_accounts, mangopay_payouts, mangopay_refunds, mangopay_cards, mangopay_deposits.
Le lien avec la facturation simple/double
| Mode | Transfers | Payouts | En cas d'avoir |
|---|---|---|---|
| Simple | PAY_IN_BROKERAGE (part vendeur) + COMMISSION/BUYER_FEES (plateforme) | 1 payout vendeur (+ payouts shop) | 1 refund du PayIn |
| Double | Identiques, mais adossés à 2 factures distinctes | Identiques | 2 temps : on inverse d'abord le transfer vendeur (transfer refund), puis on refund le PayIn |
| Commissaire-priseur | PAY_IN_AUCTIONEER + COMMISSION | Payout CP + payout shop | 1 refund du PayIn |