View | Details | Raw Unified | Return to bug 15335
Collapse All | Expand All

(-)a/C4/Payment.pm (+244 lines)
Line 0 Link Here
1
package C4::Payment;
2
3
# This file is part of Koha.
4
#
5
# Koha is free software; you can redistribute it and/or modify it
6
# under the terms of the GNU General Public License as published by
7
# the Free Software Foundation; either version 3 of the License, or
8
# (at your option) any later version.
9
#
10
# Koha is distributed in the hope that it will be useful, but
11
# WITHOUT ANY WARRANTY; without even the implied warranty of
12
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
# GNU General Public License for more details.
14
#
15
# You should have received a copy of the GNU General Public License
16
# along with Koha; if not, see <http://www.gnu.org/licenses>.
17
18
use Modern::Perl;
19
use C4::Context;
20
use C4::Members;
21
use C4::Log qw(logaction);
22
23
use Digest::MD5 qw ( md5_hex );
24
use Carp;
25
use Data::Dumper qw(Dumper);
26
27
use vars qw($VERSION @ISA @EXPORT);
28
29
BEGIN {
30
    # set the version for version checking
31
    $VERSION = 3.07.00.049;
32
    require Exporter;
33
    @ISA    = qw(Exporter);
34
    @EXPORT = qw(
35
      &AddOrder
36
      &DelOrder
37
      &ModOrder
38
      &GetOrder
39
      &AddToOrder
40
      &GetOrderDetails
41
      &GetOrderHash
42
    );
43
}
44
45
=head1 NAME
46
47
C4::Payment - Functions for dealing with online payments
48
49
=head1 SYNOPSIS
50
51
use C4::Payment;
52
53
=head1 DESCRIPTION
54
55
The functions in this module deal with the orders and online payments.
56
They allow to add, delete and modify orders.
57
58
=head1 FUNCTIONS
59
60
=head2 AddOrder
61
62
  &AddOrder();
63
64
=cut
65
66
sub AddOrder {
67
    my $args = shift;
68
    croak "No borrowernumber provided" unless $args && $args->{'borrowernumber'};
69
    my $dbh  = C4::Context->dbh;
70
71
    my $query =
72
        'INSERT INTO paymentorders ' . '('
73
      . join( ',', keys %$args ) . ')'
74
      . 'VALUES ('
75
      . join( ',', map { '?' } keys %$args ) . ')';
76
77
    my $sth = $dbh->prepare($query);
78
    $sth->execute( values %$args );
79
    $sth->finish();
80
    return $dbh->{mysql_insertid};
81
}
82
83
=head2 AddToOrder
84
85
  &AddToOrder($orderid, $accountlines_id);
86
87
=cut
88
89
sub AddToOrder {
90
    my ($orderid, $accountlines_id) = @_;
91
    croak "No accountlines_id provided" unless $accountlines_id;
92
    croak "No orderid provided" unless $orderid;
93
    my $dbh = C4::Context->dbh;
94
95
    my $sth = $dbh->prepare( '
96
		SELECT * FROM accountlines
97
        WHERE
98
	    accountlines_id=?
99
        ' );
100
    $sth->execute($accountlines_id);
101
    my $accountline = $sth->fetchrow_hashref;
102
    croak "No such accountline: $accountlines_id" unless $accountline;
103
104
    my $amount   = $accountline->{'amountoutstanding'};
105
    my $currency = C4::Context->preference('OpacPaymentCurrency');
106
107
    $sth = $dbh->prepare( '
108
        INSERT INTO paymentorderdetails
109
        (orderid, accountlines_id, amount, currency)
110
        VALUES (?, ?, ?, ?)
111
        ' );
112
    $sth->execute( $orderid, $accountlines_id, $amount, $currency );
113
    $sth->finish();
114
}
115
116
=head2 DelOrder
117
118
  &DelOrder($orderid);
119
120
=cut
121
122
sub DelOrder {
123
    my $orderid = shift;
124
    croak "No orderid provided" unless $orderid;
125
    my $dbh = C4::Context->dbh;
126
127
    my $sth = $dbh->prepare( '
128
        DELETE FROM paymentorders
129
        WHERE
130
        orderid=?
131
        ' );
132
    $sth->execute($orderid);
133
    $sth->finish();
134
}
135
136
=head2 GetOrder
137
138
  &GetOrder($orderid);
139
140
=cut
141
142
sub GetOrder {
143
    my $orderid = shift;
144
    croak "No orderid provided" unless $orderid;
145
    my $dbh = C4::Context->dbh;
146
147
    my $sth = $dbh->prepare( '
148
        SELECT * FROM paymentorders
149
        WHERE
150
        orderid=?
151
        ' );
152
    $sth->execute($orderid);
153
    return $sth->fetchrow_hashref;
154
}
155
156
=head2 ModOrder
157
158
  &ModOrder($order);
159
160
=cut
161
162
sub ModOrder {
163
    my $order = shift;
164
    croak "Incomplete order provided" unless $order->{'orderid'};
165
    my $dbh = C4::Context->dbh;
166
167
    my $query = 'UPDATE paymentorders';
168
    $query .= ' SET ' . join( ' = ?, ', keys %$order ) . ' = ?';
169
    $query .= ' WHERE orderid = ?';
170
    my $sth = $dbh->prepare($query);
171
    $sth->execute( values %$order, $order->{'orderid'} );
172
    $sth->finish();
173
}
174
175
=head2 GetOrderDetails
176
177
  &GetOrderDetails($orderid);
178
179
=cut
180
181
sub GetOrderDetails {
182
    my $orderid = shift;
183
    croak "No orderid provided" unless $orderid;
184
    my $dbh = C4::Context->dbh;
185
186
    my $sth = $dbh->prepare('
187
        SELECT paymentorderdetails.*, accountlines.* FROM paymentorderdetails
188
        LEFT JOIN accountlines ON paymentorderdetails.accountlines_id=accountlines.accountlines_id
189
        WHERE
190
        orderid=?
191
        ');
192
    $sth->execute($orderid);
193
    return $sth->fetchall_arrayref( {} );
194
}
195
196
=head2 GetOrderHash_DIBS
197
198
  &GetOrderHash_DIBS($orderid);
199
200
=cut
201
202
sub GetOrderHash {
203
    my $orderid = shift;
204
    croak "No orderid provided" unless $orderid;
205
206
    my $order = GetOrder($orderid);
207
    croak "No such order: $orderid" unless $order;
208
209
    my $provider   = C4::Context->preference('OpacPaymentProvider');
210
211
    if ( $provider eq 'dibs' ) {
212
        my $currency   = C4::Context->preference('OpacPaymentCurrency');
213
        my $merchantid = C4::Context->preference('OpacPaymentMerchantID');
214
        my $k1         = C4::Context->preference('OpacPaymentK1');
215
        my $k2         = C4::Context->preference('OpacPaymentK2');
216
217
        my $data =
218
            "merchant="
219
          . $merchantid
220
          . "&orderid="
221
          . $orderid
222
          . "&currency="
223
          . $currency
224
          . "&amount="
225
          . ( $order->{'amount'} /
226
              C4::Context->preference('OpacPaymentCurrencySubunit') );
227
228
        return md5_hex( $k2 . md5_hex( $k1 . $data ) );
229
    } else {
230
        croak "GetOrderHash for provider \"$provider\" not implemented";
231
    }
232
}
233
234
END { }    # module clean-up code here (global destructor)
235
236
1;
237
__END__
238
239
=head1 AUTHOR
240
241
Martin Stenberg <martin@koha.xinxidi.net>
242
243
=cut
244
(-)a/installer/data/mysql/atomicupdate/bug_15335-payment-sysprefs.sql (+8 lines)
Line 0 Link Here
1
INSERT INTO systempreferences (variable,value,options,explanation,type) VALUES('OpacPayment','0',NULL,'Online payments from OPAC','YesNo');
2
INSERT INTO systempreferences (variable,value,options,explanation,type) VALUES('OpacPaymentTest','1',NULL,'Online payments test','YesNo');
3
INSERT INTO systempreferences (variable,value,options,explanation,type) VALUES('OpacPaymentProvider','dibs','dibs','Provider','Choice');
4
INSERT INTO systempreferences (variable,value,options,explanation,type) VALUES ('OpacPaymentMerchantID','',NULL,'Merchant ID','Free');
5
INSERT INTO systempreferences (variable,value,options,explanation,type) VALUES ('OpacPaymentK1','',NULL,'Authentication key 1','Free');
6
INSERT INTO systempreferences (variable,value,options,explanation,type) VALUES ('OpacPaymentK2','',NULL,'Authentication key 2','Free');
7
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');
8
INSERT INTO systempreferences (variable,value,options,explanation,type) VALUES ('OpacPaymentCurrencySubunit','0.001',NULL,'Smallest subunit of currency','Free');
(-)a/installer/data/mysql/atomicupdate/bug_15335-payment.sql (+23 lines)
Line 0 Link Here
1
DROP TABLE IF EXISTS `paymentorders`;
2
DROP TABLE IF EXISTS `paymentorderdetails`;
3
4
CREATE TABLE `paymentorders` (
5
    `orderid` INT(11) NOT NULL auto_increment,
6
    `orderdate` TIMESTAMP DEFAULT NOW(),
7
    `modificationdate` TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
8
    `status` ENUM('pending', 'payed','canceled') DEFAULT 'pending',
9
    `amount` DOUBLE DEFAULT 0,
10
    `currency` SMALLINT DEFAULT NULL,
11
    `borrowernumber` INT(11) NOT NULL,
12
    PRIMARY KEY (`orderid`),
13
    CONSTRAINT `paymentorders_ibfk_1` FOREIGN KEY (`borrowernumber`) REFERENCES `borrowers` (`borrowernumber`)
14
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
15
16
CREATE TABLE `paymentorderdetails` (
17
    `orderid` INT(11) NOT NULL,
18
    `accountlines_id` INT(11) NOT NULL,
19
    `amount` DOUBLE DEFAULT 0,
20
    `currency` SMALLINT DEFAULT NULL,
21
    CONSTRAINT `paymentorderdetails_ibfk_1` FOREIGN KEY (`accountlines_id`) REFERENCES `accountlines` (`accountlines_id`)
22
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
23
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/opac.pref (+53 lines)
Lines 705-707 OPAC: Link Here
705
                subtype: Subtypes
705
                subtype: Subtypes
706
                sorting: Sorting
706
                sorting: Sorting
707
                location: Location and availability
707
                location: Location and availability
708
    Payment:
709
        -
710
            - pref: OpacPayment
711
              choices:
712
                  yes: Enable
713
                  no: Disable
714
            - "Online payments of fines and charges from OPAC. Requires
715
              OPACBaseURL to be set."
716
        -
717
        -
718
            - pref: OpacPaymentTest
719
              choices:
720
                  yes: Do
721
                  no: Don't
722
            - "run online payments in test mode (no real transactions will
723
              occur)"
724
        -
725
            - Provider
726
            - pref: OpacPaymentProvider
727
              choices:
728
                dibs: DIBS
729
        -
730
            - Merchant ID
731
            - pref: OpacPaymentMerchantID
732
        -
733
            - Authentication key 1
734
            - pref: OpacPaymentK1
735
        -
736
            - Authentication key 2
737
            - pref: OpacPaymentK2
738
        -
739
            - Currency
740
            - pref: OpacPaymentCurrency
741
              choices:
742
                208: Danish Kroner (DKK)
743
                978: Euro (EUR)
744
                840: US Dollar $ (USD)
745
                826: English Pound £ (GBP)
746
                752: Swedish Kroner (SEK)
747
                036: Australian Dollar (AUD)
748
                124: Canadian Dollar (CAD)
749
                352: Icelandic Kroner (ISK)
750
                392: Japanese Yen (JPY)
751
                554: New Zealand Dollar (NZD)
752
                578: Norwegian Kroner (NOK)
753
                756: Swiss Franc (CHF)
754
                949: Turkish Lire (TRY)
755
        -
756
            - Smallest subunit of currency
757
            - pref: OpacPaymentCurrencySubunit
758
              default: 0.001
759
              class: currency
760
            - (e.g. 1 cent = 0.001)
(-)a/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-account.tt (-2 / +112 lines)
Lines 24-34 Link Here
24
                    [% INCLUDE 'navigation.inc' IsPatronPage=1 %]
24
                    [% INCLUDE 'navigation.inc' IsPatronPage=1 %]
25
                </div>
25
                </div>
26
            </div>
26
            </div>
27
            [% SET HAVE_OUTSTANDING = 0 %]
28
            [% FOREACH ACCOUNT_LINE IN ACCOUNT_LINES %]
29
                [% IF ACCOUNT_LINE.amountoutstanding > 0 %]
30
                    [% HAVE_OUTSTANDING = 1 %]
31
                    [% LAST %]
32
                [% END %]
33
            [% END %]
27
            <div class="span10">
34
            <div class="span10">
28
                <div id="useraccount" class="maincontent">
35
                <div id="useraccount" class="maincontent">
36
                    [% IF HAVE_OUTSTANDING %]
29
                    <h3>Fines and charges</h3>
37
                    <h3>Fines and charges</h3>
30
38
31
                    [% IF ( ACCOUNT_LINES ) %]
39
                    [% IF ( ACCOUNT_LINES ) %]
40
                    [% IF Koha.Preference('OpacPayment') %]
41
                    <form method="POST" action="/cgi-bin/koha/opac-pay-[% Koha.Preference('OpacPaymentProvider') %].pl">
42
                        <input type="hidden" name="action" value="checkout"/>
43
                    [% END %]
32
                        <table class="table table-bordered table-striped">
44
                        <table class="table table-bordered table-striped">
33
                            <thead>
45
                            <thead>
34
                                <tr>
46
                                <tr>
Lines 36-53 Link Here
36
                                    <th>Description</th>
48
                                    <th>Description</th>
37
                                    <th>Fine amount</th>
49
                                    <th>Fine amount</th>
38
                                    <th>Amount outstanding</th>
50
                                    <th>Amount outstanding</th>
51
                                    [% IF Koha.Preference('OpacPayment') %]
52
                                    <th>Pay</th>
53
                                    [% END %]
39
                                </tr>
54
                                </tr>
40
                            </thead>
55
                            </thead>
41
56
42
                            <tfoot>
57
                            <tfoot>
43
                            <tr>
58
                            <tr>
59
                                [% IF Koha.Preference('OpacPayment') %]
60
                                <th class="sum" colspan="4">Total due</th>
61
                                [% ELSE %]
44
                                <th class="sum" colspan="3">Total due</th>
62
                                <th class="sum" colspan="3">Total due</th>
63
                                [% END %]
45
                                <td class="sum">[% total %]</td>
64
                                <td class="sum">[% total %]</td>
46
                            </tr>
65
                            </tr>
66
                            [% IF Koha.Preference('OpacPayment') %]
67
                            <tr>
68
                                <th class="sum" colspan="4">Total to pay</th>
69
                                <td class="sum" id="topay">0</td>
70
                            </tr>
71
                            [% END %]
47
                            </tfoot>
72
                            </tfoot>
48
73
49
                            <tbody>
74
                            <tbody>
50
                                [% FOREACH ACCOUNT_LINE IN ACCOUNT_LINES %]
75
                                [% FOREACH ACCOUNT_LINE IN ACCOUNT_LINES %]
76
                                [% IF ACCOUNT_LINE.amountoutstanding > 0 %]
77
                                    [% IF ( ACCOUNT_LINE.odd ) %]<tr class="highlight">[% ELSE %]<tr>[% END %]
78
                                        <td>[% ACCOUNT_LINE.date | $KohaDates %]</td>
79
                                        <td>
80
                                            [% SWITCH ACCOUNT_LINE.accounttype %]
81
                                            [% CASE 'Pay' %]Payment, thanks
82
                                            [% CASE 'Pay00' %]Payment, thanks (cash via SIP2)
83
                                            [% CASE 'Pay01' %]Payment, thanks (VISA via SIP2)
84
                                            [% CASE 'Pay02' %]Payment, thanks (credit card via SIP2)
85
                                            [% CASE 'N' %]New card
86
                                            [% CASE 'F' %]Fine
87
                                            [% CASE 'A' %]Account management fee
88
                                            [% CASE 'M' %]Sundry
89
                                            [% CASE 'L' %]Lost item
90
                                            [% CASE 'W' %]Writeoff
91
                                            [% CASE 'FU' %]Accruing fine
92
                                            [% CASE 'Rent' %]Rental fee
93
                                            [% CASE 'FOR' %]Forgiven
94
                                            [% CASE 'LR' %]Lost item fee refund
95
                                            [% CASE 'PAY' %]Payment
96
                                            [% CASE 'WO' %]Writeoff
97
                                            [% CASE 'C' %]Credit
98
                                            [% CASE 'CR' %]Credit
99
                                            [% CASE %][% ACCOUNT_LINE.accounttype %]
100
                                          [%- END -%]
101
                                          [%- IF ACCOUNT_LINE.description %], [% ACCOUNT_LINE.description %][% END %]
102
                                          [% IF ACCOUNT_LINE.title %]([% ACCOUNT_LINE.title %])[% END %]
103
                                        </td>
104
                                        [% IF ( ACCOUNT_LINE.amountcredit ) %]<td class="credit">[% ELSE %]<td class="debit">[% END %][% ACCOUNT_LINE.amount %]</td>
105
                                        <td class="debit">[% ACCOUNT_LINE.amountoutstanding %]</td>
106
                                        [% IF Koha.Preference('OpacPayment') %]
107
                                        <td class="debit"><input type="checkbox" name="accountlines_id" value="[% ACCOUNT_LINE.accountlines_id %]" data-sum="[% ACCOUNT_LINE.amountoutstanding %]"/></td>
108
                                        [% END %]
109
                                    </tr>
110
                                [% END %]
111
                                [% END %]
112
                            </tbody>
113
                        </table>
114
                    [% IF Koha.Preference('OpacPayment') %]
115
                        <div style="text-align: right;">
116
                            <a href="#" id="CheckAll">Select all</a>
117
                            <a href="#" id="CheckNone">Clear all</a>
118
                            <input type="submit" class="btn btn-primary" value="Checkout"/>
119
                        </div>
120
                    </form>
121
                    [% END %]
122
                    [% END %]
123
124
                    <h3>History</h3>
125
126
                        <table class="table table-bordered table-striped">
127
                            <thead>
128
                                <tr>
129
                                    <th>Date</th>
130
                                    <th>Description</th>
131
                                    <th>Fine amount</th>
132
                                </tr>
133
                            </thead>
134
135
                            <tbody>
136
                                [% FOREACH ACCOUNT_LINE IN ACCOUNT_LINES %]
137
                                [% IF ACCOUNT_LINE.amountoutstandingcredit %]
51
                                    [% IF ( ACCOUNT_LINE.odd ) %]<tr class="highlight">[% ELSE %]<tr>[% END %]
138
                                    [% IF ( ACCOUNT_LINE.odd ) %]<tr class="highlight">[% ELSE %]<tr>[% END %]
52
                                        <td>[% ACCOUNT_LINE.date | $KohaDates %]</td>
139
                                        <td>[% ACCOUNT_LINE.date | $KohaDates %]</td>
53
                                        <td>
140
                                        <td>
Lines 76-84 Link Here
76
                                          [% IF ACCOUNT_LINE.title %]([% ACCOUNT_LINE.title %])[% END %]
163
                                          [% IF ACCOUNT_LINE.title %]([% ACCOUNT_LINE.title %])[% END %]
77
                                        </td>
164
                                        </td>
78
                                        [% IF ( ACCOUNT_LINE.amountcredit ) %]<td class="credit">[% ELSE %]<td class="debit">[% END %][% ACCOUNT_LINE.amount %]</td>
165
                                        [% IF ( ACCOUNT_LINE.amountcredit ) %]<td class="credit">[% ELSE %]<td class="debit">[% END %][% ACCOUNT_LINE.amount %]</td>
79
                                        [% IF ( ACCOUNT_LINE.amountoutstandingcredit ) %]<td class="credit">[% ELSE %]<td class="debit">[% END %][% ACCOUNT_LINE.amountoutstanding %]</td>
80
                                    </tr>
166
                                    </tr>
81
                                [% END %]
167
                                [% END %]
168
                                [% END %]
82
                            </tbody>
169
                            </tbody>
83
170
84
                        </table>
171
                        </table>
Lines 92-95 Link Here
92
</div> <!-- / .main -->
179
</div> <!-- / .main -->
93
180
94
[% INCLUDE 'opac-bottom.inc' %]
181
[% INCLUDE 'opac-bottom.inc' %]
95
[% BLOCK jsinclude %][% END %]
182
[% BLOCK jsinclude %]
183
<script type="text/javascript">
184
//<![CDATA[
185
$(document).ready(function(){
186
    $('input[name="accountlines_id"]').change(function() {
187
        var total=0;
188
        $('input[name="accountlines_id"]:checked').each(function(){
189
            total += $(this).data('sum');
190
        });
191
        $('#topay').text(total);
192
    });
193
194
    $('#CheckAll').click(function() {
195
        $('input[name="accountlines_id"]').attr('checked', true);
196
        return false;
197
    });
198
    $('#CheckNone').click(function() {
199
        $('input[name="accountlines_id"]').attr('checked', false);
200
        return false;
201
    });
202
});
203
//]]>
204
</script>
205
[% END %]
(-)a/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-pay-dibs.tt (+213 lines)
Line 0 Link Here
1
[% USE Koha %]
2
[% USE KohaDates %]
3
4
[% INCLUDE 'doc-head-open.inc' %]
5
<title>[% IF ( LibraryNameTitle ) %][% LibraryNameTitle %][% ELSE %]Koha online[% END %] catalog &rsaquo; Pay fines and charges</title>
6
[% INCLUDE 'doc-head-close.inc' %]
7
[% BLOCK cssinclude %][% END %]
8
</head>
9
<body id="opac-account" class="scrollto">
10
[% INCLUDE 'bodytag.inc' bodyid='opac-account' bodyclass='scrollto' %]
11
[% INCLUDE 'masthead.inc' %]
12
13
<div class="main">
14
    <ul class="breadcrumb">
15
        <li><a href="/cgi-bin/koha/opac-main.pl">Home</a> <span class="divider">&rsaquo;</span></li>
16
        <li><a href="/cgi-bin/koha/opac-user.pl">[% BORROWER_INFO.firstname %] [% BORROWER_INFO.surname %]</a> <span class="divider">&rsaquo;</span></li>
17
        <li><a href="/cgi-bin/koha/opac-account.pl">Your fines</a> <span class="divider">&rsaquo;</span></li>
18
        <li>Pay fines and charges</li>
19
    </ul>
20
21
    <div class="container-fluid">
22
        <div class="row-fluid">
23
            <div class="span2">
24
                <div id="navigation">
25
                    [% INCLUDE 'navigation.inc' IsPatronPage=1 %]
26
                </div>
27
            </div>
28
            <div class="span10">
29
                <div id="useraccount" class="maincontent">
30
                    [%
31
                        SET SUBUNIT = Koha.Preference('OpacPaymentCurrencySubunit') || 1;
32
                        SET PRECISION = "%." _ SUBUNIT.replace('^[^\.]*\.','').length _ "f";
33
                    %]
34
                    <h3>Pay fines and charges</h3>
35
                    [% IF state == 'checkout' %]
36
                    <form method="POST" action="https://payment.architrade.com/paymentweb/start.action">
37
                        [% IF Koha.Preference('OpacPaymentTest') %]
38
                        <input type="hidden" name="test" value="1"/>
39
                        [% END %]
40
                        <input type="hidden" name="accepturl" value="[% accepturl%]"/>
41
                        <input type="hidden" name="cancelurl" value="[% cancelurl%]"/>
42
                        <input type="hidden" name="callbackurl" value="[% callbackurl%]"/>
43
                        <input type="hidden" name="lang" value="[% lang %]"/>
44
                        <input type="hidden" name="amount" value="[% amount %]"/>
45
                        <input type="hidden" name="currency" value="[% currency %]"/>
46
                        <input type="hidden" name="merchant" value="[% merchant %]"/>
47
                        <input type="hidden" name="orderid" value="[% order.orderid %]"/>
48
                        <input type="hidden" name="md5key" value="[% md5key %]"/>
49
                        <input type="hidden" name="HTTP_COOKIE" value="[% HTTP_COOKIE %]"/>
50
                    [% END %]
51
                    <div>
52
                        [% IF state != 'success' %]
53
                        <div class="span6">
54
                            <h4>Summary</h4>
55
                            <table class="table table-bordered table-striped">
56
                                <thead>
57
                                    <tr>
58
                                        <th>Date</th>
59
                                        <th>Description</th>
60
                                        <th>Amount</th>
61
                                    </tr>
62
                                </thead>
63
64
                                <tfoot>
65
                                <tr>
66
                                    <th class="sum" colspan="2">Total</th>
67
                                    [% IF state == 'success' %]
68
                                    <td class="sum payed">[% order.amount | format(PRECISION) %]</td>
69
                                    [% ELSE %]
70
                                    <td class="sum">[% order.amount | format(PRECISION) %]</td>
71
                                    [% END %]
72
                                </tr>
73
                                </tfoot>
74
75
                                <tbody>
76
                                    [% FOREACH acctline IN accountlines %]
77
                                        <tr>
78
                                            <td>[% acctline.date | $KohaDates %]</td>
79
                                            <td>
80
                                                [% SWITCH acctline.accounttype %]
81
                                                [% CASE 'Pay' %]Payment, thanks
82
                                                [% CASE 'Pay00' %]Payment, thanks (cash via SIP2)
83
                                                [% CASE 'Pay01' %]Payment, thanks (VISA via SIP2)
84
                                                [% CASE 'Pay02' %]Payment, thanks (credit card via SIP2)
85
                                                [% CASE 'N' %]New card
86
                                                [% CASE 'F' %]Fine
87
                                                [% CASE 'A' %]Account management fee
88
                                                [% CASE 'M' %]Sundry
89
                                                [% CASE 'L' %]Lost item
90
                                                [% CASE 'W' %]Writeoff
91
                                                [% CASE 'FU' %]Accruing fine
92
                                                [% CASE 'Rent' %]Rental fee
93
                                                [% CASE 'FOR' %]Forgiven
94
                                                [% CASE 'LR' %]Lost item fee refund
95
                                                [% CASE 'PAY' %]Payment
96
                                                [% CASE 'WO' %]Writeoff
97
                                                [% CASE 'C' %]Credit
98
                                                [% CASE 'CR' %]Credit
99
                                                [% CASE %][% acctline.accounttype %]
100
                                              [%- END -%]
101
                                              [%- IF acctline.description %], [% acctline.description %][% END %]
102
                                              [% IF acctline.title %]([% acctline.title %])[% END %]
103
                                            </td>
104
                                            [% IF state == 'success' %]
105
                                                <td class="credit">[% acctline.amountoutstanding | format(PRECISION) %]</td>
106
                                            [% ELSE %]
107
                                                <td class="debit">[% acctline.amountoutstanding | format(PRECISION) %]</td>
108
                                            [% END %]
109
                                        </tr>
110
                                    [% END %]
111
                                </tbody>
112
                            </table>
113
                            [% IF state == 'checkout' %]
114
                            <div class="pull-right">
115
                                <input type="submit" class="btn btn-primary" value="Confirm & pay"/>
116
                            </div>
117
                            [% END %]
118
                        </div>
119
                        [% END %]
120
                        [% IF state == 'checkout' %]
121
                        <div class="span6">
122
                            <h4>Billing information</h4>
123
                            <table>
124
                                <tbody>
125
                                    <tr>
126
                                        <td>First name</td>
127
                                        <td><input type="text" name="billingFirstName" value="[% BORROWER_INFO.firstname %]"/></td>
128
                                    </tr>
129
                                    <tr>
130
                                        <td>Surname</td>
131
                                        <td><input type="text" name="billingLastName" value="[% BORROWER_INFO.surname %]"/></td>
132
                                    </tr>
133
                                    <tr>
134
                                        <td>Address</td>
135
                                        <td><input type="text" name="billingAddress" value="[% BORROWER_INFO.address %] [% BORROWER_INFO.streetnumber %]"/></td>
136
                                    </tr>
137
                                    <tr>
138
                                        <td>Address 2</td>
139
                                        <td><input type="text" name="billingAddress2" value="[% BORROWER_INFO.address2 %]"/></td>
140
                                    </tr>
141
                                    <tr>
142
                                        <td>Zip code</td>
143
                                        <td><input type="text" name="billingPostalCode" value="[% BORROWER_INFO.zipcode %]"/></td>
144
                                    </tr>
145
                                    <tr>
146
                                        <td>City</td>
147
                                        <td><input type="text" name="billingPostalPlace" value="[% BORROWER_INFO.city%]"/></td>
148
                                    </tr>
149
                                    <tr>
150
                                        <td>Cardholder name</td>
151
                                        <td><input type="text" name="cardholder_name" value="[% BORROWER_INFO.firstname %] [% BORROWER_INFO.surname %]"/></td>
152
                                    </tr>
153
                                    <tr>
154
                                        <td>Cardholder address</td>
155
                                        <td><input type="text" name="cardholder_address1" value="[% BORROWER_INFO.address %] [% BORROWER_INFO.streetnumber %]"/></td>
156
                                    </tr>
157
                                    <tr>
158
                                        <td>Zip code</td>
159
                                        <td><input type="text" name="cardholder_zipcode" value="[% BORROWER_INFO.zipcode %]"/></td>
160
                                    </tr>
161
                                    <tr>
162
                                        <td>Email</td>
163
                                        <td><input type="text" name="email" value="[% BORROWER_INFO.email%]"/></td>
164
                                    </tr>
165
                                </tbody>
166
                            </table>
167
                        </div>
168
                        [% ELSIF state == 'success' %]
169
                        <div class="alert-success">
170
                            <h4>Payment successful</h4>
171
                            <p>
172
                            Thank you!
173
                            </p>
174
                        </div>
175
                        [% ELSIF state == 'error' %]
176
                        <div class="span6 alert">
177
                            <h4>Payment failed</h4>
178
                            <p><b>Orderd ID: [% order.orderid %]</b></p>
179
                            <p>
180
                            [% IF error == 'authkey' %]
181
                                Invalid authentication key recived. Some data was corrupted
182
                                during transaction. Please contact library staff.
183
                            [% END %]
184
                            </p>
185
                        </div>
186
                        [% ELSIF state == 'canceled' %]
187
                        <div class="span6 alert-info">
188
                            <h4>Payment canceled</h4>
189
                            <p><b>Orderd ID: [% order.orderid %]</b></p>
190
                            <p>
191
                                Your payment was canceled.
192
                            </p>
193
                        </div>
194
                        [% END %]
195
                    </div>
196
                    [% IF state == 'checkout' %]
197
                    </form>
198
                    [% END %]
199
                </div> <!-- / #useraccount -->
200
            </div> <!-- / .span10 -->
201
        </div> <!-- / .row-fluid -->
202
    </div> <!-- / .container-fluid -->
203
</div> <!-- / .main -->
204
205
[% INCLUDE 'opac-bottom.inc' %]
206
[% BLOCK jsinclude %]
207
<script type="text/javascript">
208
//<![CDATA[
209
$(document).ready(function(){
210
});
211
//]]>
212
</script>
213
[% END %]
(-)a/koha-tmpl/opac-tmpl/bootstrap/less/opac.less (+4 lines)
Lines 709-714 td.sum { Link Here
709
    font-weight: bold;
709
    font-weight: bold;
710
}
710
}
711
711
712
td.sum.payed {
713
    background-color: #CFC;
714
}
715
712
th[scope=row] {
716
th[scope=row] {
713
    background-color: transparent;
717
    background-color: transparent;
714
    text-align : right;
718
    text-align : right;
(-)a/opac/opac-pay-dibs.pl (-1 / +214 lines)
Line 0 Link Here
0
- 
1
#!/usr/bin/perl
2
3
# This file is part of Koha.
4
#
5
# Parts Copyright (C) 2013  Mark Tompsett
6
#
7
# Koha is free software; you can redistribute it and/or modify it
8
# under the terms of the GNU General Public License as published by
9
# the Free Software Foundation; either version 3 of the License, or
10
# (at your option) any later version.
11
#
12
# Koha is distributed in the hope that it will be useful, but
13
# WITHOUT ANY WARRANTY; without even the implied warranty of
14
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
# GNU General Public License for more details.
16
#
17
# You should have received a copy of the GNU General Public License
18
# along with Koha; if not, see <http://www.gnu.org/licenses>.
19
20
use Modern::Perl;
21
use CGI qw ( -utf8 );
22
use LWP::UserAgent;
23
use C4::Members;
24
use C4::Auth;    # get_template_and_user
25
use C4::Output;
26
use C4::Context;
27
use C4::Payment;
28
use C4::Accounts;
29
30
use Digest::MD5 qw ( md5_hex );
31
use DateTime::Format::MySQL;
32
use Carp;
33
34
my $cgi         = new CGI;
35
my $dbh         = C4::Context->dbh;
36
my $script_name = '/cgi-bin/koha/opac-pay-dibs.pl';
37
my $baseurl     = C4::Context->preference('OPACBaseURL')
38
  or croak
39
  'OPACBaseURL not defined. Required for OPAC online payments to work.';
40
my $action      = $cgi->param('action');
41
42
if ( $action eq 'callback' ) {
43
    my $orderid = $cgi->param('orderid');
44
    my $authkey = $cgi->param('authkey');
45
46
    # DIBS-specific authentication check
47
    my $k1      = C4::Context->preference('OpacPaymentK1');
48
    my $k2      = C4::Context->preference('OpacPaymentK2');
49
    my $my_authkey = md5_hex(
50
        $k2
51
          . md5_hex(
52
                $k1
53
              . 'transact='
54
              . $cgi->param('transact')
55
              . '&amount='
56
              . $cgi->param('amount')
57
              . '&currency='
58
              . $cgi->param('currency')
59
          )
60
      );
61
62
    if ( $authkey ne $my_authkey ) {
63
        print $cgi->header(
64
            -type=>'text/plain',
65
            -status=> '403 invalid authentication key'
66
        );
67
        exit;
68
    }
69
70
    # Authentication passed
71
72
    my $order        = GetOrder($orderid);
73
    my $orderdetails = GetOrderDetails($orderid);
74
75
    # make payments for each accountline
76
    for my $od (@$orderdetails) {
77
        makepayment(
78
            $od->{'accountlines_id'},
79
            $od->{'borrowernumber'},
80
            $od->{'accountno'},
81
            $od->{'amount'},
82
            undef, # user
83
            C4::Context->userenv ? C4::Context->userenv->{branch} : undef,
84
            'Online payment by user', # payment note
85
        );
86
    }
87
88
    $order->{'status'} = 'payed';
89
    $order->{'modificationdate'} =
90
      DateTime::Format::MySQL->format_datetime( DateTime->now );
91
    ModOrder($order);
92
93
    print $cgi->header(
94
        -type=>'text/plain',
95
        -status=> '200'
96
    );
97
    exit;
98
}
99
100
my ( $template, $borrowernumber, $cookie ) = get_template_and_user(
101
    {
102
        template_name   => 'opac-pay-dibs.tt',
103
        type            => 'opac',
104
        query           => $cgi,
105
        authnotrequired => ( C4::Context->preference('OpacPublic') ? 1 : 0 ),
106
    }
107
);
108
109
# get borrower information ....
110
my $borr = GetMemberDetails($borrowernumber);
111
112
if ( $action eq 'checkout' ) {
113
    #get account details
114
    my @acctids = $cgi->multi_param('accountlines_id');
115
    my ( $total, $accts, $numaccts ) = GetMemberAccountRecords($borrowernumber);
116
    my %accts_h = map { $_->{'accountlines_id'} => $_ } @$accts;
117
    my @acctlines = map { $accts_h{$_} } @acctids;
118
119
    my $subunit = C4::Context->preference('OpacPaymentCurrencySubunit') || 1;
120
    my $amount = 0;
121
    $amount += $_->{'amountoutstanding'} for @acctlines;
122
123
    # Generate a new order id and add to db
124
    my $orderid = AddOrder(
125
        {
126
            borrowernumber => $borrowernumber,
127
            amount   => $amount,
128
            currency => C4::Context->preference('OpacPaymentCurrency')
129
        }
130
    );
131
    AddToOrder($orderid, $_->{'accountlines_id'} ) for @acctlines;
132
133
    $template->param(
134
        BORROWER_INFO => $borr,
135
        HTTP_COOKIE   => $cookie,
136
        accountlines  => \@acctlines,
137
        accepturl     => $baseurl . $script_name . '?action=accept',
138
        cancelurl     => $baseurl . $script_name . '?action=cancel',
139
        callbackurl   => $baseurl . $script_name . '?action=callback',
140
        lang          => C4::Languages::getlanguage($cgi) || 'en',
141
        amount        => $amount / $subunit,
142
        total         => $amount,
143
        currency      => C4::Context->preference('OpacPaymentCurrency'),
144
        merchant      => C4::Context->preference('OpacPaymentMerchantID'),
145
        order         => GetOrder($orderid),
146
        md5key        => GetOrderHash($orderid),
147
        state         => 'checkout'
148
    );
149
}
150
elsif ( $action eq 'accept' ) {
151
    my $orderid = $cgi->param('orderid');
152
    my $authkey = $cgi->param('authkey');
153
154
    # DIBS-specific authentication check
155
    my $k1      = C4::Context->preference('OpacPaymentK1');
156
    my $k2      = C4::Context->preference('OpacPaymentK2');
157
    my $my_authkey = md5_hex(
158
        $k2
159
          . md5_hex(
160
                $k1
161
              . 'transact='
162
              . $cgi->param('transact')
163
              . '&amount='
164
              . $cgi->param('amount')
165
              . '&currency='
166
              . $cgi->param('currency')
167
          )
168
      );
169
170
    if ( $authkey ne $my_authkey ) {
171
        $template->param(
172
            BORROWER_INFO => $borr,
173
            state         => 'error',
174
            error         => 'authkey',
175
            orderid       => $orderid
176
        );
177
        carp "Invalid authentication key returned for orderid $orderid";
178
        output_html_with_http_headers $cgi, $cookie, $template->output;
179
        exit;
180
    }
181
182
    # Authentication passed
183
184
    my $order        = GetOrder($orderid);
185
    my $orderdetails = GetOrderDetails($orderid);
186
187
    $template->param(
188
        BORROWER_INFO => $borr,
189
        accountlines  => $orderdetails,
190
        order         => $order,
191
        state         => 'success'
192
    );
193
}
194
elsif ( $action eq 'cancel' ) {
195
    my $orderid = $cgi->param('orderid');
196
    my $authkey = $cgi->param('authkey');
197
198
    my $order = GetOrder($orderid);
199
    my $orderdetails = GetOrderDetails($orderid);
200
201
    $order->{'status'} = 'canceled';
202
    $order->{'modificationdate'} =
203
      DateTime::Format::MySQL->format_datetime( DateTime->now );
204
    ModOrder($order);
205
206
    $template->param(
207
        BORROWER_INFO => $borr,
208
        accountlines  => $orderdetails,
209
        order         => $order,
210
        state         => 'canceled'
211
    );
212
}
213
214
output_html_with_http_headers $cgi, $cookie, $template->output;

Return to bug 15335