Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

added example project, authorize.net gateway

  • Loading branch information...
commit 9085a630e8f79bc11feb9c75600b89f8f6f7ee8c 1 parent 57fb038
@ashok-raavi ashok-raavi authored
View
0  __init__.py
No changes.
View
61 credit_card.py
@@ -0,0 +1,61 @@
+
+import re
+import datetime
+
+CARD_COMPANIES = {
+ 'visa' : '^4\d{12}(\d{3})?$',
+ 'master' : '^(5[1-5]\d{4}|677189)\d{10}$',
+ 'discover' : '^(6011|65\d{2})\d{12}$',
+ 'american_express' : '^3[47]\d{13}$',
+ 'diners_club' : '^3(0[0-5]|[68]\d)\d{11}$',
+ 'jcb' : '^35(28|29|[3-8]\d)\d{12}$',
+ 'switch' : '^6759\d{12}(\d{2,3})?$',
+ 'solo' : '^6767\d{12}(\d{2,3})?$',
+ 'dankort' : '^5019\d{12}$',
+ 'maestro' : '^(5[06-8]|6\d)\d{10,17}$',
+ 'forbrugsforeningen' : '^600722\d{10}$',
+ 'laser' : '^(6304|6706|6771|6709)\d{8}(\d{4}|\d{6,7})?$'
+}
+
+class CreditCard(object):
+ def __init__(self, first_name=None, last_name=None, month=None, year=None, number=None, card_type=None, verification_value=None):
+ self.first_name = first_name
+ self.last_name = last_name
+ self.month = month
+ self.year = year
+ self.number = number
+ self.card_type = card_type or self.get_card_type(number)
+ self.verification_value = verification_value
+
+ def get_card_type(self):
+ for company, pattern in CARD_COMPANIES.items():
+ # Right now the Maestro regexp overlaps with the MasterCard regexp (IIRC).
+ if not company == 'maestro' and re.match(self.number, pattern):
+ return company
+ return 'maestro' if re.match(self.number, CARD_COMPANIES['maestro']) else None
+
+ def is_luhn_valid(self):
+ # Checks the validity of a card number by use of the the Luhn Algorithm.
+ # Please see http://en.wikipedia.org/wiki/Luhn_algorithm for details.
+ num = [int(x) for x in str(self.number)]
+ return not sum(num[::-2] + [sum(divmod(d * 2, 10)) for d in num[-2::-2]]) % 10
+
+ def is_expired(self):
+ return datetime.date.today() > datetime.date(self.year, self.month, 1)
+
+ def valid_essential_attributes(self):
+ return self.first_name and \
+ self.last_name and \
+ self.month and \
+ self.year and \
+ self.number and \
+ self.verification_value
+
+ def is_valid(self):
+ return self.is_luhn_valid() and \
+ not self.is_expired() and \
+ self.valid_essential_attributes()
+
+ @property
+ def expire_date(self):
+ return '%02d-%04d' % (self.month, self.year)
View
2  docs/overview.txt
@@ -38,7 +38,7 @@ Provides templates
{% paypal 10 %}
-This will show a Paypal Website Stanradr form to charge 10$ with default settings.
+This will show a Paypal Website Standard form to charge 10$ with default settings.
needs to specify
View
0  example/__init__.py
No changes.
View
BIN  example/__init__.pyc
Binary file not shown
View
0  example/app/__init__.py
No changes.
View
BIN  example/app/__init__.pyc
Binary file not shown
View
3  example/app/models.py
@@ -0,0 +1,3 @@
+from django.db import models
+
+# Create your models here.
View
BIN  example/app/models.pyc
Binary file not shown
View
13 example/app/templates/app/base.html
@@ -0,0 +1,13 @@
+<html>
+
+<head>
+ <title>merchant example</title>
+</head>
+
+<body>
+ <h2>example project</h2>
+ {% block content %}
+
+ {% endblock %}
+</body>
+</html>
View
5 example/app/templates/app/index.html
@@ -0,0 +1,5 @@
+{% extends 'app/base.html' %}
+
+{% block content %}
+template: app/templates/app/index.html
+{% endblock %}
View
23 example/app/tests.py
@@ -0,0 +1,23 @@
+"""
+This file demonstrates two different styles of tests (one doctest and one
+unittest). These will both pass when you run "manage.py test".
+
+Replace these with more appropriate tests for your application.
+"""
+
+from django.test import TestCase
+
+class SimpleTest(TestCase):
+ def test_basic_addition(self):
+ """
+ Tests that 1 + 1 always equals 2.
+ """
+ self.failUnlessEqual(1 + 1, 2)
+
+__test__ = {"doctest": """
+Another way to test that 1 + 1 is equal to 2.
+
+>>> 1 + 1 == 2
+True
+"""}
+
View
6 example/app/urls.py
@@ -0,0 +1,6 @@
+
+from django.conf.urls.defaults import *
+
+urlpatterns = patterns('app.views',
+ url(r'^$', 'index', name='app_index'),
+)
View
BIN  example/app/urls.pyc
Binary file not shown
View
9 example/app/views.py
@@ -0,0 +1,9 @@
+
+from django.shortcuts import render_to_response
+from django.template import RequestContext
+
+def render(request, template, template_vars={}):
+ return render_to_response(template, template_vars, RequestContext(request))
+
+def index(request):
+ return render(request, 'app/index.html')
View
BIN  example/app/views.pyc
Binary file not shown
View
11 example/manage.py
@@ -0,0 +1,11 @@
+#!/usr/bin/env python
+from django.core.management import execute_manager
+try:
+ import settings # Assumed to be in the same directory.
+except ImportError:
+ import sys
+ sys.stderr.write("Error: Can't find the file 'settings.py' in the directory containing %r. It appears you've customized things.\nYou'll have to run django-admin.py, passing it your settings module.\n(If the file settings.py does indeed exist, it's causing an ImportError somehow.)\n" % __file__)
+ sys.exit(1)
+
+if __name__ == "__main__":
+ execute_manager(settings)
View
96 example/settings.py
@@ -0,0 +1,96 @@
+# Django settings for example project.
+
+DEBUG = True
+TEMPLATE_DEBUG = DEBUG
+
+ADMINS = (
+ # ('Your Name', 'your_email@domain.com'),
+)
+
+MANAGERS = ADMINS
+
+DATABASES = {
+ 'default': {
+ 'ENGINE': 'django.db.backends.', # Add 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'oracle'.
+ 'NAME': '', # Or path to database file if using sqlite3.
+ 'USER': '', # Not used with sqlite3.
+ 'PASSWORD': '', # Not used with sqlite3.
+ 'HOST': '', # Set to empty string for localhost. Not used with sqlite3.
+ 'PORT': '', # Set to empty string for default. Not used with sqlite3.
+ }
+}
+
+# Local time zone for this installation. Choices can be found here:
+# http://en.wikipedia.org/wiki/List_of_tz_zones_by_name
+# although not all choices may be available on all operating systems.
+# On Unix systems, a value of None will cause Django to use the same
+# timezone as the operating system.
+# If running in a Windows environment this must be set to the same as your
+# system time zone.
+TIME_ZONE = 'America/Chicago'
+
+# Language code for this installation. All choices can be found here:
+# http://www.i18nguy.com/unicode/language-identifiers.html
+LANGUAGE_CODE = 'en-us'
+
+SITE_ID = 1
+
+# If you set this to False, Django will make some optimizations so as not
+# to load the internationalization machinery.
+USE_I18N = True
+
+# If you set this to False, Django will not format dates, numbers and
+# calendars according to the current locale
+USE_L10N = True
+
+# Absolute path to the directory that holds media.
+# Example: "/home/media/media.lawrence.com/"
+MEDIA_ROOT = ''
+
+# URL that handles the media served from MEDIA_ROOT. Make sure to use a
+# trailing slash if there is a path component (optional in other cases).
+# Examples: "http://media.lawrence.com", "http://example.com/media/"
+MEDIA_URL = ''
+
+# URL prefix for admin media -- CSS, JavaScript and images. Make sure to use a
+# trailing slash.
+# Examples: "http://foo.com/media/", "/media/".
+ADMIN_MEDIA_PREFIX = '/media/'
+
+# Make this unique, and don't share it with anybody.
+SECRET_KEY = 'wobwwik!&)qmyt2kf3(^jjc6gff)jbtuir+&2)ux7e#xozf5@m'
+
+# List of callables that know how to import templates from various sources.
+TEMPLATE_LOADERS = (
+ 'django.template.loaders.filesystem.Loader',
+ 'django.template.loaders.app_directories.Loader',
+# 'django.template.loaders.eggs.Loader',
+)
+
+MIDDLEWARE_CLASSES = (
+ 'django.middleware.common.CommonMiddleware',
+ 'django.contrib.sessions.middleware.SessionMiddleware',
+ 'django.middleware.csrf.CsrfViewMiddleware',
+ 'django.contrib.auth.middleware.AuthenticationMiddleware',
+ 'django.contrib.messages.middleware.MessageMiddleware',
+)
+
+ROOT_URLCONF = 'example.urls'
+
+TEMPLATE_DIRS = (
+ # Put strings here, like "/home/html/django_templates" or "C:/www/django/templates".
+ # Always use forward slashes, even on Windows.
+ # Don't forget to use absolute paths, not relative paths.
+)
+
+INSTALLED_APPS = (
+ 'django.contrib.auth',
+ 'django.contrib.contenttypes',
+ 'django.contrib.sessions',
+ 'django.contrib.sites',
+ 'django.contrib.messages',
+ # Uncomment the next line to enable the admin:
+ # 'django.contrib.admin',
+
+ 'app',
+)
View
BIN  example/settings.pyc
Binary file not shown
View
19 example/urls.py
@@ -0,0 +1,19 @@
+from django.conf.urls.defaults import *
+
+# Uncomment the next two lines to enable the admin:
+# from django.contrib import admin
+# admin.autodiscover()
+
+urlpatterns = patterns('',
+ # Example:
+ # (r'^example/', include('example.foo.urls')),
+
+ # Uncomment the admin/doc line below and add 'django.contrib.admindocs'
+ # to INSTALLED_APPS to enable admin documentation:
+ # (r'^admin/doc/', include('django.contrib.admindocs.urls')),
+
+ # Uncomment the next line to enable the admin:
+ # (r'^admin/', include(admin.site.urls)),
+
+ url(r'^', include('app.urls')),
+)
View
BIN  example/urls.pyc
Binary file not shown
View
130 gateways/authorize_net.py
@@ -0,0 +1,130 @@
+
+import urllib
+import urllib2
+
+API_VERSION = '3.1'
+DELIM_CHAR = ','
+ENCAP_CHAR = '$'
+APPROVED, DECLINED, ERROR, FRAUD_REVIEW = 1, 2, 3, 4
+RESPONSE_CODE, RESPONSE_REASON_CODE, RESPONSE_REASON_TEXT = 0, 2, 3
+
+
+class AuthorizeNetGateway:
+ def __init__(self, login, password, test_mode=True):
+ self.login = login
+ self.password = password
+ self.test_mode = test_mode
+ self.test_url = "https://test.authorize.net/gateway/transact.dll"
+ self.live_url = "https://secure.authorize.net/gateway/transact.dll"
+
+ # self.arb_test_url = 'https://apitest.authorize.net/xml/v1/request.api'
+ # self.arb_live_url = 'https://api.authorize.net/xml/v1/request.api'
+
+ # def authorize(money, credit_card, options={}):
+ def purchase(self, money, credit_card, options={}):
+ post = {}
+
+ self.add_invoice(post, options)
+ self.add_creditcard(post, credit_card)
+ self.add_address(post, options)
+ self.add_customer_data(post, options)
+ # self.add_duplicate_window(post)
+
+ self.commit('AUTH_CAPTURE', money, post)
+
+ def add_invoice(self, post, options):
+ post['invoice_num'] = options.get('order_id', None)
+ post['description'] = options.get('description', None)
+
+ def add_creditcard(self, post, credit_card):
+ post['card_num'] = credit_card.number
+ post['card_code'] = credit_card.verification_value
+ post['exp_date'] = credit_card.expire_date
+ post['first_name'] = credit_card.first_name
+ post['last_name'] = credit_card.last_name
+
+ def add_address(self, post, options):
+ if options.get('billing_address', None):
+ address = options.get('billing_address')
+ post['address'] = address.get('address', '')
+ post['company'] = address.get('company', '')
+ post['phone'] = address.get('phone', '')
+ post['zip'] = address.get('zip', '')
+ post['city'] = address.get('city', '')
+ post['country'] = address.get('country', '')
+ post[':state'] = address.get('state', '')
+
+ if options.get('shipping_address', None):
+ address = options.get('shipping_address')
+ post['ship_to_first_name'] = address.get('first_name', '')
+ post['ship_to_last_name'] = address.get('last_name', '')
+ post['ship_to_address'] = address.get('address', '')
+ post['ship_to_company'] = address.get('company', '')
+ post['ship_to_phone'] = address.get('phone', '')
+ post['ship_to_zip'] = address.get('zip', '')
+ post['ship_to_city'] = address.get('city', '')
+ post['ship_to_country'] = address.get('country', '')
+ post['ship_to_state'] = address.get('state', '')
+
+ def add_customer_data(self, post, options):
+ if options.has_key('email'):
+ post['email'] = options['email']
+ post['email_customer'] = false
+
+ if options.has_key('customer'):
+ post['cust_id'] = options['customer']
+
+ if options.has_key('ip'):
+ post['customer_ip'] = options['ip']
+
+ def commit(self, action, money, parameters):
+ if not action == 'VOID':
+ parameters['amount'] = money
+
+ parameters[:test_request] = self.test_mode
+ url = self.test_url if self.test_mode else self.live_url
+ data = self.post_data(action, parameters)
+ response = self.request(url, data)
+ return response
+
+ def post_data(self, action, parameters = {}):
+ post = {}
+
+ post['version'] = API_VERSION
+ post['login'] = self.login
+ post['tran_key'] = self.password
+ post['relay_response'] = "FALSE"
+ post['type'] = action
+ post['delim_data'] = "TRUE"
+ post['delim_char'] = DELIM_CHAR
+ post['encap_char'] = ENCAP_CHAR
+
+ post.update(parameters)
+ d = {}
+ for key, value in post.items():
+ d['x_%s' % (key)] = value
+ return urllib.urlencode(d)
+
+ # this shoud be moved to a requests lib file
+ def request(self, url, data, headers={}):
+ conn = urllib2.Request(url=url, data=data, headers=headers)
+ try:
+ open_conn = urllib2.urlopen(conn)
+ response = open_conn.read()
+ except urllib2.URLError, ue:
+ return (5, '1', 'Could not talk to payment gateway.')
+ fields = response[1::-1].split('%s%s%s' % (ENCAP_CHAR, DELIM_CHAR, ENCAP_CHAR))
+ return [int(fields[RESPONSE_CODE]),
+ fields[RESPONSE_REASON_CODE],
+ fields[RESPONSE_REASON_TEXT]]
+
+"""
+ params = urllib.urlencode(raw_params)
+ headers = { 'content-type':'application/x-www-form-urlencoded',
+ 'content-length':len(params) }
+ post_url = settings.AUTHNET_POST_URL
+ post_path = settings.AUTHNET_POST_PATH
+ cn = httplib.HTTPSConnection(post_url, httplib.HTTPS_PORT)
+ cn.request('POST', post_path, params, headers)
+ return cn.getresponse().read().split(delimiter)
+"""
Please sign in to comment.
Something went wrong with that request. Please try again.