1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95
|
<?php
/**
* Vérifie le numéro de sécurité sociale. S'il est valide, renvoit un tableau des infos
* sinon renvoie FALSE
* @author Webu (Dylann Cordel <d.cordel@webu.fr>)
* @param string $numero à 15 chiffre
* @return mixed array avec les infos récupérées du num de sécu ou FALSE
*/
function checkNumSecu($numero){
//Expression de base d'Antoun et SNAFU (http://www.developpez.net/forums/d677820/php/langage/regex/verification-numero-securite-sociale/#post3969560),
//mais corigée par mes soins pour respecter plus scrupuleusement le format
$regexp = '/^ # début de chaîne
(?<sexe>[1278]) # 1 et 7 pour les hommes ou 2 et 8 pour les femmes
(?<annee>[0-9]{2}) # année de naissance
(?<mois>0[1-9]|1[0-2]|20) # mois de naissance (si >= 20, c\'est qu\'on ne connaissait pas le mois de naissance de la personne
(?<departement>[02][1-9]|2[AB]|[1345678][0-9]|9[012345789]) # le département : 01 à 19, 2A ou 2B, 21 à 95, 99 (attention, cas particulier hors métro traité hors expreg)
(?<numcommune>[0-9]{3}) # numéro d\'ordre de la commune (attention car particuler pour hors métro traité hors expression régulière)
(?<numacte>00[1-9]|0[1-9][0-9]|[1-9][0-9]{2}) # numéro d\'ordre d\'acte de naissance dans le mois et la commune ou pays
(?<clef>0[1-9]|[1-8][1-9]|9[1-7])? # numéro de contrôle (facultatif)
$ # fin de chaîne
/x';
//références : http://fr.wikipedia.org/wiki/Num%C3%A9ro_de_s%C3%A9curit%C3%A9_sociale_en_France#Signification_des_chiffres_du_NIR
if(!preg_match($regexp, $numero, $match)){
return FALSE ;
}
/* attention à l'overflow de php :)
i.e :
$test = '1850760057018' ;
$clef = 97 - (substr($test, 0, 13) % 97) ;
// => clef = 32 car l'opérande "%" travaille avec des entiers, et sur une archi 32 bits, 1850760057018 est transformé en 2147483647 ^_^
$clef = 97 - fmod(substr($test, 0, 13), 97) ;
// => clef = 18 (la valeur correcte, car fmod travaille avec des flottants)
*/
$return = array(
'sexe' => $match['sexe'],//7,8 => homme et femme ayant un num de sécu temporaire
'annee' =>$match['annee'],//année de naissance + ou - un siècle uhuh
'mois' =>$match['mois'],//20 = inconnu
'departement' =>$match['departement'],//99 = étranger
'numcommune' =>$match['numcommune'],//990 = inconnu
'numacte' =>$match['numacte'],//001 à 999
'clef' =>isset($match['clef'])?$match['clef']:NULL,//00 à 97
'pays' =>'fra',//par défaut, on change que pour le cas spécifique
);
//base du calcul par défaut pour la clef (est modifié pour la corse)
$aChecker = floatval(substr($numero, 0, 13));
/*Traitement des cas des personnes nées hors métropole ou en corse*/
switch(true){
//départements corses. Le calcul de la cles est différent
case $return['departement'] == '2A' :
$aChecker = floatval(str_replace('A', 0, substr($numero, 0, 13)));
$aChecker-= 1000000 ;
break;
case $return['departement'] == '2B' :
$aChecker = floatval(str_replace('A', 0, substr($numero, 0, 13)));
$aChecker-= 2000000 ;
break;
case $return['departement'] == 97 || $return['departement'] == 98 :
$return['departement'].=substr($return['numcommun'], 0, 1);
$return['numcommun'] = substr($return['numcommun'], 1, 2) ;
if($return['numcommun'] > 90){//90 = commune inconnue
return FALSE ;
}
break;
case $return['departement'] == 99 :
$return['pays'] = $match['numcommune'] ;
if($return['numcommun'] > 990){//990 = pays inconnu
return FALSE ;
}
break;
default :
if($return['numcommun'] > 990){//990 = commune inconnue
return FALSE ;
}
break;
}
$clef = 97 - fmod($aChecker, 97) ;
if(empty($return['clef'])){
$return['clef'] = $clef ; //la clef est optionnelle, si elle n'est pas spécifiée, le numéro est valide, mais on rajoute la clef
}if($clef != $return['clef']){
return FALSE ;
}
return $return ;
} |
Partager