Olá, pessoal!
Boa tarde!

Neste post, vou demonstrar mais uma vez a utilização de OLE Automation no SQL Server para consumir os dados de um serviço da Web. Dessa vez, vou consumir o serviço dos Correios para calcular prazo e valor do frete (muito utilizado pra e-Commerce).

Conhecendo o WebService dos Correios

Antes de iniciarmos a criação da Stored Procedure que irá consultar os dados, precisamos primeiro entender os parâmetros e flags do serviço dos Correios.

WebService Correios - Parâmetros de Entrada

CampoTipoObrigatórioDescrição
nCdEmpresaStringNão. O parâmetro tem que ser passado mesmo vazio.Seu código administrativo junto à ECT. O código está disponível no corpo do contrato firmado com os Correios.
sDsSenhaStringNão. O parâmetro tem que ser passado mesmo vazio.Senha para acesso ao serviço associada ao seu código administrativo. A senha inicial corresponde aos 8 primeiros dígitos do CNPJ informado no contrato.
nCdServicoStringSimCódigo do serviço
sCepOrigemStringSimCEP de Origem sem hífen.Exemplo: 05311900
sCepDestinoStringSimCEP de Destino sem hífen
nVlPesoDecimalSimPeso da encomenda incluindo sua embalagem. O peso deve ser informado em quilogramas.
nCdFormatoIntSimFormato da encomenda (incluindo embalagem). 1 – Formato caixa/pacote / 2 – Formato rolo/prisma
nVlComprimentoDecimalSimComprimento da encomenda (incluindo embalagem) em centímetros.
nVlAlturaDecimalSimAltura da encomenda (incluindo embalagem) em centímetros.
nVlLarguraDecimalSimLargura da encomenda (incluindo embalagem) em centímetros.
nVlDiametroDecimalSimDiâmetro da encomenda (incluindo embalagem) em centímetros.
sCdMaoPropriaStringSimIndica se a encomenda será entregue com o serviço adicional mão própria. Valores possíveis: S ou N (S – Sim / N – Não)
nVlValorDeclaradoDecimalSimIndica se a encomenda será entregue com o serviço adicional valor declarado. Neste campo deve ser apresentado o valor declarado desejado em Reais.
sCdAvisoRecebimentoStringSimIndica se a encomenda será entregue com o serviço adicional aviso de recebimento. Valores possíveis: S ou N (S – Sim / N – Não)
StrRetornoStringSimIndica a forma de retorno da consulta. XML = Resultado em XML / Popup = Resultado em uma janela popup / <URL> = Resultado via post em uma página do requisitante

WebService Correios - Parâmetros de Retorno

Parâmetro de SaídaDescrição
CodigoCódigo do Serviço de Entrega.
ValorValorDeclaradoPreço do serviço adicional Valor Declarado.
ValorPreço total da encomenda em Reais incluindo os preços dos serviços opcionais.
ValorMaoPropriaPreço do serviço adicional Mão Própria.
ValorAvisoRecebimentoPreço do serviço adicional Aviso de Recebimento.
PrazoEntregaPrazo estimado em dias para entrega do produto. Se o valor retornado for 0 (zero) indica que o prazo não foi retornado corretamente.
EntregaDomiciliarInforma se a localidade informada possui entrega domiciliária. Se o prazo não for retornado corretamente o retorno deste parâmetro será vazio.
EntregaSabadoInforma se a localidade informada possui entrega domiciliária aos sábados. Se o prazo não for retornado corretamente o retorno deste parâmetro será vazio.
ErroOs mesmos do Web Services.
MsgErroRetorna a descrição do erro gerado.

WebService Correios - Códigos de Serviço

Códigos de Serviço
41106PAC sem contrato
40010SEDEX sem contrato
40045SEDEX a Cobrar sem contrato
40126SEDEX a Cobrar com contrato
40215SEDEX 10 sem contrato
40290SEDEX Hoje sem contrato
40096SEDEX com contrato
40436SEDEX com contrato
40444SEDEX com contrato
81019e-SEDEX com contrato
41068PAC com contrato
40568SEDEX com contrato
40606SEDEX com contrato
81868(Grupo 1) e-SEDEX com contrato
81833(Grupo 2) e-SEDEX com contrato
81850(Grupo 3) e-SEDEX com contrato

Criando a Stored Procedure para consultar os dados

Com o trecho de código abaixo, iremos criar a Stored Procedure que iremos utilizar para consultar os dados de valor do frete e prazo de entrega utilizando procedures OLE Automation para realizar a requisição GET e retornar o XML da Web, que iremos ler utilizando XQuery.

CREATE PROCEDURE dbo.stpConsulta_Frete_Correios (
    @sCepOrigem VARCHAR(12),
    @sCepDestino VARCHAR(12),
    @nCdServico INT,
    @nVlPeso FLOAT = 0.1,
    @nCdFormato SMALLINT = 1,
    @nVlComprimento INT = 20,
    @nVlAltura INT = 5,
    @nVlLargura INT = 15,
    @nVlDiametro INT = 0,
    @CdMaoPropria CHAR(1) = 'n',
    @nVlValorDeclarado FLOAT = 0,
    @CdAvisoRecebimento CHAR(1) = 'n'
)
AS BEGIN
 
 
    DECLARE 
        @obj INT,
        @Url VARCHAR(500),
        @resposta VARCHAR(8000),
        @xml XML
        
        
        
    -- Recupera apenas os números do CEP de Origem
    DECLARE @startingIndex INT = 0
    
    WHILE (1=1)
    BEGIN
      
        SET @startingIndex = PATINDEX('%[^0-9]%', @sCepOrigem)  
        
        IF (@startingIndex <> 0)
            SET @sCepOrigem = REPLACE(@sCepOrigem, SUBSTRING(@sCepOrigem, @startingIndex, 1), '')  
        ELSE    
            BREAK
            
    END
    
    
    
    -- Recupera apenas os números do CEP de Destino
    SET @startingIndex = 0
    
    WHILE (1=1)
    BEGIN
      
        SET @startingIndex = PATINDEX('%[^0-9]%', @sCepDestino)  
        
        IF (@startingIndex <> 0)
            SET @sCepDestino = REPLACE(@sCepDestino, SUBSTRING(@sCepDestino, @startingIndex, 1), '')  
        ELSE    
            BREAK
            
    END
        
 
 
    SET @Url = 'http://ws.correios.com.br/calculador/CalcPrecoPrazo.aspx?' + 
    'sCepOrigem=' + @sCepOrigem + 
    '&sCepDestino=' + @sCepDestino + 
    '&nVlPeso=' + CAST(@nVlPeso AS VARCHAR(20)) + 
    '&nCdFormato=' + CAST(@nCdFormato AS VARCHAR(20)) + 
    '&nVlComprimento=' + CAST(@nVlComprimento AS VARCHAR(20)) + 
    '&nVlAltura=' + CAST(@nVlAltura AS VARCHAR(20)) + 
    '&nVlLargura=' + CAST(@nVlLargura AS VARCHAR(20)) + 
    '&sCdMaoPropria=' + @CdMaoPropria + 
    '&nVlValorDeclarado=' + CAST(@nVlValorDeclarado AS VARCHAR(20)) + 
    '&sCdAvisoRecebimento=' + @CdAvisoRecebimento + 
    '&nCdServico=' + CAST(@nCdServico AS VARCHAR(20)) + 
    '&nVlDiametro=' + CAST(@nVlDiametro AS VARCHAR(20)) + '&StrRetorno=xml'
 
    EXEC sys.sp_OACreate 'MSXML2.ServerXMLHTTP', @obj OUT
    EXEC sys.sp_OAMethod @obj, 'open', NULL, 'GET', @Url, FALSE
    EXEC sys.sp_OAMethod @obj, 'send'
    EXEC sys.sp_OAGetProperty @obj, 'responseText', @resposta OUT
    EXEC sys.sp_OADestroy @obj
    
    SET @xml = @resposta COLLATE SQL_Latin1_General_CP1251_CS_AS
    
    
    SELECT
        @xml.value('(/Servicos/cServico/Codigo)[1]', 'bigint') AS Codigo_Servico,
        @xml.value('(/Servicos/cServico/Valor)[1]', 'varchar(20)') AS Valor_Frete,
        @xml.value('(/Servicos/cServico/PrazoEntrega)[1]', 'int') AS Prazo_Entrega,
        @xml.value('(/Servicos/cServico/ValorSemAdicionais)[1]', 'varchar(20)') AS Valor_Sem_Adicionais,
        @xml.value('(/Servicos/cServico/ValorMaoPropria)[1]', 'varchar(20)') AS Valor_Entrega_Em_Maos,
        @xml.value('(/Servicos/cServico/ValorAvisoRecebimento)[1]', 'varchar(20)') AS Valor_Aviso_Recebimento,
        @xml.value('(/Servicos/cServico/EntregaDomiciliar)[1]', 'varchar(20)') AS Entrega_Domiciliar,
        @xml.value('(/Servicos/cServico/EntregaDomiciliar)[1]', 'varchar(1)') AS Entrega_Domiciliar,
        @xml.value('(/Servicos/cServico/EntregaSabado)[1]', 'varchar(1)') AS Entrega_Sabado,
        @xml.value('(/Servicos/cServico/Erro)[1]', 'int') AS Codigo_Erro,
        @xml.value('(/Servicos/cServico/MsgErro)[1]', 'varchar(500)') AS Mensagem_Erro
        
 
END

Exemplos de uso

Realizando um teste simples, preenchendo só os parâmetros obrigatórios

WebService Correios - Teste simples
WebService Correios - Teste simples

Realizando um teste mais completo, preenchendo todos os parâmetros da SP

WebService Correios - Teste completo
WebService Correios - Teste completo

Chamando a SP, mas informando um CEP inválido

WebService Correios - CEP inválido
WebService Correios - CEP inválido

É isso aí, pessoal!
Até o próximo post!