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()