3 # This file is part of Koha.
5 # Copyright (C) 2012-2013 ByWater Solutions
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.
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.
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>.
26 use C4::SIP::Sip::Constants qw(:all);
29 use constant { LANGUAGE => '001' };
40 my $patron_identifier;
47 my $fee_acknowledged = 0;
61 "a|address|host|hostaddress=s" => \$host, # sip server ip
62 "p|port=s" => \$port, # sip server port
63 "su|sip_user=s" => \$login_user_id, # sip user
64 "sp|sip_pass=s" => \$login_password, # sip password
65 "l|location|location_code=s" => \$location_code, # sip location code
67 "patron=s" => \$patron_identifier, # patron cardnumber or login
68 "password=s" => \$patron_password, # patron's password
70 "i|item=s" => \$item_identifier,
72 "fa|fee-acknowledged" => \$fee_acknowledged,
74 "s|summary=s" => \$summary,
76 "fee-type=s" => \$fee_type,
77 "payment-type=s" => \$payment_type,
78 "currency-type=s" => \$currency_type,
79 "fee-amount=s" => \$fee_amount,
80 "fee-identifier=s" => \$fee_identifier,
81 "transaction-id=s" => \$transaction_id,
83 "t|terminator=s" => \$terminator,
85 "m|message=s" => \@messages,
100 $terminator = ( $terminator eq 'CR' ) ? $CR : $CRLF;
102 # Set perl to expect the same record terminator it is sending
105 my $transaction_date = C4::SIP::Sip::timestamp();
107 my $terminal_password = $login_password;
110 print "Attempting socket connection to $host:$port...";
112 my $socket = IO::Socket::INET->new("$host:$port")
113 or die "failed! : $!\n";
119 subroutine => \&build_login_command_message,
121 login_user_id => $login_user_id,
122 login_password => $login_password,
123 location_code => $location_code,
126 patron_status_request => {
127 name => 'Patron Status Request',
128 subroutine => \&build_patron_status_request_command_message,
130 transaction_date => $transaction_date,
131 institution_id => $location_code,
132 patron_identifier => $patron_identifier,
133 terminal_password => $terminal_password,
134 patron_password => $patron_password,
136 optional => [ 'patron_password', ],
138 patron_information => {
139 name => 'Patron Information',
140 subroutine => \&build_patron_information_command_message,
142 transaction_date => $transaction_date,
143 institution_id => $location_code,
144 patron_identifier => $patron_identifier,
145 terminal_password => $terminal_password,
146 patron_password => $patron_password,
149 optional => [ 'patron_password', 'summary' ],
151 item_information => {
152 name => 'Item Information',
153 subroutine => \&build_item_information_command_message,
155 transaction_date => $transaction_date,
156 institution_id => $location_code,
157 item_identifier => $item_identifier,
158 terminal_password => $terminal_password,
164 subroutine => \&build_checkout_command_message,
166 SC_renewal_policy => 'Y',
168 transaction_date => $transaction_date,
169 nb_due_date => undef,
170 institution_id => $location_code,
171 patron_identifier => $patron_identifier,
172 item_identifier => $item_identifier,
173 terminal_password => $terminal_password,
174 item_properties => undef,
175 patron_password => $patron_password,
176 fee_acknowledged => $fee_acknowledged,
180 'nb_due_date', # defaults to transaction date
189 subroutine => \&build_checkin_command_message,
192 transaction_date => $transaction_date,
193 return_date => $transaction_date,
194 current_location => $location_code,
195 institution_id => $location_code,
196 item_identifier => $item_identifier,
197 terminal_password => $terminal_password,
198 item_properties => undef,
202 'return_date', # defaults to transaction date
210 subroutine => \&build_renew_command_message,
212 third_party_allowed => 'N',
214 transaction_date => $transaction_date,
215 nb_due_date => undef,
216 institution_id => $location_code,
217 patron_identifier => $patron_identifier,
218 patron_password => $patron_password,
219 item_identifier => $item_identifier,
220 title_identifier => undef,
221 terminal_password => $terminal_password,
222 item_properties => undef,
223 fee_acknowledged => $fee_acknowledged,
226 'nb_due_date', # defaults to transaction date
237 subroutine => \&build_fee_paid_command_message,
239 transaction_date => $transaction_date,
240 fee_type => $fee_type,
241 payment_type => $payment_type,
242 currency_type => $currency_type,
243 fee_amount => $fee_amount,
244 institution_id => $location_code,
245 patron_identifier => $patron_identifier,
246 terminal_password => $terminal_password,
247 patron_password => $patron_password,
248 fee_identifier => $fee_identifier,
249 transaction_id => $transaction_id,
252 'fee_type', # has default
253 'payment_type', # has default
254 'currency_type', #has default
263 my $data = run_command_message('login');
265 if ( $data =~ '^941' ) { ## we are logged in
266 foreach my $m (@messages) {
269 my $data = run_command_message($m);
277 sub build_command_message {
280 ##FIXME It would be much better to use exception handling so we aren't priting from subs
281 unless ( $handlers->{$message} ) {
282 say "$message is an unsupported command!";
286 my $subroutine = $handlers->{$message}->{subroutine};
287 my $parameters = $handlers->{$message}->{parameters};
288 my %optional = map { $_ => 1 } @{ $handlers->{$message}->{optional} };
290 foreach my $key ( keys %$parameters ) {
291 unless ( $parameters->{$key} ) {
292 unless ( $optional{$key} ) {
293 say "$key is required for $message";
299 return &$subroutine($parameters);
302 sub run_command_message {
305 my $command_message = build_command_message($message);
307 return unless $command_message;
309 say "SEND: $command_message";
310 print $socket $command_message . $terminator;
312 my $data = <$socket>;
319 sub build_login_command_message {
322 my $login_user_id = $params->{login_user_id};
323 my $login_password = $params->{login_password};
324 my $location_code = $params->{location_code};
328 . build_field( FID_LOGIN_UID, $login_user_id )
329 . build_field( FID_LOGIN_PWD, $login_password )
330 . build_field( FID_LOCATION_CODE, $location_code );
333 sub build_patron_status_request_command_message {
336 my $transaction_date = $params->{transaction_date};
337 my $institution_id = $params->{institution_id};
338 my $patron_identifier = $params->{patron_identifier};
339 my $terminal_password = $params->{terminal_password};
340 my $patron_password = $params->{patron_password};
346 . build_field( FID_INST_ID, $institution_id )
347 . build_field( FID_PATRON_ID, $patron_identifier )
348 . build_field( FID_TERMINAL_PWD, $terminal_password )
349 . build_field( FID_PATRON_PWD, $patron_password );
352 sub build_patron_information_command_message {
355 my $transaction_date = $params->{transaction_date};
356 my $institution_id = $params->{institution_id};
357 my $patron_identifier = $params->{patron_identifier};
358 my $terminal_password = $params->{terminal_password};
359 my $patron_password = $params->{patron_password};
360 my $summary = $params->{summary};
369 . build_field( FID_INST_ID, $institution_id )
370 . build_field( FID_PATRON_ID, $patron_identifier )
371 . build_field( FID_TERMINAL_PWD, $terminal_password )
372 . build_field( FID_PATRON_PWD, $patron_password, { optional => 1 } );
375 sub build_item_information_command_message {
378 my $transaction_date = $params->{transaction_date};
379 my $institution_id = $params->{institution_id};
380 my $item_identifier = $params->{item_identifier};
381 my $terminal_password = $params->{terminal_password};
387 . build_field( FID_INST_ID, $institution_id )
388 . build_field( FID_ITEM_ID, $item_identifier )
389 . build_field( FID_TERMINAL_PWD, $terminal_password );
392 sub build_checkout_command_message {
395 my $SC_renewal_policy = $params->{SC_renewal_policy} || 'N';
396 my $no_block = $params->{no_block} || 'N';
397 my $transaction_date = $params->{transaction_date};
398 my $nb_due_date = $params->{nb_due_date};
399 my $institution_id = $params->{institution_id};
400 my $patron_identifier = $params->{patron_identifier};
401 my $item_identifier = $params->{item_identifier};
402 my $terminal_password = $params->{terminal_password};
403 my $item_properties = $params->{item_properties};
404 my $patron_password = $params->{patron_password};
405 my $fee_acknowledged = $params->{fee_acknowledged} || 'N';
406 my $cancel = $params->{cancel} || 'N';
408 $SC_renewal_policy = $SC_renewal_policy eq 'Y' ? 'Y' : 'N';
409 $no_block = $no_block eq 'Y' ? 'Y' : 'N';
410 $fee_acknowledged = $fee_acknowledged eq 'Y' ? 'Y' : 'N';
411 $cancel = $cancel eq 'Y' ? 'Y' : 'N';
413 $nb_due_date ||= $transaction_date;
421 . build_field( FID_INST_ID, $institution_id )
422 . build_field( FID_PATRON_ID, $patron_identifier )
423 . build_field( FID_ITEM_ID, $item_identifier )
424 . build_field( FID_TERMINAL_PWD, $terminal_password )
425 . build_field( FID_ITEM_PROPS, $item_properties, { optional => 1 } )
426 . build_field( FID_PATRON_PWD, $patron_password, { optional => 1 } )
427 . build_field( FID_FEE_ACK, $fee_acknowledged, { optional => 1 } )
428 . build_field( FID_CANCEL, $cancel, { optional => 1 } );
431 sub build_checkin_command_message {
434 my $no_block = $params->{no_block} || 'N';
435 my $transaction_date = $params->{transaction_date};
436 my $return_date = $params->{return_date};
437 my $current_location = $params->{current_location};
438 my $institution_id = $params->{institution_id};
439 my $item_identifier = $params->{item_identifier};
440 my $terminal_password = $params->{terminal_password};
441 my $item_properties = $params->{item_properties};
442 my $cancel = $params->{cancel} || 'N';
444 $no_block = $no_block eq 'Y' ? 'Y' : 'N';
445 $cancel = $cancel eq 'Y' ? 'Y' : 'N';
447 $return_date ||= $transaction_date;
454 . build_field( FID_CURRENT_LOCN, $current_location )
455 . build_field( FID_INST_ID, $institution_id )
456 . build_field( FID_ITEM_ID, $item_identifier )
457 . build_field( FID_TERMINAL_PWD, $terminal_password )
458 . build_field( FID_ITEM_PROPS, $item_properties, { optional => 1 } )
459 . build_field( FID_CANCEL, $cancel, { optional => 1 } );
462 sub build_renew_command_message {
465 my $third_party_allowed = $params->{third_party_allowed} || 'N';
466 my $no_block = $params->{no_block} || 'N';
467 my $transaction_date = $params->{transaction_date};
468 my $nb_due_date = $params->{nb_due_date};
469 my $institution_id = $params->{institution_id};
470 my $patron_identifier = $params->{patron_identifier};
471 my $patron_password = $params->{patron_password};
472 my $item_identifier = $params->{item_identifier};
473 my $title_identifier = $params->{title_identifier};
474 my $terminal_password = $params->{terminal_password};
475 my $item_properties = $params->{item_properties};
476 my $fee_acknowledged = $params->{fee_acknowledged} || 'N';
478 $third_party_allowed = $third_party_allowed eq 'Y' ? 'Y' : 'N';
479 $no_block = $no_block eq 'Y' ? 'Y' : 'N';
480 $fee_acknowledged = $fee_acknowledged eq 'Y' ? 'Y' : 'N';
482 $nb_due_date ||= $transaction_date;
486 . $third_party_allowed
490 . build_field( FID_INST_ID, $institution_id )
491 . build_field( FID_PATRON_ID, $patron_identifier )
492 . build_field( FID_PATRON_PWD, $patron_password, { optional => 1 } )
493 . build_field( FID_ITEM_ID, $item_identifier )
494 . build_field( FID_TITLE_ID, $title_identifier )
495 . build_field( FID_TERMINAL_PWD, $terminal_password )
496 . build_field( FID_ITEM_PROPS, $item_properties, { optional => 1 } )
497 . build_field( FID_FEE_ACK, $fee_acknowledged, { optional => 1 } );
500 sub build_fee_paid_command_message {
503 my $transaction_date = $params->{transaction_date};
504 my $fee_type = $params->{fee_type} || '01';
505 my $payment_type = $params->{payment_type} || '00';
506 my $currency_type = $params->{currency_type} || 'USD';
507 my $fee_amount = $params->{fee_amount};
508 my $institution_id = $params->{location_code};
509 my $patron_identifier = $params->{patron_identifier};
510 my $terminal_password = $params->{terminal_password};
511 my $patron_password = $params->{patron_password};
512 my $fee_identifier = $params->{fee_identifier};
513 my $transaction_id = $params->{transaction_id};
521 . build_field( FID_FEE_AMT, $fee_amount )
522 . build_field( FID_INST_ID, $institution_id )
523 . build_field( FID_PATRON_ID, $patron_identifier )
524 . build_field( FID_TERMINAL_PWD, $terminal_password, { optional => 1 } )
525 . build_field( FID_PATRON_PWD, $patron_password, { optional => 1 } )
526 . build_field( FID_FEE_ID, $fee_identifier, { optional => 1 } )
527 . build_field( FID_TRANSACTION_ID, $transaction_id, { optional => 1 } );
531 my ( $field_identifier, $value, $params ) = @_;
535 return q{} if ( $params->{optional} && !$value );
537 return $field_identifier . (($value) ? $value : '') . '|';
541 say q/sip_cli_emulator.pl - SIP command line emulator
543 Test a SIP2 service by sending patron status and patron
544 information requests.
547 sip_cli_emulator.pl [OPTIONS]
550 --help display help message
552 -a --address SIP server ip address or host name
553 -p --port SIP server port
555 -su --sip_user SIP server login username
556 -sp --sip_pass SIP server login password
558 -l --location SIP location code
560 --patron ILS patron cardnumber or username
561 --password ILS patron password
563 -s --summary Optionally define the patron information request summary field.
564 Please refer to the SIP2 protocol specification for details
566 --item ILS item identifier ( item barcode )
568 -t --terminator SIP2 message terminator, either CR, or CRLF
571 -fa --fee-acknowledged Sends a confirmation of checkout fee
573 --fee-type Fee type for Fee Paid message, defaults to '01'
574 --payment-type Payment type for Fee Paid message, default to '00'
575 --currency-type Currency type for Fee Paid message, defaults to 'USD'
576 --fee-amount Fee amount for Fee Paid message, required
577 --fee-identifier Fee identifier for Fee Paid message, optional
578 --transaction-id Transaction id for Fee Paid message, optional
580 -m --message SIP2 message to execute
582 Implemented Messages:
583 patron_status_request