From fe369ed93a3b07513478656e884b82435bf0a92d Mon Sep 17 00:00:00 2001 From: Martin Stenberg Date: Sun, 13 Dec 2015 15:08:53 +0100 Subject: [PATCH] Bug 15335: Online payment of fines This patch implements DIBS online payments for paying fines and other charges directly from OPAC. Patch prepares for easily integrating other payment services, such as Paypal. Test plan: 1. apply patch 2. run updatedatabase.pl 3. create a DIBS account at http://www.dibspayment.com/demo-signup 4. set system preferences OpacPayment* and make sure OPACBaseURL is set 5. create some fines for a patron (e.g. make a checkout with a passed return date) 6. log in to opac with said patron 7. go to "your fines" 8. fines should now show under the "Fines and charges" header 9. select the fines you want to pay and press "Checkout" 10. confirm and/or update your billing information 11. press "confirm & pay" 12. test cards can be found here: http://tech.dibspayment.com/D2/Toolbox/Test_information/Cards --- C4/Payment.pm | 244 +++++++++++++++++++++ .../atomicupdate/bug_15335-payment-sysprefs.sql | 8 + .../data/mysql/atomicupdate/bug_15335-payment.sql | 23 ++ .../prog/en/modules/admin/preferences/opac.pref | 53 +++++ .../opac-tmpl/bootstrap/en/modules/opac-account.tt | 114 +++++++++- .../bootstrap/en/modules/opac-pay-dibs.tt | 213 ++++++++++++++++++ koha-tmpl/opac-tmpl/bootstrap/less/opac.less | 4 + opac/opac-pay-dibs.pl | 214 ++++++++++++++++++ 8 files changed, 871 insertions(+), 2 deletions(-) create mode 100644 C4/Payment.pm create mode 100644 installer/data/mysql/atomicupdate/bug_15335-payment-sysprefs.sql create mode 100644 installer/data/mysql/atomicupdate/bug_15335-payment.sql create mode 100644 koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-pay-dibs.tt create mode 100755 opac/opac-pay-dibs.pl diff --git a/C4/Payment.pm b/C4/Payment.pm new file mode 100644 index 0000000..ee2a376 --- /dev/null +++ b/C4/Payment.pm @@ -0,0 +1,244 @@ +package C4::Payment; + +# This file is part of Koha. +# +# Koha is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# Koha is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Koha; if not, see . + +use Modern::Perl; +use C4::Context; +use C4::Members; +use C4::Log qw(logaction); + +use Digest::MD5 qw ( md5_hex ); +use Carp; +use Data::Dumper qw(Dumper); + +use vars qw($VERSION @ISA @EXPORT); + +BEGIN { + # set the version for version checking + $VERSION = 3.07.00.049; + require Exporter; + @ISA = qw(Exporter); + @EXPORT = qw( + &AddOrder + &DelOrder + &ModOrder + &GetOrder + &AddToOrder + &GetOrderDetails + &GetOrderHash + ); +} + +=head1 NAME + +C4::Payment - Functions for dealing with online payments + +=head1 SYNOPSIS + +use C4::Payment; + +=head1 DESCRIPTION + +The functions in this module deal with the orders and online payments. +They allow to add, delete and modify orders. + +=head1 FUNCTIONS + +=head2 AddOrder + + &AddOrder(); + +=cut + +sub AddOrder { + my $args = shift; + croak "No borrowernumber provided" unless $args && $args->{'borrowernumber'}; + my $dbh = C4::Context->dbh; + + my $query = + 'INSERT INTO paymentorders ' . '(' + . join( ',', keys %$args ) . ')' + . 'VALUES (' + . join( ',', map { '?' } keys %$args ) . ')'; + + my $sth = $dbh->prepare($query); + $sth->execute( values %$args ); + $sth->finish(); + return $dbh->{mysql_insertid}; +} + +=head2 AddToOrder + + &AddToOrder($orderid, $accountlines_id); + +=cut + +sub AddToOrder { + my ($orderid, $accountlines_id) = @_; + croak "No accountlines_id provided" unless $accountlines_id; + croak "No orderid provided" unless $orderid; + my $dbh = C4::Context->dbh; + + my $sth = $dbh->prepare( ' + SELECT * FROM accountlines + WHERE + accountlines_id=? + ' ); + $sth->execute($accountlines_id); + my $accountline = $sth->fetchrow_hashref; + croak "No such accountline: $accountlines_id" unless $accountline; + + my $amount = $accountline->{'amountoutstanding'}; + my $currency = C4::Context->preference('OpacPaymentCurrency'); + + $sth = $dbh->prepare( ' + INSERT INTO paymentorderdetails + (orderid, accountlines_id, amount, currency) + VALUES (?, ?, ?, ?) + ' ); + $sth->execute( $orderid, $accountlines_id, $amount, $currency ); + $sth->finish(); +} + +=head2 DelOrder + + &DelOrder($orderid); + +=cut + +sub DelOrder { + my $orderid = shift; + croak "No orderid provided" unless $orderid; + my $dbh = C4::Context->dbh; + + my $sth = $dbh->prepare( ' + DELETE FROM paymentorders + WHERE + orderid=? + ' ); + $sth->execute($orderid); + $sth->finish(); +} + +=head2 GetOrder + + &GetOrder($orderid); + +=cut + +sub GetOrder { + my $orderid = shift; + croak "No orderid provided" unless $orderid; + my $dbh = C4::Context->dbh; + + my $sth = $dbh->prepare( ' + SELECT * FROM paymentorders + WHERE + orderid=? + ' ); + $sth->execute($orderid); + return $sth->fetchrow_hashref; +} + +=head2 ModOrder + + &ModOrder($order); + +=cut + +sub ModOrder { + my $order = shift; + croak "Incomplete order provided" unless $order->{'orderid'}; + my $dbh = C4::Context->dbh; + + my $query = 'UPDATE paymentorders'; + $query .= ' SET ' . join( ' = ?, ', keys %$order ) . ' = ?'; + $query .= ' WHERE orderid = ?'; + my $sth = $dbh->prepare($query); + $sth->execute( values %$order, $order->{'orderid'} ); + $sth->finish(); +} + +=head2 GetOrderDetails + + &GetOrderDetails($orderid); + +=cut + +sub GetOrderDetails { + my $orderid = shift; + croak "No orderid provided" unless $orderid; + my $dbh = C4::Context->dbh; + + my $sth = $dbh->prepare(' + SELECT paymentorderdetails.*, accountlines.* FROM paymentorderdetails + LEFT JOIN accountlines ON paymentorderdetails.accountlines_id=accountlines.accountlines_id + WHERE + orderid=? + '); + $sth->execute($orderid); + return $sth->fetchall_arrayref( {} ); +} + +=head2 GetOrderHash_DIBS + + &GetOrderHash_DIBS($orderid); + +=cut + +sub GetOrderHash { + my $orderid = shift; + croak "No orderid provided" unless $orderid; + + my $order = GetOrder($orderid); + croak "No such order: $orderid" unless $order; + + my $provider = C4::Context->preference('OpacPaymentProvider'); + + if ( $provider eq 'dibs' ) { + my $currency = C4::Context->preference('OpacPaymentCurrency'); + my $merchantid = C4::Context->preference('OpacPaymentMerchantID'); + my $k1 = C4::Context->preference('OpacPaymentK1'); + my $k2 = C4::Context->preference('OpacPaymentK2'); + + my $data = + "merchant=" + . $merchantid + . "&orderid=" + . $orderid + . "¤cy=" + . $currency + . "&amount=" + . ( $order->{'amount'} / + C4::Context->preference('OpacPaymentCurrencySubunit') ); + + return md5_hex( $k2 . md5_hex( $k1 . $data ) ); + } else { + croak "GetOrderHash for provider \"$provider\" not implemented"; + } +} + +END { } # module clean-up code here (global destructor) + +1; +__END__ + +=head1 AUTHOR + +Martin Stenberg + +=cut + diff --git a/installer/data/mysql/atomicupdate/bug_15335-payment-sysprefs.sql b/installer/data/mysql/atomicupdate/bug_15335-payment-sysprefs.sql new file mode 100644 index 0000000..f747c95 --- /dev/null +++ b/installer/data/mysql/atomicupdate/bug_15335-payment-sysprefs.sql @@ -0,0 +1,8 @@ +INSERT INTO systempreferences (variable,value,options,explanation,type) VALUES('OpacPayment','0',NULL,'Online payments from OPAC','YesNo'); +INSERT INTO systempreferences (variable,value,options,explanation,type) VALUES('OpacPaymentTest','1',NULL,'Online payments test','YesNo'); +INSERT INTO systempreferences (variable,value,options,explanation,type) VALUES('OpacPaymentProvider','dibs','dibs','Provider','Choice'); +INSERT INTO systempreferences (variable,value,options,explanation,type) VALUES ('OpacPaymentMerchantID','',NULL,'Merchant ID','Free'); +INSERT INTO systempreferences (variable,value,options,explanation,type) VALUES ('OpacPaymentK1','',NULL,'Authentication key 1','Free'); +INSERT INTO systempreferences (variable,value,options,explanation,type) VALUES ('OpacPaymentK2','',NULL,'Authentication key 2','Free'); +INSERT INTO systempreferences (variable,value,options,explanation,type) VALUES('OpacPaymentCurrency','208','208|978|840|826|752|036|124|352|392|554|578|756|949','Currency', 'Choice'); +INSERT INTO systempreferences (variable,value,options,explanation,type) VALUES ('OpacPaymentCurrencySubunit','0.001',NULL,'Smallest subunit of currency','Free'); diff --git a/installer/data/mysql/atomicupdate/bug_15335-payment.sql b/installer/data/mysql/atomicupdate/bug_15335-payment.sql new file mode 100644 index 0000000..4e3eddd --- /dev/null +++ b/installer/data/mysql/atomicupdate/bug_15335-payment.sql @@ -0,0 +1,23 @@ +DROP TABLE IF EXISTS `paymentorders`; +DROP TABLE IF EXISTS `paymentorderdetails`; + +CREATE TABLE `paymentorders` ( + `orderid` INT(11) NOT NULL auto_increment, + `orderdate` TIMESTAMP DEFAULT NOW(), + `modificationdate` TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + `status` ENUM('pending', 'payed','canceled') DEFAULT 'pending', + `amount` DOUBLE DEFAULT 0, + `currency` SMALLINT DEFAULT NULL, + `borrowernumber` INT(11) NOT NULL, + PRIMARY KEY (`orderid`), + CONSTRAINT `paymentorders_ibfk_1` FOREIGN KEY (`borrowernumber`) REFERENCES `borrowers` (`borrowernumber`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +CREATE TABLE `paymentorderdetails` ( + `orderid` INT(11) NOT NULL, + `accountlines_id` INT(11) NOT NULL, + `amount` DOUBLE DEFAULT 0, + `currency` SMALLINT DEFAULT NULL, + CONSTRAINT `paymentorderdetails_ibfk_1` FOREIGN KEY (`accountlines_id`) REFERENCES `accountlines` (`accountlines_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/opac.pref b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/opac.pref index 17d0b1a..b7eb79f 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/opac.pref +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/opac.pref @@ -705,3 +705,56 @@ OPAC: subtype: Subtypes sorting: Sorting location: Location and availability + Payment: + - + - pref: OpacPayment + choices: + yes: Enable + no: Disable + - "Online payments of fines and charges from OPAC. Requires + OPACBaseURL to be set." + - + - + - pref: OpacPaymentTest + choices: + yes: Do + no: Don't + - "run online payments in test mode (no real transactions will + occur)" + - + - Provider + - pref: OpacPaymentProvider + choices: + dibs: DIBS + - + - Merchant ID + - pref: OpacPaymentMerchantID + - + - Authentication key 1 + - pref: OpacPaymentK1 + - + - Authentication key 2 + - pref: OpacPaymentK2 + - + - Currency + - pref: OpacPaymentCurrency + choices: + 208: Danish Kroner (DKK) + 978: Euro (EUR) + 840: US Dollar $ (USD) + 826: English Pound £ (GBP) + 752: Swedish Kroner (SEK) + 036: Australian Dollar (AUD) + 124: Canadian Dollar (CAD) + 352: Icelandic Kroner (ISK) + 392: Japanese Yen (JPY) + 554: New Zealand Dollar (NZD) + 578: Norwegian Kroner (NOK) + 756: Swiss Franc (CHF) + 949: Turkish Lire (TRY) + - + - Smallest subunit of currency + - pref: OpacPaymentCurrencySubunit + default: 0.001 + class: currency + - (e.g. 1 cent = 0.001) diff --git a/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-account.tt b/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-account.tt index e26776c..136d6b8 100644 --- a/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-account.tt +++ b/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-account.tt @@ -24,11 +24,23 @@ [% INCLUDE 'navigation.inc' IsPatronPage=1 %] + [% SET HAVE_OUTSTANDING = 0 %] + [% FOREACH ACCOUNT_LINE IN ACCOUNT_LINES %] + [% IF ACCOUNT_LINE.amountoutstanding > 0 %] + [% HAVE_OUTSTANDING = 1 %] + [% LAST %] + [% END %] + [% END %]
+ [% IF HAVE_OUTSTANDING %]

Fines and charges

[% IF ( ACCOUNT_LINES ) %] + [% IF Koha.Preference('OpacPayment') %] +
+ + [% END %] @@ -36,18 +48,93 @@ + [% IF Koha.Preference('OpacPayment') %] + + [% END %] + [% IF Koha.Preference('OpacPayment') %] + + [% ELSE %] + [% END %] + [% IF Koha.Preference('OpacPayment') %] + + + + + [% END %] [% FOREACH ACCOUNT_LINE IN ACCOUNT_LINES %] + [% IF ACCOUNT_LINE.amountoutstanding > 0 %] + [% IF ( ACCOUNT_LINE.odd ) %][% ELSE %][% END %] + + + [% IF ( ACCOUNT_LINE.amountcredit ) %] + + [% IF Koha.Preference('OpacPayment') %] + + [% END %] + + [% END %] + [% END %] + +
Description Fine amount Amount outstandingPay
Total dueTotal due[% total %]
Total to pay0
[% ACCOUNT_LINE.date | $KohaDates %] + [% SWITCH ACCOUNT_LINE.accounttype %] + [% CASE 'Pay' %]Payment, thanks + [% CASE 'Pay00' %]Payment, thanks (cash via SIP2) + [% CASE 'Pay01' %]Payment, thanks (VISA via SIP2) + [% CASE 'Pay02' %]Payment, thanks (credit card via SIP2) + [% CASE 'N' %]New card + [% CASE 'F' %]Fine + [% CASE 'A' %]Account management fee + [% CASE 'M' %]Sundry + [% CASE 'L' %]Lost item + [% CASE 'W' %]Writeoff + [% CASE 'FU' %]Accruing fine + [% CASE 'Rent' %]Rental fee + [% CASE 'FOR' %]Forgiven + [% CASE 'LR' %]Lost item fee refund + [% CASE 'PAY' %]Payment + [% CASE 'WO' %]Writeoff + [% CASE 'C' %]Credit + [% CASE 'CR' %]Credit + [% CASE %][% ACCOUNT_LINE.accounttype %] + [%- END -%] + [%- IF ACCOUNT_LINE.description %], [% ACCOUNT_LINE.description %][% END %] + [% IF ACCOUNT_LINE.title %]([% ACCOUNT_LINE.title %])[% END %] + [% ELSE %][% END %][% ACCOUNT_LINE.amount %][% ACCOUNT_LINE.amountoutstanding %]
+ [% IF Koha.Preference('OpacPayment') %] + +
+ [% END %] + [% END %] + +

History

+ + + + + + + + + + + + [% FOREACH ACCOUNT_LINE IN ACCOUNT_LINES %] + [% IF ACCOUNT_LINE.amountoutstandingcredit %] [% IF ( ACCOUNT_LINE.odd ) %][% ELSE %][% END %] [% IF ( ACCOUNT_LINE.amountcredit ) %] - [% IF ( ACCOUNT_LINE.amountoutstandingcredit ) %] [% END %] + [% END %]
DateDescriptionFine amount
[% ACCOUNT_LINE.date | $KohaDates %] @@ -76,9 +163,9 @@ [% IF ACCOUNT_LINE.title %]([% ACCOUNT_LINE.title %])[% END %] [% ELSE %][% END %][% ACCOUNT_LINE.amount %][% ELSE %][% END %][% ACCOUNT_LINE.amountoutstanding %]
@@ -92,4 +179,27 @@
[% INCLUDE 'opac-bottom.inc' %] -[% BLOCK jsinclude %][% END %] +[% BLOCK jsinclude %] + +[% END %] diff --git a/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-pay-dibs.tt b/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-pay-dibs.tt new file mode 100644 index 0000000..414c0e9 --- /dev/null +++ b/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-pay-dibs.tt @@ -0,0 +1,213 @@ +[% USE Koha %] +[% USE KohaDates %] + +[% INCLUDE 'doc-head-open.inc' %] +[% IF ( LibraryNameTitle ) %][% LibraryNameTitle %][% ELSE %]Koha online[% END %] catalog › Pay fines and charges +[% INCLUDE 'doc-head-close.inc' %] +[% BLOCK cssinclude %][% END %] + + +[% INCLUDE 'bodytag.inc' bodyid='opac-account' bodyclass='scrollto' %] +[% INCLUDE 'masthead.inc' %] + +
+ + +
+
+
+ +
+
+
+ [% + SET SUBUNIT = Koha.Preference('OpacPaymentCurrencySubunit') || 1; + SET PRECISION = "%." _ SUBUNIT.replace('^[^\.]*\.','').length _ "f"; + %] +

Pay fines and charges

+ [% IF state == 'checkout' %] +
+ [% IF Koha.Preference('OpacPaymentTest') %] + + [% END %] + + + + + + + + + + + [% END %] +
+ [% IF state != 'success' %] +
+

Summary

+ + + + + + + + + + + + + [% IF state == 'success' %] + + [% ELSE %] + + [% END %] + + + + + [% FOREACH acctline IN accountlines %] + + + + [% IF state == 'success' %] + + [% ELSE %] + + [% END %] + + [% END %] + +
DateDescriptionAmount
Total[% order.amount | format(PRECISION) %][% order.amount | format(PRECISION) %]
[% acctline.date | $KohaDates %] + [% SWITCH acctline.accounttype %] + [% CASE 'Pay' %]Payment, thanks + [% CASE 'Pay00' %]Payment, thanks (cash via SIP2) + [% CASE 'Pay01' %]Payment, thanks (VISA via SIP2) + [% CASE 'Pay02' %]Payment, thanks (credit card via SIP2) + [% CASE 'N' %]New card + [% CASE 'F' %]Fine + [% CASE 'A' %]Account management fee + [% CASE 'M' %]Sundry + [% CASE 'L' %]Lost item + [% CASE 'W' %]Writeoff + [% CASE 'FU' %]Accruing fine + [% CASE 'Rent' %]Rental fee + [% CASE 'FOR' %]Forgiven + [% CASE 'LR' %]Lost item fee refund + [% CASE 'PAY' %]Payment + [% CASE 'WO' %]Writeoff + [% CASE 'C' %]Credit + [% CASE 'CR' %]Credit + [% CASE %][% acctline.accounttype %] + [%- END -%] + [%- IF acctline.description %], [% acctline.description %][% END %] + [% IF acctline.title %]([% acctline.title %])[% END %] + [% acctline.amountoutstanding | format(PRECISION) %][% acctline.amountoutstanding | format(PRECISION) %]
+ [% IF state == 'checkout' %] +
+ +
+ [% END %] +
+ [% END %] + [% IF state == 'checkout' %] +
+

Billing information

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
First name
Surname
Address
Address 2
Zip code
City
Cardholder name
Cardholder address
Zip code
Email
+
+ [% ELSIF state == 'success' %] +
+

Payment successful

+

+ Thank you! +

+
+ [% ELSIF state == 'error' %] +
+

Payment failed

+

Orderd ID: [% order.orderid %]

+

+ [% IF error == 'authkey' %] + Invalid authentication key recived. Some data was corrupted + during transaction. Please contact library staff. + [% END %] +

+
+ [% ELSIF state == 'canceled' %] +
+

Payment canceled

+

Orderd ID: [% order.orderid %]

+

+ Your payment was canceled. +

+
+ [% END %] +
+ [% IF state == 'checkout' %] +
+ [% END %] +
+
+
+
+
+ +[% INCLUDE 'opac-bottom.inc' %] +[% BLOCK jsinclude %] + +[% END %] diff --git a/koha-tmpl/opac-tmpl/bootstrap/less/opac.less b/koha-tmpl/opac-tmpl/bootstrap/less/opac.less index 6da32e5..cf30630 100644 --- a/koha-tmpl/opac-tmpl/bootstrap/less/opac.less +++ b/koha-tmpl/opac-tmpl/bootstrap/less/opac.less @@ -709,6 +709,10 @@ td.sum { font-weight: bold; } +td.sum.payed { + background-color: #CFC; +} + th[scope=row] { background-color: transparent; text-align : right; diff --git a/opac/opac-pay-dibs.pl b/opac/opac-pay-dibs.pl new file mode 100755 index 0000000..780f20a --- /dev/null +++ b/opac/opac-pay-dibs.pl @@ -0,0 +1,214 @@ +#!/usr/bin/perl + +# This file is part of Koha. +# +# Parts Copyright (C) 2013 Mark Tompsett +# +# Koha is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# Koha is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Koha; if not, see . + +use Modern::Perl; +use CGI qw ( -utf8 ); +use LWP::UserAgent; +use C4::Members; +use C4::Auth; # get_template_and_user +use C4::Output; +use C4::Context; +use C4::Payment; +use C4::Accounts; + +use Digest::MD5 qw ( md5_hex ); +use DateTime::Format::MySQL; +use Carp; + +my $cgi = new CGI; +my $dbh = C4::Context->dbh; +my $script_name = '/cgi-bin/koha/opac-pay-dibs.pl'; +my $baseurl = C4::Context->preference('OPACBaseURL') + or croak + 'OPACBaseURL not defined. Required for OPAC online payments to work.'; +my $action = $cgi->param('action'); + +if ( $action eq 'callback' ) { + my $orderid = $cgi->param('orderid'); + my $authkey = $cgi->param('authkey'); + + # DIBS-specific authentication check + my $k1 = C4::Context->preference('OpacPaymentK1'); + my $k2 = C4::Context->preference('OpacPaymentK2'); + my $my_authkey = md5_hex( + $k2 + . md5_hex( + $k1 + . 'transact=' + . $cgi->param('transact') + . '&amount=' + . $cgi->param('amount') + . '¤cy=' + . $cgi->param('currency') + ) + ); + + if ( $authkey ne $my_authkey ) { + print $cgi->header( + -type=>'text/plain', + -status=> '403 invalid authentication key' + ); + exit; + } + + # Authentication passed + + my $order = GetOrder($orderid); + my $orderdetails = GetOrderDetails($orderid); + + # make payments for each accountline + for my $od (@$orderdetails) { + makepayment( + $od->{'accountlines_id'}, + $od->{'borrowernumber'}, + $od->{'accountno'}, + $od->{'amount'}, + undef, # user + C4::Context->userenv ? C4::Context->userenv->{branch} : undef, + 'Online payment by user', # payment note + ); + } + + $order->{'status'} = 'payed'; + $order->{'modificationdate'} = + DateTime::Format::MySQL->format_datetime( DateTime->now ); + ModOrder($order); + + print $cgi->header( + -type=>'text/plain', + -status=> '200' + ); + exit; +} + +my ( $template, $borrowernumber, $cookie ) = get_template_and_user( + { + template_name => 'opac-pay-dibs.tt', + type => 'opac', + query => $cgi, + authnotrequired => ( C4::Context->preference('OpacPublic') ? 1 : 0 ), + } +); + +# get borrower information .... +my $borr = GetMemberDetails($borrowernumber); + +if ( $action eq 'checkout' ) { + #get account details + my @acctids = $cgi->multi_param('accountlines_id'); + my ( $total, $accts, $numaccts ) = GetMemberAccountRecords($borrowernumber); + my %accts_h = map { $_->{'accountlines_id'} => $_ } @$accts; + my @acctlines = map { $accts_h{$_} } @acctids; + + my $subunit = C4::Context->preference('OpacPaymentCurrencySubunit') || 1; + my $amount = 0; + $amount += $_->{'amountoutstanding'} for @acctlines; + + # Generate a new order id and add to db + my $orderid = AddOrder( + { + borrowernumber => $borrowernumber, + amount => $amount, + currency => C4::Context->preference('OpacPaymentCurrency') + } + ); + AddToOrder($orderid, $_->{'accountlines_id'} ) for @acctlines; + + $template->param( + BORROWER_INFO => $borr, + HTTP_COOKIE => $cookie, + accountlines => \@acctlines, + accepturl => $baseurl . $script_name . '?action=accept', + cancelurl => $baseurl . $script_name . '?action=cancel', + callbackurl => $baseurl . $script_name . '?action=callback', + lang => C4::Languages::getlanguage($cgi) || 'en', + amount => $amount / $subunit, + total => $amount, + currency => C4::Context->preference('OpacPaymentCurrency'), + merchant => C4::Context->preference('OpacPaymentMerchantID'), + order => GetOrder($orderid), + md5key => GetOrderHash($orderid), + state => 'checkout' + ); +} +elsif ( $action eq 'accept' ) { + my $orderid = $cgi->param('orderid'); + my $authkey = $cgi->param('authkey'); + + # DIBS-specific authentication check + my $k1 = C4::Context->preference('OpacPaymentK1'); + my $k2 = C4::Context->preference('OpacPaymentK2'); + my $my_authkey = md5_hex( + $k2 + . md5_hex( + $k1 + . 'transact=' + . $cgi->param('transact') + . '&amount=' + . $cgi->param('amount') + . '¤cy=' + . $cgi->param('currency') + ) + ); + + if ( $authkey ne $my_authkey ) { + $template->param( + BORROWER_INFO => $borr, + state => 'error', + error => 'authkey', + orderid => $orderid + ); + carp "Invalid authentication key returned for orderid $orderid"; + output_html_with_http_headers $cgi, $cookie, $template->output; + exit; + } + + # Authentication passed + + my $order = GetOrder($orderid); + my $orderdetails = GetOrderDetails($orderid); + + $template->param( + BORROWER_INFO => $borr, + accountlines => $orderdetails, + order => $order, + state => 'success' + ); +} +elsif ( $action eq 'cancel' ) { + my $orderid = $cgi->param('orderid'); + my $authkey = $cgi->param('authkey'); + + my $order = GetOrder($orderid); + my $orderdetails = GetOrderDetails($orderid); + + $order->{'status'} = 'canceled'; + $order->{'modificationdate'} = + DateTime::Format::MySQL->format_datetime( DateTime->now ); + ModOrder($order); + + $template->param( + BORROWER_INFO => $borr, + accountlines => $orderdetails, + order => $order, + state => 'canceled' + ); +} + +output_html_with_http_headers $cgi, $cookie, $template->output; -- 2.6.3