From 7ad06e98f77955447bde12a08738487d8a69053a Mon Sep 17 00:00:00 2001
From: erickson <erickson@dcc99617-32d9-48b4-a31d-7c20da2025e4>
Date: Fri, 16 Oct 2009 15:43:19 +0000
Subject: [PATCH] Patch from Lebbeous Fogle-Weekley and Joe Atzberger.  Adds
 org unit settings for Authorize.net and PayPal credit card processors.

git-svn-id: svn://svn.open-ils.org/ILS/trunk@14471 dcc99617-32d9-48b4-a31d-7c20da2025e4
---
 Open-ILS/src/extras/ils_events.xml                 | 13 ++++
 .../src/perlmods/OpenILS/Application/CreditCard.pm | 73 +++++++++++++++-------
 Open-ILS/src/sql/Pg/002.schema.config.sql          |  2 +-
 Open-ILS/src/sql/Pg/950.data.seed-values.sql       | 50 ++++++++++++++-
 .../0037.data.org-setting-authorizenet-paypal.sql  | 55 ++++++++++++++++
 5 files changed, 168 insertions(+), 25 deletions(-)
 create mode 100644 Open-ILS/src/sql/Pg/upgrade/0037.data.org-setting-authorizenet-paypal.sql

diff --git a/Open-ILS/src/extras/ils_events.xml b/Open-ILS/src/extras/ils_events.xml
index 1d31af54d5..696d36a3af 100644
--- a/Open-ILS/src/extras/ils_events.xml
+++ b/Open-ILS/src/extras/ils_events.xml
@@ -736,6 +736,19 @@
 	<event code='2003' textcode='INTERNAL_SERVER_ERROR'>
 		<desc xml:lang="en-US">There was an internal server error</desc>
 	</event>
+
+    <!-- CREDIT EVENTS -->
+	<event code='4001' textcode='CREDIT_PROCESSOR_NOT_ENABLED'>
+		<desc xml:lang="en-US">Credit card processor not enabled</desc>
+	</event>
+	<event code='4002' textcode='CREDIT_PROCESSOR_BAD_PARAMS'>
+		<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>
+	</event>
+
+
 	<event code='5000' textcode='PERM_FAILURE'>
 		<desc xml:lang="en-US">Permission Denied</desc>
 	</event>
diff --git a/Open-ILS/src/perlmods/OpenILS/Application/CreditCard.pm b/Open-ILS/src/perlmods/OpenILS/Application/CreditCard.pm
index 1e8e2797d5..7250c9f4e8 100644
--- a/Open-ILS/src/perlmods/OpenILS/Application/CreditCard.pm
+++ b/Open-ILS/src/perlmods/OpenILS/Application/CreditCard.pm
@@ -28,7 +28,7 @@ use OpenILS::Utils::CStoreEditor qw/:funcs/;
 use OpenILS::Application::AppUtils;
 my $U = "OpenILS::Application::AppUtils";
 
-my @ALLOWED_PROCESSORS = qw/AuthorizeNet PayPal/;
+use constant CREDIT_OPTS_NS => "global.credit.processor";
 
 # Given the argshash from process_payment(), this helper function just finds
 # a function in the current namespace named "bop_args_{processor}" and calls
@@ -67,6 +67,17 @@ sub bop_args_PayPal {
     );
 }
 
+sub get_processor_settings {
+    my $org_unit = shift;
+    my $processor = lc shift;
+
+    +{ map { ($_ =>
+        $U->ou_ancestor_setting_value(
+            $org_unit, CREDIT_OPTS_NS . ".${processor}.${_}"
+        )) } qw/enabled login password signature server testmode/
+    };
+}
+
 __PACKAGE__->register_method(
     method    => 'process_payment',
     api_name  => 'open-ils.credit.process',
@@ -75,24 +86,20 @@ __PACKAGE__->register_method(
         params => [
             { desc => q/Hash of arguments with these keys:
                 patron_id: Not a barcode, but a patron's internal ID
-                processor: the transaction "clearing house" (e.g. PayPal)
-                    login: supplied by processor to institution for their API
-                 password: supplied by processor to institution for their API
+                       ou: Org unit where transaction happens
+                processor: Payment processor to use (AuthorizeNet, PayPal, etc)
                        cc: credit card number
                      cvv2: 3 or 4 digits from back of card
                    amount: transaction value
-                 testmode: optional (default: NO, i.e. a REAL transaction), note this is different than targeting the processor's test server
                    action: optional (default: Normal Authorization)
-                signature: optional (required by some processor APIs)
                first_name: optional (default: patron's first_given_name field)
                 last_name: optional (default: patron's family_name field)
                   address: optional (default: patron's street1 field)
                      city: optional (default: patron's city field)
                     state: optional (default: patron's state field)
                       zip: optional (default: patron's zip field)
-                  country: optional (some processor APIs. 2 letter code.)
+                  country: optional (some processor APIs: 2 letter code.)
               description: optional
-                   server: optional (for testing some APIs, i.e. AuthorizeNet)
                 /, type => 'hash' }
         ],
         return => { desc => 'Hash of status information', type =>'hash' }
@@ -102,17 +109,40 @@ __PACKAGE__->register_method(
 sub process_payment {
     my ($self, $client, $argshash) = @_; # $client is unused in this sub
 
-    # Confirm required arguments.
+    # Confirm some required arguments.
     return OpenILS::Event->new('BAD_PARAMS')
-      unless $argshash
-         and $argshash->{login}
-         and $argshash->{password}
-         and $argshash->{processor}
-         and $argshash->{cc};
-
-     # A valid patron_id is also required.
-     my $e = new_editor();
-     my $patron = $e->retrieve_actor_user(
+        unless $argshash
+            and $argshash->{cc}
+            and $argshash->{amount}
+            and $argshash->{expiration}
+            and $argshash->{ou}
+            and $argshash->{processor};
+
+    # Basic sanity check on processor name.
+    if ($argshash->{processor} !~ /^[a-z0-9_\-]+$/i) {
+        return OpenILS::Event->new('CREDIT_PROCESSOR_NOT_ALLOWED');
+    }
+
+    # Get org unit settings related to our processor
+    my $psettings = get_processor_settings(
+        $argshash->{ou}, $argshash->{processor}
+    );
+
+    if (!$psettings->{enabled}) {
+        return OpenILS::Event->new('CREDIT_PROCESSOR_NOT_ENABLED');
+    }
+
+    # Add the org unit settings for the chosen processor to our argshash.
+    $argshash = +{ %{$argshash}, %{$psettings} };
+
+    # At least the following (derived from org unit settings) are required.
+    return OpenILS::Event->new('CREDIT_PROCESSOR_BAD_PARAMS')
+        unless $argshash->{login}
+            and $argshash->{password};
+
+    # A valid patron_id is also required.
+    my $e = new_editor();
+    my $patron = $e->retrieve_actor_user(
         [
             $argshash->{patron_id},
             {
@@ -122,11 +152,7 @@ sub process_payment {
         ]
     ) or return $e->event;
 
-    if (grep { $_ eq $argshash->{processor} } @ALLOWED_PROCESSORS) {
-        return dispatch($argshash, $patron);
-    } else {
-        return OpenILS::Event->new('BAD_PARAMS');   # no supported processor
-    }
+    return dispatch($argshash, $patron);
 }
 
 sub prepare_bop_content {
@@ -171,6 +197,7 @@ sub prepare_bop_content {
     $content{city}       ||= $patron->mailing_address->city;
     $content{state}      ||= $patron->mailing_address->state;
     $content{zip}        ||= $patron->mailing_address->post_code;
+    $content{country}    ||= $patron->mailing_address->country;
 
     %content;
 }
diff --git a/Open-ILS/src/sql/Pg/002.schema.config.sql b/Open-ILS/src/sql/Pg/002.schema.config.sql
index 2683cc6ed3..01fbc694d5 100644
--- a/Open-ILS/src/sql/Pg/002.schema.config.sql
+++ b/Open-ILS/src/sql/Pg/002.schema.config.sql
@@ -51,7 +51,7 @@ CREATE TABLE config.upgrade_log (
     install_date    TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW()
 );
 
-INSERT INTO config.upgrade_log (version) VALUES ('0036'); -- miker
+INSERT INTO config.upgrade_log (version) VALUES ('0037'); -- atz
 
 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 dfc32a619f..fe8b5ae96c 100644
--- a/Open-ILS/src/sql/Pg/950.data.seed-values.sql
+++ b/Open-ILS/src/sql/Pg/950.data.seed-values.sql
@@ -1693,7 +1693,55 @@ INSERT into config.org_unit_setting_type
 ( 'circ.obscure_dob',
     'Obscure the Date of Birth field',
     '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' );
+    'bool' ),
+
+( 'global.credit.processor.authorizenet.enabled',
+    'Credit card processing: Enable AuthorizeNet payments',
+    '',
+    'bool' ),
+
+( 'global.credit.processor.authorizenet.login',
+    'Credit card processing: AuthorizeNet login',
+    '',
+    'string' ),
+
+( 'global.credit.processor.authorizenet.password',
+    'Credit card processing: AuthorizeNet password',
+    '',
+    'string' ),
+
+( 'global.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 card processing: AuthorizeNet test mode',
+    '',
+    'bool' ),
+
+( 'global.credit.processor.paypal.enabled',
+    'Credit card processing: Enable PayPal payments',
+    '',
+    'bool' ),
+( 'global.credit.processor.paypal.login',
+    'Credit card processing: PayPal login',
+    '',
+    'string' ),
+( 'global.credit.processor.paypal.password',
+    'Credit card processing: PayPal password',
+    '',
+    'string' ),
+( 'global.credit.processor.paypal.signature',
+    'Credit card processing: PayPal signature',
+    '',
+    'string' ),
+( 'global.credit.processor.paypal.testmode',
+    'Credit card processing: PayPal test mode',
+    '',
+    'bool' )
+
+;
 
 -- Org_unit_setting_type(s) that need an fm_class:
 INSERT into config.org_unit_setting_type
diff --git a/Open-ILS/src/sql/Pg/upgrade/0037.data.org-setting-authorizenet-paypal.sql b/Open-ILS/src/sql/Pg/upgrade/0037.data.org-setting-authorizenet-paypal.sql
new file mode 100644
index 0000000000..25c5782ac3
--- /dev/null
+++ b/Open-ILS/src/sql/Pg/upgrade/0037.data.org-setting-authorizenet-paypal.sql
@@ -0,0 +1,55 @@
+-- org_unit setting types
+BEGIN;
+
+INSERT INTO config.upgrade_log (version) VALUES ('0037');
+
+INSERT into config.org_unit_setting_type
+( name, label, description, datatype ) VALUES
+
+( 'global.credit.processor.authorizenet.enabled',
+    'Credit card processing: Enable AuthorizeNet payments',
+    '',
+    'bool' ),
+
+( 'global.credit.processor.authorizenet.login',
+    'Credit card processing: AuthorizeNet login',
+    '',
+    'string' ),
+
+( 'global.credit.processor.authorizenet.password',
+    'Credit card processing: AuthorizeNet password',
+    '',
+    'string' ),
+
+( 'global.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 card processing: AuthorizeNet test mode',
+    '',
+    'bool' ),
+
+( 'global.credit.processor.paypal.enabled',
+    'Credit card processing: Enable PayPal payments',
+    '',
+    'bool' ),
+( 'global.credit.processor.paypal.login',
+    'Credit card processing: PayPal login',
+    '',
+    'string' ),
+( 'global.credit.processor.paypal.password',
+    'Credit card processing: PayPal password',
+    '',
+    'string' ),
+( 'global.credit.processor.paypal.signature',
+    'Credit card processing: PayPal signature',
+    '',
+    'string' ),
+( 'global.credit.processor.paypal.testmode',
+    'Credit card processing: PayPal test mode',
+    '',
+    'bool' );
+
+COMMIT;
-- 
2.11.0