Suivre les statuts¶
Ce guide explique comment synchroniser les statuts de paiement avec votre PMS.
Stratégie de synchronisation¶
Deux approches complémentaires :
| Méthode | Usage | Latence |
|---|---|---|
| Polling (GET statuses + mark-retrieved) | Synchronisation batch périodique | Quelques minutes |
| Webhooks (IPN) | Notification en temps réel | Quelques secondes |
Synchronisation incrémentale¶
L'endpoint /statuses/ retourne par défaut uniquement ce qui est nouveau ou a changé depuis le dernier acquittement du PMS. Couplé à POST /mark-retrieved/, il forme un flux de sync incrémental sans doublons.
Principe¶
- Fetch —
GET /statuses/retourne :- les demandes jamais acquittées (= nouvelles créations)
- les demandes acquittées mais modifiées depuis (ex. passage en
CAPTUREDvia webhook)
- Process — le PMS traite chaque demande (création d'arrhes, mise à jour du séjour, etc.)
- Ack —
POST /mark-retrieved/avec les UUIDs traités - Boucle — au prochain fetch, seules les évolutions ultérieures remontent
Pourquoi ré-acquitter les statuts qui changent
Si le PMS acquitte une demande en PENDING, puis le guest paye (webhook → CAPTURED), la demande réapparaît automatiquement au prochain fetch. Le PMS peut alors mettre à jour son enregistrement et ré-acquitter.
Requête — fetch incrémental¶
Requête — acquittement¶
curl -X POST \
-H "X-API-Key: votre-clé-api" \
-H "Content-Type: application/json" \
-d '{"uuids": ["550e8400-...", "7c9e6679-..."]}' \
https://votre-domaine.com/api/payment-requests/mark-retrieved/
Réponse :
Snapshot complet¶
Pour une réconciliation périodique ou un audit, récupérez l'intégralité en ignorant l'acquittement :
curl -H "X-API-Key: votre-clé-api" \
"https://votre-domaine.com/api/payment-requests/statuses/?include_retrieved=true"
Réponse type /statuses/¶
[
{
"uuid": "550e8400-...",
"reference": "DEP-2026-0042",
"reservation_ref": "RES-001",
"request_type": "DEPOSIT",
"status": "CAPTURED",
"order_cycle": "CLOSED",
"amount": 150.00,
"amount_captured": 150.00
},
{
"uuid": "7c9e6679-...",
"reference": "IMP-2026-0015",
"reservation_ref": "RES-002",
"request_type": "IMPRINT",
"status": "AUTHORISED",
"order_cycle": "OPEN",
"amount": 200.00,
"amount_captured": 0.00
}
]
Fréquence recommandée
Synchronisez toutes les 5 à 10 minutes pour un bon compromis entre fraîcheur des données et charge serveur.
Liste filtrée par statut¶
Pour récupérer toutes les demandes dans un statut donné :
# Toutes les demandes en attente
curl -H "X-API-Key: votre-clé-api" \
"https://votre-domaine.com/api/payment-requests/?status=PENDING"
Statuts de référence¶
| Statut | Code | Terminal | Description |
|---|---|---|---|
| Non initié | NOT_INITIATED |
Non | Demande créée, formulaire non ouvert |
| En attente | PENDING |
Non | Formulaire ouvert par le client |
| Autorisé | AUTHORISED |
Non | Paiement autorisé (empreinte enregistrée) |
| A valider | AUTHORISED_TO_VALIDATE |
Non | Pré-autorisation en attente de capture |
| Capturé | CAPTURED |
Oui | Montant débité |
| Refusé | REFUSED |
Oui | Refusé par la banque |
| Erreur | ERROR |
Non | Erreur technique |
| Annulé | CANCELLED |
Oui | Annulé par l'hôtel |
| Expiré | EXPIRED |
Oui | Délai dépassé |
| Remboursé | REFUNDED |
Oui | Montant remboursé |
Champ order_cycle¶
| Valeur | Signification |
|---|---|
OPEN |
Transaction en cours |
CLOSED |
Transaction terminée |
Exemple d'intégration PMS¶
import requests
API_KEY = "votre-clé-api"
BASE_URL = "https://votre-domaine.com/api"
HEADERS = {"X-API-Key": API_KEY}
def fetch_pending() -> list[dict]:
"""Récupère les demandes non acquittées ou modifiées depuis le dernier ack."""
response = requests.get(
f"{BASE_URL}/payment-requests/statuses/",
headers=HEADERS,
)
response.raise_for_status()
return response.json()
def mark_retrieved(uuids: list[str]) -> int:
"""Acquitte un lot d'UUIDs côté M-Pay. Retourne le nombre de lignes mises à jour."""
if not uuids:
return 0
response = requests.post(
f"{BASE_URL}/payment-requests/mark-retrieved/",
json={"uuids": uuids},
headers=HEADERS,
)
response.raise_for_status()
return response.json()["marked"]
def sync_cycle():
"""Un cycle complet : fetch → process → ack."""
pending = fetch_pending()
if not pending:
return
processed = []
for item in pending:
try:
handle_in_pms(item) # création d'arrhes, mise à jour séjour, etc.
processed.append(item["uuid"])
except Exception:
# En cas d'erreur, on n'acquitte pas -> la demande reviendra au prochain cycle
continue
mark_retrieved(processed)
def handle_in_pms(item: dict):
"""Logique métier PMS. À implémenter selon votre logiciel."""
...
# Exécution périodique (cron, Celery beat, etc.)
sync_cycle()
Ne pas acquitter ce qui n'a pas été traité
N'incluez dans mark-retrieved que les UUIDs réellement persistés côté PMS. Si le traitement échoue, laissez la demande non acquittée : elle réapparaîtra au prochain fetch.