Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added stripe gateway #22

Merged
merged 34 commits into from Jan 27, 2012
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
560db7e
added purchase method for stripe
hayyat Dec 22, 2011
ba39025
added stripe_gateway file
hayyat Dec 22, 2011
975ea56
got stripe payment gateway purchase method working
hayyat Dec 23, 2011
fdfa063
added store function to stripe gateway
hayyat Dec 23, 2011
a27a168
added recurring method to stripe gateway
hayyat Dec 23, 2011
f053821
modified stripe recurring method and pep8 stripe gateway file
hayyat Dec 25, 2011
d09cc37
added unstore method to stripe gateway
hayyat Dec 25, 2011
1519848
added credit method to stripe gateway
hayyat Dec 25, 2011
964430d
pyflaked stripe gateway file
hayyat Dec 26, 2011
99cc9b1
added tests for stripe gateway
hayyat Dec 26, 2011
34cbe4f
added plaban to contributors
hayyat Dec 26, 2011
45ecaad
added stripe tests
hayyat Dec 26, 2011
a10872a
added testcredit method to stripe test
hayyat Dec 26, 2011
be0d3dd
slightly modified credit method
hayyat Dec 26, 2011
1f2a818
added docs for stripe gateway
hayyat Dec 27, 2011
c6bd550
added purchase and authorize method of samurai
hayyat Dec 27, 2011
6d688bb
added capture method of samurai
hayyat Dec 28, 2011
e7e6830
added authorize and capture method and their tests and docs to stripe…
hayyat Dec 28, 2011
f8b3375
debugged a mistake in docs
hayyat Dec 28, 2011
08c0e14
added stripe integration and some more methods to samurai
hayyat Dec 28, 2011
2a623c8
pep8fied some files
hayyat Dec 28, 2011
d78388b
pyflaked some files
hayyat Dec 28, 2011
6bec806
some minor changes to gateway file and test file of stripe
hayyat Dec 29, 2011
2c36660
added more methods to samurai
hayyat Dec 29, 2011
496c819
added samurai gateway tests and pep8fied and pyflaked files
hayyat Dec 30, 2011
8e6fc0b
added samurai docs and updated localsettings.example.py
hayyat Dec 30, 2011
b82ad49
changed samurai docs
hayyat Dec 30, 2011
a89e468
changed stripe docs
hayyat Dec 30, 2011
78e96f0
updated docs index
hayyat Dec 30, 2011
40ebfff
added samurai to app
hayyat Dec 30, 2011
ba4a039
added samurai integration
hayyat Jan 2, 2012
fa75c15
added docs for samurai integration
hayyat Jan 2, 2012
dab193e
modified samurai docs
hayyat Jan 2, 2012
8ea9552
debugged docs
hayyat Jan 2, 2012
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
6 changes: 5 additions & 1 deletion .gitignore
Expand Up @@ -4,10 +4,14 @@
src
tmp
*.db

*.*~
#*#
example/tmp
example/localsettings.py

docs/_build/*

*_flymake.py*
#*
.py#

1 change: 1 addition & 0 deletions CONTRIBUTORS.txt
Expand Up @@ -10,3 +10,4 @@ Thanks go out to all the contributors listed in alphabetical order:
* Markus Gattol <markus.gattol@sunoano.org>
* Shabda Raaj <shabda@agiliq.com>
* Thejaswi Puthraya <thejaswi.puthraya@gmail.com>
* Plaban Nayak <plaban.nayak@gmail.com>
8 changes: 8 additions & 0 deletions billing/forms/samurai_forms.py
@@ -0,0 +1,8 @@
from django import forms


class SamuraiForm(forms.Form):
credit_card__number = forms.CharField()
credit_card__cvc = forms.CharField(max_length=4)
credit_card__expiration_month = forms.CharField(max_length=7)
credit_card__expiration_year = forms.CharField(max_length=7)
8 changes: 8 additions & 0 deletions billing/forms/stripe_forms.py
@@ -0,0 +1,8 @@
from django import forms


class StripeForm(forms.Form):
credit_card__number = forms.CharField()
credit_card__cvc = forms.CharField(max_length=4)
credit_card__expiration_month = forms.CharField(max_length=7)
credit_card__expiration_year = forms.CharField(max_length=7)
23 changes: 11 additions & 12 deletions billing/gateway.py
Expand Up @@ -28,7 +28,7 @@ class Gateway(object):
# Sequence of countries supported by the gateway in ISO 3166 alpha-2 format.
# http://en.wikipedia.org/wiki/ISO_3166-1_alpha-2
supported_countries = []
# Sequence of supported card types by the gateway. Members should be valid
# Sequence of supported card types by the gateway. Members should be valid
# subclasses of the Credit Card object.
supported_cardtypes = []
# Home page URL for the gateway. Used for information purposes only.
Expand All @@ -55,39 +55,39 @@ def validate_card(self, credit_card):
# Gateways might provide some random number which
# might not pass Luhn's test.
if self.test_mode:
return True
return True
return credit_card.is_valid()

def purchase(self, money, credit_card, options = None):
def purchase(self, money, credit_card, options=None):
"""One go authorize and capture transaction"""
raise NotImplementedError

def authorize(self, money, credit_card, options = None):
def authorize(self, money, credit_card, options=None):
"""Authorization for a future capture transaction"""
raise NotImplementedError

def capture(self, money, authorization, options = None):
def capture(self, money, authorization, options=None):
"""Capture funds from a previously authorized transaction"""
raise NotImplementedError

def void(self, identification, options = None):
def void(self, identification, options=None):
"""Null/Blank/Delete a previous transaction"""
raise NotImplementedError

def credit(self, money, identification, options = None):
def credit(self, money, identification, options=None):
"""Refund a previously 'settled' transaction"""
raise NotImplementedError

def recurring(self, money, creditcard, options = None):
def recurring(self, money, creditcard, options=None):
"""Setup a recurring transaction"""
raise NotImplementedError

def store(self, creditcard, options = None):
def store(self, creditcard, options=None):
"""Store the credit card and user profile information
on the gateway for future use"""
raise NotImplementedError

def unstore(self, identification, options = None):
def unstore(self, identification, options=None):
"""Delete the previously stored credit card and user
profile information on the gateway"""
raise NotImplementedError
Expand All @@ -98,14 +98,13 @@ def get_gateway(gateway, *args, **kwargs):
This caches gateway classes in a module-level dictionnary to avoid hitting
the filesystem every time we require a gateway.

Should the list of available gateways change at runtime, one should then
Should the list of available gateways change at runtime, one should then
invalidate the cache, the simplest of ways would be to:

>>> gateway_cache = {}
"""
# Is the class in the cache?
clazz = gateway_cache.get(gateway, None)

if not clazz:
# Let's actually load it (it's not in the cache)
gateway_filename = "%s_gateway" %gateway
Expand Down
95 changes: 95 additions & 0 deletions billing/gateways/samurai_gateway.py
@@ -0,0 +1,95 @@
from billing import Gateway
from billing.utils.credit_card import InvalidCard, Visa, MasterCard, \
AmericanExpress, Discover
import samurai
from django.conf import settings


class SamuraiGateway(Gateway):
supported_cardtypes = [Visa, MasterCard, AmericanExpress, Discover]
supported_countries = ['US']
default_currency = "USD"
homepage_url = "https://samurai.feefighters.com/"
display_name = "Samurai"

def __init__(self):
import samurai.config as config
config.merchant_key = settings.SAMURAI_MERCHANT_KEY
config.merchant_password = settings.SAMURAI_MERCHANT_PASSWORD
config.processor_token = settings.SAMURAI_PROCESSOR_TOKEN
self.samurai = samurai

def purchase(self, money, credit_card):
if not self.validate_card(credit_card):
raise InvalidCard("Invalid Card")
try:
from samurai.payment_method import PaymentMethod
from samurai.processor import Processor
pm = PaymentMethod.create(credit_card.number, credit_card.verification_value,
credit_card.month, credit_card.year)
payment_method_token = pm.payment_method_token
response = Processor.purchase(payment_method_token, money)
except Exception, error:
return {'status': 'FAILURE', 'response': error}
return {'status': 'SUCCESS', 'response': response}

def authorize(self, money, credit_card, options=None):
if not self.validate_card(credit_card):
raise InvalidCard("Invalid Card")
try:
from samurai.payment_method import PaymentMethod
from samurai.processor import Processor
pm = PaymentMethod.create(credit_card.number, credit_card.verification_value, credit_card.month, credit_card.year)
payment_method_token = pm.payment_method_token
response = Processor.authorize(payment_method_token, money)
except Exception, error:
return {'status': 'FAILURE', 'response': error}
return {'status': 'SUCCESS', 'response': response}

def capture(self, money, identification, options=None):
from samurai.transaction import Transaction
trans = Transaction.find(identification)
if not trans.errors:
new_trans = trans.capture(money)
return{'status': "SUCCESS", "response": new_trans}
else:
return{"status": "FAILURE", "response": trans.errors}

def reverse(self, money, identification, options=None):
from samurai.transaction import Transaction
trans = Transaction.find(identification)
if not trans.errors:
new_trans = trans.reverse(money)
return{'status': "SUCCESS", "response": new_trans}
else:
return{"status": "FAILURE", "response": trans.errors}

def void(self, identification, options=None):
from samurai.transaction import Transaction
trans = Transaction.find(identification)
if not trans.errors:
new_trans = trans.void()
return{'status': "SUCCESS", "response": new_trans}
else:
return{"status": "FAILURE", "response": trans.errors}

def credit(self, money, identification, options=None):
from samurai.transaction import Transaction
trans = Transaction.find(identification)
if not trans.errors:
new_trans = trans.credit(money)
return{'status': "SUCCESS", "response": new_trans}
else:
return{"status": "FAILURE", "response": trans.errors}

def store(self, credit_card, options=None):
from samurai.payment_method import PaymentMethod
pm = PaymentMethod.create(credit_card.number, credit_card.verification_value, credit_card.month, credit_card.year)
response = pm.retain()
return {'status': 'SUCCESS', 'response': response}

def unstore(self, identification, options=None):
from samurai.payment_method import PaymentMethod
payment_method = PaymentMethod.find(identification)
payment_method = payment_method.redact()
return {"status": "SUCCESS", "response": payment_method}
118 changes: 118 additions & 0 deletions billing/gateways/stripe_gateway.py
@@ -0,0 +1,118 @@
from billing import Gateway
from billing.utils.credit_card import InvalidCard, Visa, MasterCard, \
AmericanExpress, Discover
import stripe
from django.conf import settings


class StripeGateway(Gateway):
supported_cardtypes = [Visa, MasterCard, AmericanExpress, Discover]
supported_countries = ['US']
default_currency = "USD"
homepage_url = "https://stripe.com/"
display_name = "Stripe"

def __init__(self):
stripe.api_key = settings.STRIPE_API_KEY
self.stripe = stripe

def purchase(self, amount, credit_card, options=None):
if not self.validate_card(credit_card):
raise InvalidCard("Invalid Card")
try:
response = self.stripe.Charge.create(
amount=amount * 100,
currency=self.default_currency.lower(),
card={
'number': credit_card.number,
'exp_month': credit_card.month,
'exp_year': credit_card.year,
'cvc': credit_card.verification_value
},)
except self.stripe.CardError, error:
return {'status': 'FAILURE', 'response': error}
return {'status': 'SUCCESS', 'response': response}

def store(self, credit_card, options=None):
if not self.validate_card(credit_card):
raise InvalidCard("Invalid Card")
customer = self.stripe.Customer.create(
card={
'number': credit_card.number,
'exp_month': credit_card.month,
'exp_year': credit_card.year,
'cvc': credit_card.verification_value
},
description="Storing for future use"
)
return {'status': 'SUCCESS', 'response': customer}

def recurring(self, credit_card, options=None):
if not self.validate_card(credit_card):
raise InvalidCard("Invalid Card")
response = None
try:
plan_id = options['plan_id']
self.stripe.Plan.retrieve(options['plan_id'])
try:
response = self.stripe.Customer.create(
card={
'number': credit_card.number,
'exp_month': credit_card.month,
'exp_year': credit_card.year,
'cvc': credit_card.verification_value
},
plan=plan_id,
description="Thanks for subscribing"
)
return {"status": "SUCCESS", "response": response}
except self.stripe.CardError, error:
return {"status": "FAILURE", "response": error}
except self.stripe.InvalidRequestError, error:
return {"status": "FAILURE", "response": error}
except TypeError:
return {"status": "FAILURE", "response": "please give a plan id"}

def unstore(self, identification, options=None):
try:
customer = self.stripe.Customer.retrieve(identification)
response = customer.delete()
return {"status": "SUCCESS", "response": response}
except self.stripe.InvalidRequestError, error:
return {"status": "FAILURE", "response": error}

def credit(self, identification, money=None, options=None):
try:
charge = self.stripe.Charge.retrieve(identification)
response = charge.refund(amount=money)
return {"status": "SUCCESS", "response": response}
except self.stripe.InvalidRequestError, error:
return {"status": "FAILURE", "error": error}

def authorize(self, money, credit_card, options=None):
if not self.validate_card(credit_card):
raise InvalidCard("Invalid Card")
try:
token = self.stripe.Token.create(
card={
'number': credit_card.number,
'exp_month': credit_card.month,
'exp_year': credit_card.year,
'cvc': credit_card.verification_value
},
amount=money * 100
)
return {'status': "SUCCESS", "response": token}
except self.stripe.InvalidRequestError, error:
return {"status": "FAILURE", "response": error}

def capture(self, money, authorization, options=None):
try:
response = self.stripe.Charge.create(
amount=money * 100,
card=authorization,
currency="usd"
)
return {'status': "SUCCESS", "response": response}
except self.stripe.InvalidRequestError, error:
return {"status": "FAILURE", "response": error}
27 changes: 27 additions & 0 deletions billing/integrations/samurai_integration.py
@@ -0,0 +1,27 @@
from billing import Integration
from django.conf import settings
from django.conf.urls.defaults import patterns, url
from django.views.decorators.csrf import csrf_exempt
from django.http import HttpResponse
from billing.forms.samurai_forms import SamuraiForm


class SamuraiIntegration(Integration):
def __init__(self):
super(SamuraiIntegration, self).__init__()

def generate_form(self):
initial_data = self.fields
form = SamuraiForm(initial=initial_data)
return form


@csrf_exempt
def get_token(self, request):
token = request.POST['samuraiToken']
return HttpResponse('Success')

def get_urls(self):
urlpatterns = patterns('',
url('^samurai-get-token/$', self.get_token, name="get_token"),)
return urlpatterns
29 changes: 29 additions & 0 deletions billing/integrations/stripe_integration.py
@@ -0,0 +1,29 @@
from billing import Integration
from django.conf import settings
from django.conf.urls.defaults import patterns, url
import stripe
from billing.forms.stripe_forms import StripeForm
from django.views.decorators.csrf import csrf_exempt
from django.http import HttpResponse


class StripeIntegration(Integration):
def __init__(self):
super(StripeIntegration, self).__init__()
stripe.api_key = settings.STRIPE_API_KEY
self.stripe = stripe

def generate_form(self):
initial_data = self.fields
form = StripeForm(initial=initial_data)
return form

@csrf_exempt
def get_token(self, request):
token = request.POST['stripeToken']
return HttpResponse('Success')

def get_urls(self):
urlpatterns = patterns('',
url('^stripe-get-token/$', self.get_token, name="get_token"),)
return urlpatterns
6 changes: 6 additions & 0 deletions billing/templates/billing/samurai.html
@@ -0,0 +1,6 @@
<div class="payment-errors"> </div>
<form method="post" id="payment-form">{% csrf_token %}

{{ integration.generate_form.as_p }}
<input type="submit" value="Pay" class="submit-button"/>
</form>
6 changes: 6 additions & 0 deletions billing/templates/billing/stripe.html
@@ -0,0 +1,6 @@
<div class="payment-errors"> </div>
<form method="post" id="payment-form">{% csrf_token %}

{{ integration.generate_form.as_p }}
<input type="submit" value="Pay" class="submit-button"/>
</form>