diff --git a/api.php b/api.php index 062be19..60258aa 100644 --- a/api.php +++ b/api.php @@ -1,6 +1,7 @@ connect_error) { + die(json_encode(['error' => 'Database connectie mislukt'])); +} + $action = $_GET['action'] ?? ''; -// --- AUTH --- +// --- 1. LOGIN ACTIE --- if ($action === 'login') { $input = json_decode(file_get_contents('php://input'), true); $stmt = $db->prepare("SELECT password, full_name FROM sales_users WHERE username = ?"); $stmt->bind_param("s", $input['username']); $stmt->execute(); $res = $stmt->get_result()->fetch_assoc(); + if ($res && password_verify($input['password'], $res['password'])) { $_SESSION['user'] = $input['username']; $_SESSION['full_name'] = $res['full_name']; session_write_close(); echo json_encode(['success' => true, 'user' => $res['full_name']]); } else { - http_response_code(401); echo json_encode(['error' => 'Login mislukt']); + http_response_code(401); + echo json_encode(['error' => 'Inloggegevens onjuist']); } exit; } -if (!isset($_SESSION['user'])) { http_response_code(403); exit; } +// Auth check voor alle andere acties +if (!isset($_SESSION['user']) && $action !== 'login') { + http_response_code(403); + echo json_encode(['error' => 'Sessie verlopen']); + exit; +} +// --- CLIENTS --- $woocommerce = new Client($_ENV['WC_URL'], $_ENV['WC_KEY'], $_ENV['WC_SECRET'], ['version' => 'wc/v3', 'verify_ssl' => false, 'timeout' => 400]); -// --- CREATE ORDER --- -if ($action === 'create_order') { - $input = json_decode(file_get_contents('php://input'), true); - try { - $mediacode = $input['mediacode_internal'] ?? 'Geen'; - $wc_gateway_id = $input['payment_method']; - $mollie_method = str_replace(['mollie_wc_gateway_', 'rve_'], '', $wc_gateway_id); - - $input['payment_method'] = $wc_gateway_id; - - // Compacte meta_data om WAF blokkades te voorkomen - $input['meta_data'] = [ - ['key' => '_wc_order_attribution_source_type', 'value' => 'utm'], - ['key' => '_wc_order_attribution_utm_source', 'value' => 'SalesPanel'], - ['key' => '_wc_order_attribution_utm_campaign', 'value' => $mediacode], - ['key' => 'Mediacode', 'value' => $mediacode] - ]; - - // 1. Order aanmaken (Hier gaat de 500 error vaak mis door WAF) - $order = $woocommerce->post('orders', $input); - - $mollie = new MollieApiClient(); - $mollie->setApiKey($_ENV['MOLLIE_KEY']); - - $paymentData = [ - "amount" => ["currency" => "EUR", "value" => number_format((float)$order->total, 2, '.', '')], - "description" => "Order #{$order->id}", - "redirectUrl" => $_ENV['WC_URL'] . "/checkout/order-received/{$order->id}/?key={$order->order_key}&order_id={$order->id}&utm_source=SalesPanel&utm_campaign={$mediacode}", - "webhookUrl" => $_ENV['WC_URL'] . "/wc-api/{$wc_gateway_id}/?key={$order->order_key}&order_id={$order->id}", - "method" => $mollie_method, - "metadata" => ["order_id" => (string)$order->id, "mediacode" => $mediacode] - ]; - - // Verplichte adresvelden voor achteraf betalen - if (in_array($mollie_method, ['in3', 'klarna', 'klarnapaylater', 'klarnasliceit', 'riverty'])) { - $paymentData["billingAddress"] = [ - "givenName" => $input['billing']['first_name'], - "familyName" => $input['billing']['last_name'], - "email" => $input['billing']['email'], - "streetAndNumber" => $input['billing']['address_1'], - "city" => $input['billing']['city'], - "postalCode" => $input['billing']['postcode'], - "country" => "NL" - ]; -$paymentData["lines"] = [[ - "name" => "Bestelling #" . $order->id, - "quantity" => 1, - "unitPrice" => ["currency" => "EUR", "value" => number_format((float)$order->total, 2, '.', '')], - "totalAmount" => ["currency" => "EUR", "value" => number_format((float)$order->total, 2, '.', '')], - "vatRate" => "21.00", - "vatAmount" => ["currency" => "EUR", "value" => number_format((float)$order->total_tax, 2, '.', '')] - ]]; - } - - $payment = $mollie->payments->create($paymentData); - // Update meta in aparte call om de eerste POST klein te houden - $woocommerce->put("orders/{$order->id}", ['meta_data' => [['key' => '_transaction_id', 'value' => $payment->id]]]); - - echo json_encode(['payment_url' => $payment->getCheckoutUrl()]); - } catch (Exception $e) { - http_response_code(422); echo json_encode(['error' => $e->getMessage()]); - } - exit; -} - -// --- OVERIGE ACTIES (POSTCODE, PRODUCTS, LOGOUT) --- +// --- 2. HELPERS --- if ($action === 'get_payment_methods') { try { $gateways = $woocommerce->get('payment_gateways'); $output = []; foreach ($gateways as $gw) { + // Filter Apple Pay en Google Pay hier volledig weg + if (str_contains($gw->id, 'applepay') || str_contains($gw->id, 'googlepay') || str_contains($gw->id, 'riverty') || str_contains($gw->id, 'klarna')) { + continue; + } if ($gw->enabled && (str_contains($gw->id, 'mollie') || str_contains($gw->id, 'riverty') || str_contains($gw->id, 'klarna'))) { $output[] = ['id' => $gw->id, 'title' => $gw->method_title]; } } echo json_encode($output); - } catch (Exception $e) { echo json_encode([]); } + } catch (Exception $e) { + echo json_encode([]); + } exit; } @@ -133,16 +88,108 @@ if ($action === 'get_products') { $enriched[] = $p; } echo json_encode($enriched); - } catch (Exception $e) { echo json_encode([]); } + } catch (Exception $e) { + echo json_encode([]); + } exit; } if ($action === 'postcode_check') { $postcode = str_replace(' ', '', $_GET['postcode']); $url = "https://postcode.tech/api/v1/postcode?postcode={$postcode}&number=" . $_GET['number']; - $ch = curl_init($url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + $ch = curl_init($url); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_HTTPHEADER, ["Authorization: Bearer " . $_ENV['POSTCODE_TECH_KEY']]); - echo curl_exec($ch); exit; + echo curl_exec($ch); + exit; } -if ($action === 'logout') { session_destroy(); echo json_encode(['success' => true]); exit; } \ No newline at end of file +// --- 3. CREATE ORDER (V7.0 - INCL. 100 EURO THRESHOLD) --- +if ($action === 'create_order') { + $input = json_decode(file_get_contents('php://input'), true); + try { + $mediacode = $input['mediacode_internal'] ?? 'Geen'; + $wc_gateway_id = $input['payment_method']; + $mollie_method = str_replace(['mollie_wc_gateway_', 'rve_'], '', $wc_gateway_id); + + $input['payment_method'] = $wc_gateway_id; + $input['customer_note'] = "Agent: {$_SESSION['user']} | Mediacode: $mediacode"; + + // Attribution data voor herkomst-blokje + $input['meta_data'][] = ['key' => '_wc_order_attribution_source_type', 'value' => 'utm']; + $input['meta_data'][] = ['key' => '_wc_order_attribution_utm_source', 'value' => 'SalesPanel']; + $input['meta_data'][] = ['key' => '_wc_order_attribution_utm_campaign', 'value' => $mediacode]; + $input['meta_data'][] = ['key' => '_wc_order_attribution_origin', 'value' => 'Sales Panel']; + $input['meta_data'][] = ['key' => 'Mediacode', 'value' => $mediacode]; + + // A. Order aanmaken in WooCommerce + $order = $woocommerce->post('orders', $input); + + // EXTRA CHECK: Termijn betalingen pas vanaf 100 euro + if (in_array($mollie_method, ['in3', 'klarna', 'klarnapaylater', 'klarnasliceit']) && (float)$order->total < 100.00) { + $woocommerce->delete("orders/{$order->id}", ['force' => true]); + throw new Exception("Termijnbetaling (in3/Klarna) pas mogelijk vanaf €100,-"); + } + + $mollie = new MollieApiClient(); + $mollie->setApiKey($_ENV['MOLLIE_KEY']); + $is_sub = (stripos(json_encode($order->line_items), 'abonnement') !== false); + + // B. Voorbereiden Mollie Data + $paymentData = [ + "amount" => ["currency" => "EUR", "value" => ($mollie_method === 'ideal' && $is_sub) ? "0.01" : number_format((float)$order->total, 2, '.', '')], + "description" => "Order #{$order->id}", + "redirectUrl" => $_ENV['WC_URL'] . "/checkout/order-received/{$order->id}/?key={$order->order_key}&order_id={$order->id}&utm_source=SalesPanel&utm_campaign={$mediacode}", + "webhookUrl" => $_ENV['WC_URL'] . "/wc-api/{$wc_gateway_id}/?key={$order->order_key}&order_id={$order->id}", + "method" => $mollie_method, + "metadata" => ["order_id" => (string)$order->id, "mediacode" => $mediacode] + ]; + + // C. "Light Lines" fix voor Server Error 500 / Klarna-validatie + if (in_array($mollie_method, ['in3', 'klarna', 'klarnapaylater', 'klarnasliceit', 'riverty'])) { + if ($mollie_method === 'riverty') { + $paymentData["captureMode"] = "manual"; + } + $paymentData["billingAddress"] = [ + "givenName" => $input['billing']['first_name'], + "familyName" => $input['billing']['last_name'], + "email" => $input['billing']['email'], + "streetAndNumber" => $input['billing']['address_1'], + "city" => $input['billing']['city'], + "postalCode" => $input['billing']['postcode'], + "country" => "NL" + ]; + $paymentData["lines"] = [[ + "name" => "Bestelling #" . $order->id, + "quantity" => 1, + "unitPrice" => ["currency" => "EUR", "value" => number_format((float)$order->total, 2, '.', '')], + "totalAmount" => ["currency" => "EUR", "value" => number_format((float)$order->total, 2, '.', '')], + "vatRate" => "21.00", + "vatAmount" => ["currency" => "EUR", "value" => number_format((float)$order->total_tax, 2, '.', '')] + ]]; + } + + // D. Mollie betaling aanmaken + $payment = $mollie->payments->create($paymentData); + + // E. Update Mollie ID in WooCommerce + $woocommerce->put("orders/{$order->id}", ['meta_data' => [['key' => '_mollie_payment_id', 'value' => $payment->id], ['key' => '_transaction_id', 'value' => $payment->id], ['key' => '_mediacode', 'value' => $mediacode]]]); + + $woocommerce->post("orders/{$order->id}/notes", [ + 'note' => "Betaallink gegenereerd: " . $payment->getCheckoutUrl(), + 'customer_note' => true // Dit stuurt een mail naar de klant met de link! + ]); + + echo json_encode(['payment_url' => $payment->getCheckoutUrl()]); + } catch (Exception $e) { + http_response_code(422); + echo json_encode(['error' => $e->getMessage()]); + } + exit; +} + +if ($action === 'logout') { + session_destroy(); + echo json_encode(['success' => true]); + exit; +} diff --git a/index.html b/index.html index 28665f4..25d365a 100644 --- a/index.html +++ b/index.html @@ -24,7 +24,7 @@
-

TELVERO PANEL

+

TELVERO PANEL

@@ -54,12 +54,12 @@ - +
-

Producten

+

Selectie

-
+
+