feat/payment-link-flow #12
|
|
@ -2,9 +2,9 @@
|
|||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
||||
<link rel="icon" type="image/png" href="/simaya.png"/>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>core-midtrans-cifo</title>
|
||||
<title>Simaya Midtrans | Retail Payment</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
|
|
|
|||
Binary file not shown.
|
After Width: | Height: | Size: 98 KiB |
|
|
@ -124,7 +124,7 @@ const ENABLE = {
|
|||
// --- Payment Link Config
|
||||
const EXTERNAL_API_KEY = process.env.EXTERNAL_API_KEY || ''
|
||||
const PAYMENT_LINK_SECRET = process.env.PAYMENT_LINK_SECRET || ''
|
||||
const PAYMENT_LINK_TTL_MINUTES = parseInt(process.env.PAYMENT_LINK_TTL_MINUTES || '30', 10)
|
||||
const PAYMENT_LINK_TTL_MINUTES = parseInt(process.env.PAYMENT_LINK_TTL_MINUTES || '1440', 10)
|
||||
const PAYMENT_LINK_BASE = process.env.PAYMENT_LINK_BASE || 'http://localhost:5174/pay'
|
||||
const activeOrders = new Map() // order_id -> expire_at
|
||||
// Map untuk menyimpan mercant_id per order_id agar notifikasi ERP bisa dinamis
|
||||
|
|
@ -234,7 +234,7 @@ app.get('/api/payment-links/:token', (req, res) => {
|
|||
if (result.error) {
|
||||
logWarn('paymentlink.invalid', { error: result.error })
|
||||
if (isDevEnv()) {
|
||||
const ttlMin = PAYMENT_LINK_TTL_MINUTES > 0 ? PAYMENT_LINK_TTL_MINUTES : 30
|
||||
const ttlMin = PAYMENT_LINK_TTL_MINUTES > 0 ? PAYMENT_LINK_TTL_MINUTES : 1440
|
||||
const fallback = { order_id: token, nominal: 150000, expire_at: Date.now() + ttlMin * 60 * 1000 }
|
||||
logInfo('paymentlink.dev.fallback', { order_id: fallback.order_id })
|
||||
return res.json(fallback)
|
||||
|
|
@ -386,7 +386,7 @@ app.post('/createtransaksi', async (req, res) => {
|
|||
}
|
||||
const nominal = Number(nominalRaw)
|
||||
const now = Date.now()
|
||||
const ttlMin = PAYMENT_LINK_TTL_MINUTES > 0 ? PAYMENT_LINK_TTL_MINUTES : 30
|
||||
const ttlMin = PAYMENT_LINK_TTL_MINUTES > 0 ? PAYMENT_LINK_TTL_MINUTES : 1440
|
||||
const expire_at = now + ttlMin * 60 * 1000
|
||||
|
||||
// Block jika sudah selesai
|
||||
|
|
|
|||
|
|
@ -14,9 +14,10 @@ function useCountdown(expireAt: number) {
|
|||
}, [])
|
||||
const remainMs = Math.max(0, expireAt - now)
|
||||
const totalSec = Math.floor(remainMs / 1000)
|
||||
const mm = String(Math.floor(totalSec / 60)).padStart(2, '0')
|
||||
const hh = String(Math.floor(totalSec / 3600)).padStart(2, '0')
|
||||
const mm = String(Math.floor((totalSec % 3600) / 60)).padStart(2, '0')
|
||||
const ss = String(totalSec % 60).padStart(2, '0')
|
||||
return `${mm}:${ss}`
|
||||
return `${hh}:${mm}:${ss}`
|
||||
}
|
||||
|
||||
export interface PaymentSheetProps {
|
||||
|
|
@ -93,4 +94,4 @@ export function PaymentSheet({ merchantName = 'Simaya', orderId, amount, expireA
|
|||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ export function PayPage() {
|
|||
const { token } = useParams()
|
||||
const [orderId, setOrderId] = useState<string>('')
|
||||
const [amount, setAmount] = useState<number>(0)
|
||||
const [expireAt, setExpireAt] = useState<number>(Date.now() + 30 * 60 * 1000)
|
||||
const [expireAt, setExpireAt] = useState<number>(Date.now() + 24 * 60 * 60 * 1000)
|
||||
const [selectedMethod, setSelectedMethod] = useState<Method>(null)
|
||||
const [locked, setLocked] = useState<boolean>(false)
|
||||
const [selectedBank, setSelectedBank] = useState<BankKey | null>(null)
|
||||
|
|
@ -39,7 +39,7 @@ export function PayPage() {
|
|||
if (cancelled) return
|
||||
setOrderId(payload.order_id)
|
||||
setAmount(payload.nominal)
|
||||
setExpireAt(payload.expire_at ?? Date.now() + 30 * 60 * 1000)
|
||||
setExpireAt(payload.expire_at ?? Date.now() + 24 * 60 * 60 * 1000)
|
||||
setAllowedMethods(payload.allowed_methods)
|
||||
setError(null)
|
||||
} catch (err) {
|
||||
|
|
@ -245,4 +245,4 @@ export function PayPage() {
|
|||
</div>
|
||||
</PaymentSheet>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -137,14 +137,16 @@ export async function getPaymentLinkPayload(token: string): Promise<PaymentLinkP
|
|||
order_id: json.order_id || token,
|
||||
nominal: Number(json.nominal) || 150000,
|
||||
customer: json.customer || {},
|
||||
expire_at: json.expire_at || Date.now() + 30 * 60 * 1000,
|
||||
expire_at: json.expire_at || Date.now() + 24 * 60 * 60 * 1000
|
||||
,
|
||||
allowed_methods: json.allowed_methods || undefined,
|
||||
}
|
||||
} catch {
|
||||
return {
|
||||
order_id: token,
|
||||
nominal: 150000,
|
||||
expire_at: Date.now() + 30 * 60 * 1000,
|
||||
expire_at: Date.now() + 24 * 60 * 60 * 1000
|
||||
,
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue