A Google Checkout class

The Checkout API is capable of several checkout patterns. In Chapter 2, Setting Up Shop in 30 Minutes, we implemented the simplest pattern involving a single "Buy It Now" button. In Chapter 3 we implemented a custom shopping-cart solution. In the previous section we built a generic approach to implement checkout functionality for any service. We will now implement our Google Checkout shopping cart solution using this generic framework. Later in this chapter we will also implement another checkout service, Amazon's Flexible Payment System, on top of our generic framework.

To build our Google Checkout class, we inherit all of the functionality from our generic checkout view and add some additional data and methods. We will store our Google API and merchant key as class attributes as well as the shopping cart XML template name. Our XML template will be treated like the checkout HTML template, which will give us the flexibility to use different XML shopping cart templates for the same website if needed.

We'll also implement a shopping cart conversion method that converts our site's Cart model into a Google Checkout cart using the XML template. This is the same conversion function we used in the previous chapter to render the XML template and calculate a base-64 signature. The conversion method will update our class's extra_context data member to automatically include the Google cart when the view is rendered.

This system will be represented by a subclass called GoogleCheckoutView. The code listing for this class is below:

class GoogleCheckoutView(CheckoutView):
    google_cart_template = 'payments/googlecheckout.xml'
    merchant_key =    getattr(settings, 'GOOGLE_MERCHANT_KEY', '')
    merchant_id = getattr(settings, 'GOOGLE_MERCHANT_ID', '')

    def convert_shopping_cart(self):
        cart = self.get_shopping_cart()
        cart_cleartext = render_to_string(self.google_cart_template,
	                                       {'cart': cart})
        cart_sig = hmac.new(self.merchant_key, cart_cleartext, sha).digest()
        cart_base64 = base64.b64encode(cart_cleartext)
        sig_base64 = base64.b64encode(cart_sig)
        self.extra_context.update({'googleCart': cart_base64,
                                   'googleSig': sig_base64})

    def return_response(self):
        self.convert_shopping_cart()
        return super(CheckoutView, self).return_response()

The only new code here is the return_response method, which uses polymorphism to call our shopping cart conversion method before returning the view response as normal by calling the parent class's implementation. This method has been modified slightly from our original version earlier in the book. Instead of returning the cart and signature data, it adds them to the extra_context attribute. This attribute is automatically added to the template context when the view is rendered from return_response.

Much more functionality is available in the XML version of the Checkout API, but if your implementation requires support for the HTML Checkout API version, we can implement another view to support this very easily. The HTML API uses a similar approach to the XML, but is not cryptographically signed and submits a full HTML form with hidden input fields for all products in the cart.

An HTML version of the GoogleCheckoutView class is as follows:

class GoogleCheckoutHTMLView(CheckoutView):
    google_cart_template = 'payments/googlecheckout.html'
    merchant_key = getattr(settings, 'GOOGLE_MERCHANT_KEY', None)   
    merchant_id = getattr(settings, 'GOOGLE_MERCHANT_ID', None)
 
    def convert_shopping_cart(self):
        cart = self.get_shopping_cart()
        checkout_form = render_to_string(self.google_cart_template,
                                         {'cart': cart})
        self.extra_context.update({'checkout_form': checkout_form})

     def return_response(self):
          self.convert_shopping_cart()
          return super(CheckoutView, self).return_response()

In this case, we render a special HTML template called google_cart_template, just as we did in the XML version. We store the resulting HTML fragment string in the extra_context. The HTML form in this fragment will contain all hidden fields and the submit button that features the Google logo. An example of this HTML template looks like this:

<form method="POST"
action="https://sandbox.google.com/checkout/api/checkout/v2/checkoutForm/Merchant/REPLACE_WITH_YOUR_SANDBOX_MERCHANT_ID"
accept-charset="utf-8">
    {% for item in cart %}
    {% with counter as forloop.counter %}
    <input type="hidden" name="item_name_{{ counter }}" 
               value="{{ item.product.name }}"/>
    <input type="hidden" name="item_description_{{ counter }}" 
               value="{{ item.product.description }}"/>
    <input type="hidden" name="item_price_{{ counter }}" 
               value="{{ item.price_in_dollars }}"/>
    <input type="hidden" name="item_currency_{{ counter }}"
               value="USD"/>
    <input type="hidden" name="item_quantity_{{ counter }}" 
               value="{{ item.quantity }}"/>
    <input type="hidden" name="item_merchant_id_{{ counter }}"  
               value="PROD{{ item.product.id }}"/>
    {% endwith %}
    {% endfor %}
    <input type="hidden" name="_charset_" />

    <!-- Button code -->
    <input type="image"
      name="Google Checkout"
      alt="Fast checkout through Google"  src="http://sandbox.google.com/checkout/buttons/checkout.gif?merchant_id=REPLACE_WITH_YOUR_SANDBOX_MERCHANT_ID&w=180&h=46&style=white&variant=text&loc=en_US"
       height="46"
       width="180" />
</form>

We've just written two different implementations of the Google Checkout API in a very small amount of code by building on our generic checkout view framework. The Google Checkout API has numerous additional features that could be integrated to the above designs. Additional features are fully described in the Checkout API documentation.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset