Spaces:
Running on CPU Upgrade
Download docs/RAZORPAY_SETUP.md from larxius/SentinelScan-WSS: direct link, hf CLI and curl.
- Browser
- Download file 5.59 kB
-
https://huggingface.co/spaces/larxius/SentinelScan-WSS/resolve/main/docs/RAZORPAY_SETUP.md
- Command line
-
hf download hf://spaces/larxius/SentinelScan-WSS/docs/RAZORPAY_SETUP.md
-
curl -L -o RAZORPAY_SETUP.md https://huggingface.co/spaces/larxius/SentinelScan-WSS/resolve/main/docs/RAZORPAY_SETUP.md
Razorpay Payments Setup (India + International)
LarShield pricing uses Razorpay for one-time plan purchases:
- INR checkout for Indian customers (UPI, cards, netbanking, wallets)
- USD checkout for international customers (international cards)
- A platform fee is added on top of the plan price at checkout
1. What the customer pays
| Line item | Calculation |
|---|---|
| Service price | Plan price from subscription_tiers |
| Platform fee | PLATFORM_FEE_PERCENT (default 2%) of the service price |
| GST | PLATFORM_FEE_GST_PERCENT (default 18%) of the platform fee, INR only |
| Total | Service + platform fee + GST |
Example (Quick Scan, INR):
Service price Rs.499.00
Platform fee (2%) Rs. 9.98
GST (18%) Rs. 1.80
Total payable Rs.510.78
USD checkouts add the 2% platform fee only (no Indian GST).
All amounts are recalculated server-side in minor units (paise/cents). The browser never sends an amount.
2. Create the Razorpay account
- Sign up at https://dashboard.razorpay.com/signup.
- Complete KYC (business PAN, bank account) to move from Test to Live.
- Enable international payments: Dashboard -> Account & Settings -> Payment methods -> International payments -> Request activation.
- Enable UPI / wallets / netbanking under Payment methods if they are not already on.
3. Get the API keys
Dashboard -> Account & Settings -> API Keys -> Generate Key.
You get:
Key ID rzp_test_xxxxxxxxxxxx (or rzp_live_...)
Key Secret xxxxxxxxxxxxxxxxxxxxxxxx
Store the Key ID and Key Secret only on the server (HF Secrets). The Key ID is sent to the browser as part of the order response; the Secret is never exposed.
4. Configure the webhook
Dashboard -> Account & Settings -> Webhooks -> Add New Webhook.
- URL:
https://<your-space>.hf.space/api/billing/webhook - Secret: choose a strong random string, save it as
RAZORPAY_WEBHOOK_SECRET - Active events:
payment.capturedorder.paidpayment.failed
The webhook is the safety net: if the customer closes the tab after paying, the webhook still activates the plan. Fulfilment is idempotent (same payment is never credited twice).
5. Environment variables
Set these in Hugging Face Space -> Settings -> Secrets (or in .env locally):
RAZORPAY_KEY_ID=rzp_test_xxxxxxxxxxxx
RAZORPAY_KEY_SECRET=xxxxxxxxxxxxxxxxxxxxxxxx
RAZORPAY_WEBHOOK_SECRET=whsec_your_random_secret
PLATFORM_FEE_PERCENT=2
PLATFORM_FEE_GST_PERCENT=18
USD_TO_INR_RATE=88
Then Factory Rebuild the Space.
6. How the flow works
Pricing card "Get Started"
|
v
POST /api/billing/quote -> service + fee + GST + total (displayed in modal)
|
v
POST /api/billing/create-order -> Razorpay order created, pending Payment row saved
|
v
Razorpay Checkout (UPI / card / netbanking / wallet / international card)
|
v
handler -> POST /api/billing/verify-payment
- HMAC SHA256 signature check
- amount + currency + order id confirmed with Razorpay
- organization tier upgraded
- +3 scan credits added
- audit log written
|
v
Success modal and page reload
Fallback: Razorpay webhook (payment.captured / order.paid)
performs the same activation if the browser never returns.
7. Test cards
Razorpay test mode:
| Method | Details |
|---|---|
| Card (success) | 4111 1111 1111 1111, any future expiry, CVV 123 |
| Card (failure) | 5104 0600 0000 0008 |
| UPI (success) | success@razorpay |
| UPI (failure) | failure@razorpay |
Test mode does not move real money.
8. What gets written to the database
payments row:
| Column | Meaning |
|---|---|
amount |
Total charged (service + fee + GST), minor units |
base_amount |
Service price, minor units |
platform_fee |
Platform fee, minor units |
tax_amount |
GST, minor units |
currency |
INR or USD |
razorpay_order_id |
Razorpay order id |
razorpay_payment_id |
Razorpay payment id (unique - idempotency) |
status |
created -> successful / failed |
tier_id |
quick / advanced / deep |
On success the app also:
- sets
organizations.subscription_tierto the purchased tier - adds
+3toorganization_scan_quotasfor that scan type - writes an
audit_logsentry
9. Admin controls
Super Admin -> Dashboard -> Dynamic Billing Control edits USD and INR prices.
The API is PUT /api/billing/tiers/<tier_id> and accepts:
{
"monthly_price": 499,
"yearly_price": 4990,
"monthly_price_inr": 49900,
"yearly_price_inr": 499000
}
All values are minor units.
10. Troubleshooting
| Symptom | Cause / fix |
|---|---|
Payment gateway is not configured yet |
RAZORPAY_KEY_ID / RAZORPAY_KEY_SECRET missing in Space Secrets, or Space not rebuilt |
Could not start the payment |
Invalid keys, or the Razorpay account is not activated for that currency |
| International cards fail | International payments not enabled in Razorpay Dashboard |
| Payment succeeds but plan not upgraded | Webhook URL/secret wrong, or verify-payment never reached. Open Razorpay Dashboard -> Payments, copy pay_... id, then contact support; the audit log will show whether fulfilment ran |
Invalid payment signature |
Wrong RAZORPAY_KEY_SECRET for the key id used to create the order |
| Old INR price shown | Update the tier in Super Admin -> Dynamic Billing Control |