Автоматический вариант работы с программой Спасибо
В статье описан процесс настройки системы для автоматического начисления и списания балов Спасибо при оплате заказа на кассовой станции.
Настройки в системе
В группу Анализ чека (системы лояльности) добавьте скрипт:
Скриптprocedure
ReceiptXMLAnalysis1001330(AXMLReceiptParameters: TXMLReceiptParameters);
var
p:
integer
;
xml, PaymentTag, ExtInfo, CardInfo:
string
;
begin
xml := AXMLReceiptParameters
.
ReceiptXML;
while
xml <>
''
do
begin
p := pos(
'<PAYMENT '
, xml);
if
p =
0
then
exit;
xml := copy(xml, p, length(xml));
p := pos(
'/>'
, xml);
PaymentTag := copy(xml,
1
, p +
1
);
xml := copy(xml, p +
2
, length(xml));
p := pos(
'exttransactioninfo="BANK:SBRF'
, PaymentTag);
if
p >
0
then
begin
ExtInfo := copy(PaymentTag, p + length(
'exttransactioninfo="'
),
length(PaymentTag));
p := pos(
'"'
, ExtInfo);
ExtInfo := copy(ExtInfo,
1
, p -
1
);
p := pos(
'/PdsCard='
, ExtInfo);
if
p =
0
then
begin
p := pos(
'PdsCard='
, ExtInfo);
if
p =
1
then
CardInfo := copy(ExtInfo,
1
+ length(
'PdsCard='
), length(ExtInfo))
else
CardInfo :=
''
;
end
else
CardInfo := copy(ExtInfo, p + length(
'/PdsCard='
), length(ExtInfo));
if
CardInfo <>
''
then
begin
p := pos(CardInfo,
'/'
);
if
p >
0
then
CardInfo := copy(CardInfo,
1
, p -
1
);
AXMLReceiptParameters
.
CardCode := CardInfo;
AXMLReceiptParameters
.
DoTransfer :=
true
;
AXMLReceiptParameters
.
SilentMode :=
true
;
end
;
end
;
end
;
end
;
- Назначьте скрипт интерфейсу SBRF_Spasibo созданному ранее
Автоматическое списание Спасибо
- В настройках созданного ранее MCR-алгоритма проверьте активность типа устройства Скрипты.
- В свойствах драйвера измените значение параметра RemindLoyalty на WithPayPass
- В настройках параметров самого терминала TlvEdit.exe измените значение параметра Возвращать промежуточный код ответа (DF7D) на По картам Сбербанка:
- В форме где будет использоваться функционал — здесь выбрана Редактирование заказа (быстрый чек) создайте копию предустановленного экземпляра формы, переименуйте ее и сохраните изменения
Откройте редактор формы, выделите компонент CheckView в строке OnOrderVerify добавьте скрипт:
if
AVerifyType = vtAfterPay
then
CheckLoyaltyOnAuthorization;
В самом начале обработчика событий и форм вставьте скрипт
скриптconst
minordersum =
250
;
const
SpasiboCurrencyCode =
126
;
function
ExtractPartFromExtTransactionInfo(ExtTransactionInfo:
String
;
PartName:
String
):
String
;
var
i:
Integer
;
s:
string
;
begin
i:=pos(PartName,ExtTransactionInfo);
if
i>
1
then
begin
i:=pos(
'/'
+PartName,ExtTransactionInfo);
if
i>
0
then
i:=i+
1
;
end
;
if
i=
0
then
s:=
''
else
begin
s:=copy(ExtTransactionInfo,i+length(PartName),
65535
);
i:=pos(
'/'
,s);
if
i>
0
then
SetLength(s,i-
1
);
end
;
Result:=s;
end
;
procedure
PerformLoyalyMCR(PayLine: TPayLine);
var
i:
integer
;
CardCode:
string
;
FirstNumbers:
String
;
LastNumbers:
String
;
BankName:
String
;
begin
CardCode := ExtractPartFromExtTransactionInfo(PayLine
.
ExtTransactionInfo,
'PdsCard='
);
i:=pos(
';'
,CardCode);
if
i >
0
then
begin
LastNumbers:=copy(CardCode,i+
1
,
255
);
SetLength(CardCode, i-
1
);
end
else
LastNumbers:=
''
;
FirstNumbers:=PayLine
.
CardNum;
i:=pos(
'*'
,PayLine
.
CardNum);
if
i>
0
then
SetLength(FirstNumbers, i-
1
);
BankName:=ExtractPartFromExtTransactionInfo(PayLine
.
ExtTransactionInfo,
'BANK:'
);
// Slide a spasibo card
//RK7.PerformMcrAlgorithSilent('BANK:'+BankName+';'+FirstNumbers+';'+LastNumbers+';'+CardCode, 1);
RK7
.
PerformMcrAlgorithSilent(BankName+
':'
+CardCode+
';'
+LastNumbers,
1
);
end
;
function
SpasiboOnAuthorize(PayLine: TPayLine):
Boolean
;
var
i, k:
integer
;
CardCode:
string
;
it: TCheckItem;
McrPay: TMcrPay;
a:
double
;
Editor: TNumEditor;
SpasiboExists:
boolean
;
BankName:
String
;
begin
//Exit; //Uncomment me to disable auto write-off SB SPASIBO
// Looking for payment in tsAuthoring state
Result:=
False
;
a :=
0
;
SpasiboExists :=
False
;
for
i :=
0
to
RKCheck
.
CurrentOrder
.
Sessions
.
LinesCount -
1
do
begin
it := RKCheck
.
CurrentOrder
.
Sessions
.
Lines[i];
if
SYS
.
ObjectInheritsFrom(TObject(it),
'TPayLine'
)
then
begin
if
it
.
Code = trunc(SpasiboCurrencyCode)
then
SpasiboExists :=
True
;
if
(it<>PayLine)
and
(it
.
State <> disClosed)
and
(it
.
State <> disDeleted)
then
a := a + TPayLine(it).BasicSum;
end
;
end
;
if
PayLine =
Nil
then
Exit;
BankName:=ExtractPartFromExtTransactionInfo(PayLine
.
ExtTransactionInfo,
'BANK:'
);
if
(PayLine
.
OriginalSum <= minordersum)
or
SpasiboExists
or
(BankName<>
'SBRF'
)
then
Exit;
// Spasibo card code: between "PdsCard=" and "/"
CardCode := ExtractPartFromExtTransactionInfo(PayLine
.
ExtTransactionInfo,
'PdsCard='
);
if
copy(CardCode,
1
,
1
)=
'H'
then
CardCode := Copy(CardCode,
2
,
255
);
// Slide a spasibo card
PerformLoyalyMCR(PayLine);
Editor := TNumEditor(GUI
.
FindComponentByName(
'Editor'
));
for
i :=
0
to
RKCheck
.
CurrentOrder
.
Sessions
.
McrPays
.
Count -
1
do
begin
McrPay := TMcrPay(RKCheck
.
CurrentOrder
.
Sessions
.
McrPays
.
Items[i]);
// Checking mcr-payment for spasibo card
if
(McrPay
.
CardNum = CardCode)
and
(McrPay
.
Amount >= minordersum -
1
)
then
begin
k := GUI
.
MessageDlgEx(
'Предложите гостю оплатить заказ бонусами "Спасибо". '
+
'К оплате бонусов: '
+ FloatToStr(McrPay
.
Amount), mtInformation,
mbYes + mbNo + mbCancel,
'Полностью;Частично;Не списывать'
);
if
k = ID_YES
then
begin
// Maximum
RKCheck
.
DeleteCheckItem(PayLine);
if
a =
0
then
a := RKCheck
.
CurrentOrder
.
ToPaySum
else
a := RKCheck
.
CurrentOrder
.
ToPaySum - a;
if
a > McrPay
.
Amount
then
a := McrPay
.
Amount
else
a := a -
1
;
Editor
.
Text := FloatToStr(a);
RKCheck
.
CreateCheckItem(rkrefCurrencies, IntToStr(McrPay
.
Code), McrPay
.
CardNum);
Result:=
True
;
end
else
if
k = ID_NO
then
begin
// Partially
RKCheck
.
DeleteCheckItem(PayLine);
Result:=
True
;
end
;
Exit;
end
;
end
;
// Mcr-pay not found, Result=False
end
;
procedure
CheckLoyaltyOnAuthorization;
var
i:
integer
;
it: TCheckItem;
PayLine: TPayLine;
begin
PayLine :=
Nil
;
for
i :=
0
to
RKCheck
.
CurrentOrder
.
Sessions
.
LinesCount -
1
do
begin
it := RKCheck
.
CurrentOrder
.
Sessions
.
Lines[i];
if
SYS
.
ObjectInheritsFrom(TObject(it),
'TPayLine'
)
then
begin
if
TPayLine(it).TransactionStatus = tsAuthorizing
then
PayLine := TPayLine(it)
end
;
end
;
if
PayLine =
Nil
then
Exit;
if
SpasiboOnAuthorize(PayLine)
then
exit;
RK7
.
PerformOperation(rkoReAuhorizePay,
0
);
end
;
minordersum = 250 — минимальная сумма заказа при которой можно использовать оплату баллами "Спасибо", где:
SpasiboCurrencyCode =126 — это код валюты, у которой в качестве интерфейса выбран интерфейс Спасибо. В данном случае, при настройке Extspasibo.ini выбрана валюта с кодом 12
Начиная с версии 7.07.00.277 поддержан режим, когда зарезервированная сумма (рубль) оплачивается обязательно картой и без второго прикладывания карты. В этом случае скрипты такие:скриптconst
minordersum =
2
;
const
SpasiboCurrencyCode =
97
;
const
RESERVE_VALUE =
1.0
;
function
ExtractPartFromExtTransactionInfo(ExtTransactionInfo:
String
;
PartName:
String
):
String
;
var
i:
Integer
;
s:
string
;
begin
i:=pos(PartName,ExtTransactionInfo);
if
i>
1
then
begin
i:=pos(
'/'
+PartName,ExtTransactionInfo);
if
i>
0
then
i:=i+
1
;
end
;
if
i=
0
then
s:=
''
else
begin
s:=copy(ExtTransactionInfo,i+length(PartName),
65535
);
i:=pos(
'/'
,s);
if
i>
0
then
SetLength(s,i-
1
);
end
;
Result:=s;
end
;
procedure
PerformLoyalyMCR(PayLine: TPayLine);
var
i:
integer
;
CardCode:
string
;
FirstNumbers:
String
;
LastNumbers:
String
;
BankName:
String
;
begin
CardCode := ExtractPartFromExtTransactionInfo(PayLine
.
ExtTransactionInfo,
'PdsCard='
);
i:=pos(
';'
,CardCode);
if
i >
0
then
begin
LastNumbers:=copy(CardCode,i+
1
,
255
);
SetLength(CardCode, i-
1
);
end
else
LastNumbers:=
''
;
FirstNumbers:=PayLine
.
CardNum;
i:=pos(
'*'
,PayLine
.
CardNum);
if
i>
0
then
SetLength(FirstNumbers, i-
1
);
BankName:=ExtractPartFromExtTransactionInfo(PayLine
.
ExtTransactionInfo,
'BANK:'
);
// Slide a spasibo card
//RK7.PerformMcrAlgorithSilent('BANK:'+BankName+';'+FirstNumbers+';'+LastNumbers+';'+CardCode, 1);
RK7
.
PerformMcrAlgorithSilent(BankName+
':'
+CardCode+
';'
+LastNumbers,
1
);
end
;
function
PartialSpasiboPay(PayLine: TPayLine; MCRPay: TMCRPay; prepaid:
double
; toPay:
double
):
boolean
;
var
sourceValue, a:
double
;
peio: TPayExtraInfoObj;
Editor: TNumEditor;
CurrCode:
integer
;
begin
Editor := TNumEditor(GUI
.
FindComponentByName(
'Editor'
));
peio := payLine
.
GetExtraInfoObj();
sourceValue := payLine
.
BasicSum;
CurrCode := PayLine
.
RefItem
.
Code;
RKCheck
.
DeleteCheckItem(PayLine);
Editor
.
Text := FloatToStr(toPay);
RKCheck
.
CreateCheckItem(rkrefCurrencies, IntToStr(McrPay
.
Code), McrPay
.
CardNum);
a := RKCheck
.
CurrentOrder
.
ToPaySum - prepaid - toPay;
if
a > sourceValue
then
a := sourceValue;
Editor
.
Text :=
''
;
RKCheck
.
CreatePayLine(CurrCode, a, peio);
Result :=
True
;
end
;
function
SpasiboOnAuthorize(PayLine: TPayLine):
Boolean
;
var
i, k:
integer
;
CardCode:
string
;
it: TCheckItem;
McrPay: TMcrPay;
prepaid:
double
;
SpasiboExists:
boolean
;
BankName:
String
;
toPay:
double
;
newValStr:
string
;
a:
double
;
begin
//Exit; //Uncomment me to disable auto write-off SB SPASIBO
Result:=
False
;
prepaid :=
0
;
SpasiboExists :=
False
;
for
i :=
0
to
RKCheck
.
CurrentOrder
.
Sessions
.
LinesCount -
1
do
begin
it := RKCheck
.
CurrentOrder
.
Sessions
.
Lines[i];
if
SYS
.
ObjectInheritsFrom(TObject(it),
'TPayLine'
)
then
begin
if
it
.
Code = trunc(SpasiboCurrencyCode)
then
SpasiboExists :=
True
;
if
(it<>PayLine)
and
(it
.
State <> disClosed)
and
(it
.
State <> disDeleted)
then
prepaid := prepaid + TPayLine(it).BasicSum;
end
;
end
;
if
PayLine =
Nil
then
Exit;
BankName:=ExtractPartFromExtTransactionInfo(PayLine
.
ExtTransactionInfo,
'BANK:'
);
//gui.showmessage('BankName: '+BankName+' paid='+floattostr(prepaid));
if
(PayLine
.
OriginalSum <= minordersum)
or
SpasiboExists
or
(BankName<>
'SBRF'
)
then
Exit;
// Spasibo card code: between "PdsCard=" and "/"
CardCode := ExtractPartFromExtTransactionInfo(PayLine
.
ExtTransactionInfo,
'PdsCard='
);
if
copy(CardCode,
1
,
1
)=
'H'
then
CardCode := Copy(CardCode,
2
,
255
);
// Slide a spasibo card
PerformLoyalyMCR(PayLine);
//gui.showmessage('McrPays.Count= '+inttostr(RKCheck.CurrentOrder.Sessions.McrPays.Count));
for
i :=
0
to
RKCheck
.
CurrentOrder
.
Sessions
.
McrPays
.
Count -
1
do
begin
McrPay := TMcrPay(RKCheck
.
CurrentOrder
.
Sessions
.
McrPays
.
Items[i]);
// Checking mcr-payment for spasibo card
if
(McrPay
.
CardNum = CardCode)
and
(McrPay
.
Amount >= minordersum - RESERVE_VALUE)
then
begin
a := prepaid;
if
a < RESERVE_VALUE
then
a := RESERVE_VALUE;
toPay := RKCheck
.
CurrentOrder
.
ToPaySum - a;
if
toPay > McrPay
.
Amount
then
toPay := McrPay
.
Amount;
repeat
k := GUI
.
MessageDlgEx(
'Предложите гостю оплатить заказ бонусами "Спасибо". '
+
'Можно потратить бонусов: '
+ FloatToStr(toPay), mtInformation,
mbYes + mbNo + mbCancel,
'Полностью;Частично;Не списывать'
);
if
k = ID_YES
then
Result := PartialSpasiboPay(PayLine, McrPay, prepaid, toPay)
else
if
k = ID_NO
then
begin
// Partially
newValStr := gui
.
InputBox(
''
,
'Введите сумму баллов "Спасибо", которую надо потратить, не менее '
+FloatToStr(minordersum - RESERVE_VALUE), floattostr(toPay),
true
);
a := StrToFloat(newValStr);
if
a < minordersum -
1
then
begin
gui
.
showMessage(
'Слишком маленькая сумма, нельзя тратить менее '
+FloatToStr(minordersum - RESERVE_VALUE));
end
else
begin
if
a > toPay
then
a := toPay;
Result := PartialSpasiboPay(PayLine, McrPay, prepaid, a);
Exit;
end
;
end
;
until
k <> ID_NO;
Exit;
end
;
end
;
// Mcr-pay not found, Result=False
end
;
procedure
CheckLoyaltyOnAuthorization;
var
i:
integer
;
it: TCheckItem;
PayLine: TPayLine;
begin
PayLine :=
Nil
;
// Looking for payment in tsAuthoring state
for
i :=
0
to
RKCheck
.
CurrentOrder
.
Sessions
.
LinesCount -
1
do
begin
it := RKCheck
.
CurrentOrder
.
Sessions
.
Lines[i];
if
SYS
.
ObjectInheritsFrom(TObject(it),
'TPayLine'
)
then
begin
if
TPayLine(it).TransactionStatus = tsAuthorizing
then
PayLine := TPayLine(it)
end
;
end
;
if
PayLine =
Nil
then
Exit;
if
SpasiboOnAuthorize(PayLine)
then
exit;
RK7
.
PerformOperation(rkoReAuhorizePay,
0
);
end
;
- Сохраните изменения
Модифицированную форму назначьте для схемы форм, которая будет применяться на станции
Настроенную схему форм добавьте в использование.
Пользовательский сценарий работы на кассовой станции
В данном примере использован сценарий работы в быстром чеке.
- Наполните заказ позициями меню
Если стоимость заказа меньше указанного в скрипте значение const minordersum = 250 — процесс расчета аналогичен классической оплате по банковской карте, при выборе формы чека с настроенной информацией о статусах в системе "Спасибо" можно наблюдать количество начисленных балов - Нажмите кнопку Оплатить Рубли > Кредитные карты > Валюта VISA
- Будет получено сообщение о подтверждении операции
Подтверждение можно исключить, если назначить валюте Автозаполнение в значение Вся сумма. - Согласитесь с подтверждением, далее произойдет оплата:
- После настроек печати чека вы увидите начисление баллов Спасибо, при печати
- Сумма заказа превышает порог, назначенный переменной minordersum, в нашем случае это 250 рублей.
После прохождения Оплатить Рубли > Кредитные карты > Валюта VISA будет получено сообщение, формируемое в скрипте: - От выбора кнопки зависит дальнейший расчет:
- Полностью — бонусами оплачивается вся сумма минус 1 рубль, его оплачиваем наличными или банковской картой
- Частично — укажите сумму частичной оплаты балами и выберите валюту, указанную при настройке Extspasibo.ini для оплаты балами Спасибо. В данном случае выбрана валюта с кодом 126
Остаток доплатите рублями- Не списывать — простая оплата картой, с начислением баллов по программе "Спасибо"
- Полностью — бонусами оплачивается вся сумма минус 1 рубль, его оплачиваем наличными или банковской картой