feat/payment-link-flow #12

Merged
root merged 2 commits from feat/payment-link-flow into main 2025-11-22 05:01:18 +00:00
4 changed files with 14 additions and 11 deletions
Showing only changes of commit ec96b71161 - Show all commits

View File

@ -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

View File

@ -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 {

View File

@ -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) {

View File

@ -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
,
}
}
}