1 package Business::OnlinePayment::HTTPS;
4 use vars qw($VERSION $DEBUG $ssl_module $skip_NetSSLeay);
7 use base qw(Business::OnlinePayment);
17 die if defined($skip_NetSSLeay) && $skip_NetSSLeay;
19 Net::SSLeay->VERSION(1.30);
22 # qw(get_https post_https make_form make_headers);
23 $ssl_module = 'Net::SSLeay';
28 require LWP::UserAgent;
29 require HTTP::Request::Common;
30 require Crypt::SSLeay;
32 #import HTTP::Request::Common qw(GET POST);
33 $ssl_module = 'Crypt::SSLeay';
37 unless ($ssl_module) {
38 die "One of Net::SSLeay (v1.30 or later)"
39 . " or Crypt::SSLeay (+LWP) is required";
46 Business::OnlinePayment::HTTPS - Base class for HTTPS payment APIs
50 package Business::OnlinePayment::MyProcessor;
51 use base qw(Business::OnlinePayment::HTTPS);
58 # pass a list (order is preserved, if your gateway needs that)
59 ( $page, $response, %reply_headers )
60 = $self->https_get( field => 'value', ... );
63 my %hash = ( field => 'value', ... );
64 ( $page, $response_code, %reply_headers )
65 = $self->https_get( \%hash );
72 This is a base class for HTTPS based gateways, providing useful code
73 for implementors of HTTPS payment APIs.
75 It depends on Net::SSLeay _or_ ( Crypt::SSLeay and LWP::UserAgent ).
81 =item https_get [ \%options ] HASHREF | FIELD => VALUE, ...
83 Accepts parameters as either a hashref or a list of fields and values.
84 In the latter case, ordering is preserved (see L<Tie::IxHash> to do so
85 when passing a hashref).
87 Returns a list consisting of the page content as a string, the HTTP
88 response code and message (i.e. "200 OK" or "404 Not Found"), and a list of
89 key/value pairs representing the HTTP response headers.
91 The options hashref supports setting headers and Content-Type:
94 headers => { 'X-Header1' => 'value', ... },
95 Content-Type => 'text/namevalue',
103 # handle optional options hashref
105 if ( scalar(@_) > 1 and ref( $_[0] ) eq "HASH" ) {
109 # accept a hashref or a list (keep it ordered)
111 if ( ref( $_[0] ) eq 'HASH' ) {
114 elsif ( scalar(@_) > 1 ) {
115 tie my %hash, 'Tie::IxHash', @_;
118 elsif ( scalar(@_) == 1 ) {
122 die "https_get called with no params\n";
125 $opts->{"Content-Type"} ||= "application/x-www-form-urlencoded";
129 if ( ref( $opts->{headers} ) eq "HASH" ) {
130 %headers = %{ $opts->{headers} };
132 $headers{'Host'} ||= $self->server;
134 my $path = $self->path;
135 if ( keys %$post_data ) {
138 map { uri_escape($_) . '=' . uri_escape( $post_data->{$_} ) }
142 $self->build_subs(qw( response_page response_code response_headers ));
144 if ( $ssl_module eq 'Net::SSLeay' ) {
146 import Net::SSLeay qw(get_https make_headers);
147 my $headers = make_headers(%headers);
149 my( $res_page, $res_code, @res_headers ) =
150 get_https( $self->server,
155 $opts->{"Content-Type"},
158 $res_code =~ /^(HTTP\S+ )?(.*)/ and $res_code = $2;
160 $self->response_page( $res_page );
161 $self->response_code( $res_code );
162 $self->response_headers( { @res_headers } );
164 ( $res_page, $res_code, @res_headers );
166 } elsif ( $ssl_module eq 'Crypt::SSLeay' ) {
168 import HTTP::Request::Common qw(GET);
170 my $url = 'https://' . $self->server;
171 $url .= ':' . $self->port
172 unless $self->port == 443;
175 my $ua = new LWP::UserAgent;
176 foreach my $hdr ( keys %headers ) {
177 $ua->default_header( $hdr => $headers{$hdr} );
179 my $res = $ua->request( GET($url) );
181 my @res_headers = map { $_ => $res->header($_) }
182 $res->header_field_names;
184 $self->response_page( $res->content );
185 $self->response_code( $res->code. ' '. $res->message );
186 $self->response_headers( { @res_headers } );
188 ( $res->content, $res->code. ' '. $res->message, @res_headers );
191 die "unknown SSL module $ssl_module";
196 =item https_post [ \%options ] SCALAR | HASHREF | FIELD => VALUE, ...
198 Accepts form fields and values as either a hashref or a list. In the
199 latter case, ordering is preserved (see L<Tie::IxHash> to do so when
202 Also accepts instead a simple scalar containing the raw content.
204 Returns a list consisting of the page content as a string, the HTTP
205 response code and message (i.e. "200 OK" or "404 Not Found"), and a list of
206 key/value pairs representing the HTTP response headers.
208 The options hashref supports setting headers and Content-Type:
211 headers => { 'X-Header1' => 'value', ... },
212 Content-Type => 'text/namevalue',
220 # handle optional options hashref
222 if ( scalar(@_) > 1 and ref( $_[0] ) eq "HASH" ) {
226 # accept a hashref or a list (keep it ordered)
228 if ( ref( $_[0] ) eq 'HASH' ) {
231 elsif ( scalar(@_) > 1 ) {
232 tie my %hash, 'Tie::IxHash', @_;
235 elsif ( scalar(@_) == 1 ) {
239 die "https_post called with no params\n";
242 $opts->{"Content-Type"} ||= "application/x-www-form-urlencoded";
246 if ( ref( $opts->{headers} ) eq "HASH" ) {
247 %headers = %{ $opts->{headers} };
249 $headers{'Host'} ||= $self->server;
251 if ( $DEBUG && ref($post_data) ) {
254 map { " $_ => " . $post_data->{$_} . "\n" } keys %$post_data );
257 $self->build_subs(qw( response_page response_code response_headers ));
259 if ( $ssl_module eq 'Net::SSLeay' ) {
261 import Net::SSLeay qw(post_https make_headers make_form);
262 my $headers = make_headers(%headers);
265 no warnings 'uninitialized';
266 warn $self->server . ':' . $self->port . $self->path . "\n";
267 $Net::SSLeay::trace = $DEBUG;
270 my $raw_data = ref($post_data) ? make_form(%$post_data) : $post_data;
272 my( $res_page, $res_code, @res_headers ) =
273 post_https( $self->server,
278 $opts->{"Content-Type"},
281 $res_code =~ /^(HTTP\S+ )?(.*)/ and $res_code = $2;
283 $self->response_page( $res_page );
284 $self->response_code( $res_code );
285 $self->response_headers( { @res_headers } );
287 ( $res_page, $res_code, @res_headers );
289 } elsif ( $ssl_module eq 'Crypt::SSLeay' ) {
291 import HTTP::Request::Common qw(POST);
293 my $url = 'https://' . $self->server;
294 $url .= ':' . $self->port
295 unless $self->port == 443;
302 my $ua = new LWP::UserAgent;
303 foreach my $hdr ( keys %headers ) {
304 $ua->default_header( $hdr => $headers{$hdr} );
308 if ( ref($post_data) ) {
309 $res = $ua->request( POST( $url, [%$post_data] ) );
312 my $req = new HTTP::Request( 'POST' => $url );
313 $req->content_type( $opts->{"Content-Type"} );
314 $req->content($post_data);
315 $res = $ua->request($req);
318 my @res_headers = map { $_ => $res->header($_) }
319 $res->header_field_names;
321 $self->response_page( $res->content );
322 $self->response_code( $res->code. ' '. $res->message );
323 $self->response_headers( { @res_headers } );
325 ( $res->content, $res->code. ' '. $res->message, @res_headers );
328 die "unknown SSL module $ssl_module";
337 L<Business::OnlinePayment>