English Русский 中文 Español Deutsch 日本語 한국어 Français Italiano Türkçe
Usar WinInet em MQL5.  Parte 2:  Solicitações POST e Arquivos

Usar WinInet em MQL5. Parte 2: Solicitações POST e Arquivos

MetaTrader 5Exemplos | 6 março 2014, 16:06
2 243 0
---
---

Introdução

Na lição anterior "Usar WinInet.dll para trocar dados entre terminais via internet", nós aprendemos a trabalhar com a biblioteca, abrir páginas web, enviar e receber informações utilizando solicitações GET.

Nesta lição, nós iremos aprender a:

  • criar e enviar solicitações POST simples a um servidor;
  • enviar arquivos a um servidor usando o método de representação multipart/form-data;
  • trabalhar com Cookies e ler informações a partir de websites utilizando o seu login.

Conforme anteriormente, recomendamos configurar um servidor proxy local Charles; isto será necessário durante o seu estudo e testes posteriores.


Solicitações POST

Para enviar informações, nós precisaremos das funções wininet.dll e da classe CMqlNet criada que foram descritas no artigo anterior.

Devido ao grande número de campos dos métodos CMqlNet::Request, nós tivemos que criar uma estrutura tagRequest separada que contém todos os campos requeridos para uma solicitação.

//------------------------------------------------------------------ struct tagRequest
struct tagRequest
{
  string stVerb;   // method of the request GET/POST/…
  string stObject; // path to an instance of request, for example "/index.htm" или "/get.php?a=1"  
  string stHead;   // request header
  string stData;   // addition string of data
  bool fromFile;   // if =true, then stData designates the name of a data file
  string stOut;    // string for receiving an answer
  bool toFile;     // if =true, then stOut designates the name of a file for receiving an answer

  void Init(string aVerb, string aObject, string aHead, 
            string aData, bool from, string aOut, bool to); // function of initialization of all fields
};
//------------------------------------------------------------------ Init
void tagRequest::Init(string aVerb, string aObject, string aHead, 
                      string aData, bool from, string aOut, bool to)
{
  stVerb=aVerb;     // method of the request GET/POST/…
  stObject=aObject; // path to the page "/get.php?a=1" or "/index.htm"
  stHead=aHead;     // request header, for example "Content-Type: application/x-www-form-urlencoded"
  stData=aData;     // addition string of data
  fromFile=from;    // if =true, the stData designates the name of a data file
  stOut=aOut;       // field for receiving an answer
  toFile=to;        // if =true, then stOut designates the name of a file for receiving an answer
}

Além disso, nós precisamos substituir o cabeçalho do método CMqlNet::Request por um mais curto:

//+------------------------------------------------------------------+
bool MqlNet::Request(tagRequest &req)
  {
   if(!TerminalInfoInteger(TERMINAL_DLLS_ALLOWED))
     {
      Print("-DLL not allowed"); return(false);
     }
//--- checking whether DLLs are allowed in the terminal
   if(!MQL5InfoInteger(MQL5_DLLS_ALLOWED))
     {
      Print("-DLL not allowed");
      return(false);
     }
//--- checking whether DLLs are allowed in the terminal
   if(req.toFile && req.stOut=="")
     {
      Print("-File not specified ");
      return(false);
     }
   uchar data[]; 
    int hRequest,hSend;
   string Vers="HTTP/1.1"; 
    string nill="";

//--- read file to array
   if(req.fromFile)
     {
      if(FileToArray(req.stData,data)<0)
        {
         Print("-Err reading file "+req.stData);
         return(false);
        }
     }
   else StringToCharArray(req.stData,data);

   if(hSession<=0 || hConnect<=0)
     {
      Close();
      if(!Open(Host,Port,User,Pass,Service))
        {
         Print("-Err Connect");
         Close();
         return(false);
        }
     }
//--- creating descriptor of the request
   hRequest=HttpOpenRequestW(hConnect,req.stVerb,req.stObject,Vers,nill,0,
   INTERNET_FLAG_KEEP_CONNECTION|INTERNET_FLAG_RELOAD|INTERNET_FLAG_PRAGMA_NOCACHE,0);
   if(hRequest<=0)
     {
      Print("-Err OpenRequest");
      InternetCloseHandle(hConnect);
      return(false);
     }
//--- sending the request
   hSend=HttpSendRequestW(hRequest,req.stHead,StringLen(req.stHead),data,ArraySize(data));
//--- sending the file
   if(hSend<=0)
     {
      int err=0;
      err=GetLastError(err);
      Print("-Err SendRequest= ",err);
     }
//--- reading the page
   if(hSend>0) ReadPage(hRequest,req.stOut,req.toFile);
//--- closing all handles
   InternetCloseHandle(hRequest); InternetCloseHandle(hSend);

   if(hSend<=0)
     {
      Close();
      return(false);
     }
   return(true);
  }
    

Agora vamos começar a trabalhar.


Enviar dados a um website do tipo "application/x-www-form-urlencoded"

Na lição anterior, nós analisamos o exemplo MetaArbitrage (monitoramento de cotações).

Vamos recordar que o EA envia preços de lances do seu símbolo utilizando uma solicitação GET; e, como resposta, ele recebe preços de outros corretores que são enviadas da mesma forma ao servidor a partir de outros terminais.

Para trocar uma solicitação GET por uma POST, é suficiente "esconder" a linha da solicitação em si no corpo da solicitação que segue após o seu cabeçalho.

BOOL HttpSendRequest(
__in HINTERNET hRequest,
__in LPCTSTR lpszHeaders,
__in DWORD dwHeadersLength,
__in LPVOID lpOptional,
__in DWORD dwOptionalLength
);

  • hRequest [in]
    Handle retornado por HttpOpenRequest.
  • lpszHeaders [in]
    Ponteiro para uma linha que contém cabeçalhos a serem adicionados à solicitação. Este parâmetro pode ser nulo.
  • dwHeadersLength [in]
    Tamanho do cabeçalho em bytes.
  • lpOptional [in]
    Ponteiro para um array com dados uchar que são enviados imediatamente após o cabeçalho. Geralmente, este parâmetro é utilizado para operações POST e PUT.
  • dwOptionalLength [in]
    Tamanho dos dados em bytes. O parâmetro pode ser =0; isso significa que nenhuma informação adicional foi enviada.

A partir da descrição da função, nós podemos entender que os dados são enviados como byte uchar-array (o quarto parâmetro da função). Isto é tudo o que precisamos saber nesta etapa.

No exemplo MetaArbitrage, a solicitação GET tem o seguinte aspecto:

www.fxmaster.de/metaarbitr.php?server=Metaquotes&pair=EURUSD&bid=1.4512&time=13286794


A solicitação em si é destacada com a cor vermelha. Assim, se nós precisarmos fazer uma solicitação POST, teremos que mover o seu texto para o array de dados lpOptional.

Vamos criar um script chamado MetaSwap, o qual irá enviar e receber informações sobre trocas de um símbolo.

#include <InternetLib.mqh>

string Server[];        // array of server names
double Long[], Short[]; // array for swap information
MqlNet INet;           // class instance for working

//------------------------------------------------------------------ OnStart
void OnStart()
{
//--- opening a session
  if (!INet.Open("www.fxmaster.de", 80, "", "", INTERNET_SERVICE_HTTP)) return;
 
//--- zeroizing arrays
  ArrayResize(Server, 0); ArrayResize(Long, 0); ArrayResize(Short, 0);
//--- the file for writing an example of swap information
  string file=Symbol()+"_swap.csv";
//--- sending swaps
  if (!SendData(file, "GET")) 
  { 
    Print("-err RecieveSwap"); 
    return; 
  }
//--- read data from the received file
  if (!ReadSwap(file)) return; 
//--- refresh information about swaps on the chart
  UpdateInfo();               
}

A operação do script é muito simples.

Primeiramente, abre-se a sessão da internet INet.Open. Em seguida, a função SendData envia informações sobre as trocas do símbolo atual. Após, caso sejam enviadas com sucesso, as trocas recebidas são lidas com a utilização do ReadSwap e são exibidas no gráfico com UpdateInfo.

Neste momento, apenas a função SendData nos interessa.

//------------------------------------------------------------------ SendData bool SendData(string file, string mode) {   string smb=Symbol();   string Head="Content-Type: application/x-www-form-urlencoded"; // header   string Path="/mt5swap/metaswap.php"; // path to the page   string Data="server="+AccountInfoString(ACCOUNT_SERVER)+               "&pair="+smb+               "&long="+DTS(SymbolInfoDouble(smb, SYMBOL_SWAP_LONG))+               "&short="+DTS(SymbolInfoDouble(smb, SYMBOL_SWAP_SHORT));   tagRequest req; // initialization of parameters   if (mode=="GET")  req.Init(mode, Path+"?"+Data, Head, "",   false, file, true);   if (mode=="POST") req.Init(mode, Path,          Head, Data, false, file, true);   return(INet.Request(req)); // sending request to the server }

Neste script, são demonstrados dois métodos de envio de informações - utilizando GET e POST, para que você perceba a diferença entre eles.

Descreveremos as variáveis da função uma a uma:

  • Head - cabeçalho da solicitação descrevendo o tipo de seu conteúdo. Na realidade, este não é o cabeçalho completo da solicitação. Os outros campos do cabeçalho são criados pela biblioteca wininet.dll. Entretanto, eles podem ser modificados através da função HttpAddRequestHeaders.
  • Path - este é o caminho para a instância de solicitação relativa ao domínio www.fxmaster.de inicial. Em outras palavras, é o caminho para um script php que processará a solicitação. A propósito, não é necessário solicitar apenas um script php, poderá ser uma página html comum (inclusive, nós tentamos solicitar um arquivo mq5 durante a nossa primeira lição).
  • Data - estas são as informações que serão enviadas ao servidor. Os dados são escritos de acordo com as regras de passagem de parameter name=value. E o símbolo "&" é usado como separador de dados.

O principal detalhe é prestar atenção à diferença entre fazer solicitações GET e POST em tagRequest::Init.

No método GET, o caminho é enviado junto com o corpo da solicitação (unidos com o símbolo "?"), e o campo de dados lpOptional (denominado stData na estrutura) é deixado vazio.
No método POST
, o caminho permanece independente e o corpo da solicitação é movido para lpOptional.

Como você pode perceber, a diferença não é significativa. O script metaswap.php do servidor, o qual recebe a solicitação, está anexo ao artigo.


Enviar dados "multipart/form-data"

Na realidade, solicitações POST não são análogas às solicitações GET (caso contrário, elas não seriam necessárias). As solicitações POST apresentam uma vantagem significativa - ao usá-las, você pode enviar arquivos de conteúdo binário.

A questão é que uma solicitação do tipo URL codificado pode enviar somente um conjunto limitado de símbolos. Caso contrário, os símbolos "não autorizado" serão substituídos por códigos. Dessa forma, durante o envio de dados binários, eles serão distorcidos. Assim, você não poderá enviar até mesmo um pequeno arquivo gif utilizando uma solicitação GET.

Para solucionar este problema, regras especiais de descrição de solicitação são desenvolvidas; elas permitem a troca de arquivos binários além de arquivos de texto.

Para alcançar este objetivo, o corpo da solicitação é dividido em seções. O principal detalhe é que cada seção pode ter o seu próprio tipo de dados. Por exemplo, o primeiro é um arquivo de texto, o próximo é uma imagem/jpeg, etc. Em outras palavras, uma solicitação enviada ao servidor pode conter diferentes tipos de dados de uma só vez.

Vamos observar a estrutura desta descrição através do exemplo de dados passados através do script MetaSwap.

Cabeçalho da solicitação - Head terá o seguinte formato:

Content-Type: multipart/form-data; boundary=SEPARATOR\r\n


A palavra-chave SEPARATOR – é um conjunto de símbolos aleatórios. Entretanto, você deve se certificar de que isto seja diferente dos dados de solicitação. Em outras palavras, esta deve ser uma linha única - algo aleatório como hdsJK263shxaDFHLsdhsDdjf9 ou qualquer outra sequência que vier a sua mente :). Em PHP, uma linha como esta é formada com o uso do código MD5 de um horário atual.

A solicitação POST em si tem o seguinte aspecto (para melhor compreensão, os campos estão destacados de acordo com o significado geral):

\r\n
--SEPARATOR\r\n

Content-Disposition: form-data; name="Server"\r\n
\r\n
MetaQuotes-Demo

\r\n
--SEPARATOR\r\n

Content-Disposition: form-data; name="Pair"\r\n
\r\n
EURUSD

\r\n
--SEPARATOR\r\n

Content-Disposition: form-data; name="Long"\r\n
\r\n
1.02

\r\n
--SEPARATOR\r\n

Content-Disposition: form-data; name="Short"\r\n
\r\n
-0.05

\r\n
--SEPARATOR--\r\n


Nós especificamos os locais para novas linhas "\r\n" explicitamente, porque eles são símbolos obrigatórios em uma solicitação. Como você pode perceber, os mesmos quatro campos são passados na solicitação e isso é feito da forma textual comum.

Os detalhes importantes ao posicionar separadores:

  • Dois símbolos "--" são posicionados antes do separador.
  • Para fechar o separador, dois símbolos "--" adicionais são colocados após ele.


No próximo exemplo, você pode observar um método correto para enviar arquivos em uma solicitação.

Imagine que um Expert Advisor capture a imagem de um gráfico e faça um relatório detalhado sobre conta em um arquivo de texto ao fechar uma posição.

\r\n
--SEPARATOR\r\n

Content-Disposition: form-data; name="ExpertName"\r\n
\r\n
MACD_Sample

\r\n
--SEPARATOR\r\n

Content-Disposition: file; name="screen"; filename="screen.gif"\r\n
Content-Type: image/gif\r\n
Content-Transfer-Encoding: binary\r\n
\r\n
......conteúdo do arquivo gif.....

\r\n
--SEPARATOR\r\n

Content-Disposition: form-data; name="statement"; filename="statement.csv"\r\n
Content-Type: application/octet-stream\r\n
Content-Transfer-Encoding: binary\r\n
\r\n
......conteúdo do arquivo csv.....

\r\n
--SEPARATOR--\r\n


Dois novos cabeçalhos aparecem na solicitação:

Content-Type - descreve o tipo de conteúdo. Todos os tipos possíveis estão descritos com precisão no padrão RFC[2046]. Nós usamos dois tipos - image/gif e application/octet-stream.

Duas variantes ao escrever Content-Disposition, file e form-data, são equivalentes e serão corretamente processadas por PHP nos dois casos. Assim, você tem a opção de usar file ou form-data. Você pode observar melhor a diferença entre as representações das variantes no Charles.

Content-Transfer-Encoding - descreve a codificação do conteúdo. Poderá ser inexistente em dados de texto.

Para consolidar o material, escreveremos o script ScreenPost, o qual envia capturas de imagem ao servidor:

#include <InternetLib.mqh>

MqlNet INet; // class instance for working

//------------------------------------------------------------------ OnStart
void OnStart()
{
  // opening session
  if (!INet.Open("www.fxmaster.de", 80, "", "", INTERNET_SERVICE_HTTP)) return;

  string giffile=Symbol()+"_"+TimeToString(TimeCurrent(), TIME_DATE)+".gif"; // name of file to be sent
 
  // creating screenshot 800х600px
  if (!ChartScreenShot(0, giffile, 800, 600)) { Print("-err ScreenShot "); return; }
 
  // reading gif file to the array
  int h=FileOpen(giffile, FILE_ANSI|FILE_BIN|FILE_READ); if (h<0) { Print("-err Open gif-file "+giffile); return; }
  FileSeek(h, 0, SEEK_SET);
  ulong n=FileSize(h); // determining the size of file
  uchar gif[]; ArrayResize(gif, (int)n); // creating uichar array according to the size of data
  FileReadArray(h, gif); // reading file to the array
  FileClose(h); // closing the file
 
  // creating file to be sent
  string sendfile="sendfile.txt";
  h=FileOpen(sendfile, FILE_ANSI|FILE_BIN|FILE_WRITE); if (h<0) { Print("-err Open send-file "+sendfile); return; }
  FileSeek(h, 0, SEEK_SET);

  // forming a request
  string bound="++1BEF0A57BE110FD467A++"; // separator of data in the request
  string Head="Content-Type: multipart/form-data; boundary="+bound+"\r\n"; // header
  string Path="/mt5screen/screen.php"; // path to the page
 
  // writing data
  FileWriteString(h, "\r\n--"+bound+"\r\n");
  FileWriteString(h, "Content-Disposition: form-data; name=\"EA\"\r\n"); // the "name of EA" field
  FileWriteString(h, "\r\n");
  FileWriteString(h, "NAME_EA");
  FileWriteString(h, "\r\n--"+bound+"\r\n");
  FileWriteString(h, "Content-Disposition: file; name=\"data\"; filename=\""+giffile+"\"\r\n"); // field of the gif file
  FileWriteString(h, "Content-Type: image/gif\r\n");
  FileWriteString(h, "Content-Transfer-Encoding: binary\r\n");
  FileWriteString(h, "\r\n");
  FileWriteArray(h, gif); // writing gif data
  FileWriteString(h, "\r\n--"+bound+"--\r\n");
  FileClose(h); // closing the file

  tagRequest req; // initialization of parameters
  req.Init("POST", Path, Head, sendfile, true, "answer.htm", true);
 
  if (INet.Request(req)) Print("-err Request"); // sending the request to the server
  else Print("+ok Request");
} 

O script do servidor que recebe a informação:

<?php
$ea=$_POST['EA'];
$data=file_get_contents($_FILES['data']['tmp_name']); // information in the file
$file=$_FILES['data']['name'];
$h=fopen(dirname(__FILE__)."/$ea/$file", 'wb'); // creating a file in the EA folder
fwrite($h, $data); fclose($h); // saving data
?>
    

é altamente recomendo que você se familiarize com as regras de recebimento de arquivos do servidor para evitar problemas de segurança!


Trabalhar com Cookies

Este assunto será descrito brevemente em adição à lição anterior para que você pense mais a respeito de suas funcionalidades.

Como você sabe, Cookies têm a função de evitar que os servidores façam solicitações contínuas de detalhes pessoais. Uma vez que um servidor recebe do usuário os detalhes pessoais requeridos para a sessão de trabalho atual, ele armazena um arquivo de texto com estas informações no computador do usuário. Mais tarde, quando o usuário acessa outras páginas, o servidor não solicita aquelas mesmas informações do usuário; ele recebe as informações do cache do navegador.

Por exemplo, quando você habilita a opção "Continuar conectado" ao fazer a autorização no servidor www.mql5.com, você salva um Cookie com os seus detalhes em seu computador. Na sua próxima visita ao website, o navegador irá transmitir o Cookie ao servidor sem lhe perguntar.

Caso tenha interesse, você pode abrir a pasta (WinXP) C:\Documents and Settings\\Cookies e visualizar o conteúdo dos diferentes websites que você visitou.

Em relação as nossa necessidades, os Cookies podem ser usados para ler as suas páginas do fórum do MQL5. Em outras palavras, você lerá as informações como se você estivesse autorizado no website com o seu login e então você irá analisar as páginas obtidas. A melhor alternativa é analisar Cookies utilizando um servidor proxy local Charles. Ele mostra informações detalhadas sobre todas as solicitações recebidas/enviadas, incluindo Cookies.

Por exemplo:

  • Um Expert Advisor (ou um aplicativo externo) que solicita a página https://www.mql5.com/pt/job uma vez por hora e recebe a lista de novas ofertas de emprego.
  • Além disso, ele também solicita uma ramificação, a página https://www.mql5.com/en/forum/53, por exemplo, e verifica se há novas mensagens.
  • Ademais, ele poderá verificar se há ou não novas "mensagens privadas" nos fóruns.

A função InternetSetCookie é utilizada para estabelecer um Cookie em uma solicitação.

BOOL InternetSetCookie(
__in LPCTSTR lpszUrl,
__in LPCTSTR lpszCookieName,
__in LPCTSTR lpszCookieData
);

  • lpszUrl [in] - Nome de um servidor, por exemplo, www.mql5.com
  • lpszCookieName [in]- Nome de um Cookie
  • lpszCookieData [in] - Dados para o Cookie

Para estabelecer diversos Cookies, utilize esta função para cada um deles.

Uma característica interessante: você pode utilizar InternetSetCookie a qualquer tempo, mesmo quando você não estiver conectado ao servidor.


Conclusão

Nós nos familiarizamos com outros tipos de solicitações HTTP, aprendemos a possibilidade de enviar arquivos binários, o que permite aumentar a facilidade de trabalhar com os seus servidores; e aprendemos os métodos para trabalhar com Cookies.

é possível determinar a seguinte lista de direções de desenvolvimentos futuros:

  • Organização de armazenamento remoto de relatórios;
  • Troca de arquivos entre usuários, atualização de versões de Expert Advisors/Indicadores.
  • Criação de rastreadores personalizados que trabalham na sua conta e monitoram a atividade em um website.


Links úteis

  1. Um servidor proxy para visualizar os cabeçalhos enviados - http://www.charlesproxy.com/
  2. Descrição do WinHTTP - http://msdn.microsoft.com/en-us/library/aa385331%28VS.85%29.aspx
  3. Descrição da Sessão HTTP - http://msdn.microsoft.com/en-us/library/aa384322%28VS.85%29.aspx
  4. O kit de ferramentas Denwer para uma instalação local de Apache+PHP - http://www.denwer.ru/
  5. Tipos de cabeçalhos de solicitação - http://www.codenet.ru/webmast/php/HTTP-POST.php#part_3_2
  6. Tipos de solicitações - http://www.w3.org/TR/REC-html40/interact/forms.html#form-content-type
  7. Tipos de solicitações - ftp://ftp.isi.edu/in-notes/iana/assignments/media-types/media-types.
  8. Estrutura do uso de HINTERNET - http://msdn.microsoft.com/en-us/library/aa383766%28VS.85%29.aspx
  9. Trabalhando com arquivos - http://msdn.microsoft.com/en-us/library/aa364232%28VS.85%29.aspx
  10. Tipos de dados para passar a MQL - http://msdn.microsoft.com/en-us/library/aa383751%28VS.85%29.aspx

Traduzido do russo pela MetaQuotes Ltd.
Artigo original: https://www.mql5.com/ru/articles/276

Arquivos anexados |
metaswap.zip (0.66 KB)
screenpost.zip (0.33 KB)
internetlib.mqh (12.82 KB)
screenpost.mq5 (2.63 KB)
metaswap.mq5 (4.84 KB)
Aplicação da transformada de Fisher e da transformada inversa de Fisher à análise de mercado no MetaTrader 5 Aplicação da transformada de Fisher e da transformada inversa de Fisher à análise de mercado no MetaTrader 5
Sabemos que a função de densidade de probabilidade (PDF) de um ciclo de mercado não se parece com uma curva de Gauss e sim com uma PDF de onda senoidal e que a maioria dos indicadores supõe que a PDF de ciclo de mercado seja uma curva de Gauss, precisamos encontrar uma maneira de "corrigir" isso. A solução é utilizar a transformada de Fisher. A transformada de Fisher faz com que a PDF de qualquer forma de onde se aproxime a uma onda de Gauss. Este artigo descreve a matemática por trás da transformada de Fisher e da transformada inversa de Fisher e sua aplicação a negociação. Um módulo de sinal de negócio proprietário com base na transformada inversa de Fisher é apresentada e avaliada.
A Implementação da Análise Automática das Ondas de Elliott em MQL5 A Implementação da Análise Automática das Ondas de Elliott em MQL5
Um dos métodos mais populares de análise do mercado é o princípio das ondas de Elliott. No entanto, este processo é muito complicado, o que leva à utilização de ferramentas adicionais. Um desses instrumentos é o marcador automático. Este artigo descreve a criação de um analisador automático de ondas de Elliott na linguagem MQL5.
Como Adicionar Novas Linguagens de IU na Plataforma MetaTrader 5 Como Adicionar Novas Linguagens de IU na Plataforma MetaTrader 5
A interface do usuário da plataforma MetaTrader 5 é traduzido em vários idiomas. Não se preocupe se a sua língua materna não está entre as suportados. Você pode facilmente completar a tradução usando o utilitário especial MetaTrader MultiLanguage Pack, oferecido pela MetaQuotes Corp. gratuitamente para todos os clientes. Neste artigo mostraremos alguns exemplos de como adicionar linguagens de interface de usuário para a plataforma do MetaTrader 5.
Diminuindo o Consumo de Memória pelos Indicadores Auxiliares Diminuindo o Consumo de Memória pelos Indicadores Auxiliares
Se um indicador usa valores de muitos outros indicadores para seus cálculos, ele consome muita memória. O artigo descreve diversos métodos para diminuir o consumo de memória quando estiver usando indicadores auxiliares. A memória salva permite o aumento de pares de moedas, indicadores e estratégias usados simultaneamente no terminal cliente. Ele aumenta a confiabilidade do portfólio comercial. Esse cuidado simples sobre os recursos técnicos do seu computador pode se transformar em recursos monetários em seu depósito.