File Coverage

blib/lib/WWW/ModulrFinance.pm
Criterion Covered Total %
statement 26 73 35.6
branch 0 14 0.0
condition 0 8 0.0
subroutine 9 22 40.9
pod 10 12 83.3
total 45 129 34.8


line stmt bran cond sub pod time code
1             package WWW::ModulrFinance;
2              
3 1     1   23044 use strict;
  1         2  
  1         27  
4 1     1   22 use 5.008_005;
  1         3  
5             our $VERSION = '0.02';
6              
7 1     1   659 use LWP::UserAgent;
  1         54041  
  1         62  
8 1     1   13 use HTTP::Date qw/time2str/;
  1         3  
  1         141  
9 1     1   1038 use Digest::HMAC_SHA1 qw(hmac_sha1);
  1         8371  
  1         94  
10 1     1   709 use MIME::Base64;
  1         735  
  1         91  
11 1     1   10 use URI::Escape qw/uri_escape/;
  1         3  
  1         88  
12 1     1   4 use Carp qw/croak/;
  1         2  
  1         71  
13 1     1   1194 use JSON;
  1         13924  
  1         5  
14              
15             sub new {
16 0     0 0   my $class = shift;
17 0 0         my %params = @_ % 2 ? %{$_[0]} : @_;
  0            
18              
19 0 0         $params{api_key} or croak "api_key is required";
20 0 0         $params{hmac_secret} or croak "hmac_secret is required";
21              
22 0   0       $params{base_url} ||= 'https://api-sandbox.modulrfinance.com/api-sandbox/';
23 0   0       $params{ua} ||= LWP::UserAgent->new(agent => "WWW-ModulrFinance-$VERSION");
24              
25 0           return bless \%params, $class;
26             }
27              
28             sub get_accounts {
29 0     0 1   (shift)->request('GET', 'accounts', @_);
30             }
31              
32             sub get_account {
33 0     0 1   my ($self, $id) = @_;
34 0           return $self->request('GET', 'accounts/' . $id);
35             }
36              
37             sub update_account {
38 0     0 1   my ($self, $id, $data) = @_;
39 0           return $self->request('PUT', 'accounts/' . $id, $data);
40             }
41              
42             sub get_customer_accounts {
43 0     0 1   my ($self, $cid, $params) = @_;
44 0           return $self->request('GET', 'customers/' . $cid . '/accounts', $params);
45             }
46              
47             sub create_customer_account {
48 0     0 1   my ($self, $cid, $data) = @_;
49 0           return $self->request('POST', 'customers/' . $cid . '/accounts', $data);
50             }
51              
52             sub get_transactions {
53 0     0 1   my ($self, $id, $params) = @_;
54 0           return $self->request('GET', 'accounts/' . $id . '/transactions', $params);
55             }
56              
57             sub get_payments {
58 0     0 1   my ($self, $params) = @_;
59 0           $self->request('GET', 'payments', $params);
60             }
61              
62             sub post_payments {
63 0     0 1   my ($self, $data) = @_;
64 0           return $self->request('POST', 'payments', $data);
65             }
66              
67             sub post_batchpayments {
68 0     0 1   my ($self, $data) = @_;
69 0           return $self->request('POST', 'batchpayments', $data);
70             }
71              
72             sub get_batchpayment {
73 0     0 1   my ($self, $id) = @_;
74 0           return $self->request('GET', 'batchpayments/' . $id);
75             }
76              
77             sub request {
78 0     0 0   my ($self, $method, $uri, $data) = @_;
79              
80 0           my $url = $self->{base_url} . $uri;
81 0 0 0       if ($method eq 'GET' and $data) {
82 0           my $uri = URI->new($url);
83 0           $uri->query_form($data);
84 0           $url = $uri->as_string;
85 0           $data = undef; # don't be in POST content
86             }
87              
88 0           my $req = HTTP::Request->new($method => $url => $self->__signature());
89 0 0         $req->content(encode_json($data)) if $data;
90              
91             # print Dumper(\$req); use Data::Dumper;
92              
93 0           my $res = $self->{ua}->request($req);
94 0 0         if ($res->header('Content-Type') =~ 'json') {
95 0           return decode_json($res->content);
96             }
97              
98 0 0         croak $res->status_line unless $res->is_success;
99 0           return $res->content;
100             }
101              
102             sub __signature {
103 0     0     my ($self) = @_;
104              
105 0           my $date = time2str(time());
106 0           my $nonce = time() . '-' . $$ . '-' . rand(100000);
107 0           my $str = "date: $date\nx-mod-nonce: $nonce";
108 0           my $sig = uri_escape(encode_base64(hmac_sha1($str, $self->{hmac_secret}), ''));
109              
110             # Authorization: Signature keyId="57502612d1bb2c0001000025fd53850cd9a94861507a5f7cca236882",algorithm="hmac-sha1",headers="date x-mod-nonce",signature="WBMr%2FYdhysbmiIEkdTrf2hP7SfA%3D"
111             return [
112             'Date' => $date,
113             'x-mod-nonce' => $nonce,
114 0           'Authorization' => qq~Signature keyId="~ . $self->{api_key} . qq~",algorithm="hmac-sha1",headers="date x-mod-nonce",signature="$sig"~,
115             "Content-Type" => "application/json;charset=UTF-8",
116             ];
117             }
118              
119             1;
120             __END__