269 lines
9.3 KiB
PHP
269 lines
9.3 KiB
PHP
<?php
|
||
/**
|
||
* Demo: Cart / Checkout Page
|
||
* Shows how to embed paypal-checkout-widget.php on a multi-item cart page.
|
||
*
|
||
* In your real app, replace $school, $cartItems, and $buyerEmail
|
||
* with values from your session and database.
|
||
*/
|
||
|
||
require_once __DIR__ . '/demo-helper.php';
|
||
|
||
// ── In your real app these come from session / DB ─────────────────────────────
|
||
// Auto-resolve to a PayPal-connected school so the buttons actually render.
|
||
// (Pass ?school=Name to force a specific connected school.)
|
||
$school = pp_demo_resolve_school($_GET['school'] ?? null);
|
||
$schoolReady = $school !== null;
|
||
$schoolLabel = $school ?? 'Demo School';
|
||
$buyerEmail = ''; // e.g. $_SESSION['user']['email']
|
||
|
||
$cartItems = [
|
||
['name' => 'Monthly Lunch Plan — October', 'qty' => 1, 'price' => 95.00, 'emoji' => '🍱'],
|
||
['name' => 'Morning Snack Pack × 20 days', 'qty' => 1, 'price' => 28.00, 'emoji' => '🥐'],
|
||
['name' => 'Juice Box Bundle × 20 days', 'qty' => 1, 'price' => 14.00, 'emoji' => '🧃'],
|
||
];
|
||
$currency = 'USD';
|
||
// ── End of real-app variables ─────────────────────────────────────────────────
|
||
|
||
// Calculate total + build PayPal line items
|
||
$total = 0.0;
|
||
$ppItems = [];
|
||
foreach ($cartItems as $item) {
|
||
$lineTotal = $item['price'] * $item['qty'];
|
||
$total += $lineTotal;
|
||
$ppItems[] = [
|
||
'name' => $item['name'],
|
||
'quantity' => (string)$item['qty'],
|
||
'unit_amount' => ['currency_code' => $currency, 'value' => number_format($item['price'], 2, '.', '')],
|
||
];
|
||
}
|
||
|
||
$ppCheckout = [
|
||
'school_name' => $schoolLabel,
|
||
'amount' => number_format($total, 2, '.', ''),
|
||
'currency' => $currency,
|
||
'items' => $ppItems,
|
||
'buyer_email' => $buyerEmail,
|
||
'page_type' => 'cart', // tells PayPal this is a cart page
|
||
'order_api_url' => './order-api.php',
|
||
'success_url' => './demo-success.php?school=' . urlencode($schoolLabel),
|
||
'cancel_url' => './demo-cart.php',
|
||
];
|
||
?>
|
||
<!DOCTYPE html>
|
||
<html lang="en">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
<title>Your Cart — <?= htmlspecialchars($schoolLabel) ?></title>
|
||
<style>
|
||
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
|
||
body {
|
||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
||
background: #f7f8fa;
|
||
color: #1a202c;
|
||
}
|
||
|
||
/* ── Top bar ── */
|
||
.topbar {
|
||
background: #fff;
|
||
border-bottom: 1px solid #e2e8f0;
|
||
padding: 14px 24px;
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 12px;
|
||
}
|
||
.topbar-logo { font-size: 22px; }
|
||
.topbar-name { font-weight: 700; font-size: 17px; color: #003087; }
|
||
.topbar-school { font-size: 13px; color: #718096; margin-left: auto; }
|
||
.topbar-back {
|
||
font-size: 13px; color: #003087; text-decoration: none;
|
||
padding: 6px 14px; border: 1px solid #bee3f8; border-radius: 6px;
|
||
background: #ebf8ff;
|
||
}
|
||
|
||
/* ── Layout ── */
|
||
.page { max-width: 960px; margin: 32px auto; padding: 0 20px; display: grid; grid-template-columns: 1fr 400px; gap: 28px; align-items: start; }
|
||
@media (max-width: 700px) { .page { grid-template-columns: 1fr; } }
|
||
|
||
/* ── Cart items ── */
|
||
.cart-card {
|
||
background: #fff;
|
||
border-radius: 12px;
|
||
border: 1px solid #e2e8f0;
|
||
overflow: hidden;
|
||
}
|
||
.cart-header {
|
||
padding: 18px 24px;
|
||
border-bottom: 1px solid #e2e8f0;
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
}
|
||
.cart-header h2 { font-size: 17px; font-weight: 700; }
|
||
.cart-count { font-size: 13px; color: #718096; }
|
||
.cart-item {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 16px;
|
||
padding: 16px 24px;
|
||
border-bottom: 1px solid #f0f0f0;
|
||
}
|
||
.cart-item:last-child { border-bottom: none; }
|
||
.cart-item-emoji { font-size: 32px; flex-shrink: 0; }
|
||
.cart-item-name { font-size: 15px; font-weight: 600; margin-bottom: 3px; }
|
||
.cart-item-sub { font-size: 13px; color: #718096; }
|
||
.cart-item-price { margin-left: auto; font-size: 16px; font-weight: 700; white-space: nowrap; }
|
||
|
||
/* ── Order summary panel ── */
|
||
.summary-panel {
|
||
background: #fff;
|
||
border-radius: 12px;
|
||
border: 1px solid #e2e8f0;
|
||
padding: 24px;
|
||
position: sticky;
|
||
top: 24px;
|
||
}
|
||
.summary-title { font-size: 16px; font-weight: 700; margin-bottom: 18px; }
|
||
.summary-row {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
font-size: 14px;
|
||
color: #4a5568;
|
||
padding: 6px 0;
|
||
}
|
||
.summary-row.total {
|
||
border-top: 2px solid #e2e8f0;
|
||
margin-top: 8px;
|
||
padding-top: 14px;
|
||
font-size: 18px;
|
||
font-weight: 700;
|
||
color: #1a202c;
|
||
}
|
||
.summary-divider { margin: 20px 0; }
|
||
|
||
/* ── Card payment fallback ── */
|
||
.card-section h4 { font-size: 14px; font-weight: 600; color: #4a5568; margin-bottom: 14px; }
|
||
.card-field {
|
||
border: 1.5px solid #e2e8f0; border-radius: 8px;
|
||
padding: 11px 14px; font-size: 15px; width: 100%;
|
||
margin-bottom: 12px; color: #a0aec0;
|
||
}
|
||
.card-row { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
|
||
.btn-card {
|
||
width: 100%; padding: 13px;
|
||
background: #2d3748; color: #fff;
|
||
border: none; border-radius: 8px;
|
||
font-size: 15px; font-weight: 600; cursor: pointer; margin-top: 4px;
|
||
}
|
||
.btn-card:hover { background: #1a202c; }
|
||
.secure-note {
|
||
text-align: center; font-size: 12px; color: #a0aec0; margin-top: 14px;
|
||
display: flex; align-items: center; justify-content: center; gap: 4px;
|
||
}
|
||
</style>
|
||
</head>
|
||
<body>
|
||
|
||
<nav class="topbar">
|
||
<span class="topbar-logo">🍽️</span>
|
||
<span class="topbar-name">HotLunches</span>
|
||
<a href="demo-product.php?school=<?= urlencode($schoolLabel) ?>" class="topbar-back">← Continue shopping</a>
|
||
<span class="topbar-school"><?= htmlspecialchars($schoolLabel) ?></span>
|
||
</nav>
|
||
|
||
<div class="page">
|
||
|
||
<!-- Left: cart items -->
|
||
<div>
|
||
<div class="cart-card">
|
||
<div class="cart-header">
|
||
<h2>Your Order</h2>
|
||
<span class="cart-count"><?= count($cartItems) ?> item<?= count($cartItems) > 1 ? 's' : '' ?></span>
|
||
</div>
|
||
|
||
<?php foreach ($cartItems as $item): ?>
|
||
<div class="cart-item">
|
||
<div class="cart-item-emoji"><?= $item['emoji'] ?></div>
|
||
<div>
|
||
<div class="cart-item-name"><?= htmlspecialchars($item['name']) ?></div>
|
||
<div class="cart-item-sub">Qty: <?= $item['qty'] ?></div>
|
||
</div>
|
||
<div class="cart-item-price">$<?= number_format($item['price'], 2) ?></div>
|
||
</div>
|
||
<?php endforeach; ?>
|
||
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Right: checkout panel -->
|
||
<div>
|
||
<div class="summary-panel">
|
||
|
||
<div class="summary-title">Order Summary</div>
|
||
|
||
<?php foreach ($cartItems as $item): ?>
|
||
<div class="summary-row">
|
||
<span><?= htmlspecialchars($item['name']) ?></span>
|
||
<span>$<?= number_format($item['price'], 2) ?></span>
|
||
</div>
|
||
<?php endforeach; ?>
|
||
|
||
<div class="summary-row total">
|
||
<span>Total</span>
|
||
<span>$<?= number_format($total, 2) ?></span>
|
||
</div>
|
||
|
||
<?php
|
||
/* Pay Later message below cart total — shows "Pay later with PayPal" (placement: cart) */
|
||
$ppMessage = [
|
||
'school_name' => $schoolLabel,
|
||
'amount' => number_format($total, 2, '.', ''),
|
||
'currency' => $currency,
|
||
'placement' => 'cart',
|
||
'page_type' => 'cart',
|
||
];
|
||
require_once __DIR__ . '/paypal-paylater-message.php';
|
||
?>
|
||
|
||
<div class="summary-divider"></div>
|
||
|
||
<?php if (!$schoolReady): ?>
|
||
<div style="background:#fffaf0;border:1px solid #feebc8;color:#9c4221;border-radius:10px;padding:14px 16px;font-size:13px;line-height:1.6;margin-bottom:16px;">
|
||
<strong>No PayPal-connected school found.</strong><br>
|
||
The checkout buttons appear once a school has completed PayPal onboarding.
|
||
Connect one in <a href="index.php" style="color:#9c4221;font-weight:600;">School Merchant Setup</a>,
|
||
or open this page as <code>?school=<connected school name></code>.
|
||
</div>
|
||
<?php endif; ?>
|
||
|
||
<?php
|
||
/*
|
||
* ══════════════════════════════════════════════════════
|
||
* PAYPAL WIDGET — rendered FIRST, above card payment.
|
||
* page_type='cart' is passed so PayPal can apply
|
||
* cart-specific optimisations (e.g. express checkout).
|
||
* ══════════════════════════════════════════════════════
|
||
*/
|
||
require_once __DIR__ . '/paypal-checkout-widget.php';
|
||
?>
|
||
|
||
<!-- Card payment — shown below the widget divider -->
|
||
<div class="card-section">
|
||
<h4>Pay with card</h4>
|
||
<input class="card-field" type="text" placeholder="Card number" disabled>
|
||
<div class="card-row">
|
||
<input class="card-field" type="text" placeholder="MM / YY" disabled>
|
||
<input class="card-field" type="text" placeholder="CVV" disabled>
|
||
</div>
|
||
<button class="btn-card" disabled>Pay $<?= number_format($total, 2) ?></button>
|
||
<p class="secure-note">🔒 Secured by PayPal</p>
|
||
</div>
|
||
|
||
</div>
|
||
</div>
|
||
|
||
</div>
|
||
</body>
|
||
</html>
|