PageRenderTime 98ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 1ms

/lib/Vend/Payment.pm

https://github.com/pajamian/interchange
Perl | 753 lines | 571 code | 100 blank | 82 comment | 89 complexity | 503f945a1ab2933608db19f917d02509 MD5 | raw file
  1. # Vend::Payment - Interchange payment processing routines
  2. #
  3. # $Id: Payment.pm,v 2.23 2009-03-20 22:15:56 markj Exp $
  4. #
  5. # Copyright (C) 2002-2009 Interchange Development Group
  6. # Copyright (C) 1996-2002 Red Hat, Inc.
  7. #
  8. # This program is free software; you can redistribute it and/or modify
  9. # it under the terms of the GNU General Public License as published by
  10. # the Free Software Foundation; either version 2 of the License, or
  11. # (at your option) any later version.
  12. #
  13. # This program is distributed in the hope that it will be useful,
  14. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. # GNU General Public License for more details.
  17. #
  18. # You should have received a copy of the GNU General Public
  19. # License along with this program; if not, write to the Free
  20. # Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
  21. # MA 02110-1301 USA.
  22. package Vend::Payment;
  23. require Exporter;
  24. $VERSION = substr(q$Revision: 2.23 $, 10);
  25. @ISA = qw(Exporter);
  26. @EXPORT = qw(
  27. charge
  28. charge_param
  29. );
  30. @EXPORT_OK = qw(
  31. map_actual
  32. );
  33. use Vend::Util;
  34. use Vend::Interpolate;
  35. use Vend::Order;
  36. use IO::Pipe;
  37. use strict;
  38. use vars qw/$Have_LWP $Have_Net_SSLeay/;
  39. my $pay_opt;
  40. my %cyber_remap = (
  41. qw/
  42. configfile CYBER_CONFIGFILE
  43. id CYBERCASH_ID
  44. mode CYBER_MODE
  45. host CYBER_HOST
  46. port CYBER_PORT
  47. remap CYBER_REMAP
  48. currency CYBER_CURRENCY
  49. precision CYBER_PRECISION
  50. /
  51. );
  52. my %ignore_mv_payment = (
  53. qw/
  54. gateway 1
  55. /
  56. );
  57. sub charge_param {
  58. my ($name, $value, $mode) = @_;
  59. my $opt;
  60. if($mode) {
  61. $opt = $Vend::Cfg->{Route_repository}{$mode} ||= {};
  62. }
  63. else {
  64. $opt = $pay_opt ||= {};
  65. }
  66. if($name =~ s/^mv_payment_//i) {
  67. $name = lc $name;
  68. }
  69. if(defined $value) {
  70. return $pay_opt->{$name} = $value;
  71. }
  72. # Find if set in route or options
  73. return $opt->{$name} if defined $opt->{$name};
  74. # "gateway" and possibly other future options
  75. return undef if $ignore_mv_payment{$name};
  76. # Now check Variable space as last resort
  77. my $uname = "MV_PAYMENT_\U$name";
  78. return $::Variable->{$uname} if defined $::Variable->{$uname};
  79. return $::Variable->{$cyber_remap{$name}}
  80. if defined $::Variable->{$cyber_remap{$name}};
  81. return undef;
  82. }
  83. # Do remapping of payment variables submitted by user
  84. # Can be changed/extended with remap/MV_PAYMENT_REMAP
  85. sub map_actual {
  86. my ($vref, $cref) = (@_);
  87. $vref = $::Values unless $vref;
  88. $cref = \%CGI::values unless $cref;
  89. my @map = qw(
  90. address
  91. address1
  92. address2
  93. amount
  94. b_address
  95. b_address1
  96. b_address2
  97. b_city
  98. b_country
  99. b_company
  100. b_fname
  101. b_lname
  102. b_name
  103. b_state
  104. b_zip
  105. check_account
  106. check_acctname
  107. check_accttype
  108. check_bankname
  109. check_checktype
  110. check_dl
  111. check_magstripe
  112. check_number
  113. check_routing
  114. check_transit
  115. city
  116. comment1
  117. comment2
  118. corpcard_type
  119. country
  120. cvv2
  121. email
  122. company
  123. fname
  124. item_code
  125. item_desc
  126. lname
  127. mv_credit_card_cvv2
  128. mv_credit_card_exp_month
  129. mv_credit_card_exp_year
  130. mv_credit_card_number
  131. mv_order_number
  132. mv_transaction_id
  133. name
  134. origin_zip
  135. phone_day
  136. phone_night
  137. pin
  138. po_number
  139. salestax
  140. shipping
  141. state
  142. tax_duty
  143. tax_exempt
  144. tender
  145. zip
  146. );
  147. my %map = qw(
  148. cyber_mode mv_cyber_mode
  149. comment giftnote
  150. );
  151. @map{@map} = @map;
  152. # Allow remapping of the variable names
  153. my $remap;
  154. if( $remap = charge_param('remap') ) {
  155. $remap =~ s/^\s+//;
  156. $remap =~ s/\s+$//;
  157. my (%remap) = split /[\s=]+/, $remap;
  158. for (keys %remap) {
  159. $map{$_} = $remap{$_};
  160. }
  161. }
  162. my %actual;
  163. my $key;
  164. my %billing_set;
  165. my @billing_set = qw/
  166. b_address1
  167. b_address2
  168. b_address3
  169. b_city
  170. b_state
  171. b_zip
  172. b_country
  173. /;
  174. my @billing_ind = qw/
  175. b_address1
  176. b_city
  177. /;
  178. if(my $str = $::Variable->{MV_PAYMENT_BILLING_SET}) {
  179. @billing_set = grep $_ !~ /\W/, split /[\s,\0]+/, $str;
  180. }
  181. if(my $str = $::Variable->{MV_PAYMENT_BILLING_INDICATOR}) {
  182. @billing_ind = grep $_ !~ /\W/, split /[\s,\0]+/, $str;
  183. }
  184. @billing_set{@billing_set} = @billing_set;
  185. my $no_billing_xfer = 1;
  186. for(@billing_ind) {
  187. $no_billing_xfer = 0 unless length($vref->{$_});
  188. }
  189. # pick out the right values, need alternate billing address
  190. # substitution
  191. foreach $key (keys %map) {
  192. $actual{$key} = $vref->{$map{$key}} || $cref->{$key};
  193. my $secondary = $key;
  194. next unless $secondary =~ s/^b_//;
  195. if ($billing_set{$key}) {
  196. next if $no_billing_xfer;
  197. $actual{$key} = $vref->{$secondary};
  198. next;
  199. }
  200. next if $actual{$key};
  201. $actual{$key} = $vref->{$map{$secondary}} || $cref->{$map{$secondary}};
  202. }
  203. $actual{name} = "$actual{fname} $actual{lname}"
  204. if $actual{lname};
  205. $actual{b_name} = "$actual{b_fname} $actual{b_lname}"
  206. if $actual{b_lname};
  207. if($actual{b_address1}) {
  208. $actual{b_address} = "$actual{b_address1}";
  209. $actual{b_address} .= ", $actual{b_address2}"
  210. if $actual{b_address2};
  211. }
  212. if($actual{address1}) {
  213. $actual{address} = "$actual{address1}";
  214. $actual{address} .= ", $actual{address2}"
  215. if $actual{address2};
  216. }
  217. # Do some standard processing of credit card expirations
  218. $actual{mv_credit_card_exp_month} =~ s/\D//g;
  219. $actual{mv_credit_card_exp_month} =~ s/^0+//;
  220. $actual{mv_credit_card_exp_year} =~ s/\D//g;
  221. $actual{mv_credit_card_exp_year} =~ s/\d\d(\d\d)/$1/;
  222. $actual{mv_credit_card_reference} = $actual{mv_credit_card_number} =~ s/\D//g;
  223. $actual{mv_credit_card_reference} =~ s/^(\d\d).*(\d\d\d\d)$/$1**$2/;
  224. $actual{mv_credit_card_exp_all} = sprintf(
  225. '%02d/%02d',
  226. $actual{mv_credit_card_exp_month},
  227. $actual{mv_credit_card_exp_year},
  228. );
  229. $actual{cyber_mode} = charge_param('transaction')
  230. || $actual{cyber_mode}
  231. || 'mauthcapture';
  232. return %actual;
  233. }
  234. sub gen_order_id {
  235. my $opt = shift || {};
  236. if( $opt->{order_id}) {
  237. # do nothing, already set
  238. }
  239. elsif($opt->{counter}) {
  240. $opt->{order_id} = Vend::Interpolate::tag_counter(
  241. $opt->{counter},
  242. { start => $opt->{counter_start} || 100000,
  243. sql => $opt->{sql_counter},
  244. },
  245. );
  246. }
  247. else {
  248. my(@t) = gmtime(time());
  249. my($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = @t;
  250. $opt->{order_id} = POSIX::strftime("%y%m%d%H%M%S$$", @t);
  251. }
  252. return $opt->{order_id};
  253. }
  254. sub charge {
  255. my ($charge_type, $opt) = @_;
  256. my $pay_route;
  257. ### We get the payment base information from a route with the
  258. ### same name as $charge_type if it is there
  259. if($Vend::Cfg->{Route}) {
  260. $pay_route = $Vend::Cfg->{Route_repository}{$charge_type} || {};
  261. }
  262. else {
  263. $pay_route = {};
  264. }
  265. ### Then we take any payment options set in &charge, [charge ...],
  266. ### or $Tag->charge
  267. # $pay_opt is package-scoped but lexical
  268. $pay_opt = { %$pay_route };
  269. for(keys %$opt) {
  270. $pay_opt->{$_} = $opt->{$_};
  271. }
  272. # We relocate these to subroutines to standardize
  273. ### Maps the form variable names to the names needed by the routine
  274. ### Standard names are defined ala Interchange or MV4.0x, b_name, lname,
  275. ### etc. with b_varname taking precedence for these. Falls back to lname
  276. ### if the b_lname is not set
  277. my (%actual) = map_actual();
  278. $pay_opt->{actual} = \%actual;
  279. # We relocate this to a subroutine to standardize. Uses the payment
  280. # counter if there
  281. my $orderID = gen_order_id($pay_opt);
  282. ### Set up the amounts. The {amount} key will have the currency prepended,
  283. ### e.g. "usd 19.95". {total_cost} has just the cost.
  284. # Uses the {currency} -> MV_PAYMENT_CURRENCY options if set
  285. my $currency = charge_param('currency')
  286. || ($Vend::Cfg->{Locale} && $Vend::Cfg->{Locale}{currency_code})
  287. || 'usd';
  288. # Uses the {precision} -> MV_PAYMENT_PRECISION options if set
  289. my $precision = charge_param('precision') || 2;
  290. my $penny = charge_param('penny_pricing') || 0;
  291. my $amount = $pay_opt->{amount} || Vend::Interpolate::total_cost();
  292. $amount = round_to_frac_digits($amount, $precision);
  293. $amount = sprintf "%.${precision}f", $amount;
  294. $amount *= 100 if $penny;
  295. $pay_opt->{total_cost} = $amount;
  296. $pay_opt->{amount} = "$currency $amount";
  297. ###
  298. ### Finish setting amounts and currency
  299. # If we have a previous payment amount, delete it but push it on a stack
  300. #
  301. my $stack = $Vend::Session->{payment_stack} || [];
  302. delete $Vend::Session->{payment_result};
  303. delete $Vend::Session->{cybercash_result}; ### Deprecated
  304. #::logDebug("Called charge at " . scalar(localtime));
  305. #::logDebug("Charge caller is " . join(':', caller));
  306. #::logDebug("mode=$pay_opt->{gateway}");
  307. #::logDebug("pay_opt=" . ::uneval($pay_opt));
  308. # Default to the gateway same as charge type if no gateway specified,
  309. # and set the gateway in the session for logging on completion
  310. if(! $opt->{gateway}) {
  311. $pay_opt->{gateway} = charge_param('gateway') || $charge_type;
  312. }
  313. #$charge_type ||= $pay_opt->{gateway};
  314. $Vend::Session->{payment_mode} = $pay_opt->{gateway};
  315. # See if we are in test mode
  316. $pay_opt->{test} = charge_param('test');
  317. # just convenience
  318. my $gw = $pay_opt->{gateway};
  319. # See if we are calling a defined GlobalSub payment mode
  320. my $sub = $Global::GlobalSub->{$gw};
  321. # Try our predefined modes
  322. if (! $sub and defined &{"Vend::Payment::$gw"} ) {
  323. $sub = \&{"Vend::Payment::$gw"};
  324. }
  325. # This is the return from all routines
  326. my %result;
  327. if($sub) {
  328. #::logDebug("Charge sub");
  329. # Calling a defined GlobalSub payment mode
  330. # Arguments are the passed option hash (if any) and the route hash
  331. my $pid;
  332. my $timeout = $pay_opt->{global_timeout} || charge_param('global_timeout');
  333. %result = eval {
  334. if ($timeout > 0) {
  335. my $pipe = IO::Pipe->new;
  336. unless ($pid = fork) {
  337. Vend::Server::child_process_dbi_prep();
  338. $pipe->writer;
  339. my %rv = $sub->($pay_opt);
  340. $pipe->print( ::uneval(\%rv) );
  341. exit;
  342. }
  343. $pipe->reader;
  344. my $to_msg = $pay_opt->{global_timeout_msg}
  345. || charge_param('global_timeout_msg')
  346. || 'Due to technical difficulties, your order could not be processed.';
  347. local $SIG{ALRM} = sub { die "$to_msg\n" };
  348. alarm $timeout;
  349. wait;
  350. alarm 0;
  351. $pid = undef;
  352. my $rv = eval join ('', $pipe->getlines);
  353. return %$rv;
  354. }
  355. return $sub->($pay_opt);
  356. };
  357. if($@) {
  358. my $msg = errmsg(
  359. "payment routine '%s' returned error: %s",
  360. $charge_type,
  361. $@,
  362. );
  363. kill (KILL => $pid)
  364. if $pid && kill (0 => $pid);
  365. ::logError($msg);
  366. $result{MStatus} = 'died';
  367. $result{MErrMsg} = $msg;
  368. }
  369. }
  370. elsif($charge_type =~ /^\s*custom\s+(\w+)(?:\s+(.*))?/si) {
  371. #::logDebug("Charge custom");
  372. # MV4 and IC4.6.x methods
  373. my (@args);
  374. @args = Text::ParseWords::shellwords($2) if $2;
  375. if(! defined ($sub = $Global::GlobalSub->{$1}) ) {
  376. ::logError("bad custom payment GlobalSub: %s", $1);
  377. return undef;
  378. }
  379. eval {
  380. %result = $sub->(@args);
  381. };
  382. if($@) {
  383. my $msg = errmsg(
  384. "payment routine '%s' returned error: %s",
  385. $charge_type,
  386. $@,
  387. );
  388. ::logError($msg);
  389. $result{MStatus} = $msg;
  390. }
  391. }
  392. elsif (
  393. $actual{cyber_mode} =~ /^minivend_test(?:_(.*))?/
  394. or
  395. $charge_type =~ /^internal_test(?:[ _]+(.*))?/
  396. )
  397. {
  398. #::logDebug("Internal test");
  399. # Test mode....
  400. my $status = $1 || charge_param('result') || undef;
  401. # Interchange test mode
  402. my %payment = ( %$pay_opt );
  403. &testSetServer ( %payment );
  404. %result = testsendmserver(
  405. $actual{cyber_mode},
  406. 'Order-ID' => $orderID,
  407. 'Amount' => $amount,
  408. 'Card-Number' => $actual{mv_credit_card_number},
  409. 'Card-Name' => $actual{b_name},
  410. 'Card-Address' => $actual{b_address},
  411. 'Card-City' => $actual{b_city},
  412. 'Card-State' => $actual{b_state},
  413. 'Card-Zip' => $actual{b_zip},
  414. 'Card-Country' => $actual{b_country},
  415. 'Card-Exp' => $actual{mv_credit_card_exp_all},
  416. );
  417. $result{MStatus} = $status if defined $status;
  418. }
  419. else {
  420. #::logDebug("Unknown charge type");
  421. my $msg = errmsg("Unknown charge type: %s", $charge_type);
  422. ::logError($msg);
  423. $result{MStatus} = $msg;
  424. }
  425. push @$stack, \%result;
  426. $Vend::Session->{payment_result} = \%result;
  427. $Vend::Session->{payment_stack} = $stack;
  428. my $svar = charge_param('success_variable') || 'MStatus';
  429. my $evar = charge_param('error_variable') || 'MErrMsg';
  430. if($result{$svar} !~ /^success/) {
  431. $Vend::Session->{payment_error} = $result{$evar};
  432. if ($result{$evar} =~ /\S/) {
  433. $Vend::Session->{errors}{mv_credit_card_valid} = $result{$evar};
  434. }
  435. $result{'invalid-order-id'} = delete $result{'order-id'}
  436. if $result{'order-id'};
  437. }
  438. elsif($result{$svar} =~ /success-duplicate/) {
  439. $Vend::Session->{payment_error} = $result{$evar};
  440. $result{'invalid-order-id'} = delete $result{'order-id'}
  441. if $result{'order-id'};
  442. }
  443. else {
  444. delete $Vend::Session->{payment_error};
  445. }
  446. $Vend::Session->{payment_id} = $result{'order-id'};
  447. my $encrypt = charge_param('encrypt');
  448. if($encrypt and $CGI::values{mv_credit_card_number} and $Vend::Cfg->{EncryptKey}) {
  449. my $prog = charge_param('encrypt_program') || $Vend::Cfg->{EncryptProgram};
  450. if($prog =~ /pgp|gpg/) {
  451. $CGI::values{mv_credit_card_force} = 1;
  452. (
  453. undef,
  454. $::Values->{mv_credit_card_info},
  455. $::Values->{mv_credit_card_exp_month},
  456. $::Values->{mv_credit_card_exp_year},
  457. $::Values->{mv_credit_card_exp_all},
  458. $::Values->{mv_credit_card_type},
  459. $::Values->{mv_credit_card_error}
  460. ) = encrypt_standard_cc(\%CGI::values);
  461. }
  462. }
  463. ::logError(
  464. "Order id for charge type %s: %s",
  465. $charge_type,
  466. $Vend::Session->{cybercash_id},
  467. )
  468. if $pay_opt->{log_to_error};
  469. # deprecated
  470. for(qw/ id error result /) {
  471. $Vend::Session->{"cybercash_$_"} = $Vend::Session->{"payment_$_"};
  472. }
  473. return \%result if $pay_opt->{hash};
  474. return $result{'order-id'};
  475. }
  476. sub testSetServer {
  477. my %options = @_;
  478. my $out = '';
  479. for(sort keys %options) {
  480. $out .= "$_=$options{$_}\n";
  481. }
  482. logError("Test CyberCash SetServer:\n%s\n" , $out);
  483. 1;
  484. }
  485. sub testsendmserver {
  486. my ($type, %options) = @_;
  487. my $out ="type=$type\n";
  488. for(sort keys %options) {
  489. $out .= "$_=$options{$_}\n";
  490. }
  491. logError("Test CyberCash sendmserver:\n$out\n");
  492. my $oid;
  493. eval {
  494. $oid = Vend::Interpolate::tag_counter(
  495. "$Vend::Cfg->{ScratchDir}/internal_test.payment.number"
  496. );
  497. };
  498. return ('MStatus', 'success', 'order-id', $oid || 'COUNTER_FAILED');
  499. }
  500. sub post_data {
  501. my ($opt, $query) = @_;
  502. unless ($opt->{use_wget} or $Have_Net_SSLeay or $Have_LWP) {
  503. die "No Net::SSLeay or Crypt::SSLeay found.\n";
  504. }
  505. my $submit_url = $opt->{submit_url};
  506. my $server;
  507. my $port = $opt->{port} || 443;
  508. my $script;
  509. my $protocol = $opt->{protocol} || 'https';
  510. if($submit_url) {
  511. $server = $submit_url;
  512. $server =~ s{^https://}{}i;
  513. $server =~ s{(/.*)}{};
  514. $port = $1 if $server =~ s/:(\d+)$//;
  515. $script = $1;
  516. }
  517. elsif ($opt->{host}) {
  518. $server = $opt->{host};
  519. $script = $opt->{script};
  520. $script =~ s:^([^/]):/$1:;
  521. $submit_url = join "",
  522. $protocol,
  523. '://',
  524. $server,
  525. ($port ? ":$port" : ''),
  526. $script,
  527. ;
  528. }
  529. my %header = ( 'User-Agent' => "Vend::Payment (Interchange version $::VERSION)");
  530. if($opt->{extra_headers}) {
  531. for(keys %{$opt->{extra_headers}}) {
  532. $header{$_} = $opt->{extra_headers}{$_};
  533. }
  534. }
  535. my %result;
  536. if($opt->{use_wget}) {
  537. ## Don't worry about OS independence with UNIX wget
  538. my $bdir = "$Vend::Cfg->{ScratchDir}/wget";
  539. unless (-d $bdir) {
  540. mkdir $bdir, 0777
  541. or do {
  542. my $msg = "Failed to create directory %s: %s";
  543. $msg = errmsg($msg, $bdir, $!);
  544. logError($msg);
  545. die $msg;
  546. };
  547. }
  548. my $filebase = "$Vend::SessionID.wget";
  549. my $statfile = Vend::File::get_filename("$filebase.stat", 1, 1, $bdir);
  550. my $outfile = Vend::File::get_filename("$filebase.out", 1, 1, $bdir);
  551. my $infile = Vend::File::get_filename("$filebase.in", 1, 1, $bdir);
  552. my $cmd = $opt->{use_wget} =~ m{/} ? $opt->{use_wget} : 'wget';
  553. my @post;
  554. while( my ($k,$v) = each %$query ) {
  555. $k = hexify($k);
  556. $v = hexify($v);
  557. push @post, "$k=$v";
  558. }
  559. my $post = join "&", @post;
  560. open WIN, "> $infile"
  561. or die errmsg("Cannot create wget post input file %s: %s", $infile, $!) . "\n";
  562. print WIN $post;
  563. local($/);
  564. my @args = $cmd;
  565. push @args, "--output-file=$statfile";
  566. push @args, "--output-document=$outfile";
  567. push @args, "--server-response";
  568. push @args, "--post-file=$infile";
  569. push @args, $submit_url;
  570. system @args;
  571. #::logDebug("wget cmd line: " . join(" ", @args));
  572. if($?) {
  573. $result{reply_os_error} = $!;
  574. $result{reply_os_status} = $?;
  575. $result{result_page} = 'FAILED';
  576. }
  577. else {
  578. #::logDebug("wget finished.");
  579. open WOUT, "< $outfile"
  580. or die errmsg("Cannot read wget output from %s: %s", $outfile, $!) . "\n";
  581. $result{result_page} = <WOUT>;
  582. close WOUT
  583. or die errmsg("Cannot close wget output %s: %s", $outfile, $!) . "\n";
  584. unlink $outfile unless $opt->{debug};
  585. }
  586. seek(WIN, 0, 0)
  587. or die errmsg("Cannot seek on wget input file %s: %s", $infile, $!) . "\n";
  588. unless($opt->{debug}) {
  589. my $len = int(length($post) / 8) + 1;
  590. print WIN 'deadbeef' x $len;
  591. }
  592. close WIN
  593. or die errmsg("Cannot close wget post input file %s: %s", $infile, $!) . "\n";
  594. unlink $infile unless $opt->{debug};
  595. open WSTAT, "< $statfile"
  596. or die errmsg("Cannot read wget status from %s: %s", $statfile, $!) . "\n";
  597. my $err = <WSTAT>;
  598. close WSTAT
  599. or die errmsg("Cannot close wget status %s: %s", $statfile, $!) . "\n";
  600. unlink $statfile unless $opt->{debug};
  601. $result{wget_output} = $err;
  602. $err =~ s/.*HTTP\s+request\s+sent,\s+awaiting\s+response[.\s]*//s;
  603. my @raw = split /\r?\n/, $err;
  604. my @head;
  605. for(@raw) {
  606. s/^\s*\d+\s*//
  607. or last;
  608. push @head, $_;
  609. }
  610. $result{status_line} = shift @head;
  611. $result{status_line} =~ /^HTTP\S+\s+(\d+)/
  612. and $result{response_code} = $1;
  613. $result{header_string} = join "\n", @head;
  614. }
  615. elsif($opt->{use_net_ssleay} or ! $opt->{use_crypt_ssl} && $Have_Net_SSLeay) {
  616. #::logDebug("placing Net::SSLeay request: host=$server, port=$port, script=$script");
  617. #::logDebug("values: " . ::uneval($query) );
  618. my ($page, $response, %reply_headers)
  619. = post_https(
  620. $server, $port, $script,
  621. make_headers( %header ),
  622. make_form( %$query ),
  623. );
  624. my $header_string = '';
  625. for(keys %reply_headers) {
  626. $header_string .= "$_: $reply_headers{$_}\n";
  627. }
  628. #::logDebug("received Net::SSLeay header: $header_string");
  629. $result{status_line} = $response;
  630. $result{status_line} =~ /^HTTP\S+\s+(\d+)/
  631. and $result{response_code} = $1;
  632. $result{header_string} = $header_string;
  633. $result{result_page} = $page;
  634. }
  635. else {
  636. my @query = %{$query};
  637. my $ua = new LWP::UserAgent;
  638. my $req = POST($submit_url, \@query, %header);
  639. #::logDebug("placing LWP request: " . ::uneval_it($req) );
  640. my $resp = $ua->request($req);
  641. $result{status_line} = $resp->status_line();
  642. $result{status_line} =~ /(\d+)/
  643. and $result{response_code} = $1;
  644. $result{header_string} = $resp->as_string();
  645. $result{header_string} =~ s/\r?\n\r?\n.*//s;
  646. #::logDebug("received LWP header: $header_string");
  647. $result{result_page} = $resp->content();
  648. }
  649. #::logDebug("returning thing: " . ::uneval(\%result) );
  650. return \%result;
  651. }
  652. 1;
  653. __END__