Ultimate Guide to Integrating Payment Gateways in Python, React, and DRF
Comments
Sign in to join the conversation
Monetizing your application is a critical step for many SaaS products and e-commerce platforms. In this guide, we'll walk through the process of integrating a robust payment gateway—Stripe—into a modern stack comprising a Python backend (specifically Django Rest Framework) and a React frontend.
We will cover:
While there are many libraries like PayPal, Braintree, and Razorpay, Stripe stands out for its developer-friendly API, comprehensive documentation, and robust testing environment.
First, install the Stripe python library:
pip install stripe
Add your keys to settings.py (use environment variables in production!):
# settings.py
import os
STRIPE_SECRET_KEY = os.environ.get('STRIPE_SECRET_KEY')
STRIPE_PUBLISHABLE_KEY = os.environ.get('STRIPE_PUBLISHABLE_KEY')
We need an endpoint that the frontend handles to initiate a payment. This endpoint creates a PaymentIntent on Stripe servers and returns the client_secret to the frontend.
# views.py
import stripe
from django.conf import settings
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
stripe.api_key = settings.STRIPE_SECRET_KEY
class CreatePaymentIntentView(APIView):
def post(self, request, *args, **kwargs):
try:
data = request.data
amount = data.get('amount') # Amount in cents
# Create a PaymentIntent with the order amount and currency
intent = stripe.PaymentIntent.create(
amountamount
Don't forget to register this view in your urls.py.
On the client side, we'll use react-stripe-js.
npm install @stripe/react-stripe-js @stripe/stripe-js
We need to wrap our payment elements in the Elements provider.
import React, { useState, useEffect } from "react";
import { loadStripe } from "@stripe/stripe-js";
import { Elements } from "@stripe/react-stripe-js";
import CheckoutForm from "./CheckoutForm";
// Make sure to call loadStripe outside of a component’s render to avoid
// recreating the Stripe object on every render.
const stripePromise = loadStripe("pk_test_..."); // Your Publishable Key
export default function App() {
const [clientSecret, setClientSecret
CheckoutForm Componentimport React, { useEffect, useState } from "react";
import {
PaymentElement,
useStripe,
useElements
} from "@stripe/react-stripe-js";
export default function CheckoutForm() {
const stripe = useStripe();
const elements = useElements();
const [message, setMessage] = useState(null);
const isLoading setIsLoading
To ensure your database stays in sync with Stripe (e.g., fulfilling orders only after a successful payment), you must use webhooks. Relying solely on the frontend redirect is insecure as the user can close the window before the redirect happens.
payment_intent.succeeded events.@csrf_exempt
def stripe_webhook(request):
payload = request.body
sig_header = request.META['HTTP_STRIPE_SIGNATURE']
event = None
try:
event = stripe.Webhook.construct_event(
payload, sig_header, settings.STRIPE_WEBHOOK_SECRET
)
except ValueError as e:
# Invalid payload
return HttpResponse(status=400)
except stripe.error.SignatureVerificationError as e:
# Invalid signature
return HttpResponse(status=400)
# Handle the event
While Stripe is a giant, there are other noteworthy options:
Integrating payments creates a bridge between your users and your value proposition. By using Django Rest Framework for secure backend handling and React for a seamless frontend experience, you can build a professional-grade checkout flow. Always use webhooks for reliability and keep your API keys secure!