feat: deposit module — QR flow, PayDepositPage, BookingDetailPanel widget
- Backend: GET /api/pay/:slug (public) — returns active hold confirmation URL - PayDepositPage: public page /:slug/pay for guests (no login required) - DepositSettingsPage: QR code section with print button - BookingDetailPanel: DepositWidget in payment tab - Наличными / ЮКасса (QR) buttons - hold_created: copy link + refresh - hold_confirmed: release form (вернуть / списать) - Final status badges Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -288,6 +288,33 @@ const deposit: FastifyPluginAsync = async (fastify) => {
|
||||
},
|
||||
)
|
||||
|
||||
// ── GET /api/pay/:slug — public, no auth ─────────────────────────────────
|
||||
fastify.get<{ Params: { slug: string } }>(
|
||||
'/api/pay/:slug',
|
||||
async (request, reply) => {
|
||||
const { slug } = request.params
|
||||
const hotelId = await getHotelId(slug)
|
||||
if (!hotelId) return reply.code(404).send({ error: 'Not found' })
|
||||
|
||||
const { rows } = await db.query(
|
||||
`SELECT d.yookassa_confirmation_url, d.amount, h.name AS hotel_name
|
||||
FROM booking_deposits d
|
||||
JOIN hotels h ON h.id = d.hotel_id
|
||||
WHERE d.hotel_id = $1 AND d.status = 'hold_created'
|
||||
ORDER BY d.created_at DESC LIMIT 1`,
|
||||
[hotelId],
|
||||
)
|
||||
if (!rows[0]?.yookassa_confirmation_url) {
|
||||
return reply.code(404).send({ error: 'No active payment' })
|
||||
}
|
||||
return {
|
||||
confirmationUrl: rows[0].yookassa_confirmation_url,
|
||||
amount: rows[0].amount,
|
||||
hotelName: rows[0].hotel_name,
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
// ── POST /api/webhooks/yookassa ───────────────────────────────────────────
|
||||
fastify.post<{ Body: { event: string; object: { id: string; status: string } } }>(
|
||||
'/api/webhooks/yookassa',
|
||||
|
||||
Reference in New Issue
Block a user