Формирование УИН для ГИС ГМП на VB.NET и C#

Вс, 10 ноября 2013 @ 5:22 AM написал в .NET3 комментариев

УИН - Универсальный Идентификатор Начисления, 20-тизначный код, используемый при регистрации платежей в ГИС ГМП (Государственная Информ. Система о Государственных и муниципальных платежах).

ГИС ГМП начала функционировать в 2013 г. Этот сервис призван обеспечить передачу сведений об уплате гражданами и организациями штрафов, пошлин, сборов. При этом не требуется представлять в соответствующие ведомства документы, подтверждающие оплату.
В целях корректной обработки информации и идентификации платежа в Государственной информационной системе о государственных и муниципальных платежах (ГИС ГМП) при оформлении платежа в бюджет необходимо соблюдать правила формирования УИН - от 9 августа 2013 г. № 13/9-4902.


Как, согласно идее, эта система должна работать:
1. Оператор начисляет штраф (пошлину) (на него генерируется УИН)
2. Передает информацию в ГИС ГМП
3. Гражданин приходит в банк, банк запрашивает в ГИС ГМП информацию о начислениях по данному гражданину, и видит этот штраф(пошлину).
4. После оплаты банк передает в ГИС ГМП информацию о платеже.
5. В системе происходит квитование.
6. Оператору приходит информация, что гражданин штраф оплатил в автоматическом режиме.

Рассмотрим алгоритм формирования УИН на примере оплаты штрафа ГИБДД(см. правила):

1-3 - КБК (188)
4 - ГИБДД (1)
5 - вид платежа ( 0- штраф, 1 - пошлина)
6-7 -дата (base 64)
8-19 - серия и номер постановления
20 -контрольная сумма

Создать(генерировать) УИН онлайн прямо здесь
Номер документа
, например, 77ФА666667

Дата документа    
, например, 05.07.2013


Ниже представлена готовая функция на VB.NET для формирования УИН по номеру документа и дате создания(вынесения):

'Generating UIN function
'Author: Tagiltsev Y, 2013
'Using: getUIN("77КК123456","01.01.2013")
Function getUIN(ByVal doc as string, byval dat as string) as string
'Объявление массивов значений для подсчета контрольной суммы
Dim a1() As String = {"0","1","2","3","4","5","6","7","8","9","A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "А", "Б", "В", "Г", "Д", "Е", "Ж", "З", "И", "Й", "К", "Л", "М", "Н", "О", "П", "Р", "С", "Т", "У", "Ф", "Х", "Ц", "Ч", "Ш", "Щ", "Э", "Ю", "Я", "Ъ", "Ы", "Ь"}
Dim a2() As Integer = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 3, 17, 29, 6, 30, 31, 13, 32, 33, 10, 34, 12, 35, 14, 16, 36, 37, 38, 18, 39, 40, 41, 21, 19, 42, 1, 2, 3, 4, 5, 6, 7, 8, 9, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 33, 38, 42}
'Массив для кодирования значений >35 в 64-ричной системе счисления
Dim b64() as String = {"А", "Б", "В", "Г", "Д", "Е", "Ж", "З", "И", "К", "Л", "М", "Н", "О", "П", "Р", "С", "Т", "У", "Ф", "Х", "Ц", "Ч", "Ш", "Ь", "Э", "Ю", "Я"}

'Переводим дату документа в десятичное представление
Dim dt = DateTime.ParseExact(mid(dat,1,10), "dd.MM.yyyy", CultureInfo.InvariantCulture)
Dim day = dt.DayOfYear
Dim year = Mid(dt.Year, 4, 1)
Dim dtInt=Int(day & year)

'Преобразуем в 64-ричное представление
Dim dt64 = ""
Do Until dtInt = 0
If dtInt Mod 64 < 10 Then
dt64 = dtInt Mod 64 & dt64
Else If dtInt Mod 64 > 35 Then
dt64 = b64(dtInt Mod 64 - 36) & dt64
Else
dt64 = ChrW(dtInt Mod 64 + 55) & dt64
End If
dtInt = (dtInt - dtInt Mod 64) / 64
Loop

'Заполняем символом Z недостающие позиции
Dim fillZ=""
for i=len(doc)+1 to 12
fillZ &= "Z"
next

Dim uin = "18810" & dt64 & doc & fillZ

'Получаем контрольную сумму
Dim crc=0
try
crc += 1 * (a2(Array.IndexOf(a1, cStr(uin(0)))) mod 10)
crc += 2 * (a2(Array.IndexOf(a1, cStr(uin(1)))) mod 10)
crc += 3 * (a2(Array.IndexOf(a1, cStr(uin(2)))) mod 10)
crc += 4 * (a2(Array.IndexOf(a1, cStr(uin(3)))) mod 10)
crc += 5 * (a2(Array.IndexOf(a1, cStr(uin(4)))) mod 10)
crc += 6 * (a2(Array.IndexOf(a1, cStr(uin(5)))) mod 10)
crc += 7 * (a2(Array.IndexOf(a1, cStr(uin(6)))) mod 10)
crc += 8 * (a2(Array.IndexOf(a1, cStr(uin(7)))) mod 10)
crc += 9 * (a2(Array.IndexOf(a1, cStr(uin(8)))) mod 10)
crc += 10 * (a2(Array.IndexOf(a1, cStr(uin(9)))) mod 10)
crc += 1 * (a2(Array.IndexOf(a1, cStr(uin(10)))) mod 10)
crc += 2 * (a2(Array.IndexOf(a1, cStr(uin(11)))) mod 10)
crc += 3 * (a2(Array.IndexOf(a1, cStr(uin(12)))) mod 10)
crc += 4 * (a2(Array.IndexOf(a1, cStr(uin(13)))) mod 10)
crc += 5 * (a2(Array.IndexOf(a1, cStr(uin(14)))) mod 10)
crc += 6 * (a2(Array.IndexOf(a1, cStr(uin(15)))) mod 10)
crc += 7 * (a2(Array.IndexOf(a1, cStr(uin(16)))) mod 10)
crc += 8 * (a2(Array.IndexOf(a1, cStr(uin(17)))) mod 10)
crc += 9 * (a2(Array.IndexOf(a1, cStr(uin(18)))) mod 10)
catch ex as Exception
end try
crc = crc Mod 11
if crc=10 then
try
crc += 3 * (a2(Array.IndexOf(a1, cStr(uin(0)))) mod 10)
crc += 4 * (a2(Array.IndexOf(a1, cStr(uin(1)))) mod 10)
crc += 5 * (a2(Array.IndexOf(a1, cStr(uin(2)))) mod 10)
crc += 6 * (a2(Array.IndexOf(a1, cStr(uin(3)))) mod 10)
crc += 7 * (a2(Array.IndexOf(a1, cStr(uin(4)))) mod 10)
crc += 8 * (a2(Array.IndexOf(a1, cStr(uin(5)))) mod 10)
crc += 9 * (a2(Array.IndexOf(a1, cStr(uin(6)))) mod 10)
crc += 10 * (a2(Array.IndexOf(a1, cStr(uin(7)))) mod 10)
crc += 1 * (a2(Array.IndexOf(a1, cStr(uin(8)))) mod 10)
crc += 2 * (a2(Array.IndexOf(a1, cStr(uin(9)))) mod 10)
crc += 3 * (a2(Array.IndexOf(a1, cStr(uin(10)))) mod 10)
crc += 4 * (a2(Array.IndexOf(a1, cStr(uin(11)))) mod 10)
crc += 5 * (a2(Array.IndexOf(a1, cStr(uin(12)))) mod 10)
crc += 6 * (a2(Array.IndexOf(a1, cStr(uin(13)))) mod 10)
crc += 7 * (a2(Array.IndexOf(a1, cStr(uin(14)))) mod 10)
crc += 8 * (a2(Array.IndexOf(a1, cStr(uin(15)))) mod 10)
crc += 9 * (a2(Array.IndexOf(a1, cStr(uin(16)))) mod 10)
crc += 10 * (a2(Array.IndexOf(a1, cStr(uin(17)))) mod 10)
crc += 1 * (a2(Array.IndexOf(a1, cStr(uin(18)))) mod 10)
catch ex as Exception
end try
crc = crc Mod 11
if crc=10 then
crc=0
end if
end if

uin &= crc
return uin
End Function


Эту функцию очень легко можно изменить для использования в C# или любом другом языке программирования.

Вариант функции, чтобы получить УИН на языке программирования C# (до-диез):

//Generating UIN function
//Author: Tagiltsev Y, 2013
//Using: getUIN("77КК123456","01.01.2013")
String getUIN(String doc, String dat)
{
//Объявление массивов значений для подсчета контрольной суммы
String[] a1 = { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "А", "Б", "В", "Г", "Д", "Е", "Ж", "З", "И", "Й", "К", "Л", "М", "Н", "О", "П", "Р", "С", "Т", "У", "Ф", "Х", "Ц", "Ч", "Ш", "Щ", "Э", "Ю", "Я", "Ъ", "Ы", "Ь" };
int[] a2 = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 3, 17, 29, 6, 30, 31, 13, 32, 33, 10, 34, 12, 35, 14, 16, 36, 37, 38, 18, 39, 40, 41, 21, 19, 42, 1, 2, 3, 4, 5, 6, 7, 8, 9, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 33, 38, 42 };
//Массив для кодирования значений >35 в 64-ричной системе счисления
String[] b64 = { "А", "Б", "В", "Г", "Д", "Е", "Ж", "З", "И", "К", "Л", "М", "Н", "О", "П", "Р", "С", "Т", "У", "Ф", "Х", "Ц", "Ч", "Ш", "Ь", "Э", "Ю", "Я" };

//Переводим дату документа в десятичное представление
DateTime dt = DateTime.ParseExact(dat.Substring(0, 10), "dd.MM.yyyy", System.Globalization.CultureInfo.InvariantCulture);
String day = dt.DayOfYear.ToString();
String year = dt.Year.ToString().Substring(3, 1);
int dtInt = int.Parse(day + year);

//Преобразуем в 64-ричное представление
String dt64 = "";
while (dtInt > 0)
{
if (dtInt % 64 < 10)
{
dt64 = (dtInt % 64).ToString() + dt64;
}
else if (dtInt % 64 > 35)
{
dt64 = b64[dtInt % 64 - 36] + dt64;
}
else
{
dt64 = (char)(dtInt % 64 + 55) + dt64;
}
dtInt = (dtInt - dtInt % 64) / 64;
}

//Заполняем символом Z недостающие позиции
String fillZ = "";
for (int i = doc.Length + 1; i <= 12; i++)
{
fillZ += "Z";
}

String uin = "18810" + dt64 + doc + fillZ;

//Получаем контрольную сумму
int crc = 0;
try
{
crc += 1 * (a2[Array.IndexOf(a1, uin[0].ToString())] % 10);
crc += 2 * (a2[Array.IndexOf(a1, uin[1].ToString())] % 10);
crc += 3 * (a2[Array.IndexOf(a1, uin[2].ToString())] % 10);
crc += 4 * (a2[Array.IndexOf(a1, uin[3].ToString())] % 10);
crc += 5 * (a2[Array.IndexOf(a1, uin[4].ToString())] % 10);
crc += 6 * (a2[Array.IndexOf(a1, uin[5].ToString())] % 10);
crc += 7 * (a2[Array.IndexOf(a1, uin[6].ToString())] % 10);
crc += 8 * (a2[Array.IndexOf(a1, uin[7].ToString())] % 10);
crc += 9 * (a2[Array.IndexOf(a1, uin[8].ToString())] % 10);
crc += 10 * (a2[Array.IndexOf(a1, uin[9].ToString())] % 10);
crc += 1 * (a2[Array.IndexOf(a1, uin[10].ToString())] % 10);
crc += 2 * (a2[Array.IndexOf(a1, uin[11].ToString())] % 10);
crc += 3 * (a2[Array.IndexOf(a1, uin[12].ToString())] % 10);
crc += 4 * (a2[Array.IndexOf(a1, uin[13].ToString())] % 10);
crc += 5 * (a2[Array.IndexOf(a1, uin[14].ToString())] % 10);
crc += 6 * (a2[Array.IndexOf(a1, uin[15].ToString())] % 10);
crc += 7 * (a2[Array.IndexOf(a1, uin[16].ToString())] % 10);
crc += 8 * (a2[Array.IndexOf(a1, uin[17].ToString())] % 10);
crc += 9 * (a2[Array.IndexOf(a1, uin[18].ToString())] % 10);
}
catch (Exception ex) { }
crc = crc % 11;
if (crc==10){
try{
crc += 3 * (a2[Array.IndexOf(a1, uin[0].ToString())] % 10);
crc += 4 * (a2[Array.IndexOf(a1, uin[1].ToString())] % 10);
crc += 5 * (a2[Array.IndexOf(a1, uin[2].ToString())] % 10);
crc += 6 * (a2[Array.IndexOf(a1, uin[3].ToString())] % 10);
crc += 7 * (a2[Array.IndexOf(a1, uin[4].ToString())] % 10);
crc += 8 * (a2[Array.IndexOf(a1, uin[5].ToString())] % 10);
crc += 9 * (a2[Array.IndexOf(a1, uin[6].ToString())] % 10);
crc += 10 * (a2[Array.IndexOf(a1, uin[7].ToString())] % 10);
crc += 1 * (a2[Array.IndexOf(a1, uin[8].ToString())] % 10);
crc += 2 * (a2[Array.IndexOf(a1, uin[9].ToString())] % 10);
crc += 3 * (a2[Array.IndexOf(a1, uin[10].ToString())] % 10);
crc += 4 * (a2[Array.IndexOf(a1, uin[11].ToString())] % 10);
crc += 5 * (a2[Array.IndexOf(a1, uin[12].ToString())] % 10);
crc += 6 * (a2[Array.IndexOf(a1, uin[13].ToString())] % 10);
crc += 7 * (a2[Array.IndexOf(a1, uin[14].ToString())] % 10);
crc += 8 * (a2[Array.IndexOf(a1, uin[15].ToString())] % 10);
crc += 9 * (a2[Array.IndexOf(a1, uin[16].ToString())] % 10);
crc += 10 * (a2[Array.IndexOf(a1, uin[17].ToString())] % 10);
crc += 1 * (a2[Array.IndexOf(a1, uin[18].ToString())] % 10);
catch(Exception ex){}
crc = crc % 11;
if (crc==10){crc=0;}
}

uin += crc.ToString();
return uin;
}


Обо всех возникающих трудностях или замеченных ошибках обязательно сообщайте в комментариях.

Тагильцев Ю.В.
http://tagiltsev.ru/?goto=315

Теги: php

Всего 3 комментариев на эту тему

  • Суровая Немка написал 2013-11-10 18:37:17:

    правительство опять изобретает велосипед

  • Онтон написал 2013-11-11 20:04:20:

    портировать на PHP?..

  • Елена написал 2016-06-01 04:14:55:

    4 позиция - код подразделения в рамках МВД, для ГИБДД -1, где узнать коды других подразделений?

Оставить комментарий

поставьте галочку если вы не бот)