Files
HotLunches/pp-integration/demo-cart.php
T
2026-10-19 15:22:52 -07:00

269 lines
9.3 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?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=&lt;connected school name&gt;</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>