Skip to content

Instantly share code, notes, and snippets.

@jerinisready
Last active October 29, 2023 20:21
Show Gist options
  • Save jerinisready/398e9c26a169c411977061d4693bde03 to your computer and use it in GitHub Desktop.
Save jerinisready/398e9c26a169c411977061d4693bde03 to your computer and use it in GitHub Desktop.
How to integrate Stripe payment in Django Oscar!
PAYMENT_EVENT_PURCHASE = 'Purchase'
PAYMENT_METHOD_STRIPE = 'Stripe'
STRIPE_EMAIL = 'stripeEmail'
STRIPE_TOKEN = 'stripeToken'
class AbstractFacade(object):
session = None
def __init__(self):
"""
Initializing Function. Set all api Keys here or create a client connection with name 'self.session'
"""
@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, token, currency='INR', description=None, metadata=None, **kwargs):
"""
'Facade.charge()' Function charges the required payment~
order_number: str => Reference number we should pass to provider.
total: float => Total Amount (inclusive of all taxs) to be charged for order.
token: string => Token generated by third party authentication Mechanism,
which is needed for triggering transaction.
currency: string => Currency code. eg: INR
description: string => Description shown along with the transaction.
metadata: dict => Description shown along with the transaction.
"""
from django.conf import settings
from oscar.apps.payment.exceptions import UnableToTakePayment, InvalidGatewayRequestError
import razorpay
from apps.checkout.facade__abstract_facade import AbstractFacade
class RazorPayFacade(AbstractFacade):
def __init__(self):
super().__init__()
self.session = razorpay.Client(auth=(settings.RAZOR_PAY_PUBLIC_KEY, settings.RAZOR_PAY_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_amount_incl_tax, token, currency=settings.PAYMENT_CURRENCY,
description=None, metadata=None, **kwargs):
self.session.payment.capture(token, "5000")
from django.conf import settings
from oscar.apps.payment.exceptions import UnableToTakePayment, InvalidGatewayRequestError
import stripe
from apps.checkout.facade__abstract_facade import AbstractFacade
class StripeFacade(AbstractFacade):
def __init__(self):
stripe.api_key = settings.RAZORPAY_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,
token,
currency=settings.PAYMENT_CURRENCY,
description=None,
metadata=None,
**kwargs):
try:
return stripe.Charge.create(
amount=(total.incl_tax * 100).to_integral_value(),
currency=currency,
card=token,
description=description,
metadata=(metadata or {'order_number': order_number}),
**kwargs).id
except stripe.CardError as e:
raise UnableToTakePayment(self.get_friendly_decline_message(e))
except stripe.StripeError as 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())
stripeTokenType = forms.CharField(widget=forms.HiddenInput(), required=False)
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 oscar.templatetags.currency_filters import currency
from apps.checkout.facade__stripe import StripeFacade as Facade
from . import PAYMENT_METHOD_STRIPE, PAYMENT_EVENT_PURCHASE, STRIPE_EMAIL, STRIPE_TOKEN
from apps.checkout import forms
SourceType = get_model('payment', 'SourceType')
Source = get_model('payment', 'Source')
"""
REQUIRED!
settings.STRIPE_PUBLIC_KEY = 'pk_test_pww_________________2235QtrBk9'
settings.STRIPE_SECRET_KEY = 'sk_test_5Li________________s00Lkbs47HE'
settings.PAYMENT_CURRENCY = 'INR'
"""
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)
else:
ctx['stripe_publishable_key'] = settings.STRIPE_PUBLIC_KEY
ctx['order_total_incl_tax_cents'] = (
ctx['order_total'].incl_tax * 100 # Rs 100.00 is needed as 10000
).to_integral_value()
ctx['shop_name'] = 'Project Name'
ctx['description'] = f'Payment with \'Project Name\' with an amount of {currency(ctx["order_total"].incl_tax)} INR '
return ctx
def handle_payment(self, order_number, total, **kwargs):
if self.request.POST['payment_method'] == 'cod':
return self.handle_cod(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.PAYMENT_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 handle_cod(self, order_number, total, **kwargs):
# https://github.com/jerinisready/django-oscar-cash-on-delivery/tree/master/cashondelivery
# https://stackoverflow.com/questions/43408588/implementing-django-oscar-cod
self.amount = float(total.excl_tax)
gateway_code = self.request.POST.get('gateway_code', None)
if gateway_code and gateway_code == 'cash-on-delivery':
# Record payment source and event
source_type, is_created = SourceType.objects.get_or_create(
name='cash-on-delivery')
source = source_type.sources.model(
source_type=source_type,
amount_allocated=total.excl_tax)
self.add_payment_source(source)
self.add_payment_event('CREATED', total.excl_tax)
return
def payment_description(self, order_number, total, **kwargs):
from datetime import datetime
from pytz import timezone
ist = timezone('Asia/Kolkata')
ist_time = datetime.now(ist)
return f"Payment with 'Project Name' against order #{order_number} with an amount of {total.incl_tax} INR on {ist_time.strftime('%Y-%m-%d_%H-%M-%S')}"
def payment_metadata(self, order_number, total, **kwargs):
return {'order_number': order_number, 'amount': total.incl_tax}
@koupro0204
Copy link

Nice to meet you I am currently trying to introduce Stripe to django-oscar. I was unsuccessful and found this code.
But it doesn't work. If you don't mind, could you also show other code such as Settings.py and urls.py?
I'm a beginner, so I can't understand well with only the published code.
I'm sorry, but please.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment