mark: A photo of Mark kneeling on top of the Taal Volcano in the Philippines. It was a long hike. (Default)
Mark Smith ([staff profile] mark) wrote in [site community profile] changelog2009-04-25 08:36 am

[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 [staff profile] mark.

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?>
--------------------------------------------------------------------------------

Post a comment in response:

This account has disabled anonymous posting.
If you don't have an account you can create one now.
HTML doesn't work in the subject.
More info about formatting

If you are unable to use this captcha for any reason, please contact us by email at support@dreamwidth.org