Introduction
While Stripe is a developer favorite, PayPal remains a dominant force in global payments. Many users prefer PayPal for its trusted brand and ease of use (no credit card entry required if they have an account).
In this article, we'll explore how to add a "Pay with PayPal" button to your React app and handle the transaction verification on your Django backend.
The Architecture
The flow for PayPal is slightly different from Stripe's custom elements:
- Client-Side: Render the PayPal buttons using the PayPal JavaScript SDK.
- Client-Side: User approves the payment on PayPal's popup.
- Client-Side:
onApprovecallback triggers. - Backend: We verify the order ID with PayPal to ensure the transaction is valid before fulfilling the order.
Frontend: React with @paypal/react-paypal-js
PayPal provides an official React wrapper which makes integration smooth.
1. Installation
npm install @paypal/react-paypal-js
2. Implementation
Refrain from using the raw script tag; use the PayPalScriptProvider.
import { PayPalScriptProvider, PayPalButtons } from "@paypal/react-paypal-js";
import { useState } from "react";
export default function PayPalCheckout() {
const [success, setSuccess] = useState(false);
const [errorMessage, setErrorMessage] = useState("");
// Create the order on the client or call your backend to create it
const createOrder = (data, actions) => {
return actions.order.create({
purchase_units: [
{
amount: {
value: "10.00",
},
},
],
});
};
// Handle the payment approval
const onApprove = async (data, actions) => {
// Capture the funds from the transaction
const details = await actions.order.capture();
// Show a success message to the buyer
const name = details.payer.name.given_name;
alert(`Transaction completed by ${name}`);
// OPTIONAL: Call your backend to save the transaction
verifyTransaction(data.orderID);
};
const verifyTransaction = async (orderID) => {
try {
const response = await fetch('/api/verify-paypal-transaction/', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ orderID }),
});
const result = await response.json();
if (result.success) {
setSuccess(true);
}
} catch (err) {
setErrorMessage("Payment verification failed on server.");
}
};
return (
<PayPalScriptProvider options={{ "client-id": "test" }}>
<PayPalButtons
createOrder={createOrder}
onApprove={onApprove}
onError={(err) => setErrorMessage(err.toString())}
/>
{success && <div>Order verified and saved!</div>}
{errorMessage && <div className="text-red-500">{errorMessage}</div>}
</PayPalScriptProvider>
);
}
Backend: Django Verification
Although actions.order.capture() on the client captures the money, you should verify this on the server to prevent spoofing.
1. Install PayPal SDK (Optional) or use Requests
PayPal has a REST API. You can use requests to verify the token.
pip install requests
2. Verification View
import requests
from rest_framework.views import APIView
from rest_framework.response import Response
from django.conf import settings
class VerifyPayPalTransaction(APIView):
def post(self, request):
order_id = request.data.get('orderID')
# Get an access token first
client_id = settings.PAYPAL_CLIENT_ID
secret = settings.PAYPAL_SECRET
auth_response = requests.post(
'https://api-m.sandbox.paypal.com/v1/oauth2/token',
auth=(client_id, secret),
data={'grant_type': 'client_credentials'}
)
access_token = auth_response.json().get('access_token')
# Verify the order details
headers = {
'Authorization': f'Bearer {access_token}',
}
order_details = requests.get(
f'https://api-m.sandbox.paypal.com/v2/checkout/orders/{order_id}',
headers=headers
)
data = order_details.json()
if data['status'] == 'COMPLETED':
# Fulfill order logic here
return Response({'success': True})
return Response({'success': False, 'status': data['status']}, status=400)
PayPal vs. Stripe
| Feature | Stripe | PayPal |
|---|---|---|
| Customization | High (Custom Elements) | Medium (Smart Buttons) |
| Global Reach | Excellent | Ubiquitous |
| Fees | Standard (~2.9% + 30¢) | Standard (varies by region) |
| DX | Excellent | Good |
Conclusion
Adding PayPal gives your users more choice, often leading to higher conversion rates. With the react-paypal-js library, the integration is cleaner than ever.
Comments
Sign in to join the conversation