File Coverage

blib/lib/Net/Correios.pm
Criterion Covered Total %
statement 53 69 76.8
branch 10 28 35.7
condition 6 20 30.0
subroutine 14 16 87.5
pod 4 6 66.6
total 87 139 62.5


line stmt bran cond sub pod time code
1 8     8   1220418 use strict;
  8         12  
  8         230  
2 8     8   57 use warnings;
  8         12  
  8         290  
3              
4 8     8   5165 use HTTP::Tiny;
  8         363498  
  8         320  
5 8     8   3253 use MIME::Base64 ();
  8         4937  
  8         193  
6 8     8   42 use Carp ();
  8         13  
  8         85  
7 8     8   25 use Scalar::Util ();
  8         8  
  8         63  
8 8     8   3051 use JSON ();
  8         44567  
  8         1282  
9              
10             $Carp::Internal{ 'Net::Correios' }++;
11              
12             package Net::Correios;
13              
14             our $VERSION = '0.004';
15              
16             my %libs = (
17             token => 'Token',
18             cep => 'CEP',
19             sro => 'SRO',
20             preco => 'Preco',
21             prazo => 'Prazo',
22             empresas => 'Empresas',
23             prepostagens => 'Prepostagens',
24             faturas => 'Faturas',
25             agencias => 'Agencias',
26             manifestacao => 'Manifestacao',
27             );
28              
29             # create lazy accessors.
30             foreach my $method (keys %libs) {
31             $Carp::Internal{ 'Net::Correios::' . $libs{$method} }++;
32             my $sub = sub {
33 6     6   3113 my ($self, %args) = @_;
34 6         17 my $internal_key = 'endpoint_' . $method;
35 6 50       49 if (!$self->{$internal_key}) {
36 6         17 my $module = 'Net/Correios/' . $libs{$method} . '.pm';
37 6         5038 require $module;
38 6         24 my $class = 'Net::Correios::' . $libs{$method};
39 6         27 $self->{$internal_key} = $class->new( $self );
40             }
41 6         41 return $self->{$internal_key};
42             };
43 8     8   72 { no strict 'refs';
  8         16  
  8         5059  
44             *{"Net\::Correios\::$method"} = $sub;
45             }
46             }
47              
48             sub new {
49 11     11 1 1147716 my ($class, %args) = @_;
50             Carp::croak 'Net::Correios::new - "username" and "password" are required'
51 11 100 100     416 unless $args{username} && $args{password};
52 8         52 my $auth_basic = MIME::Base64::encode_base64($args{username} . ':' . $args{password}, '');
53             return bless {
54             debug => $args{debug},
55             contrato => $args{contrato},
56             cartao => $args{cartao},
57             sandbox => !!$args{sandbox},
58             base_url => 'https://api' . (('hom')x!!$args{sandbox}) . '.correios.com.br/',
59             auth_basic => $auth_basic,
60             agent => HTTP::Tiny->new(
61             default_headers => {
62             'Accept' => 'application/json',
63             'Content-Type' => 'application/json',
64             },
65             verify_SSL => 1,
66 8   50     127 timeout => $args{timeout} || 5,
67             ),
68             }, $class;
69             }
70              
71 2     2 1 191 sub is_sandbox { $_[0]->{sandbox} }
72              
73             sub access_token {
74 10     10 1 19 my ($self, $token_type) = @_;
75 10 50 33     80 die 'token deve ser "cartao", "contrato" ou undef'
      33        
76             if defined $token_type && $token_type ne 'cartao' && $token_type ne 'contrato';
77              
78 10 50       47 my $storage_key = 'token' . (defined $token_type ? '_' . $token_type : '');
79 10 50       71 return $self->{$storage_key} if defined $self->{$storage_key};
80              
81             my $token_res = $self->token->autentica(
82 0 0       0 (defined $token_type ? ($token_type => $self->{$token_type}) : ())
83             );
84              
85 0         0 $self->{$storage_key} = $token_res->{token};
86 0 0 0     0 if ($token_res->{cartaoPostagem} && (!$self->{cartao} || $self->{cartao} eq $token_res->{cartaoPostagem}{numero})) {
      0        
87 0         0 $self->{dr} = $token_res->{cartaoPostagem}{dr};
88 0 0       0 $self->{contrato} = $token_res->{cartaoPostagem}{contrato} if !$self->{contrato};
89             }
90 0         0 return $self->{$storage_key};
91             }
92              
93             sub make_request {
94 8     8 0 26 my ($self, $token_type, $method, $url, $args) = @_;
95 8 100       42 $args = {} if !defined $args;
96 8         20 $url = $self->{base_url} . $url;
97 8         24 my $token = $self->access_token($token_type);
98 8         40 $args->{headers}{Authorization} = 'Bearer ' . $token;
99 8         26 my $res = $self->{agent}->request($method, $url, $args);
100              
101 8 50       21186 if ($self->{debug}) {
102             $self->_debug(
103             "curl -X $method '$url' -H 'accept: application/json' -H 'Content-Type: application/json' -H 'Authorization: Bearer $token' " . (exists $args->{content} && defined $args->{content} && length($args->{content}) ? ("-d '" . $args->{content} . "'") : ''),
104             "Response: " . $res->{status} . "\n" . $res->{content}
105 0 0 0     0 );
106             }
107              
108 8         25 return $res;
109             }
110              
111             sub parse_response {
112 9     9 0 26 my ($self, $res) = @_;
113 9 50       24 if ($res->{success}) {
114 9         182 my $data = JSON::decode_json($res->{content});
115 9         68 return $data;
116             }
117             else {
118 0           my $error = $res->{status} . ' ' . $res->{reason};
119 0 0         $error .= ":\n" . $res->{content} if length $res->{content};
120 0           $error .= "\n " . $res->{url};
121 0           Carp::croak($error);
122             }
123             }
124              
125             sub debug {
126 0     0 1   my ($self, $debug) = @_;
127 0 0         $self->{debug} = $debug if @_ > 1;
128 0           return $self->{debug};
129             }
130              
131             sub _debug {
132 0     0     my ($self, @msg) = @_;
133 0           print STDERR '[' . __PACKAGE__ . ']' . join("\n", @msg);
134             }
135              
136             1;
137             __END__