Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 26 additions & 12 deletions src/CheckSum.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,25 +6,39 @@

final class CheckSum
{
private const DICTIONARY = [0 => 0, 1 => 1, 2 => 2, 3 => 3, 4 => 4, 5 => 5, 6 => 6, 7 => 7, 8 => 8, 9 => 9, 'A' => 10, 'B' => 11, 'C' => 12, 'D' => 13, 'E' => 14, 'F' => 15, 'G' => 16, 'H' => 17, 'I' => 18, 'J' => 19, 'K' => 20, 'L' => 21, 'M' => 22, 'N' => 23, '&' => 24, 'O' => 25, 'P' => 26, 'Q' => 27, 'R' => 28, 'S' => 29, 'T' => 30, 'U' => 31, 'V' => 32, 'W' => 33, 'X' => 34, 'Y' => 35, 'Z' => 36, ' ' => 37, '#' => 38];
private $dictionary = [];

/**
* Se encarga de generar el diccionario a usar.
*/
public function __construct()
{
$dictionary = '0123456789ABCDEFGHIJKLMN&OPQRSTUVWXYZ #';
$dic = [];
foreach (str_split($dictionary) as $index => $char) {
$dic = array_merge($dic, [$char => $index]);
}
$this->dictionary = $dic;
}

public function calculate(string $rfc): string
{
// 'Ñ' translated to '#' because 'Ñ' is multibyte 0xC3 0xB1
$chars = str_split(str_replace('Ñ', '#', $rfc), 1);
array_pop($chars); // remove predefined checksum
$chars = str_split(str_replace('Ñ', '#', $rfc));
$length = count($chars);
$sum = (11 === $length) ? 481 : 0; // 481 para morales, 0 para físicas
$j = $length + 1;
array_pop($chars); // remove predefined checksum
$sum = (12 === $length) ? 481 : 0; // 481 para morales, 0 para físicas
foreach ($chars as $i => $char) {
$sum += self::DICTIONARY[$char] * ($j - $i);
$posChar = intval($this->dictionary[$char]);
$factor = $length - $i;
$sum += $posChar * $factor;
}
$digit = strval(11 - $sum % 11);
if ('11' === $digit) {
$digit = '0';
} elseif ('10' === $digit) {
$digit = 'A';
$mod11 = $sum % 11;
if ($mod11 === 0) {
return '0';
} elseif ($mod11 === 1) {
return 'A';
}
return $digit;
return strval(11 - $mod11);
}
}