ProCheck — це COM/OLE-сервер (DLL in-process) для роботи з програмним реєстратором розрахункових операцій (ПРРО) відповідно до законодавства України.
Основний COM-об'єкт бібліотеки:
ProCheck.ProgramRRO (IProgramRRO) — для роботи з програмним ПРРО.
Ця документація описує виключно IProgramRRO — інтерфейс для роботи з ПРРО.
Всі методи повертають Integer: 0 — успіх, ненульове — помилка.
Детальне повідомлення про помилку завжди доступне у властивості LastErrorMessage.
Числовий код помилки ПРРО — у властивості LastErrorCode.
Властивості Barcode, ExciseStamp, CustomsCode, CheckComment, FooterCheckComment встановлюються перед відповідною операцією і автоматично скидаються після неї.
regsvr32 ProCheck.dll
regsvr32 /u ProCheck.dll
Windows 7 / Windows 10 / Windows 11, x32 або x64.
При використанні у 64-бітному процесі — використовуйте 64-бітну версію DLL.
При використанні у 32-бітному процесі — 32-бітну версію DLL.
uses ComObj;
var
RRO: OleVariant;
begin
RRO := CreateOleObject('ProCheck.ProgramRRO');
if RRO.Connect(4000154869, 'COM3', 115200) = 0 then
ShowMessage('Підключено успішно');
end;
Або через інтерфейс (рання прив'язка):
uses ComObj, ProCheck_TLB;
var
RRO: IProgramRRO;
begin
RRO := CreateComObject(CLASS_ProgramRRO) as IProgramRRO;
end;
import win32com.client
rro = win32com.client.Dispatch("ProCheck.ProgramRRO")
if rro.Connect(4000154869, "COM3", 115200) == 0:
print("Підключено")
else:
print(f"Помилка підключення: {rro.LastErrorMessage}")
// Рання прив'язка: додати COM-посилання на ProCheck.tlb
// Або пізня прив'язка:
Type rroType = Type.GetTypeFromProgID("ProCheck.ProgramRRO");
dynamic rro = Activator.CreateInstance(rroType);
int result = rro.Connect(4000154869L, "COM3", 115200);
if (result == 0)
Console.WriteLine("Підключено");
1. Connect / ConnectLan ← підключитись до ПРРО (Connect — COM-порт, ConnectLan — мережевий ESC/POS-принтер)
2. OpenReceipt(0, '') ← відкрити чек продажу
3. [Barcode := '...'] ← необов'язково: штрихкод товару
4. Sale(...) ← додати позицію (можна кілька разів)
5. [AddReceiptText(...)] ← необов'язково: додатковий текст
6. Pay(0, 0) ← оплата готівкою на повну суму
7. CloseReceipt ← закрити та надіслати чек у ПРРО
8. DataFields[4],[15] ← прочитати фіскальний номер, PDF тощо
Після успішного CloseReceipt повний набір результатів доступний через
DataFields[Index]. Найчастіше використовувані поля:
NewCheckNum := RRO.DataFields[4]; // фіскальний номер чека
CheckUrl := RRO.DataFields[10]; // посилання на чек
PdfBase64 := RRO.DataFields[15]; // PDF чека для друку/відправки клієнту
CheckHash := RRO.DataFields[16]; // SHA-256
IsOffline := RRO.DataFields[13] = 'OFFLINE';
Повний перелік полів для кожної операції — у описі відповідного методу
(розділи 6 і 7).
1. IsRetCheckExist('XXXX') ← перевірити, чи існує чек для повернення
2. OpenReceipt(1, 'XXXX') ← відкрити чек повернення з номером фіскального чека
3. Sale(...) ← додати позиції для повернення
4. Pay(0, 0) ← оплата повернення
5. CloseReceipt ← закрити чек
1. ZReport ← закрити зміну, надіслати Z-звіт до ПРРО
Підключення до ПРРО через COM-порт.
Параметри:
ID — фіскальний номер ПРРО (Int64).
Port — назва COM-порту, наприклад 'COM3', 'COM10' (String).
Speed — швидкість порту (Integer), зазвичай 115200.
Повертає: 0 — успіх, інше — помилка.
Підключення до мережевого ESC/POS-принтера по TCP.
Параметри:
ID — фіскальний номер ПРРО (Int64).
IP — IP-адреса мережевого принтера (String).
Port — TCP-порт принтера (Integer), зазвичай 9100.
Повертає: 0 — успіх, інше — помилка.
Підключення через принтер Windows.
Параметри:
ID — фіскальний номер ПРРО (Int64).
PrinterName — системна назва принтера (String).
Повертає: 0 — успіх, інше — помилка.
Відключення від ПРРО. Рекомендується викликати при завершенні роботи.
Повертає: 0 — успіх, інше — помилка.
Відкриття нового чека.
Параметри:
CheckType — тип чека (Integer): 0 — чек продажу, 1 — чек повернення.
RetCheckNum — для повернення: фіскальний номер оригінального чека (String). Для продажу передавати ''.
Повертає: 0 — успіх, інше — помилка.
Приклад:
RRO.OpenReceipt(0, ''); // чек продажу
RRO.OpenReceipt(1, '12345678'); // чек повернення
Додавання позиції (товару або послуги) до відкритого чека.
Параметри:
Code — код товару, артикул (Int64).
AName — назва товару, до 256 символів (String).
Price — ціна за одиницю в гривнях (Double).
Amount — кількість (Double).
Tax — номер ставки ПДВ (Integer), від 1 до 4 відповідно до конфігурації.
DiscountType — тип знижки (Integer), див. розділ 12.
DiscountValue — значення знижки: відсоток або сума (Double).
Властивості, що встановлюються перед викликом:
Barcode — штрихкод товару (EAN-13 тощо). Встановити перед Sale, автоматично скидається після.
ExciseStamp — акцизна марка (серія та номер).
CustomsCode — митний код товару.
Повертає: 0 — успіх, інше — помилка.
Приклад:
RRO.Barcode := '4820000000001';
RRO.Sale(1001, 'Молоко 1л', 35.50, 2, 1, 0, 0);
Додавання оплати до відкритого чека.
Параметри:
PayType — тип оплати (Integer), див. розділ 11.
Sum — сума оплати в гривнях (Double). Значення 0 означає оплатити всю залишкову суму.
Повертає: 0 — успіх, інше — помилка.
Приклад:
RRO.Pay(0, 0); // оплата готівкою на повну суму
RRO.Pay(1, 100); // оплата карткою 100 грн
Знижка на весь чек. Викликається після всіх позицій і до оплати.
Параметри:
DiscountType — тип знижки (Integer), див. розділ 12.
DiscountSum — значення знижки: відсоток або сума (Double).
Повертає: 0 — успіх, інше — помилка.
Додає довільний текстовий рядок до поточного чека. Текст роздруковується у тілі чека.
Параметри:
Text — текст рядка (String).
Повертає: 0 — успіх, інше — помилка.
Закриття чека і надсилання до ПРРО.
Властивості, що встановлюються перед викликом:
CheckComment — текстовий коментар у заголовку чека.
FooterCheckComment — текстовий коментар у нижній частині чека.
Повертає: 0 — успіх, інше — помилка. Після успіху фіскальний номер чека доступний у LastReceiptNum.
Поля результату (після успіху доступні через DataFields[Index]):
| Індекс | Опис |
|---|---|
| 1 | '0' — ознака успіху |
| 2 | Кількість чеків продажу в зміні |
| 3 | Кількість чеків повернення в зміні |
| 4 | Фіскальний номер чека |
| 10 | Посилання на чек (URL) |
| 11 | Текстове представлення чека |
| 12 | Текст чека з ESC-послідовностями для друку |
| 13 | 'OFFLINE' / 'ONLINE' — режим роботи ПРРО на момент закриття |
| 15 | PDF чека в base64 |
| 16 | SHA-256 хеш фіскального чека |
| 17 | Номер останнього відправленого чека |
| 18 | ID зміни |
| 21 | Текст чека в UTF-8 (для CrossLib) |
Скасування поточного відкритого чека без його закриття.
Повертає: 0 — успіх, інше — помилка.
Перевірка, чи існує фіскальний чек для можливості оформлення повернення.
Параметри:
CheckNum — фіскальний номер чека (String).
Повертає: 0 — чек знайдено, -1 — не знайдено, інше — помилка зв'язку.
Отримання інформації про поточний відкритий чек. Результат записується у властивість ReceivedData (повний JSON-рядок від сервера ДПС), а окремі поля — у DataFields[Index].
Повертає: 0 — успіх, інше — помилка.
X-звіт (проміжний звіт без закриття зміни). Зміна залишається відкритою.
Повертає: 0 — успіх, інше — помилка.
Поля результату (доступні через DataFields[Index]):
| Індекс | Опис |
|---|---|
| 1 | ID поточної зміни |
| 10 | Посилання на чек звіту |
| 11 | Текст чека X-звіту |
| 12 | Текст чека з ESC-послідовностями |
| 21 | Текст чека в UTF-8 (для CrossLib) |
Z-звіт — закриття зміни і надсилання підсумків до ПРРО. Після виконання відкривається нова зміна.
Повертає: 0 — успіх, інше — помилка.
Поля результату (після успіху доступні через DataFields[Index]):
| Індекс | Опис |
|---|---|
| 1 | ID зміни, що закривається |
| 10 | Посилання на чек звіту |
| 11 | Текст чека Z-звіту |
| 12 | Текст чека з ESC-послідовностями |
| 13 | Фіскальний номер чека Z-звіту |
| 14 | Номер Z-звіту в системі ПРРО |
| 21 | Текст чека в UTF-8 (для CrossLib) |
| 25 | Кількість чеків продажу за зміну |
| 26 | Кількість чеків повернення за зміну |
| 27 | Загальна сума знижок за чеками продажу |
| 28 | Загальна сума знижок за чеками повернення |
| 29 | Кількість чеків зняття готівки |
Інкасо або підкріплення каси.
Параметри:
Sum — сума в гривнях (Double). Значення більше нуля — підкріплення (внесення готівки). Значення менше нуля — інкасо (вилучення готівки).
Повертає: 0 — успіх, інше — помилка.
Поля результату (після успіху доступні через DataFields[Index]):
| Індекс | Опис |
|---|---|
| 1 | Сума в касі × 100 (в копійках) |
| 2 | Загальна сума внесень за зміну |
| 3 | Загальна сума інкасацій за зміну |
| 4 | Фіскальний номер чека |
| 5 | ID зміни |
| 11 | Текст чека |
| 12 | Текст чека з ESC-послідовностями |
Отримання інформації про поточну зміну: номер зміни, суми тощо. Результат записується у властивість ReceivedData (повний JSON), а окремі поля — у DataFields[Index].
Повертає: 0 — успіх, інше — помилка.
Отримання поточних підсумків зміни.
Параметри:
iParam — режим отримання (Integer). Значення 0 — стандартні підсумки; значення від 1 і вище — розширені підсумки (залежить від конфігурації).
Результат записується у властивість ReceivedData (повний JSON), а окремі поля — у DataFields[Index].
Повертає: 0 — успіх, інше — помилка.
Повертає текстовий опис помилки за її числовим кодом.
Параметри:
ErrCode — числовий код помилки (Integer).
Повертає: рядок з описом помилки.
Отримання списку Z-звітів за діапазон дат. Результат записується у властивість ReceivedData — рядок номерів Z-звітів, розділених ;, наприклад:
12;13;14;15;
Параметри:
Date1 — дата початку у форматі 'DDMMYYYY', наприклад '01052026' (String).
Date2 — дата кінця у форматі 'DDMMYYYY' (String).
Повертає: 0 — успіх, інше — помилка.
Зазвичай використовується у парі з ReadCheckListByZ для отримання реєстру чеків за період: спочатку ReadZListByDate повертає список Z-звітів, потім для кожного Z викликається ReadCheckListByZ — і виходить повний реєстр чеків. Див. приклад нижче.
Реєстр чеків Z-звіту. Повертає повний JSON-масив з усіма чеками вказаного Z-звіту: метадані + повний XML кожного чека (у base64).
Параметри:
ZNum — номер Z-звіту (Integer).
Повертає: 0 — успіх, інше — помилка.
Результат — JSON-масив у властивості ReceivedData. Кожен елемент описує один чек:
| Поле JSON | Опис |
|---|---|
ZNum |
Номер зміни (Z) |
LocalCheckNum |
Локальний номер чека в зміні |
FiscalCheckNum |
Фіскальний номер чека (присвоєний ДПС) |
Date |
Дата та час чека (DD.MM.YYYY HH:MM:SS) |
Sum |
Сума чека (грн, два знаки після коми) |
CheckType |
Тип чека: Sale, Return, Zet, OpenZ, CloseZ, OffLineBegin, OffLineEnd, InOut, CashWithdrawal |
PayType |
Тип оплати: Cash, Card, Credit, Mixed |
Comment |
Коментар з чека |
OffLine |
"True" / "False" — чи був чек створений у офлайн-режимі |
Revoked |
"True" / "False" — чи був чек анульований |
UID |
Унікальний ідентифікатор чека |
Xml |
Повний XML тіла чека, закодований у base64 |
Приклад: повний реєстр за період (Delphi/COM):
uses ComObj, System.JSON, System.NetEncoding;
procedure DownloadPeriodRegister(const D1, D2: string);
var
RRO: OleVariant;
ZList: TArray<string>;
ZNumStr: string;
ZNum: Integer;
Checks: TJSONArray;
Check: TJSONObject;
CheckXmlBytes: TBytes;
begin
RRO := CreateOleObject('ProCheck.ProgramRRO');
RRO.ConnectLan(4000154869, '192.168.1.100', 9100);
// 1. Список Z-звітів за період
if RRO.ReadZListByDate(D1, D2) <> 0 then Exit;
ZList := SplitString(RRO.ReceivedData, ';');
// 2. Для кожного Z отримуємо реєстр чеків (JSON)
for ZNumStr in ZList do
begin
if ZNumStr = '' then Continue;
ZNum := StrToInt(ZNumStr);
if RRO.ReadCheckListByZ(ZNum) <> 0 then Continue;
Checks := TJSONObject.ParseJSONValue(RRO.ReceivedData) as TJSONArray;
try
for var I := 0 to Checks.Count - 1 do
begin
Check := Checks.Items[I] as TJSONObject;
// Розшифровка XML з base64
CheckXmlBytes := TNetEncoding.Base64.DecodeStringToBytes(Check.GetValue('Xml').Value);
// ... обробка чека ...
end;
finally
Checks.Free;
end;
end;
RRO.Disconnect;
end;
// Виклик: реєстр за травень 2026
DownloadPeriodRegister('01052026', '31052026');
Періодичний звіт — згорнутий Z-звіт за довільний період (день / тиждень / місяць / квартал тощо). Агрегує суми продажу, повернення, інкасації та внесення за період.
Параметри:
Date1 — дата початку у форматі 'DDMMYYYY' (String).
Date2 — дата кінця у форматі 'DDMMYYYY' (String).
Повертає: 0 — успіх, інше — помилка.
Поля результату (після успіху доступні через DataFields[Index]):
| Індекс | Опис |
|---|---|
| 0 | Літери груп ПДВ (через ;), напр. A;B;C;D; |
| 1 | Обороти продажу за групами ПДВ (через ;) |
| 2 | Суми ПДВ по продажу за групами (через ;) |
| 3 | Обороти повернення за групами ПДВ (через ;) |
| 4 | Суми ПДВ по поверненню за групами (через ;) |
| 5 | Загальна сума продажу за період |
| 6 | Загальна сума повернень за період |
| 7 | Кількість чеків продажу |
| 8 | Кількість чеків повернення |
| 9 | Загальна сума внесень готівки (Service Input) |
| 10 | Загальна сума інкасацій (Service Output) |
| 11 | Сума за чеками зняття готівки (cash-out) |
| 12 | Кількість чеків зняття готівки |
| 50 | Date1 (як був переданий — для контролю) |
| 51 | Date2 (як був переданий — для контролю) |
Приклад (Delphi/COM):
// Звіт за травень 2026
if RRO.PeriodicReport('01052026', '31052026') = 0 then
begin
TotalSales := StrToFloat(RRO.DataFields[5]);
TotalRet := StrToFloat(RRO.DataFields[6]);
CheckCount := StrToInt(RRO.DataFields[7]);
ShowMessage(Format('Продажів: %.2f грн (%d чеків)', [TotalSales, CheckCount]));
end;
Приклад (CrossLib / C):
if (PeriodicReport("01052026", "31052026") == 0) {
printf("Продаж: %s, повернень: %s\n", GetDataField(5), GetDataField(6));
printf("Чеків продажу: %s\n", GetDataField(7));
}
Встановлення таймауту читання відповіді в мілісекундах.
Параметри:
lMSec — таймаут у мілісекундах (Integer).
Підписати обєкт на події прогресу довгих операцій (ReadCheckListByZ, PeriodicReport, побудова реєстру за період). Корисно для відображення статусу у UI без блокування на час виклику.
Параметри:
Handler (Variant) — COM-обєкт (через IDispatch), що має метод:
function OnProgress(TaskID: Integer;
MinValue, CurPos, MaxValue: Integer;
Text: WideString): Integer;
Передайте Null (Unassigned), щоб зняти підписку.
Параметри callback:
| Параметр | Опис |
|---|---|
TaskID |
1 — обробка списку змін, 2 — обробка чеків у зміні, 3 — обробка списку чеків |
MinValue, MaxValue |
Діапазон значень (зазвичай 0..N) |
CurPos |
Поточна позиція |
Text |
Людино-читаний опис етапу (українською/російською) |
Повернення з OnProgress наразі зарезервовано (ігнорується), рекомендується повертати 0.
Важливо: callback викликається синхронно з робочого потоку ПРРО. Не виконуйте у ньому тривалих UI-операцій — використайте чергу повідомлень, Application.ProcessMessages або PostMessage.
Приклад (Delphi):
type
TMyHandler = class(TAutoObject, IMyHandler)
public
function OnProgress(TaskID, Min, Cur, Max: Integer;
const Text: WideString): Integer; safecall;
end;
function TMyHandler.OnProgress(TaskID, Min, Cur, Max: Integer;
const Text: WideString): Integer;
begin
Form1.ProgressBar.Max := Max;
Form1.ProgressBar.Position := Cur;
Form1.StatusBar.SimpleText := Text;
Application.ProcessMessages;
Result := 0;
end;
// Підписка
RRO.SetProgressHandler(CreateComObject(CLASS_MyHandler) as IDispatch);
RRO.ReadCheckListByZ(42);
RRO.SetProgressHandler(Null); // зняти
Приклад (Python / pywin32):
import win32com.client
import win32com.server.util
class ProgressHandler:
_public_methods_ = ["OnProgress"]
def OnProgress(self, task_id, min_value, current, max_value, text):
print(f"{current}/{max_value} {text}")
return 0
rro = win32com.client.Dispatch("ProCheck.ProgramRRO")
handler = win32com.server.util.wrap(ProgressHandler())
rro.SetProgressHandler(handler)
rro.ReadCheckListByZ(42)
rro.SetProgressHandler(None)
Приклад (C# .NET, late binding):
public class ProgressHandler {
public int OnProgress(int taskID, int min, int cur, int max, string text) {
Console.WriteLine($"{cur}/{max}: {text}");
return 0;
}
}
dynamic rro = Activator.CreateInstance(Type.GetTypeFromProgID("ProCheck.ProgramRRO"));
rro.SetProgressHandler(new ProgressHandler());
rro.ReadCheckListByZ(42);
rro.SetProgressHandler(null);
Приклад (1С):
// Обробник у вигляді ВнешнейОбработки з методом OnProgress
Обробник = Новый ВнешняяОбработка(КаталогОбработок() + "ProgressHandler.epf");
ПРРО.SetProgressHandler(Обробник);
ПРРО.ReadCheckListByZ(42);
ПРРО.SetProgressHandler(Неопределено);
LastErrorMessage (String) — текст останньої помилки, у тому числі відповідь сервера ДПС.
LastErrorCode (Integer) — числовий код останньої помилки.
LastReceiptNum (String) — фіскальний номер останнього закритого чека.
ReceivedData (String) — дані, отримані від останньої операції: JSON або текст.
OfflineMode (Boolean) — значення True означає, що ПРРО працює в офлайн-режимі.
DataFields[Index] (String, індексована) — окремі поля результату останньої операції. Заповнюються методами CloseReceipt, XReport, ZReport, InOut, GetReceiptInfo, GetDayInfo, GetCurrentSums. Конкретний склад полів для кожного методу див. у його описі. Індекс — від 0 до 200.
RRO.CloseReceipt;
LastNum := RRO.DataFields[4]; // фіскальний номер
PdfBase64 := RRO.DataFields[15]; // PDF чека
SaleBarcode (String) — штрихкод товару. Встановити перед Sale, автоматично скидається після виклику.
ExciseStamp (String) — акцизна марка (серія та номер). Встановити перед Sale.
CustomsCode (String) — митний код товару. Встановити перед Sale.
CloseReceiptCheckComment (String) — коментар у заголовку чека.
FooterCheckComment (String) — коментар у нижній частині чека.
Параметр PayType у методі Pay:
0 — готівка.
1 — безготівкова оплата (банківська картка).
2 — попередня оплата (аванс).
3 — кредит.
Параметр DiscountType у методах Sale та TotalDiscount:
0 — без знижки (DiscountValue ігнорується).
1 — відсоткова знижка (DiscountValue — відсоток, наприклад 5.0).
2 — сумова знижка (DiscountValue — сума в гривнях).
-1 — те саме, що 0 (без знижки).
ReadZListByDate, ReadCheckListByZ — формат 'DDMMYYYY', наприклад '01052025'.
LastReceiptNum — рядок із фіскальним номером чека (формат визначається ПРРО).
uses ComObj;
procedure PrintReceipt;
var
RRO: OleVariant;
R: Integer;
begin
RRO := CreateOleObject('ProCheck.ProgramRRO');
// Підключення
R := RRO.Connect(4000154869, 'COM3', 115200);
if R <> 0 then begin
ShowMessage('Помилка підключення: ' + RRO.LastErrorMessage);
Exit;
end;
// Відкрити чек продажу
R := RRO.OpenReceipt(0, '');
if R <> 0 then begin
ShowMessage('Помилка відкриття чека: ' + RRO.LastErrorMessage);
Exit;
end;
// Додати позиції
RRO.Barcode := '4820000000001';
R := RRO.Sale(1001, 'Молоко 2.5% 1л', 38.50, 2, 1, 0, 0);
if R <> 0 then begin
ShowMessage('Помилка позиції: ' + RRO.LastErrorMessage);
RRO.CancelReceipt;
Exit;
end;
R := RRO.Sale(2005, 'Хліб пшеничний', 22.00, 1, 1, 0, 0);
if R <> 0 then begin
RRO.CancelReceipt;
Exit;
end;
// Оплата готівкою
R := RRO.Pay(0, 0);
if R <> 0 then begin
ShowMessage('Помилка оплати: ' + RRO.LastErrorMessage);
RRO.CancelReceipt;
Exit;
end;
// Коментар і закриття
RRO.CheckComment := 'Дякуємо за покупку!';
R := RRO.CloseReceipt;
if R = 0 then
ShowMessage('Чек #' + RRO.LastReceiptNum + ' пробито успішно')
else
ShowMessage('Помилка закриття: ' + RRO.LastErrorMessage);
end;
import win32com.client
rro = win32com.client.Dispatch("ProCheck.ProgramRRO")
if rro.Connect(4000154869, "COM3", 115200) != 0:
raise RuntimeError(f"Помилка підключення: {rro.LastErrorMessage}")
try:
result = rro.ZReport()
if result == 0:
print("Z-звіт виконано успішно")
else:
print(f"Помилка Z-звіту: {rro.LastErrorMessage}")
finally:
rro.Disconnect()
using System;
using System.Runtime.InteropServices;
class Program
{
static void Main()
{
Type rroType = Type.GetTypeFromProgID("ProCheck.ProgramRRO");
if (rroType == null)
{
Console.WriteLine("ProCheck.dll не зареєстровано!");
return;
}
dynamic rro = Activator.CreateInstance(rroType);
int r = rro.Connect(4000154869L, "COM3", 115200);
if (r != 0)
{
Console.WriteLine($"Помилка підключення: {rro.LastErrorMessage}");
return;
}
r = rro.XReport();
Console.WriteLine(r == 0
? "X-звіт виконано"
: $"Помилка X-звіту: {rro.LastErrorMessage}");
rro.Disconnect();
Marshal.ReleaseComObject(rro);
}
}
ПРРО = Новый COMОбъект("ProCheck.ProgramRRO");
// Підключення
Результат = ПРРО.Connect(4000154869, "COM3", 115200);
Если Результат <> 0 Тогда
Сообщить("Помилка підключення: " + ПРРО.LastErrorMessage);
Возврат;
КонецЕсли;
// Відкрити чек продажу
Результат = ПРРО.OpenReceipt(0, "");
Если Результат <> 0 Тогда
Сообщить("Помилка відкриття чека: " + ПРРО.LastErrorMessage);
Возврат;
КонецЕсли;
// Додати позиції
ПРРО.Barcode = "4820000000001";
Результат = ПРРО.Sale(1001, "Молоко 2.5% 1л", 38.50, 2, 1, 0, 0);
Если Результат <> 0 Тогда
Сообщить("Помилка позиції: " + ПРРО.LastErrorMessage);
ПРРО.CancelReceipt();
Возврат;
КонецЕсли;
Результат = ПРРО.Sale(2005, "Хліб пшеничний", 22.00, 1, 1, 0, 0);
Если Результат <> 0 Тогда
ПРРО.CancelReceipt();
Возврат;
КонецЕсли;
// Оплата готівкою на повну суму
Результат = ПРРО.Pay(0, 0);
Если Результат <> 0 Тогда
Сообщить("Помилка оплати: " + ПРРО.LastErrorMessage);
ПРРО.CancelReceipt();
Возврат;
КонецЕсли;
// Коментар і закриття чека
ПРРО.CheckComment = "Дякуємо за покупку!";
Результат = ПРРО.CloseReceipt();
Если Результат = 0 Тогда
Сообщить("Чек #" + ПРРО.LastReceiptNum + " пробито успішно");
Иначе
Сообщить("Помилка закриття: " + ПРРО.LastErrorMessage);
КонецЕсли;
ПРРО.Disconnect();
ПРРО = Новый COMОбъект("ProCheck.ProgramRRO");
Если ПРРО.Connect(4000154869, "COM3", 115200) <> 0 Тогда
Сообщить("Помилка підключення: " + ПРРО.LastErrorMessage);
Возврат;
КонецЕсли;
Результат = ПРРО.ZReport();
Если Результат = 0 Тогда
Сообщить("Z-звіт виконано успішно");
Иначе
Сообщить("Помилка Z-звіту: " + ПРРО.LastErrorMessage);
КонецЕсли;
ПРРО.Disconnect();
CrossLib — це окрема реалізація того ж функціоналу ПРРО у вигляді кросплатформенної динамічної бібліотеки libprocheck.so (Linux) або procheck.dll (Windows) без COM-обгортки. Експортує ті ж самі імена функцій (Connect, OpenReceipt, Sale, Pay, CloseReceipt тощо), але працює інакше — як звичайна shared-бібліотека з C-сумісним ABI.
Призначена для:
| Аспект | COM (ProCheck.dll) |
CrossLib (libprocheck.so) |
|---|---|---|
| Реєстрація | regsvr32 обов'язкова |
Не потрібна, файл просто лежить поряд із застосунком |
| Платформа | Тільки Windows | Linux, Windows, Android, ARM |
| Інтерфейс | OLE/Automation | Прямий експорт C-функцій |
| Угода виклику | COM stdcall | cdecl (Linux) / stdcall (Windows) |
| Стан | Окремий екземпляр на CreateOleObject |
Один глобальний синглтон на процес |
| Властивості | RRO.Barcode := '…' |
Set_Barcode("…") / Get_Barcode() |
| Рядки | BSTR / WideString |
PChar (нуль-термінований UTF-8) |
| Помилки | Властивість LastErrorMessage |
Функція GetLastErrorMessage() |
#include "procheck.h"
// libprocheck.so має бути в LD_LIBRARY_PATH або поряд з виконуваним файлом
int r = Connect(4000154869LL, "/dev/ttyUSB0", 115200);
Заголовний файл і скрипт збірки: Demo/GCC/procheck.h, Demo/GCC/build.sh.
import procheck as pc
pc.load() # шукає libprocheck.so поряд зі скриптом
pc.Connect(4000154869, '/dev/ttyUSB0', 115200)
Модуль-обгортка: Demo/Python/procheck.py.
HMODULE h = LoadLibrary("procheck.dll");
typedef int (__stdcall *Connect_t)(int64_t, const char*, int);
Connect_t Connect = (Connect_t)GetProcAddress(h, "Connect");
int r = Connect(4000154869LL, "COM3", 115200);
На відміну від COM, де CreateOleObject створює окремий екземпляр, CrossLib має один глобальний об'єкт ПРРО на процес. Він автоматично ініціалізується при першому виклику будь-якої функції — окремого Init робити не потрібно.
Наслідки:
Усі функції приймають і повертають PChar — вказівник на нуль-термінований рядок. Конкретне кодування рядків задається через SetStringEncoding (див. 13.4.1).
Передача рядків у функцію. Викликаюча сторона передає const char*; бібліотека копіює дані у внутрішні буфери, тож рядок можна звільняти одразу після виклику.
Отримання рядків. GetLastErrorMessage, GetLastReceiptNum, GetDataField, Get_Barcode, GetReceivedData тощо повертають вказівник на внутрішній статичний буфер бібліотеки. Цей вказівник дійсний лише до наступного виклику тієї ж функції. Якщо значення потрібне пізніше — скопіюйте його одразу:
const char* err = GetLastErrorMessage();
char saved[512];
strncpy(saved, err, sizeof(saved) - 1);
saved[sizeof(saved) - 1] = '\0';
// тепер можна викликати інші функції, saved залишиться валідним
У Python-обгортці копіювання виконується автоматично — bytes → str через procheck.str_().
SetStringEncodingБібліотека вміє перекодовувати строкові параметри та результати «на льоту» відповідно до обраного режиму:
int SetStringEncoding(int Encoding);
int GetStringEncoding(void);
| Константа | Значення | Опис |
|---|---|---|
PROCHECK_ENCODING_RAW |
0 |
Без перекодування — як є у внутрішньому представленні |
PROCHECK_ENCODING_CP1251 |
1 |
Усі параметри та результати — у CP1251 |
PROCHECK_ENCODING_UTF8 |
2 |
Усі параметри та результати — у UTF-8 |
Налаштовується один раз на старті, до першого виклику будь-якої функції з рядковими аргументами:
SetStringEncoding(PROCHECK_ENCODING_UTF8);
ConnectLan(4000154869LL, "192.168.1.100", 9100);
OpenReceipt(0, "");
Sale(1001, "Молоко", 35.50, 1, 1, 0, 0); /* "Молоко" буде сприйнято як UTF-8 */
Рекомендовані значення за платформою:
PROCHECK_ENCODING_UTF8PROCHECK_ENCODING_UTF8PROCHECK_ENCODING_CP1251В обгортках за замовчуванням:
Demo/Python/procheck.py — load() автоматично виставляє UTF-8.Demo/CSharp/ProCheck.cs — статичний конструктор виставляє UTF-8.Demo/GCC/demo_receipt.c — викликає SetStringEncoding(PROCHECK_ENCODING_UTF8) на старті.COM-властивості замінені на пари функцій. Семантика збережена: значення, встановлене через Set_*, застосовується до наступної операції (Sale, CloseReceipt тощо) і потім автоматично скидається.
| COM-властивість | CrossLib-функція |
|---|---|
RRO.Barcode := '…' |
Set_Barcode("…") |
RRO.ExciseStamp := '…' |
Set_ExciseStamp("…") |
RRO.CustomsCode := '…' |
Set_CustomsCode("…") |
RRO.CheckComment := '…' |
Set_CheckComment("…") |
RRO.FooterCheckComment := '…' |
Set_FooterCheckComment("…") |
Властивості тільки для читання — окремі функції-getters:
| COM-властивість | CrossLib-функція | Тип |
|---|---|---|
LastErrorMessage |
GetLastErrorMessage() |
PChar |
LastErrorCode |
GetLastErrorCode() |
Integer |
LastReceiptNum |
GetLastReceiptNum() |
PChar |
ReceivedData |
GetReceivedData() |
PChar |
OfflineMode |
GetOfflineMode() |
WordBool (16-біт) |
Аналог COM-властивості DataFields[Index] — функція, що повертає окреме поле результату останньої операції за індексом (0..200):
int r = CloseReceipt();
if (r == 0) {
const char* fiscalNum = GetDataField(4); // фіскальний номер
const char* pdf = GetDataField(15); // PDF в base64
}
Поля автоматично оновлюються після успішного виклику CloseReceipt, XReport, ZReport, InOut, GetReceiptInfo, GetDayInfo, GetCurrentSums.
Конкретний склад полів для кожного методу див. у його описі (розділи 6, 7).
Деякі операції (ReadCheckListByZ, PeriodicReport, побудова реєстру за період) можуть займати помітний час — особливо коли в зміні багато чеків або обробляється великий період. CrossLib дозволяє підписатися на оновлення прогресу через callback:
typedef int (PRRO_API *ProgressCallback)(int TaskID,
unsigned int MinValue,
unsigned int CurPos,
unsigned int MaxValue,
const char* Text);
int SetProgressCallback(ProgressCallback Cb); // Cb=NULL — зняти
Параметри callback:
| Параметр | Опис |
|---|---|
TaskID |
Ідентифікатор задачі: 1 — обробка списку змін, 2 — обробка чеків у зміні, 3 — обробка списку чеків |
MinValue, MaxValue |
Діапазон значень (зазвичай 0..N) |
CurPos |
Поточна позиція в діапазоні |
Text |
Людино-читаний опис етапу (з урахуванням SetStringEncoding) |
Константи TaskID в заголовках:
PROCHECK_TASK_SHIFT_PROCESS, PROCHECK_TASK_SHIFT_CHECKS_PROCESS, PROCHECK_TASK_CHECKS_PROCESSpc.TASK_SHIFT_PROCESS, pc.TASK_SHIFT_CHECKS_PROCESS, pc.TASK_CHECKS_PROCESSProCheckLib.TASK_SHIFT_PROCESS, TASK_SHIFT_CHECKS_PROCESS, TASK_CHECKS_PROCESSПовернення з callback зарезервовано (наразі ігнорується), рекомендується повертати 0.
Приклад (C):
static int OnProgress(int task, unsigned min, unsigned cur, unsigned max, const char* text)
{
int percent = (max > min) ? (cur * 100 / (max - min)) : 0;
printf("\r[%3d%%] %s", percent, text);
fflush(stdout);
return 0;
}
SetProgressCallback(OnProgress);
ReadCheckListByZ(42); // тепер callback викликається під час обробки
SetProgressCallback(NULL); // знімаємо
Приклад (Python):
def on_progress(task, min_v, cur, max_v, text):
pct = int(cur * 100 / max(1, max_v - min_v))
print(f'\r[{pct:3d}%] {text}', end='', flush=True)
return 0
pc.SetProgressCallback(on_progress)
pc.ReadCheckListByZ(42)
pc.SetProgressCallback(None)
Приклад (C#):
ProCheckLib.SetProgress((task, min, cur, max, text) => {
int pct = max > min ? (int)(cur * 100 / (max - min)) : 0;
Console.Write($"\r[{pct,3}%] {text}");
return 0;
});
ProCheckLib.ReadCheckListByZ(42);
ProCheckLib.SetProgress(null);
Важливо:
Усі експортовані функції використовують стандартну C-сумісну угоду виклику відповідної платформи:
cdeclstdcall (__stdcall)При роботі з бібліотекою через ctypes у Python модуль автоматично обирає CDLL або WinDLL.
Готові робочі приклади з повним циклом пробиття чека (підключення → відкриття чека → дві позиції → оплата → закриття):
Demo/GCC/demo_receipt.c + Demo/GCC/build.shDemo/Python/demo_receipt.py + Demo/Python/procheck.pyЗаголовний файл Demo/GCC/procheck.h містить декларації всіх експортованих функцій із докладними коментарями та коректними типами C (int64_t, double, const char*, short для WordBool).
Версія документації: 2.2 | Дата: травень 2026