Kirjoittaja: Metabolix
Kirjoitettu: 24.03.2019 – 24.03.2019
Tagit: teksti, yhteiskunta, hyvää koodia, koodi näytille, vinkki, yleispätevä
Tämä koodivinkki esittelee pankkimaksuissa käytettävän viitenumeron laskentaa.
Suomalainen viitenumero sisältää 4–20 numeroa, joista viimeinen on tarkastusmerkki. Laskentakaavassa kerrotaan viitenumeron valinnaisen osan numerot vuorotellen 1:lla, 3:lla ja 7:lla siten, että viimeinen numero tulee kerrotuksi 7:lla. Kertolaskujen tulokset lasketaan yhteen. Tarkastusmerkki valitaan siten, että kun se lisätään summaan, summasta tulee jaollinen 10:llä.
Viitteen alku: 8 5 5 8 4 8 2 Kertoimet: 7 1 3 7 1 3 7 Tulos: 56 + 5 + 15 + 56 + 4 + 24 + 14 = 174 Tarkastusmerkki: 180 - 174 = (10 - 174 % 10) % 10 = 6 Viite: 855 84826
<?php # Moduuli suomalaisten viitenumeroiden käsittelyyn. class SuomalainenViite { # Luo kokonaisen viitteen (alku + tarkiste) alkuosan perusteella. public static function luo($alku, $ryhmittely = true) { # Poistetaan muut kuin numerot. $alku = preg_replace("/[^0-9]*/s", "", $alku); # Tarkastusmerkin laskenta. $summa = 0; $l = strlen($alku); for ($i = 0; $i < $l; ++$i) { $summa += substr($alku, -1 - $i, 1) * [7, 3, 1][$i % 3]; } $merkki = (10 - $summa % 10) % 10; $viite = $alku . $merkki; return $ryhmittely ? self::ryhmittele($viite) : $viite; } # Ryhmittelee viitenumeron viiden numeron sarjoihin lopusta alkuun. public static function ryhmittele($viite) { $viite = preg_replace("/[^0-9]*/s", "", $viite); return strrev(trim(chunk_split(strrev($viite), 5, " "))); } # Tarkastaa, onko viite kelvollinen. public static function tarkasta($viite) { # Vääriä merkkejä? if (strspn($viite, "0123456789 ") != strlen($viite)) { return false; } $viite = str_replace(" ", "", $viite); # Väärä pituus? if (strlen($viite) > 20 || strlen($viite) < 4) { return false; } # Väärä tarkistusmerkki? return $viite == self::luo(substr($viite, 0, -1), false); } }
Kansainvälistä viitenumeroa käytetään esimerkiksi SEPA-maksuissa. Viitenumeron alussa ovat merkit RF ja kaksinumeroinen tarkiste, ja tämän jälkeen voi tulla enintään 21 omavalintaista merkkiä. Suomessa käytetään loppuosana yleensä numeroista 0–9 muodostuvaa suomalaista viitenumeroa, mutta myös kirjaimet A–Z ja a–z ovat sallittuja. Tarkiste muodostetaan seuraavasti:
Kansainvälistä viitenumeroa koskee standardi ISO 11649.
<?php # Moduuli kansainvälisten viitenumeroiden käsittelyyn (ISO_11649). class SepaViite { # Siivoaa viitteestä ylimääräiset välimerkit. public static function siivoa($viite) { return strtoupper(preg_replace("/[^0-9a-zA-Z]/s", "", $viite)); } # Muuttaa viitteen numeeriseen muotoon jakojäännöstä varten. public static function numeeriseksi($viite) { return preg_replace_callback( "/([0-9])|([A-Z])|([a-z])|./s", function($m) { if (!empty($m[2])) return ord($m[2]) - ord("A") + 10; if (!empty($m[3])) return ord($m[3]) - ord("a") + 10; return $m[1] ?? ""; }, $viite ); } # Jakojäännös 97:llä pitkästä luvusta onnistuu esim. GMP-kirjastolla. public static function mod97($luku) { return (int) gmp_mod($luku, 97); } # Luo kokonaisen viitteen (RF + tarkiste) loppuosan perusteella. public static function luo($loppuosa, $ryhmittely = true) { $loppuosa = self::siivoa($loppuosa); $luku = self::numeeriseksi($loppuosa . "RF00"); $tarkiste = sprintf("%02d", (98 - self::mod97($luku))); $viite = "RF" . $tarkiste . $loppuosa; return $ryhmittely ? self::ryhmittele($viite) : $viite; } # Ryhmittelee viitteen neljän merkin joukkoihin alusta alkaen. public static function ryhmittele($viite) { $viite = self::siivoa($viite); return trim(chunk_split($viite, 4, " ")); } # Tarkastaa, onko viite kelvollinen. public static function tarkasta($viite) { $viite = self::siivoa($viite); if (strlen($viite) > 25 || strlen($viite) <= 4) { return false; } $luku = self::numeeriseksi(substr($viite, 4) . substr($viite, 0, 4)); return self::mod97($luku) == 1; } }
Suomessa yleensä halutaan käyttää suomalaista viitenumeroa, joka kuitenkin sitten kansainväliselle asiakkaalle voi olla tarpeen antaa kansainvälisessä muodossa. Yleensä viitenumero muodostetaan esimerkiksi laskun numerosta. Näin se käy:
<?php require_once "SuomalainenViite.php"; require_once "SepaViite.php"; $lasku = "881628761018"; $suomiviite = SuomalainenViite::luo($lasku); $sepaviite = SepaViite::luo($suomiviite); echo "Suomi: {$suomiviite}\n"; echo "SEPA: {$sepaviite}\n";