Вводная информация

Новые версии драйверов находятся в актуальных дистрибутивах r_keeper, но их можно скачать и отдельно с FTP-сервера: ftp://ftp.ucs.ru/rk7/drivers/. Версия отдельных драйверов может отставать от актуальных версий r_keeper 7. Обновления драйверов выпускаются только для UniFR, Атол и Штрих.

1.1. Интерфейс предназначен для общения приложений с фискальными регистраторами и чековыми принтерами
1.2. Номер версии протокола: 71 (31.08.2023). Нумерация версий общая с протоколом взаимодействия с драйверами терминалов авторизации
1.2.1 В версии 2 добавлена поддержка документа ReturnDeletion — удаление возврата. Добавлен callback печати на другой принтер (функция cpfPrintTextOther)
1.2.2 В версии 3 добавлены атрибуты Order.StartSession, Payment.Id, Payment.Code, добавлен тэг LinkReceipt внутри FiscalDocument для копий чека, удалений и счетов-фактур
1.2.3 В версии 4 добавлены поля Timeout в структуры TDialogInfo, TGetStringInfo
1.2.4 В версии 5 добавлен тэг Footer, атрибут Item.ShortName объявляется устаревшим и не рекомендуется к использованию
1.2.5 В версии 6 добавлена функция UFRStarted; поле TUFRLogicError.LogicErrorText переименовано в LogicErrorTextANSI, так как в предыдущих версиях оно ошибочно использовалось в ANSI кодировке (Win1251), поле LogicErrorTextANSI считается устаревшим. Добавлено новое поле LogicErrorTextUTF8. Драйвер низкого уровня должен проверять size (в версиях 6+ size>=520). Драйвер верхнего уровня может использовать поле LogicErrorTextANSI при пустом поле LogicErrorTextUTF8
1.2.6 В версии 7 тэг RawBlock с Encoding="No" объявлен устаревшим и не рекомендуется к использованию при генерации XML. Используйте Encoding="Base64"
1.2.7 В версии 8 во время инициализации в тэг DriverParameters может добавляться атрибут ProtocolVersion, содержащий поддерживаемую хостом версию этого протокола
1.2.8 В версии 9 добавлена опция foDiscWithTaxes и необязательный атрибут IgnoreTaxesMode
1.2.9 В версии 10 добавлена опция foCanIgnoreTaxes
1.2.10 В версии 11 добавлены опции foAbsItemDiscount, foAbsItemMarkup, foAbsMarkupSum 
1.2.11 В версии 12 добавлена поддержка QRCode
1.2.12 В версии 13 добавлена новая процедура инициализации UFRInitXML, заменяющая UFRInit, UFRMaxProtocolSupported, UFRGetOptions. Добавлена UFRMenuOperation для обработки пользовательского меню. В тэге ZReportData тэг DepartValues объявлен устаревшим, добавлен тэг CounterValues.
1.2.13 В версии 14 добавлен тип документа Custom 
1.2.14 В версии 15 добавлено поле TUFRStatus.PaperStatus, флаг fnPaperStatus
1.2.15 В версии 16 добавлена опция MaxOneMarkupDiscount, при превышении количества скидки/наценки должны складываться и передаваться с пустым именем. Подтэг Unfiscal в Discount и Payment при включенном TextInLine. В Receipt добавлен Guid; в LinkReceipt добавлен Guid
1.2.16 В версии 17 добавлены поля TUFRStatus.XMLBuffer, TUFRStatus.XMLBufferSize, а UFRGetZReportData объявлена устаревшей и не рекомендуется к использованию
1.2.17 В версии 18 добавлены типы документов Bill, CreateOrder, Correction, CloseOrder, CancelSeat опции "Bill", "CreateCloseOrder", "Correction" (foBill, foCreateCloseOrder, foCorrection), добавлен тэг Seat, в тэг Order добавлены Guid, Name, в тэг Receipt добавлен LastBill
1.2.18 В версии 19 добавлены необязательный подтэг Barcodes тэга Item
1.2.19 В версии 20 добавлен тип документа "ReturnReceipt", опция "ReturnReceipt" (foReturnReceipt)
1.2.20 В версии 21 добавлен атрибут PortionName в тэге Item. Начиная с версии 21 серийный номер обязателен, при отсутствии серийного номера и поддержке протокола 21 устройство должно считаться неактивным
1.2.21 В версии 22 в статус добавлен признак EKLZNearEnd
1.2.22 В версии 23 в тэг Item добавлен подтэг CustomData
1.2.23 В версии 24 добавлена опция PayUngrouped (foPayUngrouped), в тэг Payment добавлены атрибуты ISOCode, Rate и OriginalValue
1.2.24 В версии 25 в тэг Item добавлен необязательный атрибут DepartmentName, добавлен тип документа "PrintLog", добавлены универсальные ошибки errLogicBadAnswerFormat, errExtPrintError, опция "Logger"
1.2.25 В версии 26 в тэг Header добавлен необязательный подтэг CustomProperties, используется при поддержке 54-ФЗ
1.2.26 В версии 27 добавлена опция WorkWithoutPaper. при наличии которой хост должен кроме статуса проверять состояние бумаги.
1.2.27 В версии 28 возвратный XML с корневым тэгом FiscalDocumentReturn может содержать подтэг ToPrint для печати. Используется RK7 с документами типа PrintLog.
1.2.28 В версии 29 добавлен атрибут Time в тэг Receipt
1.2.29 В версии 30 добавлен атрибут Position в тэг Unfiscal в позиции чека, вместо DriverParameters возможен корневой тэг xmlConfig
1.2.30 В версии 31 добавлен отчёт "OFDStatus"
1.2.31 В версии 32 добавлена опция "CorrectPriceToPay", "RoundDiscountOnly", атрибут PriceToPay в тэге Item
1.2.32 В версии 33 добавлен необязательный атрибут "TaxType" в тэге Receipt
1.2.33 В версии 34 добавлен необязательный атрибут "TaxPayerIdNum" в тэге Operator. В России это ИНН
1.2.23 В версии 35 добавлен документ "CorrectionReceipt", в России это чек коррекции, опция "CorrectionReceipt", TUFRStatus.OFDUnsentCount, TUFRStatus.OFDOldestUnsent, флаг fnOFDStatus
1.2.24 В версии 36 добавлен необязательный атрибут Item ForAdvance, по умолчанию=0; в UFRInitXMLReturn добавлен тэг Hardware с подтэгом Fiscal
1.2.24 В версии 37 добавлено поле необязательный атрибут Item ForAdvance, по умолчанию=0; в UFRInitXMLReturn добавлен тэг Hardware с подтэгом Fiscal; Добавлено поле TUFRStatus.OFDOldestUnsentTime
1.2.25 В версии 38 добавлена поддержка функций callback  cpfDeviceSignal,  cpfPerformMessage,  cpfExecXML 
1.2.26 В версии 39 добавлены поля TUFRStatus.InternalDate, TUFRStatus.InternalTime, флаг fnInternalDateTime
1.2.27 В версии 40 добавлен тэг Reason для указания причины внесения/выплаты. Добавлена опция foManyCashInOutPayments.
1.2.28 В версии 41 в UFRInitXMLReturn добавлен тэг DataFormat с подтэгом Rounding, в скидки-наценки добавлен атрибут ForRounding, указывающий, что эта скидка/наценка предназначена для округления
1.2.29 В версии 42 после печати фискального документа драйвер заполняет в поле XMLBuffer тэг DocumentInfo с атрибутом GlobalId
1.2.30 В версии 43 в UFRInitXMLReturn добавлен тэг ChangeFromTypeIndexes
1.2.31 В версии 44 в Payment добавлены атрибуты CardNum, AuthCode, RRN. Для их получения, драйвер обязан выставить foPayUngrouped.
1.2.32 В версии 45 добавлена новая функция UpgradeXMLParams
1.2.33 В версии 46 в тег Item добавлены необязательные атрибуты ItemKind и PaymentKind. Драйвер обязан поддерживать совместимость этих атрибутов с ForAdvance. См. ниже примечания к ForAdvance.
1.2.34 В версии 47 после тэга Item.Discounts или Receipt.Discounts может идти необязательный подтэг DiscInfos, содержащий тэги DiscInfo - информация о скидке, сумма которой уже включена в цену и сумму позиций.
1.2.35 В версии 48 добавлена опция foOpenShiftReport и новый тип отчёта OpenShiftReport
1.2.36 В версии 49 добавлен подтег RawTLVAttributes в тег Item
1.2.37 В версии 50 в тег Order добавлен необязательный атрибут GlobalId
1.2.38 В версии 51 в тег PRINTUNFISCAL добавлен необязательный атрибут xml:lang, передающий язык в стандарте ISO 639-1
1.2.39 Начиная с версии 52 необязательный тэг Reason может передаваться для документов Deletion, Return, ReturnReceipt. В тэг LinkReceipt добавлен необязательный подтэг CustomProperties, содержащий свойства исходного чека. В тэг LinkReceipt добавлен необязательный атрибут FiscalDocNum, содержащий фискальный номер документа оригинального чека
1.2.40 В версии 52 в Unfiscal добавлен необязательный подтег AddInfo с обязательными атрибутами Name и Data.
1.2.41 В версии 53 добавлены поля TUFRStatus.ProgramDateMin, TUFRStatus.ProgramTimeMin, флаг fnProgramDateTimeMin
1.2.42 В версии 54 в теги LinkReceipt добавлен атрибут GlobalFiscalId.
1.2.43 В версии 55 в тег Unfiscal.Barcode добавлены атрибуты Align и FlowTextLines
1.2.44 В версии 56 в тэг Item добавлен необязательный подтэг Voids
1.2.45 В версии 57 добавлены: опция foCancelOrder, фискальный документ CancelOrder - документ отмены заказа.
1.2.46 В версии 58 добавлены: опция foCancelBill, фискальный документ CancelBill - документ отмены счёта/пречека.
1.2.47 В версии 60 в тэг UFRInitXMLReturn добавлен подтэг Logs ( В версии 7.60.367 добавлена возможность использовать систему налогообложения, заданную в ФР )
1.2.48 В версии 62 добавлены: опция foCheckMarking, документ CheckMarking, подтег MarkingData в тег Item, подтег CheckMarkingInfo в тег FiscalDocumentReturnCardHolder
1.2.49 В версии 63 добавлен счётчик Global_13
1.2.50 В версии 64 добавлен атрибуты QuantityUnitType и PartsPerPackage.
1.2.51 В версии 65 добавлен вариант OneString атрибута dialogType тэга DIALOGINFO
1.2.52 В версии 66 добавлен документ CorrectionReceipt2, в России это чек коррекции по ФФД1.1. и ФФД1.2, опция CorrectionReceipt2
1.2.53 В версии 67 добавлен атрибут EstimatedStatus в тэг MarkingData
1.2.54 В версии 68 добавлены поле TUFRStatus.EKLZdaysNearEnd, флаг fnEKLZdaysNearEnd
1.2.55 В версии 69 добавлен документ GetDocumentData и опция foGetDocumentData
1.2.56 В версии 70 добавлены атрибуты TerminalId и PaymentSystem тэга Payment. Для их получения нужно выставить опцию foPayUngrouped
1.2.57 В версии 71 добавлен атрибут MarkSign в тег CheckMarkingInfo
1.2.58 В версии 72 добавлен атрибут NoOnline в тег MarkingData.

Новый драйвер

Описание процесса интеграции нового драйвера в RKeeper 7 содержится в статье Разработка универсального драйвера ФР нижнего уровня

Сокращения

ФР – фискальный регистратор.
УДФР – универсальный драйвер ФР. 
ОФД – оператор фискальных данных – здесь глобальный сервис, куда отсылаются данные о фискальных продажах.

Соглашения

  • Integer = LongInt       – четырёхбайтовое целое со знаком.
  • DWord = cardinal        - четырёхбайтовое целое без знака
  • Word                    – двухбайтное целое без знака.
  • Boolean                 – однобайтное со значением 1 - истина, 0 - ложь.
  • 'YYYY-MM-DDThh:nn:ss'   - Строковый формат Дата/Время, где: 
  • YYYY - год
  • MM - месяц
  • DD - день
  • hh - часы
  • nn - минуты
  • ss - секунды
String[n] = packed record
  Len: Byte;
  Str: Array[0..n-1] of Char
end;            
  • ShortString = String[255] - короткая строка, n <= 255.
  • OpenString  – специальный тип, не зависящий от опций компилятора, используется при передаче ShortString var-параметром.
  • Int64 – восьмибайтовое целое со знаком.
  • XML в кодировке "UTF-8", все строки в кодировке "UTF-8", если явно не указано ANSI.
  • Количества передаются целыми числами в ТЫСЯЧНЫХ ДОЛЯХ. Например, для количества "1" передаётся значение "1000".
  • Деньги передаются целыми числами, в КОПЕЙКАХ, кроме значения счётчиков ФР, возвращаемых в CounterValue.
  • Ставки налога передаются целым числом в десятых долях процента.
  • Курс валюты - плавающее число, разделитель - точка (стандарт XML), единственное число с плавающей точкой
  • Хост - приложение или модуль, загружающий DLL универсального драйвера, формирующий входные данные и разбирающий выход.

Процедуры

Инициализация - финализация: UFRMaxProtocolSupported, UFRInit, UFRDone, UFRGetOptions

function UFRMaxProtocolSupported(): Integer;

  • Обязательная функция для протоколов 1..12, для 13+ может быть определена для совместимости.
  • Возвращает максимальный номер поддерживаемого протокола. Текущий номер версии указан в начале этого документа.

UFRInit

function UFRInit(Number: Integer;
                 XMLParams: PAnsiChar;
                 InterfaceCallback: tInterfaceCallbackProc;
                 PropCallback: tPropCallbackProc): Integer; stdcall;
  • Обязательная функция для протоколов 1..12, для 13+ может быть определена для совместимости.
  • Инициализация ФР (инстанса) с номером Number.
  • На одной кассе может быть несколько ФР с различными номерами Number.
  • XMLParams – ссылка на XML <DriverParameters ProtocolVersion="8">..</DriverParameters> с параметрами (начиная с протокола 30 возможен <xmlConfig ProtocolVersion="8">..</xmlConfig>), необязательный атрибут ProtocolVersion добавляется хостом, содержит версию этого протокола (поддерживается начиная с версии 8). Если ProtocolVersion не задан, то считается, что хост работает с протоколом версии 0. Драйвер, имеющий обязательную минимальную версию не будет работать. Настоятельно рекомендуется всегда заполнять ProtocolVersion последней версией протокола, которая принималась во внимание при разработке хоста.
  • PropCallbackProc - не обязателен. Возможно добавление всех необходимых свойств
  • в XML документ, однако, вынесение запроса редких свойств в PropCallbackProc
  • позволит не увеличивать размер XML документа до бесконечности.
  • В случае успеха возвращает 0, иначе - код ошибки.
  • Если вызов UFRInit завершается с ошибкой, в этом случае необходимо закрыть COM-порт,
  • все открытые файлы и т.п, потому что DLL-файл драйвера нижнего уровня будет перезагружен
  • через FreeLibrary, LoadLibrary, с повторным вызовом UFRInit. Описания обработки ошибок в пункте 8.
  • При выгрузке DLL через FreeLibrary без завершения процесса COM-порт автоматически
  • не закрывается.

UFRInitXML

  • Если эта функция определена и хост поддерживает протокол 13+, то хост должен вызвать эту функцию и не вызывать UFRInit, UFRGetOptions, UFRMaxProtocolSupported.
function UFRInitXML(Number: Integer;
                 XMLParams: PAnsiChar;
                 InterfaceCallback: tInterfaceCallbackProc;
                 PropCallback: tPropCallbackProc;
                 InitXMLReturnBuffer: PAnsiChar): Integer; stdcall;
  • Инициализация ФР (инстанса) с номером Number.

  • На одной кассе может быть несколько ФР с различными номерами Number.
  • XMLParams – ссылка на XML <DriverParameters ProtocolVersion="13">..</DriverParameters> с параметрами (начиная с протокола 30 возможен <xmlConfig ProtocolVersion="8">..</xmlConfig>), обязательный атрибут ProtocolVersion добавляется хостом, содержит версию этого протокола. Настоятельно рекомендуется всегда заполнять ProtocolVersion последней версией протокола, которая принималась во внимание при разработке хоста.
  • PropCallbackProc - не обязателен. 
  • В случае успеха возвращает 0, иначе - код ошибки. См. комментарии в UFRInit по поводу обработки ошибок инициализации
  • InitXMLReturnBuffer ссылается на буфер, размером не меньше 500K (524288 байт, драйвер не должен возвращать строки длиннее 524287 байт), куда драйвер запишет ASCIIZ строку с XML возврата вида (тэг Options обязательный, атрибут MaxProtocolSupported обязательный, остальные необязательные, тэг Menu не обязательный).
<UFRInitXMLReturn MaxProtocolSupported="13" DriverName="Low level super driver" VersionInfo="1.1 special++">
	<Options>
		<Option Name="Text"/>
		<Option Name="ZeroReceipt"/>
		<Option Name="DeleteReceipt"/>
		<Option Name="ZReport"/>
		<Option Name="MoneyInOut"/>
		<Option Name="XReport"/>
		<Option Name="SpecialReport"/>
		<Option Name="ZeroSale"/>
		<Option Name="Program"/>
		<Option Name="FullLastShift"/>
		<Option Name="AllMoneyOut"/>
		<Option Name="TextInReceipt"/>
		<Option Name="BarCodeInNotFisc"/>
		<Option Name="ZClearMoney"/>
		<Option Name="CheckCopy"/>
		<Option Name="TextInLine"/>
		<Option Name="ItemDepartments"/>
		<Option Name="OnlyFixed"/>
		<Option Name="TextOpenShift"/>
		<Option Name="DrawerOpen"/>
		<Option Name="DrawerState"/>
		<Option Name="CustomerDisplay"/>
		<Option Name="Slip"/>
		<Option Name="CalcChange"/>
		<Option Name="ZWhenClosedShift"/>
		<Option Name="AbsDiscountSum"/>
		<Option Name="FiscInvoice"/>
		<Option Name="CashRegValue"/>
		<Option Name="FixedNames"/>
		<Option Name="DeleteReturn"/>
		<Option Name="DiscWithTaxes"/>
		<Option Name="CanIgnoreTaxes"/>
		<Option Name="AbsItemDiscount"/>
		<Option Name="AbsItemMarkup"/>
		<Option Name="AbsMarkupSum"/>
		<Option Name="MaxOneMarkupDiscount"/><!-- с версии 16 не более одной скидки/наценки на каждую позицию и не более одной скидки/наценки на чек-->
		<Option Name="Bill"/><!-- с версии 18-->
		<Option Name="CreateCloseOrder"/><!-- с версии 18-->
		<Option Name="Correction"/><!-- с версии 18-->
		<Option Name="ReturnReceipt"/><!-- с версии 20-->
		<Option Name="PayUngrouped"/><!-- с версии 24-->
		<Option Name="Logger"/><!-- с версии 25-->
		<Option Name="WorkWithoutPaper"/><!-- с версии 27-->
		<Option Name="CorrectPriceToPay"/><!-- с версии 32-->
		<Option Name="RoundDiscountOnly"/><!-- с версии 32-->
		<Option Name="CorrectionReceipt"/><!-- с версии 35-->
                <Option Name="ManyCashInOutPayments"/><!-- с версии 40-->
                <Option Name="OpenShiftReport"/><!-- с версии 48-->
                <Option Name="CancelOrder"/><!-- с версии 57 -->
                <Option Name="CancelBill"/><!-- с версии 58 -->
<Option Name="CheckMarking"/><!-- c версии 62 -->
               <Option Name="CorrectionReceipt2"/><!-- c версии 66 -->
               <Option Name="GetDocumentData"/><!-- c версии 69 --> </Options><!-- см. раздел Поддерживаемые опции и информация о драйвере--> <MENU caption="Super driver menu"> <!-- начиная с версии 13, caption здесь не обязательный, RK7 в 7.5.5 заменяет его на имя логического устройства --> <MENUITEM caption="Group 1"> <!-- так задаётся подменю, caption - обязательный --> <MENUITEM caption="Test supergiperfunction" <!-- обязательный --> operationId="{123E720F-BAFC-453F-9948-50662663F75C}" <!-- обязательный для исполняемого пункта меню --> parameter="12345" <!-- не обязательный, если есть будет скопирован при вызове в parameter --> purposeToLock="{A4C4606D-F7C4-4FBF-83D7-00AD12DD7E55}" <!-- назначение печати, перед выполнением принтер с этого назначения будет заблокирован, не обязательный --> userRight="{A4C4606D-F7C4-4FBF-83D7-00AD12DD7E55}"> <!-- право, которое будет проверяться перед выполнением, не обязательный --> <DIALOGINFO dialogType="DateInterval"|"NumberInterval"|"OneDate"|"OneNumber"|"OneString" caption="Enter date interval for superreport"/>
<!-- DIALOGINFO не обязательный, OneString начиная с 65 --> </MENUITEM> <MENUITEM caption="Settings"> <!-- подменю --> <MENUITEM caption="Set superpassword" <!-- обязательный --> operationId="{123E720F-BAFC-453F-9948-50662663F75C}"/> </MENUITEM> </MENUITEM> </MENU> <Hardware><!--начиная с версии 36, не обязательный--> <!-- Fiscal начиная с версии 36, не обязательный - информация о характеристиках устройства, связанных с функциями налогового учёта и контроля EndDate - дата окончания работы (первый день, когда не будет работать) фискального накопителя (и его аналогов), при невозможности заполнить - не добавлять атрибут --> <Fiscal EndDate="2020-12-23" /> </Hardware> <DataFormat><!--начиная с версии 41, не обязательный--> <!-- Rounding начиная с версии 41, не обязательный - информация о правилах округления сумм по позициям Multiplier - точность округления, по умолчанию 0.01 --> <Rounding Multiplier="0.01" /> </DataFormat> <ChangeFromTypeIndexes>0 2 4</ChangeFromTypeIndexes><!-- начиная с версии 43, не обязательный. Индексы валют, с которых разрешено давать сдачу. Список, разделённый пробелами. Используется только при выставленной опции foCalcChange. Если отсутствует или пустой, то разрешена сдача только с наличных в национальной валюте. -->
<Logs><!-- начиная с версии 60, не обязательный, содержит маски логов, атрибуты не обязательны, если на заданы будут заполнены верхним уровнем.-->
<Log Module="fpSpark.dll#0">c:\ucs\rkeeper 7\bin\win\fpSpark_0.log</Log>
 <Log Module="fpSpark.dll#0">c:\ucs\rkeeper 7\bin\win\fpSpark_0.*.log</Log>
<Log Module="/fpSpark.dll#0/SparkServ.exe">c:\ucs\rkeeper 7\bin\win\SparkServ\SparkServ*.log</Log>
</Logs> </UFRInitXMLReturn>

InterfaceCallback

tInterfaceCallbackProc = procedure(ModuleHandle: tHandle;
                                   Number: Integer;
                                   FuncID: Integer;
                                   ProtocolVersion: Integer;
                                   FuncParams: Pointer); stdcall;
  • ModuleHandle - хэнд модуля, который вызывает процедуру;
  • Number - Номер ФР, который передали при регистрации;
  • FuncParams - указатель на параметр, возможно структура, часть полей которой могут меняться (для возврата значений).

Описание функций вызова в разделе 4

const //Список функций Callback процедуры (параметр "FuncID").
  cpfDialog = 1; //Вызов диалога, структура tDialogInfo //см. Вызов диалога на станции.
  cpfProgress = 2; //Индикация прогресса, структура tProgressInfo //см. Иллюстрация прогресса.
  cpfGetStringDialog = 3; //Диалог запроса строки, структура tGetStringInfo //см. Вызов диалога запроса строки.
  cpfRegisterSpecMenu = 4; //Зарегистрировать специальное меню, структура tDriverMenuInfo
                          //см. Дополнительные функции (спец. меню, общее с другими драйверам).
  cpfLog=5; //Логирование
  cpfTranslate=6; //Перевод, структура tTranslateInfo
  cpfPrintTextOther = 7; //Печать текста на другой принтер, структура tPrintTextOtherInfo (версия 2+)
  cpfDeviceSignal     = 8; //Послать сигнал с идентификатором как от внешнего устройства, структура tDeviceSignalInfo (версия 38+)
  cpfPerformMessage   = 9; //Синхронно обработать сообщение с возвратом результата, структура tPerformMessageInfo (версия 38+)
  cpfExecXML          = 10;//Выполнение XML команды, структура tExecXMLInfo (версия 38+)

PropCallback

tPropCallbackProc = procedure(XMLTag: PAnsiChar;
                              Identifier: PAnsiChar;
                              PropName: PAnsiChar;
                              var PropValue: OpenString); stdcall;
  • XMLTag - тип элемента, совпадает с тэгом. Поддерживаются варианты: "Operator", "Item", "Discount", "Payment","Restaurant"
  • Идентификатор - атрибут Id соответствующего 
  • Identifier - Идентификатор элемента
  • PropName   - Имя свойства


Например, для получения наименования единиц измерения можно использовать следующий фрагмент:

var
  fPropCallback: tPropCallbackProc; // заполняется внутри UFRInit
  Measures: ShortString; //искомое наименование единиц измерения товара
  ItemNode:IXMLNode;// XML тэг Item
  ItemIdStr:AnsiString;
...

ItemIdStr:=ItemNode.GetAttr('Id');
Measures:='';
if assigned(fPropCallback) then
  fPropCallBack('Item', PAnsiChar(ItemIdStr),'PortionName',Measures);

Формат XML параметров (устаревший)

  • В этом разделе описывается примерный формат XML файла, содержащего параметры. 
  • Содержимое этого файла передаётся драйверу в функции UFRInit в параметре XMLParams.
  • Для конкретного драйвера формат может быть другим, обязательным является только имя корневого тега DriverParameters. Разработчик драйвера описывает формат параметров, требующихся его драйверу в виде XML файла конфигурации параметров. Атрибуты корневого тэга могут модифицироваться.
<DriverParameters
   ProtocolVersion="10"> <!-- ProtocolVersion не задаётся пользователем, а прописывается хостом, начиная с версии 8, версия протокола, поддерживаемая хостом -->
  <Parameter Name="Port Name"
             LocaleID="0419"
             IntegerValue=""
             StringValue="Com1"/>

  <Parameter Name="Port Configuration"
             IntegerValue=""
             StringValue="baud=9600 parity=N"/>

  <Parameter Name="Password"
             IntegerValue="0"/>

  <Parameter Name="Password2"
             IntegerValue="0"/>

  <Parameter Name="ZRepCounters"
             IntegerValue=""
             StringValue="money_1 money_2 operator_name"/>

</DriverParameters>
  • "Port Configuration" - предназначен для передачи в функцию WinAPI "SetCommState".
  • Password - основной пароль доступа к ФР, нужен для выполнения любых действий на ФР
  • Password2 - дополнительный пароль (например, пароль старшего администратора), нужен для выполнения на ФР действий, требующих указания дополнительного пароля, помимо основного. Указывать дополнительный пароль нужно не для всех ФР, а только для тех, которые не позволяют получить дополнительный пароль, зная основной. Примером такого ФР служит PayVKP-80K.
  • NeedWorkToStart - параметр, определяющий необходимость проверки работоспособности ФР при вызове UFRInit

XML файл конфигурации параметров (устаревший)

  • Внимание, этот раздел описывает устаревшую информацию, о новом способе задания параметров см. раздел "схема параметров и новый формат (xmlConfig)".
  • Редактор параметров нужен для автоматизации формирования XML-параметров функции UFRInit.
  • Для работы редактору параметров необходима входная информация, представленная в файле <name>.cfg.xml для драйвера <name>.dll в следующем виде:
<DriverConfiguration>
  <ParametersConfiguration>
    <ParameterInfo Name="Port Configuration"
                   Type="String"
                   DefaultValue="baud=9600">
      <Skin LocaleID="419"
            UserName="Конфигурация порта"
            Description="Конфигурация COM порта вида baud=XXX parity=YYY, подробнее см. mode /?">
      </Skin>
      <Skin LocaleID="409"
            UserName="Com configuration"
            Desctiption="Com configuration like baud=XXX parity=YYY, see mode /?">
      </Skin>
    </ParameterInfo>
    <ParameterInfo Name="AutoProgramTime"
                   Type="ListItemValue"
                   MinValue="0"
                   MaxValue="65535"
                   DefaultValue="0">
      <Skin LocaleID="419"
            UserName="АвтоПрогрВремя"
            Description="Автоматически программировать время">
        <ListItems>
           <ListItem StringValue="Нет" IntegerValue="0"/>
           <ListItem StringValue="Да" IntegerValue="1"/>
        </ListItems>
      </Skin>
      <Skin LocaleID="409"
            UserName="AutoProgramTime"
            Desctiption="Program internal device time automatically">
        <ListItems>
           <ListItem StringValue="No" IntegerValue="0"/>
           <ListItem StringValue="Yes" IntegerValue="1"/>
        </ListItems>
      </Skin>
    </ParameterInfo>
    <ParameterInfo Name="Classification"
                   Type="Integer"
                   MinValue="0"
                   MaxValue="65535"
                   DefaultValue="0">
      <Skin LocaleID="419"
            UserName="Код классификации"
            Description="Код классификации">
      </Skin>
      <Skin LocaleID="409"
            UserName="AutoProgramTime"
            Desctiption="Program internal device time automatically">
        <ListItems>
           <ListItem StringValue="No" IntegerValue="0"/>
           <ListItem StringValue="Yes" IntegerValue="1"/>
        </ListItems>
      </Skin>
    </ParameterInfo>
  </ParametersConfiguration>

  <SupportDevices>
    <Drawer Count="0"/>
    <CustomerDisplay Count="0"/>
    <ExtPrinter Count="0"/>
  </SupportDevices>

  <ReferentProperties>
    <Property Name="FR12324"
              ObjectClass="tCurrency"
              MinValue="0"
              MaxValue="4"
              DefaultValue="0">
       <Skin LocaleID="419"
             UserName="FR12324"
             Description="Тип платежа, используемый фискальным регистратором FR12324 для данной валюты ">

         <ListItems>
            <ListItem StringValue="Наличные" IntegerValue="0"/>
            <ListItem StringValue="Карта 1" IntegerValue="1"/>
            <ListItem StringValue="Карта 2" IntegerValue="2"/>
          <ListItem StringValue="Карта 3" IntegerValue="3"/>
         </ListItems>
       </Skin>
       <Skin LocaleID="409"
             UserName="FR12324"
             Desctiption="Fiscal register FR12324 will use this pay type for this currency">

         <ListItems>
            <ListItem StringValue="Cash" IntegerValue="0"/>
            <ListItem StringValue="Card 1" IntegerValue="1"/>
            <ListItem StringValue="Card 2" IntegerValue="2"/>
            <ListItem StringValue="Card 3" IntegerValue="3"/>
         </ListItems>
       </Skin>
    </Property>
    <Property Name="FR12324"
              ObjectClass="tTaxRate"
              MinValue="0"
              MaxValue="4"
              DefaultValue="0">
    </Property>
  </ReferentProperties>

</DriverConfiguration>
  • Значение атрибута LocaleID задавать в шестнадцатеричном формате.

Схема параметров и новый формат (xmlConfig)

  • Все драйвера начиная с 2016 года содержат ресурс DEVICECONFIGV01XSD
  • Этот ресурс содержит схему параметров в формате .xsd
  • Требования: двухуровневая иерархия параметров (группы параметров, в них сами параметры), корневой тэг параметров должен называться "xmlConfig". Поддерживаемые типы данных: xs:string, xs:normalizedString, xs:integer, xs:decimal, xs:boolean. Подробнее см. http://tracker.ucs.ru/issues/66361 Логическое значение поля xs:time
  • Пример:

<xmlConfig ProtocolVersion="30">
  <Parameters>
    <LogLevel>5</LogLevel>
    <MsgLanguage>ru</MsgLanguage>
    <CMDpassword>11111111</CMDpassword>
    <COMnum>2</COMnum>
    <Header>Line 1&#13;&#10;lllll  %s  llllllllllll&#13;&#10;lineeeeeeeeeeeeeeeeeee 3&#13;&#10;&#9;&#9;</Header>
    <PaperWidth>40</PaperWidth>
    <PrinterDeviceID>20</PrinterDeviceID>
    <PrintingTimeout>60</PrintingTimeout>
  </Parameters>
  <FilesAndPaths>
    <FileNameXML>DOC%1:.6d_%2:s.xml</FileNameXML>
    <FileNameControlTape>%1:.6d_%2:s.txt</FileNameControlTape>
    <TapePath>%0:s\%1:.6d</TapePath>
    <CopyPath>copy%0:s\SHIFT%1:.6d</CopyPath>
    <BackupPath>backup%0:s</BackupPath>
  </FilesAndPaths>
  <InitXMLFixedData>
    <nod_numurs>1234567890123</nod_numurs>
    <reg_adrese>111 street</reg_adrese>
    <veikala_adrese>222 street</veikala_adrese>
    <kases_nosaukums>RK7</kases_nosaukums>
    <kases_sistemas_nr>121212</kases_sistemas_nr>
  </InitXMLFixedData>
</xmlConfig>
 
и соответствующая структура:
 
<?xml version="1.0" encoding="utf-8"?>

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:element name="xmlConfig">
    <xs:complexType>
      <xs:all>
        <xs:element name="Parameters">
          <xs:complexType>
            <xs:all>
              <xs:element name="LogLevel" type="xs:integer" default="3">
                <xs:annotation>
                  <xs:documentation xml:lang="en" source="captiontext">Log Level</xs:documentation>                  <xs:documentation xml:lang="en" source="description">0-errors, 1-external function calls, 2-all function calls, 3-high level transport, 4-low level transport, 5-all</xs:documentation>
                </xs:annotation>     
 </xs:element>
              <xs:element name="MsgLanguage" type="xs:normalizedString" default="LAT">
                <xs:annotation>
                  <xs:documentation xml:lang="en" source="captiontext">Message Language</xs:documentation>
                  <xs:documentation xml:lang="en" source="description">3 character language string (RUS, LAT)</xs:documentation>
                </xs:annotation>     
 </xs:element>
              <xs:element name="CMDpassword" type="xs:normalizedString" default="00000000">
                <xs:annotation>
                  <xs:documentation xml:lang="en" source="captiontext">Device Command Password</xs:documentation>
                  <xs:documentation xml:lang="en" source="description">Device Command Password - 8 characters, see device documentation.</xs:documentation>
                </xs:annotation>
 </xs:element>
              <xs:element name="COMnum" type="xs:integer">
                <xs:annotation>
                  <xs:documentation xml:lang="en" source="captiontext">Com Port Number</xs:documentation>
                  <xs:documentation xml:lang="en" source="description">Com Port Number</xs:documentation>
                </xs:annotation>     
 </xs:element>
              <xs:element name="Header" type="xs:string">
                <xs:annotation>
                  <xs:documentation xml:lang="en" source="captiontext">Document Header</xs:documentation>
                  <xs:documentation xml:lang="en" source="description">Multi line header of document to print</xs:documentation>
                </xs:annotation>     
 </xs:element>
              <xs:element name="PaperWidth" type="xs:integer" default="40">
                <xs:annotation>
                  <xs:documentation xml:lang="en" source="captiontext">Paper Width</xs:documentation>                  <xs:documentation xml:lang="en" source="description">Paper width in characters</xs:documentation>
                </xs:annotation>     
 </xs:element>
              <xs:element name="PrinterDeviceID" type="xs:normalizedString">
                <xs:annotation>
                  <xs:documentation xml:lang="en" source="captiontext">Printer Device ID</xs:documentation>
                  <xs:documentation xml:lang="en" source="description">Code of logical device for print. Also can be GUID of logical device or printing purpose. If empty "Printer COM Port" should be filled</xs:documentation>
                </xs:annotation>     
 </xs:element>
              <xs:element name="PrinterCOMPort" type="xs:integer" default="0">
                <xs:annotation>
                  <xs:documentation xml:lang="en" source="captiontext">Printer COM Port Number</xs:documentation>
                  <xs:documentation xml:lang="en" source="description">Printer Com port number, if 0 "Printer Device ID" should be filled</xs:documentation>
                </xs:annotation>     
 </xs:element>
              <xs:element name="PrinterCOMConfig" type="xs:normalizedString">
                <xs:annotation>
                  <xs:documentation xml:lang="en" source="captiontext">Printer COM Config</xs:documentation>
                  <xs:documentation xml:lang="en" source="description">Printer Com configuration, if printer com port name filled, for documentation see help for mode command, run "mode/?"</xs:documentation>
                </xs:annotation>     
 </xs:element>
              <xs:element name="PrintingTimeout" type="xs:integer" default="60">
                <xs:annotation>
                  <xs:documentation xml:lang="en" source="captiontext">Printing Timeout</xs:documentation>
                  <xs:documentation xml:lang="en" source="description">Maximal time of printing in seconds</xs:documentation>
                </xs:annotation>
</xs:element>
              <xs:element name="DefaultUnitName" type="xs:normalizedString" default="gab">
                <xs:annotation>
                  <xs:documentation xml:lang="en" source="captiontext">Default Unit Name</xs:documentation>
                  <xs:documentation xml:lang="en" source="description">Default Unit Name (if empty in menu item)</xs:documentation>
                </xs:annotation>
              </xs:element>
              <xs:element name="PrnComInit" type="xs:normalizedString" default="">
                <xs:annotation>
                  <xs:documentation xml:lang="en" source="captiontext">Initial sequence</xs:documentation>
                  <xs:documentation xml:lang="en" source="description">Initial sequence for each document</xs:documentation>
                </xs:annotation>     
              </xs:element>
              <xs:element name="PrnComCompressed" type="xs:integer" default="0">
                <xs:annotation>
                  <xs:documentation xml:lang="en" source="captiontext">Compressed Font</xs:documentation>
                  <xs:documentation xml:lang="en" source="description">0=Normal Font (Font A),1=Compressed Font (Font B)</xs:documentation>
                </xs:annotation>     
     </xs:element>
            </xs:all>
          </xs:complexType>
        </xs:element>
        <xs:element name="FilesAndPaths">
          <xs:complexType>
            <xs:all>
              <xs:element name="FileNameXML" type="xs:normalizedString" default="DOC%1:.6d_%2:s.xml">
                <xs:annotation>
                  <xs:documentation xml:lang="en" source="captiontext">XML Tape File Name</xs:documentation>
                  <xs:documentation xml:lang="en" source="description">%0:s - serial number, %1:.6d - shift number; %2:s - date</xs:documentation>
                </xs:annotation>     
     </xs:element>
              <xs:element name="FileNameControlTape" type="xs:normalizedString" default="%1:.6d_%2:s.txt">                <xs:annotation>
                  <xs:documentation xml:lang="en" source="captiontext">Control Tape File Format</xs:documentation>
                  <xs:documentation xml:lang="en" source="description">%0:s - serial number, %1:.6d - shift number; %2:s - date</xs:documentation>
                </xs:annotation>     
     </xs:element>
              <xs:element name="TapePath" type="xs:normalizedString" default="%0:s">
                <xs:annotation>
                  <xs:documentation xml:lang="en" source="captiontext">Tape file path</xs:documentation>                  <xs:documentation xml:lang="en" source="description">Path to store actual XML and text document files. %0:s - serial number, %1:.6d - shift number</xs:documentation>
                </xs:annotation>     
     </xs:element>
              <xs:element name="CopyPath" type="xs:normalizedString" default="copy%0:s">
                <xs:annotation>
                  <xs:documentation xml:lang="en" source="captiontext">Copy file path</xs:documentation>                  <xs:documentation xml:lang="en" source="description">Path to store actual copy of XML and text document files. %0:s - serial number, %1:.6d - shift number</xs:documentation>
                </xs:annotation>     
     </xs:element>
              <xs:element name="BackupPath" type="xs:normalizedString" default="backup%0:s">
                <xs:annotation>
                  <xs:documentation xml:lang="en" source="captiontext">Backup path</xs:documentation>                  <xs:documentation xml:lang="en" source="description">Path to store copy of XML and text document files. Files will be copied on Z report. %0:s - serial number, %1:.6d - shift number; %2:s - date</xs:documentation>
                </xs:annotation>     
     </xs:element>
            </xs:all>
          </xs:complexType>
        </xs:element>
        <xs:element name="InitXMLFixedData">
          <!--<xs:annotation>
            <xs:documentation xml:lang="en" source="description">Data to fill Initialization document, first in XML electronic tape (nodes lietotajs, kases_dati)</xs:documentation>
          </xs:annotation>
          <xs:complexType>
            <xs:all>
              <xs:element name="nod_numurs" type="xs:normalizedString">
                <xs:annotation>
                  <xs:documentation xml:lang="en" source="captiontext">Taxpayer Number</xs:documentation>
                  <xs:documentation xml:lang="en" source="description">Taxpayer Number in XML initialization document (kases_sistema.lietotajs.nod_numurs)</xs:documentation>
                </xs:annotation>     
     </xs:element>
              <xs:element name="reg_adrese" type="xs:normalizedString">
                <xs:annotation>
                  <xs:documentation xml:lang="en" source="captiontext">Legal address</xs:documentation>                  <xs:documentation xml:lang="en" source="description">Legal address in XML initialization document (kases_sistema.lietotajs.adreses.reg_adrese)</xs:documentation>
                </xs:annotation>     
     </xs:element>
              <xs:element name="veikala_adrese" type="xs:normalizedString">
                <xs:annotation>
                  <xs:documentation xml:lang="en" source="captiontext">Trading address</xs:documentation>
                  <xs:documentation xml:lang="en" source="description">Trading address in XML initialization document (kases_sistema.lietotajs.adreses.veikala_adrese)</xs:documentation>
                </xs:annotation>     
     </xs:element>
              <xs:element name="kases_nosaukums" type="xs:normalizedString">
                <xs:annotation>
                  <xs:documentation xml:lang="en" source="captiontext">Cash system name</xs:documentation>
                  <xs:documentation xml:lang="en" source="description">Cash register system name in XML initialization document (kases_sistema.kases_dati.kases_nosaukums)</xs:documentation>
                </xs:annotation>     
     </xs:element>
              <xs:element name="kases_sistemas_nr" type="xs:normalizedString">
                <xs:annotation>
                  <xs:documentation xml:lang="en" source="captiontext">Cash system number</xs:documentation>
                  <xs:documentation xml:lang="en" source="description">Cash register system number in XML initialization document (kases_sistema.kases_dati.kases_sistemas_nr)</xs:documentation>
                </xs:annotation>
     </xs:element>
            </xs:all>
          </xs:complexType>
</xs:element>
      </xs:all>
    </xs:complexType>
  </xs:element>
</xs:schema>

procedure UFRDone(Number: Integer); stdcall;

  • Обязательная функция. Всегда определяется.
  • Для каждого успешного UFRInit должен быть вызван UFRDone, даже если освобождается библиотека FreeLibrary.
  • После вызова последнего UFRDone (когда не осталось проинициализированных экземпляров), драйвер должен автоматически выполнить финализационные процедуры.
  • Желательно не оставлять финализационные процедуры в финализационных частях модулей, так как потоки в Windows не просыпаются во время финализации DLL.

    В UFRDone callback-функции "InterfaceCallback", "PropCallback" не вызывать.

Поддерживаемые опции и информация о драйвере: UFRGetOptions

function UFRGetOptions(Number: Integer;
                       var Options: Int64;
                       var DriverName: OpenString;
                       var VersionInfo: OpenString;
                       var DriverState: OpenString): Integer; stdcall;
Обязательная функция для протоколов 1..12, для 13+ может быть определена для совместимости, должна вызываться после UFRInit.
  • DriverName  – About
  • DriverState – configuration / errors – отладочная информация о драйвере
  • VersionInfo - номер версии драйвера
  • Options – комбинация констант foXXX

В случае успеха возвращает 0, иначе - код ошибки.

const //для UFRGetOptions
  foText = $1; //ФР поддерживает отдельную нефискальную печать (не в чеке).
  foZeroReceipt = $2; //ФР поддерживает печать нулевого чека (с нулевой стоимостью).
  foDeleteReceipt = $4; //ФР поддерживает удаление чека или аннулирование или возврат.
  foZReport = $8; //ФР поддерживает Z отчёт.
  foMoneyInOut = $10; //ФР поддерживает внесения-выдачи.
  foXReport = $20; //ФР поддерживает X отчёт.
  foSpecialReport = $40; //ФР поддерживает специальные отчёты:
                         //BriefByDate; DetailByDate; BriefByNumber; OFDStatus; ByArticul; ZeroCheck
  foZeroSale = $80; //ФР поддерживает печать продажи с "нулевой" суммой, если этой опции нет, драйвер нижнего уровня 
                    //не должен давать ошибку, а должен, если сможет, напечатать имя нефискальным текстом, 
                    //если и это не сможет, просто проигнорировать
  foProgram = $100; //ФР поддерживает программирование принтера (при закрытой смене).
  foFullLastShift = $200; //ФР поддерживает распечатку последней смены.
  foAllMoneyOut = $400; //ФР поддерживает изъятие всех денег.
  foTextInReceipt = $800; //ФР поддерживает нефискальную печать внутри чека (внутри <Header>).
  foBarCodeInNotFisc = $1000; //ФР поддерживает печать штрих-кода в нефискальной части чека.
  foZClearMoney = $2000; //Z-отчёт автоматически очищает остаток денег в кассе.
  foCheckCopy = $4000; //Фискальный документ - копия чека (пока только в Латвии).
  foTextInLine = $8000; //ФР поддерживает нефискальную печать внутри линии чека (внутри <Item> или <Payment> или <Discount>).
  foItemDepartments  = $10000; //ФР поддерживает отделы по товарам/услугам.
  foOnlyFixed = $20000; //Работа только с заранее запрограммированными товарами
                        //(RK7 в этом случае использует блюда "итого" по отделам с кодами отделов
                        // и распечатывает "суммарные" чеки с такими блюдами), пример: prim08 в режиме отделов.
  foTextOpenShift = $40000; //Признак, что нефискальная печать открывает фискальную смену.
  foDrawerOpen = $80000; //ФР может открывать ящик.
  foDrawerState = $100000; //ФР может возвращать состояние ящика.
  foCustomerDisplay = $200000; //ФР поддерживает вывод на дисплей покупателя.
  foSlip = $400000; //ФР поддерживает печать на бланке.
  foCalcChange = $0800000; //ФР поддерживает вычисление сдачи (если установлена, то по платежу придет две суммы - сколько дали наличных и сколько сдача с минусом (например, 10 и -3); если не установлена, то придет одна сумма (например, 7))
  foZWhenClosedShift = $1000000; //ФР поддерживает печать Z-отчёта при закрытой смене.
  foAbsDiscountSum = $2000000; //ФР поддерживает абсолютные (не процентные) скидки, если UFRMaxProtocolSupported<11, 
                               //то если этот флаг выставлен, то надо считать выставленными foAbsItemDiscount, foAbsItemMarkup, foAbsMarkupSum.
  foFiscInvoice = $4000000; //ФР поддерживает печать фискального чека как счет-фактуру.
  foCashRegValue = $8000000; //ФР поддерживает возврат значения регистра кассовой наличности.
  foFixedNames = $10000000; //ФР требует неизменности имён позиций в течении дня.
  foDeleteReturn = $20000000; //(версия 2+) ФР поддерживает операцию удаление выкупа.
  foDiscWithTaxes = $40000000; //(версия 9+) ФР принимает скидки на чек вместе с налоговыми ставками, соответственно, 
                               //скидки должны разбиваться по ставкам, в скидках на чек надо указывать налоги, 
                               //иначе для правильного расчёта налогов скидки надо разбивать по товарам (скидкам на позицию налоги не нужны).
                               //Скидки округления (см. foRoundDiscountOnly) всегда передаются без налогов
  foCanIgnoreTaxes = $080000000; //(версия 10+) ФР может не передавать налоги вместе с товаром и скидкой, 
                                 //при выставлении этой опции драйвер нижнего.
  foAbsItemDiscount     = $100000000; //(версия 11+) ФР может печатать скидки на позиции, 
                                 //для более старых версий такие скидки считаются возможными, если включено foAbsDiscountSum. 
                                //Если включено foAbsItemDiscount и выключено foAbsDiscountSum, то суммовые скидки разбиваются по позициям.
  foAbsItemMarkup       = $200000000; //(версия 11+) ФР может печатать наценки на позиции, для более старых версий 
                              //такие наценки считаются возможными, если включено foAbsDiscountSum. 
                              //Если включено foAbsItemMarkup и выключено foAbsDiscountSum, то суммовые наценки
                              //приходят в драйвер разбитые по товарам уровня 
                              //должен быть готов к отсутствию тэга Taxes как в Item так и в Discount.
                              // Драйвер верхнего уровня либо заполняет Taxes везде либо не заполняет нигде (только если есть такая опция)
  foAbsMarkupSum        = $400000000; //(версия 11+) ФР поддерживает абсолютные (не процентные) наценки на чек
  foMaxOneMarkupDiscount= $800000000; //(версия 16+) Не больше одной наценки/скидки
  foBill              =  $1000000000; //(версия 18+) ФР печатает фискальные документы "Счёт"
  foCreateCloseOrder  =  $2000000000; //(версия 18+) ФР печатает фискальные документы "Открытие заказа", "Закрытие заказа"
  foCorrection        =  $4000000000; //(версия 18+) ФР печатает фискальные документы "Коррекция заказа"
  foReturnReceipt     =  $8000000000; //(версия 20+) ФР печатает фискальные документы "Возврат по чеку"
  foPayUngrouped      = $10000000000; //(версия 24+) Не группировать платежи по индексу платежа, добавлять в тэг Payment атрибуты ISOCode, Rate, OriginalValue. Начиная с 44 версии CardNum, AuthCode, CardHolder, RRN. Начиная с 70 версии TerminalID и PaymentSystem. 
  foLogger            = $20000000000; //(версия 25+) Устройство используется для логирования печати других устройств
  foWorkWithoutPaper  = $40000000000; //(версия 27+) Устройство может выполнять фискальные операции без бумаги. Если это не устраивает, хост должен анализировать PaperStatus
  foCorrectPriceToPay = $80000000000; //(версия 32+) Если хост поддерживает протокол 32 и драйвер выставил эту опцию, хост должен передавать атрибут PriceToPay и так, чтобы PriceToPay * Quantity равна сумме к оплате по позиции, если опции нет, то может передавать, может не передавать, а драйвер может вычислить. 
  foRoundDiscountOnly =$100000000000; //(версия 32+) Если выставлена эта опция, то корректировка округления добавляется отдельной суммарной скидкой без налогов на маленькую сумму. При foAbsDiscountSum без foAbsItemDiscount поведение аналогичное, но скидка с налогами если foDiscWithTaxes. 
  foCorrectionReceipt =$200000000000; //(версия 35+) ФР печатает фискальные документы "Чек коррекции" (Россия)
  foManyCashInOutPayments =$400000000000; //(версия 40+) ФР умеет принимать несколько типов платежей в одном документе CashInOut. Если не указана, то тэг Payment должен быть только один.
  foOpenShiftReport =$800000000000; //(версия 48+) ФР умеет делать отчёт OpenShiftReport - отчёт открытия смены.
  foCancelOrder    =$1000000000000; //(версия 57+) ФР умеет печатать фискальный документ CancelOrder
  foCancelBill     =$2000000000000; //(версия 58+) ФР умеет печатать фискальный документ CancelBill
foCheckMarking =$4000000000000; //(версия 62+) ФР умеет проверять обязательную маркировку товара по фискальному документу CheckMarking
foCorrectionReceipt2 =$8000000000000; //(версия 66+) ФР печатает фискальные документы "Чек коррекции" по ФФД 1.1 и ФФД 1.2(Россия)
foGetDocumentData = $10000000000000; //(версия 69+) Драйвер поддерживает получение данных чека через документ GetDocumentData

UFRStarted (начиная с версии 6)

procedure UFRStarted(Number: Integer);stdcall;

Процедура вызывается после того, как загружены все драйверы принтеров и прочие драйвера, к которым может быть неявное обращение. Например, из этой процедуры можно печатать на другой принтер и т.п.

Проверка (запрос) статуса: UFRGetStatus

function UFRGetStatus(Number: Integer;
                      var Status: TUFRStatus;
                      FieldsNeeded: Cardinal): Integer; stdcall;
  • Обязательная функция. Всегда определяется.
  • Перед вызовом в структуре заполнить поле Size, все остальные поля структуры должны быть обнулены.
  • Если драйвер не поддерживает какое-либо поле, оно остаётся равным нулю (драйвер неизвестную ему часть структуры не изменяет).
  • Статус смены надо заполнять даже если аппарат не предоставляет такой возможности. При этом, Z отчёт (DocType="Report" и Report.ReportType="Z") должен приводить к состоянию закрытой смены, а любой чек к состоянию открытой. Если аппарат поддерживает печать нулевых чеков (опция ZeroSale), нулевой чек должен открывать смену).
  •  FieldsNeeded – битовая маска, указывающая, какие поля необходимо заполнить (в разных ситуациях требуются разные поля). В случае успеха возвращает 0, иначе - код ошибки.  Описания обработки ошибок в пункте 8.
type
  TString35 = String[35];
  TMoney    = type Int64;
  TUFRShiftState = (ssShiftClosed, ssShiftOpened, ssShiftOpened24hoursExceeded);

const
  paperOk=0;
  paperOut=1;
  paperLow=2;
doorOpen=4; type PUFRStatus = ^TUFRStatus; TUFRStatus = packed record Size: Integer; //SizeOf(TUFRStatus), заполняется до вызова, драйвер нижнего уровня не должен ругаться на больший размер, чем он ожидает. Лишние поля (лишнее место в конце) просто не трогать. NotReady: Boolean; //Не готов Busy: Boolean; //Работает [занят] CannotPrintUnfiscal: Boolean; //Невозможно выполнить нефискальную печать QueueSize: Integer; //Размер очереди для нефискальной печати //NOTE. По возможности, возвращать сумму длин очередей драйвера и устройства DrawerOpened: Boolean; //Ящик открыт ShiftState: TUFRShiftState; //Статус фискальной смены SerialNum: TString35; //Уникальный идентификатор ФР (возможно с моделью), начиная с версии 21 обязателен LastShiftNum: Word; //Номер последнего Z отчёта //(номер закрытой смены) LastDocNum: Integer; //Последний номер напечатанного документа //(в том числе инкассации и т.п.) LastReceiptNum: Integer; //Последний номер чека SaledValue: Int64; //Сумма продаж за смену, в копейках CashRegValue: TMoney; //Сумма в кассе, в копейках PaperStatus: Integer; //15+ paperOk=0 - ок, paperOut=1 - бумага закончилась, paperLow=2 - бумага близка к завершению, doorOpen=4 - крышка принтера открыта XMLBuffer: PAnsiChar; //17+ указатель на буфер для возврата XML в виде строки, завершающейся 0 в кодировке utf-8, //заполняется до вызова UFRGetStatus или UFRFiscalDocument, перед вызовом надо в первый байт буфера прописать 0, допустимо передавать nil. Рекомендуемый размер буфера 512к. XMLBufferSize: Integer; //17+ размер буфера, заполняется до вызова UFRGetStatus или UFRFiscalDocument, в случае недостаточного размера и XMLBuffer<>nil возвращается ошибка errAssertInsufficientBufferSize, а в этом поле содержится требуемый размер (включая концевой 0) EKLZNearEnd: Boolean; //22+ Warning о скором заполнении ЭКЛЗ или его аналогов, соответствующий флаг fnOFDStatus OFDUnsentCount: Integer; //35+ Количество неотправленных в ОФД документов, соответствующий флаг fnOFDStatus OFDOldestUnsent: Integer; //35+ Дата старейшего неотправленного документа - число дней от 30.12.1899, соответствующий флаг fnOFDStatus OFDOldestUnsentTime: Integer; //37+ Время в миллисекундах от начала дня старейшего неотправленного документа, соответствующий флаг fnOFDStatus. InternalDate: Integer; //39+ Внутренняя дата в ФР - число дней от 30.12.1899, соответствующий флаг fnInternalDateTime. InternalTime: Integer; //39+ Внутреннее время в ФР в миллисекундах от начала дня, соответствующий флаг fnInternalDateTime. ProgramDateMin:      Integer;     //53+ Минимально допустимая для программирования дата. 0 - если не ограничено. флаг fnProgramDateTimeMin. ProgramTimeMin:      Integer;     //53+ Минимально допустимое для программирования время. Значимо, если ProgramDateMin > 0. флаг fnProgramDateTimeMin.
   EKLZdaysNearEnd:     Integer;     //68+ Количество дней до окончания ЭКЛЗ, соответствующий флаг fnEKLZdaysNearEnd
end;

При сброшенном поле "fnNotCancelReceipt" необходимо выполнить проверку: если чек
открыт, то его необходимо отменить. Однако, для избранных типов ФР (DATECS и т.п.),
в которых оплаты и закрытие чека разнесены по разным командам, неполностью
оплаченный чек отменить уже нельзя. Такой чек можно только закрыть, но сначала
его необходимо полностью оплатить наличными.

const //значения маски FieldsNeeded для UFRGetStatus

fnNotCancelReceipt = $0001; //Не отменять открытый чек.
  fnBusy = $0002; //Требуется заполнить Busy и NotReady.
  fnUnfiscalPrint = $0004; //Требуется заполнить CanNotPrintUnfiscal.
  fnPrintQueue   = $0008; //Длина очереди печати (для нефискальной печати).
  fnDrawerOpened = $0010; //Признак открытого ящика.
  fnPaperStatus  = $0020; //Надо вернуть информацию о конце бумаги
  fnShiftState   = $0100; //Статус фискальной смены. 
  fnSerialNumber = $0200; //Строка-идентификатор ФР, кроме серийного номера можно прописать закодированную модель ФР. 
  fnLastShiftNum = $0400; //Номер последней закрытой[!] фискальной смены, если первая смена, то 0. 
  fnLastDocNum   = $0800; //Последний номер напечатанного документа (включая внесения-выдачи).
  fnLastReceiptNum = $1000; //Последний номер фискального чека может совпадать с номером документа.
  fnSaledValue = $2000;   //Сумма продаж или за смену или глобально. //Использовать только для проверки изменилась/не изменилась (прошёл или нет последний чек).
  fnOFDStatus = $4000;    //информация о неотправленных документах и признак скорого переполнения EKLZNearEnd
  fnCashRegValue = $8000; //Запрос значения регистра кассовой наличности в ФР.
  fnInternalDateTime = $10000; //Запрос полей InternalDate и InternalTime.
  fnProgramDateTimeMin  = $20000; //53+ Запрос полей ProgramDateMin, ProgramTimeMin
fnEKLZdaysNearEnd = $40000; //68+ Запрос поля EKLZdaysNearEnd

Нефискальная печать: UFRUnfiscalPrint

 function UFRUnfiscalPrint(Number: Integer; XMLBuffer: PAnsiChar; Flags: Integer): Integer; stdcall;

  • Необязательная функция. Может не определяться.
  • В случае успеха возвращает 0, иначе - код ошибки.  Описания обработки ошибок в пункте 8.
  • XMLBuffer содержит XML с корневым тэгом Unfiscal.
  • Flags всегда 0

Тэг Unfiscal

  • Все атрибуты необязательные кроме Text, Encoding, Value, Number
<!-- Slip: 0 - переключиться на рулон | 1 - переключиться на подкладную печать (на бланке) -->
<!-- CutAfter: 1 - отрезать бумагу после[!] печати нефискального документа -->
<Unfiscal Slip="0"|"1" CutAfter="0"|"1">
        <TextBlock FontNum="1"
              Bold="0"|"1"
              BigHeight="0"
              BigWidth="0"
              Inverted="0"
              Tapes="1"|"2"|"3">
      Строка 1
      Строка 2
      Строка 3
   </TextBlock>
   <TextBlock FontNum="1" Bold="0"|"1" BigHeight="0" BigWidth="0" Inverted="0" Tapes="1"|"2"|"3">
<![CDATA[ 
      Строка 4 
      Строка 5 
      Строка 6
]]> </TextBlock>
<!-- строка целиком -->
<!-- ПРИМЕЧАНИЕ. В языке Паскаль аналог "WriteLn" -->
<TextLine FontNum="1" <!-- номер шрифта. может отсутствовать -->
Bold="0"|"1" <!-- 0 - обычная яркость шрифта | 1 - повышенная яркость шрифта -->
BigHeight="0"|"1" <!-- 0 - обычная высота символов | 1 - двойная высота символов -->
BigWidth="0"|"1" <!-- 0 - обычная ширина символов | 1 - двойная ширина символов -->
Inverted="0"|"1" <!-- 0 - сбросить выделение цветом | 1 - установить выделение цветом -->
Tapes="1"|"2"|"3" <!-- Выбор лент для печати: 1 - основная, 2 - контрольная, 3 - обе -->
Text="Text"/>
<!-- часть строки -->
<!--
Если от КАССЫ была получена непустая строка символов без символа перевода строки "0x0A",
последовательность печатных символов оформляется тэгом <TextPart> (часть строки)
-->

<!-- ПРИМЕЧАНИЕ. В языке Паскаль аналог "Write" -->

<TextPart FontNum="1"
Bold="0"|"1"
BigHeight="0"
BigWidth="0"
Inverted="0"
Tapes="1"|"2"|"3"
Text="Text"/>
<RawBlock Encoding="No"> <!--Не рекомендуется использовать, используйте Encoding="Base64" -->
&#0;&#x11; &#x22;&#xAA;
</RawBlock>
<RawBlock Encoding="Base64">
ABEiqg==
</RawBlock>

<!-- штрих-код, все атрибуты кроме Value не обязательные -->

<BarCode Width="2" <!-- ширина минимального элемента в точках -->
Height="100" <!-- высота в точках -->
Type="EAN-13"|"Code-39"|"Code-128"|"QRCode"
TextPosition="No"|"Top"|"Bottom"|"Top&Bottom" <!-- для Type≠QRCode -->
CorrectionLevel="7%"|"15%"|"25%"|"30%"<!-- необязательный, начиная с 12 версии, только для Type=QRCode -->
Align="Center"|"Left"|"Right" <!-- необязательный, начиная с 55 версии, только для Type=QRCode. Выравнивание кода.  Если не задан, то считать Center -->
FlowTextLines="0" <!-- необязательный, начиная с 55 версии, только для Type=QRCode. Сколько следующих строк текста распечатать рядом с кодом, только для Align="Left" или Align="Right" -->
Value = "ABRACADABRA"/>

<Beep/> <!-- звуковой сигнал -->
<Drawer Number="0"|"1"/> <!-- импульс на разъем ящика с номером = Number -->
<Logo Number="1"/> <!-- печать картинки из памяти принтера, номер = Number может быть текстом, например -->
<Pass Lines="0".."99"/> <!-- прогон нескольких строк, количество строк = Lines -->
<Wait MSecs="0".."100000"/> <!-- подождать, миллисекунд = MSecs -->
<AddInfo Name="fooName" Data="barData"> <!-- необязательный. Name и Data обязательные. Дополнительная информация специфичная для применения. В RK7 добавляется ESC-командой "AddInfo fooName= barData" в макете. -->
</Unfiscal>

Для того чтобы закодировать «]]>» в разделе CDATA, заменяют все вхождения этого набора символов на следующее: ]]]]><![CDATA[>

В штрих-кодах горизонтальный размер может задаваться свойством Width, вертикальный Height. В QR кодах могут использоваться оба атрибута, поэтому хосту рекомендуется задавать оба (иметь возможность настраивать). В документации драйвера нижнего уровня должно быть отражено, какой из атрибутов Width или Height используется для определения масштаба

Тэг Unfiscal внутри позиции чека

При включенной опции TextInLine внутри тэгов Item, Payment, Discount может быть подтэг Unfiscal. Содержимое этого тэга такое же, как и тэга Unfiscal, описанного в 3.4.1. Начиная с версии 30 возможен необязательный атрибут Position со значениями "Before" или "After". Других атрибутов тэга Unfiscal быть не должно. Если аппарат не позволяет напечатать в конкретной ситуации, то драйвер не должен вызывать ошибку. Если аппарат не позволяет напечатать текст в нужной позиции сверху/снизу, то надо печатать там, где это возможно.

Печать фискального документа: UFRFiscalDocument

function UFRFiscalDocument(Number: Integer;
                           XMLDoc: PAnsiChar;
                           var Status: TUFRStatus;
                           var FieldsFilled: Cardinal): Integer; stdcall;
  • Необязательная функция. Может не определяться.

Вых. параметры:

  • Status - свойства статуса
    • XMLBuffer - 17+ см. TUFRStatus
  • FieldsFilled – маска заполненных свойств в статусе.
  • В случае успеха возвращает 0, иначе - код ошибки.  Описания обработки ошибок в пункте 8.

Если программе мало полученных данных по соответствующим заполненным свойствам в статусе, она может дополнительно вызывать UFRGetStatus.
Однако, если в результате выполнения фискальной печати данные о статусе есть без дополнительных команд, желательно, чтобы драйвер их заполнял (заполнив соответствующие биты в маске).
 
Внутри XMLBuffer строка XML в кодировке utf-8, завершающаяся нулём. Корневой тэг FiscalDocumentReturn с возможными подтэгами:

  • ToPrint с подтэгом Unfiscal (см. 3.4.1, начиная с 28) для печати (в RK7 поддерживается только для PrintLog, для остальных документов драйвер сам печатает при необходимости через callback) ,
  • CustomData для возврата произвольной информации,
  • ZReportData в соответствии с пунктом 3.6.1 для Z отчёта
  • DocumentInfo с атрибутом GlobalId (начиная с 42)
    • В теге DocumentInfo должен быть заполнен атрибут GlobalId, однозначно идентифицирующий фискальный документ. Для ФР в России GlobalId имеет формат данных QR-кода фискального чека по 54-ФЗ.

      Например

      <?xml version="1.0" encoding="utf-8"?>
      <FiscalDocumentReturn>
        <DocumentInfo GlobalId="t=20210822T2321&s=5.00&fn=9999078902009292&i=180&fp=1785927743&n=1"/>
      </FiscalDocumentReturn>
      CODE
  • CheckMarkingInfo с атрибутами:
    • Result = 0 - проверка пройдена, маркировка валидная
    • Result = 1 - проверка пройдена, маркировка не валидная
    • Result = 2 - драйвер или аппарат не поддерживает проверку маркировки
    • Result >=3 - другие результаты
    • Message - текст результата проверки, понятный кассиру
    • MarkSign - знак проверки маркировки (вычисляется по тегу 2106). Необязательный. Если присутствует, то используется вместо Result
    • MarkSign = 0 - соответствует знаку \[M-\]
    • MarkSign = 1 - соответствует знаку \[M+\]
    • MarkSign = 2 - соответствует знаку \[M\]

      <?xml version="1.0" encoding="utf-8"?>
      <FiscalDocumentReturn>
        <CheckMarkingInfo Result="0" Message="Код маркировки правильный." MarkSign="1"/>
      </FiscalDocumentReturn>

Формат XMLDoc:

Все атрибуты и тэги обязательные (для соответствующей версии протокола), если явно не указано другое, кроме тэга Unfiscal.

<FiscalDocument DocType="Receipt"|"Invoice"|"Deletion"|"ReturnReceipt"|"ReceiptCopy"|"Return"|"ReturnDeletion"|
                        |"CashInOut"|"CollectAll"|"Report"|"Custom"|"Bill"|"CreateOrder"|"Correction"|"CloseOrder"|"CancelSeat"
|"PrintLog"|"CorrectionReceipt"|"CancelOrder"|"CancelBill"|"CheckMarking"|"CorrectionReceipt2"
|"GetDocumentData"

                 Options=""> <Header> <Restaurant Code="10" Name="Астория"/> <Operator Id="123123" Code="20" Name="Петров" TaxPayerIdNum="1234567890"/> <!-- кассир, Id не обязателен TaxPayerIdNum (в России ИНН) начиная с 34, не обязательный --> <Station Id="321321" Code="30" Name="TEST_ST_310"/> <!-- POS станция, Id не обязателен --> <Unfiscal> <!-- см. 3.4.1 --> <TextBlock> Нефискальный заголовок документа </TextBlock> </Unfiscal> <CustomProperties> <!-- Начиная с 26, необязательный --> <CustomProp> <Name>EXTRASYSTEMPROPERTY</Name> <Data>SomeValue</Data> </CustomProp> </CustomProperties> </Header> <Footer> <!-- необязательный, начиная с версии 5 --> <Unfiscal><!-- см. 3.4.1 Нефискальный футер документа --> </Unfiscal> </Footer> <Invoice <!-- если драйвер выставил foFiscInvoice. Для счёта-фактуры (DocType="Invoice") обязателен. Для документов возврата необязательный. --> INN="1234567890" <!-- Поле "ИНН" из формы "Реквизиты организации" --> Name="Волков А.Б." <!-- Поле "Наименование" из формы "Реквизиты организации" --> Address="Deep Forest, 1" <!-- Поле "Адрес" из формы "Реквизиты организации" --> ExtraInfo="Restaurant" <!-- Поле "Доп. инфо" из формы "Реквизиты организации" --> Comment="No" <!-- Поле "Комментарий" из формы "Реквизиты организации" --> Time="YYYY-MM-DDThh:nn:ss" <!-- Значение поля "DateTime" из датасета "DSN_INVOICES" --> Number="1" <!-- Значение поля "InvoiceNum" из датасета "DSN_INVOICES" --> Seller="Зайцев В.Г."/> <!-- Продавец (Кассир) --> <LinkReceipt Number="" FiscalDocNum="" Guid="{569BA754-58A0-4520-95C8-886996E10F5B}" GlobalFiscalId="RcptId75617bis" /> <!-- Для копии чека, удаления чека, счёта-фактуры, удаления возврата. Для удаления дублируется внутри тэга Deletion. Number - номер исходного чека, сгенерированный фискальником, возвращённый в TUFRStatus.LastReceiptNum FiscalDocNum - с версии 52 - фискальный номер исходного документа, сгенерированный фискальником, возвращённый в TUFRStatus.LastDocNum Guid - начиная с версии 16, идентификатор чека, строка, не обязательно является GUID, но длиной не более 38 символов, совпадает с Receipt.Guid GlobalFiscalId - начиная с версии 54. строка. Необязательный. Совпадает с FiscalDocumentReturn/DocumentInfo.GlobalId возвращаемого из чека продажи --> <Receipt DocNumber="123" Guid="{569BA754-58A0-4520-95C8-886996E10F5B}" LastBill="1" Time="YYYY-MM-DDThh:nn:ss"> <!— Для чека, счёта, копии чека, удаления чека, возврата, счёта-фактуры, удаления возврата. открытия заказа, закрытия заказа DocNumber - ссылка на документ во внешней системе Guid - Начиная с версии 16, генерируется хостом, идентификатор чека, строка, не обязательно является GUID, но длиной не более 38 символов LastBill - Начиная с версии 18, не обязательный Time - начиная с версии 29 TaxType - начиная с 32, не обязательный - тип налогообложения, в России: 0 - общее, 1-УСН доход, 2-УСН доход - расход, 3-ЕНВД, 4-ЕСН, 5-Патент --> <Order Table="стол" Guests="5" StartService="2014-02-04T15:58" Guid="{DC5BB359-9718-446E-9169-1C0D16DC2230}" Name="123456" GlobalId="XXX-YYY-ZZZ"> <!-- тэг не обязательный для чека, StartService, Name не обязательные ,  Guid - идентификатор заказа, строка, не обязательно является GUID, но длиной не более 38 символов, GlobalId не обязательный, с протокола 50--> <Operator Code="21" Name="Иванов"/> <!-- официант --> <Seat Number="1" Name="1"/><!--не обязательный, место за столом--> </Order> <Deletion Time="YYYY-MM-DDThh:nn:ss"> <!-- Это для удаления чека и удаления возврата --> <LinkReceipt Number="" FiscalDocNum="" Guid="{569BA754-58A0-4520-95C8-886996E10F5B}"<!-- Начиная с версии 16 --> GlobalFiscalId="RcptId75617bis" <!-- Начиная с версии 54. Необязательный. Значение FiscalDocumentReturn/DocumentInfo.GlobalId из чека продажи --> /> <Operator Code="22" Name="Васин" TaxPayerIdNum="1234567890"/> <!-- менеджер, удаливший чек TaxPayerIdNum (в России ИНН) начиная с 34, не обязательный --> </Deletion> <Items> <Item Id="235" <!-- идентификатор элемента справочника товара --> Name="Торт" ShortName="Торт" <!-- устаревший, не использовать --> Code="123321" <!-- код в справочнике --> Department="3" <!-- отдел --> DepartmentName="Супертовары" <!-- необязательный, начиная с 25 версии, имя отдела --> Quantity="2000" <!-- количество в тясячных долях (2000 = 2) -->
QuantityUnitType="0" <!-- Мера количества предмета расчета. Необязательный, с 64 версии. Если не указано, то 0. соответствует тегу 2108 в 54-ФЗ. см. прим. ниже. -->
PartsPerPackage="0" <!-- Количество дробных частей в маркированной пачке. Не обязательный, с 64 версии. Если 0 или не указано, то считается, что пачка продаётся целиком. см. прим. ниже.-->        
PricePerOne="500" <!-- цена за единицу, которая до применения скидки на позицию--> PriceToPay ="500" <!-- необязательный, начиная с 32 версии цена за единицу с учётом скидок, при опции CorrectPriceToPay - обязательный--> ForAdvance ="0" <!-- необязательный. Появился в версии 36. Должен отсутствовать при наличии ItemKind. Устаревший начиная с 46 версии. Значения - при 1 продажа аванса, которым в будущем можно будет расплачиваться, например, подарочная карта, по умолчанию 0.--> ItemKind="" <!-- не обязательный. Появился в версии 46. Заменяет ForAdvance. Признак предмета расчета. Если не передан, то драйвер использует значение "товар", для России 1. Значения для России: 1 - товар, 10 - аванс. Остальные значения тега 1212 из 54-ФЗ. --> PaymentKind="" !-- не обязательный. Появился в версии 46. Обязательный при наличии ItemKind. Признак способа расчета. Если не передан, то драйвер использует значение для России 4. Значения для России: 4 - полный расчёт в момент передачи товара, 3 - аванс. Остальные значения тега 1214 из 54-ФЗ. --> PortionName="шт" <!-- необязательный, начиная с 21 версии --> Value="1000"> <!-- сумма позиции=Quantity*PricePerOne/1000, которая до применения скидки на позицию --> <Taxes><!-- если выставлена опция foCanIgnoreTaxes, тэг не обязательный--> <Tax TaxRateIndex="1" RateValue="1800" TaxValue="153"/> <!-- Обязательно хотя бы один такой тэг для каждого Item, если есть тэг Taxes> <Tax TaxRateIndex="4" RateValue="500" TaxValue="48"/> </Taxes> <Unfiscal Position="Before/After"><!-- включена опция TextInLine, см. 3.4.2 Нефискальная печать в позиции чека.--> </Unfiscal> <Barcodes> <!-- начиная с протокола 19, необязательный, штрихкоды Value с множителями, множители Multiplier xs:decimal --> <Barcode Value="1234567890123" Multiplier="0.125"/> <Barcode Value="8765432190123" Multiplier="1"/> </Barcodes> <CustomData> <!-- начиная с протокола 23, необязательный, данные должны быть в тексте именованных подтэгов, внутри CustomData текста быть не должно --> </CustomData> <RawTLVAttributes><!-- Начиная с 49. Необязательный. Для России. TLV атрибуты позиции. Все подтеги необязательные. В подтегах атрибуты Id и Value обязательные. --> <TLVBIN Id="1162" Value="0005000002C11E5E4144676F705371"/>           <TLVSTR Id="1226" Value="222222222260"/> <TLVU08 Id="1222" Value="4"/> <STLV Id="1223"> <TLVSTR Id="1075" Value="+79012345678"/> <TLVSTR Id="1044" Value="Взаимозачёт"/> <TLVSTR Id="1073" Value="+79012345679"/> <TLVSTR Id="1074" Value="+79012345689"/> <TLVSTR Id="1026" Value="ООО Оператор перевода ИКС"/> <TLVSTR Id="1005" Value="г. Москва, ул. Гагарина, д.63 оф. 350"/> <TLVSTR Id="1016" Value="123456789047"/> </STLV> <STLV Id="1224"> <TLVSTR Id="1171" Value="+79012345690"/> <TLVSTR Id="1225" Value="ООО Поставщик Игрек"/> </STLV> </RawTLVAttributes>
       <MarkingData
         EstimatedStatus="1" <!-- не обязательный. Начиная с 67 версии. Планируемый статус маркированного товара (тэг 2003) -->
         NoOnline="0" <!-- необязательный. Начиная с 72 версии. Отключение онлайн проверки маркировки -->
         Value="MDEwMjkwMDAwMDQ3NTgzMDIxTWRFZng6WHA2WUZkNx05MTgwMjkdOTJhUUlRa0k3b0hYbXpHL21kS3h6Q1VDS1RKSFhvQk9EZG1DZE01azhRajdnYVpWMnhibjY2eEJYR0lLcnRmdnFQSU5BMmprYmp5ajMvTytreTZvdTFOQT09" <-- обязательный. Код маркировки в base64 -->
        /> <!-- не обязательный. Начиная с 62 версии. Данные обязательной маркировки в кодировке base64 -->
     </Item> <Item Id="23211" Name="Суп" Code="356721" Department="1" Quantity="1000" PricePerOne="556" Value="556"> <Discounts><!-- не обязательный тэг --> <!-- Скидки/наценки на позицию. --> <Discount <!-- не обязательный. Фискальная скидка/наценка. Если ФР не поддерживает более одной, то их следует просуммировать. См. опции foAbsItemDiscount, foAbsItemMarkup. Налоги в скидках/наценках на позицию не указываются, так как всё пропорционально: одна позиция - одна ставка.--> Id="2343" <!-- идентификатор элемента справочника скидок, не обязательный --> Name="Подпорченное блюдо" Code="211232" Value="-10" /> </Discounts> <DiscInfos><!-- не обязательный. Появился в версии 47. Дополнительная информация о скидках/наценках, которая уже учтена --> <DiscInfo <!-- не обязательный. Появился в версии 47. Информация о скидке/наценке, сумма которой уже включена в атрибуты Item. ФР попытается распечатать нефискально в чеке. Не должен дублировать Discount. --> Id="2343" <!-- идентификатор элемента справочника скидок, не обязательный --> Name="Скидка за муху." Code="211232" Value="-10" /> </DiscInfos> <Taxes><!-- если выставлена опция foCanIgnoreTaxes, тэг не обязательный, иначе должен быть хотя бы один тэг Tax--> <Tax TaxRateIndex="1" <!-- индекс налоговой ставки --> RateValue="1800"/> <!-- значение налоговой ставки --> </Taxes> <Barcodes> <!-- начиная с протокола 19, необязательный, штрихкоды Value с множителями, множители Multiplier xs:decimal --> <Barcode Value="4444567890123" Multiplier="8"/> <Barcode Value="9765432190123" Multiplier="1"/> </Barcodes> <Voids> <!-- не обязательный. Появился в версии 56. Удаления (уменьшения количества), выполненные за время жизни заказа --> <!-- Id - идентификатор причины удаления, Code - код причины удаления, Name - имя/текст причины удаления, Quantity - количество, удалённое по этой причине-->
          <Void Id="1221" Code="211232" Name="По требованию клиента" Quantity="2000" />
        </Voids>
      </Item> 
    </Items>
    <Discounts> <!-- не обязательный --> 
      <Discount  <!-- не обязательный. Скидка/наценка на чек. --> 
        Id="23213" <!-- идентификатор элемента справочника скидок, не обязательный --> 
        Name="Любимый клиент" 
        Code="211232" 
        Value="-123" Comment="Иванов И.И."> 
        <Taxes> <!-- Скидка на налоги, должны быть заполнены, если у фискальника опция foDiscWithTaxes. Например, в ФР "ШТРИХ" --> 
          <Tax TaxRateIndex="1" RateValue="1800" /> 
        </Taxes> 
      </Discount> 
      <Discount Id="2222" Name="Концерт (наценка)" Code="2434372" Value="10000" ForRounding="1"> 
        <!--  опция ForRounding не обязательная, начиная с версии 41 -->
        <Taxes> 
          <Tax TaxRateIndex="1" <!-- индекс налоговой ставки --> RateValue="1800" /> <!-- значение налоговой ставки --> 
        </Taxes> 
        <Unfiscal><!--  включена опция TextInLine, см. 3.4.2 Нефискальная печать в позиции чека. Если не поддерживается, то игнорировать --> </Unfiscal> 
      </Discount>
    </Discounts>
    <DiscInfos> <!-- не обязательный --> 
      <DiscInfo <!-- не обязательный. Появился в версии 47. Информация о скидке, сумма которой уже включена сумму чека. ФР попытается распечатать нефискально в чеке. Не должен дублировать Discount. Налоги не передаются, т.к. всё уже учтено.--> 
        Id="23213" <!-- идентификатор элемента справочника скидок, не обязательный --> 
        Name="Скидка за вторую муху." 
        Code="211232" 
        Value="-123"> 
      </DiscInfo> 
    </DiscInfos>
    <Payments> <!-- Платежи группируются по типам оплат и знакам сумм если не выставлено PayUngrouped -->
      <Payment 
        Id="10" 
        Code="10" <!-- не обязательный --> 
        Name="Чек" 
        TypeIndex="3" <!-- номер типа платежа, значение определяется внешними настройками --> 
        CardNum="XXXXXXXXXXXX" <!-- не обязательный, начиная с версии 44 --> 
        AuthCode="XXXXXXXXXXXX" <!-- не обязательный, начиная с версии 44 -->
        PaymentSystem="Mastercard" <!-- не обязательный, начиная с версии 70 -->
        CardHolder="XXXXXXXXXXXX YYYY" <!-- не обязательный, начиная с версии 44 -->
        RRN="XXXXXXXXXXXX" <!-- не обязательный, начиная с версии 44 -->
        TerminalId="XXXXXXXXXXXX" <!-- не обязательный, начиная с версии 70 -->
        Value="5000" 
      />
      <Payment Id="11" Code="11" <!-- не обязательный --> Name="Кредитная карта" TypeIndex="2" Value="5000" ISOCode="RUR" Rate="1.0000" OriginalValue="5000" /> <!-- ISOCode, OriginalValue и Rate начиная с 24 при включенном параметре PayUngrouped --> <Payment Id="1" Code="1" Name="Рубли" TypeIndex="0" Value="10000" /> <Payment Id="1" Code="1" Name="Рубли" TypeIndex="0" Value="-4222" /> <!-- если с минусом - это сдача --> <Unfiscal><!-- начиная с версии 16, если включена опция TextInLine, см. 3.4.2 Нефискальная печать в позиции чека. Если не поддерживается, то игнорировать --> </Unfiscal> </Payment> </Payments> </Receipt> <!-- Внесение(+)/выдача(-) наличных денег при DocType="CashInOut" --> <Payment Name="Рубли" Id="1" <!-- не обязательный --> Code="1"<!-- не обязательный --> TypeIndex="0" <!-- номер типа платежа, значение определяется внешними настройками --> Value="150" ISOCode="RUR" Rate="1.0000" OriginalValue="150" /> <!-- внесение, ISOCode, OriginalValue и Rate начиная с 24 --> <Payment Name="Рубли"
    Id="1" <!-- не обязательный --> 
    Code="1"<!-- не обязательный --> TypeIndex="0" Value="-50" <!-- -50 копеек -->
    /> <!-- выдача --> 
  <!-- Отчёты DocType="Report"--> 
  <Report ReportType="X"|"Z"|"BriefByDate"|"DetailByDate"|"BriefByNumber"|"LastShift"|"ByArticul"|"ZeroCheck"|"OFDStatus"|"OpenShiftReport" Parameters=""/> <-- параметры отчёта см. ниже --> 
  <!-- DocType="CorrectionReceipt" и DocType="CorrectionReceipt2" описание ниже в разделах "CorrectionReceipt - чек коррекции" и "CorrectionReceipt2 - чек коррекции по ФФД 1.1 и ФФД 1.2", здесь пример формата --> 
  <FFD Code="31">
    <TLV Tag="" Value=""/>
    <STLV Tag="1174"> 
      <TLV Tag="1177" Value=""/>
      <TLV Tag="1178" Value=""/>
      <TLV Tag="1179" Value=""/>
    </STLV>
  </FFD>
  <Reason Id="1" Code="1" Name="Инкассация"/> <!-- Для документа CashInOut. Причина внесения/выплаты. Необязательный, начиная с 40 версии --> 
</FiscalDocument>

Типы документов (атрибут DocType):

  • Receipt - Простой фискальный чек. Должен быть заполнен тег <Receipt>.
  • Invoice - Фискальный чек как счет-фактура. Должен быть заполнен тег <Invoice>(и всё, что нужно для чека). Если печатается документ типа Invoice, то вызова для печати документа типа Receipt не будет. Драйвер должен напечатать оба документа, если это необходимо.
  • Deletion - Аннулирование чека, должен быть заполнен <Receipt>, <Deletion>, <LinkReceipt>. Если аппарат не поддерживает аннулирований и удалений, но поддерживает возврат, выполнять возврат. С версии 52 добавлен необязательный тэг Reason.
  • ReceiptCopy - Копия чека, должен быть заполнен <LinkReceipt>
  • Return - Чек выкупа. Должен быть заполнен тег <Receipt>. Если аппарат не поддерживает выкупов, но можно выполнить возврат - выполнять возврат, если не может выполнить ни выкуп не возврат, но может выполнить удаление - выполнять удаление. С версии 52 добавлен необязательный тэг Reason.
  • ReturnReceipt - Чек возврата по чеку (версия 20+). Должен быть заполнен тег <Receipt>, <Deletion>, <LinkReceipt>. Если аппарат не поддерживает возвратов или не отличает их от аннулирований, не надо выставлять опцию ReturnReceipt(foReturnReceipt) и в обоих случаях (аннулирование и возврат по чеку) должен приходить документ Deletion. С версии 52 добавлен необязательный тэг Reason.
  • ReturnDeletion - Удаление возврата (версия 2+), если не поддерживается, то заменяется продажей, должен быть заполнен <Receipt>, <Deletion>, <LinkReceipt>
  • CashInOut - Подкрепление/инкассация (внесение/выплата) денег. Должны присутствовать теги <Payment> вне тега <Receipt>. Все суммы в рамках одного документа должны иметь одинаковый знак. Если драйвер не указал опцию foManyCashInOutPayments, то тег <Payment> может быть только один. С 40 версии добавлен тэг <Reason>, описывающий причину внесения/выплаты денег.
  • CollectAll  - Изъятие всех денег за смену, элемент <CashInOut>..</CashInOut> не создается
  • Report      - Отчёты, см. 3.5.5. При вызове UFRFiscalDocument в Status надо заполнить XMLBuffer ссылкой на буфер (рекомендуемый размер 512k) с первым байтом 0 и XMLBufferSize - размер буфера в байтах.
  • Custom (с версии 15) - никаких требований к внутренностям FiscalDocument
  • Bill (с версии 18) - счёт. Должен быть заполнен тег <Receipt>, тэг <Payments> не обязательный.
  • CreateOrder (с версии 18) - открытие заказа. В тэге <Receipt> должен быть заполнен <Order> и <Items>(может быть пустым), остальное не обязательно
  • Correction (с версии 18) - изменение количества товара в созданном заказе (до счёта). В тэге <Receipt> должен быть заполнен <Order> и <Items>, остальное не обязательно. В тэге Item Quantity и Value может быть отрицательным
  • CloseOrder (с версии 18) - закрытие пустого заказа. В тэге <Receipt> должен быть заполнен <Order>, остальное не обязательно
  • CancelSeat (с версии 18) - превращение заказа на место в общий заказ (на место 0)
  • PrintLog (с версии 25) - внутри FiscalDocument только Header с заполненным Unfiscal, остальные тэги Header не обязательные, в возвратном XMLBuffer может быть FiscalDocumentReturn с подтэгом - изменённым Unfiscal, если он вернулся изменённым, хост должен печатать изменённый текст, а не оригинальный.
  • CorrectionReceipt (с версии 35) - внутри FiscalDocument только Header и FFD, см. 3.5.7
  • CorrectionReceipt2 (с версии 66) - чек коррекции по ФФД 1.1 и ФФД 1.2. Заполнены теги: <Header>, <Receipt>, <FFD>:

    <FFD Code="31">
      <TLV Tag="1054" Value="1"/>
      <TLV Tag="1173" Value="1"/>
      <STLV Tag="1174">
        <TLV Tag="1178" Value="2022-05-12T00:00:00"/>
        <TLV Tag="1179" Value="Предписание №12345 "/>
      </STLV>
    </FFD>
    CODE
  • CancelBill (с версии 58) - счёт. Должен быть заполнен тег <Receipt>, тэг <Payments> не обязательный.
  • CheckMarking (с версии 62) - проверка обязательной маркировки. Должен быть заполнен тег MarkingData в единственном теге Item. Возвращает результат в CheckMarkingInfo в Status.XmlBuffer
  • GetDocumentData (с версии 69) - получение данных распечатанного чека

Примечания:

  1. Атрибуту "Code" в теге <Item /> для "ИТОГОВОЙ" группы будет присвоено нулевое значение.
  2. В теге <Item /> сначала должен быть тег <Discounts />, а затем тег <Taxes />.
  3. Для пустого тега <Items /> (пустой список элементов <Item>) фискальный чек не печатается.
  4. Для скидок/наценок на сумму чека для налогов атрибут "TaxValue" не указывается.
  5. Атрибут ForAdvance устарел начиная с версии 46. Начиная с 46 версии вместо ForAdvance = 0 следует передавать ItemKind=1 PaymentKind=4. Вместо ForAdvance=1 следует передавать ItemKind=10 PaymentKind=3.
  6. Значения атрибута ItemKind соответствуют значениям тега 1212 из 54-ФЗ, но могут быть расширены в будущем.
  7. Значения атрибута PaymentKind соответствуют значениям тега 1214 из 54-ФЗ, но могут быть расширены в будущем.
  8. Значение атрибута QuantityUnitType соответствуют значениям тега 2108 из 54-ФЗ.
  9. Значение атрибута PartsPerPackage соответствует значению тега 1294 из 54-ФЗ. Используется при продаже дробного количества маркированной продукции (например сигары поштучно). Для тега 1293 использовать Quantity/1000
  10. Значение атрибута EstimatedStatus соответствует значению тега 2003 из 54-ФЗ
  11. Указание NoOnline="1" отключает проверку маркировки при печати фискального чека в FiscalDocument

CustomProperties

{44727918-5294-40F8-9FF8-65270A8E2C9C} - e-mail покупателя, используется в России при поддержке 54-ФЗ

{A598C6FD-E347-414C-8E40-E5B846973ACF} - абонентский номер покупателя (номер телефона), используется в России при поддержке 54-ФЗ. Должен быть вида +7NNNNNNNNNN. Если заданы и телефон и e-mail, телефон игнорируется

{2A8EF470-821B-43B6-B16E-2517DDD1F768} - признак того, что не надо печатать чек на бумаге, при значении 1 печатать не надо

  <Header>
    <CustomProperties> <!-- Начиная с 26, необязательный --> 
      <CustomProp>
        <Name>{44727918-5294-40F8-9FF8-65270A8E2C9C}</Name> 
        <Data>test@ucs.ru</Data> 
      </CustomProp> 
      <CustomProp>
        <Name>{A598C6FD-E347-414C-8E40-E5B846973ACF}</Name> 
        <Data>+79991234455</Data> 
      </CustomProp> 
    </CustomProperties>
  </Header> 

Сырые атрибуты блюда ( Россия 54-ФЗ)

       <RawTLVAttributes><!-- Начиная с 49. Необязательный. Для России. TLV атрибуты позиции. Все подтеги необязательные. В подтегах атрибуты Id и Value обязательные.  -->
          <TLVBIN Id="1162" Value="0005000002C11E5E4144676F705371"/>
          <TLVU08 Id="1222" Value="4"/>
          <STLV Id="1223">
            <TLVSTR Id="1075" Value="+79012345678"/>
            <TLVSTR Id="1044" Value="Взаимозачёт"/>
            <TLVSTR Id="1073" Value="+79012345679"/>
            <TLVSTR Id="1074" Value="+79012345689"/>
            <TLVSTR Id="1026" Value="ООО Оператор перевода ИКС"/>
            <TLVSTR Id="1005" Value="г. Москва, ул. Гагарина, д.63 оф. 350"/>
            <TLVSTR Id="1016" Value="123456789047"/>
          </STLV>
          <STLV Id="1224">
            <TLVSTR Id="1171" Value="+79012345690"/>
            <TLVSTR Id="1225" Value="ООО Поставщик Игрек"/>
          </STLV>
        </RawTLVAttributes>

Типы:
TLVBIN - массив октетов, в HEX кодировке.
TLVU08 - целое, беззнаковое, один октет.
TLVSTR - строка символов необходимой длины в кодировке utf-8.
STLV - массив подтегов

Контроль размеров данных на стороне хоста, драйвер только записывает всё присланное в бинарную структуру TLV. Описание тэгов, например, http://www.consultant.ru/document/cons_doc_LAW_214339/

Типы отчётов

  • X - опция XReport
  • Z - опция ZReport. В 17+ в случае Z отчёта в поле Status.XMLBuffer надо вернуть XML с корневым тэгом FiscalDocumentReturn и подтэгом ZReportData в соответствии с пунктом 3.6.1.
  • BriefByDate - опция SpecialReport, краткий по датам, параметры - диапазон дат, см. 3.5.6
  • DetailByDate - опция SpecialReport, подробный по датам, параметры - диапазон дат, см. 3.5.6
  • BriefByNumber - опция SpecialReport, краткий по номерам смен, параметры - диапазон номеров смен, см. 3.5.6
  • ByArticul - опция SpecialReport, по артикулам
  • ZeroCheck - опция SpecialReport, "нулевой чек"
  • OFDStatus начиная с версии 31 - опция SpecialReport, отчёт, печатающий информацию о состоянии связи и/или состоянии очереди отправки на сайт, собирающий данные чеков для фискальных органов (в России это ОФД)
  • OpenShiftReport начиная с версии 48 - опция SpecialReport, отчёт, печатает отчёт об открытии смены. Поддержан если выставлена опция foOpenShiftReport. Если смена уже открыта, то драйвер должен вернуть ошибку errLogicShiftAlreadyOpened. Если смена превышена, то драйвер должен вернуть ошибку errLogic24hour. Если смена закрыта, то драйвер должен распечатать документ открытия смены.

Параметры отчёта

  • Несколько параметров разделяются символом ";".

Итоговый/Детализированный отчет по датам

Значение атрибута "Parameters" для BriefByDate, DetailByDate: YYYY-MM-DD;YYYY-MM-DD – даты начала и конца включительно

Итоговый отчет по сменам

Значение атрибута "Parameters" для BriefByNumber: %d;%d – номера начальной и конечной смен включительно.

CorrectionReceipt - чек коррекции (Россия)

Внутри FiscalDocument только Header и FFD. Опция "CorrectionReceipt".

Типы данных стандартные: целые числа (в десятичном формате) (деньги в копейках), строки как есть (в utf-8), даты в стандартном XML формате дата-время:
<?xml version="1.0" encoding="utf-8"?>
<FiscalDocument Options="" DocType="CorrectionReceipt">
  <Header>
    <Restaurant Id="1002199" Code="7" Name="Вкусный Ресторан"/>
    <Operator Id="1000060" Code="57" Name="Иванов Иван Иванович, кассир" TaxPayerIdNum="123456789012"/>
    <Station Id="15023" Code="9" Name="Касса №1"/>
    <Unfiscal/>
  </Header>
  <FFD Code="31">
    <TLV Tag="1173" Value="1"/> <!-- тип коррекции 0 - самостоятельная операция, 1 - операция по предписанию. Целое -->
    <TLV Tag="1054" Value="1"/> <!-- признак расчета. 1 - приход (коррекция прихода), 3 - расход (коррекция расхода). Целое -->
    <TLV Tag="1020" Value="321100"/> <!-- сумма коррекции - целая в копейках -->
    <TLV Tag="1055" Value="1"/> <!-- форма налогообложения, битовая маска, допустим только один установленный бит. Целое -->
    <TLV Tag="1031" Value="321100"/> <!-- сумма по чеку наличными - целое в копейках -->
    <TLV Tag="1081" Value="0"/> <!-- сумма по чеку электронные - целое в копейках -->
    <TLV Tag="1215" Value="0"/> <!-- сумма по чеку зачёт аванса - целое в копейках -->
    <TLV Tag="1216" Value="0"/> <!-- сумма по чеку в кредит - целое в копейках -->
    <TLV Tag="1217" Value="0"/> <!-- сумма по чеку встречным предоставлением - целое в копейках -->
    <TLV Tag="1102" Value="0"/> <!-- сумма НДС по ставке 18% - целое в копейках -->
    <TLV Tag="1103" Value="29190"/> <!-- сумма НДС по ставке 10% - целое в копейках -->
    <TLV Tag="1104" Value="0"/> <!-- сумма расчета по чеку с НДС по ставке 0% - целое в копейках -->
    <TLV Tag="1105" Value="0"/> <!-- сумма расчета по чеку без НДС - целое в копейках -->
    <TLV Tag="1106" Value="0"/> <!-- сумма НДС чека по расч. ставке 18/118 - целое в копейках -->
    <TLV Tag="1107" Value="0"/> <!-- сумма НДС чека по расч. ставке 10/110 - целое в копейках -->
    <TLV Tag="1021" Value="Иванов Иван Иванович, кассир"/> <!-- кассир. Должность и фамилия-->
    <TLV Tag="1203" Value="123456789012"/> <!-- ИНН кассира -->
    <STLV Tag="1174"> <!-- основание для коррекции -->
      <TLV Tag="1177" Value="01.02.2017 не сформирован и не выдан кассовый чек"/> <!-- описание коррекции, наименование документа основания для коррекции -->
      <TLV Tag="1178" Value="2017-02-28T00:00:00"/> <!-- дата документа основания для коррекции. В данном реквизите время всегда указывать, как 00:00:00. -->
      <TLV Tag="1179" Value="№1"/> <!-- номер документа основания для коррекции. Текст. -->
    </STLV> 
  </FFD> 
</FiscalDocument>

Список тэгов описан в официальных документах, например http://www.consultant.ru/document/cons_doc_LAW_214339/.

GetDocumentData — Получение данных распечатанного чека (в России в формате TVL)

Начиная с версии 69 драйвер может обрабатывать документ "GetDocumentData", выставив соответствующую опцию "foGetDocumentData". Header может быть пустым, должен присутствовать тэг GetData с атрибутами, позволяющими найти документ, в России это FiscDocNumber.

<?xml version="1.0" encoding="utf-8"?>
<FiscalDocument Options="" DocType="GetDocumentData">
  <Header/>

  <GetData FiscDocNumber="123321"/>
</FiscalDocument>

Возврат в Status.XMLBuffer в формате

Например

<?xml version="1.0" encoding="utf-8"?>
<FiscalDocumentReturn>
  <DocumentData Form="3" Format="TLVbase64" Value="asdfGERTYERYGEASDFsdg"/>
</FiscalDocumentReturn>

Form = "3" код формы по ФФД
Format = "TLVbase64"

Получить данные Z-Отчета: UFRGetZReportData (устаревшая для 17+)

function UFRGetZReportData(Number: Integer;
                           XMLData: PAnsiChar;
                           var XMLDataSize: Integer): Integer; stdcall;
  • Необязательная функция. Может не определяться. Начиная с версии 17 не рекомендуется использовать, вместо неё надо возвращать XML с тэгом FiscalDocumentReturn и подтэгом ZReportData, как описано в 3.6.1 в UFRStatus.XMLBuffer в UFRFiscalDocument на DocType="Report" и Report.ReportType="Z"
  • Вызывать непосредственно перед закрытием смены (печатью Z-отчета).


Вх. параметр:
  XMLData - буфер для получения от драйвера ФР ASCIIZ-строки c данными Z-отчета
            в XML-формате;
 
Вх./вых. параметр:
  XMLDataSize - в функцию передается размер буфера XMLData в байтах, возвращается
                фактическое количество байт ASCIIZ-строки, скопированных в
                буфер XMLData.

  • В случае успеха возвращает 0, иначе - код ошибки.
  • Память для буфера XMLData выделяет и освобождает вызывающая сторона.
  • При успешном копировании данных в буфер функция возвращает 0, в XMLDataSize записывается количество байт ASCIIZ-строки, скопированной в буфер XMLData.
  • Возвращаемое значение XMLDataSize должно быть меньше или равно переданному в функцию значению XMLDataSize.
  • При недостаточном XMLDataSize (размере буфера) или XMLData = nil функция возвращает код ошибки errAssertInsufficientBufferSize, данные Z-отчета в буфер XMLData не копируются, в XMLDataSize функция возвращает рекомендуемый размер буфера для ASCIIZ-строки. Возвращаемое значение XMLDataSize должно быть больше переданного в функцию значения XMLDataSize.

Формат XMLData, тэг ZReportData (в 17+ он же подтэг FiscalDocumentReturn)

<ZReportData POS_ID="1234567890"    <!-- Идентификатор ФР -->
             ZReportNumber="1"      <!-- Порядковый номер Z-отчета -->
             CashInValue="2000"     <!-- Сумма вложений (разменные деньги), в копейках -->
             PayCashValue="8000"    <!-- Сумма оплат наличными за смену, в копейках -->
             PayNonCashValue="2000" <!-- Сумма безналичных оплат (включая банковские карты) за смену, в копейках -->
             DayValue="10000"       <!-- Выручка: Дневной итог продаж (возможно, минус возврат, см. комментарий) за смену, в копейках -->
             ReturnValue="100"      <!-- Сумма возвратов по продажам за смену, в копейках -->
             TaxValue="50"          <!-- Дневной итог налогов за смену, в копейках -->
             Total="500000">        <!-- Общий итог продаж за все смены не считая текущей незакрытой, в копейках -->

  <DepartmentValues> <!-- только для версий 1..12 -->
    <DepartmentValue Number="1"
                     Name="Отдел 1"
                     Value="10000" /> <!-- Сумма выручки отдела, в копейках -->

    <DepartmentValue Number="2"
                     Name="Отдел 2"
                     Value="3000" />
  </DepartmentValues>
  <CounterValues> <!-- для версий 13+ -->
    <CounterValue SourceID="PayCashValue" ValueKeyID="{E53B030C-845D-4CBC-8A03-EBFFAE5D08B8}" Value="54.32"/>
    <CounterValue SourceID="Global_6" ValueKeyID="{C22FF005-6D98-4C7D-BD59-86D4B0B4560C}" Value="54.32"/>
    <CounterValue SourceID="operator_name" ValueKeyID="{09BBBC8A-85B7-44D3-A0AF-8FC1B9BA4E15}" Value="Пупкин В."/>
    <CounterValue SourceID="money_12" Value="1234.56"/>
  </CounterValues>

</ZReportData>

Примечания

  1. Из-за того, что вызов "UFRGetZReportData" выполняется до печати Z-отчета, в XML-данных значение атрибута "Total" (Общий итог продаж за все смены) не включает значение атрибута "DayValue" (Дневной итог продаж за текущую, но еще незакрытую смену). Для получения значения счётчика для следующего дня к Total будет прибавлено DayValue. Больше ни для чего DayValue не   используется. Соответственно, значение DayValue должно определяться так, чтобы правильно спрогнозировать следующее значение необнуляемого счётчика Total. Начиная с протокола 17+ можно возвращать XML в FiscalDocumentReturn, поэтому можно запрашивать счётчики и до и после выполнения Z отчёта.
  2. При отсутствии информации по какому-либо параметру Z-отчета соответствующий атрибут в теге <ZReportData> не создается.
  3. DepartmentValues в версиях 1..12. В версиях 13+ допускается добавление пустого тэга <DepartmentValues /> для совместимости.
  4. CounterValues начиная с 13.  

Важно

SourceID - уникальное имя счётчика для конкретного аппарата. ValueKeyID - GUID, уникальный глобальный идентификатор счётчика, не обязателен для уникальных или серийных счётчиков, предустановленные GUID см. в 3.6.3. Если Value содержит число, то разделитель - точка, если деньги, то в "рублях". Драйвер должен иметь настройку списка счётчиков, значения которых надо выгружать в XML, а не выгружать всё подряд.

Предустановленные счётчики

Начиная с 13+. Для задания предустановленных счётчиков необходимо заполнять у счётчиков поле ValueKeyID. Имя счётчика, если он соответствует реальному счётчику ФР лучше оставить совместимым с остальными именами. Для имён синтетических счётчиков можно использовать префикс "Global_".

  • Global_1 {25E19D75-EFA5-4B57-BD29-DDB14A2E1F64} - Сумма продаж (без возвратов и удалений) за смену
  • Global_2 {CD369812-9E51-46BD-A99D-18843718BCD4} - Сумма возвратов и удалений (удаления возвратов с минусом) за смену, совпадает с ZReportData.ReturnValue/100
  • Global_3 {B704B8E1-CB6B-4E19-B414-B9939CF97C71} - Сумма всех налогов по продажам (без возвратов и удалений) за смену, совпадает с ZReportData.TaxValue/100
  • Global_4 {C788DDEA-6E64-4233-B215-13A48A0B76AF} - Сумма продаж (без возвратов и удалений) без всех налогов за смену
  • Global_5 {E53B030C-845D-4CBC-8A03-EBFFAE5D08B8} - Сумма наличных за смену (с учётом возвратов и удалений), совпадает с ZReportData.PayCashValue/100
  • Global_6 {C22FF005-6D98-4C7D-BD59-86D4B0B4560C} - Сумма по банковским картам за смену (с учётом возвратов и удалений)
  • Global_7 {39EAF8BD-9BD4-4A02-B09B-735C125A08C3} - Сумма по безналичным(всё минус нал минус банк) за смену (с учётом возвратов и удалений)
  • Global_8 {99F188AE-EEB6-4EB2-A1E2-24777161337A} - количество чеков продажи за смену
  • Global_9 {EAEEF2F4-5EF3-4595-910C-7A0D7D2A1DD3} - количество удалений чеков продажи за смену
  • Global_10 {B7AE6698-D455-4ACF-AE4A-378EA253FDEB} - количество чеков возвратов за смену
  • Global_11 {6CD60D76-A3A3-4B35-9AFD-1BA8AE208C76} - количество удалений чеков возвратов за смену
  • Global_12 {4559FBEA-7C7D-42A9-9039-E049DF8B16F7} - Общая сумма внесений (подкреплений) наличности, оформленных за смену через устройство, совпадает с ZReportData.CashInValue/100
  • Global_13 {2F0BD957-6F3D-495F-87D9-F4B392CA421A} - Дата окончания работы устройства в формате YYYY-MM-DD (в России срок окончания ФН) Начиная с версии 63

Открыть денежный ящик: UFROpenDrawer

Открытие ящика – отдельная опция, возможно, доступная при отсутствии возможности нефискальной печати.

function UFROpenDrawer(Number: Integer; DrawerNum: Integer): Integer; stdcall;
  • Необязательная функция. Может не определяться.
  • Number    - номер ФР, который передали при регистрации;
  • DrawerNum - номер ящика.
  • В случае успеха возвращает 0, иначе - код ошибки.

Вывод на дисплей покупателя: UFRCustomerDisplay

function UFRCustomerDisplay(Number: Integer;
                            XMLBuffer: PAnsiChar;
                            Flags: integer): Integer; stdcall;
  • Необязательная функция. Может не определяться.
  • В случае успеха возвращает 0, иначе - код ошибки.


Пример XMLBuffer:
 

<Unfiscal Slip="0"|"1">
  <TextBlock FontNum="1"
             Bold="0"|"1"
             BigHeight="0"
             BigWidth="0"
             Inverted="0"
             AltLang="0"|"1">
     Строка 1
     Строка 2
  </TextBlock>

  <TextLine FontNum="1"
            Bold="0"|"1"
            BigHeight="0"
            BigWidth="0"
            Inverted="0"
            AltLang="0"|"1"
            Text="Text"/> <!-- строка целиком -->

  <TextPart FontNum="1"
            Bold="0"|"1"
            BigHeight="0"
            BigWidth="0"
            Inverted="0"
            AltLang="0"|"1"
            Text="Text"/> <!-- часть строки -->

  <RawBlock Encoding="Base64">
     001122AA
  </RawBlock>
</Unfiscal>

Программирование ФР: UFRProgram

Программирование ФР должно вызываться только при закрытой смене. Желательно перед печатью чека проверить состояние смены и, если смена закрыта,
вызвать UFRProgram. Некоторые ФР поддерживают некоторое программирование и при открытой смене.

function UFRProgram(Number: Integer; XMLDoc: PAnsiChar): Integer; stdcall;
  • Необязательная функция. Может не определяться.
  • В случае успеха возвращает 0, иначе - код ошибки. Описания обработки ошибок в пункте 8.

Пример XMLDoc:

<ProgramFR>

  <ProgramDateTime Source="System" /> <!-- брать из системных настроек -->

  <ProgramTaxes>
    <Tax TaxRateIndex="1"
         RateValue="1800"
         TaxName="НДС"
         RateName="НДС 18%" />

    <Tax TaxRateIndex="2"
         RateValue="2000"
         TaxName="НДС"
         RateName="НДС 20%" />
  </ProgramTaxes>

  <ProgramDepartments DefaultDepartmentName = "Имя отдела по умолчанию">
    <Department Number="1" Name="Отдел 1"/>
    <Department Number="2" Name="Отдел 2"/>
  </ProgramDepartments>

</ProgramFR>
При программировании принтера не обрабатывать секцию, не подерживаемую конкретным ФР.

Специальное меню драйвера (регистрация через UFRInitXML, 13+): UFRMenuOperation


Начиная с версии 13 в XML возврата из UFRInitXML может быть определено меню драйвера в тэге MENU. В этом случае должна быть определена функция UFRMenuOperation, если меню не надо регистрировать, можно не определять эту функцию.
 

function UFRMenuOperation(Number: Integer;
                           XMLData: PAnsiChar; var XMLReturn: PAnsiChar): Integer; stdcall;
  • XMLData имеет вид (обязательный атрибут operationId, всё остальное не обязательное):
<MENUOPERATION
  operationId="5B3F851D-1C75-41C1-B3B3-B0927E49D3ED"
  parameter="12345">
  <DIALOGINFO from="2014-12-31" to="2015-12-31"/> <!-- не обязательный, если был вызов диалога, from заполняется всегда, а to заполняется для типов диалога "DateInterval","NumberInterval" -->
</MENUOPERATION>


XMLReturn -- указатель на буфер, память выделяется драйвером. Сам драйвер эту память и освобождает. В функцию можно передавать XMLReturn как nil.  Содержимое валидное до следующего вызова любой функции. Текст, для примера, имеет вид (всё не обязательное):
 

<MENUOPERATIONRESULT
  operationId="5B3F851D-1C75-41C1-B3B3-B0927E49D3ED">
  <PRINTUNFISCAL xml:lang="ru"> 
    <Unfiscal> 
    </Unfiscal>
    <Unfiscal> 
    </Unfiscal>
  </PRINTUNFISCAL>
</MENUOPERATIONRESULT>

Начиная с версии 51 содержит необязательный атрибут xml:lang, указывающий язык в стандарте ISO 639-1

  • В случае успеха возвращает 0, иначе - код ошибки.

Апгрейд параметров драйвера, 45: UpgradeXMLParams

Начиная с версии 45 драйвер может предоставить необязательную процедуру для обновления параметров.
 
function UpgradeXMLParams(OldXMLParams: PAnsiChar; NewXMLParams: PAnsiChar; var BufferSize: Integer): Integer; stdcall;

  • При успешной конвертации функция обязана вернуть результат 0 и заполнить NewXMLParams.
  • В BufferSize хост записывает размер буфера для результата, а функция записывает реальный использованный размер (включая завершающий ноль) или требуемый размер при нехватке исходного BufferSize для результата
  • При нехватке памяти для сохранения результата, функция возвращает errAssertInsufficientBufferSize и заполняет требуемый BufferSize


NewXMLParams -- указатель на буфер, память выделяется хостом. При любом результате функции кроме нуля хост должен игнорировать NewXMLParams. После успешной конвертации XML должен соответствовать схеме из ресурса DEVICECONFIGV01XSD. Драйвер должен учитывать, что хост не обязан вызывать эту функцию до инициализации, и что могут приходить параметры в старом формате (драйвер сам может вызывать эту функцию для конверсии). Драйвер не должен заполнять атрибут ProtocolVersion корневого тэга результата. Хост при необходимости (вызов перед инициализацией для работы, а не для конфигурирования) должен заполнить этот атрибут у отконвертированного XML перед передачей в InitXML.

Интерфейс

Через InterfaceCallback. Описание InterfaceCallback см. выше.
В этом разделе описываются функции графического интерфейса драйвера с пользователем.

const
  cpfDialog          = 1; //Вызов диалога, структура tDialogInfo, см. Вызов диалога на станции.
  cpfProgress        = 2; //Индикация прогресса, структура tProgressInfo.
  cpfGetStringDialog = 3; //Диалог запроса строки, структура tGetStringInfo.
  cpfRegisterSpecMenu = 4; //Зарегистрировать специальное меню, структура tDriverMenuInfo
                          //см. Дополнительные функции (спец. меню, общее с другими драйверам).
  cpfLog=5; //Логирование
  cpfTranslate=6; //Перевод, структура tTranslateInfo
  cpfPrintTextOther = 7; //Печать текста на другой принтер, структура tPrintTextOtherInfo (версия 2+)
  cpfDeviceSignal     = 8; //Послать сигнал с идентификатором как от внешнего устройства, структура tDeviceSignalInfo (версия 38+)
  cpfPerformMessage   = 9; //Выполнить сообщение с возвратом результата, структура tPerformMessageInfo (версия 38+)
  cpfExecXML          = 10;//Выполнение XML команды, структура tExecXMLInfo (версия 38+)

Вызов диалога на станции

Для отображения диалога на кассе надо вызвать InterfaceCallback - процедуру с функцией cpfDialog и параметром – ссылкой на структуру типа TDialogInfo.

TMsgDlgType = (mtWarning,
               mtError,
               mtInformation,
               mtConfirmation,
               mtCustom,
               mtZRepConfirm);
  • mtZRepConfirm - специальный запрос на подтверждение Z-отчёта, по возможности избегать этого диалога, возвращая ошибку errLogic24hour.
TMsgDlgBtn = (mbYes,
              mbNo,
              mbOK,
              mbCancel,
              mbAbort,
              mbRetry,
              mbIgnore,
              mbAll,
              mbNoToAll,
              mbYesToAll,
              mbHelp);

TMsgDlgButtons = set of TMsgDlgBtn;

const
  mrNone     = 0;
  mrOk       = 1;
  mrCancel   = 2;
  mrAbort    = 3;
  mrRetry    = 4;
  mrIgnore   = 5;
  mrYes      = 6;
  mrNo       = 7;
  mrAll      = mrNo + 1;
  mrNoToAll  = mrAll + 1;
  mrYesToAll = mrNoToAll + 1;

  mrTimeout = 254;
  mrInternalError = 255;

  mbYesNoCancel      = [mbYes, mbNo, mbCancel];
  mbOKCancel         = [mbOK, mbCancel];
  mbAbortRetryIgnore = [mbAbort, mbRetry, mbIgnore];
  • Типы TMsgDlgType, TMsgDlgBtn, TMsgDlgButtons и константы mrXXX, mbXXX определены в модуле ParConst.pas.
type
  PDialogInfo = ^TDialogInfo;
  TDialogInfo = packed record

    Size:     Integer;     //Заполнить SizeOf(TDialogInfo)
    Message:  ShortString;//ANSI, Заполнить сообщение
    Header:   ShortString; //Поле НЕ ПОДДЕРЖИВАЕТСЯ RKeeper 7
    DlgType:  TMsgDlgType;//Заполнить тип диалога
    ShowHere: Boolean;     //Заполнить true – показать на компьютере драйвера, иначе – на заблокировавшем.
    Buttons:  TMsgDlgButtons;//Заполнить набор кнопок
    Result:   Integer; //Возврат - результат mrXXXX
    Timeout: DWORD; //начиная с версии 4, Заполнить таймаут в миллисекундах, INFINITE - без ограничений
end;

Вызов диалога запроса строки

Если требуется запрос строки, то можно вызвать InterfaceCallback процедуру с номером функции cpfGetStringDialog и параметром–ссылкой на структуру типа
TGetStringInfo.

type
  PGetStringInfo = ^TGetStringInfo;
  TGetStringInfo = packed record

    Size:      Integer;     //Заполнить SizeOf(TGetStringInfo)
    Message:   ShortString; //ANSI, сообщение
    Header:    ShortString; //ANSI, заголовок. Если пусто, выведется заголовок с указанием имени драйвера и номера.
    Default:   ShortString; //ANSI, Строка по умолчанию
    Mask:      ShortString; //ANSI, Маска ввода
    ShowHere:  Boolean;     //Заполнить true - показать на компьютере драйвера, иначе - на заблокировавшем
    Result:    Boolean;     //Возврат Результат выполнения. false возможен при разрыве связи, закрытии формы и т.п.
    ResString: ShortString; //ANSI, Возврат - строка-результат
    Timeout: DWORD; //начиная с версии 4, Заполнить таймаут в миллисекундах, 0 и INFINITE обрабатываются одинаково - без ограничений
end;
  • При отмене запроса (Result = false) в поле "ResString" будет сохранено сообщение об ошибке.

Иллюстрация прогресса


Для иллюстрации прогресса на кассе надо вызвать InterfaceCallback процедуру с номером функции cpfProgress и параметром–ссылкой на структуру типа TProgressInfo.

type
  PProgressInfo = ^TProgressInfo;
  TProgressInfo = packed record
    Size:        Integer;     //Заполнить SizeOf(TProgressInfo)
    Message:     ShortString;//ANSI, сообщение
    Position:    Integer;     //Заполнить 0..MaxPosition
    MaxPosition: Integer; //Заполнить 
end;

Перевод

type
  pTranslateInfo = ^tTranslateInfo;
  tTranslateInfo = packed record
    Size:         Integer;    //Заполнить SizeOf(tTranslateInfo)
    TranslateFrom: ShortString;//ANSI,Заполнить 
    LocaleID:      Integer;   //Заполнить 
    TranslateTo  : ShortString;//ANSI, Возврат
  end;

Специальное меню драйвера (регистрация через InterfaceCallback)

Для регистрации функции, вызываемой из специального меню драйверов надо вызвать InterfaceCallback процедуру с номером функции cpfRegisterSpecMenu и параметром-ссылкой на структуру типа tDriverMenuInfo.

TDriverMenuItemProcedure = procedure(MenuInfo: pDriverMenuInfo;
                                     DialogValue: PAnsiChar;
                                     FileToPrintName: PAnsiChar); stdcall;
	DialogValue     - если вызывался диалог, то здесь в строке то, что ввёл пользователь.
	FileToPrintName - указатель на буфер размером MAX_PATH, куда надо записать имя файла, который надо напечатать, если требуется.
const //Типы диалогов

  dtNoDialog       = 0;
  dtDateInterval   = 1;
  dtNumberInterval = 2;
  dtOneDate        = 3;
  dtOneNumber      = 4;
dtOneString      = 5;
PFRDriverMenuInfo = ^TFRDriverMenuInfo; TDriverMenuInfo = packed record Size: Integer; //SizeOf(tDriverMenuInfo). Заполнить до регистрации. MenuHandle: Integer; //Идентификатор меню. Заполняется при регистрации. ParentMenuHandle: Integer; //Может быть = 0. ItemProc: TDriverMenuItemProcedure; ItemProcParameter: Pointer; //Передаётся в ItemProc. PurposeToLock: Integer; //Для ФР не используется. Назначение печати. //Если не 0, то принтер должен существовать и будет заблокирован до вызова, после вызова на него //напечатается файл FileToPrintName, затем принтер разблокируется. //Предустановленные назначения: // 1 - для чеков; // 2 - для пречеков; // 3 - для отчётов; // 4 - для XML отчётов MenuCaption: String[83]; //ANSI,Обязательное поле. Если пусто и заполнен MenuHandle, то отменить регистрацию. DialogType: Integer; //см. константы dtXXXX. DialogParams: ShortString; //ANSI,Заголовок окна диалога. В будущем могут быть спецпараметры новых типов диалогов. ModuleHandle: tHandle; //Лучше передавать. В будущем может быть контроль. UserRightID: Integer; //Идентификатор пользовательского права на операцию. При отсутствии права кнопка прячется. 0 - игнорировать. end;
  • Типы TDriverMenuInfo, TDriverMenuItemProcedure определены в модуле DrivMenu.pas.

Печать текста на другое устройство (версия 2+)


Для печати драйвер вызывает InterfaceCallBack процедуру с функцией cpfPrintTextOther. В качестве параметра передаётся указатель на структуру:

type
  pPrintTextOtherInfo = ^tPrintTextOtherInfo;

  tPrintTextOtherInfo = packed record
    Size:         Integer;    //Заполнить SizeOf(tPrintTextOtherInfo)
    DeviceIdent: ShortString;// Заполнить или код или GUID или ещё какой идентификатор
    PrintBuffer: PAnsiChar;//Заполнить строка, заканчивающаяся 0 - XML в UTF-8 с корневым тэгом Unfiscal, см. выше
    Res: Boolean; //Возврат успешность, true - без ошибки, иначе заполнено ErrorText
    ErrorText:ShortString;//Возврат текст ошибки, не пусто, если была ошибка
    ToWait: Boolean; //Заполнить Ждать окончания печати
    Timeout: DWord;//Заполнить Таймаут печати в миллисекундах, если ждать, иначе таймаут блокировки (ожидания готовности)
  end;

Логирование

Для ведения лога драйвер вызывает InterfaceCallBack процедуру с функцией cpfLog. В качестве параметра передаётся указатель на структуру:

type
  PFRLog = ^TFRLog;
  TFRLog = packed record

    Size: Integer; //Заполнить SizeOf(TFRLog)
    LogEventType: Integer; //Заполнить одна из констант letXXXX
    TextData:     PAnsiChar;   //Заполнить строка в кодировке UTF8, заканчивающаяся 0
    BinData:      Pointer;
    BinDataSize:  Integer;
end;

const //Для лога

  letUndefined       = 0;
  letError               = 1; //Ошибка. В поле TextData - строка в кодировке UTF8
  letInitializing        = 2; //В начале инициализации. В поле TextData - строка в кодировке UTF8
  letInitialized         = 3; //При успешной инициализации. В поле TextData - строка кодировке UTF8
  letFiscCommand         = 4; //Текстовое и бинарное представление фискальной команды.
                              //В поле TextData: номер | описание | параметр.
                              //В поле BinData: пакет данных для отправки в ФР).
  letFiscCommandComplete = 5; //Текстовое и бинарное представление ответа фискальника.
                              //В поле TextData: код ошибки | время выполнения фискальной команды | расшифровка содержательного
                              //ответа ФР (например, на запрос статуса). В поле BinData: пакет данных, полученный от ФР.
  letTextCommand         = 6; //Текстовое и бинарное представление команды вывода текста (нефискальная печать, вывод на дисплей покупателя).
                              //В поле BinData: пакет данных для отправки в ФР.
  letTextCommandComplete = 7; //Текстовое и бинарное представление ответа от ФР.
                              //В поле TextData: код ошибки | время выполнения фискальной команды | расшифровка содержательного
                              //ответа ФР (например, статус печатающего стройства). В поле BinData: пакет данных, полученный от ФР.
  letBinInput            = 8; //Бинарный системный вход, не описанный в letFiscCommandComplete, letTextCommandComplete.
                              //Например, подтверждение от ФР о получении пакета `` данных.
  letBinOut              = 9; //Бинарный системный вывод, не описанный в letFiscCommand, letTextCommand.
                              //Например, подтверждение о получении пакета данных или подготовка ФР к отправке команды.

4.8. Сигнал от внешнего устройства (версия 38+)

Для отправки сигнала от внешнего устройства драйвер вызывает InterfaceCallBack процедуру с функцией cpfDeviceSignal. В качестве параметра передаётся указатель на структуру:

type
  pDeviceSignalInfo = ^tDeviceSignalInfo;

  tDeviceSignalInfo = packed record
    Size:         Integer;    //Заполнить SizeOf(tDeviceSignalInfo)
    DeviceType:  Integer;   //тип устройства dstXXXX: 0 - магнитная карта, 1 - штрих-код, 2 - Dallas, 3 - ввод с клавиатуры, 4 - бесконтактная карта
    DeviceID:    Integer;   //Идентификатор устройства
    Data:        ShortString;//Данные сигнала
  end;

const
  dstMagCard = 0;
  dstBarCode = 1;
  dstDallas  = 2;
  dstInpKBD  = 3;
  dstNoTouch = 4;

Синхронная обработка сообщения оконной системой кассы (версия 38+)

Для отправки сигнала в очередь сообщений кассы драйвер вызывает InterfaceCallBack процедуру с функцией cpfPerformMessage. В качестве параметра передаётся указатель на структуру:

type
  pPerformMessageInfo = ^tPerformMessageInfo;

  tPerformMessageInfo = packed record
    Size:        Integer;   //SizeOf(tPerformMessageInfo)
    Msg:         Integer;   //идентификатор сообщения (WM_... или аналог)
    WParam:      Integer;
    LParam:      Integer;
    Res:         Integer;   //результат синхронной обработки сообщения
  end;

Выполнение XML команды (версия 38+)

Для выполнения XML команды драйвер вызывает InterfaceCallBack процедуру с функцией cpfExecXML. В качестве параметра передаётся указатель на структуру:

type
  pExecXMLInfo = ^tExecXMLInfo;

  tExecXMLInfo = packed record
    Size:        Integer;   //SizeOf(tExecXMLInfo)
    InXML:       PChar;     //XML команда для выполнения, если касса не умеет выполнить, должна перекинуть на сервер
    OutXMLBuf:   PChar;     //Буфер для ответа, выделяется в драйвере перед вызовом callback, размер выделенного буфера указан в OutXMLBufSize
    OutXMLBufSize: Integer; //размер выделенного буфера для ответа
    Res:         Integer;   //результат выполнения
  end;

Обработка ошибок

Коды ошибок

const
  errOk = 0; //Без ошибок

 //Универсальные ошибки (инициализация, обработка запроса): 1..99

errPortAlreadyUsed       = 1; //Порт уже используется.
errIllegalOS             = 2; //Не та OS.
errProtocolNotSupported  = 3; //Запрашиваемый протокол не поддерживается.
errFunctionNotSupported  = 4; //Функция драйвера не поддерживается данным ФР.
errInvalidHandle         = 5; //Недопустимый дескриптор (handle).
errPortOpenError         = 6; //Ошибка открытия порта.
errPortBadBaud           = 7; //Недопустимая скорость для порта.
errInternalException     = 8; //неожиданное прерывание (внутренняя ошибка)

errExtPrintError = 9; //Ошибка печати через внешнюю систему печати (через callback), доп. информация через UFRGetLastLogicError

//Универсальные ошибки низкого уровня: 100..199

errLowNotReady       = 101; //Устройство не готово принять команду. Таймаут ожидания.
errLowSendError      = 102; //Устройство отвечает ошибкой приёма команды.
errLowAnswerTimeout  = 103; //Устройство не отвечает на команду.
errLowInactiveOnExec = 104; //Устройство не отвечает на проверку работоспособности после отправки команды.
errLowBadAnswer      = 105; //Устройство отвечает мусором (невозможно повторить или повтор не помог).
errLowInternalError    = 106; //внутренний exception и т.п.  

 //Логические ошибки, вызванные работой ФР: 200..299.

Примечание: по ошибкам данного назначения есть возможность получения более подробной информации через дополнительный вызов "UFRGetLastLogicError".
errLogicError           = 200; //Логическая ошибка прочего типа.
errLogic24hour          = 201; //Смена превысила максимальную продолжительность.
errLogicPrinterNotReady = 202; //Печать была прервана по неготовности принтера. При запросе статуса не надо возвращать эту ошибку.
errLogicPaperOut        = 203; //Закончилась бумага во время печати. При запросе статуса не надо возвращать эту ошибку.
errLogicBadAnswerFormat = 204; //В ответе вроде бы не мусор и нет ошибки, но что то принципиально не то, детализацию запрашивать бесполезно - аппарат ошибки не вернул
errLogicShiftAlreadyOpened = 205; // В ответ на OpenShiftReport если смена уже открыта

  //Ошибки во входных данных, обнаруженные до отправки данных в ФР: 300..399

  errAssertItemsPaysDifferent             = 301; //В чеке не совпадают суммы по товарам и платежам.
  errAssertInvalidXMLInitializationParams = 302; //Ошибка конфигурации XMLParams при инициализации UFRInit. Для получения более подробной
                                                 //информации вызвать "UFRGetLastLogicError", поле LogicErrorText
  errAssertInvalidXMLParams               = 303; //Ошибка XML, переданного в UFRUnfiscalPrint, UFRCustomerDisplay.
                                                 //Для получения более подробной информации вызвать "UFRGetLastLogicError", поле LogicErrorText
  errAssertInsufficientBufferSize         = 304; //Недостаточный размер буфера для получения данных.
  • При недостаточном XMLDataSize (размере буфера) или XMLData = nil функция.

Описание последней логической ошибки

  • UFRxxx-функция в случае успеха возвращает 0, иначе - код ошибки.
  • Когда UFRxxx-функция возвратит один из следующих кодов (см. раздел 9.1.):
  * errExtPrintError
  * errLogicError
  * errLogic24hour
  * errLogicPrinterNotReady
  * errLogicPaperOut
  * errAssertInvalidXMLInitializationParams
  * errAssertInvalidXMLParams
  * errInternalException

- то, до вызова следующей UFRxxx-функции с помощью процедуры UFRGetLastLogicError можно, как дополнительную информацию, получить внутренний код и описание для самой последней[!] логической ошибки ФР.

  • Вызов последующей UFRxxx-функции должен обнулить информацию о логической ошибке от предыдущего вызова UFRxxx-функции.
  • Отдельно для каждого из вышеперечисленных кодов ошибок ничего запоминать не требуется.
procedure UFRGetLastLogicError(Number: Integer;
                               var LogicError: TUFRLogicError); stdcall;
  • Обязательная функция. Всегда определяется.                             
  • Если дополнительная информация отсутствует, то функция в полях структуры LogicError возвращает пустые значение (нуль и пустую строку соответственно).
  • Перед вызовом в структуре заполнить поле Size, все остальные поля структуры должны быть обнулены.
type
  PUFRLogicError = ^TUFRLogicError;
  TUFRLogicError = packed record
    Size:                Integer;     //Заполнить SizeOf(TUFRLogicError)
    LogicError:          Integer;     //Возврат Внутренний код логической ошибки ФР, определён только для ошибок errLogicXXXXX 200..299, для errAssert не использовать.
    LogicErrorTextANSI:      ShortString; // До версии 6 использовалось в кодировке 1251, устарело.
    LogicErrorTextUTF8:      ShortString; // начиная с версии 6. Возврат - описание логической ошибки ФР (если есть) или ошибки парсинга данных
end;

Примеры

https://github.com/rkeeper/rkeeper_desktop_hardware_drivers - open source тестовый драйвер