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

в 17:28, , рубрики: api, automatization, google app engine, google apps script, Privat24
Управление платежами в Приват24 из Google-таблиц - 1

Работать с интернет-банкингом большого количества предприятий может оказаться достаточно рутинной задачей. Для создания платежей и их контроля необходимо каждый раз переключаться между кабинетами. А если таких организаций больше 50, то можно с легкостью сбиться и наделать ошибок, не говоря уже о портаченном времени. Давайте посмотрим, как можно облегчить жизнь бухгалтера на примере API ПриватБанка для бизнеса.

Для работы со счетом необходимо создать Автоклиент и получить данные для авторизации. Эти данные, а так же платежную информацию будем хранить в Google-таблице.

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

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

Инструменты / Редактор скриптов. Здесь будем писать бекенд на 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

Источник


* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js