Initial support for Google Checkout as a merchant processor.
Patch by mark.
diffs (621 lines):
diff -r 4660678283bb -r f30c9dfe7830 bin/upgrading/en.dat
--- a/bin/upgrading/en.dat Tue Feb 02 06:56:18 2010 +0000
+++ b/bin/upgrading/en.dat Wed Feb 03 01:21:16 2010 +0000
@@ -4595,6 +4595,8 @@ widget.shopcart.paymentmethod.checkmoney
widget.shopcart.paymentmethod.creditcardpp=Credit Card
+widget.shopcart.paymentmethod.gco=Google Checkout Account
+
widget.shopcart.paymentmethod.paypal=PayPal Account
widget.shopcart.total=Total:
diff -r 4660678283bb -r f30c9dfe7830 bin/upgrading/update-db-general.pl
--- a/bin/upgrading/update-db-general.pl Tue Feb 02 06:56:18 2010 +0000
+++ b/bin/upgrading/update-db-general.pl Wed Feb 03 01:21:16 2010 +0000
@@ -2867,6 +2867,30 @@ CREATE table externalaccount (
)
EOC
+register_tablecreate('gco_log', <<'EOC');
+CREATE TABLE gco_log (
+ gcoid bigint unsigned not null,
+ ip varchar(15) not null,
+ transtime int unsigned not null,
+ req_content text not null,
+
+ index (gcoid)
+)
+EOC
+
+register_tablecreate('gco_map', <<'EOC');
+CREATE TABLE gco_map (
+ gcoid bigint unsigned not null,
+ cartid int unsigned not null,
+
+ email varchar(255),
+ contactname varchar(255),
+
+ index (gcoid),
+ unique (cartid)
+)
+EOC
+
register_tablecreate('pp_tokens', <<'EOC');
CREATE TABLE pp_tokens (
ppid int unsigned not null auto_increment,
diff -r 4660678283bb -r f30c9dfe7830 cgi-bin/DW/Shop.pm
--- a/cgi-bin/DW/Shop.pm Tue Feb 02 06:56:18 2010 +0000
+++ b/cgi-bin/DW/Shop.pm Wed Feb 03 01:21:16 2010 +0000
@@ -85,6 +85,10 @@ our %PAYMENTMETHODS = (
id => 3,
class => 'CreditCardPP',
},
+ gco => {
+ id => 4,
+ class => 'GoogleCheckout',
+ },
);
diff -r 4660678283bb -r f30c9dfe7830 cgi-bin/DW/Shop/Engine.pm
--- a/cgi-bin/DW/Shop/Engine.pm Tue Feb 02 06:56:18 2010 +0000
+++ b/cgi-bin/DW/Shop/Engine.pm Wed Feb 03 01:21:16 2010 +0000
@@ -20,12 +20,14 @@ use DW::Shop::Engine::CheckMoneyOrder;
use DW::Shop::Engine::CheckMoneyOrder;
use DW::Shop::Engine::CreditCardPP;
use DW::Shop::Engine::PayPal;
+use DW::Shop::Engine::GoogleCheckout;
# get( $method, $cart )
#
# 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::GoogleCheckout->new( $_[2] ) if $_[1] eq 'gco';
return DW::Shop::Engine::CreditCardPP->new( $_[2] ) if $_[1] eq
'creditcardpp';
return DW::Shop::Engine::CheckMoneyOrder->new( $_[2] ) if $_[1] eq
'checkmoneyorder';
diff -r 4660678283bb -r f30c9dfe7830 cgi-bin/DW/Shop/Engine/CheckMoneyOrder.pm
--- a/cgi-bin/DW/Shop/Engine/CheckMoneyOrder.pm Tue Feb 02 06:56:18 2010 +0000
+++ b/cgi-bin/DW/Shop/Engine/CheckMoneyOrder.pm Wed Feb 03 01:21:16 2010 +0000
@@ -26,7 +26,7 @@ use base qw/ DW::Shop::Engine /;
# new( $cart )
#
-# instantiates a new PayPal engine for the given cart
+# instantiates a new CMO engine for the given cart
sub new {
return bless { cart => $_[1] }, $_[0];
}
@@ -111,7 +111,7 @@ sub cancel_order {
my $self = $_[0];
# ensure the cart is in open state
- return $self->error( 'paypal.engbadstate' )
+ return $self->error( 'cmo.engbadstate' )
unless $self->cart->state == $DW::Shop::STATE_OPEN;
return 1;
diff -r 4660678283bb -r f30c9dfe7830 cgi-bin/DW/Shop/Engine/GoogleCheckout.pm
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/cgi-bin/DW/Shop/Engine/GoogleCheckout.pm Wed Feb 03 01:21:16 2010 +0000
@@ -0,0 +1,259 @@
+#!/usr/bin/perl
+#
+# DW::Shop::Engine::GoogleCheckout
+#
+# The interface to Google Checkout's flow. Responsible for doing all of the
+# work to talk to this merchant processor.
+#
+# Authors:
+# Mark Smith <[email protected]>
+#
+# Copyright (c) 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::GoogleCheckout;
+
+use strict;
+use Carp qw/ croak confess /;
+use Storable qw/ nfreeze thaw /;
+use Google::Checkout::General::GCO;
+use Google::Checkout::General::MerchantCheckoutFlow;
+use Google::Checkout::General::DigitalContent;
+use Google::Checkout::General::ShoppingCart;
+use Google::Checkout::Command::ChargeOrder;
+use Google::Checkout::General::Util qw/ is_gco_error /;
+
+use base qw/ DW::Shop::Engine /;
+
+
+# new( $cart )
+#
+# instantiates a new GCO engine for the given cart
+sub new {
+ return bless { cart => $_[1] }, $_[0];
+}
+
+
+# new_from_cart( $cart )
+#
+# constructs an engine from a given cart.
+sub new_from_cart {
+ my ( $class, $cart ) = @_;
+
+ my $dbh = DW::Pay::get_db_writer()
+ or die "Database temporarily unavailable.\n"; # no object yet
+
+ my ( $gcoid, $cn, $em ) =
+ $dbh->selectrow_array( 'SELECT gcoid, contactname, email FROM gco_map
WHERE cartid = ?', undef, $cart->id );
+
+ # if they have no row in the database, then this is a new cart that hasn't
+ # yet really been through the flow
+ return bless { cart => $cart }, $class
+ unless $gcoid;
+
+ # it HAS, we have a row, so populate with all of the data we have
+ return bless {
+ gcoid => $gcoid,
+ contactname => $cn,
+ email => $em,
+ cart => $cart,
+ }, $class;
+}
+
+
+# new_from_gcoid( $gcoid )
+#
+# constructs an engine from a given google order number.
+sub new_from_gcoid {
+ my ( $class, $gcoid ) = @_;
+
+ my $dbh = DW::Pay::get_db_writer()
+ or die "Database temporarily unavailable.\n"; # no object yet
+
+ my ( $cartid, $cn, $em ) =
+ $dbh->selectrow_array( 'SELECT cartid, contactname, email FROM gco_map
WHERE gcoid = ?', undef, $gcoid );
+
+ my $cart = DW::Shop::Cart->get_from_cartid( $cartid )
+ or die "Unable to load cart from Google Order Number $gcoid.\n";
+
+ # it HAS, we have a row, so populate with all of the data we have
+ return bless {
+ gcoid => $gcoid,
+ contactname => $cn,
+ email => $em,
+ cart => $cart,
+ }, $class;
+}
+
+
+# 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;
+
+ # flow for this particular order
+ my $flow = Google::Checkout::General::MerchantCheckoutFlow->new(
+ edit_cart_url => "$LJ::SITEROOT/shop/cart",
+ continue_shopping_url => "$LJ::SITEROOT/shop",
+ buyer_phone => 'false',
+ );
+
+ # and now build us a cart
+ my $gcart = Google::Checkout::General::ShoppingCart->new(
+ expiration => "+1 month",
+ private => $cart->id,
+ checkout_flow => $flow,
+ );
+
+ # now we have to stick in data for each of the items in the cart
+ foreach my $item ( @{ $cart->items } ) {
+ my $gitem = Google::Checkout::General::DigitalContent->new(
+ name => $item->class_name,
+ description => $item->short_desc,
+ price => $item->cost,
+ quantity => 1,
+ private => $item->id,
+ delivery_method =>
Google::Checkout::General::DigitalContent::EMAIL_DELIVERY,
+ );
+
+ $gcart->add_item( $gitem );
+ }
+
+ # now get a URL from Google, or try
+ my $res = $self->gco->checkout( $gcart );
+ return $self->error( "Google Checkout Error: $res" )
+ if is_gco_error $res;
+
+ # and finally, this is the URL!
+ return $res;
+}
+
+
+# cancel_order()
+#
+# cancels the order and doesn't send any money
+sub cancel_order {
+ # does not apply to this payment system ...
+ die "Does not apply to Google Checkout.\n";
+}
+
+
+# this sends the command to Google Checkout to actually charge the order. it
must
+# be open and have a GON/GCOID which means it went through the new order flow.
+sub charge_order {
+ my $self = $_[0];
+ return
+ unless $self->gcoid > 0 &&
+ $self->cart->state == $DW::Shop::STATE_OPEN;
+
+ my $charge_order = Google::Checkout::Command::ChargeOrder->new(
+ order_number => $self->gcoid,
+ amount => $self->cart->display_total,
+ );
+
+ my $response = $self->gco->command( $charge_order );
+ die "Failed to charge order: $response\n"
+ if is_gco_error $response;
+
+ # we are now pending payment for this cart ...
+ $self->cart->state( $DW::Shop::STATE_PEND_PAID );
+}
+
+
+# called by the system when we get a posted notification of some sort
+sub process_notification {
+ my ( $class, $form ) = @_;
+
+ # if no order number, invalid!
+ my $gon = $form->{'google-order-number'}
+ or return;
+
+ # log the request
+ my $dbh = DW::Pay::get_db_writer()
+ or die "failed, please retry later\n";
+ $dbh->do(
+ q{INSERT INTO gco_log (gcoid, ip, transtime, req_content)
+ VALUES (?, ?, UNIX_TIMESTAMP(), ?)},
+ undef, $gon, BML::get_remote_ip(), nfreeze( $form )
+ );
+ die "failed to insert: " . $dbh->errstr . "\n"
+ if $dbh->err;
+
+ # now that it's logged, we can do some processing depending on what type
it is
+ if ( $form->{_type} eq 'new-order-notification' ) {
+ my $cart = DW::Shop::Cart->get_from_cartid( $1 )
+ if $form->{'shopping-cart.merchant-private-data'} =~
m!note>(\d+)</merch!;
+
+ # now ensure the cart is good ...
+ return 1
+ unless $cart &&
+ $cart->state == $DW::Shop::STATE_OPEN &&
+ $cart->paymentmethod eq 'gco' &&
+ $cart->display_total == $form->{'order-total'};
+
+ $dbh->do(
+ q{INSERT INTO gco_map (gcoid, cartid, email, contactname)
+ VALUES (?, ?, ?, ?)},
+ undef, $gon, $cart->id, $form->{'buyer-billing-address.email'},
$form->{'buyer-billing-address.contact-name'}
+ );
+ die "failed to update gco_map: " . $dbh->errstr . "\n"
+ if $dbh->err;
+
+ # we need to actually charge the order now ...
+ my $eng = $class->new_from_gcoid( $gon )
+ or die "failed to load engine for Google Order Number $gon\n";
+ $eng->charge_order;
+
+ # if we actually captured some money, then we need to make sure that the
order
+ # gets to be marked as ready to go
+ } elsif ( $form->{_type} eq 'charge-amount-notification' ) {
+ my $eng = $class->new_from_gcoid( $gon )
+ or die "failed to load engine for Google Order Number $gon\n";
+
+ # sanity check again, make sure our cart still looks good
+ return 1
+ unless $eng->cart->state == $DW::Shop::STATE_PEND_PAID &&
+ $eng->cart->paymentmethod eq 'gco' &&
+ $eng->cart->display_total == $form->{'total-charge-amount'};
+
+ # looks good, mark it paid so it gets processed
+ $eng->cart->state( $DW::Shop::STATE_PAID );
+
+ # NOTE: do not send an email here. Google requests that people who
implement
+ # Google Checkout do not actually send a confirmation email, as they
will
+ # take care of that when the user places the order, and one email
should be
+ # enough for most purposes.
+ }
+}
+
+
+# accessors
+sub gcoid { $_[0]->{gcoid} }
+sub cart { $_[0]->{cart} }
+sub contactname { $_[0]->{contactname} }
+sub email { $_[0]->{email} }
+
+
+# returns a Google Checkout object with our proper server configuration
+sub gco {
+ return Google::Checkout::General::GCO->new( config_path =>
"$LJ::HOME/etc/google-checkout.conf" );
+}
+
+
+1;
diff -r 4660678283bb -r f30c9dfe7830 cgi-bin/LJ/Widget/ShopCart.pm
--- a/cgi-bin/LJ/Widget/ShopCart.pm Tue Feb 02 06:56:18 2010 +0000
+++ b/cgi-bin/LJ/Widget/ShopCart.pm Wed Feb 03 01:21:16 2010 +0000
@@ -97,34 +97,32 @@ sub render_body {
}
$ret .= "</tr>";
}
- $ret .= "<tr><td colspan='" . $colspan . "' class='total'>" . $class->ml(
'widget.shopcart.total' ) . " \$" . $cart->display_total . " USD</td></tr>";
+
+ my $buttons = ' ';
+ unless ( $opts{receipt} ) {
+ $buttons = $class->html_submit( removeselected => $class->ml(
'widget.shopcart.btn.removeselected' ) ) . " " .
+ $class->html_submit( discard => $class->ml(
'widget.shopcart.btn.discard' ) ) . "</p>";
+ }
+
+ $ret .= "<tr><td class='total' style='border-right: none; text-align:
left;' colspan='3'>$buttons</td>";
+ $ret .= "<td style='border-left: none;' colspan='" . ($colspan-3) .
+ "' class='total'>" . $class->ml( 'widget.shopcart.total' ) . " \$"
. $cart->display_total . " USD</td></tr>";
$ret .= "</table>";
unless ( $opts{receipt} ) {
- $ret .= "<div class='shop-cart-btn'>";
+ $ret .= "<div class='shop-cart-btn'><p>";
- $ret .= "<p>" . $class->html_submit( removeselected => $class->ml(
'widget.shopcart.btn.removeselected' ) ) . " ";
- $ret .= $class->html_submit( discard => $class->ml(
'widget.shopcart.btn.discard' ) ) . "</p>";
+ # google has very specific rules about where the buttons go and how to
display them
+ # ... so we have to abide by that
+ if ( LJ::is_enabled( 'googlecheckout' ) ) {
+ $ret .= '<input type="image" name="' . $class->input_prefix .
'_checkout_gco" src="https://checkout.google.com/buttons/checkout.gif?' .
+
'merchant_id=&w=180&h=46&style=trans&variant=text&loc=en_US" alt="Use Google
Checkout" style="vertical-align: middle;" /> or use ';
+ }
- my @paypal_option;
- @paypal_option = (
- paypal => $class->ml( 'widget.shopcart.paymentmethod.paypal' ),
- creditcardpp => $class->ml(
'widget.shopcart.paymentmethod.creditcardpp' ),
- )
- if keys %LJ::PAYPAL_CONFIG;
- $ret .= "<p>" . $class->ml( 'widget.shopcart.paymentmethod' ) . " ";
- $ret .= $class->html_select(
- name => 'paymentmethod',
- selected => keys %LJ::PAYPAL_CONFIG ? 'paypal' : 'checkmoneyorder',
- list => [
- @paypal_option,
- checkmoneyorder => $class->ml(
'widget.shopcart.paymentmethod.checkmoneyorder' ),
- ],
- ) . " ";
- $ret .= $class->html_submit( checkout => $class->ml(
'widget.shopcart.btn.checkout' ) ) . "</p>";
+ # check or money order button
+ $ret .= $class->html_submit( checkout_cmo => $class->ml(
'widget.shopcart.paymentmethod.checkmoneyorder' ) );
- $ret .= "</div>";
-
+ $ret .= "</p></div>";
$ret .= $class->end_form
}
@@ -134,9 +132,14 @@ sub handle_post {
sub handle_post {
my ( $class, $post, %opts ) = @_;
- # check out
- return BML::redirect(
"$LJ::SITEROOT/shop/checkout?method=$post->{paymentmethod}" )
- if $post->{checkout};
+ # checkout methods depend on which button was clicked
+ my $cm;
+ $cm = 'gco' if LJ::is_enabled( 'googlecheckout' ) && (
$post->{checkout_gco} || $post->{'checkout_gco.x'} );
+ $cm = 'checkmoneyorder' if $post->{checkout_cmo};
+
+ # check out?
+ return BML::redirect( "$LJ::SITEROOT/shop/checkout?method=$cm" )
+ if defined $cm;
# remove selected items
if ( $post->{removeselected} ) {
diff -r 4660678283bb -r f30c9dfe7830 doc/config-local.pl.txt
--- a/doc/config-local.pl.txt Tue Feb 02 06:56:18 2010 +0000
+++ b/doc/config-local.pl.txt Wed Feb 03 01:21:16 2010 +0000
@@ -51,21 +51,22 @@
private_key => $DW::PRIVATE::RECAPTCHA{private_key},
);
- # PayPal configuration
- %PAYPAL_CONFIG = (
- # express checkout URL, the token gets appended to this
- url =>
'https://www.sandbox.paypal.com/cgi-bin/webscr?cmd=_express-checkout&token=',
- api_url => 'https://api-3t.sandbox.paypal.com/nvp',
+ # PayPal configuration. If you want to use PayPal, uncomment this
+ # section and make sure to fill in the fields at the bottom of
config-private.pl.
+ #%PAYPAL_CONFIG = (
+ # # express checkout URL, the token gets appended to this
+ # url =>
'https://www.sandbox.paypal.com/cgi-bin/webscr?cmd=_express-checkout&token=',
+ # api_url => 'https://api-3t.sandbox.paypal.com/nvp',
- # credentials for the API
- user => $DW::PRIVATE::PAYPAL{user},
- password => $DW::PRIVATE::PAYPAL{password},
- signature => $DW::PRIVATE::PAYPAL{signature},
+ # # credentials for the API
+ # user => $DW::PRIVATE::PAYPAL{user},
+ # password => $DW::PRIVATE::PAYPAL{password},
+ # signature => $DW::PRIVATE::PAYPAL{signature},
- # set this to someone who is responsible for getting emails about
- # various PayPal related events
- email => $DW::PRIVATE::PAYPAL{email},
- );
+ # # set this to someone who is responsible for getting emails about
+ # # various PayPal related events
+ # email => $DW::PRIVATE::PAYPAL{email},
+ # );
# if you define these, little help bubbles appear next to common
# widgets to the URL you define:
diff -r 4660678283bb -r f30c9dfe7830 doc/google-checkout.conf.txt
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/google-checkout.conf.txt Wed Feb 03 01:21:16 2010 +0000
@@ -0,0 +1,10 @@
+# Change these.
+MERCHANT_ID = 1234
+MERCHANT_KEY = abcd
+BASE_GCO_SERVER = https://sandbox.google.com/checkout/cws/v2/Merchant
+
+# Do not change.
+XML_SCHEMA = http://checkout.google.com/schema/2
+CURRENCY_SUPPORTED = USD
+XML_VERSION = 1.0
+XML_ENCODING = UTF-8
diff -r 4660678283bb -r f30c9dfe7830 etc/config.pl
--- a/etc/config.pl Tue Feb 02 06:56:18 2010 +0000
+++ b/etc/config.pl Wed Feb 03 01:21:16 2010 +0000
@@ -183,6 +183,7 @@
eventlogrecord => 1,
feedster_search => 0,
free_create => 1,
+ googlecheckout => 1,
'interests-findsim' => 0,
memories => 0,
opt_findbyemail => 1,
diff -r 4660678283bb -r f30c9dfe7830 htdocs/admin/pay/view.bml
--- a/htdocs/admin/pay/view.bml Tue Feb 02 06:56:18 2010 +0000
+++ b/htdocs/admin/pay/view.bml Wed Feb 03 01:21:16 2010 +0000
@@ -6,6 +6,7 @@
{
use strict;
use vars qw(%GET %POST);
+ use Storable qw/ thaw /;
my $remote = LJ::get_remote();
my @displayprivs = ( "payments" );
@@ -130,15 +131,28 @@ EOF
# make an educated guess at durl-ing something
my $durl = sub {
my $val = shift;
+
+ my $hr;
+ my $out = sub {
+ foreach ( qw/ SIGNATURE USER PWD / ) {
+ $hr->{$_} = '<em>redacted</em>'
+ if exists $hr->{$_};
+ }
+ return join( '<br />', map { "<strong>$_:</strong> $hr->{$_}"
} sort keys %$hr );
+ };
+
+ # first see if it's Storable encoded ...
+ eval {
+ my $x = thaw( $val );
+ $hr = $x if $x && ref $x eq 'HASH';
+ };
+ return $out->() if $hr;
+
+ # and now fall back to urlencoded ...
return $val
unless $val =~ /&/ && $val =~ /=/;
- my ( $hr, $ar ) = ( {}, [] );
- LJ::decode_url_string( $val, $hr, $ar );
- foreach ( qw/ SIGNATURE USER PWD / ) {
- $hr->{$_} = '<em>redacted</em>'
- if exists $hr->{$_};
- }
- return "<br />-----------<br />" . join( '<br />', map {
"<strong>$_:</strong> $hr->{$_}" } sort keys %$hr );
+ LJ::decode_url_string( $val, $hr );
+ return $out->();
};
my $dbh = LJ::get_db_writer();
@@ -155,7 +169,7 @@ EOF
unless $rows && @$rows;
my @cols = sort { $a cmp $b } keys %{ $rows->[0] };
- $body .= q{<table><tr><th>};
+ $body .= q{<table border=1 cellpadding=5><tr><th>};
$body .= join( '</th><th>', @cols );
$body .= q{</th></tr>};
@@ -189,6 +203,18 @@ EOF
# now show the pp_log log
$body .= "<h2>raw: pp_log (PayPal raw log)</h2>";
$dump->( 'SELECT * FROM pp_log WHERE ppid = ?', $engine->ppid );
+
+ } elsif ( $classname eq 'GoogleCheckout' ) {
+ # show the payer's details.
+ $body .= "<h2>GCO Payer Details</h2>";
+ $body .= "<table border='1'>";
+ $body .= "<tr><th>Contact Name:</th><td>" . $engine->contactname .
"</td></tr>";
+ $body .= "<tr><th>GCO Email Address:</th><td>" . $engine->email .
"</td></tr>";
+ $body .= "</table>";
+
+ # now show the pp_trans log
+ $body .= "<h2>raw: gco_log (GCO raw)</h2>";
+ $dump->( 'SELECT * FROM gco_log WHERE gcoid = ?', $engine->gcoid );
} elsif ( $classname eq 'CheckMoneyOrder' ) {
# show the payer's details.
diff -r 4660678283bb -r f30c9dfe7830 htdocs/shop/gco_notify.bml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/htdocs/shop/gco_notify.bml Wed Feb 03 01:21:16 2010 +0000
@@ -0,0 +1,28 @@
+<?_code
+{
+ #
+ # shop/gco_notify.bml
+ #
+ # Notification system for Google Checkout.
+ #
+ # Authors:
+ # Mark Smith <[email protected]>
+ #
+ # Copyright (c) 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'.
+ #
+
+ use strict;
+ use vars qw( %FORM );
+
+ return BML::redirect( "$LJ::SITEROOT/" )
+ unless LJ::is_enabled( 'payments' );
+
+ DW::Shop::Engine::GoogleCheckout->process_notification( \%FORM );
+
+ return "failure";
+}
+_code?>
diff -r 4660678283bb -r f30c9dfe7830 htdocs/shop/receipt.bml.text
--- a/htdocs/shop/receipt.bml.text Tue Feb 02 06:56:18 2010 +0000
+++ b/htdocs/shop/receipt.bml.text Wed Feb 03 01:21:16 2010 +0000
@@ -31,6 +31,8 @@
.cart.paymentmethod.creditcardpp=Credit Card
+.cart.paymentmethod.gco=Google Checkout Account
+
.cart.paymentmethod.paypal=PayPal Account
.error.invalidordernum=Your order number is invalid.
_______________________________________________
dw-changelog mailing list
[email protected]
http://lists.dwscoalition.org/mailman/listinfo/dw-changelog