ifixkart-backend/app/core/razorpay.py

87 lines
3 KiB
Python

import razorpay
import hmac
import hashlib
import logging
from typing import Optional, Dict, Any
from app.core.config.Config import settings
logger = logging.getLogger("app.razorpay")
class RazorpayService:
def __init__(self):
self._client = None
@property
def client(self):
if self._client is None:
key_id = settings.RAZORPAY_KEY_ID
key_secret = settings.RAZORPAY_KEY_SECRET
if not key_id or not key_secret:
raise ValueError("Razorpay credentials (RAZORPAY_KEY_ID / RAZORPAY_KEY_SECRET) not configured.")
self._client = razorpay.Client(auth=(key_id, key_secret))
return self._client
def create_order(self, amount_paise: int, receipt: str, notes: Optional[Dict] = None) -> Dict[str, Any]:
"""
Creates a Razorpay Order.
"""
try:
data = {
"amount": amount_paise,
"currency": "INR",
"receipt": receipt,
"payment_capture": 1,
"notes": notes or {}
}
logger.info(f"Creating Razorpay Order for receipt {receipt}")
return self.client.order.create(data=data)
except Exception as e:
logger.error(f"Razorpay Order Creation Failed: {str(e)}")
raise
def verify_payment_signature(self, rzp_order_id: str, rzp_payment_id: str, rzp_signature: str) -> bool:
"""
Verifies HMAC-SHA256 signature returned by client-side Razorpay modal.
"""
try:
params_dict = {
'razorpay_order_id': rzp_order_id,
'razorpay_payment_id': rzp_payment_id,
'razorpay_signature': rzp_signature
}
self.client.utility.verify_payment_signature(params_dict)
return True
except Exception as e:
logger.warning(f"Razorpay Signature Verification Failed: {str(e)}")
return False
def fetch_payment(self, payment_id: str) -> Dict[str, Any]:
"""
Fetches payment details directly from Razorpay API for server-side verification.
"""
try:
return self.client.payment.fetch(payment_id)
except Exception as e:
logger.error(f"Razorpay Payment Fetch Failed: {str(e)}")
raise
def verify_webhook_signature(self, raw_body: bytes, signature: str) -> bool:
"""
Verifies Webhook signature using raw request body.
"""
secret = settings.RAZORPAY_WEBHOOK_SECRET
if not secret:
return False
try:
expected_signature = hmac.new(
secret.encode('utf-8'),
raw_body,
hashlib.sha256
).hexdigest()
return hmac.compare_digest(expected_signature, signature)
except Exception as e:
logger.warning(f"Webhook signature verification failed: {e}")
return False
razorpay_service = RazorpayService()