1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
|
package Business::OnlineThirdPartyPayment;
use strict;
use vars qw($VERSION);
use Carp;
use base qw(Business::OnlinePayment);
require 5.005;
$VERSION = '0.10';
$VERSION = eval $VERSION; # modperlstyle: convert the string into a number
my %fields = (
is_success => undef,
token => undef,
redirect => undef,
post_params => undef,
statustext => undef,
order_number => undef,
authorization => undef,
error_message => undef,
test_transaction => undef,
return_url => undef,
cancel_url => undef,
);
sub new {
my($class,$processor,%data) = @_;
croak("unspecified processor") unless $processor;
my $subclass = "${class}::$processor";
eval "use $subclass";
croak("unknown processor $processor ($@)") if $@;
my $self = bless {processor => $processor}, $subclass;
$self->build_subs(keys %fields);
if($self->can("set_defaults")) {
$self->set_defaults(%data);
}
foreach(keys %data) {
my $key = lc($_);
my $value = $data{$_};
$key =~ s/^\-+//;
$self->build_subs($key);
$self->$key($value);
}
return $self;
}
1;
__END__
=head1 NAME
Business::OnlineThirdPartyPayment - Common interface to browser-based
online payment processors
=head1 SYNOPSIS
use Business::OnlineThirdPartyPayment;
use CGI;
my %processor_info = (
'return_url' => 'https://www.example.com/payment/return',
'cancel_url' => 'https://www.example.com/payment/cancel',
# ... other processor-specific values
);
my $txn = Business::OnlineThirdPartyPayment->new('MyBank', %processor_info);
# start a payment
$txn->create( customer_id => 4030,
invoice_number => 10318,
amount => 49.95,
currency => 'CAD',
description => 'Internet Services',
);
if ( $txn->is_success} ) {
store_payment_id($txn->token); # keep it somewhere
print CGI->redirect( $txn->redirect );
} else {
die $txn->error_message;
}
...
# then, at /payment/return...
my $txn = Business::OnlineThirdPartyPayment->new('MyBank', %processor_info);
$txn->token( get_payment_id($cgi) ); # probably from a session cookie
my %params = $cgi->Vars;
$txn->execute(%params);
if ( $txn->is_success ) {
store_payment_success($txn->order_number, $txn->authorization);
print "Your payment was successful!\n";
} else {
store_payment_failure($txn->order_number, $txn->error_message);
print "Your payment failed.\n";
}
=head1 DESCRIPTION
Business::OnlineThirdPartyPayment is a generic module for processing payments
through online credit card processors, electronic cash systems, etc. through
which the payer's web browser is redirected.
=head1 METHODS
=head2 new($module, %processor_options)
Class method. Create a Business::OnlineThirdPartyPayment object.
$module is required, and defines the gateway module to use. The
other options are processor-specific, but should always include:
=over 4
=item return_url - The callback URL to redirect the user to after completing
a payment.
=item cancel_url - The URL to redirect the user to if they choose not to
complete the payment.
=back
=head2 create(%content)
Tell the gateway module to start a transaction. This may involve
communicating with the gateway, or it may happen entirely locally.
%content is a hash containing some of the following:
=head3 TRANSACTION FIELDS
=over 4
=item amount - The amount of the transaction, as a decimal number. Required.
=item description - A description of the purchase. Required.
=item invoice_number - Your invoice number, if this payment is associated
with a specific invoice.
=item currency - Currency, specified as an ISO 4217 three-letter code, such
as USD, CAD, EUR, AUD, DKK, GBP, JPY, NZD, etc.
=item customer_id - The customer number, if any.
=item email - Customer's email address.
=item customer_ip - IP address from which the transaction originated.
=back
For additional fields, see L<Business::OnlinePayment> and the specific
processor module used.
C<create()> sets properties of the transaction object to indicate the
result. These will always include:
=over 4
=item is_success - 1 if the transaction was created successfully, 0
otherwise.
=item error_message - a text description of any error that occurred.
Since the payer hasn't provided a payment account or any other
information at this stage, this is probably not meaningful to them.
=item token - a reference string that will be used to identify
this transaction later. If is_success is true, you I<must> store this
value in your merchant system and pass it to execute() later. Merchant
systems should allow at least 256 characters for this string.
=item statustext - a freeform text field for any state information
that the gateway needs to receive to complete the transaction.
=item redirect - a URL to redirect the payer to.
=item post_params - the content of an HTTP POST request to send to the
URL. Since HTTP redirects can't include POST content, in this case the
front-end system must provide another way (a self-submitting form) to
induce the purchaser's browser to make the request.
=back
=head2 execute(%params)
Complete the transaction. This should be called from the web server
(from 'return_url'). %params must contain any query parameters passed
in the redirect, and token should be set on the object.
execute() will set the transaction fields to indicate the result:
=over 4
=item is_success: 1 if the payment was successful, 0 if it was not.
=item error_message: An error message describing the reason for failure.
Unlike the message returned from C<create()>, this probably is meaningful
to the user, though the gateway may already have shown it to them.
=item order_number: The transaction ID number assigned by the processor.
=item authorization: The credit card or other authorization number
returned by the gateway. This may be needed to refund the payment or
for other customer service issues.
=back
If C<is_success> is true, the merchant system should record this as
a successful payment and apply it to the customer's account.
=head1 AUTHOR
Mark Wells <mark@freeside.biz>, based in part on code by Jeff Finucane.
=head1 COPYRIGHT
Copyright (c) 1999-2004 Jason Kohles.
Copyright (c) 2007-2013 Freeside Internet Services, Inc.
All rights reserved. This program is free software; you can redistribute
it and/or modify it under the same terms as Perl itself.
=head1 DISCLAIMER
THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
=head1 SEE ALSO
L<Business::OnlinePayment>, http://420.am/business-onlinepayment/
=cut
|