#!/usr/bin/perl
require "config.pl";
$time = time();
($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($time);
$hour1=$hour+1;
$mon++;
$year += 1900;
$lastyear = $year-1;
$lastyear2 = $year-2;
&read_post;
if ($INPUT{'charge_info'}){ &charge_info; }
if ($INPUT{'billing_contact'}){ &billing_contact; }
else{ &cc_form; }
#################################
sub charge_info{
$INPUT{'cc'}=~s/\D//g;
unless (cc_validate($INPUT{'cc'})){ &error('Credit card number is not correct'); }
if (!$INPUT{'year'} || !$INPUT{'month'} || !$INPUT{'day'}){ &error('Charge Date is not defined'); }
my $transaction_date = date_to_epoch($INPUT{'year'},$INPUT{'month'},$INPUT{'day'});
# cc_md5=[md5_value_of_creditcard], merchant_ids=[comma_separated_mids], transaction_date=[epoch_format_date]
my $post = "ACTION=MERCHANT_CS&cc_md5=".URLEncode(md5_create($INPUT{'cc'}))."&merchant_ids=".URLEncode($merchant_ids)."&transaction_date=".$transaction_date;
my $rez;
($rez,$hdr,$err)=curl_request($gateway_url,'',$post);
unless ($rez){ &error('connection error'); }
my %RZ = record_to_hash('',$rez);
my $EML_DATA;
if ($RZ{'ERROR'}){ &error( $RZ{'ERROR_CODE'}." - ".$RZ{'ERROR_MESSAGE'}); }
elsif(!$RZ{'SUCCESS'}){ &error('CONNECTION RESPONSE IS NOT CORRECT'); }
my @TRANSDATA = split(/\n/,$RZ{'TRANSDATA'});
my $count=0;
my $phone_verified="";
my $phone="";
my $OUTPUT = '
';
foreach my $line(@TRANSDATA){
$count++;
my %RE = record_to_hash('',$line);
if ($RE{'phone_verified'}){ $phone_verified=1; }
$phone = $RE{'phone'};
$OUTPUT.= < [$count] Transaction ID: $RE{'id1'} |
ORDER DATE: $RE{'date_order'} (GMT)
CHARGE DATE: $RE{'date_auth'} (GMT)
Amount: \$$RE{'AMOUNT'} USD
Name: $RE{'NAME'}
Street: $RE{'address'}
City: $RE{'city'}
State: $RE{'state'}
Zip: $RE{'zip'}
Country: $RE{'country'}
IP Address: $RE{'ip'}
IP Country: $RE{'ip_geo'}
IP State: $RE{'MAXMIND_ip_region'}
IP ISP: $RE{'MAXMIND_ip_isp'} / $RE{'MAXMIND_ip_org'}
Email: $RE{'email_masked'} (for privacy reason a part of email address is masked with "*")
Phone: $RE{'phone'}
|
EOF
$EML_DATA.=<";
}
$EML_DATA = encode($EML_DATA);
if ($phone_verified){
$VERIFIED_PHONE_MSG="NOTE: The submitted credit card number was authorized by phone. A cardholder answered an authorization call at the number $phone and confirmed it. The voice conversation is stored as the proof of purchase.
";
}
my $trword = "transaction";
$trword .= "s" if ($count > 1);
print "Content-type: text/html\n\n";
print <
$OUTPUT
$VERIFIED_PHONE_MSG
All background information of all orders including internet address and an unique identifier of personal computer of the purchaser were recorded at the time of purchase.
In case of credit card fraud, all collected information will be submitted to a domestic cyber crime police unit for investigation.
EOF
exit;
}
#############################################################################
sub billing_contact{
unless ($INPUT{'body'}){ &error('ERROR: "Your Message is emply" '); }
unless ($INPUT{'reason'}){ &error('ERROR: "Please select SUBJECT." '); }
unless ($INPUT{'from'}){ &error('ERROR: "Please fill your EMAIL." '); }
unless ($INPUT{'from'}=~/^([\w\-\.\_]+\@[\w\-\.]+\.[a-zA-Z]{2,4})$/){ &error("ERROR: EMAIL address is incorrect - .$INPUT{'from'} "); }
my $SUBJECT;
$SUBJECT = "BILLING INQUIRY: $INPUT{'reason'}";
$SUBJECT = "REFUND REQUEST: $INPUT{'reason'}" if ($INPUT{'reason'}=~/^(FRAUD|UNSATISFIED)$/);
$SUBJECT = "BILLING INQUIRY: $INPUT{'reason'}" if ($INPUT{'reason'}=~/^(OTHER)$/);
my $EML_DATA = decode($INPUT{'EDATA'});
my $FROM=$INPUT{'from'};
my $MESSAGE=<= 13 && 0+$number;
for ($i = 0; $i < length($number) - 1; $i++) {
$weight = substr($number, -1 * ($i + 2), 1) * (2 - ($i % 2));
$sum += (($weight < 10) ? $weight : ($weight - 9));
}
return 1 if substr($number, -1) == (10 - $sum % 10) % 10;
return 0;
}
#####################################
sub date_to_epoch{ # USAGE: ([year],[month],[day],[hour],[min],[sec])
my $year=$_[0];
my $month=$_[1];
my $day=$_[2];
my $hour=$_[3];
my $min=$_[4];
my $sec=$_[5];
if (!$month || !$year || !day){ &error_log("date_to_epoch: wrong parameters: $year $month $day"); return; }
eval ('use Time::Local;');
if ($@) { &error_log('DE','date_to_epoch: cannot load Time::Local,'.$@); return; }
my $DATE_UTC = timelocal($sec, $min, $hour, $day, ($month-1), $year);
return $DATE_UTC;
}
####################
sub URLEncode {
my $theURL = $_[0];
$theURL =~ s/([\W])/"%" . uc(sprintf("%2.2x",ord($1)))/eg;
return $theURL;
}
####################
sub URLDecode{
my $theURL = $_[0];
$theURL =~ tr/+/ /;
$theURL =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
return $theURL;
}
####################
sub md5_create{
my $string=$_[0];
require Digest::MD5;
$md5 = Digest::MD5->new;
$md5->add($string);
$digest = $md5->hexdigest;
$digest = uc($digest);
return $digest;
}
#########################################
sub read_post{
my $buffer;
read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'});
my @pairs = split(/&/, $buffer);
foreach $pair (@pairs) {
my ($name, $value) = split(/=/, $pair);
unless ($name=~/[-_\.a-zA-Z0-9\s]+/){ &error('invalid input name: '.$name);}
unless ($value=~/[-a-zA-Z0-9_\.\+\%\s]*/){ &error('invalid input value: '.$value);}
$value =~ tr/+/ /;
$value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
if ($value=~/\x00|\xFF/){ &error('illegal chars in input');}
if ($INPUT{$name}) { $INPUT{$name} = $INPUT{$name}.",".$value; }
else { $INPUT{$name} = $value; }
}
}
########################################################################
sub curl_request{ # USE: ([url],[referrer],[post],[login],[password],[connect_timeout],[max_connect_time])
# RETURN: ([content],[header],[error_message])
my $url = $_[0];
my $ref = $_[1];
my $post = $_[2];
my $login = $_[3];
my $passw = $_[4];
my $rez;
my $connect_timeout = 20;
my $max_connect_time = 600;
if ($_[5] >=1 ){ $connect_timeout = $_[5]; }
if ($_[6] >=1 ){ $max_connect_time = $_[6]; }
unless ($url=~/^https?\:\/\/[\w\.\-\_]+\:?\d{0,5}\/?.*$/s){
return ('','','ERROR: invalid url');
}
unless (($ref=~/^https?\:\/\/[\w\.\-\_]+\:?\d{0,5}\/?.*$/s)||(!$ref)){
return ('','','ERROR: invalid ref');
}
my $curl = "curl";
my $curl_opt='';
# $curl_opt.=' --max-filesize 100000'; # set limits
# $curl_opt.=' --retry 2 --retry-delay 5';
$curl_opt.=" --connect-timeout $connect_timeout --max-time $max_connect_time "; # set limits
$curl_opt.=" -i -k"; # include header to output, allow insecure ssl
$curl_opt.=" -e $ref" if ($ref);
$curl_opt.=" --data-ascii \"$post\"" if ($post); # POST
$curl_opt.=" -basic \"$login:$passw\"" if ($login && $passw); # BASIC AUTH
#open (README, "$curl $curl_opt \"$url\" 2>&1 |"); # receiving STDERR within STDOUT (best for debug)
open (README, "$curl $curl_opt \"$url\" 2>/dev/null |"); # disregarding STDERR
my $response=;
my ($header,$contin)="";
while (){
tr/\000-\037//d;
if ((!$_)&&($response=~/\S+ 100/)){ $response=""; } # deal with "HTTP/1.1 100 Continue"
elsif(!$_){ last; }
if (!$response){$response=$_;}
$header.=$_."\n";
}
my $content=join ("", ); # Ñ÷èòûâàåì îñòàòîê îòâåòà.
close (README);
my $resp_code=$1 if $response=~/\S+ (\d+)/;
#open (DD,">>./_curl");
#print DD "\n---\n$curl $curl_opt \"$url\"\n$content\n$header\n";
#close (DD);
if ($resp_code >= 300 and $resp_code < 400) {
return curl_request($1, $url) if $header=~/Location:\s+(.+)$/m;
return ("",$header,"CONNECTION ERROR: $response");
}elsif($response=~/200/) {
return ($content,$header,"");
}
elsif($response){
return ("",$header,"CONNECTION ERROR: $response");
}
else{
return ("","","CONNECTION ERROR: destination unreachable");
}
}
#####################################################################
sub record_to_hash{ # making hash values from a record string
# USAGE: (HASH_NAME, STRING_RECORD)
# EXAMPLE1: ('VENDOR','a=1&b=2&c=3') RESULT: make global %hash
# EXAMPLE2: ('','a=1&b=2&c=3') RESULT: returns localized %hash
my $hash_name=$_[0];
my $string=$_[1];
my %HSH=();
if ($hash_name){
eval('%'.$hash_name.'=();');
}
unless ($string=~/^[-a-zA-Z0-9_\.\,\;\+\%\s\=\&]+$/s){ &error_log('HR','record_to_hash: invalid STRING submitted 2: '.$string); return; }
if ($hash_name){
unless ($hash_name=~/^[a-zA-Z0-9_]+$/s){ &error_log('HR','record_to_hash: invalid HASH name submitted 2: '.$hash_name); return; }
}
my @pairs = split(/&/, $string);
foreach $pair (@pairs) {
my ($name, $value) = split(/=/, $pair);
unless ($name=~/^[-_\.a-zA-Z0-9\s]+$/){ &error_log('HR','record_to_hash: invalid name in db record: '.$name."
".$string); return; }
unless ($value=~/^[-a-zA-Z0-9_\.\,\;\+\%\s]*$/){ &error_log('HR','record_to_hash: invalid input in db record: '.$value); return; }
$value =~ tr/+/ /;
$value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
if ($value=~/\x00|\xFF/){ &error('record_to_hash: illegal chars in db string'); return; }
if ($hash_name){
eval('$'.$hash_name.'{$name} = $value;');
}
else{
$HSH{$name} = $value;
}
}
if (!$hash_name){
return %HSH;
}
}
#####################
sub error{
$msg = $_[0];
print "Content-type: text/plain\n\n";
print "SYSTEM ERROR: $msg";
exit;
return;
}
#########################################
sub cc_form{
print "Content-type: text/html\n\n";
print <
$COMPANY - BILLING SUPPORT