Initial commit
This commit is contained in:
@@ -0,0 +1,28 @@
|
||||
import { NextResponse } from 'next/server'
|
||||
import { FrappeError, METHODS, frappeCall, registrationEnabled } from '@/lib/lukenya-api'
|
||||
|
||||
// Asks the backend to open a Paystack checkout for a saved entry and returns its link.
|
||||
export async function POST(req: Request) {
|
||||
if (!registrationEnabled()) {
|
||||
return NextResponse.json({ error: 'Online payment is not open yet.' }, { status: 403 })
|
||||
}
|
||||
const body = await req.json().catch(() => ({}))
|
||||
const registration = typeof body.registration === 'string' ? body.registration : ''
|
||||
if (!registration) return NextResponse.json({ error: 'No entry to pay for.' }, { status: 400 })
|
||||
|
||||
try {
|
||||
const result = await frappeCall<{ authorization_url: string; reference: string }>(METHODS.startPayment, {
|
||||
args: {
|
||||
registration,
|
||||
payment_token: typeof body.payment_token === 'string' ? body.payment_token : undefined,
|
||||
channel: body.channel === 'card' ? 'card' : 'mpesa',
|
||||
},
|
||||
post: true,
|
||||
})
|
||||
if (!result?.authorization_url) throw new Error('The payment page could not be opened.')
|
||||
return NextResponse.json(result)
|
||||
} catch (err) {
|
||||
const status = err instanceof FrappeError && err.status < 500 ? 400 : 502
|
||||
return NextResponse.json({ error: (err as Error).message }, { status })
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
import { NextResponse } from 'next/server'
|
||||
import { FrappeError, METHODS, frappeCall } from '@/lib/lukenya-api'
|
||||
|
||||
// Polled by /payment/return. The backend checks with Paystack itself before answering,
|
||||
// so the browser being sent back here never confirms a payment on its own.
|
||||
export async function GET(req: Request) {
|
||||
const reference = new URL(req.url).searchParams.get('reference') || ''
|
||||
if (!/^[A-Za-z0-9._-]{4,100}$/.test(reference)) {
|
||||
return NextResponse.json({ error: 'Missing or invalid payment reference.' }, { status: 400 })
|
||||
}
|
||||
try {
|
||||
const result = await frappeCall<Record<string, unknown>>(METHODS.paymentStatus, { args: { reference } })
|
||||
return NextResponse.json(result, { headers: { 'Cache-Control': 'no-store' } })
|
||||
} catch (err) {
|
||||
const status = (err as FrappeError).status
|
||||
if (status === 404) return NextResponse.json({ error: 'We could not find this payment.' }, { status: 404 })
|
||||
// The server re-checks with Paystack in the background; keep the runner on the waiting screen.
|
||||
return NextResponse.json({ status: 'Pending' }, { headers: { 'Cache-Control': 'no-store' } })
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user