NotificationHandler is simple base class for implementing the Google Checkout Notification API (XML v2.5) with AppEngine's webapp framework.
Just copy the file to the root of your application.
Create a webapp handler by subclassing the NotificationHandler
defining a merchant_details
method and overriding any notification methods you wish to use:
class MyNotificationHandler(NotificationHandler)
def merchant_details():
"return a tuple of your merchant details"
return (your_id, your_key)
def new_order(self):
logging.info("got a new order notification", self.notification)
By default NotificationHandler
accepts (and acknowledges) all notifications and leaves a
message in the log. It expects that you will override one or more of the following methods
in your Handler:
class MyNotificationHandler(NotificationHandler)
def new_order(self):
"Do something with the new-order-notification"
def risk_information(self):
"Do something with the risk-information-notification"
def order_state_change(self):
"Do something with the order-state-change-notification"
def charge_amount(self):
"Do something with the charge-amount-notification"
def chargeback_amount(self):
"Chargeback info..."
def refund_amount(self):
"Refund info..."
def authorization_amount(self):
"Auth details..."
Within the context of a NotificationHandler self.notification
contains a dict-like object
with all the notification values from the request.
The values in self.notifications are pythonized by converting -
to _
. So 'order-summary' becomes 'order_summary'
This allows you to access the values via dot-notation. For example:
self.notification.order_summary.google_order_number # contains the order reference
As a convineince the structure for fetch the items
in the shopping-cart
elements has been shortend slightly from the XML version. To iterate each item you can do:
for item in self.notification.shopping_cart.items:
# item.item_name
# etc
As a full example, if we have a simple Order model to store our new order details we could then make a notification handler to store the order details
from google.appengine.ext import webapp,db
from google.appengine.ext.webapp import util
from googlecheckout import NotificationHandler
class Order(db.Model):
amount = db.StringProperty()
paid = db.StringProperty()
name = db.StringProperty()
email = db.StringProperty()
address_line_1 = db.StringProperty()
city = db.StringProperty()
postcode = db.StringProperty()
phone = db.StringProperty()
items = db.StringListProperty()
class CheckoutHandler(NotificationHandler):
"An example notifcation handle"
def merchant_details():
"return a tuple of your merchant details"
return ("12345678910", "Axoiuyfq2309230f9u2gf")
def new_order(self):
"Create an order for the incoming order notification"
# first check if we already created this order (maybe the notification came in twice)
order = Order.get_by_key_name(self.notification.google_order_number)
if order:
return
# otherwise create an order
order = Order(
key_name = self.notification.google_order_number,
name = self.notification.buyer_shipping_address.contact_name,
email = self.notification.buyer_shipping_address.email,
address_line_1 = self.notification.buyer_shipping_address.address1,
city = self.notification.buyer_shipping_address.city,
postcode = self.notification.buyer_shipping_address.postal_code,
amount = self.notification.order_total,
phone = self.notification.buyer_shipping_address.phone)
# record each item in the order
for item in self.notification.shopping_cart.items:
order.items.append( item.item_name )
order.put()
def charge_amount(self):
"Mark a previous order as paid"
order = Order.get_by_key_name(self.notification.google_order_number)
order.paid = True
order.put()
def main():
routes = [
('/notifications/checkout', CheckoutHandler)
]
application = webapp.WSGIApplication(routes, debug=True)
util.run_wsgi_app(application)
if __name__ == '__main__':
main()
[Experimental] A few of the Financial Commands from the Order Processing API are exposed via the remote_order
method on the handler.
remote_order
returns an instance of googlecheckout.Order for the current order.
For example if you wanted to automatically ship all orders under $10 and instantly cancel all orders over $3000 you might do something like:
class MyNotificationHandler(NotificationHandler):
"An example notifcation handler"
def merchant_details():
"return a tuple of your merchant details"
return ("12345678910", "Axoiuyfq2309230f9u2gf")
def new_order(self):
total = float(self.notificaiton.order.total)
if total < 10:
self.remote_order.charge_and_ship(self.notificaiton.order_total)
elif total > 3000:
self.remote_order.cancel()
remote_order
calls will raise an exception if they fail so you will probably want to wrap them in try
/catch
to handle them correctly.
You can use the Order Processing methods without the NotificationHandler by setting up the order class:
import googlecheckout
CheckoutOrder = googlecheckout.Client(merchant_id='171973829346743',
merchant_key='ZyCwRxR5AZrIkOkumZtyVQ',
sandbox=True,
currency="GBP")
# init order class with order-number
order = CheckoutOrder('859558483052501')
# (re)authorize an order
order.authorize()
# charge/ship order and log
# an optional shipping carrier
order.charge_and_ship(carrier="FEDEX", carrier_id="123456")
# refund an order with reason and optional amount
order.refund("it's all squishy", amount=10)
# cancel the order
order.cancel(reason="customer sounds dodgey")
Exceptions raised during execution of the notification will result in the notification being resent from google-checkout.
raise IgnoreNotification
if you wish to raise an exception and also return send an OK acknowledgement to
google-checkout to prevent re-sending.
This code started life in the chippyshop source and was refactored/hacked/extended by Chris Farmiloe into this reusable module.