File Coverage

blib/lib/Net/Moip.pm
Criterion Covered Total %
statement 50 53 94.3
branch 11 16 68.7
condition n/a
subroutine 10 10 100.0
pod 0 1 0.0
total 71 80 88.7


line stmt bran cond sub pod time code
1             package Net::Moip;
2              
3 5     5   373638 use IO::Socket::SSL;
  5         430771  
  5         51  
4 5     5   2642 use MIME::Base64;
  5         3197  
  5         327  
5 5     5   1599 use Furl;
  5         102382  
  5         167  
6              
7 5     5   1430 use String::CamelCase ();
  5         2466  
  5         113  
8 5     5   1758 use XML::SAX::Writer;
  5         183701  
  5         212  
9 5     5   2649 use XML::Generator::PerlData;
  5         24989  
  5         190  
10              
11 5     5   2105 use Moo;
  5         50686  
  5         30  
12              
13             our $VERSION = 0.06;
14              
15             has 'ua', is => 'ro', default => sub {
16             Furl->new(
17             agent => "Net-Moip/$VERSION",
18             timeout => 15,
19             max_redirects => 3,
20             # "SSL Wants a read first" I think is suggesting you
21             # haven't read OpenSSL a bedtime story in too long and perhaps
22             # it's feeling neglected and lonely?
23             # see also: https://metacpan.org/pod/IO::Socket::SSL#SNI-Support
24             # https://metacpan.org/pod/Furl#FAQ
25             # https://rt.cpan.org/Public/Bug/Display.html?id=86684
26             ssl_opts => {
27             SSL_verify_mode => SSL_VERIFY_PEER(),
28             },
29             );
30             };
31              
32             has 'token', is => 'ro', required => 1;
33              
34             has 'key', is => 'ro', required => 1;
35              
36             has 'api_url', (
37             is => 'ro',
38             writer => '_set_api_url',
39             default => 'https://www.moip.com.br/ws/alpha/EnviarInstrucao/Unica'
40             );
41              
42             has 'sandbox', (
43             is => 'rw',
44             default => 0,
45             trigger => sub {
46             my ($self, $sandbox) = @_;
47             $self->_set_api_url( $sandbox
48             ? 'https://desenvolvedor.moip.com.br/sandbox/ws/alpha/EnviarInstrucao/Unica'
49             : 'https://www.moip.com.br/ws/alpha/EnviarInstrucao/Unica'
50             );
51             }
52             );
53              
54             has 'decode_as', is => 'rw', default => undef;
55              
56             sub pagamento_unico {
57 4     4 0 8413 my ($self, $args) = @_;
58              
59 4         18 my $xml = $self->_gen_xml( $args );
60 4         240 my $auth = 'Basic ' . MIME::Base64::encode( $self->token . ':' . $self->key, '');
61              
62 4         46 my $res = $self->ua->post(
63             $self->api_url,
64             [ 'Authorization' => $auth ],
65             $xml
66             );
67              
68 4         2075 my %data = ( response => $res );
69 4 100       19 if ($res->is_success) {
70 3         25 my $c = $res->content;
71 3 50       46 $data{id} = $1 if $c =~ m{(.+?)};
72 3 50       32 $data{status} = $1 if $c =~ m{(.+?)};
73 3 100       21 $data{token} = $1 if $c =~ m{(.+?)};
74              
75 3         27 while ($c =~ m{(.+?)}gs) {
76 3         9 push @{$data{erros}}, { codigo => $1, mensagem => $2 };
  3         33  
77             }
78             }
79              
80 4         22 return \%data;
81             }
82              
83             sub _gen_xml {
84 4     4   14 my ($self, $args) = @_;
85 4         10 my $xml;
86              
87 4         62 my $generator = XML::Generator::PerlData->new(
88             Handler => XML::SAX::Writer->new(
89             Output => \$xml,
90             EncodeFrom => $self->decode_as,
91             EncodeTo => 'iso-8859-1'
92             ),
93             rootname => 'EnviarInstrucao',
94             keymap => {
95             '*' => \&String::CamelCase::camelize,
96             'url_notificacao' => 'URLNotificacao',
97             'url_logo' => 'URLLogo',
98             'url_retorno' => 'URLRetorno',
99             },
100             attrmap => { InstrucaoUnica => ['TipoValidacao'] },
101             );
102              
103 5     5   9917 no autovivification;
  5         4145  
  5         26  
104              
105 4         1679 $args->{valores}{valor} = delete $args->{valor};
106              
107 4 50       35 if (my $acrescimo = delete $args->{acrescimo}) {
108 0         0 $args->{valores}{acrescimo} = $acrescimo;
109             }
110              
111 4 50       21 if (my $deducao = delete $args->{deducao}) {
112 0         0 $args->{valores}{deducao} = $deducao;
113             }
114              
115 4 100       33 if (my $cep = delete $args->{pagador}{endereco_cobranca}{cep}) {
116 1         8 $args->{pagador}{endereco_cobranca}{CEP} = $cep;
117             }
118              
119 4         18 my $xml_args = { instrucao_unica => $args };
120              
121 4         36 $generator->parse( $xml_args );
122              
123             # FIXME: XML::Generator::PerlData does not know how to handle
124             # elements with attributes *and* (leaf) data inside. And of course
125             # Moip requires just that.
126 4 50       15725 if (exists $xml_args->{instrucao_unica}{pagador}{identidade}) {
127 0         0 $xml =~ s{(\d+)}
128             {$1};
129             }
130 4         114  
131             return $xml;
132             }
133              
134             1;
135             __END__