From c4b977c290535bf7b3b1455b16d0fbe0c7719e5b Mon Sep 17 00:00:00 2001 From: Lebbeous Fogle-Weekley Date: Thu, 19 Sep 2013 13:19:19 -0400 Subject: [PATCH] More code reshuffling in support of Stripe. Compiles, but testing to come. Signed-off-by: Lebbeous Fogle-Weekley --- .../lib/OpenILS/Application/Circ/CreditCard.pm | 12 --- .../perlmods/lib/OpenILS/Application/Circ/Money.pm | 97 +++++++++++++++++----- 2 files changed, 76 insertions(+), 33 deletions(-) diff --git a/Open-ILS/src/perlmods/lib/OpenILS/Application/Circ/CreditCard.pm b/Open-ILS/src/perlmods/lib/OpenILS/Application/Circ/CreditCard.pm index f7944e37fb..2c6183077e 100644 --- a/Open-ILS/src/perlmods/lib/OpenILS/Application/Circ/CreditCard.pm +++ b/Open-ILS/src/perlmods/lib/OpenILS/Application/Circ/CreditCard.pm @@ -76,18 +76,6 @@ sub bop_args_PayflowPro { ); } -sub get_processor_settings { - my $org_unit = shift; - my $processor = lc shift; - - # XXX TODO: make this one single cstore request instead of many - +{ map { ($_ => - $U->ou_ancestor_setting_value( - $org_unit, "credit.processor.${processor}.${_}" - )) } qw/enabled login password signature server testmode vendor partner/ - }; -} - # argshash (Hash of arguments with these keys): # patron_id: Not a barcode, but a patron's internal ID # ou: Org unit where transaction happens diff --git a/Open-ILS/src/perlmods/lib/OpenILS/Application/Circ/Money.pm b/Open-ILS/src/perlmods/lib/OpenILS/Application/Circ/Money.pm index d83a5c120f..32e4417daf 100644 --- a/Open-ILS/src/perlmods/lib/OpenILS/Application/Circ/Money.pm +++ b/Open-ILS/src/perlmods/lib/OpenILS/Application/Circ/Money.pm @@ -27,8 +27,36 @@ use OpenILS::Event; use OpenSRF::Utils::Logger qw/:logger/; use OpenILS::Utils::CStoreEditor qw/:funcs/; use OpenILS::Utils::Penalty; +use Business::Stripe; $Data::Dumper::Indent = 0; +sub get_processor_settings { + my $e = shift; + my $org_unit = shift; + my $processor = lc shift; + + # Get the names of every credit processor setting for our given processor. + # They're a little different per processor. + my $setting_names = $e->json_query({ + select => {coust => ["name"]}, + from => {coust => {}}, + where => {name => {like => 'credit.processor.${processor}.%'}} + }) or return $e->die_event; + + # Make keys for a hash we're going to build out of the last dot-delimited + # component of each setting name. + ($_->{key} = $_->{name}) =~ s/.+\.(\w+)$/$1/ for @$setting_names; + + # Return a hash with those short keys, and for values the value of + # the corresponding OU setting within our scope. + return { + map { + $_->{key} => $U->ou_ancestor_setting_value($org_unit, $_->{name}) + } @$setting_names + }; +} + +# process_stripe_or_bop_payment() # This is a helper method to make_payments() below (specifically, # the credit-card part). It's the first point in the Perl code where # we need to care about the distinction between Stripe and the @@ -37,10 +65,10 @@ $Data::Dumper::Indent = 0; # B::OP and doesn't require us to know anything about the payment card # info). # -# Return an event for failure, non-event hash from payment processor for -# success. +# Return an event in all cases. That means a success returns a SUCCESS +# event. sub process_stripe_or_bop_payment { - my ($user_id, $this_ou, $total_paid, $cc_args) = @_; + my ($e, $user_id, $this_ou, $total_paid, $cc_args) = @_; # A few stanzas to determine which processor we're using and whether we're # really adequately set up for it. @@ -52,23 +80,45 @@ sub process_stripe_or_bop_payment { } } + # Make sure the configured credit processor has a safe/correct name. return OpenILS::Event->new('CREDIT_PROCESSOR_NOT_ALLOWED') unless $cc_args->{processor} =~ /^[a-z0-9_\-]+$/i; - # XXX TODO: the following line doesn't even compile because get_procsesor_settings() is in the CreditCard package, not this one, and it also won't *work* yet because it looks for settings shaped like they are for the BOP processors, and it needs to be different for stripe. This is my very next TODO. - my $psettings = get_processor_settings(@{$cc_args}{'ou', 'processor'}); - + # Get the settings for the processor and make sure they're serviceable. + my $psettings = get_processor_settings($e, @{$cc_args}{'ou', 'processor'}); + return $psettings if defined $U->event_code($psettings); return OpenILS::Event->new('CREDIT_PROCESSOR_NOT_ENABLED') unless $psettings->{enabled}; # Now we branch. Stripe is one thing, and everything else is another. - if ($cc_args->{processor} eq 'Stripe') { - # Stripe - # XXX TODO - return OpenILS::Event->new('BAD_PARAMS', note => 'Stripe is XXX TODO'); - } else { - # B::OP style (Paypal/PayflowPro/AuthorizeNet) + if ($cc_args->{processor} eq 'Stripe') { # Stripe + my $stripe = Business::Stripe->new(-api_key => $psettings->{secretkey}); + $stripe->charges_create( + amount => $total_paid, + card => $cc_args->{stripe_token}, + description => $cc_args->{note} + ); + + if ($stripe->success) { + $logger->info("Stripe payment succeeded"); + return OpenILS::Event->new( + "SUCCESS", payload => { + map { $_ => $stripe->success->{$_} } qw( + invoice customer balance_transaction id created + ) + } + ); + } else { + $logger->info("Stripe payment failed"); + return OpenILS::Event->new( + "CREDIT_PROCESSOR_DECLINED_TRANSACTION", + payload => $stripe->error # XXX what happens if this contains + # JSON::backportPP::* objects? + ); + } + + } else { # B::OP style (Paypal/PayflowPro/AuthorizeNet) return OpenILS::Event->new('BAD_PARAMS', note => 'Need CC number') unless $cc_args->{number}; @@ -332,10 +382,10 @@ sub make_payments { # to call to the payment processor ourselves. if ($cc_args->{where_process} == 1) { my $response = process_stripe_or_bop_payment( - $user_id, $this_ou, $total_paid, $cc_args + $e, $user_id, $this_ou, $total_paid, $cc_args ); - if ($U->event_code($response)) { # non-success + if ($U->event_code($response)) { # non-success (success is 0) $logger->info( "Credit card payment for user $user_id failed: " . $response->{"textcode"} . " " . @@ -345,13 +395,18 @@ sub make_payments { # We need to save this for later in case there's a failure on # the EG side to store the processor's result. - # XXX TODO generalize this for Stripe as well as for B::OP style - $cc_payload = $response->{"payload"}; - - $approval_code = $cc_payload->{"authorization"}; - $cc_type = $cc_payload->{"card_type"}; - $cc_processor = $cc_payload->{"processor"}; - $cc_order_number = $cc_payload->{"order_number"}; + $cc_payload = $response->{"payload"}; # also used way later + + { + no warnings 'uninitialized'; + $cc_type = $cc_payload->{card_type}; + $approval_code = $cc_payload->{authorization} || + $cc_payload->{id}; + $cc_processor = $cc_payload->{processor} || + $cc_args->{processor}; + $cc_order_number = $cc_payload->{order_number} || + $cc_payload->{invoice}; + }; $logger->info("Credit card payment for user $user_id succeeded"); } } else { -- 2.11.0