XML описание кассового документа для предоставления внешним системам
Назначение
Настоящий стандарт разработан для обеспечения возможности единообразного предоставления информации о содержании покупки внешним заинтересованным системам, таким как: видео наблюдение, системы лояльности и так далее.
Общее описание
Кассовые системы компании UCS передают внешним системам информацию о чеке через ряд интерфейсов, для Rkeeper v7 основным таким интерфейсом является FarCards.
Теги всегда передаются в верхнем регистре, атрибуты - в нижнем. Формат даты времени - по XML Date/Time
Особенности использования
Заказы/чеки
Формируемый кассовой системой XML документ должен включать всю информацию о заказе, доступную кассе на момент формирования заказа. Если чеков в одном заказе несколько - то в XML документе передается именно содержимое конкретного чека, иначе - заказа (атрибут CheckNum в этом случае не заполняется).
Интерфейсы
Интерфейс - программная единица, взаимодействующая с кассовой системой, принимающая XML документы и, возможно, обеспечивающая платежный, дисконтный, бонусный функционал.
Список интерфейсов, для которых по мнению кассы, подготовлен XML, находится в теге INTERFACES тега EXTINFO. Интерфейс должен самостоятельно контролировать соответствие своего типа указанным в атрибутах type вложенного тега INTERFACE. Внешний идентификатор интерфейса так же должен быть указан в атрибуте interface тегов Payment, Discount, Bonus если соответствующая операция была произведена с участием интерфейса. Указывается фактически участвовавший в формировании операции интерфейс. Это нужно для возможности контроля на стороне внешней системы наличия/отсутствия в обрабатываемом чеке участия других систем.
Для идентификации вызывающей стороны в теге INTERFACE есть атрибут current=«Х» который принимает значение, равное внутреннему идентификатору интерфейса для которого собирается XML документ. Внешнее значение идентификатора интерфейса находится в атрибуте interface тэга INTERFACE. Для идентификации чека, полученного из внешней системы (внешняя доставка) используется атрибут тега EXTINFO - reservation (заполняется при генерации XML в RKeeper 6).
Расширение
Определяемый ниже перечень обязательных и рекомендованных тегов является минимальным. Возможно его расширение. Например атрибут «ticketkind» в описании не определен но присутствует в примере. Наличие таких атрибутов не гарантируется и должно игнорироваться принимающей стороной.
Описание XML документа
CHECK
тег верхнего уровня
атрибут | тип | обязательное | описание |
---|---|---|---|
stationcode | String | + | код станции, на которой сгенерирован документ |
restaurantcode | String | + | код ресторана, в котором сгенерирован документ |
cashservername | String | + | имя (сетевое) кассового сервера, на котором сгенерирован документ |
generateddatetime | XMLDateTime | + | время генерации |
chmode | Integer | - | режим чека (см ниже), с версии 1.4 типы 0-10, до версии 1.4 поддерживались типы 0-4 |
locale | Integer | - | Windows locale клиента, с версии 2.4, см. https://msdn.microsoft.com/en-us/goglobal/bb896001.aspx, число из первой колонки надо перевести в десятичное |
shiftdate | xmldate | - | с версии 2.6, дата смены |
shiftnum | integer | - | с версии 2.6, номер смены |
protocolversion | String | +/27 | с версии 27, версия протокола, поддерживаемая клиентом FarCards - генератором XML |
clientapp | String | +/27 | с версии 27, Имя приложения-клиента FarCards, генератора XML (RK6, RK7, Shelter, …) |
clientversion | String | +/27 | с версии 27, Версия приложения-клиента FarCards, генератора XML (RK6, RK7, Shelter, …) |
Допустимые значения атрибута chmode и их описание:
Число | Константа | Описание | Комментарий |
---|---|---|---|
0 | XMLchmodeNotCheck | не чек (вызов вне чека или технический вызов для получения, например, только имени клиента) | в GetCardInfo - короткий XML и в Transaction, если вызвано через SimpleTransaction (из скрипта) |
1 | XMLchmodeSale | оплата (касса проводит операцию оплаты заказа) | в GetCardInfo перед транзакцией и в Transaction |
2 | XMLchmodeSaleRollback | откат (касса не смогла завершить все этапы оплаты корректно, но ранее интерфейс подтвердил успешную транзакцию) | в GetCardInfo перед транзакцией и в Transaction |
3 | XMLchmodeReturn | возврат (возврат чека после успешного оформления) | в GetCardInfo перед транзакцией и в Transaction |
4 | XMLchmodeReturnRollback | откат возврата (касса не смогла завершить все этапы возврата корректно, но ранее интерфейс подтвердил успешную транзакцию возврата) | в GetCardInfo перед транзакцией и в Transaction |
5 | XMLchmodeOrderEditing | режим заказа (заказ не завершен) | в GetCardInfo (заказ может быть незавершен) |
6 | XMLchmodeOrderBill | печать пречека (заказ не завершен, но готов к завершению) | в GetCardInfo при макетировании и в Transaction (в режиме «все чеки/пречеки в farcards») |
7 | XMLchmodeOrderCalc | режим расчета (заказ не завершен, но готов к завершению) | в GetCardInfo |
8 | XMLchmodePrintCardInfo | печать инфо о карте, возможно, не из заказа - в GetCardInfo | |
9 | XMLchmodeInitEntranceCardOrder | создание заказа в «карте на входе» | в GetCardInfo (перед заказом, для запроса информации для создания заказа) - короткий XML |
10 | XMLchmodePrintAfterTransaction | после транзакций для печати слипов | в GetCardInfo короткий XML |
11 | XMLchmodeServPrint | сервис-печать (заказ не завершен) | (иногда там могут быть скидки с персональной информацией), начиная с версии 1.5 |
12 | XMLchmodeCancelBill | отмена пречека (заказ не завершен) | начиная с версии 2.4 |
13 | XMLchmodeBeforeReceipt | перед транзакциями | начиная с версии 28 |
Пример короткого XML:
<CHECK chmode="0" stationcode="5" restaurantcode="722500001" cashservername="RLSERV" generateddatetime="2012-04-15T21:32:00" locale="1049" shiftdate="xmldate" shiftnum="int" >
<EXTINFO>
<INTERFACES current="12348">
<INTERFACE type="PDS" id="12348" mode="3" interface="8">
<HOLDERS>
<ITEM cardcode="11301867"/>
</HOLDERS>
</INTERFACE>
</INTERFACES>
</EXTINFO>
</CHECK >
EXTINFO
Тег описания назначения макета: внутри этого тега содержатся теги, определяющие применимость макета для разных систем. Если какая-то система в списке не обозначена - наличие сведений для нее в самом документе не гарантируется. Специфические атрибуты для целевой системы передаются именно в теге этой системы. Для этого тега не допускается добавлять атрибуты (поскольку для некоторых систем его генерация - внешняя и основана на строковых подстановках).
Допустимые теги:
VIDEO - для систем видео-наблюдения
атрибут | тип | обязательное | описание |
---|---|---|---|
interface | Integer | + | номер интерфейса внешней системы в БД кассы |
KDS - для KDS/VDU
атрибут | тип | обязательное | описание |
---|---|---|---|
interface | Integer | + | номер интерфейса внешней системы в БД кассы |
PDS - для систем лояльности
атрибут | тип | обязательное | описание |
---|---|---|---|
id | Integer | + | внутренний идентификатор интерфейса внешней системы в БД кассы, обрабатывающей этот идентификатор |
interface | Integer | - | код интерфейса внешней системы в БД кассы, обрабатывающей этот идентификатор, используется для поиска «своих» платежей и скидок по атрибутам interface |
mode | Integer | - | для протоколов < 29: 0 - перед запросом инфо о карте1 , 1 - перед чеком, 2 - после чека. Для более высоких - передается в конкретной операции и не актуален. |
PDS → HOLDERS - в RK7 при вызове в Transaction передаются все неудалённые карты этого интерфейса из чека, а при вызове GetCardInfo реализована передача только одной текущей карты. В версии 35 добавлен новый тэг ALLCARDS, в котором передаются все карточки этого интерфейса, о которых есть информация в обрабатываемом заказе (не только чеке). В RK7 это карточки, прописанные в скидках и оплатах для данного интерфейса. Но не передаётся карточка, по которой идёт сейчас обращение(если это первое обращение), эта карточка прописывается в атрибут cardcode в тэге INTERFACE, если вызов GetCardInfo, при вызове Transaction не заполняется.
PDS → ALLCARDS → ITEM и PDS → HOLDERS → ITEM - тег элемента списка с карточкой в атрибуте cardcode.
При интеграции со Спасибо RK7 в PDS → HOLDERS добавляет код карты, вытащенный из дополнительной информации по платежу, если платёж карточкой Сбербанка и драйвер терминала авторизации заполнил в ExtTransactionInfo «PdsCard=». Для включения этой опции в RK7 в свойстве «Pass All Receipts XML Data» интерфейса pdsempty.dll должно стоять не «By script»
атрибут | тип | обязательное | описание |
---|---|---|---|
cardcode | String | - |
EXTDATA
Этот тэг содержит информацию не связанную с заказом, а связанную с контекстом общения с внешней системой. Информация, которая запрашивается у оператора для нужд интеграции, может быть передана в этом тэге. Информация, сообщённая клиентом и введённая в специальный диалог (например код авторизации, присланный клиенту в СМС для двухстадийной авторизации), передаётся в атрибуте clientinfoinput, начиная с 27. Тип информации в clientinfoinput может быть передан в атрибуте tag, заполнение которого происходит по указанию внешней системы. Для запроса этой информации внешняя система должна вернуть специальный XML с тэгом dialog.
CHECKDATA
содержимое чека
атрибут | тип | обязательное | описание |
---|---|---|---|
ordernum | String | + | номер заказа |
orderguid | String | - | GUID заказа |
guests | Integer | количество гостей | |
checknum | String | - | номер чека, на момент передачи может отсутствовать, появляется только если чек распечатан |
tablename | String | - | номер стола, может отсутствовать |
order_cat | String | - | ver 1.5 категория заказа (код), может отсутствовать |
order_type | String | - | ver 1.5 тип заказа (код), может отсутствовать |
startservice | XMLDate | + | время начала обслуживания |
closedatetime | XMLDateTime | - | время окончания обслуживания, передается только если обслуживание завершено |
checkguid | String | - | GUID в формате {XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX} |
printnum | String | - | Печатный номер чека, с версии 30 |
extfiscid | String | - | Серийный номер ФР, с версии 30 |
delprintnum | String | - | Печатный номер документа удаления чека, с версии 31 |
fiscdocnum | String | - | Фискальный номер документа для печати чека, с версии 32 |
delfiscdocnum | String | - | Фискальный номер документа удаления чека, с версии 32 |
persistentcomment | String | - | сохраняемый комментарий к визиту, с версии 34 |
CHECKPERSONS, CHECKLINES, CHECKCATEGS, CHECKDISCOUNTS, CHECKBONUSES CHECKPAYMENTS
теги по типам строк чеков и их вложенные теги
сount | Integer | + | счетчик количества элементов |
атрибут | тип | обязательное | описание |
---|---|---|---|
тег: PERSON, элемент CHECKPERSONS | |||
id | String | + | ID объекта справочника2 |
name | String | + | текст - имя кассира/официанта |
role | String | + | код роли |
code | String | + | код объекта справочника |
тег: LINE, элемент CHECKLINES | |||
id | String | + | ID объекта справочника |
uni | String | - | идентификатор линии |
parent | String | - | ссылка на родительский идентификатор линии |
type | String | + | тип строки3 |
name | String | + | текст - то что в чеке4 |
code | String | + | код объекта справочника |
quantity | Real | + | количество элементов в строке чека |
price | Real | + | цена по действующему прейскуранту (до скидок, наценок) |
sum | Real | + | сумма после скидок/наценок |
servprint | String | - | название категории классификации сервис печати5 |
servprint_id | String | + | ID категории классификации сервис печати6 |
categ | String | - | название категории для отчетов |
categ_id | String | + | ver 2.2 ID категории. Заполняется из классификации, которая указана в параметре Классификация для КДС и VDU. Вместо него можно использовать:
|
тег: DISCOUNTPART, элемент DISCOUNTS | |||
id | String | + | |
disclineuni | Integer | + | |
sum | Real | + | |
тег: CATEG, элемент CHECKCATEGS | |||
id | String | + | ID категории классификации сервис печати |
code | String | + | код категории классификации сервис печати |
sum | Real | + | оплаченная сумма |
discsum | Real | + | сумма фактических скидок по этой категории |
name | String | + | название |
тег: BONUS, элемент BONUSES (ver 1.4) | |||
id | String | + | ID скидки |
code | String | + | код скидки |
sum | Real | + | сумма рассчитанного бонуса |
name | String | + | название |
cardcode | String | - | код карты |
interface | Integer | - | интерфейс (в RK7 код логического интерфейса) |
uni | String | - | идентификатор линии (скидки) |
тег: DISCOUNT, элемент CHECKDISCOUNTS | |||
id | String | + | ID скидки |
code | String | + | код скидки |
sum | Real | + | сумма скидки фактически примененной7 |
name | String | + | название |
cardcode | String | - | код карты |
interface | Integer | - | интерфейс (в RK7 код логического интерфейса) |
uni | String | - | ver 1.4 идентификатор линии в заказе |
objectuni | String | - | ver 1.4 идентификатор линии объекта (линии блюда), может быть пустым, если скидка на весь чек (в том числе на категорию блюд) |
тег: PAYMENT, элемент CHECKPAYMENTS | |||
code | String | + | код валюты |
sum | Real | + | сумма внесенная в этой валюте8 |
bsum | Real | - | сумма внесенная в базовой валюте, должна совпадать с суммой sum по LINE9 |
name | String | + | название элемента в строке |
interface | Integer | - | интерфейс (в RK7 код логического интерфейса) |
cardcode | String | - | код карты |
ownerinfo | String | - | авторизованное имя гостя |
uni | String | - | ver 1.4 идентификатор линии |
exttransactioninfo | String | - | ver 1.4 внешняя информация о транзакции, например, информация от терминала авторизации |
paytype | Integer | - | признак типа оплаты (1 - наличные 2 - банковские карты 3 - прочее) |
Для не-распределяемых наценок в случае наличия связи скидки с интерфейсом писать не только в строки типа dish но и в CHECKDISCOUNTS
Атрибут Type
Типы строк в содержимом чека:
undefined - произвольный элемент
dish - строка блюда
combo - комбо блюдо
modify - модификатор
ticket - билет
Комбо-блюда записываются так: комбоконтейнер с типом modify а на него ссылаются строки с типом dish.
Пример XML документа
<?xml version="1.0" encoding="utf-8"?>
<--
possible variation:
<?xml version="1.0" encoding="IBM866"?>
-->
<CHECK chmode="4" stationcode="5" restaurantcode="722500001" cashservername="RLSERV" generateddatetime="2012-04-15T21:32:00" shiftdate="xmldate" shiftnum="int">
<EXTINFO reservation="49">
<EXTDATA select="12,123" clientinfoinput="123412" tag="AUTHCODE"/>
<INTERFACES current="12348">
<INTERFACE type="PDS" id="12348" mode="3" interface="8" cardcode="11307">
<HOLDERS>
<ITEM cardcode="11307"/>
</HOLDERS>
<ALLCARDS>
<ITEM cardcode="-999999999"/>
<ITEM cardcode="ucs1"/>
<ITEM cardcode="9511234567"/>
</ALLCARDS>
</INTERFACE>
<INTERFACE type="VIDEO" id="1"/>
<INTERFACE type="KDS" posid="132" id="3"/>
</INTERFACES>
</EXTINFO>
<CHECKDATA checknum="102628" guests="2" tablename="1028" startservice="2012-04-15T20:32:00" closedatetime="2012-04-15T21:30:00" ordernum="2944804.1" >
<CHECKPERSONS count="2">
<PERSON role="K" name="Вдовин Б.А." code="1234" />
<PERSON role="W" name="Вдовина А.А." code="3654" />
</CHECKPERSONS>
<CHECKLINES count="3">
<LINE id="432" type="dish" name="Сельдь с гарниром" code="7644" quantity="2.00" price="23.60" sum="27.20" servprint="bar" categ="bar2" stored="1">
<ATTRS>
<ATTR type_id="{338D933D-B332-3339-8334-33B733B3733B}" type_name="some_type" key_id="{D38D99CD-BBE2-4939-8414-DFB78FB3776B}" key_name="some name" value="424rfwer5" />
<ATTR type_id="{344D9344-4432-3444-4444-33B73443733B}" type_name="other_type" key_id="{228229CD-B222-4229-8224-D2278223226B}" key_name="other name" value="rsdfsdfwer5" />
</ATTRS>
<LINETAXES count="2">
<TAX id="2" char="A" sum="3" />
<TAX id="5" char="B" sum="89" />
</LINETAXES>
</LINE>
<LINE id="433242" type="dish" name="Сельдь без гарнира" code="8644" quantity="2.00" price="23.60" sum="27.20" servprint="bar" categ="bar2" last="1" stored="0">
<LINETAXES count="2">
<TAX id="{4DDEC90E-709B-4962-935D-F36B8FBB5B8D};1800" sum="3" />
<TAX id="{1B38B63A-60D9-4162-BFD6-B765CE7E05D5};1000" sum="89" />
</LINETAXES>
<DISCOUNTS count="2">
<DISCOUNTPART id="{0A021EF0-5ED6-45A4-934E-29C8A779B3C2}" sum="-20.00" disclineuni="21214"/>
</DISCOUNTS>
</LINE>
<LINE id="442" parent_line="433242" type="modify" name="без гарнира" code="844" quantity="2.00" price="0" sum="0" servprint="bar" categ="bar2" last="1" stored="0"/>
<LINE id="412" type="ticket" name="Мега фильм" code="84" quantity="1.00" price="23.60" sum="27.20" categ="боевик" ticketkind="простой" stored="0" >
<LINEPROPS custom="values"/>
</LINE>
</CHECKLINES>
<CHECKCATEGS count="2">
<CATEG id="42" code="3" sum="1.17" discsum="0.99" name="FOOD" />
<CATEG id="2" code="3" sum="1.17" discsum="0.99" name="FOOD" />
</CHECKCATEGS>
<CHECKDISCOUNTS count="1">
<DISCOUNT id="4" code="19" sum="-0.18" name="15%" interface="8" cardcode="11301867" account="2312312312" uni="21214"/>
</CHECKDISCOUNTS>
<CHECKBONUSES count="1">
<BONUS id="2" code="12" sum="3" name="2%" interface="9" cardcode="11867" account="2312312312" />
</CHECKBONUSES>
<CHECKPAYMENTS count="2">
<PAYMENT id="32" code="HRCP" paytype="3" sum="0.990" name="Купон HR" interface="8" cardcode="11301867" account="2312312312" ownerinfo="Прибытков Роман Михайлович" extTransactionInfo="12" />
<PAYMENT id="2" code="RUR" paytype="1" sum="200" name="Рубли" />
</CHECKPAYMENTS>
<CHECKTAXES count="2">
<TAX id="2" char="A" code="12" rate="10.00" sum="3" name="НДС" />
<TAX id="2" char="B" code="12" rate="18.00" sum="10" name="НДС" />
<TAX id="5" char="B" code="02" rate="9.00" sum="89" name="НСП" />
</CHECKTAXES>
</CHECKDATA>
</CHECK>
Получение кода текущего интерфейса
function tSailPlayProcessor.CurrentInterfaceID(XML: IXmlDocument):Integer;
var
interfaces:IXmlNodeList;
i:integer;
begin
Result:=XML.DocumentElement.NeedChild('EXTINFO').NeedChild('INTERFACES').GetIntAttr('current');
interfaces:=XML.DocumentElement.NeedChild('EXTINFO').NeedChild('INTERFACES').SelectNodes('INTERFACE');
for i:=0 to interfaces.Count-1 do
if (interfaces[i].GetIntAttr('id',Result)=Result) or (Result=0) then begin
Result:=interfaces[i].GetIntAttr('interface',Result);
Break;
end;
end;
Проверка добавленного купона
function tSailPlayProcessor.GiftExists(XML: IXmlDocument; sku:string):boolean;
var Discount:IXmlNode;
Lines,Discounts:IXmlNodeList;
i,j,CurrentIntf:integer;
begin
CurrentIntf:=CurrentInterfaceID(XML);
Lines:=XML.DocumentElement.NeedChild('CHECKDATA').NeedChild('CHECKLINES').SelectNodes('LINE');
Discounts:=XML.DocumentElement.NeedChild('CHECKDATA').EnsureChild('CHECKDISCOUNTS').SelectNodes('DISCOUNT');
Result:=False;
for i:=0 to Discounts.Count-1 do begin
Discount:=Discounts[i];
if (Discount.GetIntAttr('interface')=CurrentIntf) and (Discount.GetAttr('objectuni')<>'') then
for j:=0 to Lines.Count-1 do begin
if (Lines[j].GetAttr('uni')=Discount.GetAttr('objectuni')) and (Lines[j].GetAttr('code')=sku) then begin
Result:=True;
exit;
end;
end;
end;
end;
Списание купона на транзакции
procedure tSailPlayProcessor.ProcessGifts(XML: IXmlDocument; return: boolean; Connect: ISailPlayLow);
var Discount:IXmlNode;
Lines,Discounts:IXmlNodeList;
i,j,CurrentIntf:integer;
begin
CurrentIntf:=CurrentInterfaceID(XML);
Lines:=XML.DocumentElement.NeedChild('CHECKDATA').NeedChild('CHECKLINES').SelectNodes('LINE');
Discounts:=XML.DocumentElement.NeedChild('CHECKDATA').EnsureChild('CHECKDISCOUNTS').SelectNodes('DISCOUNT');
for i:=0 to Discounts.Count-1 do begin
Discount:=Discounts[i];
if (Discount.GetIntAttr('interface')=CurrentIntf) and (Discount.GetAttr('objectuni')<>'') and
(Discount.GetIntAttr('code')=GiftDiscountCode) then
for j:=0 to Lines.Count-1 do begin
if Lines[j].GetAttr('uni')=Discount.GetAttr('objectuni') then
Connect.GiftTransaction(Discount.GetAttr('cardcode'),
XML.DocumentElement.NeedChild('CHECKDATA').GetAttr('checkguid'),
Lines[j].GetAttr('code'),
return);
end;
end;
end;
Примечание
2) здесь и далее: для RK6 - sifr, для RK7 - GUID
3) undefined - произвольный элемент, dish - строка блюда, combo - комбо-блюдо, modify - модификатор, ticket - билет, excluded - чаевые, не входит в выручку, в чеке нулевая
4) 4
5) , 6) для RK7 - «Классификация для общего сменного отчета»
7) 5
8) 6
9) 7