Pull to refresh

Управление платежами в Приват24 из Google-таблиц

Reading time5 min
Views14K

Работать с интернет-банкингом большого количества предприятий может оказаться достаточно рутинной задачей. Для создания платежей и их контроля необходимо каждый раз переключаться между кабинетами. А если таких организаций больше 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 (row > 1) {
    
    if (col == lastCol) {
      
      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) 
  {
    iRange.setBackground('#ffff80');
    stateRange.setValue('Нет данных пользователя');
    return;
  }
    
  if (!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(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) {
    iRange.setBackground('#ffe066');
    stateRange.setValue('Нет данных пользователя');
    return;
  }

  if (!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('Не оплачено');
          }
        } else {
          Logger.log(pay + ' ' + bill.BPL_SUM)
          iRange.setBackground('#df80ff');
          stateRange.setValue('Сумма не совпадает');
        }      
      }        
    }
  }    
}


function substMonth() {
  var now = new Date();
  var start = new Date(now.getTime() - 30 * (1000 * 3600 * 24));
  return start;
}

Проверку можно поставить на триггер. Останется только наблюдать, как выполняются оплаты.



P.S. Попробуйте, как это работает на тестовой таблице (ссылка обновлена на улучшенную версию). Скопируйте ее на свой диск. Для автоматизации проверок необходимо добавить триггер по времени на функцию checkPayments.
Tags:
Hubs:
+18
Comments15

Articles

Change theme settings