Chamada via web service SOAP
Existe uma limitação no tamanho do pacote a ser enviada para nosso web service de integração com o Mega, onde caso o xml a ser enviado tenha um tamanho superior a 1,5Mb, o xml e o processo de envio necessitam ser particionados, e ser enviado uma porção do xml de cada vez.
Funcionamento
Para o envio do xml em partes, o web service deverá se ser chamado uma vez para cada parte e conforme as partes são enviadas elas ficarão salvas em disco no servidor, assim quando a última parte for enviada todas as outras partes já enviadas serão concatenadas formando novamente o xml e assim dando início ao processo de integração.
A primeira chamada deverá ter o parâmetro 'pPrimeiraParte' com o valor 'true' para indicar que é o início do envio, assim como a última parte também deverá ter o parâmetro 'pUltimaParte' com o valor 'true' para indicar o fim do envio. Ainda na primeira chamada o parâmetro pGUID pode ter o seu valor vazio, uma vez que esse parâmetro será utilizado nas próximas chamadas.
Quando a primeira parte do xml chegar no server, será gerado um 'GUID'(Identificador único universal) aleatoriamente, que será o retorno da primeira chamada dentro da tag 'Mensagem' do xml. Esse 'GUID' será utilizado para compor o nome de cada parte do xml salvo em disco, de forma que o nome será formado pelo 'GUID' seguido da ordem da parte, por exemplo, 1 para primeira parte, 2 para a segunda parte e assim por diante. Por isso, a necessidade de se passar no parâmetro 'pGuid'.
O 'GUID' gerado na primeira chamada e em todas as demais, é o que determina a ligação entre as partes do xml. Para as demais partes, com exceção da última, a chamada deverá ser feita passando os parâmetros 'pPrimeiraParte' e 'pUltimaParte' com valor false. No parâmetro 'pNumeroParte' deverá ser passado o número da parte a ser enviada, e por fim o parâmetro 'pXml' com o valor da parte a ser enviada. A chamada da última parte é igual as demais, com exceção do parâmetro 'pUltimaParte', que deverá ter o valor 'true'.
Ao chegar no servidor a última parte, será feita uma busca por todos os arquivos que comecem com o 'GUID passado por parâmetro e o conteúdo dos arquivos será concatenado na sequência, para então formar o xml a ser processado pelo Integrador.
A responsabilidade de verificar o tamanho do xml é da aplicação que consome o serviço.
O tamanho máximo de uma parte do xml ou do xml inteiro deve ser de 1,5MB, ou transformado em string, a propriedade Length deverá ser menor que 1572864 caracteres.
O retorno da primeira chamada irá retornar um xml em string ou não, dependendo do método, o 'GUID' terá de ser extraído de dentro da tag 'Mensagem'.
Resposta
Existem dois métodos para enviar o xml em partes que diferem pelo seu retorno: o método IntegraXml retorna um xml e o método IntegraXmlString retorna o xml no formato de string.
Exemplo do retorno em forma de xml do método IntegraXml:
<?xml version="1.0" encoding="utf-8"?>
<SOAP-ENV:Envelope xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:HNS="http://tempuri.org/" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:v1="http://tempuri.org/">
<SOAP-ENV:Header>
<ROClientIDHeader SOAP-ENV:mustUnderstand="0" xmlns="urn:DefaultLibrary">
<ID>{79F10A36-B949-4D29-8259-DFB6DE03BD50}</ID>
</ROClientIDHeader>
</SOAP-ENV:Header>
<SOAP-ENV:Body xmlns:ro="http://tempuri.org/">
<v1:MegaIntegradorService___IntegraXMLPartesResponse>
<v1:Result>
<v1:Erro>false</v1:Erro>
<v1:Mensagem>{17CD37B8-6929-458E-9596-7DE71761D758}</v1:Mensagem>
<v1:CodTransacao>0</v1:CodTransacao>
<v1:PKMega>
</v1:PKMega>
</v1:Result>
</v1:MegaIntegradorService___IntegraXMLPartesResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
Exemplo do retorno em forma de string do método IntegraXmlString:
<?xml version="1.0" encoding="utf-8"?>
<SOAP-ENV:Envelope xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:HNS="http://tempuri.org/" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:v1="http://tempuri.org/">
<SOAP-ENV:Header>
<ROClientIDHeader SOAP-ENV:mustUnderstand="0" xmlns="urn:DefaultLibrary">
<ID>{3C441095-BE6A-48DE-A7D8-89380452F11D}</ID>
</ROClientIDHeader>
</SOAP-ENV:Header>
<SOAP-ENV:Body xmlns:ro="http://tempuri.org/">
<v1:MegaIntegradorService___IntegraXMLPartesStringResponse>
<v1:Result><Resultado><Erro>False</Erro><Mensagem>{5512BC3A-1FB4-41B3-960A-A15D39D0B1CC}</Mensagem><CodTransacao>0</CodTransacao><PKMega></PKMega></Resultado></v1:Result>
</v1:MegaIntegradorService___IntegraXMLPartesStringResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
Exemplos
Implementação em C# .NET.
Consumindo em C#
Nos links abaixo são exibidos códigos fontes de exemplos, onde é feita uma chamada utilizando a classe IntegradorRequestSoap, que é encarregada de fazer a chamada SOAP.
Chamada
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
namespace Mega.Integrador.WebRequest.Soap
{
public class MegaIntegradorClient
{
public XmlDocument IntegraXML(string pServidor, int pPorta, int pPRO_IN_CODIGO, int pUSU_IN_CODIGO, string pXML, string pXMLHeader, string pObs, string pEnviaRecebe, int pTransacao = 0, int ptimeOut = 360000)
{
Mega.Integrador.WebRequest.Soap.IntegradorRequestSoap request = new IntegradorRequestSoap();
string metodo = "IntegraXML";
string responsePrimeiroParte = String.Empty;
string response = String.Empty;
var partesXML = request.QuebraString(pXML);
if(partesXML.Count > 1)
{
metodo = "IntegraXMLPartes";
responsePrimeiroParte = request.CallWebService(pServidor, pPorta, pPRO_IN_CODIGO, pUSU_IN_CODIGO, partesXML[0], pXMLHeader, pObs, pEnviaRecebe, pTransacao, ptimeOut, metodo,"",true);
int indexInicioAux = responsePrimeiroParte.IndexOf("<v1:Mensagem>");
int indexFimAux = responsePrimeiroParte.IndexOf("</v1:Mensagem>");
responsePrimeiroParte = responsePrimeiroParte.Substring(indexInicioAux, indexFimAux - indexInicioAux).Replace("<v1:Mensagem>", "").Replace("</v1:Mensagem>", "");
for (int i = 1; i < partesXML.Count - 1; i++)
{
request.CallWebService(pServidor, pPorta, pPRO_IN_CODIGO, pUSU_IN_CODIGO, partesXML[i], pXMLHeader, pObs, pEnviaRecebe, pTransacao, ptimeOut, metodo, responsePrimeiroParte,false,i + 1);
}
response = request.CallWebService(pServidor, pPorta, pPRO_IN_CODIGO, pUSU_IN_CODIGO, partesXML[partesXML.Count - 1], pXMLHeader, pObs, pEnviaRecebe, pTransacao, ptimeOut, metodo, responsePrimeiroParte, false, partesXML.Count, true);
}
else
{
response = request.CallWebService(pServidor, pPorta, pPRO_IN_CODIGO, pUSU_IN_CODIGO, pXML, pXMLHeader, pObs, pEnviaRecebe, pTransacao, ptimeOut, metodo);
}
XmlDocument responseDocXml = new XmlDocument();
responseDocXml.LoadXml(response);
return responseDocXml;
}
public string IntegraXMLString(string pServidor, int pPorta, int pPRO_IN_CODIGO, int pUSU_IN_CODIGO, string pXML, string pXMLHeader, string pObs, string pEnviaRecebe, int pTransacao = 0, int ptimeOut = 360000)
{
Mega.Integrador.WebRequest.Soap.IntegradorRequestSoap request = new IntegradorRequestSoap();
string metodo = "IntegraXMLString";
string responsePrimeiroParte = String.Empty;
string response = String.Empty;
var partesXML = request.QuebraString(pXML);
if(partesXML.Count > 1)
{
metodo = "IntegraXMLPartesString";
responsePrimeiroParte = request.CallWebService(pServidor, pPorta, pPRO_IN_CODIGO, pUSU_IN_CODIGO, partesXML[0], pXMLHeader, pObs, pEnviaRecebe, pTransacao, ptimeOut, metodo, "", true);
int indexInicioAux = responsePrimeiroParte.IndexOf("<v1:Mensagem>");
if (indexInicioAux < 0)
indexInicioAux = responsePrimeiroParte.IndexOf("Mensagem>");
int indexFimAux = responsePrimeiroParte.IndexOf("</v1:Mensagem>");
if (indexFimAux < 0)
indexFimAux = responsePrimeiroParte.IndexOf("</Mensagem>");
responsePrimeiroParte = responsePrimeiroParte.Substring(indexInicioAux, indexFimAux - indexInicioAux).Replace("<v1:Mensagem>", "").Replace("</v1:Mensagem>", "").Replace("Mensagem>", "").Replace("</Mensagem>", "");
for (int i = 1; i < partesXML.Count - 1; i++)
{
request.CallWebService(pServidor, pPorta, pPRO_IN_CODIGO, pUSU_IN_CODIGO, partesXML[i], pXMLHeader, pObs, pEnviaRecebe, pTransacao, ptimeOut, metodo, responsePrimeiroParte, false, i + 1);
}
response = request.CallWebService(pServidor, pPorta, pPRO_IN_CODIGO, pUSU_IN_CODIGO, partesXML[partesXML.Count - 1], pXMLHeader, pObs, pEnviaRecebe, pTransacao, ptimeOut, metodo, responsePrimeiroParte, false, partesXML.Count, true);
}
else
{
response = request.CallWebService(pServidor, pPorta, pPRO_IN_CODIGO, pUSU_IN_CODIGO, pXML, pXMLHeader, pObs, pEnviaRecebe, pTransacao, ptimeOut, metodo);
}
int indexInicio = response.IndexOf("<v1:Result>");
int indexFim = response.IndexOf("</v1:Result>");
return response.Substring(indexInicio, indexFim - indexInicio).Replace("v1:","");
}
}
}
Fonte da classe IntegradorRequestSoap
Classe encarregada de montar o pacote da chamada SOAP e consumir o webservice, devolvendo uma string com o xml do resultado:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Xml;
using System.IO;
using System.Net;
namespace Mega.Integrador.WebRequest.Soap
{
public classIntegradorRequestSoap
{
internal string CallWebService(string pServidor, int pPorta, int pPRO_IN_CODIGO, int pUSU_IN_CODIGO, string pXML, string pXMLHeader, string pObs, string pEnviaRecebe, int pTransacao = 0, int pTimeOut = 360000, string pMetodo = "IntegraXML", string pGuidMedateXml = "", bool pPrimeiraParte = false, int pNumeroParte = 1, bool pUltimaParte = false)
{
var _url = "http://" + pServidor + ":" + pPorta.ToString() + "/Integrador";
var _action = pMetodo;
XmlDocument soapEnvelopeXml = CreateSoapEnvelope(pPRO_IN_CODIGO, pUSU_IN_CODIGO, pXML, pXMLHeader, pObs, pEnviaRecebe, pTransacao, pMetodo, pGuidMedateXml, pPrimeiraParte, pNumeroParte, pUltimaParte );
HttpWebRequest webRequest = CreateWebRequest(_url, _action, pTimeOut);
InsertSoapEnvelopeIntoWebRequest(soapEnvelopeXml, webRequest);
//Início do web request assíncrono.
IAsyncResult asyncResult = webRequest.BeginGetResponse(null, null);
asyncResult.AsyncWaitHandle.WaitOne();
//Recuperando a resposta da requisição web completa.
string soapResult;
using (WebResponse webResponse = webRequest.EndGetResponse(asyncResult))
{
using (StreamReader rd = new StreamReader(webResponse.GetResponseStream()))
{
soapResult = rd.ReadToEnd();
}
Console.Write(soapResult);
return soapResult;
}
}
private HttpWebRequest CreateWebRequest(string url, string action, int timeOut)
{
HttpWebRequest webRequest = (HttpWebRequest)System.Net.WebRequest.Create(url);
webRequest.Headers.Add("SOAPAction", action);
webRequest.ContentType = "application/x-www-form-urlencoded";
webRequest.Accept = "text/xml";
webRequest.Method = "POST";
webRequest.Timeout = timeOut;
return webRequest;
}
private XmlDocument CreateSoapEnvelope(int pPRO_IN_CODIGO, int pUSU_IN_CODIGO, string pXML, string pXMLHeader, string pObs, string pEnviaRecebe, int pTransacao, string metodo = "IntegraXML", string pGuidMedateXml = "", bool pPrimeiraParte = false, int pNumeroParte = 1, bool pUltimaParte = false)
{
XmlDocument soapEnvelop = new XmlDocument();
StringBuilder str = new StringBuilder();
str.AppendLine("<?xml version=\"1.0\" encoding=\"utf-8\"?>");
str.AppendLine("<SOAP-ENV:Envelope xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\"");
str.AppendLine("xmlns:xsi=\"http://www.w3.org/1999/XMLSchema-instance\"");
str.AppendLine("xmlns:xsd=\"http://www.w3.org/1999/XMLSchema\"> ");
str.AppendLine("<SOAP-ENV:Body>");
str.AppendLine("<" + metodo + " xmlns=\"MegaIntegradorService\"");
str.AppendLine("SOAP-ENV:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">");
str.AppendLine("<pPRO_IN_ID xsi:type=\"xsd:integer\">" + pPRO_IN_CODIGO.ToString() + "</pPRO_IN_ID>");
str.AppendLine("<pUSU_IN_CODIGO xsi:type=\"xsd:integer\">" + pUSU_IN_CODIGO.ToString() + "</pUSU_IN_CODIGO>");
str.AppendLine("<pXML xsi:type=\"xsd:string\"><![CDATA[" + pXML + "]]></pXML>");
if (metodo == "IntegraXMLPartes" || metodo == "IntegraXMLPartesString")
str.AppendLine("<pGuidFile xsi:type=\"xsd:string\">" + pGuidMedateXml + "</pGuidFile>");
str.AppendLine("<pXMLHeader xsi:type=\"xsd:string\"> " + pXMLHeader + "</pXMLHeader>");
str.AppendLine("<pObs xsi:type=\"xsd:string\">" + pObs + "</pObs>");
str.AppendLine("<pEnviaRecebe xsi:type=\"xsd:string\">" + pEnviaRecebe + "</pEnviaRecebe>");
str.AppendLine("<pTransacao xsi:type=\"xsd:integer\">" + pTransacao.ToString() + "</pTransacao> ");
if (metodo == "IntegraXMLPartes" || metodo == "IntegraXMLPartesString")
{
str.AppendLine("<pPrimeiraParte xsi:type=\"xsd:boolean\">" + Convert.ToInt32(pPrimeiraParte).ToString() + "</pPrimeiraParte> ");
str.AppendLine("<pNumeroParte xsi:type=\"xsd:integer\">" + pNumeroParte.ToString() + "</pNumeroParte> ");
str.AppendLine("<pUltimaParte xsi:type=\"xsd:boolean\">" + Convert.ToInt32(pUltimaParte).ToString() + "</pUltimaParte> ");
}
str.AppendLine("</" + metodo + ">");
str.AppendLine("</SOAP-ENV:Body>");
str.AppendLine("</SOAP-ENV:Envelope>");
soapEnvelop.LoadXml(str.ToString());
return soapEnvelop;
}
private void InsertSoapEnvelopeIntoWebRequest(XmlDocument soapEnvelopeXml, HttpWebRequest webRequest)
{
using (Stream stream = webRequest.GetRequestStream())
{
soapEnvelopeXml.Save(stream);
}
}
public List<string> QuebraString(string pXml)
{
int tamanhoLimitParteXml = 1572864;// ~ 1,5Mb
List<string> resultado = new List<string>();
if (pXml.Length > tamanhoLimitParteXml)
{
int partes = pXml.Length / tamanhoLimitParteXml;
int restoDivisao = pXml.Length % tamanhoLimitParteXml;
if (restoDivisao > 0)
partes++;
resultado.Add(pXml.Substring(0, tamanhoLimitParteXml));
for (int vContador = 1; vContador < partes - 1; vContador++)
{
resultado.Add(pXml.Substring(tamanhoLimitParteXml * vContador, tamanhoLimitParteXml));
}
int inicioUltimaParte = tamanhoLimitParteXml * (partes - 1);
resultado.Add(pXml.Substring(inicioUltimaParte, pXml.Length - inicioUltimaParte));
}
else
resultado.Add(pXml);
return resultado;
}
}
}