Aller au contenu

Formulaire d'inscription

Valider un numéro sénégalais avec /v1/telephone/analyse et proposer région, département et commune en cascade avec /v1/geographie.

Objectif : un formulaire qui accepte un numéro mobile sénégalais valide et une commune réelle. Deux routes de l'API du hub suffisent.

Appelez l'API depuis votre serveur

L'API du hub n'autorise en CORS que l'origine du hub. Votre page appelle donc votre serveur, qui appelle l'API. Votre clé API reste ainsi côté serveur.

Les exemples lisent l'URL de base dans API_URL (voir Démarrer en 5 minutes). Sans clé, le quota quotidien est bas. Avec une clé, ajoutez l'en-tête Authorization: Bearer <clé>.

1. Valider le numéro

GET /v1/telephone/analyse?numero=77 123 45 67 renvoie :

JSON
{
  "input": "77 123 45 67",
  "valid": true,
  "country": "SN",
  "senegalese": true,
  "type": "MOBILE",
  "e164": "+221771234567",
  "national": "77 123 45 67",
  "international": "+221 77 123 45 67",
  "operator": { "name": "Orange (SONATEL)", "prefix": "77", "type": "mobile", "sources": ["…"] },
  "notice": "Indicatif : l'opérateur est déduit du préfixe d'origine. Avec la portabilité, un abonné peut avoir changé d'opérateur en gardant son numéro."
}

Règles utiles :

  • Acceptez le numéro si valid et senegalese sont vrais et si type vaut MOBILE (ou FIXED_LINE_OR_MOBILE). Un fixe comme 33 821 00 00 est refusé pour un OTP.
  • Enregistrez e164 : une seule forme en base.
  • N'utilisez pas operator pour choisir un canal de paiement. Le préfixe ne garantit pas l'opérateur actuel (portabilité).
  • Une saisie illisible renvoie 400 avec code = "INVALID_PHONE".

2. Proposer la commune en cascade

Le référentiel va de la région à la commune (ANSD, RGPH-5 2023). Une commune dépend d'un département, d'un arrondissement ou d'une ville. La cascade région → département → commune demande donc parfois un appel de plus.

  1. Régions : GET /v1/geographie?level=region&per_page=100 (14 lieux).
  2. Départements : GET /v1/geographie?parent_id=<id de la région>&per_page=100.
  3. Communes : enfants du département ; pour chaque arrondissement ou ville, ses propres enfants.

Affichez name quand il existe, sinon name_source (nom de l'ANSD en majuscules). Les noms accentués des communes ne sont pas encore vérifiés. Enregistrez l'id : c'est l'identifiant stable du hub.

Code serveur

JavaScript
// Node.js 18+ (fetch intégré)
const API = process.env.API_URL ?? 'http://localhost:8787';
const entetes = process.env.API_KEY ? { Authorization: `Bearer ${process.env.API_KEY}` } : {};

async function appeler(chemin) {
	const res = await fetch(`${API}${chemin}`, { headers: entetes });
	const corps = await res.json();
	if (!res.ok) throw new Error(corps.message ?? `Erreur ${res.status}`);
	return corps;
}

export async function verifierTelephone(numero) {
	const r = await appeler(`/v1/telephone/analyse?numero=${encodeURIComponent(numero)}`);
	const mobile = r.type === 'MOBILE' || r.type === 'FIXED_LINE_OR_MOBILE';
	return { ok: r.valid && r.senegalese && mobile, e164: r.e164, affichage: r.national, operateur: r.operator?.name ?? null, avertissement: r.notice };
}

const nom = (lieu) => lieu.name ?? lieu.name_source;
const enfants = async (parentId) => (await appeler(`/v1/geographie?parent_id=${parentId}&per_page=100`)).data;

export async function regions() {
	return (await appeler('/v1/geographie?level=region&per_page=100')).data.map((l) => ({ id: l.id, nom: nom(l) }));
}

export async function departements(regionId) {
	return (await enfants(regionId)).map((l) => ({ id: l.id, nom: nom(l) }));
}

// Une commune dépend d'un département, d'un arrondissement ou d'une ville.
export async function communes(departementId) {
	const liste = [];
	for (const lieu of await enfants(departementId)) {
		if (lieu.level === 'commune') liste.push(lieu);
		else liste.push(...(await enfants(lieu.id)).filter((l) => l.level === 'commune'));
	}
	return liste.map((l) => ({ id: l.id, nom: nom(l) })).sort((a, b) => a.nom.localeCompare(b.nom, 'fr'));
}

Ces fonctions ont été testées contre l'API locale : 14 régions, 5 départements pour Dakar, 19 communes pour le département de Dakar.

Côté page

Exposez ces fonctions sur vos propres routes (par exemple /api/communes). Côté page, gardez des éléments natifs : un <input type="tel" autocomplete="tel">, des <select> avec <label>, un message d'erreur relié au champ par aria-describedby. Validez aussi au moment de l'envoi : la vérification dans le navigateur ne suffit pas.

La liste des lieux change rarement. Mettez en cache les réponses de /v1/geographie, ou téléchargez le fichier lieux.json du jeu Référentiel géographique.

Et ensuite ?