Patch from Lebbeous Fogle-Weekley which integrates credit card payments into the...
authorerickson <erickson@dcc99617-32d9-48b4-a31d-7c20da2025e4>
Mon, 19 Oct 2009 15:44:32 +0000 (15:44 +0000)
committererickson <erickson@dcc99617-32d9-48b4-a31d-7c20da2025e4>
Mon, 19 Oct 2009 15:44:32 +0000 (15:44 +0000)
git-svn-id: svn://svn.open-ils.org/ILS/trunk@14492 dcc99617-32d9-48b4-a31d-7c20da2025e4

Open-ILS/src/extras/ils_events.xml
Open-ILS/src/perlmods/OpenILS/Application/Circ/Money.pm
Open-ILS/src/perlmods/OpenILS/Application/CreditCard.pm
Open-ILS/src/sql/Pg/002.schema.config.sql
Open-ILS/src/sql/Pg/950.data.seed-values.sql
Open-ILS/src/sql/Pg/upgrade/0038.data.org-setting-credit-default-proc.sql [new file with mode: 0644]
Open-ILS/src/support-scripts/test-scripts/payment_test.pl

index 696d36a..56c40da 100644 (file)
                <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>
 
 
index 0d27690..9b15e55 100644 (file)
@@ -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;
index 7250c9f..bd1a845 100644 (file)
@@ -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;
index 01fbc69..b686236 100644 (file)
@@ -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,
index 679a24f..bf1ada0 100644 (file)
@@ -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 (file)
index 0000000..b20237b
--- /dev/null
@@ -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;
index bb8fc30..41ece54 100644 (file)
@@ -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,