File Coverage

blib/lib/Business/RealEx.pm
Criterion Covered Total %
statement 16 18 88.8
branch n/a
condition n/a
subroutine 6 6 100.0
pod n/a
total 22 24 91.6


line stmt bran cond sub pod time code
1             package Business::RealEx;
2              
3 1     1   81691 use strict;
  1         5  
  1         62  
4 1     1   35 use 5.008_005;
  1         4  
  1         62  
5             our $VERSION = '0.02';
6              
7 1     1   1013 use Digest::SHA1 'sha1_hex';
  1         8149  
  1         141  
8 1     1   2688 use LWP::UserAgent;
  1         162569  
  1         79  
9 1     1   13 use Carp 'croak';
  1         2  
  1         93  
10 1     1   2184 use XML::Simple;
  0            
  0            
11              
12             sub new {
13             my $class = shift;
14              
15             my %args = @_ % 2 ? %{$_[0]} : (@_);
16              
17             $args{merchantid} or croak 'merchantid is required.';
18             $args{secret} or croak 'secret is required.';
19             $args{ua} ||= LWP::UserAgent->new;
20              
21             bless \%args, $class;
22             }
23              
24             sub edit_payer {
25             my $self = shift;
26             my %args = @_ % 2 ? %{$_[0]} : (@_);
27              
28             $args{edit_payer} = 1;
29             $self->new_payer(%args);
30             }
31              
32             sub new_payer {
33             my $self = shift;
34             my %args = @_ % 2 ? %{$_[0]} : (@_);
35              
36             foreach my $r ('payerref', 'firstname', 'surname') {
37             $args{$r} or croak "$r is required.";
38             }
39              
40             $args{payertype} ||= 'Business';
41             $args{title} ||= 'Mr';
42             $self->{__timestamp} = __timestamp();
43             my $sha1hash = $self->__sha1hash($args{orderid} || '', $args{amount} || '', $args{currency} || '', $args{payerref});
44              
45             # we omit other fields for now
46             my $action = $args{edit_payer} ? 'payer-edit' : 'payer-new';
47             my $xml = <
48            
49             $self->{merchantid}
50             $args{orderid}
51            
52             $args{title}
53             $args{firstname}
54             $args{surname}
55             XML
56              
57             $xml .= "$args{company}" if $args{company};
58              
59             $xml .= <
60            
61             $sha1hash
62            
63             XML
64              
65             return $self->__request($xml);
66             }
67              
68             sub new_card {
69             my $self = shift;
70             my %args = @_ % 2 ? %{$_[0]} : (@_);
71              
72             my @r = ('ref', 'payerref', 'expdate', 'chname', 'type');
73             push @r, 'number' unless $args{update_card}; # update card may not need number
74             foreach my $r (@r) {
75             $args{$r} or croak "$r is required.";
76             }
77              
78             $self->{__timestamp} = __timestamp();
79             my $sha1hash;
80             if ($args{update_card}) {
81             # Timestamp.merchantID.payerref.ref.expirydate.cardnumber
82             $sha1hash = $self->__sha1hash($args{payerref}, $args{ref}, $args{expdate}, $args{number} || '');
83             } else {
84             # timestamp.merchantid.orderid.amount.currency.payerref.chname.(card)number
85             $sha1hash = $self->__sha1hash($args{orderid} || '', $args{amount} || '', $args{currency} || '', $args{payerref}, $args{chname}, $args{number});
86             }
87              
88             # we omit other fields for now
89             my $action = $args{update_card} ? 'card-update-card' : 'card-new';
90             my $xml = <
91            
92             $self->{merchantid}
93             XML
94              
95             $xml .= "$args{orderid}" if $args{orderid};
96              
97             $xml .= <
98            
99             $args{ref}
100             $args{payerref}
101             $args{number}
102             $args{expdate}
103             $args{chname}
104             $args{type}
105             XML
106              
107             $xml .= "$args{issueno}" if $args{issueno};
108              
109             $xml .= <
110            
111             $sha1hash
112            
113             XML
114              
115             return $self->__request($xml);
116             }
117              
118             sub update_card {
119             my $self = shift;
120             my %args = @_ % 2 ? %{$_[0]} : (@_);
121              
122             $args{update_card} = 1;
123             $self->new_card(%args);
124             }
125              
126             sub delete_card {
127             my $self = shift;
128             my %args = @_ % 2 ? %{$_[0]} : (@_);
129              
130             my @r = ('ref', 'payerref');
131              
132             $self->{__timestamp} = __timestamp();
133             # Timestamp.merchantID.payerref.pmtref
134             my $sha1hash = $self->__sha1hash($args{payerref}, $args{ref});
135              
136             # we omit other fields for now
137             my $xml = <
138            
139             $self->{merchantid}
140            
141             $args{ref}
142             $args{payerref}
143            
144             $sha1hash
145            
146             XML
147              
148             return $self->__request($xml);
149             }
150              
151             sub receipt_in {
152             my $self = shift;
153             my %args = @_ % 2 ? %{$_[0]} : (@_);
154              
155             my @r = ('account', 'amount', 'currency', 'payerref', 'paymentmethod');
156             foreach my $r (@r) {
157             $args{$r} or croak "$r is required.";
158             }
159              
160             $self->{__timestamp} = __timestamp();
161             # timestamp.merchantid.orderid.amount.currency.payerref
162             my $sha1hash = $self->__sha1hash($args{orderid} || '', $args{amount} || '', $args{currency} || '', $args{payerref});
163              
164             $args{autosettle} = 1 unless exists $args{autosettle};
165              
166             # we omit other fields for now
167             my $action = 'receipt-in';
168             my $xml = <
169            
170             $self->{merchantid}
171             $self->{account}
172             XML
173              
174             $xml .= "$args{orderid}" if $args{orderid};
175             if ($args{cvn}) {
176             $xml .= <
177            
178            
179             $args{cvn}
180            
181            
182             XML
183             }
184              
185             $xml .= <
186             $args{amount}
187             $args{payerref}
188             $args{paymentmethod}
189            
190             XML
191              
192             $xml .= "$args{authcode}" if $args{authcode};
193              
194             $xml .= <
195             $sha1hash
196            
197             XML
198              
199             return $self->__request($xml);
200             }
201              
202             sub refund {
203             my $self = shift;
204             my %args = @_ % 2 ? %{$_[0]} : (@_);
205              
206             my @r = ('account', 'amount', 'currency', 'payerref', 'paymentmethod');
207             foreach my $r (@r) {
208             $args{$r} or croak "$r is required.";
209             }
210              
211             $args{refund_password} or $self->{refund_password} or die 'refund_password is required.';
212              
213             $self->{__timestamp} = __timestamp();
214             # timestamp.merchantid.orderid.amount.currency.payerref
215             my $sha1hash = $self->__sha1hash($args{orderid} || '', $args{amount} || '', $args{currency} || '', $args{payerref});
216             my $refundhash = sha1_hex($args{refund_password} || $self->{refund_password});
217              
218             $args{autosettle} = 1 unless exists $args{autosettle};
219              
220             # we omit other fields for now
221             my $action = 'payment-out';
222             my $xml = <
223            
224             $self->{merchantid}
225             $self->{account}
226             XML
227              
228             $xml .= "$args{orderid}" if $args{orderid};
229              
230             $xml .= <
231             $args{amount}
232             $args{payerref}
233             $args{paymentmethod}
234             XML
235              
236             $xml .= <
237             $sha1hash
238             $refundhash
239            
240             XML
241              
242             return $self->__request($xml);
243             }
244              
245             sub __request {
246             my ($self, $xml) = @_;
247              
248             my $resp = $self->{ua}->post('https://epage.payandshop.com/epage-remote-plugins.cgi', Content => $xml);
249             # use Data::Dumper; print Dumper(\$resp);
250             return { error => 'Failed to talk with remote server: ' . $resp->status_line } unless $resp->is_success;
251             return XMLin($resp->content, ForceArray => 0, SuppressEmpty => '');
252             }
253              
254             sub __sha1hash {
255             my $self = shift;
256             return sha1_hex(join('.', sha1_hex($self->__sha_string(@_)), $self->{secret}));
257             }
258              
259             sub __sha_string {
260             my $self = shift;
261             return join('.', $self->{__timestamp}, $self->{merchantid}, @_);
262             }
263              
264             sub __timestamp {
265             my @d = localtime();
266             return sprintf('%04d%02d%02d%02d%02d%02d', $d[5] + 1900, $d[4] + 1, $d[3], @d[qw/2 1 0/]);
267             }
268              
269             1;
270             __END__