Add e-payment UI, checkout payment result, and legacy migrate domain lookup.

Wire Mellat settings in business dashboard, customer bank return page with payment details, and super-admin migrate modal domain confirmation.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Alireza Hassani
2026-08-13 09:51:22 +03:30
co-authored by Cursor
parent a11f9643bb
commit cc94b929e0
54 changed files with 6415 additions and 96 deletions
+48 -2
View File
@@ -46,7 +46,8 @@ export interface ShippingAddressInput {
export type CheckoutPaymentType = 'e_payment_gate' | 'transfer'
export type OnlineGatewayType = 'mellat_behpardakht' | 'saman_kish'
/** Matches backend PaymentGatewayId (mellat first; others later). */
export type OnlineGatewayType = 'mellat' | 'sep' | 'snappay' | 'digipay' | 'zarinpal'
export interface CheckoutPaymentInput {
type: CheckoutPaymentType
@@ -55,13 +56,33 @@ export interface CheckoutPaymentInput {
transferRefNumber?: string
}
export interface PaymentRedirect {
method: 'GET' | 'POST'
url: string
fields?: Record<string, string>
}
export interface CheckoutPaymentResult {
gatewayType: string
transactionId: string
redirect: PaymentRedirect
}
export interface CheckoutInput {
addressId?: string
shippingAddress?: ShippingAddressInput
customerNotes?: string
/** Absolute URL for bank callback return (required for e_payment_gate). */
returnUrl?: string
payment: CheckoutPaymentInput
}
export interface CheckoutResponse {
message: string
order: Order
payment?: CheckoutPaymentResult
}
function cartPath(suffix = '') {
const businessId = getActiveBusinessId()
if (!businessId) {
@@ -98,9 +119,34 @@ export async function removeCartItem(itemId: string) {
}
export async function checkoutCart(input: CheckoutInput) {
return apiRequest<{ message: string; order: Order }>(cartPath('/checkout'), {
return apiRequest<CheckoutResponse>(cartPath('/checkout'), {
method: 'POST',
auth: true,
body: input,
})
}
/** Submit a gateway redirect (POST form or GET navigation). */
export function submitPaymentRedirect(redirect: PaymentRedirect) {
if (redirect.method === 'GET') {
window.location.assign(redirect.url)
return
}
const form = document.createElement('form')
form.method = 'POST'
form.action = redirect.url
form.style.display = 'none'
form.acceptCharset = 'UTF-8'
for (const [name, value] of Object.entries(redirect.fields ?? {})) {
const input = document.createElement('input')
input.type = 'hidden'
input.name = name
input.value = value
form.appendChild(input)
}
document.body.appendChild(form)
form.submit()
}
@@ -38,6 +38,22 @@ export interface OrderCustomer {
email: string | null
}
export interface OrderTransaction {
id: string
type: string
status: string
amount: number
posType: string | null
gatewayType: string | null
gatewayRef: string | null
gatewayTrackId: string | null
transferAccount: string | null
transferRefNumber: string | null
notes: string | null
createdAt: string
updatedAt: string
}
export interface Order {
id: string
businessId: string
@@ -61,6 +77,7 @@ export interface Order {
updatedAt: string
customer: OrderCustomer
items: OrderItem[]
transactions?: OrderTransaction[]
}
export interface OrdersListResponse {