Le système SAGA ID impose maintenant des contraintes d'unicité strictes sur le NIU et le numéro de téléphone pour éviter les doublons et garantir l'intégrité des données citoyennes.
regex: /^[0-9]{10}$/)Lorsqu'un service externe envoie une demande de vérification via /api/partner/v1/verify, le système :
La méthode isMatchingUser() compare les données pour distinguer les vrais doublons des mises à jour légitimes et des homonymes.
SI NIU fourni ET NIU existe déjà dans la base :
├─ Comparer nom + prénom + date de naissance
├─ SI nom ET date correspondent :
│ ├─ Comparer NIU existant avec NIU demandé
│ ├─ SI NIU identiques → OK (même personne, mise à jour)
│ └─ SI NIU différents → OK (homonymes, personnes différentes)
└─ SI nom OU date diffèrent → ERREUR 409 (duplicate_niu, vraie fraude)
SI téléphone fourni ET téléphone existe déjà dans la base :
├─ Comparer nom + prénom + date de naissance
├─ SI nom ET date correspondent :
│ ├─ Comparer NIU existant avec NIU demandé
│ ├─ SI NIU identiques → OK (même personne)
│ └─ SI NIU différents → OK (homonymes)
└─ SI nom OU date diffèrent → ERREUR 409 (duplicate_phone)
Deux personnes peuvent légitimement avoir :
Le NIU permet de les distinguer :
Personne A : Jean Dupont, né 1990-01-15, NIU 1234567890 ✅
Personne B : Jean Dupont, né 1990-01-15, NIU 9876543210 ✅
→ Les deux comptes peuvent coexister (NIU différents)
Recherche par ordre de priorité :
1. NIU (si fourni)
2. Email (si fourni)
3. Téléphone (si fourni)
Situation : Jean Pierre existe déjà avec NIU 1234567890, un service envoie une mise à jour de son email.
Compte existant : Jean Pierre, 1990-01-15, NIU 1234567890
Requête reçue : Jean Pierre, 1990-01-15, NIU 1234567890, nouvel email
Résultat : ✅ Autorisé - Nom + date + NIU correspondent → Mise à jour OK
Situation : Marie Jeanne essaie d'utiliser le NIU de Jean Pierre.
Compte existant : Jean Pierre, 1990-01-15, NIU 1234567890
Requête reçue : Marie Jeanne, 1985-03-20, NIU 1234567890
Résultat : ❌ HTTP 409 - duplicate_niu (nom/date différents, NIU identique = fraude)
Situation : Deux personnes différentes ont le même nom et date de naissance.
Compte existant : Michel Bernard, 1985-06-12, NIU 8888888801
Requête reçue : Michel Bernard, 1985-06-12, NIU 8888888802
Résultat : ✅ Autorisé - Nom + date identiques MAIS NIU différent → Personnes différentes
Situation : Paul Durant n'existe pas dans le système.
Compte existant : Aucun
Requête reçue : Paul Durant, 1992-07-10, NIU 9999999902
Résultat : ✅ Autorisé - Nouveau compte créé
duplicate_niu (409 Conflict)Cause : Le NIU fourni existe déjà pour un autre utilisateur avec des données personnelles différentes.
Réponse :
{
"success": false,
"error": "duplicate_niu",
"message": "Ce NIU est déjà associé à un autre compte citoyen. Chaque NIU doit être unique.",
"details": "Le NIU fourni existe déjà dans le système pour une personne différente."
}
Actions à prendre :
duplicate_phone (409 Conflict)Cause : Le numéro de téléphone fourni existe déjà pour un autre utilisateur avec des données personnelles différentes.
Réponse :
{
"success": false,
"error": "duplicate_phone",
"message": "Ce numéro de téléphone est déjà associé à un autre compte citoyen. Chaque numéro doit être unique.",
"details": "Le numéro de téléphone fourni existe déjà dans le système pour une personne différente."
}
Actions à prendre :
Tous les cas de doublons sont loggués avec :
use SagaId\Sdk\SagaIdClient;
use SagaId\Sdk\Exceptions\SagaIdException;
try {
$result = $sagaId->verifyIdentity([
'first_name' => 'Jean',
'last_name' => 'Pierre',
'date_of_birth' => '1990-01-15',
'niu' => '1234567890',
'phone' => '+50912345678',
]);
if ($result['verified']) {
// Citoyen vérifié
}
} catch (GuzzleException $e) {
$response = json_decode($e->getResponse()->getBody(), true);
if (isset($response['error'])) {
switch ($response['error']) {
case 'duplicate_niu':
// Gérer l'erreur de NIU en double
log_error('NIU déjà utilisé : ' . $response['message']);
// Demander au citoyen de vérifier son NIU
break;
case 'duplicate_phone':
// Gérer l'erreur de téléphone en double
log_error('Téléphone déjà utilisé : ' . $response['message']);
// Demander au citoyen de fournir un autre numéro
break;
default:
// Autre erreur
log_error('Erreur de vérification : ' . $response['message']);
}
}
}
# Première requête - doit réussir
curl -X POST http://sagaid.ht/api/partner/v1/verify \
-H "Authorization: Basic $(echo -n 'client_id:client_secret' | base64)" \
-H "Content-Type: application/json" \
-d '{
"first_name": "Jean",
"last_name": "Pierre",
"date_of_birth": "1990-01-15",
"niu": "1234567890"
}'
# Deuxième requête avec même NIU mais données différentes - doit échouer
curl -X POST http://sagaid.ht/api/partner/v1/verify \
-H "Authorization: Basic $(echo -n 'client_id:client_secret' | base64)" \
-H "Content-Type: application/json" \
-d '{
"first_name": "Marie",
"last_name": "Jeanne",
"date_of_birth": "1985-03-20",
"niu": "1234567890"
}'
# Résultat attendu : 409 Conflict avec error "duplicate_niu"
# Première requête - doit réussir
curl -X POST http://sagaid.ht/api/partner/v1/verify \
-H "Authorization: Basic $(echo -n 'client_id:client_secret' | base64)" \
-H "Content-Type: application/json" \
-d '{
"first_name": "Paul",
"last_name": "Durant",
"date_of_birth": "1992-07-10",
"phone": "+50911111111"
}'
# Deuxième requête avec même téléphone mais données différentes - doit échouer
curl -X POST http://sagaid.ht/api/partner/v1/verify \
-H "Authorization: Basic $(echo -n 'client_id:client_secret' | base64)" \
-H "Content-Type: application/json" \
-d '{
"first_name": "Sophie",
"last_name": "Martin",
"date_of_birth": "1988-11-05",
"phone": "+50911111111"
}'
# Résultat attendu : 409 Conflict avec error "duplicate_phone"
# Première requête - créer Michel Bernard avec NIU 8888888801
curl -X POST http://sagaid.ht/api/partner/v1/verify \
-H "Authorization: Basic $(echo -n 'client_id:client_secret' | base64)" \
-H "Content-Type: application/json" \
-d '{
"first_name": "Michel",
"last_name": "Bernard",
"date_of_birth": "1985-06-12",
"niu": "8888888801",
"phone": "+50912340010"
}'
# Deuxième requête - même nom et date MAIS NIU différent - doit réussir
curl -X POST http://sagaid.ht/api/partner/v1/verify \
-H "Authorization: Basic $(echo -n 'client_id:client_secret' | base64)" \
-H "Content-Type: application/json" \
-d '{
"first_name": "Michel",
"last_name": "Bernard",
"date_of_birth": "1985-06-12",
"niu": "8888888802",
"phone": "+50912340011"
}'
# Résultat attendu : HTTP 200 (création réussie)
# Raison : Les NIU sont différents donc ce sont deux personnes différentes
En cas de conflit légitime (ex: NIU correctement saisi mais signalé comme doublon), contacter :
| Validation | Champ | Action si doublon détecté | Code HTTP |
|------------|-------|---------------------------|-----------|
| Unicité NIU | niu | Comparer données → Erreur si différent | 409 |
| Unicité téléphone | phone | Comparer données → Erreur si différent | 409 |
Date de mise en œuvre : 30 mars 2026
Version : 1.0.0
Auteur : Équipe technique SAGA ID