Bugzilla – Attachment 45617 Details for
Bug 15335
Online payment of fines
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
Bug 15335: Online payment of fines
Bug-15335-Online-payment-of-fines.patch (text/plain), 40.42 KB, created by
Martin Stenberg
on 2015-12-13 14:29:44 UTC
(
hide
)
Description:
Bug 15335: Online payment of fines
Filename:
MIME Type:
Creator:
Martin Stenberg
Created:
2015-12-13 14:29:44 UTC
Size:
40.42 KB
patch
obsolete
>From fe369ed93a3b07513478656e884b82435bf0a92d Mon Sep 17 00:00:00 2001 >From: Martin Stenberg <martin@xinxidi.net> >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 <http://www.gnu.org/licenses>. >+ >+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 <martin@koha.xinxidi.net> >+ >+=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 %] > </div> > </div> >+ [% SET HAVE_OUTSTANDING = 0 %] >+ [% FOREACH ACCOUNT_LINE IN ACCOUNT_LINES %] >+ [% IF ACCOUNT_LINE.amountoutstanding > 0 %] >+ [% HAVE_OUTSTANDING = 1 %] >+ [% LAST %] >+ [% END %] >+ [% END %] > <div class="span10"> > <div id="useraccount" class="maincontent"> >+ [% IF HAVE_OUTSTANDING %] > <h3>Fines and charges</h3> > > [% IF ( ACCOUNT_LINES ) %] >+ [% IF Koha.Preference('OpacPayment') %] >+ <form method="POST" action="/cgi-bin/koha/opac-pay-[% Koha.Preference('OpacPaymentProvider') %].pl"> >+ <input type="hidden" name="action" value="checkout"/> >+ [% END %] > <table class="table table-bordered table-striped"> > <thead> > <tr> >@@ -36,18 +48,93 @@ > <th>Description</th> > <th>Fine amount</th> > <th>Amount outstanding</th> >+ [% IF Koha.Preference('OpacPayment') %] >+ <th>Pay</th> >+ [% END %] > </tr> > </thead> > > <tfoot> > <tr> >+ [% IF Koha.Preference('OpacPayment') %] >+ <th class="sum" colspan="4">Total due</th> >+ [% ELSE %] > <th class="sum" colspan="3">Total due</th> >+ [% END %] > <td class="sum">[% total %]</td> > </tr> >+ [% IF Koha.Preference('OpacPayment') %] >+ <tr> >+ <th class="sum" colspan="4">Total to pay</th> >+ <td class="sum" id="topay">0</td> >+ </tr> >+ [% END %] > </tfoot> > > <tbody> > [% FOREACH ACCOUNT_LINE IN ACCOUNT_LINES %] >+ [% IF ACCOUNT_LINE.amountoutstanding > 0 %] >+ [% IF ( ACCOUNT_LINE.odd ) %]<tr class="highlight">[% ELSE %]<tr>[% END %] >+ <td>[% ACCOUNT_LINE.date | $KohaDates %]</td> >+ <td> >+ [% 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 %] >+ </td> >+ [% IF ( ACCOUNT_LINE.amountcredit ) %]<td class="credit">[% ELSE %]<td class="debit">[% END %][% ACCOUNT_LINE.amount %]</td> >+ <td class="debit">[% ACCOUNT_LINE.amountoutstanding %]</td> >+ [% IF Koha.Preference('OpacPayment') %] >+ <td class="debit"><input type="checkbox" name="accountlines_id" value="[% ACCOUNT_LINE.accountlines_id %]" data-sum="[% ACCOUNT_LINE.amountoutstanding %]"/></td> >+ [% END %] >+ </tr> >+ [% END %] >+ [% END %] >+ </tbody> >+ </table> >+ [% IF Koha.Preference('OpacPayment') %] >+ <div style="text-align: right;"> >+ <a href="#" id="CheckAll">Select all</a> >+ <a href="#" id="CheckNone">Clear all</a> >+ <input type="submit" class="btn btn-primary" value="Checkout"/> >+ </div> >+ </form> >+ [% END %] >+ [% END %] >+ >+ <h3>History</h3> >+ >+ <table class="table table-bordered table-striped"> >+ <thead> >+ <tr> >+ <th>Date</th> >+ <th>Description</th> >+ <th>Fine amount</th> >+ </tr> >+ </thead> >+ >+ <tbody> >+ [% FOREACH ACCOUNT_LINE IN ACCOUNT_LINES %] >+ [% IF ACCOUNT_LINE.amountoutstandingcredit %] > [% IF ( ACCOUNT_LINE.odd ) %]<tr class="highlight">[% ELSE %]<tr>[% END %] > <td>[% ACCOUNT_LINE.date | $KohaDates %]</td> > <td> >@@ -76,9 +163,9 @@ > [% IF ACCOUNT_LINE.title %]([% ACCOUNT_LINE.title %])[% END %] > </td> > [% IF ( ACCOUNT_LINE.amountcredit ) %]<td class="credit">[% ELSE %]<td class="debit">[% END %][% ACCOUNT_LINE.amount %]</td> >- [% IF ( ACCOUNT_LINE.amountoutstandingcredit ) %]<td class="credit">[% ELSE %]<td class="debit">[% END %][% ACCOUNT_LINE.amountoutstanding %]</td> > </tr> > [% END %] >+ [% END %] > </tbody> > > </table> >@@ -92,4 +179,27 @@ > </div> <!-- / .main --> > > [% INCLUDE 'opac-bottom.inc' %] >-[% BLOCK jsinclude %][% END %] >+[% BLOCK jsinclude %] >+<script type="text/javascript"> >+//<![CDATA[ >+$(document).ready(function(){ >+ $('input[name="accountlines_id"]').change(function() { >+ var total=0; >+ $('input[name="accountlines_id"]:checked').each(function(){ >+ total += $(this).data('sum'); >+ }); >+ $('#topay').text(total); >+ }); >+ >+ $('#CheckAll').click(function() { >+ $('input[name="accountlines_id"]').attr('checked', true); >+ return false; >+ }); >+ $('#CheckNone').click(function() { >+ $('input[name="accountlines_id"]').attr('checked', false); >+ return false; >+ }); >+}); >+//]]> >+</script> >+[% 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' %] >+<title>[% IF ( LibraryNameTitle ) %][% LibraryNameTitle %][% ELSE %]Koha online[% END %] catalog › Pay fines and charges</title> >+[% INCLUDE 'doc-head-close.inc' %] >+[% BLOCK cssinclude %][% END %] >+</head> >+<body id="opac-account" class="scrollto"> >+[% INCLUDE 'bodytag.inc' bodyid='opac-account' bodyclass='scrollto' %] >+[% INCLUDE 'masthead.inc' %] >+ >+<div class="main"> >+ <ul class="breadcrumb"> >+ <li><a href="/cgi-bin/koha/opac-main.pl">Home</a> <span class="divider">›</span></li> >+ <li><a href="/cgi-bin/koha/opac-user.pl">[% BORROWER_INFO.firstname %] [% BORROWER_INFO.surname %]</a> <span class="divider">›</span></li> >+ <li><a href="/cgi-bin/koha/opac-account.pl">Your fines</a> <span class="divider">›</span></li> >+ <li>Pay fines and charges</li> >+ </ul> >+ >+ <div class="container-fluid"> >+ <div class="row-fluid"> >+ <div class="span2"> >+ <div id="navigation"> >+ [% INCLUDE 'navigation.inc' IsPatronPage=1 %] >+ </div> >+ </div> >+ <div class="span10"> >+ <div id="useraccount" class="maincontent"> >+ [% >+ SET SUBUNIT = Koha.Preference('OpacPaymentCurrencySubunit') || 1; >+ SET PRECISION = "%." _ SUBUNIT.replace('^[^\.]*\.','').length _ "f"; >+ %] >+ <h3>Pay fines and charges</h3> >+ [% IF state == 'checkout' %] >+ <form method="POST" action="https://payment.architrade.com/paymentweb/start.action"> >+ [% IF Koha.Preference('OpacPaymentTest') %] >+ <input type="hidden" name="test" value="1"/> >+ [% END %] >+ <input type="hidden" name="accepturl" value="[% accepturl%]"/> >+ <input type="hidden" name="cancelurl" value="[% cancelurl%]"/> >+ <input type="hidden" name="callbackurl" value="[% callbackurl%]"/> >+ <input type="hidden" name="lang" value="[% lang %]"/> >+ <input type="hidden" name="amount" value="[% amount %]"/> >+ <input type="hidden" name="currency" value="[% currency %]"/> >+ <input type="hidden" name="merchant" value="[% merchant %]"/> >+ <input type="hidden" name="orderid" value="[% order.orderid %]"/> >+ <input type="hidden" name="md5key" value="[% md5key %]"/> >+ <input type="hidden" name="HTTP_COOKIE" value="[% HTTP_COOKIE %]"/> >+ [% END %] >+ <div> >+ [% IF state != 'success' %] >+ <div class="span6"> >+ <h4>Summary</h4> >+ <table class="table table-bordered table-striped"> >+ <thead> >+ <tr> >+ <th>Date</th> >+ <th>Description</th> >+ <th>Amount</th> >+ </tr> >+ </thead> >+ >+ <tfoot> >+ <tr> >+ <th class="sum" colspan="2">Total</th> >+ [% IF state == 'success' %] >+ <td class="sum payed">[% order.amount | format(PRECISION) %]</td> >+ [% ELSE %] >+ <td class="sum">[% order.amount | format(PRECISION) %]</td> >+ [% END %] >+ </tr> >+ </tfoot> >+ >+ <tbody> >+ [% FOREACH acctline IN accountlines %] >+ <tr> >+ <td>[% acctline.date | $KohaDates %]</td> >+ <td> >+ [% 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 %] >+ </td> >+ [% IF state == 'success' %] >+ <td class="credit">[% acctline.amountoutstanding | format(PRECISION) %]</td> >+ [% ELSE %] >+ <td class="debit">[% acctline.amountoutstanding | format(PRECISION) %]</td> >+ [% END %] >+ </tr> >+ [% END %] >+ </tbody> >+ </table> >+ [% IF state == 'checkout' %] >+ <div class="pull-right"> >+ <input type="submit" class="btn btn-primary" value="Confirm & pay"/> >+ </div> >+ [% END %] >+ </div> >+ [% END %] >+ [% IF state == 'checkout' %] >+ <div class="span6"> >+ <h4>Billing information</h4> >+ <table> >+ <tbody> >+ <tr> >+ <td>First name</td> >+ <td><input type="text" name="billingFirstName" value="[% BORROWER_INFO.firstname %]"/></td> >+ </tr> >+ <tr> >+ <td>Surname</td> >+ <td><input type="text" name="billingLastName" value="[% BORROWER_INFO.surname %]"/></td> >+ </tr> >+ <tr> >+ <td>Address</td> >+ <td><input type="text" name="billingAddress" value="[% BORROWER_INFO.address %] [% BORROWER_INFO.streetnumber %]"/></td> >+ </tr> >+ <tr> >+ <td>Address 2</td> >+ <td><input type="text" name="billingAddress2" value="[% BORROWER_INFO.address2 %]"/></td> >+ </tr> >+ <tr> >+ <td>Zip code</td> >+ <td><input type="text" name="billingPostalCode" value="[% BORROWER_INFO.zipcode %]"/></td> >+ </tr> >+ <tr> >+ <td>City</td> >+ <td><input type="text" name="billingPostalPlace" value="[% BORROWER_INFO.city%]"/></td> >+ </tr> >+ <tr> >+ <td>Cardholder name</td> >+ <td><input type="text" name="cardholder_name" value="[% BORROWER_INFO.firstname %] [% BORROWER_INFO.surname %]"/></td> >+ </tr> >+ <tr> >+ <td>Cardholder address</td> >+ <td><input type="text" name="cardholder_address1" value="[% BORROWER_INFO.address %] [% BORROWER_INFO.streetnumber %]"/></td> >+ </tr> >+ <tr> >+ <td>Zip code</td> >+ <td><input type="text" name="cardholder_zipcode" value="[% BORROWER_INFO.zipcode %]"/></td> >+ </tr> >+ <tr> >+ <td>Email</td> >+ <td><input type="text" name="email" value="[% BORROWER_INFO.email%]"/></td> >+ </tr> >+ </tbody> >+ </table> >+ </div> >+ [% ELSIF state == 'success' %] >+ <div class="alert-success"> >+ <h4>Payment successful</h4> >+ <p> >+ Thank you! >+ </p> >+ </div> >+ [% ELSIF state == 'error' %] >+ <div class="span6 alert"> >+ <h4>Payment failed</h4> >+ <p><b>Orderd ID: [% order.orderid %]</b></p> >+ <p> >+ [% IF error == 'authkey' %] >+ Invalid authentication key recived. Some data was corrupted >+ during transaction. Please contact library staff. >+ [% END %] >+ </p> >+ </div> >+ [% ELSIF state == 'canceled' %] >+ <div class="span6 alert-info"> >+ <h4>Payment canceled</h4> >+ <p><b>Orderd ID: [% order.orderid %]</b></p> >+ <p> >+ Your payment was canceled. >+ </p> >+ </div> >+ [% END %] >+ </div> >+ [% IF state == 'checkout' %] >+ </form> >+ [% END %] >+ </div> <!-- / #useraccount --> >+ </div> <!-- / .span10 --> >+ </div> <!-- / .row-fluid --> >+ </div> <!-- / .container-fluid --> >+</div> <!-- / .main --> >+ >+[% INCLUDE 'opac-bottom.inc' %] >+[% BLOCK jsinclude %] >+<script type="text/javascript"> >+//<![CDATA[ >+$(document).ready(function(){ >+}); >+//]]> >+</script> >+[% 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 <http://www.gnu.org/licenses>. >+ >+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
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
|
Splinter Review
Attachments on
bug 15335
: 45617 |
45618