Add a new payment gateway to Oscar

3,071 views
Skip to first unread message

Loi Nguyen

unread,
Aug 5, 2015, 12:03:13 AM8/5/15
to django-oscar
Hi, I want to create a new payment gateway ingrate to Oscar. It use credit card to pay for order.
Can you give me some document or suggest me some payment gateway i should follow to create a new payment gateway.
Thanks a lot.

Joseph Gallagher

unread,
Aug 6, 2015, 12:33:34 AM8/6/15
to django-oscar
Hi Loi,

So I've used Stripe for credit card integration. It's not exactly obvious, and I owe everything to google but, once you've gone to Stripe and set up an account & installed Stripe in your virtualenv, what I've posted below should take care of the logic. You'll need to grab the test keys and set them in settings.py like so:

STRIPE_SECRET_KEY = "sk_test_....."
STRIPE_PUBLISHABLE_KEY = "pk_test_....."
STRIPE_CURRENCY = "USD"

Set these in your local checkout apps' __init__.py:

PAYMENT_EVENT_PURCHASE = 'Purchase'
PAYMENT_METHOD_STRIPE = 'Stripe'
STRIPE_EMAIL = 'stripeEmail'
STRIPE_TOKEN = 'stripeToken'

You will need to override the PaymentDetailsView to set the source and handle payment, as per the oscar docs:

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}

You can then create a payment facade in your local /apps/checkout. You won't be overriding an Oscar facade.py, since that doesn't exist in the checkout app. Something like this:

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))

Now register your forms in your local /apps/checkout/forms.py like so:

from django import forms


class StripeTokenForm(forms.Form):
stripeEmail = forms.EmailField(widget=forms.HiddenInput())
stripeToken = forms.CharField(widget=forms.HiddenInput())


Finally, in your payment_details.html template, you'll want this to allow Stripe's modal to pop up over your payment page:

{% 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 %}


Sorry for the mass of pasted code, but it should get you rolling. Assuming you're working with a minimally tweaked oscar app (form actions & redirects are the same as oscar's built-in), you should be able to use this code as is (setting your keys appropriately). 

Cheers,
Joseph

Loi Nguyen

unread,
Aug 6, 2015, 6:49:20 AM8/6/15
to django-oscar

Thanks a lot! It's a great help.

비아구라길라임

unread,
Jan 3, 2017, 4:49:08 AM1/3/17
to django-oscar
Thank you, Joseph. You are my hero!!

Andrew Edwards

unread,
Jan 5, 2017, 12:00:22 AM1/5/17
to django-oscar
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:

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))

instead of:

except stripe.CardError, e:
   
raise UnableToTakePayment(self.get_friendly_decline_message(e))
except stripe.StripeError, e:
   
raise InvalidGatewayRequestError(self.get_friendly_error_message(e))

**If you don't follow this next step, the transaction will never complete.**
I also had to add to my preview template in the block 'hiddenforms':
<div style="display:none">
    {%
block hiddenforms %}
        {{
stripe_token_form }}
    {%
endblock %}
</div>
This allowed the stripe payment details to persist to the preview page and so when the user clicks the place order button the payment is actually taken from the card.

One other thing I had to do was modify the else statement of the get_context_data method in your local PaymentDetailsView class such that the total price appears in the 'Pay' button of the Stripe form when you are entering payment details on the payment details page:

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

Hope this helps someone!

Message has been deleted

Ajibola L' Don jibson

unread,
Apr 23, 2018, 3:16:03 PM4/23/18
to django-oscar
Thanks a lot for this a life saver .. i really appreciate this ... saved me a lot of troubles

Ajibola L' Don jibson

unread,
Apr 23, 2018, 3:16:41 PM4/23/18
to django-oscar
It did help me a lot .. thanks 


On Thursday, January 5, 2017 at 5:00:22 AM UTC, Andrew Edwards wrote:
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!

Message has been deleted

A G

unread,
Nov 3, 2018, 11:59:57 PM11/3/18
to django-oscar
Hello! I am new in Django. Thank you for your solution. But i have a problem - After payement on the preview page, when order must be confirmed, i got error message
A problem occurred while processing payment for this order - no payment has been taken. Please contact customer services if this problem persists

Or its becouse payemtns runs in test mode? But how to test it then?
Can anybody help?

Thanks in advance!

четверг, 5 января 2017 г., 6:00:22 UTC+1 пользователь Andrew Edwards написал:

SammyJ

unread,
Nov 10, 2018, 1:23:34 AM11/10/18
to django-oscar
Hi, this error occurs when your payment form is invalid.Have you set up stripe in the checkout app?

Maybe you could check out this Solution on stackoverflow, look at the first answer. I guess it might help you solve your issue.

Dyoser

unread,
Dec 17, 2018, 11:45:45 AM12/17/18
to django-oscar



Hi Joseph , thanks for the step by step instruction....really helpful

But i've a question about where to put what in what folder.
I've a shop called tpwshop do i need to create an apps folder inside my shop folder and also a checkout one?

Is that the way to extend Oscar's payment?

If you could clarify this it would be an enormous help.


Here is a pic of my actual folder structure

oscar_folders.png


Thanks!
Message has been deleted

Pim Doodkorte

unread,
Jun 7, 2020, 9:34:51 AM6/7/20
to django-oscar
Does anyone know if and how it is possible to add another payment way, like Ideal? This should be possible with Stripe. Does anyone have any experiecen with this and can help me out? 
P.s. the above method works good for me, thanks!

Op woensdag 5 augustus 2015 06:03:13 UTC+2 schreef Loi Nguyen:

Daniel Butler

unread,
Jun 7, 2020, 2:34:34 PM6/7/20
to django...@googlegroups.com
Maybe check this out: 

I’ve never used it but it might help. 

--
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.
--
Thank you!

Daniel Butler

Nico Silva

unread,
Jan 12, 2023, 11:11:20 PM1/12/23
to django-oscar
any one here can help me whit WEBPAY ?   its a chilean company,  i need to implement it in django oscar please <3

Data Tips

unread,
Jan 31, 2023, 7:19:39 PM1/31/23
to django-oscar
anyone know how implement webpay ?

Veronica Jones

unread,
Feb 9, 2024, 11:00:16 AMFeb 9
to django-oscar
I am currently trying to integrate Stripe into Django-Oscar but feel that this code might be a little outdated now. Would any of y'all suggest an updated version of this code?

I am trying to figure it out myself, but am confused on how to split up the Stripe Payment 'form' from the submit button, while keeping whatever data was entered into the Stripe Payment 'form'. I put quotes around form because I am not referring to a Django form, but the Stripe embedded form.

I appreciate any help.

Global Psychedelic

unread,
Apr 21, 2024, 12:37:54 AM (13 days ago) Apr 21
to django-oscar
Mushrooms contain macronutrients that support a healthy immune system. According to the Mushroom Council, your immune system will benefit from mushrooms whose nutrients include: Selenium, which helps your body make antioxidant enzymes to prevent cell damage. Choose cremini or portabella mushrooms for the most benefit.😋


Check my telegram group for more information 

https://t.me/exotics_shop_1



Buy FIREMAN online 
https://t.me/exotics_shop_1/103
Buy lucky kush online 
https://t.me/exotics_shop_1/113
Buy gello gelato online 
https://t.me/exotics_shop_1/114
Buy grape fanta online 
https://t.me/exotics_shop_1/103
Buy tiramesu smalls online 
https://t.me/exotics_shop_1/97
Buy icebergs online
https://t.me/exotics_shop_1/107?single
Buy dabwoods × runtz disposable online 
https://t.me/exotics_shop_1/115?single
Buy wax crumble online 
https://t.me/exotics_shop_1/120?single
Buy golden teacher online 🍄
https://t.me/exotics_shop_1/121?single
Buy 3 grams runtz disposable vapes online 
https://t.me/exotics_shop_1/126?single
Buy polkadot bars online 
https://t.me/exotics_shop_1/128
Buy mushrooms online 
https://t.me/exotics_shop_1/130?single
Buy rosin dot bars online 
https://t.me/exotics_shop_1/132
Buy kiwano (heavy loadz) online 
https://t.me/exotics_shop_1/133?single
Buy mix and match d9  edibles online 
https://t.me/exotics_shop_1/137?single
Buy black cherry online 
https://t.me/exotics_shop_1/140
Buy FIREMAN 
Clone card available 
https://t.me/exotics_shop_1/169
Buy lsd sheets online 
https://t.me/exotics_shop_1/172
Buy polkatdot starter pack 🍄 online
https://t.me/exotics_shop_1/178?single
Buy edible candy online 
https://t.me/exotics_shop_1/180
Buy potent carbs 
https://t.me/exotics_shop_1/190?single
Buy persy snowcaps online 
https://t.me/exotics_shop_1/193?single
Buy galactic gummies online 
https://t.me/exotics_shop_1/210
Buy new cake cards online 
https://t.me/exotics_shop_1/214?single
Buy pure mdma online 
https://t.me/exotics_shop_1/215
Buy distillate online 
https://t.me/exotics_shop_1/217
Buy crumble online 
https://t.me/exotics_shop_1/218
Buy codeine online 
https://t.me/exotics_shop_1/221?single
Buy quagen online 
https://t.me/exotics_shop_1/223?single
Buy jeeter dispos online 
https://t.me/exotics_shop_1/230?single
Buy Columbia coke online 
https://t.me/exotics_shop_1/238
Buy inhale excellence online 
https://t.me/exotics_shop_1/103
Buy lucky kush online 
https://t.me/exotics_shop_1/113
Buy gello gelato online 
https://t.me/exotics_shop_1/114
Buy grape fanta online 
https://t.me/exotics_shop_1/103
Buy tiramesu smalls online 
https://t.me/exotics_shop_1/97
Buy icebergs online 
https://t.me/exotics_shop_1/107?single
https://t.me/exotics_shop_1/281?single
https://t.me/exotics_shop_1/282?single
https://t.me/exotics_shop_1/291
https://t.me/exotics_shop_1/292
https://t.me/exotics_shop_1/296
https://t.me/exotics_shop_1/299
https://t.me/exotics_shop_1/301

"Our commitment is to provide exceptional service, unparalleled quality, and personalized solutions to meet your unique needs. We strive to exceed your expectations and deliver results that make a lasting impact. Trust us to be your reliable partner in achieving your goals. Your satisfaction is our utmost priority."
Reply all
Reply to author
Forward
0 new messages