(function ($) {
"use strict";
var kaspi = function () {
var o = this;
};
var p = kaspi.prototype;
p.webroot = '/'+window.location.pathname.split('/')[1]+'/';
p.url = ''; //адрес терминала
p.name = '';//имя кассы для идентификации/регистрации в терминале
p.state = 0; //состояние(зарегистрированна касса или нет)
p.accessToken = null;//токен доступа
p.refreshToken = null;//токен для обновления токена доступа
p.expirationDate = null;//срок годности токена доступа
p.headers = {
'accesstoken':''
};//заголовки
p.processId = null;//идентификатор процесса продажи
p.transactionId = null;//идентификатор завершённой транзакции(привязывается к чеку внешней системы)
p.transactionMethod = null;//метод оплаты проведенной транзакции
p.timerId = null;//идентификатор таймера(по секундный)
p.waiting_time = 0;//показатель секунд прошедших в ожидании
p.timeout = 240;//лимит ожидания в секундах
p.timeoutId = null;//идентификатор таймера опроса терминала
p.kaspi_qr = null;//признак включеного kaspi qr в настройках внешней системы
p.next_action = null;//метод внешней системы
p.next_action_args = null;//метод внешней системы
p.next_kkm = null;//терменал для последовательной работы
p.load_finish = null;
p.refund_data = null;
p.refund_check_data = null;
p.repeat_func = null;
p.repeat_data = null;
p.control_print_check = null;//элемент управления признаком печати чека внешней системы
//инициализация
p.init = async function(url, kaspi_qr, next_action, next_kkm, print_check) {
if (!p.isEmpty(url)) p.url = url;
if (!p.isEmpty(kaspi_qr)) p.kaspi_qr = kaspi_qr;
if (!p.isEmpty(next_action)) p.next_action = next_action;
if (next_kkm) p.next_kkm = next_kkm;
else p.next_kkm = null;
if (print_check) p.control_print_check = print_check;
p.load('start');
// console.log(p.kaspi_qr);
// console.log(p.next_action);
// console.log(p.state);
// console.log(p.accessToken);
return $.post(p.webroot + 'Kaspi_api/kaspi/get_state',{},
function(data){
//console.log(data);
if (p.is_json(data)) {
var obj = JSON.parse(data);
if (!p.isEmpty(obj['accessToken'])) {
p.set_state(obj);
}
}
p.load('finish');
});
}
//устанавливаем состояние для интеграции из сессии сервера внешней системы
p.set_state = function(data) {
p.state = 0;
p.accessToken = null;
p.refreshToken = null;
p.expirationDate = null;
if (data) {
if (!p.isEmpty(data['accessToken'])) {
p.state = 1;
p.name = data['name'];
p.accessToken = data['accessToken'];
p.refreshToken = data['refreshToken'];
p.expirationDate = data['expirationDate'];
}
p.transactionId = data['transactionId'];
}
p.reflect_button_connect();
if(p.url) {
//const expirationDate = new Date('2023-08-25 15:20:18');
const expirationDate = new Date(p.expirationDate);
const now = new Date();
if (expirationDate <= now) {//если токен доступа устарел - обновляем
p.revoke({
url:p.url,
name:p.name
});
}
}
if (!p.isEmpty(localStorage.getItem('kaspi_repeat_data'))) {
var repeat_data = JSON.parse(localStorage.getItem('kaspi_repeat_data'));
console.log(repeat_data['transactionId']);
if (!p.isEmpty(repeat_data['transactionId'])) {
p.repeat();
} else {
p.remove_refund_data();
}
}
}
//регистрация или обновление связи с терминалом в настройках внешней системы
p.connect = function(data) {
if (p.state) p.revoke(data);
else p.register(data);
};
//регистрация кассы внешней системы в терминале
p.register = function(data) {
p.url = data.url;
p.load('start');
$.get(p.url + '/register?name='+data.name,
function(response){
//console.log(response);
if (!p.isEmpty(response['accessToken'])) {
p.update_session(response);
p.set_state(response);
ajax_msg('main_kaspi', 'success', 'KASPI POS: Подключение прошло успешно. Не забудьте нажать кнопку Сохранить', 2);
} else {
ajax_msg('main_kaspi', 'danger', 'KASPI POS: Терминал отклонил попытку подключения или недоступен', 2);
}
p.load('finish');
}).fail(function(xhr, status, error) {
//console.log(xhr);console.log(status);console.log(data);
ajax_msg('main_kaspi', 'danger', p.error_message(xhr), 2);
p.load('finish');
});
};
//обновление токена доступа внешней системы к терминалу
p.revoke = function(data) {
p.url = data.url;
console.log(p.url + '/revoke?name='+data.name+'&refreshToken='+p.refreshToken);
p.load('start');
$.Query(p.url + '/revoke?name='+data.name+'&refreshToken='+p.refreshToken,
function(response){
//console.log(response);
if (!p.isEmpty(response['accessToken'])) {
p.update_session(response);
p.set_state(response);
ajax_msg('main_kaspi', 'success', 'KASPI POS: Подключение обновлено успешно', 2);
} else {
ajax_msg('main_kaspi', 'danger', 'KASPI POS: Терминал отклонил попытку подключения', 2);
}
p.load('finish');
}).fail(function(xhr, status, error) {
if (xhr.responseJSON) {
p.reset_session();
p.set_state();
}
console.log(xhr);console.log(status);console.log(error);
ajax_msg('main_kaspi', 'danger', p.error_message(xhr), 2);
p.load('finish');
});
};
//старт процесса продажи на терминале
p.payment = function(data) {
//console.log(data);
p.headers.accesstoken = p.accessToken;
$.Query(p.url + '/payment?amount='+data.amount+'&owncheque=false',
function(data){
console.log(data);
if (!p.isEmpty(data['processId'])) {
p.processId = data['processId'];
p.polling();
$('#kaspiProcess').modal('show');
} else {
ajax_msg('main_kaspi', 'danger', 'KASPI POS: Терминал отклонил попытку подключения или недоступен', 2);
$("#btn_new_client").removeClass('noLink');
}
p.load('finish');
}).fail(function(xhr, status, error) {
console.log(xhr);console.log(status);console.log(data);
ajax_msg('main_kaspi', 'danger', p.error_message(xhr), 2);
$("#btn_new_client").removeClass('noLink');
p.stop_timer();
});
};
p.start_refund = function(args, data, callback) {
// console.log('start_refund');
// console.log(args);
// console.log(p.next_action_args);
// console.log(p.refund_data[args[0]]);
if (p.isEmpty(localStorage.getItem('kaspi_repeat_args'))) {
localStorage.setItem('kaspi_repeat_args', JSON.stringify(args));
}
if (data) p.refund_check_data = data;
if (callback) p.next_action = callback;
else p.next_action = null;
p.next_action_args = args;
var guid = !args[2] ? 'item'+args[0] : args[0]
var check = p.refund_data[guid];
if (args) {
p.refund({
amount: check['sum'],
method: check['transactionMethod'],
transactionId: check['transactionId'],
});
}
}
//возврат c подтверждением от клиентом на терминале
p.refund = function(data) {
console.log(data);
if (p.isEmpty(localStorage.getItem('kaspi_repeat_data'))) {
localStorage.setItem('kaspi_repeat_data', JSON.stringify(data));
}
p.repeat_data = data;
p.headers.accesstoken = p.accessToken;
$.Query(p.url + '/refund?amount='+data.amount+'&method='+data.method+'&transactionId='+data.transactionId+'&owncheque=true',
function(data){
//console.log(data);
if (!p.isEmpty(data['processId'])) {
p.processId = data['processId'];
p.polling();
$('#kaspiProcess').modal('show');
} else {
ajax_msg('main_kaspi', 'danger', 'KASPI POS: Терминал отклонил попытку подключения или недоступен', 2);
}
p.load('finish');
}).fail(function(xhr, status, error) {
console.log(xhr);console.log(status);console.log(data);
ajax_msg('main_kaspi', 'danger', p.error_message(xhr, true), 2);
p.stop_timer();
});
};
//опрос терминала о статусе продажи
p.polling = function() {
p.start_timer();
p.timeoutId = setTimeout(function poll() {
$('#kaspiProcess').modal('show');
p.status().then(function(data) {
if (data['status'] === 'wait' && p.waiting_time < p.timeout) {
p.timeoutId = setTimeout(poll, 1000);
} else {
p.stop_timer();
$('#kaspiProcess').modal('hide');
}
});
}, 1000);
}
//старт таймера реализующего общий таймаут на проведение продажи
p.start_timer = function() {
p.timerId = setInterval(function() {
p.waiting_time += 1;
}, 1000)
}
//остановка таймера реализующего общий таймаут на проведение продажи и таймера опроса
p.stop_timer = function() {
if (p.load_finish) p.load_finish();
clearTimeout(p.timeoutId);
clearInterval(p.timerId);
}
//обработка статуса продажи
p.status = function() {
p.headers.accesstoken = p.accessToken;
return $.Query(p.url + '/status?processId='+p.processId,
function(data){
if (!p.isEmpty(data['status'])) {
if (data['status'] == 'success') {
//console.log(data);
//$('#kaspiProcess').modal('hide');
// if (data["chequeInfo"]["method"] == "qr" && p.kaspi_qr) {
// $('#kaspi_check').prop("checked", true);
// }
p.transactionId = data["transactionId"];
if (data["chequeInfo"]) {
p.transactionMethod = data["chequeInfo"]["method"];
}
// console.log(p.next_action);
// console.log(p.next_action_args);
// console.log(p.refund_check_data);
if (p.next_action) {
if (p.refund_check_data) {//возврат
if (p.next_kkm) {
p.next_action(p.next_action_args);
} else {
p.next_action(p.next_action_args[0], p.next_action_args[1], p.refund_check_data);
}
p.next_action = null;
}
else {//продажа
if (p.next_kkm) {
if ($(p.control_print_check).prop("checked")) {
p.next_action();
}
} else {
p.next_action();
}
$("#btn_new_client").removeClass('noLink');
}
}
p.remove_refund_data();
}
} else {
ajax_msg('main_kaspi', 'danger', 'KASPI POS: Терминал отклонил попытку подключения или недоступен', 2);
}
}).fail(function(xhr, status, error) {
//console.log(xhr);console.log(status);console.log(data);
ajax_msg('main_kaspi', 'danger', p.error_message(xhr), 2);
$('#kaspiProcess').modal('hide');
p.stop_timer();
p.remove_refund_data();
});
}
//обновляем сессионные переменные kaspi на сервере внешней системы
p.update_session = function(data){
$.post(p.webroot + 'Kaspi_api/kaspi/update_session',data,
function(response){
console.log('session updated');
});
}
//обновляем сессионные переменные kaspi на сервере внешней системы
p.reset_session = function(){
$.post(p.webroot + 'Kaspi_api/kaspi/reset_session',{},
function(response){
console.log('session reset');
});
}
//поиск ошибок от вебкассы(если продажа на терминале прошла успешно, но продажа во внешней системе прошла без вебкассы)
p.webkassa_errors = function() {
$.post(p.webroot + 'Kaspi_api/kaspi/webkassa_errors',{},
function(response){
if (p.is_json(response)) {
var obj = JSON.parse(response);
if (obj['msg']) {
if (obj['msg'].includes('(Code2)')) {
obj['msg'] += ' Восстановить';
}
if (obj['msg'].includes('(Code11)')) {
obj['msg'] += ' ---->Закрыть смену';
}
setTimeout(function() {
ajax_msg('main_kaspi', 'danger', obj['msg'], 2);
}, 1200);
}
}
});
}
p.set_refund_data = function(json) {
if (json) p.refund_data = json;
//console.log(p.refund_data);
}
p.remove_refund_data = function() {
localStorage.removeItem('kaspi_repeat_data');
localStorage.removeItem('kaspi_repeat_args');
localStorage.removeItem('kaspi_repeat_check');
}
//отображение кнопки подключения к терминалу, в настройках внешней системы
p.reflect_button_connect = function() {
if (p.state)
$('#title_kaspipos_connect').html('Обновить подключение');
else
$('#title_kaspipos_connect').html('Подключится');
}
//показываем/скрываем процесс загрузки
p.load = function(comand){
if (comand == 'start')
$('.kaspi_load').addClass('spin');
else
$('.kaspi_load').removeClass('spin');
}
p.set_load_finish = function(func) {
p.load_finish = func;
}
//обработка ошибок
p.error_message = function(xhr, repeat) {
if (xhr.responseJSON) return 'Kaspi POS: '+xhr.responseJSON.message;
var repeat_btn = '';
if (repeat) {
if (!p.isEmpty(localStorage.getItem('kaspi_repeat_data'))) {
var repeat_data = JSON.parse(localStorage.getItem('kaspi_repeat_data'));
if (!p.isEmpty(repeat_data['transactionId'])) {
repeat_btn = ' Отменить | Повторить';
}
}
}
if (p.isEmpty(repeat)) repeat_btn = ' Обновите страницу и попробуйте ещё раз.';
return 'KASPI POS недоступен или вышло время ожидания.'+repeat_btn;
}
p.repeat = function() {
console.log(p.repeat_func);
console.log(p.repeat_data);
if (p.repeat_func) {
var repeat_data = p.repeat_data;
if (p.isEmpty(repeat_data)) {
repeat_data = JSON.parse(localStorage.getItem('kaspi_repeat_data'));
}
if (!p.next_action_args) {
p.next_action_args = JSON.parse(localStorage.getItem('kaspi_repeat_args'));
}
if (!p.refund_check_data) {
p.refund_check_data = localStorage.getItem('kaspi_repeat_check');
}
if (repeat_data) {
p.repeat_func(repeat_data);
}
//p.repeat_func = null;
}
}
p.is_json = function(str) {
try {
JSON.parse(str);
} catch (e) {
return false;
}
return true;
}
p.isEmpty = function(str) {
return (!str || str.length === 0 );
}
$.Query = function(url, callback) {
//console.log( p.headers );
// console.log( data );
return $.ajax({
headers: p.headers,
'type': 'GET',
'url': url,
'success': callback,
'timeout': 3000
});
};
p.repeat_func = p.refund;
p.test_method = function(callback) {
p.next_action = callback;
//p.next_action.call(p.next_kkm);
p.next_action();
}
window.Kaspi = new kaspi;
}(jQuery));