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 документа

тег верхнего уровня

атрибуттипобязательноеописание
stationcodeString+код станции, на которой сгенерирован документ
restaurantcodeString+код ресторана, в котором сгенерирован документ
cashservernameString+имя (сетевое) кассового сервера, на котором сгенерирован документ
generateddatetimeXMLDateTime+время генерации
chmodeInteger-режим чека (см ниже), с версии 1.4 типы 0-10, до версии 1.4 поддерживались типы 0-4
localeInteger-Windows locale клиента, с версии 2.4, см. https://msdn.microsoft.com/en-us/goglobal/bb896001.aspx, число из первой колонки надо перевести в десятичное
shiftdatexmldate-с версии 2.6, дата смены
shiftnuminteger-с версии 2.6, номер смены
protocolversionString+/27с версии 27, версия протокола, поддерживаемая клиентом FarCards - генератором XML
clientappString+/27с версии 27, Имя приложения-клиента FarCards, генератора XML (RK6, RK7, Shelter, …)
clientversionString+/27с версии 27, Версия приложения-клиента FarCards, генератора XML (RK6, RK7, Shelter, …)

Допустимые значения атрибута chmode и их описание:

ЧислоКонстантаОписаниеКомментарий
0XMLchmodeNotCheckне чек (вызов вне чека или технический вызов для получения, например, только имени клиента)в GetCardInfo - короткий XML и в Transaction, если вызвано через SimpleTransaction (из скрипта)
1XMLchmodeSaleоплата (касса проводит операцию оплаты заказа)в GetCardInfo перед транзакцией и в Transaction
2XMLchmodeSaleRollbackоткат (касса не смогла завершить все этапы оплаты корректно, но ранее интерфейс подтвердил успешную транзакцию)в GetCardInfo перед транзакцией и в Transaction
3XMLchmodeReturnвозврат (возврат чека после успешного оформления)в GetCardInfo перед транзакцией и в Transaction
4XMLchmodeReturnRollbackоткат возврата (касса не смогла завершить все этапы возврата корректно, но ранее интерфейс подтвердил успешную транзакцию возврата)в GetCardInfo перед транзакцией и в Transaction
5XMLchmodeOrderEditingрежим заказа (заказ не завершен)в GetCardInfo (заказ может быть незавершен)
6XMLchmodeOrderBillпечать пречека (заказ не завершен, но готов к завершению)в GetCardInfo при макетировании и в Transaction (в режиме «все чеки/пречеки в farcards»)
7XMLchmodeOrderCalcрежим расчета (заказ не завершен, но готов к завершению)в GetCardInfo
8XMLchmodePrintCardInfoпечать инфо о карте, возможно, не из заказа - в GetCardInfo
9XMLchmodeInitEntranceCardOrderсоздание заказа в «карте на входе»в GetCardInfo (перед заказом, для запроса информации для создания заказа) - короткий XML
10XMLchmodePrintAfterTransactionпосле транзакций для печати слиповв GetCardInfo короткий XML
11XMLchmodeServPrintсервис-печать (заказ не завершен)(иногда там могут быть скидки с персональной информацией), начиная с версии 1.5
12XMLchmodeCancelBillотмена пречека (заказ не завершен)начиная с версии 2.4
13XMLchmodeBeforeReceiptперед транзакцияминачиная с версии 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 >
CODE

EXTINFO

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

Допустимые теги:
VIDEO - для систем видео-наблюдения

атрибуттипобязательноеописание
interfaceInteger+номер интерфейса внешней системы в БД кассы


KDS - для KDS/VDU

атрибуттипобязательноеописание
interfaceInteger+номер интерфейса внешней системы в БД кассы


PDS - для систем лояльности

атрибуттипобязательноеописание
idInteger+внутренний идентификатор интерфейса внешней системы в БД кассы, обрабатывающей этот идентификатор
interfaceInteger-код интерфейса внешней системы в БД кассы, обрабатывающей этот идентификатор, используется для поиска «своих» платежей и скидок по атрибутам interface
modeInteger-для протоколов < 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»

атрибуттипобязательноеописание
cardcodeString-

EXTDATA

Этот тэг содержит информацию не связанную с заказом, а связанную с контекстом общения с внешней системой. Информация, которая запрашивается у оператора для нужд интеграции, может быть передана в этом тэге. Информация, сообщённая клиентом и введённая в специальный диалог (например код авторизации, присланный клиенту в СМС для двухстадийной авторизации), передаётся в атрибуте clientinfoinput, начиная с 27. Тип информации в clientinfoinput может быть передан в атрибуте tag, заполнение которого происходит по указанию внешней системы. Для запроса этой информации внешняя система должна вернуть специальный XML с тэгом dialog.

CHECKDATA

содержимое чека

атрибуттипобязательноеописание
ordernumString+номер заказа
orderguidString-GUID заказа
guestsIntegerколичество гостей
checknumString-номер чека, на момент передачи может отсутствовать, появляется только если чек распечатан
tablenameString-номер стола, может отсутствовать
order_catString-ver 1.5 категория заказа (код), может отсутствовать
order_typeString-ver 1.5 тип заказа (код), может отсутствовать
startserviceXMLDate+время начала обслуживания
closedatetimeXMLDateTime-время окончания обслуживания, передается только если обслуживание завершено
checkguidString-GUID в формате {XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}
printnumString-Печатный номер чека, с версии 30
extfiscidString-Серийный номер ФР, с версии 30
delprintnumString-Печатный номер документа удаления чека, с версии 31
fiscdocnumString-Фискальный номер документа для печати чека, с версии 32
delfiscdocnumString-Фискальный номер документа удаления чека, с версии 32
persistentcommentString-сохраняемый комментарий к визиту, с версии 34

CHECKPERSONS, CHECKLINES, CHECKCATEGS, CHECKDISCOUNTS, CHECKBONUSES CHECKPAYMENTS

теги по типам строк чеков и их вложенные теги

сountInteger+счетчик количества элементов
атрибуттипобязательноеописание
тег: PERSON, элемент CHECKPERSONS
idString+ID объекта справочника2
nameString+текст - имя кассира/официанта
roleString+код роли
codeString+код объекта справочника
тег: LINE, элемент CHECKLINES
idString+ID объекта справочника
uniString-идентификатор линии
parentString-ссылка на родительский идентификатор линии
typeString+тип строки3
nameString+текст - то что в чеке4
codeString+код объекта справочника
quantityReal+количество элементов в строке чека
priceReal+цена по действующему прейскуранту (до скидок, наценок)
sumReal+сумма после скидок/наценок
servprintString-название категории классификации сервис печати5
servprint_idString+ID категории классификации сервис печати6
categString-название категории для отчетов
categ_idString+ver 2.2 ID категории
тег: DISCOUNTPART, элемент DISCOUNTS
idString+
disclineuniInteger+
sumReal+
тег: CATEG, элемент CHECKCATEGS
idString+ID категории классификации сервис печати
codeString+код категории классификации сервис печати
sumReal+оплаченная сумма
discsumReal+сумма фактических скидок по этой категории
nameString+название
тег: BONUS, элемент BONUSES (ver 1.4)
idString+ID скидки
codeString+код скидки
sumReal+сумма рассчитанного бонуса
nameString+название
cardcodeString-код карты
interfaceInteger-интерфейс (в RK7 код логического интерфейса)
uniString-идентификатор линии (скидки)
тег: DISCOUNT, элемент CHECKDISCOUNTS
idString+ID скидки
codeString+код скидки
sumReal+сумма скидки фактически примененной7
nameString+название
cardcodeString-код карты
interfaceInteger-интерфейс (в RK7 код логического интерфейса)
uniString-ver 1.4 идентификатор линии в заказе
objectuniString-ver 1.4 идентификатор линии объекта (линии блюда), может быть пустым, если скидка на весь чек (в том числе на категорию блюд)
тег: PAYMENT, элемент CHECKPAYMENTS
codeString+код валюты
sumReal+сумма внесенная в этой валюте8
bsumReal-сумма внесенная в базовой валюте, должна совпадать с суммой sum по LINE9
nameString+название элемента в строке
interfaceInteger-интерфейс (в RK7 код логического интерфейса)
cardcodeString-код карты
ownerinfoString-авторизованное имя гостя
uniString-ver 1.4 идентификатор линии
exttransactioninfoString-ver 1.4 внешняя информация о транзакции, например, информация от терминала авторизации
paytypeInteger-признак типа оплаты (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>
XML

Получение кода текущего интерфейса

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;
DELPHI

Проверка добавленного купона

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;
DELPHI


Списание купона на транзакции

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;
DELPHI

Примечание

1) 1
2) здесь и далее: для RK6 - sifr, для RK7 - GUID
3) undefined - произвольный элемент, dish - строка блюда, combo - комбо-блюдо, modify - модификатор, ticket - билет, excluded - чаевые, не входит в выручку, в чеке нулевая
4) 4
5) , 6) для RK7 - «Классификация для общего сменного отчета»
7) 5
8) 6
9) 7