Разработка → Казахстан: Как я помогал сдать 100 форму налоговой отчетности. Продолжение 300 форма
- вторник, 4 апреля 2017 г. в 03:14:32
*Это не луна. Это космическая станция. – Оби-Ван Кеноби* |
Приветствую социум!
1 статья → Начало 200 форма
Продолжение...
Следующим этапом для решения задач моего заказчика были налоговые декларации по НДС. Что интересно кабинет налогоплательщика мог экспортировать лишь небольшие 300 формы в виде xml. Остальные формы экспортировались только при помощи программы СОНО. И эти формы были заархивированы.
Но не все так просто как кажется с первого раза.
и самое интересное, как программисты в компании, поддерживающей онлайн сервис по сдаче налоговых деклараций, "зашифровали" эти самые формы...
Часть первая. Мучения поиска алгоритма чтения больших форм.
Это программа СОНО. В ней работают бухгалтеры Казахстана которые сдают налоговые декларации онлайн.
С чего я начал.
Экспортировал все 300 формы деклараций из СОНО.
И попытался открыть архивы. Но не тут то было.
Архиватор выдал ошибку — "файл поврежден". Потратив 5 часов на изучение основ tar я понял, что я ничего не понял...
Изучение открытых источников тупо гугление также не помогало. И тут я натолкнулся на небольшое обсуждение на бухгалтерском форуме. Где админы откровенно издевались над алгоритмом, которым зашифрованы большие формы.
Оказывается, не долго думая не сочиняя различные криптозащиты. Авторы "шифрования" больших форм решили тупо убирать первые два символа "BZ" в начале файла.
Вставив это мега ключ в начало файла
я открыл архив. И внутри нее оказался такой же поврежденный архив. (у коддеров придумавших прятать данные внутри такого же архива, видать матрешка любимая игрушка) Умудренный опытом я повторил мега кряк добавив BZ в начало файла.
и наконец то получил доступ к данным.
Просто решение вопроса как же считать информацию из архива заняло 6 часов моей жизни. "Абилдеть" — как говорит мой дядя.
Готовая функция на php которая "расшифровывает" большие формы.
if ($_POST["action"] == "getBz2") {
$name = $_FILES["bz2"]["tmp_name"];
$homepage = file_get_contents($name);
if (strripos($_FILES["bz2"]["name"], ".xml") === false) {
$homepage = "BZ".$homepage;
file_put_contents($name, $homepage);
$baseDir = "/tmp/21";
exec("rm -f " .$baseDir . "/dir/*");
if (!@mkdir("$baseDir", 0777, true)) {
}
exec("tar -jxvf $name -C $baseDir");
exec (" rm $baseDir/*.xml -rf");
$files = glob("$baseDir/*.bz2");
$homepage = file_get_contents($files[0]);
$homepage = "BZ".$homepage;
file_put_contents($files[0], $homepage);
exec("bunzip2 ".$files[0]);
$files = glob("$baseDir/*.xml");
$homepage = file_get_contents($files[0]);
}
echo homepage;
die();
}
Конечно все можно легко улучшить, но здесь только часть кода php которая отвечает именно за "кряк".
Часть вторая чтение xml структуры и сбор необходимых данных по ТЗ
Небольшой визуальный анализ итоговых xml файлов. Дал понимание что формы которые изначально отдавались как xml имеют fno formatVersion = 1, мега зашифрованные имели fno formatVersion = 2.
Основная же структура данных полностью повторялась.
function getTitle(a) {
try {
return frame.contentWindow.document.querySelector("form[name='form_300_00'] field[name='" + a + "']").innerHTML;
} catch (ex) {
return "";
}
}
var fno = {};
fno["dt"] = {}
fno["dt"]["dt_main"] = getTitle("dt_main");
fno["dt"]["dt_regular"] = getTitle("dt_regular");
fno["dt"]["dt_additional"] = getTitle("dt_additional");
fno["dt"]["dt_notice"] = getTitle("dt_notice");
fno["dt"]["dt_final"] = getTitle("dt_final");
fno["dt"]["notice_date"] = getTitle("notice_date");
fno["dt"]["notice_number"] = getTitle("notice_number");
fno["p7"] = getFaktures(7);
fno["p8"] = getFaktures(8);
fno["period_year"] = getTitle("period_year");
fno["period_quarter"] = getTitle("period_quarter");
fno["submit_date"] = getTitle("submit_date");
fno["field_300_00_001_A"] = getTitle("field_300_00_001_A");
fno["field_300_00_001_B"] = getTitle("field_300_00_001_B");
fno["field_300_00_013_A"] = getTitle("field_300_00_013_A");
fno["field_300_00_013_B"] = getTitle("field_300_00_013_B");
fno["field_300_00_015"] = getTitle("field_300_00_015");
fno["field_300_00_021"] = getTitle("field_300_00_021");
fno["field_300_00_023"] = getTitle("field_300_00_023");
fno["iin"] = getTitle("iin");
fno["rnn"] = getTitle("rnn");
В принципе логическую структуру документа я составил за 20 минут. Если бы не мега кряк то вообще завис.
Список 300 форм:
Загрузка форм:
Просмотр форм:
p.s. Заказчик перестала писаться от радости.
p.p.s. Для интересующихся, в прикладном плане, это не "сексуальном".
p.p.p.s. Если кто хочет попробовать руками скоро скину все на гитхаб. В данный момент система не доработана. Поэтому не хочу ее показывать...