STRIPE_SECRET_KEY = "sk_test_....."
STRIPE_PUBLISHABLE_KEY = "pk_test_....."
STRIPE_CURRENCY = "USD"
PAYMENT_EVENT_PURCHASE = 'Purchase'
PAYMENT_METHOD_STRIPE = 'Stripe'
STRIPE_EMAIL = 'stripeEmail'
STRIPE_TOKEN = 'stripeToken'
from django.conf import settings
from oscar.core.loading import get_model
from django.utils.decorators import method_decorator
from django.views.decorators.csrf import csrf_exempt
from oscar.apps.checkout.views import PaymentDetailsView as CorePaymentDetailsView
from facade import Facade
from . import PAYMENT_METHOD_STRIPE, PAYMENT_EVENT_PURCHASE, STRIPE_EMAIL, STRIPE_TOKEN
import forms
SourceType = get_model('payment', 'SourceType')
Source = get_model('payment', 'Source')
class PaymentDetailsView(CorePaymentDetailsView):
@method_decorator(csrf_exempt)
def dispatch(self, request, *args, **kwargs):
return super(PaymentDetailsView, self).dispatch(request, *args, **kwargs)
def get_context_data(self, **kwargs):
ctx = super(PaymentDetailsView, self).get_context_data(**kwargs)
if self.preview:
ctx['stripe_token_form'] = forms.StripeTokenForm(self.request.POST)
ctx['order_total_incl_tax_cents'] = (
ctx['order_total'].incl_tax * 100
).to_integral_value()
else:
ctx['stripe_publishable_key'] = settings.STRIPE_PUBLISHABLE_KEY
return ctx
def handle_payment(self, order_number, total, **kwargs):
stripe_ref = Facade().charge(
order_number,
total,
card=self.request.POST[STRIPE_TOKEN],
description=self.payment_description(order_number, total, **kwargs),
metadata=self.payment_metadata(order_number, total, **kwargs))
source_type, __ = SourceType.objects.get_or_create(name=PAYMENT_METHOD_STRIPE)
source = Source(
source_type=source_type,
currency=settings.STRIPE_CURRENCY,
amount_allocated=total.incl_tax,
amount_debited=total.incl_tax,
reference=stripe_ref)
self.add_payment_source(source)
self.add_payment_event(PAYMENT_EVENT_PURCHASE, total.incl_tax)
def payment_description(self, order_number, total, **kwargs):
return self.request.POST[STRIPE_EMAIL]
def payment_metadata(self, order_number, total, **kwargs):
return {'order_number': order_number}
from django.conf import settings
from oscar.apps.payment.exceptions import UnableToTakePayment, InvalidGatewayRequestError
import stripe
class Facade(object):
def __init__(self):
stripe.api_key = settings.STRIPE_SECRET_KEY
@staticmethod
def get_friendly_decline_message(error):
return 'The transaction was declined by your bank - please check your bankcard details and try again'
@staticmethod
def get_friendly_error_message(error):
return 'An error occurred when communicating with the payment gateway.'
def charge(self,
order_number,
total,
card,
currency=settings.STRIPE_CURRENCY,
description=None,
metadata=None,
**kwargs):
try:
return stripe.Charge.create(
amount=(total.incl_tax * 100).to_integral_value(),
currency=currency,
card=card,
description=description,
metadata=(metadata or {'order_number': order_number}),
**kwargs).id
except stripe.CardError, e:
raise UnableToTakePayment(self.get_friendly_decline_message(e))
except stripe.StripeError, e:
raise InvalidGatewayRequestError(self.get_friendly_error_message(e))
from django import forms
class StripeTokenForm(forms.Form):
stripeEmail = forms.EmailField(widget=forms.HiddenInput())
stripeToken = forms.CharField(widget=forms.HiddenInput())
{% extends 'oscar/checkout/payment_details.html' %}
{% load currency_filters %}
{% block payment_details_content %}
<form action="{% url 'checkout:preview' %}" class="form-stacked" method="POST">
<script src="https://checkout.stripe.com/checkout.js" class="stripe-button"
data-key="{{ stripe_publishable_key }}" data-amount="{{ order_total_incl_tax_cents }}"
data-name="{{ shop_name }}"
data-description="{{ basket.num_items }} items ({{ order_total.incl_tax|currency }})">
</script>
</form>
{% endblock %}
except stripe.error.CardError as e:
raise UnableToTakePayment(self.get_friendly_decline_message(e))
except stripe.error.StripeError as e:
raise InvalidGatewayRequestError(self.get_friendly_error_message(e))
except stripe.CardError, e:
raise UnableToTakePayment(self.get_friendly_decline_message(e))
except stripe.StripeError, e:
raise InvalidGatewayRequestError(self.get_friendly_error_message(e))
<div style="display:none">
{% block hiddenforms %}
{{ stripe_token_form }}
{% endblock %}
</div>
def get_context_data(self, **kwargs):
ctx = super(PaymentDetailsView, self).get_context_data(**kwargs)
if self.preview:
ctx['stripe_token_form'] = forms.StripeTokenForm(self.request.POST)
ctx['order_total_incl_tax_cents'] = (
ctx['order_total'].incl_tax * 100
).to_integral_value()
else:
ctx['order_total_incl_tax_cents'] = (
ctx['order_total'].incl_tax * 100
).to_integral_value()
ctx['stripe_publishable_key'] = settings.STRIPE_PUBLISHABLE_KEY
return ctx
Awesome post Joseph!
I just wanted to update this for as of this post's creation time. I had to modify the end of the Facade class with:
---------------------
Hope this helps someone!
Here is a pic of my actual folder structure
--
https://github.com/django-oscar/django-oscar
http://django-oscar.readthedocs.org/en/latest/
https://twitter.com/django_oscar
---
You received this message because you are subscribed to the Google Groups "django-oscar" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-oscar...@googlegroups.com.
To view this discussion on the web, visit https://groups.google.com/d/msgid/django-oscar/c5c47623-e844-48a6-ab88-c067c7cb9cbfo%40googlegroups.com.