Move e-payment to Settings and add ZarinPal credentials.
Gateway config now lives on the general Settings page, with Mellat fields in a 3-column layout and ZarinPal available at checkout. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
co-authored by
Cursor
parent
9a59bc8f65
commit
e79211e3cd
@@ -7,9 +7,11 @@ import { ApiError, isAbortError } from '../../lib/api'
|
||||
import {
|
||||
checkoutCart,
|
||||
getCart,
|
||||
getPaymentMethods,
|
||||
submitPaymentRedirect,
|
||||
type CheckoutPaymentType,
|
||||
type OnlineGatewayType,
|
||||
type PublicPaymentGateway,
|
||||
} from '../../services/cartService'
|
||||
import { syncGuestCartToServer } from '../../services/syncGuestCart'
|
||||
import { formatIrtPrice } from '../../utils/irtPrice'
|
||||
@@ -17,11 +19,6 @@ import { CheckoutActionBar } from '../../components/checkout/CheckoutActionBar'
|
||||
import { CheckoutBackButton } from '../../components/checkout/CheckoutBackButton'
|
||||
import styles from './CheckoutSteps.module.css'
|
||||
|
||||
const ONLINE_GATEWAYS: { id: OnlineGatewayType; label: string; ready: boolean }[] = [
|
||||
{ id: 'mellat', label: 'درگاه پرداخت بانک ملت - بهپرداخت', ready: true },
|
||||
{ id: 'sep', label: 'درگاه پرداخت بانک سامان - سامان کیش', ready: false },
|
||||
]
|
||||
|
||||
export function CheckoutPaymentStep() {
|
||||
const navigate = useNavigate()
|
||||
const { showToast } = useToast()
|
||||
@@ -31,6 +28,8 @@ export function CheckoutPaymentStep() {
|
||||
const [loading, setLoading] = useState(true)
|
||||
const [submitting, setSubmitting] = useState(false)
|
||||
const [error, setError] = useState('')
|
||||
const [onlineGateways, setOnlineGateways] = useState<PublicPaymentGateway[]>([])
|
||||
const [onlinePaymentsEnabled, setOnlinePaymentsEnabled] = useState(false)
|
||||
const [paymentType, setPaymentType] = useState<CheckoutPaymentType>('e_payment_gate')
|
||||
const [gatewayType, setGatewayType] = useState<OnlineGatewayType>('mellat')
|
||||
const [transferAccount, setTransferAccount] = useState('')
|
||||
@@ -43,9 +42,13 @@ export function CheckoutPaymentStep() {
|
||||
async function load() {
|
||||
setLoading(true)
|
||||
try {
|
||||
let data = await getCart(controller.signal)
|
||||
const [cartResult, methodsResult] = await Promise.all([
|
||||
getCart(controller.signal),
|
||||
getPaymentMethods(controller.signal).catch(() => null),
|
||||
])
|
||||
if (controller.signal.aborted) return
|
||||
|
||||
let data = cartResult
|
||||
if (data.cart.items.length === 0) {
|
||||
try {
|
||||
const synced = await syncGuestCartToServer(controller.signal)
|
||||
@@ -59,6 +62,23 @@ export function CheckoutPaymentStep() {
|
||||
setSubtotal(data.cart.subtotal)
|
||||
if (data.cart.items.length === 0) {
|
||||
navigate('/checkout/cart', { replace: true })
|
||||
return
|
||||
}
|
||||
|
||||
const gateways = methodsResult?.gateways ?? []
|
||||
const enabled = Boolean(methodsResult?.enabled && gateways.length > 0)
|
||||
setOnlineGateways(gateways)
|
||||
setOnlinePaymentsEnabled(enabled)
|
||||
|
||||
if (enabled) {
|
||||
const preferred =
|
||||
(methodsResult?.defaultGateway &&
|
||||
gateways.find((g) => g.id === methodsResult.defaultGateway)?.id) ||
|
||||
gateways[0]?.id
|
||||
if (preferred) setGatewayType(preferred)
|
||||
setPaymentType('e_payment_gate')
|
||||
} else {
|
||||
setPaymentType('transfer')
|
||||
}
|
||||
} catch (err) {
|
||||
if (isAbortError(err)) return
|
||||
@@ -102,9 +122,8 @@ export function CheckoutPaymentStep() {
|
||||
}
|
||||
|
||||
if (paymentType === 'e_payment_gate') {
|
||||
const gateway = ONLINE_GATEWAYS.find((item) => item.id === gatewayType)
|
||||
if (!gateway?.ready) {
|
||||
setError('این درگاه هنوز فعال نیست. لطفاً ملت را انتخاب کنید.')
|
||||
if (!onlinePaymentsEnabled || !onlineGateways.some((g) => g.id === gatewayType)) {
|
||||
setError('درگاه پرداخت آنلاین در دسترس نیست. لطفاً روش دیگری انتخاب کنید.')
|
||||
return
|
||||
}
|
||||
}
|
||||
@@ -227,27 +246,29 @@ export function CheckoutPaymentStep() {
|
||||
<div className={styles.field}>
|
||||
<label>روش پرداخت</label>
|
||||
<div className={styles.paymentOptions}>
|
||||
<button
|
||||
type="button"
|
||||
className={[
|
||||
styles.paymentOption,
|
||||
paymentType === 'e_payment_gate' ? styles.paymentOptionActive : '',
|
||||
]
|
||||
.filter(Boolean)
|
||||
.join(' ')}
|
||||
onClick={() => setPaymentType('e_payment_gate')}
|
||||
disabled={submitting}
|
||||
>
|
||||
<CreditCard size={20} />
|
||||
<span className={styles.paymentOptionBody}>
|
||||
<span className={styles.paymentOptionTitle}>پرداخت آنلاین</span>
|
||||
<span className={styles.paymentOptionHint}>پرداخت امن از طریق درگاه</span>
|
||||
</span>
|
||||
</button>
|
||||
{onlinePaymentsEnabled ? (
|
||||
<button
|
||||
type="button"
|
||||
className={[
|
||||
styles.paymentOption,
|
||||
paymentType === 'e_payment_gate' ? styles.paymentOptionActive : '',
|
||||
]
|
||||
.filter(Boolean)
|
||||
.join(' ')}
|
||||
onClick={() => setPaymentType('e_payment_gate')}
|
||||
disabled={submitting}
|
||||
>
|
||||
<CreditCard size={20} />
|
||||
<span className={styles.paymentOptionBody}>
|
||||
<span className={styles.paymentOptionTitle}>پرداخت آنلاین</span>
|
||||
<span className={styles.paymentOptionHint}>پرداخت امن از طریق درگاه</span>
|
||||
</span>
|
||||
</button>
|
||||
) : null}
|
||||
|
||||
{paymentType === 'e_payment_gate' && (
|
||||
{onlinePaymentsEnabled && paymentType === 'e_payment_gate' && (
|
||||
<div className={styles.paymentSubOptions} role="radiogroup" aria-label="انتخاب درگاه">
|
||||
{ONLINE_GATEWAYS.map((gateway) => {
|
||||
{onlineGateways.map((gateway) => {
|
||||
const active = gatewayType === gateway.id
|
||||
return (
|
||||
<button
|
||||
@@ -262,15 +283,12 @@ export function CheckoutPaymentStep() {
|
||||
.filter(Boolean)
|
||||
.join(' ')}
|
||||
onClick={() => setGatewayType(gateway.id)}
|
||||
disabled={submitting || !gateway.ready}
|
||||
disabled={submitting}
|
||||
>
|
||||
<span className={styles.paymentSubRadio}>
|
||||
{active ? <span className={styles.paymentSubRadioInner} /> : null}
|
||||
</span>
|
||||
<span>
|
||||
{gateway.label}
|
||||
{!gateway.ready ? ' (بهزودی)' : ''}
|
||||
</span>
|
||||
<span>{gateway.labelFa || gateway.label}</span>
|
||||
</button>
|
||||
)
|
||||
})}
|
||||
|
||||
Reference in New Issue
Block a user