Django Payments

How to?

Rafał Gawlik

Android developer @ Altimi Solutions

Czym jest i jak działa Django?

  • MVT
  • panel administracyjny
  • serwer developerski
  • własny ORM

Django Sample App

Start project

$ django-admin startproject exampleapp

Run server

$ cd exampleapp

$ python manage.py runserver

127.0.0.1:8000

Start new app in project

$ python manage.py startapp news

Create new app

Update settings

$ cd exampleapp

$ vim settings.py

Update INSTALLED_APPS

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'news',
]

Form root project directory

$ cd news

$ vim models.py

Add model

from __future__ import unicode_literals
from django.db import models

class News(models.Model):
    title = models.CharField('Title', max_length=255)
    slug = models.SlugField('Slug', max_length=255, unique=True)
    text = models.TextField(verbose_name='Text')
    posted_date = models.DateTimeField('Added date', auto_now_add=True)

    class Meta:
        verbose_name = "News"
        verbose_name_plural = "News"

    def __unicode__(self):
        return self.title

Create DB

$ python manage.py migrate

$ python manage.py makemigrations

Add view

From root project directory

Update urls.py

$ cd exampleapp

$ vim urls.py

from django.conf.urls import url
from django.contrib import admin

import news.views

urlpatterns = [
    url(r'^admin/', admin.site.urls),

    url(r'^$', news.views.index, name='index'),
]

Update views.py

Add template

$ mkdir templates

$ vim templates/index.html

from django.shortcuts import render
from django.shortcuts import render_to_response
from django.template import RequestContext
from .models import News

def index(request):
    news = News.objects.all().order_by('-posted_date')
    return render_to_response('index.html', {'news': news, }, 
	   context_instance=RequestContext(request))
<h1>Hello world</h1>

{% for new in news %}

	<h2>{{ new.title }}</h2>
	<p>{{ new.text }}</p>

{% endfor %}

Add admins

Update admin.py

Create superuser

$ python manage.py createsuperuser

And RUN

$ python manage.py runserver

from django.contrib import admin

from models import *

class NewsAdmin(admin.ModelAdmin):
    list_display = ('title', 'posted_date')
    prepopulated_fields = {'slug': ('title',)}

admin.site.register(News, NewsAdmin)

Payment

with Stripe.com

Create new app

$ python manage.py startapp wallet

Update settings.py

$ vim exampleapp/settings.py

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'news',
    'wallet',
]

From Stripe.com

Get test secret and publishable keys

STRIPE_PUBLISHABLE_KEY = 'pk_test_YSDYoeIufMuNcQO9yW6Ts6Ln'
STRIPE_SECRET_KEY = 'sk_test_3S5pz9wHl30Sw5Vik3xKehss'

Update urls.py

from django.conf.urls import url
from django.contrib import admin

import news.views
import wallet.views

urlpatterns = [
    url(r'^admin/', admin.site.urls),

    url(r'^$', news.views.index, name='index'),
    url(r'^checkout/$', wallet.views.checkout, name='checkout'),
]

View and tamplate

Create checkout.html

<form action="" method="POST" id="payment-form">
  {% csrf_token %}
  <span class="payment-errors"></span>

  <div class="form-row">
    <label>
      <span>Card Number</span>
      <input type="text" size="20" data-stripe="number">
    </label>
  </div>

  <div class="form-row">
    <label>
      <span>Expiration (MM/YY)</span>
      <input type="text" size="2" data-stripe="exp_month">
    </label>
    <span> / </span>
    <input type="text" size="2" data-stripe="exp_year">
  </div>

  <div class="form-row">
    <label>
      <span>CVC</span>
      <input type="text" size="4" data-stripe="cvc">
    </label>
  </div>

  <input type="submit" class="submit" value="Submit Payment">
</form>

Update checkout.html

<script type="text/javascript" src="https://js.stripe.com/v2/">
</script>

Set your publishable kay

<script type="text/javascript">
    Stripe.setPublishableKey('{{publishKey}}');
</script>

Create a single use token

{% block jquery %}

  $(function() {
    var $form = $('#payment-form');
    $form.submit(function(event) {
      // Disable the submit button to prevent repeated clicks:
      $form.find('.submit').prop('disabled', true);

      // Request a token from Stripe:
      Stripe.card.createToken($form, stripeResponseHandler);

      // Prevent the form from being submitted:
      return false;
    });
  });

{% endblock %}
<script>
  $(document).ready(function(){
    {% block jquery %}
      {% endblock %}
    });
</script>

Sending the form to own server

<script type="text/javascript">
    
function stripeResponseHandler(status, response) {
  // Grab the form:
  var $form = $('#payment-form');

  if (response.error) { // Problem!

    // Show the errors on the form:
    $form.find('.payment-errors').text(response.error.message);
    $form.find('.submit').prop('disabled', false); // Re-enable submission

  } else { // Token was created!

    // Get the token ID:
    var token = response.id;

    // Insert the token ID into the form so it gets submitted to the server:
    $form.append($('<input type="hidden" name="stripeToken">').val(token));

    // Submit the form:
    $form.get(0).submit();
  }
};

</script>

Update views.py in wallet app

from django.shortcuts import render
from django.conf import settings
import stripe


stripe.api_key = settings.STRUPE_SECRET_KEY

def checkout(request):
    publishKey = settings.STRIPE_PUBLISHABLE_KEY

    if request.method == 'POST':
        token = request.POST['stripeToken']

        try:
            charge = stripe.Charge.create(
                amount=1000, # amount in cents, again
                currency="usd",
                source=token,
                description="Example charge"
            )
        except stripe.error.CardError, e:
            # The card has been declined
            pass

    context = { 'publishKey':publishKey, }
    template = 'checkout.html'
    return render(request, template, context)

Run it

http://127.0.0.1:8000/checkout/

Test credit card

Thank you!

Questions?

Resources

Django Payments

By Rafał Gawlik

Django Payments

  • 953