Работать с интернет-банкингом большого количества предприятий может оказаться достаточно рутинной задачей. Для создания платежей и их контроля необходимо каждый раз переключаться между кабинетами. А если таких организаций больше 50, то можно с легкостью сбиться и наделать ошибок, не говоря уже о портаченном времени. Давайте посмотрим, как можно облегчить жизнь бухгалтера на примере API ПриватБанка для бизнеса.
Для работы со счетом необходимо создать Автоклиент и получить данные для авторизации. Эти данные, а так же платежную информацию будем хранить в Google-таблице.
Инструменты / Редактор скриптов. Здесь будем писать бекенд на Google Apps Script, в основе которого лежит Java Script. Наша задача — создать http-запрос, указав необходимые реквизиты.
Скрипт будет реагировать на изменения в последнем столбце. Для этого добавим триггер при изменении (onEdit) — выполнять функцию onEditt(). И саму функцию:
var ss = SpreadsheetApp.getActive();
var sheet = ss.getActiveSheet();
var lastRow = sheet.getLastRow();
var lastCol = sheet.getLastColumn();
function onEditt(e) {
var range = e.range;
var col = range.getColumn();
var row = range.getRow();
if (col == lastCol && row > 1) {
var value = range.getValue();
if (value == 'Отправить') {
createPayment(range.getRow());
}
else if (value == 'Проверить') {
checkPayment(range.getRow(), sheet);
}
range.clearContent();
}
}
Создание платежек
Для создания платежек используется POST-запрос. В процессе генерируется номер документа, который пригодится чуть позже. В результате будут видны статусы выполнения по каждому запросу — или успех или ошибка.
var url = "https://acp.privatbank.ua/api/proxy/payment/create_pred";
var day = getDay();
//передать номер строки в таблице
function createPayment(i) {
var iRange = sheet.getRange(i, 1, 1, lastCol);
var values = iRange.getDisplayValues();
var docNumRange = sheet.getRange(i, 3);
var stateRange = sheet.getRange(i, 10);
var state = stateRange.getValue();
if (state == 'Создано') {
iRange.setBackground('#66ff66');
return;
} else if (state == 'Оплачено') {
iRange.setBackground('#ebebe0');
return;
}
docNumRange.clearContent();
var name = values[0][0];
var userData = getUserData(name);
if (!userData) {
iRange.setBackground('#ffff80');
stateRange.setValue('Нет данных пользователя');
return;
}
var inn = userData[1];
var id = userData[2];
var token = userData[3];
var payer_account = userData[4];
var doc_type = values[0][1];
var document_number = "" + day + (i + 10) + Math.floor(Math.random() * 90 + 10);
var payment_amount = values[0][3];
var payment_naming = values[0][4];
var recipient_account = values[0][5];
var recipient_nceo = values[0][6];
var recipient_ifi = values[0][7];
var payment_destination = values[0][8];
if (!inn || !id || !token || !payer_account || !document_number ||
!recipient_account || !recipient_nceo || !payment_naming || !recipient_ifi ||
!payment_amount || !payment_destination)
{
iRange.setBackground('#ffff80');
stateRange.setValue('Ошибка заполнения');
return;
}
var headers = {
'User-Agent' : 'GooApps',
'id' : id,
'token' : token,
'Connection' : 'close'
}
var payload = {
'document_number' : document_number,
'payer_account' : payer_account,
'recipient_account' : recipient_account,
'recipient_nceo' : recipient_nceo,
'payment_naming' : payment_naming,
'recipient_ifi' : recipient_ifi,
'payment_amount' : payment_amount,
'payment_destination' : payment_destination
};
var options = {
'method' : 'post',
'contentType' : 'application/json;charset=utf8',
'headers' : headers,
'payload' : JSON.stringify(payload),
'muteHttpExceptions' : true
};
var response = UrlFetchApp.fetch(url, options);
var respCode = response.getResponseCode();
if (respCode == 201) {
docNumRange.setValue(document_number);
iRange.setBackground('#66ff66');
stateRange.setValue('Создано');
} else {
iRange.setBackground('#ff9980');
var resp = JSON.parse(response.getContentText());
var error = resp.code;
if (!error) {
error = resp.error_code;
}
// stateRange.setValue(getErrorName(error));
stateRange.setValue(error);
}
}
//создать все платежки
function createPayments() {
var range = sheet.getRange(2, 1, lastRow, lastCol);
range.clearFormat();
for (var i = 2; i <= lastRow; i++) {
createPayment(i);
}
}
function getUserData(name) {
var uSheet = ss.getSheetByName('Users');
var uRange = usersSheet.getRange(2, 1, uSheet.getLastRow(), uSheet.getLastColumn());
var values = uRange.getDisplayValues();
for (var i = 0; i < values.length; i++) {
if (name == values[i][0]) {
return values[i];
}
}
}
function getDay() {
var now = new Date();
var start = new Date('January 1, 2018 00:00:00 +0200');
var number = Math.round((now.getTime() - start.getTime()) / (1000 * 3600 * 24));
return number;
}
Контроль оплат
Для контроля оплат будем получать все выписки за последние 30 дней и искать в них номер документа, статус и сумму оплаты. Если все совпадает — платежка оплачена. В этом случае используется GET-запрос.
var urlGet = 'https://acp.privatbank.ua/api/proxy/transactions';
var stDate = Utilities.formatDate(substMonth() , '+0200', 'dd-MM-yyyy');
var endDate = Utilities.formatDate(new Date(), '+0200', 'dd-MM-yyyy');
//передать номер строки в таблице
function checkPayment(i) {
var iRange = sheet.getRange(i, 1, 1, lastCol);
var values = iRange.getDisplayValues();
var stateRange = sheet.getRange(i, 10);
var state = stateRange.getValue();
if (state != 'Создано') {
return;
}
var name = values[0][0];
var userData = getUserData(name);
if (!userData) {
iRange.setBackground('#ffe066');
stateRange.setValue('Нет данных пользователя');
return;
}
var id = userData[2];
var token = userData[3];
var payer_account = userData[4];
var document_number = values[0][2];
var payment_amount = values[0][3];
if (!id || !token || !payer_account || ! document_number || !payment_amount) {
iRange.setBackground('#ffe066');
stateRange.setValue('Ошибка заполнения');
return;
}
var headers = {
'User-Agent' : 'GooApps',
'id' : id,
'token' : token,
'Connection' : 'close'
}
var options = {
'method' : 'get',
'contentType' : 'application/json;charset=utf8',
'headers' : headers,
'muteHttpExceptions' : true
};
var url = Utilities.formatString('%s?acc=%s&startDate=%s&endDate=%s', urlGet, payer_account, stDate, endDate);
var response = UrlFetchApp.fetch(url, options);
var resp = JSON.parse(response);
var statements = resp.StatementsResponse.statements;
for (var j = 0; j < statements.length; j++) {
for (var name in statements[j]) {
var bill = statements[j][name];
if (document_number == bill.BPL_NUM_DOC) {
var pay = payment_amount.toString().replace(',','.');
if (pay == bill.BPL_SUM) {
if ('r' == bill.BPL_PR_PR) {
iRange.setBackground('#ebebe0');
stateRange.setValue('Оплачено');
} else {
iRange.setBackground('#df80ff');
stateRange.setValue('Не оплачено');
}
}
}
}
}
}
function substMonth() {
var now = new Date();
var start = new Date(now.getTime() - 30 * (1000 * 3600 * 24));
return start;
}
Проверку можно поставить на триггер. Останется только наблюдать, как выполняются оплаты.
Автор: braker07