08.09.2020 22:39
Столкнулся с задачей разбора чека самозанятого -
на входе имеем ссылку типа

Если перейти по этой ссылке, то видим картинку чека. Из картинки вытащить информацию можно, но сложно, приходится картинку как-то распознать, затем полученный текст обработать. Распознание работает, мягко говоря, неточно. То точки пропускает, то скобки путает, то ещё что. В общем, тот ещё квест. На вопрос - как бы получить чек в нормальном формате ответа не нашёл кроме ругани на ФНС в общем и их программистов в частности.
Но экспериментальным путём было обнаружено, что если в строке адреса чека в конце вместо print подставить json, то получаем ссылку типа:

Это нормальный json, который потом можно спокойно разобрать. К сожалению, никакой информации нигде про это нет. Но работает. Из бонусов - в json гораздо больше информации по чеку, чем на картинке. Из минусов - нет имени отправителя чека (т.е. самозанятого как такового). Есть только его ИНН, впрочем, в большинстве случаев этого достаточно.

Для чека по ссылке выше получаем информацию типа:
{"receiptId":"20005tnn66","services":[{"name":"Написание статьи","quantity":1,"serviceNumber":0,"amount":1000.00}],"operationTime":"2019-07-18T13:12:45.307+03:00","requestTime":"2019-07-18T13:12:45.307+03:00","registerTime":"2019-07-18T10:12:45.374Z","taxPeriodId":201907,"paymentType":"CASH","incomeType":"FROM_LEGAL_ENTITY","totalAmount":1E+3,"cancellationInfo":{"cancellationTime":"2019-07-18T10:14:12.292Z","registerTime":"2019-07-18T10:14:12.292Z","comment":"Чек сформирован ошибочно"},"sourceDeviceId":"33A084EE-5252-4F79-998A-DE9680B3DA87","clientInn":"7706456380","clientDisplayName":"ООО «ЦБП»","partnerDisplayName":null,"partnerInn":null,"inn":"772994823230"}
21.02.2025 09:14
Похоже, прикрыла ФНС "лавочку" с возможностью получения данных по чеку самозанятых. Либо сервис перестал работать. Никто ничего не слышал/не пользуется этим механизмом ?
21.02.2025 12:17
По Вашей ссылке прилетает такой ответ:

{"code":"Not Authenticated","message":"Not Authenticated","additionalInfo":{}}

Требует какую-то авторизацию... Какую, х.з....
Просто в ЛК надо зайти, или это только отправителю чека доступно, или только самим налоговикам...
Не понятно. При этом, принт, работает
21.02.2025 12:19
Похоже, это просто дыра у них была, не документированная, которую они пофиксили.
21.02.2025 12:56
Такое сообщение и раньше было, если адрес был ошибочный. Вот и интересно - то ли "пофиксили", то ли что-то упало.
21.02.2025 15:24
Цитата:
Starter Такое сообщение и раньше было, если адрес был ошибочный. Вот и интересно - то ли "пофиксили", то ли что-то упало.
Неправда Ваша. Если адрес неверные, то приходит сообщение
Код:
{
  "code": "receipt.not.found",
  "message": "Чек не найден",
  "additionalInfo": {

  }
}
Наверное разумно проверить гипотезу, что нужна авторизация на сайте?

Да, и решил по быстрому проверить, как чеки читают бесплатные сервисы OCR, а том числе, имеющие API... Не решаясь нарушить чьи-то персональные данные, стер часть информации:

Чек No20005tnn66
(аннулирован 18.07.2019)
18.07.2019
13:12:45(МСК)
Си....а П...а
Александровна
ИНН: 772...23230
Режим НО: НПД
Наименование
Сумма
1. Написание статьи.
1 000.00 P
Итого:
Покупатель:
ИНН: 770....80
1 000.00 P

Правка: AndreyZh, 21.02.2025 15:36
24.02.2025 17:32
Писали в поддержку ФНС, получили ответ: ".. Метод получения сведений о чеках в виде json-файлов никогда не являлся публичным, нигде не публиковался. С 20.02.25 возможность использования данного метода отключена. Для получения сведений о доходах необходимо использовать метод GetIncomeRequestV2."
18.03.2025 15:20
Эхх. Жалко, прикрыли лавочку. Пришлось городить распознование OCR. Сделал через Яндекс (но там платно (0.13 р за одну картинку)) и через OCR Space (там тоже ограничения (не больше 180 запросов в час, не больше 20000 в месяц, да и периодически подвисает). Распознаёт в принципе неплохо, но всё равно нет четкого разделения где и что находится, поэтому полностью разобрать чек не получается....

Ну а GetIncomeRequestV2 - "Веб-сервисы для интеграции с ПП НПД предназначены для обмена информацией между данной подсистемой, входящей в состав АИС «Налог-3» ФНС России, и внешними информационными системами Партнеров, к которым относятся системы банков-Партнеров и платформ-Партнеров."


Ниже - что-то типа "заготовки" для получения текста чека. Без разбора.
Код:
Функция РаспознатьOCRSpace(СсылкаНаЧек) 
// подготовим файл с данными для отправки
строкаBase64=Base64Строка(ПолучитьДвоичныеДанныеФайлаПоСсылке(СсылкаНаЧек));
строкаBase64=СтрЗаменить(строкаBase64,Символы.ВК,"");
строкаBase64=СтрЗаменить(строкаBase64,Символы.ПС,"");
имяФайлаОтправки = ПолучитьимяВременногоФайла("txt");
Boundary = СтрЗаменить(Строка(Новый УникальныйИдентификатор()), "-", "");
 
ЗаписьТекста = Новый ТекстовыйДокумент;
ЗаписьТекста.РазделительСтрок=Символы.CR+Символы.LF;
 
// параметр "language"
ЗаписьТекста.ДобавитьСтроку("Content-Disposition: form-data; name=""language""");
ЗаписьТекста.ДобавитьСтроку("");
ЗаписьТекста.ДобавитьСтроку("rus");
ЗаписьТекста.ДобавитьСтроку("--"+boundary);
// параметр "filetype"
ЗаписьТекста.ДобавитьСтроку("Content-Disposition: form-data; name=""filetype""");
ЗаписьТекста.ДобавитьСтроку("");
ЗаписьТекста.ДобавитьСтроку("png");
ЗаписьТекста.ДобавитьСтроку("--"+boundary);
// параметр "OCREngine"
ЗаписьТекста.ДобавитьСтроку("Content-Disposition: form-data; name=""OCREngine""");
ЗаписьТекста.ДобавитьСтроку("");
ЗаписьТекста.ДобавитьСтроку("2");
ЗаписьТекста.ДобавитьСтроку("--"+boundary);
// параметр "isOverlayRequired"
ЗаписьТекста.ДобавитьСтроку("Content-Disposition: form-data; name=""isOverlayRequired""");
ЗаписьТекста.ДобавитьСтроку("");
ЗаписьТекста.ДобавитьСтроку("false");
ЗаписьТекста.ДобавитьСтроку("--"+boundary); 

// параметр "isTable"
ЗаписьТекста.ДобавитьСтроку("Content-Disposition: form-data; name=""isTable""");
ЗаписьТекста.ДобавитьСтроку("");
ЗаписьТекста.ДобавитьСтроку("true");
ЗаписьТекста.ДобавитьСтроку("--"+boundary); 

// параметр "scale"
ЗаписьТекста.ДобавитьСтроку("Content-Disposition: form-data; name=""scale""");
ЗаписьТекста.ДобавитьСтроку("");
ЗаписьТекста.ДобавитьСтроку("true");
ЗаписьТекста.ДобавитьСтроку("--"+boundary); 



// параметр "base64Image"
//ЗаписьТекста.ДобавитьСтроку("--"+boundary);
//ЗаписьТекста.ДобавитьСтроку("Content-Disposition: form-data; name=""file""; filename=""check.png""");
//ЗаписьТекста.ДобавитьСтроку("Content-Type: image/png");                                             
ЗаписьТекста.ДобавитьСтроку("Content-Disposition: form-data; name=""base64Image""");
ЗаписьТекста.ДобавитьСтроку("");
ЗаписьТекста.ДобавитьСтроку("data:image/png;base64,"+строкаBase64);
ЗаписьТекста.ДобавитьСтроку("");
ЗаписьТекста.ДобавитьСтроку("--"+boundary+"--");

// передадим данные на сервер 
Заголовки = Новый Соответствие();
Заголовки.Вставить("Content-Type", "multipart/form-data; boundary="+boundary);
//Заголовки.Вставить("Content-Lenght", РазмерФайлаОтправки);
Заголовки.Вставить("apikey", "ххххххххх");  //API ключ - можно получить на сервере 
	ИнетЗапрос = Новый HTTPЗапрос("Parse/Image",Заголовки);
	ИнетЗапрос.УстановитьТелоИзСтроки(ЗаписьТекста.ПолучитьТекст());
	ssl = Новый ЗащищенноеСоединениеOpenSSL;
	Соединение = новый HTTPСоединение("api.ocr.space",,,,,,ssl);
Ответ=Соединение.ОтправитьДляОбработки(ИнетЗапрос);   	
ОтветСтрока=Ответ.ПолучитьТелоКакСтроку();	

Если НЕ Ответ.КодСостояния=200 Тогда 
	Сообщить("Ошибка! "+СокрЛП(ОтветСтрока));
	Возврат "";
КОнецЕсли;

	ЧтениеОтвета = Новый ЧтениеJSON;
	ЧтениеОтвета.УстановитьСтроку(ОтветСтрока);
	структураОтвета=ПрочитатьJSON(ЧтениеОтвета);
	СтрокаТекстов="";
	стр2="";
	счч=0;
	Если структураОтвета.Свойство("ParsedResults") Тогда   
		Если СтруктураОтвета.ParsedResults.Количество()>0 Тогда
			СТрокаТекстов=структураОтвета.ParsedResults[0].ParsedText;
		КонецЕсли;
	КонецЕсли;
	мВыход=Новый Массив;
	мвыход=СтрРазделить(СтрокаТекстов,Символы.ПС);
	Возврат строкаТекстов;
КонецФункции // РаспознатьOCRSpace()

Функция ПолучитьДвоичныеДанныеФайлаПоСсылке(СсылкаНаЧек)
	Каталог = КаталогВременныхФайлов();
	Если Прав(Каталог, 1) = "\" Тогда
		СтрДлина = СтрДлина(Каталог);
		Каталог = Лев(Каталог, СтрДлина - 1);
	КонецЕсли;		
	ИмяФайлаЗначение = _ЗагрузитьКартинкуЧекаИзФНС(СсылкаНаЧек,Каталог); 
	Если ИмяФайлаЗначение="" Тогда
		ВОзврат неопределено;
	КонецЕсли;
	
	ДанныеФайла = новый ДвоичныеДанные(ИмяФайлаЗначение);	
	Возврат ДанныеФайла;
КонецФункции // ПолучитьДвоичныеДанныеФайлаПоСсылке()

Функция _ЗагрузитьКартинкуЧекаИзФНС(СсылкаНаЧек,КаталогЧеков) 
	//Загрузить картинку чека из ФНС.
	//   пар1 - ссылка на чек
	//   пар2 - каталог, в который картинка в виде файла помещается
	//Возврат - имя файла (полный путь)

	//---Разберем ссылку
	массивСсылки=СтрРазделить(СсылкаНаЧек,"/");
	Если массивСсылки.Количество()<6 Тогда
		Возврат "";
	КонецЕсли;
	
	ИмяСервера=массивСсылки[1];
	НомерЧека=массивСсылки[6];
	ИмяЧека = КаталогЧеков + "\"+НомерЧека+".png";
	HTTPЗапрос=СтрЗаменить(СсылкаНаЧек,"https://"+ИмяСервера,"");
	//---
	Соединение = Новый HTTPСоединение(ИмяСервера,443,,,,,Новый ЗащищенноеСоединениеOpenSSL());
	Попытка
		Ответ=Соединение.Получить(HTTPЗапрос, ИмяЧека);
		Если Ответ.КодСостояния=200 Тогда
			Возврат ИмяЧека;
		Иначе
			Возврат "";
		КонецЕсли;
	Исключение
		Возврат "";
	КонецПопытки;
КонецФункции // ЗагрузитьКартинкуЧекаИзФНС()
Часовой пояс GMT +3, время: 11:23.

Форум на базе vBulletin®
Copyright © Jelsoft Enterprises Ltd.
В случае заимствования информации гипертекстовая индексируемая ссылка на Форум обязательна.