#!/usr/bin/perl # # DW::Shop::Engine # # Simple interface to a payment engine. # # Authors: # Mark Smith # # Copyright (c) 2009-2010 by Dreamwidth Studios, LLC. # # This program is free software; you may redistribute it and/or modify it under # the same terms as Perl itself. For a copy of the license, please reference # 'perldoc perlartistic' or 'perldoc perlgpl'. # package DW::Shop::Engine; use strict; use DW::Shop::Engine::CheckMoneyOrder; use DW::Shop::Engine::Stripe; # get( $method, $cart ) # # returns the proper subclass for the given payment method, if one exists sub get { return DW::Shop::Engine::CheckMoneyOrder->new( $_[2] ) if $_[1] eq 'checkmoneyorder'; return DW::Shop::Engine::Stripe->new( $_[2] ) if $_[1] eq 'stripe'; warn "Payment method '$_[1]' not supported.\n"; return undef; } # temp_error( $str ) # # returns undef and sets an error string sub temp_error { my ( $self, $err, %msg ) = @_; $self->{errmsg} = LJ::Lang::ml( "error.pay.$err", \%msg ) || $err; $self->{errtemp} = 1; return undef; } # error( $ml_str ) # # returns permanent error. sub error { my ( $self, $err, %msg ) = @_; $self->{errmsg} = LJ::Lang::ml( "error.pay.$err", \%msg ) || $err; $self->{errtemp} = 0; return undef; } # errstr() # # returns the text of the last error sub errstr { return $_[0]->{errmsg}; } # err() # # returns 1/0 if we had an error sub err { return defined $_[0]->{errtemp} ? 1 : 0; } # err_is_temporary() # # returns 1/0 if the error is classified as temporary and you should retry, # also returns undef if no error has occurred. sub err_is_temporary { return $_[0]->{errtemp}; } # fail_transaction() # # this is a 'something bad has happened, consider this cart and transaction # to be dead' sort of thing sub fail_transaction { die "Please implement $_[0]" . "->fail_transaction.\n"; } # called when someone wants us to try to capture the points # FIXME: should move the 'cart' accessor and logic up to this base class ... sub try_capture_points { my $self = $_[0]; # if the order costs no points, we're done and successful return 1 unless $self->cart->total_points > 0; # else, we need to try to capture them my $u = LJ::load_userid( $self->cart->userid ) or die "Failed to load user to deduct points from.\n"; $u->give_shop_points( amount => -$self->cart->total_points, reason => sprintf( 'order %d confirmed', $self->cart->id ) ) or die "Failed to deduct points from account.\n"; # we're a happy clam return 1; } # called to give back the points that we took from the user in case another # part of the transaction has failed sub refund_captured_points { my $self = $_[0]; # if the order costs no points, we're done and successful return 1 unless $self->cart->total_points > 0; # else, we need to try to capture them my $u = LJ::load_userid( $self->cart->userid ) or die "Failed to load user to restore points to; contact site administrators.\n"; $u->give_shop_points( amount => $self->cart->total_points, reason => sprintf( 'order %d failed', $self->cart->id ) ) or die "Failed to add points to account.\n"; # we're a happy clam return 1; } 1;