NAME

WWW::Correios::SIGEP - API para o Gerenciador de Postagem dos Correios (SIGEP WEB)

SYNOPSIS

    use WWW::Correios::SIGEP;

    my $correios = WWW::Correios::SIGEP->new(
        codigo        => ..., # codigo administrativo
        identificador => ..., # CNPJ da empresa
        usuario       => ...,
        senha         => ...,
    );

    # consulta detalhes do cliente (serviços disponíveis, etc)
    my $cliente = $correios->busca_cliente(
        contrato        => ...,
        cartao_postagem => ...,
    );

    # consulta endereços por CEP
    my $cep = $correios->consulta_cep( '70002900' );
    say $cep->{cidade};
    say $cep->{endereco};

    # descobre se determinado serviço está disponível (e-SEDEX, etc)
    my $servico_disponivel = $correios->servico_disponivel(
        codigo_servico => '40215,81019',
        cep_origem     => '70002900',
        cep_destino    => '22241000',
    );

    # seu cartão de postagem ainda é válido?
    my $valido = $correios->cartao_valido( '1234567890' );

    # solicita uma ou mais etiquetas para postagem futura
    my @etiquetas = $correios->solicita_etiquetas(10);

    # gera Pré-lista de Postagem (PLP) de objetos:
    my $id_plp = $correios->fecha_plp_varios_servicos( \%dados_postagem );

    # consulta PLPs:
    my $res = $correios->status_plp( $id_plp );

DESCRIPTION

This module provides a way to query the Brazilian Postal Office (Correios) SIGEP WEB Interface, an API to manage postal packages. Since the main target for this module is Brazilian developers, the documentation is provided in portuguese only. If you need help with this module please contact the author.

DESCRIÇÃO

Os Correios disponibilizam gratuitamente para todos os clientes com contrato uma API para o sistema gerenciador de postagens SIGEP WEB, que permite a automatização de serviços como Pré-lista de Postagem (PLP), rastreamento de objetos, disponibilidade de serviços, SEDEX, logística reversa, entre muitos outros.

Este módulo permite uma integação fácil e rápida entre seu produto e a API do SIGEP WEB e de Logística Reversa.

Vale notar que apenas os métodos listados abaixo estão implementados. Se você deseja acesso a qualquer outro método descrito na API do SIGEP acima, favor entrar em contato com o autor ou criar uma issue/pull request no GitHub.

IMPORTANTE: NECESSITA DE CONTRATO COM OS CORREIOS

Este módulo funciona como interface para o Web Service do Sistema Gerenciador de Postagens (SIGEP) dos Correios, para organização de postagens contratadas. Por isso, a maioria dos métodos desta API exige contrato de prestação de serviços firmado entre a sua empresa e os Correios.

Caso não tenha, entre em contato com os Correios para obter seu cartão de parceria empresarial ANTES de tentar usar esse módulo.

MÉTODOS

new( \%opcoes )

    my $sigep = WWW::Correios::SIGEP->new({
        usuario  => 'sigep',
        senha    => 'n5f9t8',
        codigo   => '08082650',
        contrato => '9912208555',
        cartao   => '0057018901',
    });

Cria o objeto cliente das requisições para o SIGEP WEB. Aceita os seguintes parâmetros (parâmetros obrigatórios estão demarcados):

  • usuario [OBRIGATÓRIO] Seu nome de usuário para o Web Service, conforme contrato com os Correios. Se você não passar esse campo durante a inicialização do objeto, precisará passar como valor em cada requisição que exija esse campo (pode ser útil para gerir chamadas com vários contratos diferentes a partir do mesmo objeto).

  • senha [OBRIGATÓRIO] Sua senha para o Web Service, conforme contrato com os Correios. Se você não passar esse campo durante a inicialização do objeto, precisará passar como valor em cada requisição que exija esse campo (pode ser útil para gerir chamadas com vários contratos diferentes a partir do mesmo objeto).

  • contrato OBRIGATÓRIO Número do seu contrato com os Correios. Se você não passar esse campo durante a inicialização do objeto, precisará passar como valor da chave idContrato em todas as operações que exijam esse campo.

  • cartao OBRIGATÓRIO Número do seu cartão com os Correios. Se você não passar esse campo durante a inicialização do objeto, precisará passar como valor da chave idCartaoPostagem em todas as operações que exigam esse campo.

  • sandbox Se verdadeiro, utiliza os endpoints de sandbox dos Correios para todas as chamadas. Utilize esse modo para testar chamadas e valores de resposta da API sem gastar dinheiro ou consumir códigos reais. Note que você ainda precisará passar todos os parâmetros (e eles serão validados da mesma forma). Em teoria, após concluir sua homologação, basta remover essa flag e todas as chamadas continuarão rigorosamente iguais - só que agora custando/valendo de verdade.

  • debug Se verdadeiro, imprime no terminal detalhes do request, response e eventuais erros associados ao envio/recebimento do envelope SOAP. Utilize essa flag para depurar suas chamadas caso acredite que há algum problema na composição do request ou na interpretação da resposta.

  • timeout Timeout em segundos para as requisições à API dos Correios. Padrão 180 segundos (2 minutos).

  • precompile O sistema dos Correios utiliza SOAP para comunicação com a API. Como a compilação de XML é uma operação custosa (de processamento e memória), por padrão as chamadas a este módulo são todas preguiçosas, ou seja, cada operação é compilada na primeira vez em que é utilizada. Escolhemos essa abordagem para evitar um tempo alto de inicialização (e maior quantidade de memória utilizada) caso apenas uma ou outra operação seja de fato utilizada. Se preferir, pode passar uma lista de operações nesse parâmetro para pré-compilar. Assim, a inicialização do objeto demora um pouco mais, mas não há penalidade durante a primeira execução da operação. Note que você precisará utilizar o nome da operação em camelCase conforme a documentação dos Correios:

       precompile => [ 'solicitaEtiquetas' ]

    Cada método abaixo inclui descrição do nome da chamada feita ao SIGEP WEB, para eventual inclusão nessa lista ou depuração.

busca_cliente()

busca_cliente( \%opcoes )

Método da API SIGEP: buscaCliente

Retorna os serviços disponíveis para o cartão de postagem associado.

    my $cliente = $sigep->busca_cliente;

    say $cliente->{cnpj};

    # salvo casos raros, o importante desse método está aqui:
    my $servicos = $cliente->{contratos}[0]{cartoesPostagem}[0]{servicos};

    foreach my $servico ( @$servicos ) {
        my $id     = $servico->{id};
        my $codigo = $servico->{codigo};
        my $nome   = $servico->{descricao};
        my $jpeg   = $servico->{servicoSigep}{chancela}{chancela};
    }

O conteúdo da variável retornada possui a seguinte estrutura:

   $cliente = {
        dataAtualizacao        => '2014-12-18T14:01:09-02:00',
        datajAtualizacao       => 114352,
        descricaoStatusCliente => 'Ativo',
        horajAtualizacao       => 14109,
        id                     => 279311,
        inscricaoEstadual      => 'ISENTO',         # <-- ATENÇÃO! PODE CONTER ESPAÇOS!
        nome                   => 'ECT',            # <-- ATENÇÃO! PODE CONTER ESPAÇOS!
        cnpj                   => '34028316000103', # <-- ATENÇÃO! PODE CONTER ESPAÇOS!
        statusCodigo           => 1,

        contratos => [
            {
                codigoCliente              => 279311,
                codigoDiretoria            => 10,
                dataAtualizacao            => '2014-11-19T09:50:29-02:00',
                dataAtualizacaoDDMMYYYY    => '',
                datajAtualizacao           => 114323,
                datajVigenciaFim           => 118136,
                datajVigenciaInicio        => 108137,
                dataVigenciaFim            => '2018-05-16T00:00:00-03:00',
                dataVigenciaFimDDMMYYYY    => '',
                dataVigenciaInicio         => '2008-05-16T00:00:00-03:00',
                dataVigenciaInicioDDMMYYYY => '',
                descricaoDiretoriaRegional => 'DR - BRASÍLIA', # <-- ATENÇÃO! ESPAÇOS!
                horajAtualizacao           => 95029,
                statusCodigo               => 'A',

                contratoPK => {
                    diretoria => 10,
                    numero    => 9912208555,
                },

                cartoesPostagem => [
                    {
                        codigoAdministrativo => 08082650,
                        dataAtualizacao      => '2014-12-19T14:46:33-02:00',
                        datajAtualizacao     => 114353,
                        datajVigenciaFim     => 118136,
                        datajVigenciaInicio  => 114129,
                        dataVigenciaFim      => '2018-05-16T00:00:00-03:00',
                        dataVigenciaInicio   => '2014-05-09T00:00:00-03:00',
                        horajAtualizacao     => 144633,
                        numero               => 0057018901,
                        statusCartaoPostagem => 01,
                        statusCodigo         => 'A',
                        unidadeGenerica      => 08,

                        # esse parece ser o único array de verdade
                        servicos => [
                            {
                                codigo             => 40215,
                                dataAtualizacao    => '2014-05-05T13:47:35-03:00',
                                datajAtualizacao   => 114125,
                                descricao          => "SEDEX 10", <-- ATENÇAO! ESPAÇOS!
                                horajAtualizacao   => 134735,
                                id                 => 104707,
                                servicosAdicionais => [ {} ],
                                tipo1Codigo          "CNV",
                                tipo2Codigo          "A",

                                vigencia => {
                                    dataFinal   => '2040-12-31T00:00:00-02:00',
                                    dataInicial => '2001-06-10T00:00:00-03:00',
                                    datajFim    => 140366,
                                    datajIni    => 101161,
                                    id          => 104707
                                }

                                servicoSigep => {
                                    categoriaServico  => 'SERVICO_COM_RESTRICAO',
                                    exigeDimensoes    => 0,
                                    exigeValorCobrar  => 0,
                                    imitm             => 104707,
                                    servico           => 104707,
                                    ssiCoCodigoPostal => 275,

                                    chancela => {
                                        chancela        => (imagem JPEG em binário),
                                        dataAtualizacao => '2013-05-03T00:00:00-03:00',
                                        descricao       => '(104707) SEDEX 10-D',
                                        id              => 20
                                    },
                                },
                            },
                        ],
                    },
                ],
            },
        ],
   };

Nota do autor: Não encontramos documentação a respeito dos parâmetros acima. Os Correios sugerem que apenas os campos id e codigo são relevantes.

Note também que muitos campos vêm com espaços extras no final. Certifique-se de remover espaços se for utilizá-los em seu código.

consulta_cep( $cep )

Método da API SIGEP: consultaCEP

Retorna o endereço atualizado da base dos Correios. Este método não exige contrato e pode ser acessado sem usuário/senha.

    my $dados = $sigep->consulta_cep( '70002900' );  # com ou sem traço

    say $dados->{bairro}

O conteúdo da variável retornada possui a seguinte estrutura:

    $dados = {
        bairro       => "Asa Norte",
        cep          => 70002900,
        cidade       => "Brasília",
        complemento  => "",
        complemento2 => "",
        end          => "SBN Quadra 1 Bloco A",
        id           => 0,
        uf           => "DF"
    };

cartao_valido()

cartao_valido( \%opcoes )

Método da API SIGEP: getStatusCartaoPostagem

Consulta a API e retorna verdadeiro se o cartão ainda está válido, ou falso caso contrário.

    if ( $sigep->cartao_valido ) {
        ...
    }

solicita_etiquetas( $cnpj, $id, $n_etiquetas )

Método da API SIGEP: solicitaEtiquetas

    my $cnpj = '00000000000000';

    # 5 etiquetas para SEDEX com contrato (109811)
    # ATENÇÃO! Você quer o ID do serviço, não o código.
    my @etiquetas = $sigep->solicita_etiquetas( $cnpj, 109811, 5 );

Reserva e retorna uma lista de N códigos de rastreamento (etiquetas) para sua empresa. Ao contrário de uma chamada pura à API do SIGEP WEB, os códigos são retornados já prontos para uso, com dígito verificador.

De nada. :)

fecha_plp_varios_servicos( \%params )

Método da API SIGEP: fechaPlpVariosServicos

    my $id_plp = $sigep->fecha_plp_varios_servicos({
        id => 111111, # inventado pelo seu sistema, até 10 digitos (somente números)

        diretoria             => 10,  # obtido via busca_cliente()
        codigo_administrativo => 111, # obtido via busca_cliente()
        remetente => {
            nome => 'Minha Empresa LTDA',
            logradouro  => 'Minha Rua',
            numero      => 100,   # ou 's/n' para logradouros sem numeracao
            complemento => 302,  # opcional
            bairro      => 'Meu bairro',
            cep         => '111111222', # somente números
            cidade      => 'Minha Cidade',
            estado      => 'XX',
            telefone    => '', # opcional, somente números COM ddd
            fax         => '', # opcional, somente números COM ddd
            email       => '', # opcional
        },
        objetos => [
            # cada pacote vai numa estrutura separada
            {
                etiqueta => 'SS123456789BR', # obtida via solicita_etiquetas()
                codigo_postagem => '41068',  # obtido via busca_cliente()
                tipo => '001', # pode ser 001 (envelope), 002 (caixa) ou 003 (rolo)
                # envelope não precisa de medidas, mas se tipo for caixa (002)
                # você precisa informar "largura", "altura" e "comprimento".
                # Se tipo for rolo (003) você precisa informar "comprimento"
                # e "diametro". Todas as medidas são em centímetros.
                # ex: diametro => 4, comprimento => 10
                peso => 50, # em gramas
                valor_declarado => '50,00', # opcional
                # o servico adicional "25" (Registro Nacional) é obrigatório
                # em PLPs e portanto é sempre enviado. Outros servicos são:
                #   1 - aviso de recebimento
                #   2 - mão própria nacional
                #  19 - valor declarado nacional
                #  35 - carta registrada com valor declarado
                #  37 - aviso de recebimento digital
                #  47 - grandes formatos
                #  49 - devolução de nota fiscal - SEDEX
                #  57 - taxa de entrega de encomenda despadronizada
                #  67 - logística reversa simultânea domiciliária
                #  69 - logística reversa simultânea em agência
                # 107 - cobrança emergencial
                servicos_adicionais => [1,35], # opcionais
                destinatario => {
                    nome => 'Comprador Feliz da Silva',
                    logradouro => 'Rua da Entrega',
                    numero     => 1,  # ou 's/n' para logradouros sem numeracao
                    complemento => 'casa',  # opcional
                    bairro      => 'Bairro Feliz',
                    cidade      => 'Cidade Feliz',
                    uf          => 'ZZ',
                    cep         => '2222233',
                },
            },
        ],
    });

Use esse método para gerar a PLP associada à entrega de um ou mais objetos postais. O valor retornado é o id da PLP gerada, que pode ser consultada via status_plp().

Esse método gera automaticamente o XML a ser enviado para o SIGEP. Se preferir gerar em duas etapas, por exemplo para validar o XML gerado junto aos Correios, é só usar o método gera_xml_plp(). De fato, a chamada acima é exatamente igual a:

    my $xml = $sigep->gera_xml_plp({
        diretoria             => 10,
        codigo_administrativo => 111,
        remetente => {
            nome => 'Minha Empresa LTDA',
            logradouro  => 'Minha Rua',
            numero      => 100,
            complemento => 302,
            bairro      => 'Meu bairro',
            cep         => '111111222',
            cidade      => 'Minha Cidade',
            estado      => 'XX',
        },
        objetos => [
            {
                etiqueta => 'SS123456789BR',
                codigo_postagem => '41068',
                tipo => '001',
                peso => 50, # em gramas
                valor_declarado => '50,00',
                servicos_adicionais => [1,35],
                destinatario => {
                    nome => 'Comprador Feliz da Silva',
                    logradouro => 'Rua da Entrega',
                    numero     => 1,
                    complemento => 'casa',
                    bairro      => 'Bairro Feliz',
                    cidade      => 'Cidade Feliz',
                    uf          => 'ZZ',
                    cep         => '2222233',
                },
            },
        ],
    });

    my $id_plp = $sigep->fecha_plp_varios_servicos({
        id      => 111111,
        xml     => $xml,
        objetos => [{ etiqueta => 'SS123456789BR' }],
    });

status_plp( $id_plp )

Método da API SIGEP: solicitaXmlPlp

    my $res = $sigep->status_plp( '1234' );

    if (exists $res->{SigepClienteException}) {
        print $res->{SigepClienteException}{reason};
    }
    else {
        # olhar status!
    }

Recebe o id da PLP (retornado por fecha_plp_varios_servicos()) e consulta os Correios sobre o status de envio. Naturalmente, só funciona para PLPs criadas pelo próprio usuário. Se a PLP ainda não tiver sido processada pelos Correios, você receberá uma mensagem de erro (veja exemplo acima para tratar).

servico_disponivel( \%opcoes )

Método da API SIGEP: verificaDisponibilidadeServico

Recebe um hashref com o codigo do serviço e os CEPs de origem e destino.

Retorna verdadeiro se o serviço solicitado está disponível para essa origem e destino, ou falso caso contrário.

    my $opcoes = {
        codigo_servico => '40290',    # "SEDEX HOJE"
        cep_origem     => '22241000',
        cep_destino    => '70002900',

        # caso não tenha passado durante a inicializacao do objeto:
        # usuario => ...
        # senha   => ...
        # codigo  => ...
    };

    if ( $sigep->servico_disponivel($opcoes) ) {
        ...
    }

Nota: o código do serviço pode ser um código único ou mais de um, em uma string separada por vírgulas (ex: "40290,41068"). Nesse caso, o valor retornado pelos Correios será verdadeiro se pelo menos um dos serviços estiver disponível, sem dizer qual.

logistica_reversa

logistica_reversa( \%opcoes )

Este método auxiliar retorna o objeto WWW::Correios::SIGEP::LogisticaReversa criado automaticamente a partir das informações de usuario/senha/debug/sandbox do objeto que o invocou. Note que esse objeto só será criado no momento em que o método for invocado pela primeira vez, OU em chamadas futuras que incluam opções de inicialização (que, obviamente, sobrescreverão qualquer opção padrão) do módulo pai.

CONFIGURAÇÃO E VARIÁVEIS DE AMBIENTE

WWW::Correios::SIGEP não precisa de qualquer arquivo de configuraçào ou variável de ambiente.

BUGS E LIMITAÇÕES

Por favor entre em contato sobre qualquer bug ou pedido de feature em: https://github.com/garu/WWW-Correios-SIGEP/issues.

VEJA TAMBÉM

WWW::Correios::SRO Interface para o Serviço de Rastreamento de Objetos (SRO).
WWW::Correios::CEP Interface para consulta de CEP.
WWW::Correios::PrecoPrazo Interface para consulta de preços de prazos (frete).
Business::BR::CEP Interface para validação de números de CEP.
Geo::CEP Interface para geolocalização de números de CEP.

AGRADECIMENTOS

Este módulo não existiria sem a interface SIGEP WEB disponibilizada pelos Correios.

AUTOR

Breno G. de Oliveira <garu@cpan.org>

LICENÇA E COPYRIGHT

Copyright (c) 2016, Breno G. de Oliveira. Todos os direitos reservados.

Este módulo é software livre; você pode redistribuí-lo e/ou modificá-lo sob os mesmos termos que o Perl. Veja perlartistic.

Este módulo não vem com nenhuma garantia. Use sob sua própria conta e risco.

DISCLAIMER OF WARRANTY

BECAUSE THIS SOFTWARE IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE SOFTWARE, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE SOFTWARE "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE SOFTWARE IS WITH YOU. SHOULD THE SOFTWARE PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR, OR CORRECTION.

IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE SOFTWARE AS PERMITTED BY THE ABOVE LICENCE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE SOFTWARE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE SOFTWARE TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.