SolveEase Pay — Integration Guide
For product developers integrating with
pay.solveease.in
Overview
SolveEase Pay handles your payment collection in 3 simple steps:
- Create an order → your backend calls our API → we return a
paymentUrl - Redirect the customer → send the customer to
paymentUrl - Receive confirmation → we call your webhook + redirect customer back
Prerequisites
- Request an API key from the SolveEase DevOps team
- Store it securely as an environment variable — never expose in frontend code
- Set up a webhook endpoint in your product that can receive HTTPS POST requests
Step 1: Create an Order
Call our API from your backend (server-side only):
// Example: Node.js / Next.js API route
const response = await fetch('https://pay.solveease.in/api/v1/orders', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.SOLVEEASE_PAY_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
amount: 5000, // Amount in INR (₹5000)
currency: 'INR',
customer: {
name: 'Priya Sharma',
email: 'priya@example.com',
phone: '9876543210', // 10-digit Indian mobile
},
description: 'Mridu AI Pro - Monthly Subscription',
metadata: {
// Anything you need to identify this payment in your system
userId: 'usr_abc123',
planId: 'pro_monthly',
subscriptionId: 'sub_xyz',
},
returnUrl: 'https://mridu-ai.com/billing/success',
webhookUrl: 'https://mridu-ai.com/api/payments/webhook',
}),
});
const { orderId, paymentUrl } = await response.json();
// Save orderId in your DB, redirect customer to paymentUrl
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
amount | number | ✅ | Amount in INR (e.g. 5000 for ₹5000) |
currency | string | ✅ | Always "INR" for now |
customer.name | string | ✅ | Customer full name |
customer.email | string | ✅ | Customer email address |
customer.phone | string | ✅ | 10-digit mobile number |
description | string | ❌ | Short description shown on checkout |
metadata | object | ❌ | Any JSON data to associate with this payment |
returnUrl | string | ❌ | Where to redirect after payment (overrides default) |
webhookUrl | string | ❌ | Where to send payment events (overrides default) |
Response
{
"orderId": "se_ord_abc123def456",
"paymentUrl": "https://pay.solveease.in/pay/se_ord_abc123def456",
"expiresAt": "2026-08-03T15:05:00Z"
}
Step 2: Redirect the Customer
Redirect your customer to the paymentUrl. SolveEase Pay will show a branded checkout page.
// Next.js Server Action or API route
redirect(paymentUrl);
// Or client-side
window.location.href = paymentUrl;
The checkout page will:
- Show your product's branding (logo from your tenant config)
- Offer multiple payment methods (Card, UPI, Net Banking, Wallets)
- Handle the full Cashfree payment flow
Step 3: Receive Payment Confirmation
Option A: Webhook (Recommended)
We will POST to your webhookUrl after payment completes:
// Your webhook endpoint
import crypto from 'crypto';
export async function POST(req: Request) {
const body = await req.text();
const signature = req.headers.get('x-solveease-signature');
// VERIFY THE SIGNATURE (critical for security!)
const expectedSig = crypto
.createHmac('sha256', process.env.SOLVEEASE_WEBHOOK_SECRET!)
.update(body)
.digest('hex');
if (signature !== expectedSig) {
return new Response('Unauthorized', { status: 401 });
}
const event = JSON.parse(body);
switch (event.event) {
case 'payment.success':
// Activate subscription, send receipt, etc.
await activateSubscription(event.metadata.subscriptionId);
break;
case 'payment.failed':
// Handle failure
break;
}
return new Response('OK', { status: 200 });
}
Webhook Payload
{
"event": "payment.success",
"orderId": "se_ord_abc123def456",
"amount": 5000,
"currency": "INR",
"paidAt": "2026-08-02T15:10:00Z",
"customer": {
"name": "Priya Sharma",
"email": "priya@example.com",
"phone": "9876543210"
},
"metadata": {
"userId": "usr_abc123",
"subscriptionId": "sub_xyz"
}
}
Events: payment.success | payment.failed | payment.expired
Option B: Poll the Status API
const status = await fetch(
`https://pay.solveease.in/api/v1/orders/${orderId}`,
{
headers: { Authorization: `Bearer ${API_KEY}` }
}
).then(r => r.json());
// status.status: 'PENDING' | 'ACTIVE' | 'PAID' | 'FAILED' | 'EXPIRED'
Error Handling
| HTTP Status | Code | Meaning |
|---|---|---|
| 400 | VALIDATION_ERROR | Invalid request body |
| 401 | UNAUTHORIZED | Missing or invalid API key |
| 403 | FORBIDDEN | Tenant is disabled |
| 429 | RATE_LIMIT | Too many requests (100/min limit) |
| 500 | INTERNAL_ERROR | Server-side error |
Testing
Use these test credentials in your integration:
- Test API Key: Provided by DevOps team per environment
- Cashfree Sandbox Test Card:
4111111111111111, any future expiry, any CVV - UPI Test VPA:
success@cashfree - Failure Test Card:
4000000000000002
Set your environment to point to our staging server:
SOLVEEASE_PAY_API_URL=https://staging.pay.solveease.in
FAQ
Q: Can I send the amount from the frontend?
A: No. The amount is fixed at order creation (server-side). The browser never controls the payment amount.
Q: How long is a payment link valid?
A: 24 hours by default.
Q: What happens if my webhook endpoint is down?
A: We retry up to 5 times with exponential backoff (1m, 5m, 30m, 2h, 12h).
Q: Can I issue refunds?
A: Refund support is coming in v1.1. Contact DevOps for manual refunds in the meantime.