[dw-free] Finishing up payment system
[commit: http://hg.dwscoalition.org/dw-free/rev/940894138179]
http://bugs.dwscoalition.org/show_bug.cgi?id=116
Add CheckMoneyOrder engine and confirmation page.
Patch by
mark.
Files modified:
http://bugs.dwscoalition.org/show_bug.cgi?id=116
Add CheckMoneyOrder engine and confirmation page.
Patch by
![[staff profile]](https://www.dreamwidth.org/img/silk/identity/user_staff.png)
Files modified:
- bin/upgrading/en.dat
- cgi-bin/DW/Shop/Engine.pm
- cgi-bin/DW/Shop/Engine/CheckMoneyOrder.pm
- htdocs/shop/cmo_confirm.bml
-------------------------------------------------------------------------------- diff -r d48debea245b -r 940894138179 bin/upgrading/en.dat --- a/bin/upgrading/en.dat Sat Apr 25 07:40:00 2009 +0000 +++ b/bin/upgrading/en.dat Sat Apr 25 08:36:53 2009 +0000 @@ -1351,6 +1351,8 @@ error.pay.dberr=Database error: [[errstr error.pay.dberr=Database error: [[errstr]]. Please try again later. error.pay.nodb=Failed to connect to database. Please try again later. + +error.pay.cmo.engbadstate=Payment engine is in a bad state. Please try your order again. error.pay.paypal.connection=Temporary failure connecting to PayPal. Please try again later. diff -r d48debea245b -r 940894138179 cgi-bin/DW/Shop/Engine.pm --- a/cgi-bin/DW/Shop/Engine.pm Sat Apr 25 07:40:00 2009 +0000 +++ b/cgi-bin/DW/Shop/Engine.pm Sat Apr 25 08:36:53 2009 +0000 @@ -17,6 +17,7 @@ package DW::Shop::Engine; package DW::Shop::Engine; use strict; +use DW::Shop::Engine::CheckMoneyOrder; use DW::Shop::Engine::PayPal; # get( $method, $cart ) @@ -24,6 +25,7 @@ use DW::Shop::Engine::PayPal; # returns the proper subclass for the given payment method, if one exists sub get { return DW::Shop::Engine::PayPal->new( $_[2] ) if $_[1] eq 'paypal'; + return DW::Shop::Engine::CheckMoneyOrder->new( $_[2] ) if $_[1] eq 'checkmoneyorder'; warn "Payment method '$_[1]' not supported.\n"; return undef; diff -r d48debea245b -r 940894138179 cgi-bin/DW/Shop/Engine/CheckMoneyOrder.pm --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/cgi-bin/DW/Shop/Engine/CheckMoneyOrder.pm Sat Apr 25 08:36:53 2009 +0000 @@ -0,0 +1,102 @@ +#!/usr/bin/perl +# +# DW::Shop::Engine::CheckMoneyOrder +# +# This engine lets the user pay via check/money order. +# +# Authors: +# Mark Smith <mark@dreamwidth.org> +# +# Copyright (c) 2009 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::CheckMoneyOrder; + +use strict; +use Carp qw/ croak confess /; +use Storable qw/ nfreeze thaw /; + +use base qw/ DW::Shop::Engine /; + + +# new( $cart ) +# +# instantiates a new PayPal engine for the given cart +sub new { + return bless { cart => $_[1] }, $_[0]; +} + + +# new_from_cart( $cart ) +# +# constructs an engine from a given cart. doesn't really do much +# more than call new() as that's the default +sub new_from_cart { + return $_[0]->new( $_[1] ); +} + + +# checkout_url() +# +# given a shopping cart full of Stuff, build a URL for us to send the user to +# to initiate the checkout process. +sub checkout_url { + my $self = $_[0]; + + # make sure that the cart contains something that costs something. since + # this check should have been done above, we die hardcore here. + my $cart = $self->cart; + die "Constraints not met: cart && cart->has_items && cart->has_total > 0.00.\n" + unless $cart && $cart->has_items && $cart->total > 0.00; + + # and, just in case something terrible happens, make sure our state is good + die "Cart not in valid state!\n" + unless $cart->state == $DW::Shop::STATE_OPEN; + + # the cart is in a good state, so just send them to the confirmation page which + # gives them instructions on where to send it + return "$LJ::SITEROOT/shop/cmo_confirm"; +} + + +# confirm_order() +# +# all this does is mark the order as pending. +sub confirm_order { + my $self = $_[0]; + + # ensure the cart is in checkout state. if it's still open or paid + # or something, we can't touch it. + return $self->error( 'cmo.engbadstate' ) + unless $self->cart->state == $DW::Shop::STATE_CHECKOUT; + + # now set it pending + $self->cart->state( $DW::Shop::STATE_PEND_PAID ); + return 2; +} + + +# called when something terrible has happened and we need to fully fail out +# a transaction for some reason. (payment not valid, etc.) +sub fail_transaction { + my $self = $_[0]; + + # step 1) mark statuses +# $self->cart-> +} + + +################################################################################ +## internal methods, nobody else should be calling these +################################################################################ + + +# accessors +sub cart { $_[0]->{cart} } + + +1; diff -r d48debea245b -r 940894138179 htdocs/shop/cmo_confirm.bml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/htdocs/shop/cmo_confirm.bml Sat Apr 25 08:36:53 2009 +0000 @@ -0,0 +1,76 @@ +<?_c + +# +# shop/cmo_confirm.bml +# +# For users paying by check/money order to confirm. +# +# Authors: +# Mark Smith <mark@dreamwidth.org> +# +# Copyright (c) 2009 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'. +# + +_c?><?page +title=>Confirm Your Payment +body<= +<?_code +{ + use strict; + use vars qw(%GET %POST); + + return BML::redirect( "$LJ::SITEROOT/" ) + unless LJ::is_enabled( 'payments' ); + + my $cart = DW::Shop->get->cart + or return 'you do not seem to have a cart'; + my $eng = DW::Shop::Engine::CheckMoneyOrder->new_from_cart( $cart ); + return 'sorry, invalid cart' + unless $eng; + + my $ordernum = $eng->cart->ordernum; + + # cart must be in open state + return BML::redirect( "$LJ::SITEROOT/shop/cmo_receipt?ordernum=$ordernum" ) + unless $eng->cart->state == $DW::Shop::STATE_OPEN; + + # if they didn't post, give them a form + unless ( LJ::did_post() ) { + my $ret = ''; + $ret .= LJ::Widget::ShopCart->render( receipt => 1, cart => $eng->cart ); + $ret .= "<form method='post' action='$LJ::SITEROOT/shop/cmo_confirm?ordernum=$ordernum'>\n"; + $ret .= LJ::form_auth(); + $ret .= "<?p Please confirm that you wish to place the above order to $LJ::SITENAME in the amount of "; + $ret .= "\$". $eng->cart->display_total . ' USD. Once you confirm this order, you will need to write a '; + $ret .= "check or money order and mail it to: some address, somewhere. p?>"; + $ret .= '<div style="width: 350px;"><input style="float: left;" type="submit" value="Confirm Purchase" /> '; + $ret .= "<div style='float: right;'><a href='/shop/cmo_cancel?ordernum=$ordernum'>Cancel Purchase</a></div></div>"; + $ret .= '</form>'; + return $ret; + } + + # okay, they posted, verify the auth code and + return 'invalid form auth' + unless LJ::check_form_auth(); + + # and now set the state, this has been checked out... + $eng->cart->state( $DW::Shop::STATE_CHECKOUT ); + + # they want to pay us, yippee! + my $rv = $eng->confirm_order; + return $eng->errstr + unless $rv; + + # advise them the order has been placed and to watch their email + if ( $rv == 2 ) { + return '<?p Your order has been successfully placed. Please remember to mail your check! p?><?p ' . + "<a href='$LJ::SITEROOT/shop/cmo_receipt?ordernum=$ordernum'>View Receipt</a> p?>"; + } +} +_code?> +<=body +page?> --------------------------------------------------------------------------------