87 lines
3 KiB
Python
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()
|