Отличительной особенностью кассового аппарата MG-T707TS является его способность работать без использования специального OLE драйвера, как это обычно делается в 1С. Вместо драйвера можно использовать протокол Http — внутри кассового аппарата работает Web-сервер, к которому можно обращаться через локальную сеть с помощью Get и Post запросов. В 1С версий 8.х можно все операции провести встроенными средствами, а вот в «семерке» встроенных средств не хватает, но это легко обходится компонентами, доступными в Windows-среде.
Наверное, самая сложная часть процесса привязки аппарата к конфигурации это авторизация. Сервер поддерживает дайджест-авторизацию, отправка запроса происходит в два этапа: сначала делается отправка запроса к нужному ресурсу без заголовков, в ответ приходит код ошибки 401, в заголовке «WWW-Authenticate» ответа приходит дайджест, это строка примерно такого содержания:
Digest username="service", realm="HTROM", nonce="527b004c29df30afd42c9dbf43dcb6d9", uri="/cgi/state", algorithm=MD5, response="3f4f49f5adefafdf19ce9148103486af", opaque="60DB81DD", qop=auth, nc=00000001, cnonce="669bcf2a9b1c9deb" User-Agent: test
Из полученного дайджеста нужно взять несколько параметров: realm, nonce, algorithm, opaque, qop, скомпоновать новый дайджест с логином и паролем и уже используя его повторить запрос к серверу.
Пример функции, формирующей строку дайджеста,
предполагается что исходный дайджест преобразован
в список значений optionsList,
также понадобится функция вычисления хеша строки,
в этом примере MD5().
Function getAuthorizationHeader(optionsList)
user = "service";
pass = "751426";
nc = "00000001";
cnonce = "669bcf2a9b1c9deb";
uri = optionsList.Get("uri");
realm = optionsList.Get("realm");
nonce = optionsList.Get("nonce");
algorithm = optionsList.Get("algorithm");
opaque = optionsList.Get("opaque");
qop = optionsList.Get("qop");
method = optionsList.Get("httpMethod");
A1 = ""+user+":"+realm+":"+pass;
md5A1 = Lower(StrReplace(MD5(A1), " ", ""));
A2 = ""+method+":"+uri;
md5A2 = Lower(StrReplace(MD5(A2), " ", ""));
A3 = ""+md5A1+":"+nonce+":"+nc+":"+cnonce+":"+qop+":"+md5A2;
response = Lower(StrReplace(MD5(A3), " ", ""));
authorization = "Digest username="""+user+""", "+
"realm="""+realm+""", "+
"nonce="""+nonce+""", "+
"uri="""+uri+""", "+
"algorithm="""+algorithm+""", "+
"response="""+response+""", "+
"opaque="""+opaque+""", "+
"qop="""+qop+""", "+
"nc="""+nc+""", "+
"cnonce="""+cnonce+"""";
Return authorization;
EndFunction
Для работы по Http протоколу можно использовать доступный во всех версиях Windows — WinHttp, вот полный пример функции, делающей Get запрос и возвращающей текст ответа сервера:
Переменная HOST содержит сетевой адрес кассового аппарата
Function GET(resourse)
uri = "http://"+HOST+resourse;
winHttp = CreateObject("WinHttp.WinHttpRequest.5.1");
winHttp.Open("GET", uri, 0);
winHttp.SetRequestHeader("Host", HOST);
Try
winHttp.Send();
httpStatus = winHttp.Status();
If (httpStatus = 401) OR (httpStatus = 200) Then
digest = winHttp.GetResponseHeader("WWW-Authenticate");
optionsList = parseString(digest);
optionsList.Set("uri", uri);
optionsList.Set("httpMethod", "GET");
authorization = getAuthorizationHeader(optionsList);
winHttp.Open("GET", uri, 0);
winHttp.SetRequestHeader("Authorization", authorization);
winHttp.SetRequestHeader("User-Agent", "programmer");
winHttp.Send();
Return winHttp.ResponseText();
Else
Message("GET resourse: "+resourse+" ----> "+httpStatus+" "+winHttp.StatusText(), "!");
EndIf;
Except
Message("WinHttp GET error: "+GetErrorDescription(), "!");
Message(" ---> uri: "+uri, "!");
EndTry;
Return "";
EndFunction
Ответы от сервера приходят в виде JSON объектов, по этому, для удобства разбора ответа, кодов ошибок, понадобится парсер в список значений, однако в простейшем варианте это необязательно. Сообщение об ошибке может быть примерно такого вида:
{"err":{"e":"xC2","line":1}}
Здесь указан код ошибки, список кодов есть в документации, и указана строка запроса, к которой относится сообщение. Видно, что содержание понятно и без дополнительной обработки.
Также можно обойтись и без парсера в обратную сторону — для отправки запроса на аппарат текст должен быть сформирован в JSON-формате. Пример запроса на печать фискального чека:
{"F":[{"N":{"cm":"РН-011922"}},{"S":{"qty":1.000,"price":30.00,"name":"Кофе ЯКОБС МОНАРХ 60гр. раст.","code":1,"tax":1}},{"P":{"no":1}}]}
Аналогичным образом происходит формирование отчетов, служебные операции, тест состояния.