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
# 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.
}
}
+ # 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};
# 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"} . " " .
# 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 {