Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 19 additions & 15 deletions src/api/forms.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,23 @@ export interface FieldValidation {
}

// Individual form field definition with all possible properties
export interface PaymentOptions {
amount: number
currency?: string
description?: string
// Merchant / branding
businessName?: string // Shown as merchant name in Razorpay modal
logoUrl?: string // Merchant logo URL (optional)
themeColor?: string // Hex color for Razorpay modal (#rrggbb)
// Prefill respondent info
prefillName?: string
prefillEmail?: string
prefillContact?: string
// Receipt/notes
receiptPrefix?: string // e.g. "invoice", "order" — prefixed to receipt ID
notes?: string // Payment notes visible on Razorpay dashboard
}

export interface FormField {
id: string // Unique field identifier
fieldName: string // Internal field name (used in API)
Expand All @@ -37,7 +54,7 @@ export interface FormField {
min?: number // Minimum value for numeric fields
max?: number // Maximum value for numeric fields
step?: number // Step increment for numeric fields
options?: Array<string> // Options for select/radio/checkbox fields
options?: Array<string> | PaymentOptions // Options for select/radio/checkbox/payment fields
}

// Form definition containing metadata and optional fields
Expand Down Expand Up @@ -86,20 +103,7 @@ export interface CreateFieldInput {
min?: number
max?: number
step?: number
options?: Array<string>
}

export interface UpdateFieldInput {
fieldName?: string
label?: string
fieldValueType?: string
fieldType?: string
validation?: FieldValidation
placeholder?: string
min?: number
max?: number
step?: number
options?: Array<string>
options?: Array<string> | PaymentOptions
}

// Base URL for API endpoints
Expand Down
118 changes: 118 additions & 0 deletions src/api/payments.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
/**
* Payments API Layer (Razorpay)
*
* Handles all payment-related API calls:
* - Creating Razorpay orders
* - Verifying payment signatures
* - Checking payment status
* - Getting Razorpay key for frontend checkout
*/

export interface CreateOrderResponse {
orderId: string
amount: number
currency: string
keyId: string
}

export interface VerifyPaymentResponse {
orderId: string
paymentId: string
status: string
}

export interface PaymentStatus {
status: string
amount: number
currency: string
}

export interface RazorpayConfig {
keyId: string
}

interface ApiResponse<T> {
success: boolean
message?: string
data: T
}

const API_URL = import.meta.env.VITE_API_URL || 'http://localhost:8000'

async function handleResponse<T>(response: Response): Promise<T> {
const result: ApiResponse<T> = await response.json()
if (!response.ok || !result.success) {
throw new Error(result.message || `Request failed: ${response.statusText}`)
}
return result.data
}

export const paymentsApi = {
/**
* Create a Razorpay order for a payment field
*/
createOrder: async (
formId: string,
fieldId: string,
params: {
amount: number
currency?: string
responseId?: string
},
): Promise<CreateOrderResponse> => {
const response = await fetch(
`${API_URL}/payments/order/${formId}/${fieldId}`,
{
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(params),
credentials: 'include',
},
)
return handleResponse<CreateOrderResponse>(response)
},

/**
* Verify payment after Razorpay checkout callback
*/
verify: async (params: {
razorpay_order_id: string
razorpay_payment_id: string
razorpay_signature: string
formId: string
fieldId: string
responseId?: string
}): Promise<VerifyPaymentResponse> => {
const response = await fetch(`${API_URL}/payments/verify`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(params),
credentials: 'include',
})
return handleResponse<VerifyPaymentResponse>(response)
},

/**
* Get payment status by Razorpay order ID
*/
getStatus: async (orderId: string): Promise<PaymentStatus> => {
const response = await fetch(`${API_URL}/payments/status/${orderId}`, {
method: 'GET',
headers: { 'Content-Type': 'application/json' },
credentials: 'include',
})
return handleResponse<PaymentStatus>(response)
},

/**
* Get Razorpay key ID for frontend checkout
*/
getConfig: async (): Promise<RazorpayConfig> => {
const response = await fetch(`${API_URL}/payments/config`, {
method: 'GET',
headers: { 'Content-Type': 'application/json' },
credentials: 'include',
})
return handleResponse<RazorpayConfig>(response)
},
}
Loading
Loading