Server : Apache System : Linux webd003.cluster111.gra.hosting.ovh.net 5.15.206-ovh-vps-grsec-zfs-classid #1 SMP Fri May 15 02:41:25 UTC 2026 x86_64 User : edevmultrx ( 811899) PHP Version : 7.4.33 Disable Function : _dyuweyrj4,_dyuweyrj4r,dl Directory : /home/edevmultrx/www/terra-d-oro/api/ |
<?php
/**
* Terra D'Oro — Resume Payment Endpoint
* Route: GET /api/resume-payment?bid=X&tok=Y
*
* Clicked from the reminder email. Steps:
* 1. Validate the HMAC token (prevents forged booking IDs)
* 2. Fetch the booking
* 3. If already paid → redirect to home (graceful)
* 4. Check availability (dates may have been taken since the email was sent)
* 5. Rebuild session flash so /confirmation can display a summary
* 6. Create a fresh Stripe Checkout session
* 7. Redirect to Stripe
*
* Token generation (in send-reminders.php):
* hash_hmac('sha256', 'resume:{id}:{created_at}', STRIPE_SECRET_KEY)
*/
declare(strict_types=1);
if (!defined('ROOT_PATH')) {
define('ROOT_PATH', dirname(__DIR__));
}
require_once ROOT_PATH . '/core/config.php';
require_once ROOT_PATH . '/core/db.php';
require_once ROOT_PATH . '/core/helpers.php';
require_once ROOT_PATH . '/core/payment.php';
// ── Input ─────────────────────────────────────────────────────────────────────
$booking_id = (int) ($_GET['bid'] ?? 0);
$token = trim( $_GET['tok'] ?? '');
// ── Helpers ───────────────────────────────────────────────────────────────────
function rp_redirect(string $reason): never
{
header('Location: ' . BASE_URL . '/erreur-reservation?reason=' . $reason);
exit;
}
// ── Validate params ───────────────────────────────────────────────────────────
if ($booking_id <= 0 || $token === '') {
rp_redirect('invalid_link');
}
// ── Fetch booking ─────────────────────────────────────────────────────────────
$stmt = $db->prepare(
"SELECT b.id, b.unit_id, b.guest_name, b.guest_email,
b.check_in, b.check_out, b.total_price, b.paid_amount,
b.created_at, b.status,
u.name AS unit_name, u.slug AS unit_slug
FROM `" . TBL_BOOKINGS . "` b
JOIN `" . TBL_UNITS . "` u ON u.id = b.unit_id
WHERE b.id = :id
LIMIT 1"
);
$stmt->execute([':id' => $booking_id]);
$booking = $stmt->fetch();
if (!$booking) {
rp_redirect('not_found');
}
// ── Verify HMAC token ─────────────────────────────────────────────────────────
$expected = hash_hmac(
'sha256',
'resume:' . $booking['id'] . ':' . $booking['created_at'],
STRIPE_SECRET_KEY
);
if (!hash_equals($expected, $token)) {
rp_redirect('invalid_link');
}
// ── Already paid? ─────────────────────────────────────────────────────────────
if (in_array($booking['status'], ['confirmed', 'deposit_paid'], true)) {
// Graceful: don't show an error, just redirect home
header('Location: ' . BASE_URL);
exit;
}
// ── Availability check ────────────────────────────────────────────────────────
// awaiting_payment does not block availability, so no need to exclude self.
// If another booking has confirmed the dates → redirect to occupied error.
if (!is_available($db, (int) $booking['unit_id'], $booking['check_in'], $booking['check_out'])) {
rp_redirect('occupied');
}
// ── Determine original payment intent ─────────────────────────────────────────
$total = (float) $booking['total_price'];
$paid = (float) $booking['paid_amount'];
$deposit = round($total * DEPOSIT_PERCENTAGE / 100, 2);
$is_deposit = $total > 0 && abs($paid - $deposit) < 1.00;
$charge_amount = $is_deposit ? $deposit : $total;
$balance = round($total - $charge_amount, 2);
$payment_label = $is_deposit
? 'Acompte ' . DEPOSIT_PERCENTAGE . '% — ' . $booking['unit_name']
: 'Paiement intégral — ' . $booking['unit_name'];
// ── Rebuild session flash (for /confirmation display after Stripe redirect) ──
if (session_status() === PHP_SESSION_NONE) {
session_name(SESSION_NAME);
session_start();
}
$_SESSION['booking_pending'] = [
'booking_id' => $booking['id'],
'unit_name' => $booking['unit_name'],
'unit_slug' => $booking['unit_slug'],
'guest_name' => $booking['guest_name'],
'guest_email' => $booking['guest_email'],
'check_in' => $booking['check_in'],
'check_out' => $booking['check_out'],
'nights' => nights_between($booking['check_in'], $booking['check_out']),
'total' => $total,
'deposit' => $charge_amount,
'balance' => $balance,
'payment_type' => $is_deposit ? 'deposit' : 'full',
];
// ── Create fresh Stripe session ───────────────────────────────────────────────
try {
$stripe_url = create_stripe_session(
(int) $booking['id'],
$charge_amount,
$booking['unit_name'],
$booking['check_in'],
$booking['check_out'],
$booking['guest_email'],
$payment_label
);
} catch (RuntimeException) {
rp_redirect('payment_failed');
}
// ── Redirect to Stripe ────────────────────────────────────────────────────────
header('Location: ' . $stripe_url);
exit;