File Coverage

blib/lib/Business/PxPay.pm
Criterion Covered Total %
statement 17 19 89.4
branch n/a
condition n/a
subroutine 7 7 100.0
pod n/a
total 24 26 92.3


line stmt bran cond sub pod time code
1             package Business::PxPay;
2              
3             BEGIN {
4 1     1   39484 $Business::PxPay::VERSION = '0.04';
5             }
6              
7             # ABSTRACT: PX Pay Interface for www.paymentexpress.com
8              
9 1     1   12 use warnings;
  1         2  
  1         37  
10 1     1   7 use strict;
  1         2  
  1         56  
11 1     1   7 use Carp qw/croak/;
  1         1  
  1         126  
12 1     1   1228 use URI::Escape qw/uri_escape/;
  1         2074  
  1         74  
13 1     1   1642 use LWP::UserAgent;
  1         92185  
  1         42  
14 1     1   524 use XML::Simple qw/XMLin XMLout/;
  0            
  0            
15             use vars qw/%TRANSACTIONS/;
16              
17             %TRANSACTIONS = (
18             purchase => 'Purchase',
19             credit => 'Refund',
20             authorization => 'Auth',
21             capture => 'Complete',
22             validate => 'Validate'
23             );
24              
25             sub new {
26             my $class = shift;
27             my $args = scalar @_ % 2 ? shift : {@_};
28              
29             # validate
30             $args->{userid} or croak 'userid is required';
31             $args->{key} or croak 'key is required';
32              
33             $args->{url} ||= 'https://sec.paymentexpress.com/pxpay/pxaccess.aspx';
34              
35             unless ( $args->{ua} ) {
36             my $ua_args = delete $args->{ua_args} || {};
37             $args->{ua} = LWP::UserAgent->new(%$ua_args);
38             }
39              
40             bless $args, $class;
41             }
42              
43             sub request {
44             my $self = shift;
45             my $args = scalar @_ % 2 ? shift : {@_};
46              
47             my $xml = $self->request_xml($args);
48             my $resp = $self->{ua}->post( $self->{url}, Content => $xml );
49             unless ( $resp->is_success ) {
50             croak $resp->status_line;
51             }
52             my $rtn = XMLin( $resp->content, SuppressEmpty => undef );
53             return $rtn;
54             }
55              
56             sub request_xml {
57             my $self = shift;
58             my $args = scalar @_ % 2 ? shift : {@_};
59              
60             # validate
61             my $TxnType = $args->{TxnType} || croak 'TxnType is required';
62             my $Amount =
63             $args->{Amount}
64             || $self->{Amount}
65             || croak 'Amount is required';
66             $Amount = sprintf( "%.2f", $Amount ); # .XX format
67             my $Currency =
68             $args->{Currency}
69             || $self->{Currency}
70             || croak 'Currency is required';
71             my $UrlFail =
72             $args->{UrlFail}
73             || $self->{UrlFail}
74             || croak 'UrlFail is required';
75             my $UrlSuccess =
76             $args->{UrlSuccess}
77             || $self->{UrlSuccess}
78             || croak 'UrlSuccess is required';
79             my $MerchantReference = $args->{MerchantReference}
80             || croak 'MerchantReference is required';
81              
82             # UrlFail can't contain '?' or '&'
83             if ( $UrlFail =~ /\?/ or $UrlFail =~ /\&/ ) {
84             croak
85             "UrlFail can't contain '?' or '&', please use TxnData1, TxnData2, TxnData3 or Opt\n";
86             }
87             if ( $UrlSuccess =~ /\?/ or $UrlSuccess =~ /\&/ ) {
88             croak
89             "UrlSuccess can't contain '?' or '&', please use TxnData1, TxnData2, TxnData3 or Opt\n";
90             }
91              
92             my $request = {
93             GenerateRequest => {
94             PxPayUserId => [ $self->{userid} ],
95             PxPayKey => [ $self->{key} ],
96             AmountInput => [$Amount],
97             CurrencyInput => [$Currency],
98             MerchantReference => [$MerchantReference],
99             EmailAddress => [ $args->{EmailAddress} ],
100             TxnData1 => [ $args->{TxnData1} ],
101             TxnData2 => [ $args->{TxnData2} ],
102             TxnData3 => [ $args->{TxnData3} ],
103             TxnType => [$TxnType],
104             TxnId => [ $args->{TxnId} ],
105             BillingId => [ $args->{BillingId} ],
106             EnableAddBillCard => [ $args->{EnableAddBillCard} ],
107             UrlSuccess => [$UrlSuccess],
108             UrlFail => [$UrlFail],
109             Opt => [ $args->{Opt} ],
110             },
111             };
112             return XMLout( $request, KeepRoot => 1 );
113             }
114              
115             sub result {
116             my ( $self, $ResponseCode ) = @_;
117              
118             my $xml = $self->result_xml($ResponseCode);
119             my $resp = $self->{ua}->post( $self->{url}, Content => $xml );
120             unless ( $resp->is_success ) {
121             croak $resp->status_line;
122             }
123             my $rtn = XMLin( $resp->content, SuppressEmpty => undef );
124             return $rtn;
125             }
126              
127             sub result_xml {
128             my ( $self, $ResponseCode ) = @_;
129              
130             my $request = {
131             ProcessResponse => {
132             PxPayUserId => [ $self->{userid} ],
133             PxPayKey => [ $self->{key} ],
134             Response => [$ResponseCode],
135             },
136             };
137             return XMLout( $request, KeepRoot => 1 );
138             }
139              
140             1;
141              
142             =pod
143              
144             =head1 NAME
145              
146             Business::PxPay - PX Pay Interface for www.paymentexpress.com
147              
148             =head1 VERSION
149              
150             version 0.04
151              
152             =head1 SYNOPSIS
153              
154             use Business::PxPay;
155              
156             my $pxpay = Business::PxPay->new(
157             userid => 'TestAccount',
158             key => 'c9fff215b9e2add78d252b78e214880b46a906e73190a380483c1c29acab4157'
159             );
160            
161             # when submit the cart order
162             if ( $submit_order ) {
163             my $rtn = $pxpay->request($args); # $args from CGI params
164             if ( exists $rtn->{valid} and $rtn->{valid} == 1 ) {
165             print $q->redirect( $rtn->{URI} );
166             } else {
167             die Dumper(\$rtn);
168             }
169             }
170             # when user returns back from pxpal
171             elsif ( $in_return_or_cancel_page or $params->{result} ) {
172             my $rtn = $pxpay->result($params->{result});
173             if ( exists $rtn->{valid} and $rtn->{valid} == 1 ) {
174             print "Transaction Success!\n";
175             } else {
176             print "Transaction Failed!\n";
177             }
178             }
179              
180             =head1 DESCRIPTION
181              
182             PX Pay - Payment Express L
183              
184             =head2 new
185              
186             my $pxpay = Business::PxPay->new(
187             userid => $user,
188             key => $key
189             );
190              
191             =over 4
192              
193             =item * C (required)
194              
195             =item * C (required)
196              
197             PxPayUserId & PxPayKey
198              
199             =item * C
200              
201             =item * C
202              
203             By default, we use LWP::UserAgent->new as the UserAgent. you can pass C or C to use a different one.
204              
205             =item * C
206              
207             my $pxpay = Business::PxPay->new(
208             userid => $user,
209             key => $key,
210             url => 'https://sec2.paymentexpress.com/pxpay/pxaccess.aspx', # to test?
211             );
212              
213             The URL is 'https://www.paymentexpress.com/pxpay/pxaccess.aspx' by default.
214              
215             =back
216              
217             =head2 Arguments
218              
219             All those arguments can be passed into Business::PxPay->new() or pass into $pxpay->request later
220              
221             {
222             TxnType => 'Purchase',
223             Amount => 10.9,
224             UrlFail => 'http://test.com',
225             UrlSuccess => 'http://example.com',
226             MerchantReference => 'Test Transaction',
227             EmailAddress => 'test@example.com',
228             TxnData1 => 'test=A',
229             TxnData2 => 'data2=B',
230             TxnData3 => 'data3=C',
231             };
232              
233             =over 4
234              
235             =item * C (required)
236              
237             Amount value in d.cc format
238              
239             =item * C (required)
240              
241             L
242              
243             =item * C (required)
244              
245             URL of the merchant transaction failure page. No parameters ("&" or "?") are permitted.
246              
247             =item * C (required)
248              
249             URL of the merchant transaction success page. No parameters ("&" or "?") are permitted.
250              
251             =item * C (required)
252              
253             "Auth" or "Purchase"
254              
255             =item * C (required)
256              
257             Reference field to appear on transaction reports
258              
259             =item * C
260              
261             Optional identifier when adding a card for recurring billing
262              
263             =item * C
264              
265             Optional email address
266              
267             =item * C
268              
269             Required when adding a card to the DPS system for recurring billing. Set element to "1" for true
270              
271             =item * C
272              
273             A value that uniquely identifies the transaction
274              
275             =item * C
276              
277             =item * C
278              
279             =item * C
280              
281             Optional free text
282              
283             =item * C
284              
285             Optional additional parameter
286              
287             =back
288              
289             =head2 request
290              
291             my $xml = $pxpay->request_xml($args);
292             my $rtn = $pxpay->request($args);
293              
294             request and parse the response XML into HASHREF. sample:
295              
296             $VAR1 = \{
297             'URI' => 'https://sec2.paymentexpress.com/pxpay/pxpay.aspx?userid=
298             TestAccount&request=v51flwn7rvSNcbY86uRMdJ74XB2gHd8ZY-WHqyEYoPm9xd1ROXX00pXYkkuk
299             dleLlS402E65EjOSCkrqvmAsZUWRCck8RkmIJcRLvG0KZLi7PQRBfpIQ0wzKwdHGKvBCpqhRH6Tx-w93
300             MRYsP0ThOK4btgTneR_hGEk0supyLeE1taNWCkyFj8KX7rzZ9ncdWRlmciNBsiV4zX4DQ_7Poi9qiblI
301             5o0Gm49yb90kUlUtH1hrV3ulzidQbn0CcQKhHFKGX8IVMXiAtVN29r_Cgdzc7dOrwOxY-LBY2h4Or5GQ
302             hJHB96kjBziu3GyGBvaGfsosNodT3-wyM29A5M-Z62ITkno6JUA6H4',
303             'valid' => '1'
304             };
305              
306             Usually you need redirect to the $rtn->{URI} when valid is 1
307              
308             =head2 result
309              
310             my $xml = $pxpay->result_xml($ResponseCode);
311             my $rtn = $pxpay->result($ResponseCode);
312             if ( exists $rtn->{valid} and $rtn->{valid} == 1 ) {
313             print "Transaction Success!\n";
314             } else {
315             print "Transaction Failed!\n";
316             }
317              
318             PxPay will POST to your C (or C) when you finish the transaction (or click Cancel button). the POST would contain a param B which you can request to get the transaction status.
319              
320             =head2 TIPS
321              
322             =head3 I need params in C
323              
324             For example, you want your UrlSuccess to be 'http://mysite.com/cgi-bin/cart.cgi?cart_id=ABC'.
325              
326             you need write the request like:
327              
328             my $rtn = $pxpay->request(
329             # others
330             UrlSuccess => 'http://mysite.com/cgi-bin/cart.cgi',
331             TxnData1 => 'ABC',
332             );
333              
334             and you can get the C in
335              
336             my $rtn = $pxpay->result($ResponseCode);
337             my $cart_id = $rtn->{TxnData1}
338              
339             =head1 AUTHOR
340              
341             Fayland Lam
342              
343             =head1 COPYRIGHT AND LICENSE
344              
345             This software is copyright (c) 2011 by Fayland Lam.
346              
347             This is free software; you can redistribute it and/or modify it under
348             the same terms as the Perl 5 programming language system itself.
349              
350             =cut
351              
352             __END__