:: Visual Foxpro, Foxpro for DOS
Как проконтролировать 25-и разрядный УИП
urfin

Сообщений: 328
Дата регистрации: 17.08.2004
Здравствуйте.
Написал функцию, но чувствую, что неправильно понял алгоритм.
Может у кого-нибудь уже есть готовое решение ?
Или объясните, пожалуйста, что я делаю не так.

Цитата:
*Приложение 12 к Положению Банка России от 19 июня 2012 года N 383-П "О правилах осуществления перевода денежных средств*

ПОРЯДОК
ФОРМИРОВАНИЯ ПОЛУЧАТЕЛЕМ СРЕДСТВ УНИКАЛЬНОГО ИДЕНТИФИКАТОРА
ПЛАТЕЖА И ЕГО КОНТРОЛЯ БАНКОМ ПЛАТЕЛЬЩИКА В СЛУЧАЕ ПЕРЕВОДА
ДЕНЕЖНЫХ СРЕДСТВ НА БАНКОВСКИЙ СЧЕТ ПОЛУЧАТЕЛЯ СРЕДСТВ,
ОТКРЫТЫЙ В ЦЕЛЯХ ИДЕНТИФИКАЦИИ ПЛАТЕЖА

Список изменяющих документов
(введен Указанием Банка России от 29.04.2014 N 3248-У)

1. Получатель средств формирует уникальный идентификатор платежа с учетом следующего: 1 разряд - контрольный ключ, 2 - 25 разряды - информация о платеже (2 - 16 разряды - цифры, 17 - 25 разряды - символы). Если часть символов уникального идентификатора платежа не используется, то свободные знаки обозначаются нулями.
2. Банк плательщика контролирует наличие в распоряжении в реквизите "Код" уникального идентификатора платежа при наличии в реквизите "Сч. N" получателя средств номера банковского счета получателя средств, открытого в целях идентификации платежа.
Банк плательщика контролирует уникальный идентификатор платежа посредством проверки контрольного ключа.
Контрольный ключ рассчитывается с применением 1 - 5 разрядов реквизита "Сч. N" получателя средств и 1 - 16 разрядов реквизита "Код", а также следующих весовых коэффициентов, установленных для каждого разряда:

Номера разрядов 1 2 3 4 5 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
Коэффициенты 3 7 1 3 7 3 7 1 3 7 3 7 1 3 7 3 7 1 3 7 3

Расчет контрольного ключа осуществляется в следующем порядке:
значение контрольного ключа приравнивается нулю;
рассчитываются произведения значений разрядов на соответствующие весовые коэффициенты;
рассчитывается сумма значений младших разрядов полученных произведений;
младший разряд вычисленной суммы умножается на три;
значение контрольного ключа принимается равным младшему разряду полученного произведения.
Проверка контрольного ключа осуществляется посредством расчета произведения значений разрядов на соответствующие весовые коэффициенты с учетом значения контрольного ключа. Значение контрольного ключа считается верным при получении суммы, кратной десяти.
MESSAGEBOX(IIF(IsUIPCorrect('40822810704000005465', '1234567890123456ABCDEFGHI'),'УИП корректен','УИП некорректен'))
*
FUNCTION IsUIPCorrect
LPARAMETERS tcAcc AS String, tcUIP AS String
LOCAL lcSource AS String, lnCount AS Integer, lnControlKey AS Integer, lnCheckSum AS Integer
LOCAL ARRAY laWeight[21]
* ВЕСОВЫЕ КОЭФФИЦИЕНТЫ
laWeight[01] = 3
laWeight[02] = 7
laWeight[03] = 1
laWeight[04] = 3
laWeight[05] = 7
*
laWeight[06] = 3
laWeight[07] = 7
laWeight[08] = 1
laWeight[09] = 3
laWeight[10] = 7
*
laWeight[11] = 3
laWeight[12] = 7
laWeight[13] = 1
laWeight[14] = 3
laWeight[15] = 7
*
laWeight[16] = 3
laWeight[17] = 7
laWeight[18] = 1
laWeight[19] = 3
laWeight[20] = 7
*
laWeight[21] = 3
* 1) значение контрольного ключа приравнивается нулю
lcSource = LEFT(ALLTRIM(tcAcc), 5) + '0' + SUBSTR(ALLTRIM(tcUIP), 2, 15)
lnControlKey = 0
FOR lnCount = 1 TO 21
* 2) рассчитываются произведения значений разрядов на соответствующие весовые коэффициенты
* 3) рассчитывается сумма значений младших разрядов полученных произведений
lnControlKey = lnControlKey + MOD(VAL(SUBSTR(lcSource, lnCount, 1)) * laWeight[lnCount], 10)
ENDFOR
* 4) младший разряд вычисленной суммы умножается на три
* 5) значение контрольного ключа принимается равным младшему разряду полученного произведения
lnControlKey = MOD(MOD(lnControlKey, 10) * 3, 10)
?lnControlKey
* Проверка контрольного ключа осуществляется посредством расчета произведения значений разрядов на соответствующие весовые коэффициенты с учетом значения контрольного ключа.
* Значение контрольного ключа считается верным при получении суммы, кратной десяти.
lcSource = LEFT(ALLTRIM(tcAcc), 5) + TRANSFORM(lnControlKey) + SUBSTR(ALLTRIM(tcUIP), 2, 15)
lnCheckSum = 0
FOR lnCount = 1 TO 21
lnCheckSum = lnCheckSum + VAL(SUBSTR(lcSource, lnCount, 1)) * laWeight[lnCount]
ENDFOR
RETURN MOD(lnCheckSum, 10) = 0
Ratings: 0 negative/0 positive
Re: Как проконтролировать 25-и разрядный УИП
Влад Колосов

Сообщений: 22664
Откуда: Ростов-на-Дону
Дата регистрации: 05.05.2005
Как минимум, умножение на коэффициент надо начинать со второй цифры, а не с первой.


------------------
Совершенство - это не тогда, когда нельзя
ничего прибавить, а тогда, когда нечего убавить.
Ratings: 0 negative/0 positive
Re: Как проконтролировать 25-и разрядный УИП
urfin

Сообщений: 328
Дата регистрации: 17.08.2004
Там я подменил первую цифру входящего УИП на 0.
Непонятно излишнее и туманное описание алгоритма проверки вычисленного ключа, т.к. на входе мы уже знаем ключ и есть с чем сравить
Цитата:
Проверка контрольного ключа осуществляется посредством расчета произведения значений разрядов на соответствующие весовые коэффициенты с учетом значения контрольного ключа. Значение контрольного ключа считается верным при получении суммы, кратной десяти.

Ниже усовершенствованный вариант. Я правильно мыслю ?

MESSAGEBOX(IIF(IsUIPCorrect('40822810104000001234', '1234567890123456ABCDEFGHI'),'УИП корректен','УИП некорректен'))
MESSAGEBOX(IIF(IsUIPCorrect('40822810204000005678', '3234567890123456ABCDEFGHI'),'УИП корректен','УИП некорректен'))
*
FUNCTION IsUIPCorrect
LPARAMETERS tcAcc AS String, tcUIP AS String
LOCAL lcWeight AS String, lcString AS String, lnControlKey AS Integer, lnCount AS Integer
* ВЕСОВЫЕ КОЭФФИЦИЕНТЫ
lcWeight = REPLICATE('37137', 4) + '3'
* 1) значение контрольного ключа приравнивается нулю
lcString = LEFT(ALLTRIM(tcAcc), 5) + '0' + SUBSTR(ALLTRIM(tcUIP), 2, 15)
lnControlKey = 0
FOR lnCount = 1 TO 21
* 2) рассчитываются произведения значений разрядов на соответствующие весовые коэффициенты
* 3) рассчитывается сумма значений младших разрядов полученных произведений
lnControlKey = lnControlKey + MOD(VAL(SUBSTR(lcString, lnCount, 1)) * VAL(SUBSTR(lcWeight, lnCount, 1)), 10)
ENDFOR
* 4) младший разряд вычисленной суммы умножается на три
* 5) значение контрольного ключа принимается равным младшему разряду полученного произведения
lnControlKey = MOD(lnControlKey * 3, 10)
RETURN VAL(LEFT(tcUIP, 1)) = lnControlKey



Исправлено 1 раз(а). Последнее : urfin, 03.12.14 14:38
Ratings: 0 negative/0 positive
Re: Как проконтролировать 25-и разрядный УИП
Влад Колосов

Сообщений: 22664
Откуда: Ростов-на-Дону
Дата регистрации: 05.05.2005
Недосмотрел
Черт ногу сломит На первый взгляд, все верно


------------------
Совершенство - это не тогда, когда нельзя
ничего прибавить, а тогда, когда нечего убавить.




Исправлено 3 раз(а). Последнее : Влад Колосов, 03.12.14 16:18
Ratings: 0 negative/0 positive
Re: Как проконтролировать 25-и разрядный УИП
urfin

Сообщений: 328
Дата регистрации: 17.08.2004
На PL/SQL такая фигня получилась :
CREATE OR REPLACE FUNCTION IsUIPCorrect(acc IN VARCHAR2, uip IN VARCHAR2) RETURN BOOLEAN IS
/* Параметры :
acc - номер счета для идентификации платежа 40822 (достаточно балансового номера второго порядка),
uip - 25-и значный уникальный идентификатор платежа УИП (достаточно первых 16 числовых разрядов)
Результат : логическое значение, корректен ли УИП */
str VARCHAR2(21);
key INTEGER := 0;
i INTEGER;
-- весовые коэффициенты 371373713737137371373
v_k varchar2(21) := RPAD('37137', LENGTH('37137') * 4, '37137') || '3';
BEGIN
IF LENGTH(acc) >= 5 AND LENGTH(uip) >= 16
THEN
-- 1) значение контрольного ключа приравнивается нулю
str := SUBSTR(TRIM(acc), 1, 5) || '0' || SUBSTR(TRIM(uip), 2, 15);
FOR i IN 1 .. 21 LOOP
-- 2) рассчитываются произведения значений разрядов на соответствующие весовые коэффициенты
-- 3) рассчитывается сумма значений младших разрядов полученных произведений
key := key + MOD(TO_NUMBER(SUBSTR(str, i, 1)) * TO_NUMBER(SUBSTR(v_k, i, 1)), 10);
END LOOP;
-- 4) младший разряд вычисленной суммы умножается на три
-- 5) значение контрольного ключа принимается равным младшему разряду полученного произведения
key := MOD(key * 3, 10);
RETURN TO_NUMBER(SUBSTR(TRIM(uip), 1, 1)) = key;
ELSE
RETURN FALSE;
END IF;
END IsUIPCorrect;
Ratings: 0 negative/0 positive
Re: Как проконтролировать 25-и разрядный УИП
прошелмимо
Автор

Сообщений: 784
Дата регистрации: 21.02.2012
спиздилнашел и переписал для себя

form check_UIP
using pACC
pUIP.
check pUIP ne '0'.
if pUIP is initial.
message e341().
endif.
data: lv_Weight(21) value '371373713737137371373' "ВЕСОВЫЕ КОЭФФИЦИЕНТЫ
, lv_STR(21)
, lv_nControlKey type i value 0
, lv_CountKey type i value 0
, lv_CurrentKey type num1
, lv_D type num1
, lv_CountWeight type i
, lv_Count type i
, l_charWeight(1)
, l_char(1)
.
concatenate pACC(5) '0' pUIP+1(15) into lv_STR.
lv_CurrentKey = pUIP(1).
do .
if lv_STR is initial.
exit.
endif.
l_charWeight = lv_Weight(1).
l_char = lv_STR(1).
lv_CountWeight = l_charWeight.
lv_Count = l_char.
lv_Count = lv_Count * lv_CountWeight.
lv_CountKey = lv_CountKey + lv_Count.
shift: lv_STR by 1 places left
, lv_Weight by 1 places left
.
enddo.
lv_CountKey = lv_CountKey * 3.
lv_D = lv_CountKey.
if lv_D ne lv_CurrentKey.
message e341().
endif.
endform.
Ratings: 0 negative/0 positive
Re: Как проконтролировать 25-и разрядный УИП
sphinx

Сообщений: 31180
Откуда: Каменск-Уральски
Дата регистрации: 22.11.2006
Здесь еще обсуждалось: forum.foxclub.ru

А так-то где-то дома была рабочая (ее тестировали с Татьяной-tata на данных ПФР).


------------------
"Veni, vidi, vici!"(с)
Ratings: 0 negative/0 positive
Re: Как проконтролировать 25-и разрядный УИП
прошелмимо
Автор

Сообщений: 784
Дата регистрации: 21.02.2012
Здесь еще обсуждалось

а занафига мне проверка банк.счета?
Ratings: 0 negative/0 positive


Извините, только зарегистрированные пользователи могут оставлять сообщения в этом форуме.

On-line: 27 of63  (Гостей: 26)

© 2000-2024 Fox Club 
Яндекс.Метрика