diff --git a/api.php b/api.php index ca86764..062be19 100644 --- a/api.php +++ b/api.php @@ -1,6 +1,6 @@ load(); +if (file_exists(__DIR__ . '/.env')) { + $dotenv = Dotenv\Dotenv::createImmutable(__DIR__); + $dotenv->load(); +} use Automattic\WooCommerce\Client; use Mollie\Api\MollieApiClient; header('Content-Type: application/json'); -// --- DATABASE CONNECTIE VIA ENV --- $db = new mysqli($_ENV['DB_HOST'], $_ENV['DB_USER'], $_ENV['DB_PASS'], $_ENV['DB_NAME']); - -if ($db->connect_error) { - die(json_encode(['error' => 'Database connectie mislukt'])); -} - -function writeLog($action, $details) { - global $db; - $user = $_SESSION['user'] ?? 'system'; - $stmt = $db->prepare("INSERT INTO sales_logs (username, action, details, created_at) VALUES (?, ?, ?, NOW())"); - $stmt->bind_param("sss", $user, $action, $details); - $stmt->execute(); -} - $action = $_GET['action'] ?? ''; -// --- AUTH ACTIONS --- +// --- AUTH --- if ($action === 'login') { $input = json_decode(file_get_contents('php://input'), true); $stmt = $db->prepare("SELECT password, full_name FROM sales_users WHERE username = ?"); @@ -44,7 +31,7 @@ if ($action === 'login') { if ($res && password_verify($input['password'], $res['password'])) { $_SESSION['user'] = $input['username']; $_SESSION['full_name'] = $res['full_name']; - writeLog('LOGIN', 'Gebruiker ingelogd'); + session_write_close(); echo json_encode(['success' => true, 'user' => $res['full_name']]); } else { http_response_code(401); echo json_encode(['error' => 'Login mislukt']); @@ -52,19 +39,104 @@ if ($action === 'login') { exit; } -if (!isset($_SESSION['user']) && $action !== 'login') { - http_response_code(403); echo json_encode(['error' => 'Auth required']); exit; +if (!isset($_SESSION['user'])) { http_response_code(403); exit; } + +$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; } -// --- WOOCOMMERCE CLIENT VIA ENV --- -$woocommerce = new Client( - $_ENV['WC_URL'], - $_ENV['WC_KEY'], - $_ENV['WC_SECRET'], - ['version' => 'wc/v3', 'timeout' => 400, 'verify_ssl' => false] -); +// --- OVERIGE ACTIES (POSTCODE, PRODUCTS, LOGOUT) --- +if ($action === 'get_payment_methods') { + try { + $gateways = $woocommerce->get('payment_gateways'); + $output = []; + foreach ($gateways as $gw) { + 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([]); } + exit; +} + +if ($action === 'get_products') { + try { + $products = $woocommerce->get('products', ['status' => 'publish', 'per_page' => 100]); + $enriched = []; + foreach ($products as $product) { + $p = (array)$product; + $p['variation_details'] = ($product->type === 'variable') ? (array)$woocommerce->get("products/{$product->id}/variations", ['per_page' => 50]) : []; + $enriched[] = $p; + } + echo json_encode($enriched); + } catch (Exception $e) { echo json_encode([]); } + exit; +} -// --- POSTCODE CHECK --- if ($action === 'postcode_check') { $postcode = str_replace(' ', '', $_GET['postcode']); $url = "https://postcode.tech/api/v1/postcode?postcode={$postcode}&number=" . $_GET['number']; @@ -73,70 +145,4 @@ if ($action === 'postcode_check') { echo curl_exec($ch); exit; } -// --- GET PRODUCTS (FIX VOOR VARIATIES & UPSELLS) --- -if ($action === 'get_products') { - try { - $products = $woocommerce->get('products', ['status' => 'publish', 'per_page' => 100]); - $enriched = []; - foreach ($products as $product) { - $p = (array)$product; - if ($product->type === 'variable') { - $p['variation_details'] = (array)$woocommerce->get("products/{$product->id}/variations", ['per_page' => 100]); - } else { - $p['variation_details'] = []; - } - $enriched[] = $p; - } - echo json_encode($enriched); - } catch (Exception $e) { echo json_encode(['error' => $e->getMessage()]); } - exit; -} - -// --- CREATE ORDER --- -if ($action === 'create_order') { - $input = json_decode(file_get_contents('php://input'), true); - try { - $mediacode = $input['mediacode_internal'] ?? 'Geen'; - $method_input = $input['payment_method']; - - $map = [ - 'mollie_methods_ideal' => ['wc' => 'mollie_wc_gateway_ideal', 'm' => 'ideal'], - 'rve_riverty' => ['wc' => 'mollie_wc_gateway_riverty', 'm' => 'riverty'], - 'mollie_methods_creditcard' => ['wc' => 'mollie_wc_gateway_creditcard', 'm' => 'creditcard'] - ]; - $gw = $map[$method_input]; - - $input['payment_method'] = $gw['wc']; - $input['payment_method_title'] = 'iDEAL (via Mollie)'; - $input['customer_note'] = "Agent: {$_SESSION['user']} | Mediacode: $mediacode"; - - $input['meta_data'][] = ['key' => 'Mediacode', 'value' => $mediacode]; - $input['meta_data'][] = ['key' => '_wc_order_attribution_utm_campaign', 'value' => $mediacode]; - $input['meta_data'][] = ['key' => '_wc_order_attribution_utm_source', 'value' => 'SalesPanel']; - - $order = $woocommerce->post('orders', $input); - - $mollie = new MollieApiClient(); - $mollie->setApiKey($_ENV['MOLLIE_KEY']); - $is_sub = (stripos(json_encode($order->line_items), 'abonnement') !== false); - - $payment = $mollie->payments->create([ - "amount" => ["currency" => "EUR", "value" => ($gw['m'] === 'ideal' && $is_sub) ? "0.01" : number_format((float)$order->total, 2, '.', '')], - "description" => "Order #{$order->id} [$mediacode]", - "redirectUrl" => $_ENV['WC_URL'] . "/checkout/order-received/{$order->id}/?key={$order->order_key}&order_id={$order->id}&filter_flag=onMollieReturn", - "webhookUrl" => $_ENV['WC_URL'] . "/wc-api/mollie_wc_gateway_ideal?order_id={$order->id}&key={$order->order_key}&filter_flag=1", - "method" => $gw['m'], - "metadata" => ["order_id" => (string)$order->id] - ]); - - $woocommerce->put("orders/{$order->id}", ['meta_data' => [['key' => '_mollie_payment_id', 'value' => $payment->id], ['key' => '_transaction_id', 'value' => $payment->id]]]); - $woocommerce->post("orders/{$order->id}/notes", ['note' => "Betaallink: " . $payment->getCheckoutUrl(), 'customer_note' => true]); - - writeLog('ORDER_CREATED', "Order #{$order->id} voor {$input['billing']['email']}"); - echo json_encode(['payment_url' => $payment->getCheckoutUrl()]); - } catch (Exception $e) { - writeLog('ERROR', $e->getMessage()); - http_response_code(422); echo json_encode(['error' => $e->getMessage()]); - } - exit; -} \ No newline at end of file +if ($action === 'logout') { session_destroy(); echo json_encode(['success' => true]); exit; } \ No newline at end of file diff --git a/index.html b/index.html index 2818742..28665f4 100644 --- a/index.html +++ b/index.html @@ -2,68 +2,65 @@ - Telvero Sales + Telvero Sales Panel - + -
+
-

TELVERO PANEL

-
- - +

TELVERO PANEL

+
+ +
-
+
-
- - +
- -

Klantgegevens

- +
- - - - - + + + +
-

Productselectie

-