beginTransaction(); try { // 1) User aanmaken/zekerstellen + profiel updaten (stored procedures uit je DB) $db->exec("SET @uid=NULL"); $q = $db->prepare("CALL sp_ensure_user(:e,:n,@uid)"); $q->execute([':e' => $email, ':n' => $name]); $uid = (int)($db->query("SELECT @uid AS uid")->fetch()['uid'] ?? 0); $up = $db->prepare("CALL sp_upsert_profile(:e,:n,:ph,:co,:vat,:ad,:pc,:ci,:ct)"); $up->execute([ ':e' => $email, ':n' => $name, ':ph' => $phone, ':co' => $company, ':vat' => $vat, ':ad' => $address, ':pc' => $post, ':ci' => $city, ':ct' => $country ]); // 2) Ordernummer $number = 'TT' . date('YmdHis') . random_int(100, 999); // 3) Order opslaan $currency = strtoupper((string)($tot['currency'] ?? 'EUR')); $grand = (float)($tot['grand'] ?? 0); $st = $db->prepare( "INSERT INTO orders (user_id, number, status, ordered_at, currency, total_gross, total_net, notes) VALUES (:uid,:num,:st,NOW(),:cur,:gross,NULL,:notes)" ); $st->execute([ ':uid' => $uid, ':num' => $number, ':st' => ($pm === 'sepa' ? 'awaiting_payment' : 'pending'), ':cur' => $currency, ':gross' => money($grand), ':notes' => $notes ]); $orderId = (int)$db->lastInsertId(); // 4) Orderregels $ins = $db->prepare( "INSERT INTO order_items (order_id, sku, title, qty, unit_price, line_total, meta) VALUES (:oid,:sku,:title,:qty,:price,:line,:meta)" ); foreach ($items as $it) { $qtyRaw = (float)($it['qty'] ?? 1); $qty = max(0.001, $qtyRaw); $price = (float)($it['price'] ?? 0); $line = $qty * $price; $ins->execute([ ':oid' => $orderId, ':sku' => clean_text($it['sku'] ?? ''), ':title' => clean_text($it['name'] ?? $it['title'] ?? 'Product'), ':qty' => qtyfmt($qty), ':price' => money($price), ':line' => money($line), ':meta' => json_encode($it['meta'] ?? new stdClass(), JSON_UNESCAPED_UNICODE) ]); } // 5) Factuur alvast klaarzetten (open) – webhook kan later definitief maken $invNo = 'INV' . substr($number, 2); $db->exec("SET @iid=NULL"); $iv = $db->prepare( "CALL sp_upsert_invoice(:email,:inv,'open',NOW(),NULL,:tot,:due,:cur,NULL,:ord,@iid)" ); $iv->execute([ ':email' => $email, ':inv' => $invNo, ':tot' => money($grand), ':due' => money($grand), ':cur' => $currency, ':ord' => $number ]); $db->commit(); // --- SEPA/offline route --- if ($pm === 'sepa') { json_ok([ 'ok' => true, 'mode' => 'sepa', 'order_number' => $number, 'sepa' => [ 'iban' => 'BE63377065491508', 'name' => APP_NAME, 'amount' => money($grand), 'remittance' => $number ] ]); } // --- Stripe Checkout route --- $autoload = __DIR__ . '/vendor/autoload.php'; if (!file_exists($autoload)) { // Vriendelijke fout als stripe-php (composer) nog niet is geïnstalleerd json_err('Stripe library ontbreekt (vendor/autoload.php). Installeer stripe-php via Composer.', 500, [ 'hint' => 'composer require stripe/stripe-php' ]); } require_once $autoload; \Stripe\Stripe::setApiKey(STRIPE_SECRET); $line_items = []; foreach ($items as $it) { $qtyItem = (int)max(1, (float)($it['qty'] ?? 1)); $priceC = (int)round(100 * (float)($it['price'] ?? 0)); $nameP = $it['name'] ?? $it['title'] ?? 'Product'; $line_items[] = [ 'quantity' => $qtyItem, 'price_data' => [ 'currency' => strtolower($currency), 'unit_amount' => $priceC, 'product_data' => [ 'name' => $nameP, 'metadata' => ['sku' => $it['sku'] ?? ''] ], ], ]; } // Verzendkosten als los item (indien > 0) $ship = (float)($tot['ship'] ?? 0); if ($ship > 0) { $line_items[] = [ 'quantity' => 1, 'price_data' => [ 'currency' => strtolower($currency), 'unit_amount' => (int)round(100 * $ship), 'product_data'=> ['name' => 'Verzending'] ] ]; } // NB: Kortingen via Stripe-coupon vooraf aanmaken en via discounts[] koppelen // In deze implementatie is de loyaliteitskorting al in de front-end/totals verwerkt. $origin = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off' ? 'https' : 'http') . '://' . $_SERVER['HTTP_HOST']; $session = \Stripe\Checkout\Session::create([ 'mode' => 'payment', 'customer_email' => $email, 'metadata' => ['order_number' => $number, 'user_id' => $uid], 'line_items' => $line_items, 'success_url' => $origin . '/thanks.html?order=' . rawurlencode($number), 'cancel_url' => $origin . '/checkout.html?canceled=1', ]); // Status naar processing tot webhook bevestigt $upd = $db->prepare("UPDATE orders SET status='processing' WHERE id=:id"); $upd->execute([':id' => $orderId]); json_ok([ 'ok' => true, 'mode' => 'stripe', 'url' => $session->url, 'order_number' => $number ]); } catch (Throwable $e) { if ($db->inTransaction()) $db->rollBack(); json_err('Opslaan mislukt', 500, ['detail' => $e->getMessage()]); }