Django-Paypal standard subscriptions integration

Want to have a site with PayPal integration using Django with no fuss? That is just django-paypal’s game. I’ll show you how to integrate with Website Payments Standard in a jiffy.

pip install django-paypal

You are using pip, right? If not:

apt-get install python-setuptools
easy_install pip

Whew! Thats better. Let’s fix up your settings.py:

PAYPAL_RECEIVER_EMAIL = "yourbusinessaccount@example.com"

INSTALLED_APPS = ( ...,
  'paypal.standard.ipn',
  ...)

Now, you’ll have to add an entry in your urls.py for the Instant Payment Notifications (IPNs) from PayPal that let you know when people have paid:

urlpatterns = patterns('',
  ...
  url(r'^/something/hard/to/guess/, include('paypal.standard.ipn.urls')),
  ...
)

We need a view in views.py. That is easy too:

from django.conf import settings
...
def subscribe(request):
    # What you want the button to do.
    paypal_dict = {
    "cmd": "_xclick-subscriptions",
	"business": settings.PAYPAL_RECEIVER_EMAIL,
	"a1": "0",	                   # trial price
	"p1": 1,	                   # trial duration, duration of unit defaults to month
	"a3": "29.95",                     # yearly price
	"p3": 1,                           # duration of each unit (depends on unit)
	"t3": "Y",                         # duration unit ("M for Month")
    "src": "1",                        # make payments recur
	"sra": "1",                        # reattempt payment on payment error
	"no_note": "1",                    # remove extra notes (optional)
    "item_name": "PayPal Shows This To The User",
    "invoice": "101",
    "notify_url": "http://example.com/something/hard/to/guess/",
    "return_url": "http://example.com/thanks/",
    "cancel_return": "http://example.com/cancel/",
    "custom": request.user.username,   # put whatever data you need to track things here
    }

    # Create the instance.
    form = PayPalPaymentsForm(initial=paypal_dict, button_type="subscribe")

    context = {"form": form, "encoded_email" : urlquote(settings.PAYPAL_RECEIVER_EMAIL), "paid" : request.user.get_profile().paid}

The reason I’ve included the encoded_email in the view is related to the unsubscribe button we’ll setup in a minute. The button in that view will be a subscription. You can easily modify it to be a buy now button. See the README for django-paypal. If you browse the code on github and checkout paypal.standard.forms.py you can see all the possible options for buttons.

Now we can create the template and the (optional) unsubscribe button:

{% extends "base.html" %}

{% block content %}

{% if paid %}
<h2>Thank you! You are currently subscribed.</h2>
<p id="page-intro">You can cancel anytime online using your PayPal account or from this page.
	If you have any questions or problems please <a href="mailto:you@example.com">email us</a>.
	</p>

	<A HREF="https://www.paypal.com/cgi-bin/webscr?cmd=_subscr-find&alias={{ encoded_email }}" _fcksavedurl="https://www.paypal.com/cgi-bin/webscr?cmd=_subscr-find&alias={{ encoded_email }}"><IMG BORDER="0" SRC="https://www.paypal.com/en_US/i/btn/btn_unsubscribe_LG.gif"></A>
{% else %}
	<!-- Page Head -->
	<h2>Please subscribe to Example using PayPal.</h2>
	<p id="page-intro">You can cancel anytime online using your PayPal account or on this page.
		If you have any questions or problems please <a href="mailto:you@example.com">email us</a>.
		</p>

	{{ form.render }}
{% endif %}
{% endblock %}

Keying off of if the user has paid or not means we can use this template for subscribing or unsubscribing. Now go get paid!

WordPress, Ubuntu – Now

I recently found cause to setup some mini-sales sites according to advice I’ve seen from Tim Ferriss, Rob Walling, and others. If you need to get something up fast, cheap, and quick this is for you.

Login to the Rackspace Cloud site and create a new server instance with your favorite flavor of Ubuntu. I used Lucid Lynx 10.02.

ssh root@
apt-get update
apt-get install ufw mysql-server wordpress links

I grabbed Uncomplicated Firewall (ufw) to lockdown the box. It’s an simplified wrapper for iptables on Ubuntu. This will install wordpress to /usr/share/wordpress.

For my purposes (mini-sales site) I wanted the wordpress installation at the domain root. You might want it to be at /wordpress or another url. I’ll show it both ways here:

# Show apache2 where wordpress lives
#for wordpress at http://example.com/wordpress
ln -s /usr/share/wordpress /var/www/wordpress
# (site root and not /wordpress/)
rm -rf /var/www && ln -s /usr/share/wordpress /var/www
mkdir -p /usr/share/wordpress/wp-updates
mkdir -p /usr/share/wordpress/wp-updates/localhost

If you wanted it at http://example.com/wordpress you’d use line 3 only. Otherwise you need lines 5-7. Now we can install the database and wordpress itself:

# Install WordPress to db using the provided script
bash /usr/share/doc/wordpress/examples/setup-mysql -n wordpress localhost
/etc/init.d/apache2 restart

Now we need to install wordpress from localhost so we’re forced to use a text based browser. Load up links and fill in a blog name and email. The site will give you an admin login and password. Login using that username and password and navigate to Settings -> General. Change the WordPress Address and Blog Address domains to your URL: http://example.com. You’ll want to use http://example.com/wordpress/ if you didn’t install at the site root.

links http://localhost

Finally we can set the permissions and prep the site for being public (be sure to change example.com to your domain):

chown -R www-data /usr/share/wordpress
ln -s /etc/wordpress/config-localhost.php /etc/wordpress/config-example.com.php
/etc/init.d/apache2 restart

Voila! Use your local machine to navigate to your domain. Happy blogging/mini-sales sites.

Goals for Whitetail Software

In the last year I’ve created two full software products while I learned an incredible amount about software, persistence, business, marketing, deployment, and more. I’ve shifted my efforts from creating applications I think are cool to exploring markets I like by talking to customers and trying to pivot ideas toward what people really want or need. I read Eric Ries and Steve Blank among many others to develop my thinking along those lines. I plan to continue calling, emailing, and speaking with people in my market to improve my products and/or pivot to better ideas. The biggest way I’m going to push in this direction in 2011 is to attend conferences both as an attendee and exhibitor to try and connect with customers in multiple ways. I hope to leverage those trips into relationships and customers that give me real traction and word of mouth for the future. This leads in to the specific things I’d like to accomplish this year with Whitetail Software.

2011 Goals

  1. 10 Whitetail Scout (Harvest & Observation Records) Customers
  2. 100 Whitetail Census Surveys
  3. 2-3 posts per month on this blog and on Managing Whitetail
  4. Develop a product that helps people find hunting leases
  5. Integrate all products with Amazon Payments and PayPal
  6. Develop How-To and help videos for the products as a FAQ
  7. Begin a newsletter across Whitetail Software offerings
  8. Experiment with Census pricing and bundling
  9. Relaunch the improved version of Whitetail Scout
  10. Attend 2 or more industry conferences to talk to customers and prospects
  11. Experiment with Organic SEO Content at scale

Conditional on Feedback

  1. OSS project extracting my Mechanical Turk and trust system code into a Django app
  2. AJAX and new features for Whitetail Scout
  3. Develop a site that serves as a directory for the industry similar to Cattle Pages

I’m just getting started on my sojourn to build my own software enterprise from scratch but I have already learned quite a bit in a plethora of categories.  I think one important lesson that you can continually relearn is persistence. Things that have helped me stay the course include support from my wife, a long term perspective on the effort I put into Whitetail Software, and staying focused on the immediate and long term goals as motivation. I think knowing where you want to be in five years and what you think needs to happen this week to get closer to that are critical to accomplishing anything of scale. If you aim at nothing, you’ll hit it every time.