Ir para conteúdo
Emerson Rodrigo

Leitura de Arquivos OFX com PHP

Recommended Posts

Fala pessoal!

 

Hoje precisei criar uma rotina para importação de arquivos OFX, aqueles que são usados para fazer integração bancária.

 

Esse arquivos nada mais são do que o extrato bancário em um formato universal para integração com vários tipos de sistemas e linguagens de programação.

 

Como não é uma coisa que se acha fácil por ai, resolvi postar e deixar disponível para quem precisar.

 

Código do arquivo Ofx.php

<?phpclass Ofx {    private $ofxFile;    public function __construct($ofxFile) {        $this->ofxFile = $ofxFile;    }    /*     * Converte o arquivo OFX para XML     */    public function getOfxAsXML() {        $content = file_get_contents($this->ofxFile);        $line = strpos($content, "<OFX>");        $ofx = substr($content, $line - 1);        $buffer = $ofx;        $count = 0;        while ($pos = strpos($buffer, '<')) {            $count++;            $pos2 = strpos($buffer, '>');            $element = substr($buffer, $pos + 1, $pos2 - $pos - 1);            if (substr($element, 0, 1) == '/')                $sla[] = substr($element, 1);            else                $als[] = $element;            $buffer = substr($buffer, $pos2 + 1);        }        $adif = array_diff($als, $sla);        $adif = array_unique($adif);        $ofxy = $ofx;        foreach ($adif as $dif) {            $dpos = 0;            while ($dpos = strpos($ofxy, $dif, $dpos + 1)) {                $npos = strpos($ofxy, '<', $dpos + 1);                $ofxy = substr_replace($ofxy, "</$dif>\n<", $npos, 1);                $dpos = $npos + strlen($element) + 3;            }        }        $ofxy = str_replace('&', '&', $ofxy);        return $ofxy;    }    /*     * Retorna o Saldo da conta na data de exportação do extrato     */    public function getBalance() {        $xml = new SimpleXMLElement($this->getOfxAsXML());        $balance = $xml->BANKMSGSRSV1->STMTTRNRS->STMTRS->LEDGERBAL->BALAMT;        $dateOfBalance = $xml->BANKMSGSRSV1->STMTTRNRS->STMTRS->LEDGERBAL->DTASOF;        $date = strtotime(substr($dateOfBalance, 0, 8));        $dateToReturn = date('Y-m-d', $date);        return Array('date' => $dateToReturn, 'balance' => $balance);    }    /*     * Retora um array de objetos com as transações     *      * DTPOSTED => Data da Transação     * TRNAMT   => Valor da Transação     * TRNTYPE  => Tipo da Transação (Débito ou Crédito)     * MEMO     => Descrição da transação     */    public function getTransactions() {        $xml = new SimpleXMLElement($this->getOfxAsXML());        $transactions = $xml->BANKMSGSRSV1->STMTTRNRS->STMTRS->BANKTRANLIST->STMTTRN;        return $transactions;    }}

Exemplo de utilização:

<?phprequire_once 'Ofx.php';$ofx = new Ofx('extrato.ofx');$saldo = $ofx->getBalance();?><html>    <head>        <title>Transações</title>    </head>    <body>        <h1>Seu saldo em <?php echo date("d/m/Y", strtotime($saldo['date'])); ?> é de R$ <?echo $saldo['balance']; ?></h1>               <h2>Transações</h2>        <table border="1" cellpadding="3" cellspacing="0">            <thead>                <tr>                    <th>Data</th>                    <th>Descrição</th>                    <th>Tipo</th>                    <th>Valor</th>                </tr>            </thead>            <tbody>                <?php foreach ($ofx->getTransactions() as $transaction) : ?>                    <tr>                        <td><?php echo date("Y-m-d", strtotime(substr($transaction->DTPOSTED, 0, 8))); ?></td>                        <td><?php echo $transaction->MEMO; ?></td>                        <td><?php echo $transaction->TRNTYPE; ?></td>                        <td><?php echo $transaction->TRNAMT; ?></td>                    </tr>                <?php endforeach; ?>            </tbody>        </table>    </body></html>

É isso ai, espero que seja útil!

Editado por Mário Monteiro
  • +1 1

Compartilhar este post


Link para o post
Compartilhar em outros sites

Olá Emerson.

Muito Obrigado pelo post..

mais cara infelizmente na minha maquina o código não funciona

gera vários erros de WARNiNG: SIMPLEXMLELEMENT,

ainda sou meio leigo em php e gostaria muito de sua ajuda.

não teria como postar o código zipado para download juntamente com um exemplo

de arquivo ofx.

 

Att. Alessandro

Compartilhar este post


Link para o post
Compartilhar em outros sites

Pra quem está tento problemas com a codificação do arquivo OFX altere a linha

$content = file_get_contents($this->ofxFile);

para:

$content = utf8_decode(file_get_contents($this->ofxFile));

isso deve resolver

Compartilhar este post


Link para o post
Compartilhar em outros sites

Emerson, muito obrigado. Mesmo após 2.5 anos seu post me ajudou demais.

Só deu problema em casos de OFX's provenientes do Banco do Brasil.

Aparentemente é porque os arquivos não fecham algumas tags aí dá erro.

 

Compartilhar este post


Link para o post
Compartilhar em outros sites

Emerson, valeu pelo post... ajudou muito.

 
Devy++, tive o mesmo problema e resolvi assim:
 
    public function __construct($ofxFile) {
        $this->ofxFile = $this->closeTags($ofxFile);
    }

    public function closeTags($ofx=null) {
      $buffer = '';
      $source = fopen($ofx, 'r') or die("Unable to open file!");
      while(!feof($source)) {
          $line = trim(fgets($source));
          if ($line === '') continue;

          if (substr($line, -1, 1) !== '>') {
              list($tag) = explode('>', $line, 2);
              $line .= '</' . substr($tag, 1) . '>';
          }
          $buffer .= $line ."\n";
      }

      $name = realpath(dirname($ofx)) . '/' . date('Ymd') . '.ofx';
      $file = fopen($name, "w") or die("Unable to open file!");
      fwrite($file, $buffer);
      fclose($file);

      return $name;
    }

Compartilhar este post


Link para o post
Compartilhar em outros sites
Em 14/06/2017 at 12:06, aMaltha disse:

Emerson, valeu pelo post... ajudou muito.

 
Devy++, tive o mesmo problema e resolvi assim:
 

    public function __construct($ofxFile) {
        $this->ofxFile = $this->closeTags($ofxFile);
    }

    public function closeTags($ofx=null) {
      $buffer = '';
      $source = fopen($ofx, 'r') or die("Unable to open file!");
      while(!feof($source)) {
          $line = trim(fgets($source));
          if ($line === '') continue;

          if (substr($line, -1, 1) !== '>') {
              list($tag) = explode('>', $line, 2);
              $line .= '</' . substr($tag, 1) . '>';
          }
          $buffer .= $line ."\n";
      }

      $name = realpath(dirname($ofx)) . '/' . date('Ymd') . '.ofx';
      $file = fopen($name, "w") or die("Unable to open file!");
      fwrite($file, $buffer);
      fclose($file);

      return $name;
    }

 

Compartilhar este post


Link para o post
Compartilhar em outros sites

o composer nao esta instalando da a mensagem de erro abaixo ---   alguem pode ajudar --  preciso importar o .ofx e gravar no Banco de Dados mysql

[InvalidArgumentException]
  Could not find a version of package asmpkg/ofx matching your minimum-stability (stable). Require it with an explicit version constraint allowing its desir   
  ed stability.

 

 

Compartilhar este post


Link para o post
Compartilhar em outros sites

Esse código tem problema se o cara usar uma palavra reservada na descrição do extrato bancário,
E seria interessante  bufferizar somente 1x;
mas enfim quem esta querendo resolver algum problema em código de manutenção na empresa como eu:

 

	$ofxy = $ofx;
	foreach ($adif as $dif) {
		$dpos = 0;
-		while ($dpos = strpos($ofxy, $dif, $dpos + 1)) {       // mudar essa linha
+		while ($dpos = strpos($ofxy, "<$dif", $dpos + 1)) {
			$npos = strpos($ofxy, '<', $dpos + 1);
			$ofxy = substr_replace($ofxy, "</$dif>\n<", $npos, 1);
			$dpos = $npos + strlen($element) + 3;
		}
	}
	$ofxy = str_replace('&', '&', $ofxy);
	return $ofxy;



 

Compartilhar este post


Link para o post
Compartilhar em outros sites

Crie uma conta ou entre para comentar

Você precisar ser um membro para fazer um comentário

Criar uma conta

Crie uma nova conta em nossa comunidade. É fácil!

Crie uma nova conta

Entrar

Já tem uma conta? Faça o login.

Entrar Agora

×

Informação importante

Ao usar o fórum, você concorda com nossos Termos e condições.