Configurando a API do Tinkoff Bank. Como está sua intuição ....? Ou uma música sobre Oauth 2.0

Há algumas semanas, em um dos projetos, surgiu a questão de integrar o CRM à API do Tinkoff Bank. Em particular, tratava-se de obter um extrato de conta bancária.

O ativo tinha:

  1. openapi.tinkoff.ru
  2. Serviço de suporte por telefone (dada a ocupação do departamento de suporte técnico - o trabalho de salvar o afogado, a obra do próprio afogado).
  3. Documento pesquisado no Google: 24386_policy.pdf (com letras russas no interior, com expressões divertidas, reviravoltas de bruxaria, inadequadas, mas, no entanto, uma coisa ...)

No decorrer da caixa do google, também foram encontradas críticas de que a configuração da API do Tinkoff Bank é muito divertida e não é trivial (consulte o artigo em banki.ru "API do Tinkoff - somos burros demais para isso" ).

Sim, tive que mexer um pouco, portanto, para economizar tempo para outros camaradas do workshop, este artigo foi escrito.

Observo que a API do Tinkoff Bank usa o Oauth 2.0 para autorização.

Por que precisamos do openapi.tinkoff.ru?

  1. para o teste (veja abaixo);
  2. para adivinhar o que é o que e como; não há tala direta; Trabalhamos ao nível da intuição! ...

Vamos começar. Na seção “Autorização SSO”, clique em “como / ocultar” e depois em / secure / token # refresh-token (“emitindo um token por token de atualização”), selecione grant_type como parâmetro e, em seguida, no campo refresh_token (você pode obtê-lo em Conta de usuário). Clique no botão "Experimente!" O resultado dessas ações é obter uma coisa tão importante quanto o access_token (ou seja, o openapi.tinkoff.ru demonstra a possibilidade de recebê-lo).

Em seguida, consulte a seção "Contas e pagamentos", clique em / partner / company / {INN} / trecho ("Recebimento do extrato"). Estudamos quais parâmetros são necessários para obtê-lo: Authorization, INN, accountNumber, from, till.

Autorização - acreditamos que Autorização nada mais é do que access_token, recebido por nós na seção "Autorização de SSO";
DCI - DCI da organização para a qual configuramos a API;
a partir de - a partir de qual dia (período de alta);
até - em que dia (período de alta).

Assim (examinamos o material Oauth 2.0), a obtenção de dados da instrução ocorre em dois estágios - primeiro obtemos o access_token, depois, tendo o access_token em mãos, obtemos os dados para essa instrução . Ótimo. O algoritmo é claro, escrevemos o código (parâmetros de acesso nos valores de código para $ user, $ pass, $ refresh_token, $ inn, $ accountNumber - no código abaixo são alterados, por razões óbvias).

Crie os seguintes arquivos:

  1. O primeiro arquivo de configurações é StartSettings.php
  2. O segundo arquivo inicial é Start.php
  3. O terceiro arquivo para postar / analisar dados de / para a API é TinkoffInsertData.php ; nós usamos CURL (php).
  4. Um dump de banco de dados vazio no qual você pode carregar os dados de seus extratos: bank.sql ; Banco de dados MySQL (enviamos dados para o banco de dados através do DOP).

Então, olhe o código e comente!

Arquivo de configurações - StartSettings.php:

$host = '127.0.0.1'; $db = 'bank'; $user = 'root'; $pass = ''; $charset = 'utf8'; $dsn = "mysql:host=$host;dbname=$db;charset=$charset"; $opt = [ PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, PDO::ATTR_EMULATE_PREPARES => false, ]; $pdo = new PDO($dsn, $user, $pass, $opt); $user="IKu0jn98kllkI90kklii"; //20  $pass="ds4234SDFsdfsdijoijslkkdjfoIOi"; //30  $refresh_token='dsfh345kljlkjsdf098sdfkljklj098sdfkklKKLjhjihiKL90909llkrre5345dfFDDFretertERTERETfdgd==';// 88  $inn = '750151513135'; $accountNumber = '40802810300000121212';//20  $from_year = '1980'; $from_month = '01'; $from_day = '01'; $till_year = date('Y'); $till_month = date('m'); $till_day = date('d'); 

Iniciar arquivo - Start.php:

 session_start(); error_reporting(E_ALL); include 'StartSettings.php'; include 'TinkoffInsertData.php'; TinkoffInsertData($user,$pass,$refresh_token, $inn, $accountNumber, $from_year, $from_month, $from_day, $till_year, $till_month, $till_day, $pdo); $stmt = $pdo->prepare("INSERT INTO `bank`.`dateofwork` (dateofwork) VALUES (NOW())"); $stmt->execute(); 

Arquivo para postar / analisar dados de / para a API - TinkoffInsertData.php:

 function TinkoffInsertData($user,$pass,$refresh_token, $inn, $accountNumber, $from_year, $from_month, $from_day, $till_year, $till_month, $till_day, $pdo){ //  -    access_token $from_date = $from_year."-".$from_month."-".$from_day.'%2B03%3A00%3A00'; $till_date = $till_year."-".$till_month."-".$till_day.'%2B03%3A00%3A00'; $params=['grant_type'=>'refresh_token', 'refresh_token'=>$refresh_token ]; $headers = [ 'POST /secure/token HTTP/1.1', 'Content-Type: application/x-www-form-urlencoded' ]; $curlURL='https://sso.tinkoff.ru/secure/token'; $ch = curl_init(); curl_setopt($ch, CURLOPT_URL,$curlURL); curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC); curl_setopt($ch, CURLOPT_USERPWD, $user . ":" . $pass); curl_setopt($ch, CURLOPT_HEADER, true); curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POSTFIELDS,http_build_query($params)); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_VERBOSE, true); $curl_res = curl_exec($ch); if($curl_res) { $server_output = json_decode($curl_res); } // access_token -     2  $access_token_pos_start = strpos ($curl_res, 'access_token', 0); $access_token_pos_start = $access_token_pos_start + 15; $token_type_pos_start = strpos ($curl_res, "token_type", 0); $access_token = mb_substr($curl_res, $access_token_pos_start, ($token_type_pos_start-$access_token_pos_start-3)); //!....   ..... // ,    sleep,        //sleep(1); //  -     $params=[ 'Authorization'=>$access_token, 'INN'=>$inn, 'accountNumber'=>$accountNumber ]; $headers = [ 'Authorization: Bearer '.$access_token ]; $curlURL='https://sme-partner.tinkoff.ru/api/v1/partner/company/'.$inn.'/excerpt?accountNumber='.$accountNumber.'&from='.$from_date.'&till='.$till_date; $ch = curl_init(); curl_setopt($ch, CURLOPT_URL,$curlURL); curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC); curl_setopt($ch, CURLOPT_USERPWD, $user . ":" . $pass); curl_setopt($ch, CURLOPT_HEADER, true); curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); curl_setopt($ch, CURLOPT_POST, false); curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET'); curl_setopt($ch, CURLOPT_POSTFIELDS,http_build_query($params)); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_VERBOSE, true); $curl_res = curl_exec($ch); if($curl_res) { $server_output = json_decode($curl_res); } $IE_Edge_pos_start = strpos ($curl_res, 'IE=Edge', 0); $IE_Edge_pos_start = $IE_Edge_pos_start + 7; $tinkoff_json = mb_substr($curl_res, $IE_Edge_pos_start); $tinkoff_json = trim($tinkoff_json); $tinkoff_json = json_decode($tinkoff_json); //     ,  ;) foreach ($tinkoff_json as $k=>$v){ if($k=='accountNumber'){ if(!($v==$accountNumber)) die('not that accountNumber'); } } //$tinkoff_array -    json   foreach ($tinkoff_json as $k=>$v){ if($k=='operation'){ $i=0; foreach ($v as $t=>$s){ foreach ($s as $e=>$f){ $tinkoff_array[$i][$e]=$f; } $i++; } } } //   $tinkoff_array    for ($i=0;$i<count($tinkoff_array);$i++){ $temp_id = $pdo->query("SELECT count(*) FROM `justtin`.`tinkoff` WHERE id=".$tinkoff_array[$i]['id'].";")->fetchColumn(); if ($temp_id==0){ if (Get_highly_likely_is_number_bill($tinkoff_array[$i]['paymentPurpose'])!=""){ $stmt = $pdo->prepare("INSERT INTO `justtin`.`tinkoff` (id, date, amount, drawDate, payerName, payerInn, payerAccount, payerCorrAccount, payerBic, payerBank, chargeDate, recipient, recipientInn, recipientAccount, recipientCorrAccount, recipientBic, recipientBank, operationType, uin, paymentPurpose, creatorStatus, payerKpp, executionOrder, date_of_save) VALUES (:id, :date, :amount, :drawDate, :payerName, :payerInn, :payerAccount, :payerCorrAccount, :payerBic, :payerBank, :chargeDate, :recipient, :recipientInn, :recipientAccount, :recipientCorrAccount, :recipientBic, :recipientBank, :operationType, :uin, :paymentPurpose, :creatorStatus, :payerKpp, :executionOrder, NOW())"); $stmt->bindParam(':id', $tinkoff_array[$i]['id']); $stmt->bindParam(':date', $tinkoff_array[$i]['date']); $stmt->bindParam(':amount', $tinkoff_array[$i]['amount']); $stmt->bindParam(':drawDate', $tinkoff_array[$i]['drawDate']); $stmt->bindParam(':payerName', $tinkoff_array[$i]['payerName']); $stmt->bindParam(':payerInn', $tinkoff_array[$i]['payerInn']); $stmt->bindParam(':payerAccount', $tinkoff_array[$i]['payerAccount']); $stmt->bindParam(':payerCorrAccount', $tinkoff_array[$i]['payerCorrAccount']); $stmt->bindParam(':payerBic', $tinkoff_array[$i]['payerBic']); $stmt->bindParam(':payerBank', $tinkoff_array[$i]['payerBank']); $stmt->bindParam(':chargeDate', $tinkoff_array[$i]['chargeDate']); $stmt->bindParam(':recipient', $tinkoff_array[$i]['recipient']); $stmt->bindParam(':recipientInn', $tinkoff_array[$i]['recipientInn']); $stmt->bindParam(':recipientAccount', $tinkoff_array[$i]['recipientAccount']); $stmt->bindParam(':recipientCorrAccount', $tinkoff_array[$i]['recipientCorrAccount']); $stmt->bindParam(':recipientBic', $tinkoff_array[$i]['recipientBic']); $stmt->bindParam(':recipientBank', $tinkoff_array[$i]['recipientBank']); $stmt->bindParam(':operationType', $tinkoff_array[$i]['operationType']); $stmt->bindParam(':uin', $tinkoff_array[$i]['uin']); $stmt->bindParam(':paymentPurpose', $tinkoff_array[$i]['paymentPurpose']); $stmt->bindParam(':creatorStatus', $tinkoff_array[$i]['creatorStatus']); $stmt->bindParam(':payerKpp', $tinkoff_array[$i]['payerKpp']); $stmt->bindParam(':executionOrder', $tinkoff_array[$i]['executionOrder']); $stmt->execute(); } } } } 

Leitores: Espero que este material ajude a monetizar seus serviços da Web e os serviços de seus clientes. Que a força venha com você!

Pessoal de suporte técnico do Tinkoff Bank: Espero que este artigo reduza a carga sobre você! Boa sorte

Source: https://habr.com/ru/post/pt431908/


All Articles