www_csc/lib/csc/Controller/payment.pm

625 lines
24 KiB

package csc::Controller::payment;
use strict;
use warnings;
use base 'Catalyst::Controller';
=head1 NAME
csc::Controller::payment - Catalyst Controller
=head1 DESCRIPTION
Catalyst Controller.
=head1 METHODS
=head2 index
=cut
sub index : Private {
my ( $self, $c ) = @_;
$c->response->redirect('http://www.libratel.at/')
unless defined $c->request->params->{sk} and
$c->request->params->{sk} eq $c->session->{shop}{session_key};
if(exists $c->session->{mpay24_errors}) {
$c->stash->{mpay24_errors} = $c->session->{mpay24_errors};
delete $c->session->{mpay24_errors};
}
if(exists $c->session->{refill}) {
$c->stash->{refill} = $c->session->{refill};
delete $c->session->{refill};
}
$c->stash->{template} = 'tt/shop/payment_select.tt';
$c->stash->{backend} = 'payment';
$c->stash->{sk} = $c->session->{shop}{session_key};
$c->stash->{phones} = $c->session->{shop}{phones};
$c->stash->{price_sum} = $c->session->{shop}{price_sum};
$c->stash->{tarif} = $c->session->{shop}{tarif};
$c->stash->{number} = '0'. $c->session->{shop}{number}{ac} .' '. $c->session->{shop}{number}{sn};
return 1;
}
sub dopay_eps : Local {
my ( $self, $c ) = @_;
$c->log->debug('***payment::dopay_eps called');
$c->response->redirect('http://www.libratel.at/')
unless defined $c->request->params->{sk} and
$c->request->params->{sk} eq $c->session->{shop}{session_key};
my $amount = $c->session->{shop}{price_sum} * 100;
my $bankname = $c->request->params->{bankname};
my ($bank, $bankid);
$bank = $bankname;
if($bankname =~ /^ARZ_/) {
($bank, $bankid) = split /_/, $bankname;
}
my $tid = $self->_start_transaction($c, 'eps', $amount);
unless($tid) {
$c->response->redirect('/payment?sk='. $c->session->{shop}{session_key});
return;
}
delete $c->session->{shop}{payment_details} if exists $c->session->{shop}{payment_details};
$c->session->{shop}{payment_details} = {
type => 'eps',
bank => $bank,
bankid => $bankid,
};
if($c->model('Mpay24')->accept_eps_payment($c, $tid, $amount, $bank, $bankid)) {
unless($c->model('Provisioning')->call_prov($c, 'billing', 'update_payment',
{ id => $tid,
data => { state => 'transact' },
},
undef
))
{
return;
}
$c->response->redirect($c->session->{mpay24}{LOCATION});
$c->log->info("redirected customer to ". $c->session->{mpay24}{LOCATION});
} elsif(defined $c->session->{mpay24}) { # application error
$self->_fail_transaction($c, $tid);
$c->session->{mpay24_errors}{eps} = $c->session->{mpay24}{EXTERNALSTATUS}
|| $c->model('Provisioning')->localize('Web.Payment.UnknownError');
$c->session->{refill}{eps}{bankname} = $bankname;
$c->response->redirect('/payment?sk='. $c->session->{shop}{session_key} .'#eps');
} else { # transport error
$self->_fail_transaction($c, $tid);
$c->session->{mpay24_errors}{eps} = $c->model('Provisioning')->localize('Web.Payment.HttpFailed');
$c->session->{refill}{eps}{bankname} = $bankname;
$c->response->redirect('/payment?sk='. $c->session->{shop}{session_key} .'#eps');
}
return 1;
}
sub dopay_elv : Local {
my ( $self, $c ) = @_;
$c->log->debug('***payment::dopay_elv called');
$c->response->redirect('http://www.libratel.at/')
unless defined $c->request->params->{sk} and
$c->request->params->{sk} eq $c->session->{shop}{session_key};
my $amount = $c->session->{shop}{price_sum} * 100;
my $agb_ack = $c->request->params->{agb_ack};
my $accountnumber = $c->request->params->{accountnumber};
my $bankid = $c->request->params->{bankid};
my $tid = $self->_start_transaction($c, 'elv', $amount);
unless($tid) {
$c->response->redirect('/payment?sk='. $c->session->{shop}{session_key});
return;
}
delete $c->session->{shop}{payment_details} if exists $c->session->{shop}{payment_details};
$c->session->{shop}{payment_details} = {
type => 'elv',
bankid => $bankid,
account => $accountnumber,
};
if($c->model('Mpay24')->accept_elv_payment($c, $tid, $amount, $accountnumber, $bankid)) {
$c->response->redirect('/shop/finish?sk='. $c->session->{shop}{session_key});
return;
} elsif(defined $c->session->{mpay24}) {
$self->_fail_transaction($c, $tid);
$c->session->{mpay24_errors}{elv} = $c->session->{mpay24}{EXTERNALSTATUS}
|| $c->model('Provisioning')->localize('Web.Payment.UnknownError');
$c->session->{refill}{elv}{accountnumber} = $accountnumber;
$c->session->{refill}{elv}{bankid} = $bankid;
$c->response->redirect('/payment?sk='. $c->session->{shop}{session_key} .'#elv');
} else {
$self->_fail_transaction($c, $tid);
$c->session->{mpay24_errors}{elv} = $c->model('Provisioning')->localize('Web.Payment.HttpFailed');
$c->session->{refill}{elv}{accountnumber} = $accountnumber;
$c->session->{refill}{elv}{bankid} = $bankid;
$c->response->redirect('/payment?sk='. $c->session->{shop}{session_key} .'#elv');
}
return 1;
}
sub dopay_cc : Local {
my ( $self, $c ) = @_;
$c->log->debug('***payment::dopay_cc called');
$c->response->redirect('http://www.libratel.at/')
unless defined $c->request->params->{sk} and
$c->request->params->{sk} eq $c->session->{shop}{session_key};
my $amount = $c->session->{shop}{price_sum} * 100;
my $cctype = $c->request->params->{cctype};
my $cardnum = $c->request->params->{cardnum};
my $cvc = $c->request->params->{cvc};
my $cc_month = $c->request->params->{cc_month};
my $cc_year = $c->request->params->{cc_year};
$cc_year =~ s/^\d\d//;
my $expiry = sprintf("%02d%02d", $cc_year, $cc_month);
my $tid = $self->_start_transaction($c, 'cc', $amount);
unless($tid) {
$c->response->redirect('/payment?sk='. $c->session->{shop}{session_key});
return;
}
delete $c->session->{shop}{payment_details} if exists $c->session->{shop}{payment_details};
$c->session->{shop}{payment_details} = {
type => 'cc',
cctype => $cctype,
cardnum => $cardnum,
};
$c->session->{shop}{payment_details}{cardnum} =~ s/^(\d{8})(\d+)/$1 . "x" x length $2/ex;
my $rc = $c->model('Mpay24')->accept_cc_payment($c, $tid, $amount, $cctype, $cardnum, $expiry, $cvc);
if($rc == 1) {
$c->response->redirect('/shop/finish?sk='. $c->session->{shop}{session_key});
return;
} elsif($rc == 2) {
unless($c->model('Provisioning')->call_prov($c, 'billing', 'update_payment',
{ id => $tid,
data => { state => 'transact' },
},
undef
))
{
return;
}
$c->response->redirect($c->session->{mpay24}{LOCATION});
$c->log->info("redirected customer to ". $c->session->{mpay24}{LOCATION});
} elsif(defined $c->session->{mpay24}) {
$self->_fail_transaction($c, $tid);
$c->session->{mpay24_errors}{cc} = $c->session->{mpay24}{EXTERNALSTATUS}
|| $c->model('Provisioning')->localize('Web.Payment.UnknownError');
$c->session->{refill}{cc}{cctype} = $cctype;
$c->session->{refill}{cc}{cardnum} = $cardnum;
$c->session->{refill}{cc}{cvc} = $cvc;
$c->session->{refill}{cc}{cc_month} = $cc_month;
$c->session->{refill}{cc}{cc_year} = $cc_year;
$c->response->redirect('/payment?sk='. $c->session->{shop}{session_key} .'#cc');
} else {
$self->_fail_transaction($c, $tid);
$c->session->{mpay24_errors}{cc} = $c->model('Provisioning')->localize('Web.Payment.HttpFailed');
$c->session->{refill}{cc}{cctype} = $cctype;
$c->session->{refill}{cc}{cardnum} = $cardnum;
$c->session->{refill}{cc}{cvc} = $cvc;
$c->session->{refill}{cc}{cc_month} = $cc_month;
$c->session->{refill}{cc}{cc_year} = $cc_year;
$c->response->redirect('/payment?sk='. $c->session->{shop}{session_key} .'#cc');
}
return 1;
}
sub dopay_maestro : Local {
my ( $self, $c ) = @_;
$c->log->debug('***payment::dopay_maestro called');
$c->response->redirect('http://www.libratel.at/')
unless defined $c->request->params->{sk} and
$c->request->params->{sk} eq $c->session->{shop}{session_key};
my $amount = $c->session->{shop}{price_sum} * 100;
my $cardnum = $c->request->params->{cardnum};
my $maestro_month = $c->request->params->{maestro_month};
my $maestro_year = $c->request->params->{maestro_year};
$maestro_year =~ s/^\d\d//;
my $expiry = sprintf("%02d%02d", $maestro_year, $maestro_month);
my $tid = $self->_start_transaction($c, 'maestro', $amount);
unless($tid) {
$c->response->redirect('/payment?sk='. $c->session->{shop}{session_key});
return;
}
delete $c->session->{shop}{payment_details} if exists $c->session->{shop}{payment_details};
$c->session->{shop}{payment_details} = {
type => 'maestro',
cardnum => $cardnum,
};
if($c->model('Mpay24')->accept_maestro_payment($c, $tid, $amount, $cardnum, $expiry)) {
unless($c->model('Provisioning')->call_prov($c, 'billing', 'update_payment',
{ id => $tid,
data => { state => 'transact' },
},
undef
))
{
return;
}
$c->response->redirect($c->session->{mpay24}{LOCATION});
$c->log->info("redirected customer to ". $c->session->{mpay24}{LOCATION});
} elsif(defined $c->session->{mpay24}) {
$self->_fail_transaction($c, $tid);
$c->session->{mpay24_errors}{maestro} = $c->session->{mpay24}{EXTERNALSTATUS}
|| $c->model('Provisioning')->localize('Web.Payment.UnknownError');
$c->session->{refill}{maestro}{cardnum} = $cardnum;
$c->session->{refill}{maestro}{maestro_month} = $maestro_month;
$c->session->{refill}{maestro}{maestro_year} = $maestro_year;
$c->response->redirect('/payment?sk='. $c->session->{shop}{session_key} .'#maestro');
} else {
$self->_fail_transaction($c, $tid);
$c->session->{mpay24_errors}{maestro} = $c->model('Provisioning')->localize('Web.Payment.HttpFailed');
$c->session->{refill}{maestro}{cardnum} = $cardnum;
$c->session->{refill}{maestro}{maestro_month} = $maestro_month;
$c->session->{refill}{maestro}{maestro_year} = $maestro_year;
$c->response->redirect('/payment?sk='. $c->session->{shop}{session_key} .'#maestro');
}
return 1;
}
sub dopay_paypal : Local {
my ( $self, $c ) = @_;
$c->log->debug('***payment::dopay_paypal called');
$c->response->redirect('http://www.libratel.at/')
unless defined $c->request->params->{sk} and
$c->request->params->{sk} eq $c->session->{shop}{session_key};
my $amount = $c->session->{shop}{price_sum} * 100;
my $tid = $self->_start_transaction($c, 'paypal', $amount);
unless($tid) {
$c->response->redirect('/payment?sk='. $c->session->{shop}{session_key});
return;
}
$c->session->{paypal}{tid} = $tid;
delete $c->session->{shop}{payment_details} if exists $c->session->{shop}{payment_details};
$c->session->{shop}{payment_details} = { type => 'paypal' };
unless($c->model('Paypal')->set_express_checkout($c, $amount, 'shop')) {
$c->response->redirect('/payment?sk='. $c->session->{shop}{session_key});
return;
}
$c->response->redirect($c->config->{paypal_redirecturl} . $c->session->{paypal}{Token});
return 1;
}
sub paidack : Local {
my ( $self, $c ) = @_;
$c->log->debug('***payment::paidack called');
my $token = $c->request->params->{token};
my $payerid = $c->request->params->{PayerID};
if($c->session->{paypal}{Token} eq $token and length $payerid) {
$c->session->{paypal}{PayerID} = $payerid;
} else {
$c->session->{prov_error} = 'Server.Paypal.Invalid';
$c->response->redirect('/payment?sk='. $c->session->{shop}{session_key});
return;
}
unless($c->model('Paypal')->do_express_checkout($c)) {
$self->_fail_transaction($c, $c->session->{paypal}{tid});
$c->session->{prov_error} = 'Server.Paypal.Error' unless $c->session->{prov_error};
$c->response->redirect('/payment?sk='. $c->session->{shop}{session_key});
return;
}
$self->_finish_transaction($c, $c->session->{paypal}{tid});
$c->response->redirect('/shop/finish?sk='. $c->session->{shop}{session_key});
}
sub paiderr : Local {
my ( $self, $c ) = @_;
$c->log->debug('***payment::paiderr called');
$self->_fail_transaction($c, $c->session->{paypal}{tid});
$c->session->{prov_error} = 'Server.Paypal.Error';
$c->response->redirect('/payment?sk='. $c->session->{shop}{session_key});
}
sub confirm : Local {
my ( $self, $c ) = @_;
use Data::Dumper;
$c->log->info("***payment::confirm called!");
$c->log->info(Dumper $c->request->params);
unless($c->model('Provisioning')->call_prov($c, 'billing', 'update_payment',
{ id => $c->request->params->{TID},
data => { mpaytid => $c->request->params->{MPAYTID},
status => $c->request->params->{STATUS},
},
},
undef
))
{
return;
}
if($c->request->params->{STATUS} eq 'BILLED') {
$self->_finish_transaction($c, $c->request->params->{TID});
} elsif($c->request->params->{STATUS} eq 'ERROR') {
$self->_fail_transaction($c, $c->request->params->{TID});
}
$c->response->body('OK');
}
sub success : Local {
my ( $self, $c ) = @_;
use Data::Dumper;
$c->log->info("***payment::success called!");
$c->log->info(Dumper $c->request->params);
my $payment;
unless($c->model('Provisioning')->call_prov($c, 'billing', 'get_payment',
{ id => $c->request->params->{TID} },
\$payment
))
{
$c->response->redirect('/payment?sk='. $c->session->{shop}{session_key});
return;
}
my $order;
unless($c->model('Provisioning')->call_prov($c, 'billing', 'get_order',
{ id => $$payment{order_id} },
\$order
))
{
$c->response->redirect('/payment?sk='. $c->session->{shop}{session_key});
return;
}
$c->log->info("***payment::success payment $$payment{id} for order $$order{id} status is: $$payment{status} / $$payment{state}");
if($$order{type} eq 'charge') {
$c->response->redirect('https://csc.libratel.at/account/success?tid='. $$payment{id});
return;
}
if($$payment{status} eq 'RESERVED' or $$payment{status} eq 'BILLED' or $$payment{status} eq 'CREDITED') {
$c->response->redirect('/shop/finish?sk='. $c->session->{shop}{session_key});
return;
} else {
$c->response->redirect('/payment?sk='. $c->session->{shop}{session_key});
return;
}
}
sub error : Local {
my ( $self, $c ) = @_;
use Data::Dumper;
$c->log->info("***payment::error called!");
$c->log->info(Dumper $c->request->params);
my $payment;
unless($c->model('Provisioning')->call_prov($c, 'billing', 'get_payment',
{ id => $c->request->params->{TID} },
\$payment
))
{
$c->session->{mpay24_errors}{top} = $c->model('Provisioning')->localize('Web.Payment.ExternalError');
if($c->session->{shop}{session_key}) {
$c->response->redirect('/payment?sk='. $c->session->{shop}{session_key});
} elsif($c->session->{payment}{amount}) {
$c->response->redirect('https://csc.libratel.at/account/error?tid='. $c->request->params->{TID});
} else {
$c->response->redirect('http://'. $c->config->{www_server});
}
return;
}
my $order;
unless($c->model('Provisioning')->call_prov($c, 'billing', 'get_order',
{ id => $$payment{order_id} },
\$order
))
{
$c->session->{mpay24_errors}{top} = $c->model('Provisioning')->localize('Web.Payment.ExternalError');
if($c->session->{shop}{session_key}) {
$c->response->redirect('/payment?sk='. $c->session->{shop}{session_key});
} elsif($c->session->{payment}{amount}) {
$c->response->redirect('https://csc.libratel.at/account/error?tid='. $c->request->params->{TID});
} else {
$c->response->redirect('http://'. $c->config->{www_server});
}
return;
}
$c->log->info("***payment::error payment $$payment{id} for order $$order{id} status is: $$payment{status} / $$payment{state}");
if($$order{type} eq 'charge') {
$c->response->redirect('https://csc.libratel.at/account/error?tid='. $$payment{id});
return;
}
$c->session->{mpay24_errors}{$$payment{type}} = $$payment{externalstatus}
|| $c->model('Provisioning')->localize('Web.Payment.ExternalError');
$c->response->redirect('/payment?sk='. $c->session->{shop}{session_key} .'#'. $$payment{type});
return;
}
sub _start_transaction : Private {
my ($self, $c, $type, $amount) = @_;
my $payment_id;
unless($c->model('Provisioning')->call_prov($c, 'billing', 'create_payment',
{ order_id => $c->session->{shop}{order_id},
type => $type,
amount => $amount,
},
\$payment_id
))
{
return;
}
return $payment_id;
}
sub _finish_transaction : Private {
my ($self, $c, $tid) = @_;
unless($c->model('Provisioning')->call_prov($c, 'billing', 'update_payment',
{ id => $tid,
data => { state => 'success' },
},
undef
))
{
return;
}
my $payment;
unless($c->model('Provisioning')->call_prov($c, 'billing', 'get_payment',
{ id => $tid },
\$payment
))
{
return;
}
unless($c->model('Provisioning')->call_prov($c, 'billing', 'update_order',
{ id => $$payment{order_id},
data => { state => 'transact' },
},
undef
))
{
return;
}
my $order;
unless($c->model('Provisioning')->call_prov($c, 'billing', 'get_order',
{ id => $$payment{order_id} },
\$order
))
{
return;
}
foreach my $contract (@{$$order{contracts}}) {
next unless $$contract{class} eq 'voip';
unless($c->model('Provisioning')->call_prov($c, 'billing', 'activate_voip_account',
{ id => $$contract{id} },
undef
))
{
return;
}
}
return 1;
}
sub _fail_transaction : Private {
my ($self, $c, $tid) = @_;
my %mpay;
$mpay{mpaytid} = $c->session->{mpay24}{MPAYTID} if defined $c->session->{mpay24}{MPAYTID};
$mpay{status} = $c->session->{mpay24}{STATUS} if defined $c->session->{mpay24}{STATUS};
$mpay{errno} = $c->session->{mpay24}{ERRNO} if defined $c->session->{mpay24}{ERRNO};
$mpay{returncode} = $c->session->{mpay24}{RETURNCODE} if defined $c->session->{mpay24}{RETURNCODE};
$mpay{externalstatus} = $c->session->{mpay24}{EXTERNALSTATUS} if defined $c->session->{mpay24}{EXTERNALSTATUS};
unless($c->model('Provisioning')->call_prov($c, 'billing', 'update_payment',
{ id => $tid,
data => { state => 'failed', %mpay },
},
undef
))
{
return;
}
return 1;
}
sub end : ActionClass('RenderView') {
my ( $self, $c ) = @_;
$c->stash->{current_view} = 'Frontpage';
unless($c->response->{status} =~ /^3/) { # only if not a redirect
if(exists $c->session->{prov_error}) {
$c->session->{messages}{prov_error} = $c->session->{prov_error};
delete $c->session->{prov_error};
}
if(exists $c->session->{messages}) {
$c->stash->{messages} = $c->model('Provisioning')->localize($c->session->{messages});
delete $c->session->{messages};
}
}
}
=head1 BUGS AND LIMITATIONS
=over
=item functions should be documented
=back
=head1 SEE ALSO
Provisioning model, Catalyst
=head1 AUTHORS
Daniel Tiefnig <dtiefnig@sipwise.com>
=head1 COPYRIGHT
The payment controller is Copyright (c) 2007 Sipwise GmbH, Austria. All
rights reserved.
=cut
1;