From 6aa910c2ece9cd5bcae3c45e383c89c0b70539fe Mon Sep 17 00:00:00 2001 From: erickson <erickson@dcc99617-32d9-48b4-a31d-7c20da2025e4> Date: Mon, 19 Oct 2009 15:44:32 +0000 Subject: [PATCH] Patch from Lebbeous Fogle-Weekley which integrates credit card payments into the existing staff client payment API call. Also updates some unnecessarily long org unit settings names git-svn-id: svn://svn.open-ils.org/ILS/trunk@14492 dcc99617-32d9-48b4-a31d-7c20da2025e4 --- Open-ILS/src/extras/ils_events.xml | 11 ++++++- .../src/perlmods/OpenILS/Application/Circ/Money.pm | 37 +++++++++++++++++++--- .../src/perlmods/OpenILS/Application/CreditCard.pm | 23 +++++++++++--- Open-ILS/src/sql/Pg/002.schema.config.sql | 3 +- Open-ILS/src/sql/Pg/950.data.seed-values.sql | 29 ++++++++++------- .../0038.data.org-setting-credit-default-proc.sql | 35 ++++++++++++++++++++ .../support-scripts/test-scripts/payment_test.pl | 8 +++-- 7 files changed, 120 insertions(+), 26 deletions(-) create mode 100644 Open-ILS/src/sql/Pg/upgrade/0038.data.org-setting-credit-default-proc.sql diff --git a/Open-ILS/src/extras/ils_events.xml b/Open-ILS/src/extras/ils_events.xml index 696d36a3af..56c40da1d8 100644 --- a/Open-ILS/src/extras/ils_events.xml +++ b/Open-ILS/src/extras/ils_events.xml @@ -745,7 +745,16 @@ <desc xml:lang="en-US">Not enough parameters to use credit card processor</desc> </event> <event code='4003' textcode='CREDIT_PROCESSOR_NOT_ALLOWED'> - <desc xml:lang="en-US">The credit card processor you have named is not allowed.</desc> + <desc xml:lang="en-US">The credit card processor you have named is not allowed</desc> + </event> + <event code='4004' textcode='CREDIT_PROCESSOR_NOT_SPECIFIED'> + <desc xml:lang="en-US">No credit card processor specified either in org unit settings or in call to credit service API method.</desc> + </event> + <event code='4010' textcode='CREDIT_PROCESSOR_NO_DEFAULT_SELECTED'> + <desc xml:lang="en-US">No default credit processor is selected</desc> + </event> + <event code='4020' textcode='CREDIT_PROCESSOR_DECLINED_TRANSACTION'> + <desc xml:lang="en-US">The credit card processor has declined the transaction.</desc> </event> diff --git a/Open-ILS/src/perlmods/OpenILS/Application/Circ/Money.pm b/Open-ILS/src/perlmods/OpenILS/Application/Circ/Money.pm index 0d27690161..9b15e55e3a 100644 --- a/Open-ILS/src/perlmods/OpenILS/Application/Circ/Money.pm +++ b/Open-ILS/src/perlmods/OpenILS/Application/Circ/Money.pm @@ -200,11 +200,38 @@ sub make_payments { } if($type eq 'credit_card_payment') { - # TODO send to credit card processor - # amount == $total_paid - # user == $user_id - # other args == $cc_args (hash, see api docs) - # $e->rollback if processing fails. This will undo everything. + my $this_ou = $e->requestor->ws_ou; + my $response = $apputils->simplereq( + 'open-ils.credit', + 'open-ils.credit.process', + { + "desc" => $payments->{note}, + "amount" => $total_paid, + "patron_id" => $user_id, + "cc" => $payments->{cc_number}, + "expiration" => sprintf( + "%02d-%04d", + $payments->{expire_month}, + $payments->{expire_year} + ), + "ou" => $this_ou + } + ); + # senator: Should failures and/or declines be logged somewhere? Is + # some other cog taking care of this? Actually, what about the + # successes, too? There's an approval code from the payment processor + # that could go somewhere... + if (exists $response->{ilsevent}) { + $e->rollback; + return $response; + } + if ($response->{statusCode} != 200) { + $e->rollback; + return OpenILS::Event->new( + 'CREDIT_PROCESSOR_DECLINED_TRANSACTION', + note => $response->{statusText} + ); + } } $e->commit; diff --git a/Open-ILS/src/perlmods/OpenILS/Application/CreditCard.pm b/Open-ILS/src/perlmods/OpenILS/Application/CreditCard.pm index 7250c9f4e8..bd1a845326 100644 --- a/Open-ILS/src/perlmods/OpenILS/Application/CreditCard.pm +++ b/Open-ILS/src/perlmods/OpenILS/Application/CreditCard.pm @@ -21,6 +21,7 @@ use strict; use warnings; use Business::CreditCard; use Business::OnlinePayment; +use Locale::Country; use OpenILS::Event; use OpenSRF::Utils::Logger qw/:logger/; @@ -28,7 +29,7 @@ use OpenILS::Utils::CStoreEditor qw/:funcs/; use OpenILS::Application::AppUtils; my $U = "OpenILS::Application::AppUtils"; -use constant CREDIT_OPTS_NS => "global.credit.processor"; +use constant CREDIT_NS => "credit"; # Given the argshash from process_payment(), this helper function just finds # a function in the current namespace named "bop_args_{processor}" and calls @@ -73,7 +74,7 @@ sub get_processor_settings { +{ map { ($_ => $U->ou_ancestor_setting_value( - $org_unit, CREDIT_OPTS_NS . ".${processor}.${_}" + $org_unit, CREDIT_NS . ".processor.${processor}.${_}" )) } qw/enabled login password signature server testmode/ }; } @@ -115,9 +116,15 @@ sub process_payment { and $argshash->{cc} and $argshash->{amount} and $argshash->{expiration} - and $argshash->{ou} - and $argshash->{processor}; + and $argshash->{ou}; + if (!$argshash->{processor}) { + if (!($argshash->{processor} = + $U->ou_ancestor_setting_value( + $argshash->{ou}, CREDIT_NS . '.processor.default'))) { + return OpenILS::Event->new('CREDIT_PROCESSOR_NOT_SPECIFIED'); + } + } # Basic sanity check on processor name. if ($argshash->{processor} !~ /^[a-z0-9_\-]+$/i) { return OpenILS::Event->new('CREDIT_PROCESSOR_NOT_ALLOWED'); @@ -199,6 +206,12 @@ sub prepare_bop_content { $content{zip} ||= $patron->mailing_address->post_code; $content{country} ||= $patron->mailing_address->country; + # Yet another fantastic kludge. country2code() comes from Locale::Country. + # PayPal must have 2 letter country field (ISO 3166) that's uppercase. + if (length($content{country}) > 2 && $argshash->{processor} eq 'PayPal') { + $content{country} = uc country2code($content{country}); + } + %content; } @@ -322,7 +335,7 @@ sub retrieve_payable_balance { my $o = $org->{billing_location}; $o = $org->{circ_lib} unless $o; next if $hash{$o}; # was $hash{$org}, but that doesn't make sense. $org is a hashref and $o gets added in the next line. - $hash{$o} = $U->ou_ancestor_setting_value($o, 'global.credit.allow', $e); + $hash{$o} = $U->ou_ancestor_setting_value($o, CREDIT_NS . '.payments.allow', $e); } my @credit_orgs = map { $hash{$_} ? ($_) : () } keys %hash; diff --git a/Open-ILS/src/sql/Pg/002.schema.config.sql b/Open-ILS/src/sql/Pg/002.schema.config.sql index 01fbc694d5..b68623605b 100644 --- a/Open-ILS/src/sql/Pg/002.schema.config.sql +++ b/Open-ILS/src/sql/Pg/002.schema.config.sql @@ -51,7 +51,8 @@ CREATE TABLE config.upgrade_log ( install_date TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW() ); -INSERT INTO config.upgrade_log (version) VALUES ('0037'); -- atz +INSERT INTO config.upgrade_log (version) VALUES ('0038'); -- senator + CREATE TABLE config.bib_source ( id SERIAL PRIMARY KEY, diff --git a/Open-ILS/src/sql/Pg/950.data.seed-values.sql b/Open-ILS/src/sql/Pg/950.data.seed-values.sql index 679a24fac0..bf1ada0a28 100644 --- a/Open-ILS/src/sql/Pg/950.data.seed-values.sql +++ b/Open-ILS/src/sql/Pg/950.data.seed-values.sql @@ -1205,7 +1205,7 @@ INSERT INTO permission.perm_list VALUES (325,'UPDATE_ORG_UNIT_SETTING.org.bounced_emails', oils_i18n_gettext(325,'FIXME: Need description for UPDATE_ORG_UNIT_SETTING.org.bounced_emails', 'ppl', 'description')), (326,'UPDATE_ORG_UNIT_SETTING.circ.hold_expire_alert_interval', oils_i18n_gettext(326,'FIXME: Need description for UPDATE_ORG_UNIT_SETTING.circ.hold_expire_alert_interval', 'ppl', 'description')), (327,'UPDATE_ORG_UNIT_SETTING.circ.hold_expire_interval', oils_i18n_gettext(327,'FIXME: Need description for UPDATE_ORG_UNIT_SETTING.circ.hold_expire_interval', 'ppl', 'description')), - (328,'UPDATE_ORG_UNIT_SETTING.global.credit.allow', oils_i18n_gettext(328,'FIXME: Need description for UPDATE_ORG_UNIT_SETTING.global.credit.allow', 'ppl', 'description')), + (328,'UPDATE_ORG_UNIT_SETTING.credit.payments.allow', oils_i18n_gettext(328,'FIXME: Need description for UPDATE_ORG_UNIT_SETTING.credit.payments.allow', 'ppl', 'description')), (329,'UPDATE_ORG_UNIT_SETTING.circ.void_overdue_on_lost', oils_i18n_gettext(329,'FIXME: Need description for UPDATE_ORG_UNIT_SETTING.circ.void_overdue_on_lost', 'ppl', 'description')), (330,'UPDATE_ORG_UNIT_SETTING.circ.hold_stalling.soft', oils_i18n_gettext(330,'FIXME: Need description for UPDATE_ORG_UNIT_SETTING.circ.hold_stalling.soft', 'ppl', 'description')), (331,'UPDATE_ORG_UNIT_SETTING.circ.hold_boundary.hard', oils_i18n_gettext(331,'FIXME: Need description for UPDATE_ORG_UNIT_SETTING.circ.hold_boundary.hard', 'ppl', 'description')), @@ -1475,7 +1475,7 @@ INSERT into config.org_unit_setting_type 'Amount of time after a hold is placed before the hold expires. Example "100 days"', 'interval' ), -( 'global.credit.allow', +( 'credit.payments.allow', '', 'If enabled, patrons will be able to pay fines accrued at this location via credit card', 'bool' ), @@ -1695,48 +1695,53 @@ INSERT into config.org_unit_setting_type 'When true, the Date of Birth column in patron lists will default to Not Visible, and in the Patron Summary sidebar the value will display as <Hidden> unless the field label is clicked.', 'bool' ), -( 'global.credit.processor.authorizenet.enabled', +( 'credit.processor.default', + 'Credit card processing: Name default credit processor', + 'This might be "AuthorizeNet", "PayPal", etc.', + 'string' ), + +( 'credit.processor.authorizenet.enabled', 'Credit card processing: Enable AuthorizeNet payments', '', 'bool' ), -( 'global.credit.processor.authorizenet.login', +( 'credit.processor.authorizenet.login', 'Credit card processing: AuthorizeNet login', '', 'string' ), -( 'global.credit.processor.authorizenet.password', +( 'credit.processor.authorizenet.password', 'Credit card processing: AuthorizeNet password', '', 'string' ), -( 'global.credit.processor.authorizenet.server', +( 'credit.processor.authorizenet.server', 'Credit card processing: AuthorizeNet server', 'Required if using a developer/test account with AuthorizeNet', 'string' ), -( 'global.credit.processor.authorizenet.testmode', +( 'credit.processor.authorizenet.testmode', 'Credit card processing: AuthorizeNet test mode', '', 'bool' ), -( 'global.credit.processor.paypal.enabled', +( 'credit.processor.paypal.enabled', 'Credit card processing: Enable PayPal payments', '', 'bool' ), -( 'global.credit.processor.paypal.login', +( 'credit.processor.paypal.login', 'Credit card processing: PayPal login', '', 'string' ), -( 'global.credit.processor.paypal.password', +( 'credit.processor.paypal.password', 'Credit card processing: PayPal password', '', 'string' ), -( 'global.credit.processor.paypal.signature', +( 'credit.processor.paypal.signature', 'Credit card processing: PayPal signature', '', 'string' ), -( 'global.credit.processor.paypal.testmode', +( 'credit.processor.paypal.testmode', 'Credit card processing: PayPal test mode', '', 'bool' ) diff --git a/Open-ILS/src/sql/Pg/upgrade/0038.data.org-setting-credit-default-proc.sql b/Open-ILS/src/sql/Pg/upgrade/0038.data.org-setting-credit-default-proc.sql new file mode 100644 index 0000000000..b20237b9fb --- /dev/null +++ b/Open-ILS/src/sql/Pg/upgrade/0038.data.org-setting-credit-default-proc.sql @@ -0,0 +1,35 @@ +BEGIN; + +INSERT INTO config.upgrade_log (version) VALUES ('0038'); -- senator + +UPDATE permission.perm_list + SET code = 'UPDATE_ORG_UNIT_SETTING.credit.payments.allow' + WHERE code = 'UPDATE_ORG_UNIT_SETTING.global.credit.allow'; + +UPDATE config.org_unit_setting_type + SET name = 'credit.payments.allow' + WHERE name = 'global.credit.allow'; + +UPDATE config.org_unit_setting_type + SET name = REGEXP_REPLACE(name, E'global\.', '') + WHERE name LIKE 'global.credit.%'; + +UPDATE config.org_unit_setting_type + SET label = 'Credit card processing: AuthorizeNet enabled' + WHERE name = 'credit.processor.authorizenet.enabled'; + +UPDATE config.org_unit_setting_type + SET label = 'Credit card processing: PayPal enabled' + WHERE name = 'credit.processor.paypal.enabled'; + +INSERT INTO + config.org_unit_setting_type ( name, label, description, datatype ) + VALUES ( + 'credit.processor.default', + 'Credit card processing: Name default credit processor', + 'This might be "AuthorizeNet", "PayPal", etc.', + 'string' + ); + + +COMMIT; diff --git a/Open-ILS/src/support-scripts/test-scripts/payment_test.pl b/Open-ILS/src/support-scripts/test-scripts/payment_test.pl index bb8fc30bc7..41ece54d6d 100644 --- a/Open-ILS/src/support-scripts/test-scripts/payment_test.pl +++ b/Open-ILS/src/support-scripts/test-scripts/payment_test.pl @@ -16,6 +16,7 @@ $0 [-h] --login=UserName --password==MyPass [OPTIONS] [Transaction data] Required Arguments: -l --login Assigned by your processor API (specified in -t) -p --password Assigned by your processor API (specified in -t) + -o --org-unit What library/branch is making this payment (numeric) Options: -t --target Payment processor (default PayPal) @@ -48,11 +49,12 @@ my $expires = '12-2014'; my $id = 5; ### Empties -my ($login, $password, $signature, $help, $amount, $server); +my ($login, $password, $ou, $signature, $help, $amount, $server); GetOptions( 'config_file=s' => \$config, 'target=s' => \$processor, + 'org-unit=i' => \$ou, 'login=s' => \$login, 'password=s' => \$password, 's|signature=s' => \$signature, @@ -66,7 +68,7 @@ GetOptions( $help and print usage and exit; -unless ($login and $processor and $password) { +unless ($login and $processor and $password and $ou) { print usage; exit; } @@ -81,6 +83,7 @@ Attempting transaction: login => $login, password => $password, signature => $signature, + ou => $ou, amount => $amount, cc => $number, expiration => $expires, @@ -99,6 +102,7 @@ my( $user, $evt ) = simplereq('open-ils.credit', 'open-ils.credit.process', login => $login, password => $password, signature => $signature, + ou => $ou, amount => $amount, cc => $number, expiration => $expires, -- 2.11.0