Razorpay Python SDK
Official Python SDK for Razorpay — India's leading payment gateway. Current version: 2.0.1 (Mar 2026). Auth uses API key + secret tuple. All amounts in paise (1 INR = 100 paise) — not rupees. Payment flow: create order server-side → collect payment client-side → verify signature server-side. Signature verification is mandatory — skipping it is a security vulnerability. Test keys start with 'rzp_test_', live keys with 'rzp_live_'.
Warnings
- breaking All amounts are in paise (smallest currency unit) — NOT rupees. 500 INR must be passed as 50000. Passing 500 charges 5 paise (₹0.05). No error is raised — silent wrong charge.
- breaking Signature verification is mandatory after payment. Skipping it allows fraudulent payment_id injection. Never fulfill orders without calling verify_payment_signature().
- gotcha Test keys (rzp_test_) and live keys (rzp_live_) are different. Test payments don't transfer real money. Accidentally using live keys in development charges real users.
- gotcha Webhook signature uses a separate webhook secret — not the API secret. Using API secret for webhook verification raises SignatureVerificationError.
- gotcha payment_capture=1 in order.create auto-captures payment. Without it, payment is authorized but not captured — must manually call client.payment.capture(payment_id, amount).
- gotcha SDK method naming: client.payment (singular) not client.payments. client.order (singular) not client.orders. Common LLM error.
- gotcha Razorpay only supports INR for domestic payments. International currencies require Razorpay's international payment product with separate activation.
Install
-
pip install razorpay
Imports
- Client + order creation
import razorpay client = razorpay.Client(auth=('rzp_test_KEY', 'SECRET')) # Amount MUST be in paise — 500 INR = 50000 paise order = client.order.create({ 'amount': 50000, # 500 INR in paise 'currency': 'INR', 'receipt': 'order_rcpt_001', 'payment_capture': 1 # auto-capture payment }) print(order['id']) # pass this to frontend - verify_payment_signature
import razorpay client = razorpay.Client(auth=('rzp_test_KEY', 'SECRET')) # After frontend payment — MUST verify signature params = { 'razorpay_order_id': order_id, # from order creation 'razorpay_payment_id': payment_id, # from frontend callback 'razorpay_signature': signature # from frontend callback } try: client.utility.verify_payment_signature(params) # Signature valid — payment confirmed print('Payment verified') except razorpay.errors.SignatureVerificationError: # Signature invalid — do NOT fulfill order print('Payment verification failed')
Quickstart
# pip install razorpay
import razorpay
# Use test keys from dashboard.razorpay.com
client = razorpay.Client(auth=('rzp_test_YOUR_KEY', 'YOUR_SECRET'))
client.enable_retry(True) # retry on transient failures
# Step 1: Create order server-side
order = client.order.create({
'amount': 50000, # 500 INR in paise
'currency': 'INR',
'receipt': 'receipt_001',
'notes': {
'product': 'Widget',
'user_id': '123'
}
})
print('Order ID:', order['id'])
# Pass order['id'], key_id, amount to frontend Razorpay checkout
# Step 2: After frontend payment, verify signature
params = {
'razorpay_order_id': order['id'],
'razorpay_payment_id': 'pay_XXXX', # from frontend
'razorpay_signature': 'SIG_XXXX' # from frontend
}
try:
client.utility.verify_payment_signature(params)
print('Payment confirmed')
except razorpay.errors.SignatureVerificationError:
print('Invalid signature — reject payment')
# Fetch payment details
payment = client.payment.fetch('pay_XXXX')
print(payment['status'], payment['amount'])
# Refund
refund = client.payment.refund('pay_XXXX', {'amount': 50000})
print(refund['id'])