dolibarr.idsconnect/mockserver.php
data 5f5a389809 IDS Connect v2.2 - Menü-Integration, ADL-Hooks, Admin-Erweiterung
- Menü unter Einkauf > Lieferantenbestellungen statt eigenes Top-Menü
- ADL-Buttons auf Produkt-Lieferantenpreisen per Hook (pricesuppliercard)
- Admin-Seite: Großhändler-Schnellübersicht mit Version-Check
- Dashboard: Shop-öffnen-Button (LI-Action)
- Neue Datei: class/actions_idsconnect.class.php

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 17:45:15 +01:00

338 lines
14 KiB
PHP
Executable file

<?php
/* Copyright (C) 2026 Eduard Wisch <data@data-it-solution.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*/
/**
* \file idsconnect/mockserver.php
* \ingroup idsconnect
* \brief Mock-Server der einen Großhandels-Shop simuliert
*
* Dieser Server empfängt IDS Connect Anfragen und simuliert einen Shop.
* Damit können alle Funktionen getestet werden, ohne echte Bestellungen auszulösen.
*/
// Dolibarr laden (ohne Login für den Mock-Server)
define('NOLOGIN', 1);
define('NOCSRFCHECK', 1);
define('NOREQUIREMENU', 1);
$res = 0;
if (!$res && !empty($_SERVER["CONTEXT_DOCUMENT_ROOT"])) {
$res = @include $_SERVER["CONTEXT_DOCUMENT_ROOT"]."/main.inc.php";
}
$tmp = empty($_SERVER['SCRIPT_FILENAME']) ? '' : $_SERVER['SCRIPT_FILENAME'];
$tmp2 = realpath(__FILE__);
$i = strlen($tmp) - 1;
$j = strlen($tmp2) - 1;
while ($i > 0 && $j > 0 && isset($tmp[$i]) && isset($tmp2[$j]) && $tmp[$i] == $tmp2[$j]) {
$i--;
$j--;
}
if (!$res && $i > 0 && file_exists(substr($tmp, 0, ($i + 1))."/main.inc.php")) {
$res = @include substr($tmp, 0, ($i + 1))."/main.inc.php";
}
if (!$res && $i > 0 && file_exists(dirname(substr($tmp, 0, ($i + 1)))."/main.inc.php")) {
$res = @include dirname(substr($tmp, 0, ($i + 1)))."/main.inc.php";
}
if (!$res && file_exists("../main.inc.php")) {
$res = @include "../main.inc.php";
}
if (!$res && file_exists("../../main.inc.php")) {
$res = @include "../../main.inc.php";
}
if (!$res) {
die("Include of main fails");
}
// Nur im Testmodus erreichbar
if (!getDolGlobalInt('IDSCONNECT_TESTMODE')) {
http_response_code(403);
die("Mock-Server ist nur im Testmodus verfügbar");
}
// IDS-Parameter aus POST lesen
$kndnr = GETPOST('kndnr', 'alphanohtml') ?: '';
$name_kunde = GETPOST('name_kunde', 'alphanohtml') ?: '';
$pw_kunde = GETPOST('pw_kunde', 'none') ?: '';
$version = GETPOST('version', 'alphanohtml') ?: '2.5';
$ids_action = GETPOST('action', 'alpha') ?: '';
$hookurl = GETPOST('hookurl', 'alphanohtml') ?: '';
$warenkorb_xml = GETPOST('warenkorb', 'none') ?: '';
$artikelnr = GETPOST('artikelnr', 'alphanohtml') ?: '';
// Mock-Server Action bestimmen
$mock_action = GETPOST('mock_action', 'alpha') ?: '';
// Beispiel-Artikel für den Mock-Shop
$mock_articles = array(
array('nr' => '1234567', 'bezeichnung' => 'Leitungsschutzschalter B16 1-polig', 'preis' => 5.42, 'einheit' => 'STK', 'hersteller' => 'Hager', 'ean' => '3250613160012'),
array('nr' => '2345678', 'bezeichnung' => 'FI-Schutzschalter 40A 30mA 4-polig', 'preis' => 28.90, 'einheit' => 'STK', 'hersteller' => 'ABB', 'ean' => '7612271443526'),
array('nr' => '3456789', 'bezeichnung' => 'NYM-J 3x1,5 mm² (100m Ring)', 'preis' => 62.50, 'einheit' => 'STK', 'hersteller' => 'Lapp', 'ean' => '4044774881328'),
array('nr' => '4567890', 'bezeichnung' => 'Schalterdose UP D=60mm', 'preis' => 0.35, 'einheit' => 'STK', 'hersteller' => 'Kaiser', 'ean' => '4013456000216'),
array('nr' => '5678901', 'bezeichnung' => 'Zählerschrank 1-Feld komplett', 'preis' => 189.00, 'einheit' => 'STK', 'hersteller' => 'Hager', 'ean' => '3250616167483'),
array('nr' => '6789012', 'bezeichnung' => 'Wallbox 11kW mit Ladesteckdose Typ 2', 'preis' => 495.00, 'einheit' => 'STK', 'hersteller' => 'ABL', 'ean' => '4015141000001'),
array('nr' => '7890123', 'bezeichnung' => 'SLS-Schalter E-Charakteristik 35A 1-polig', 'preis' => 22.80, 'einheit' => 'STK', 'hersteller' => 'Hager', 'ean' => '3250613211363'),
array('nr' => '8901234', 'bezeichnung' => 'Überspannungsschutz Typ 2 TN-S', 'preis' => 78.50, 'einheit' => 'STK', 'hersteller' => 'Dehn', 'ean' => '4013364108530'),
);
// ============================================================
// Warenkorb an HOOKURL zurücksenden
// ============================================================
if ($mock_action === 'send_cart' && !empty($hookurl)) {
$cart_items = array();
if (!empty($_POST['cart_items']) && is_array($_POST['cart_items'])) {
foreach ($_POST['cart_items'] as $idx => $item) {
$qty = (int) ($item['qty'] ?? 0);
if ($qty > 0 && isset($mock_articles[$idx])) {
$art = $mock_articles[$idx];
$cart_items[] = array(
'nr' => $art['nr'],
'bezeichnung' => $art['bezeichnung'],
'menge' => $qty,
'einheit' => $art['einheit'],
'einzelpreis' => $art['preis'],
'ean' => $art['ean'],
'hersteller' => $art['hersteller'],
);
}
}
}
if (empty($cart_items)) {
$error_msg = 'Keine Artikel ausgewählt';
} else {
// Warenkorb-XML im IDS Connect 2.5 Format generieren
$xml = '<?xml version="1.0" encoding="UTF-8"?>'."\n";
$xml .= '<Warenkorb xmlns="http://www.itek.de/Shop-Anbindung/Warenkorb/">'."\n";
$xml .= ' <WarenkorbInfo>'."\n";
$xml .= ' <Date>'.date('Y-m-d').'</Date>'."\n";
$xml .= ' <Time>'.date('H:i:s').'</Time>'."\n";
$xml .= ' <RueckgabeKZ>Warenkorbru&#xFC;ckgabe</RueckgabeKZ>'."\n";
$xml .= ' <Version>2.5</Version>'."\n";
$xml .= ' </WarenkorbInfo>'."\n";
$xml .= ' <Order>'."\n";
$xml .= ' <OrderInfo>'."\n";
$xml .= ' <ModeOfShipment>Lieferung</ModeOfShipment>'."\n";
$xml .= ' <Cur>EUR</Cur>'."\n";
$xml .= ' </OrderInfo>'."\n";
foreach ($cart_items as $item) {
$xml .= ' <OrderItem>'."\n";
$xml .= ' <ArtNo>'.htmlspecialchars($item['nr'], ENT_XML1).'</ArtNo>'."\n";
$xml .= ' <Qty>'.$item['menge'].'</Qty>'."\n";
$xml .= ' <QU>'.htmlspecialchars($item['einheit'], ENT_XML1).'</QU>'."\n";
$xml .= ' <Kurztext>'.htmlspecialchars($item['bezeichnung'], ENT_XML1).'</Kurztext>'."\n";
$xml .= ' <NetPrice>'.$item['einzelpreis'].'</NetPrice>'."\n";
$xml .= ' <OfferPrice>'.$item['einzelpreis'].'</OfferPrice>'."\n";
$xml .= ' <PriceBasis>1</PriceBasis>'."\n";
$xml .= ' <VAT>19</VAT>'."\n";
$xml .= ' <EAN>'.htmlspecialchars($item['ean'], ENT_XML1).'</EAN>'."\n";
$xml .= ' <ManufacturerID>'.htmlspecialchars($item['hersteller'], ENT_XML1).'</ManufacturerID>'."\n";
$xml .= ' </OrderItem>'."\n";
}
$xml .= ' </Order>'."\n";
$xml .= '</Warenkorb>';
// Per Redirect mit POST-Daten an HOOKURL senden
// Wir nutzen ein Auto-Submit-Formular (wie IDS Connect es spezifiziert)
header('Content-Type: text/html; charset=UTF-8');
echo '<!DOCTYPE html><html><head><meta charset="UTF-8">';
echo '<title>Mock-Server - Warenkorb wird gesendet...</title></head>';
echo '<body onload="document.forms[0].submit();">';
echo '<p>Warenkorb wird an Dolibarr gesendet ('.count($cart_items).' Artikel)...</p>';
echo '<form method="post" action="'.htmlspecialchars($hookurl).'" enctype="multipart/form-data">';
echo '<input type="hidden" name="warenkorb" value="'.htmlspecialchars($xml).'">';
echo '<noscript><input type="submit" value="Warenkorb senden"></noscript>';
echo '</form></body></html>';
exit;
}
}
// ============================================================
// Mock-Shop HTML ausgeben
// ============================================================
header('Content-Type: text/html; charset=UTF-8');
?>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>IDS Connect Mock-Server - Testshop</title>
<style>
body { font-family: Arial, sans-serif; max-width: 900px; margin: 20px auto; padding: 0 20px; background: #f5f5f5; }
.header { background: #e74c3c; color: white; padding: 15px 20px; border-radius: 5px 5px 0 0; }
.header h1 { margin: 0; font-size: 20px; }
.header .badge { background: #c0392b; padding: 3px 10px; border-radius: 3px; font-size: 12px; margin-left: 10px; }
.content { background: white; padding: 20px; border-radius: 0 0 5px 5px; box-shadow: 0 2px 5px rgba(0,0,0,0.1); }
.info { background: #ffeaa7; padding: 10px; border-radius: 3px; margin-bottom: 15px; border-left: 4px solid #fdcb6e; }
.credentials { background: #dfe6e9; padding: 10px; border-radius: 3px; margin-bottom: 15px; font-size: 13px; }
table { width: 100%; border-collapse: collapse; margin: 15px 0; }
th { background: #2c3e50; color: white; padding: 10px; text-align: left; }
td { padding: 8px 10px; border-bottom: 1px solid #eee; }
tr:hover { background: #f8f9fa; }
input[type="number"] { width: 60px; padding: 5px; border: 1px solid #ccc; border-radius: 3px; }
.btn { background: #27ae60; color: white; padding: 10px 25px; border: none; border-radius: 5px; cursor: pointer; font-size: 14px; }
.btn:hover { background: #219a52; }
.btn-cancel { background: #95a5a6; }
.btn-cancel:hover { background: #7f8c8d; }
.price { text-align: right; font-family: monospace; }
</style>
</head>
<body>
<div class="header">
<h1>🔌 Mock-Elektrogroßhandel <span class="badge">TESTMODUS</span></h1>
</div>
<div class="content">
<div class="info">
<strong>⚠️ Dies ist ein Testshop!</strong> Keine echten Bestellungen werden ausgelöst.
Alle Daten sind Beispieldaten für Entwicklungszwecke.
</div>
<?php if (!empty($error_msg)): ?>
<div style="background:#fab1a0; padding:10px; border-radius:3px; margin-bottom:15px;">
<strong>Fehler:</strong> <?php echo htmlspecialchars($error_msg); ?>
</div>
<?php endif; ?>
<div class="credentials">
<strong>Empfangene IDS-Daten:</strong>
Kundennr: <code><?php echo htmlspecialchars($kndnr); ?></code> |
Benutzer: <code><?php echo htmlspecialchars($name_kunde); ?></code> |
Version: <code><?php echo htmlspecialchars($version); ?></code> |
Action: <code><?php echo htmlspecialchars($ids_action); ?></code>
</div>
<?php if ($ids_action === 'WKS' && !empty($warenkorb_xml)): ?>
<h2>Bestellung empfangen (WKS)</h2>
<div style="background:#d4edda; padding:15px; border-radius:5px; border-left:4px solid #28a745; margin-bottom:15px;">
<strong>Bestellung erfolgreich empfangen!</strong><br>
Der Großhandel hat folgende Artikel erhalten:
</div>
<?php
// Empfangenes Warenkorb-XML parsen und anzeigen
dol_include_once('/idsconnect/class/idsconnect.class.php');
$parser = new IdsConnect($db);
$received_items = $parser->parseCartXml($warenkorb_xml);
if (is_array($received_items) && count($received_items) > 0):
?>
<table>
<tr>
<th>Art.-Nr.</th>
<th>Bezeichnung</th>
<th class="price">Einzelpreis (&euro;)</th>
<th>Menge</th>
<th>Einheit</th>
</tr>
<?php $wks_total = 0; foreach ($received_items as $ri):
$line_total = $ri['menge'] * $ri['einzelpreis'];
$wks_total += $line_total;
?>
<tr>
<td><code><?php echo htmlspecialchars($ri['artikelnr']); ?></code></td>
<td><?php echo htmlspecialchars($ri['bezeichnung']); ?></td>
<td class="price"><?php echo number_format($ri['einzelpreis'], 2, ',', '.'); ?></td>
<td><?php echo (int)$ri['menge']; ?></td>
<td><?php echo htmlspecialchars($ri['einheit']); ?></td>
</tr>
<?php endforeach; ?>
<tr style="font-weight:bold; border-top:2px solid #333;">
<td colspan="4" style="text-align:right;">Gesamt netto:</td>
<td class="price"><?php echo number_format($wks_total, 2, ',', '.'); ?> &euro;</td>
</tr>
</table>
<?php else: ?>
<p style="color:#e74c3c;">Warenkorb-XML konnte nicht geparst werden.</p>
<details>
<summary>XML-Rohdaten</summary>
<pre style="background:#f8f9fa; padding:10px; overflow:auto;"><?php echo htmlspecialchars($warenkorb_xml); ?></pre>
</details>
<?php endif; ?>
<div style="margin-top:20px; padding:15px; background:#fff3cd; border-radius:5px; border-left:4px solid #ffc107;">
<strong>Mock-Server Simulation:</strong> Im Live-Betrieb w&uuml;rde der Sonepar-Shop diese Bestellung entgegennehmen und verarbeiten.
</div>
<?php elseif ($ids_action === 'WKE' || empty($ids_action)): ?>
<h2>Artikel auswählen</h2>
<form method="post" action="<?php echo htmlspecialchars($_SERVER['PHP_SELF']); ?>">
<input type="hidden" name="mock_action" value="send_cart">
<input type="hidden" name="hookurl" value="<?php echo htmlspecialchars($hookurl); ?>">
<table>
<tr>
<th>Art.-Nr.</th>
<th>Bezeichnung</th>
<th>Hersteller</th>
<th class="price">Preis (€)</th>
<th>Menge</th>
</tr>
<?php foreach ($mock_articles as $idx => $art): ?>
<tr>
<td><code><?php echo htmlspecialchars($art['nr']); ?></code></td>
<td><?php echo htmlspecialchars($art['bezeichnung']); ?></td>
<td><?php echo htmlspecialchars($art['hersteller']); ?></td>
<td class="price"><?php echo number_format($art['preis'], 2, ',', '.'); ?></td>
<td><input type="number" name="cart_items[<?php echo $idx; ?>][qty]" value="0" min="0" max="999"></td>
</tr>
<?php endforeach; ?>
</table>
<div style="text-align:right; margin-top:15px;">
<?php if (!empty($hookurl)): ?>
<button type="submit" class="btn">🛒 Warenkorb an Dolibarr senden</button>
<?php else: ?>
<p style="color:#e74c3c;">Keine HOOKURL empfangen - Rücksendung nicht möglich.</p>
<?php endif; ?>
</div>
</form>
<?php elseif ($ids_action === 'ADL'): ?>
<h2>Artikel Deep-Link</h2>
<div style="padding:20px; background:#f8f9fa; border-radius:5px;">
<p>Angefragter Artikel: <strong><?php echo htmlspecialchars($artikelnr); ?></strong></p>
<?php
$found = false;
foreach ($mock_articles as $art) {
if ($art['nr'] === $artikelnr) {
$found = true;
echo '<table>';
echo '<tr><td><strong>Artikelnummer:</strong></td><td>'.htmlspecialchars($art['nr']).'</td></tr>';
echo '<tr><td><strong>Bezeichnung:</strong></td><td>'.htmlspecialchars($art['bezeichnung']).'</td></tr>';
echo '<tr><td><strong>Hersteller:</strong></td><td>'.htmlspecialchars($art['hersteller']).'</td></tr>';
echo '<tr><td><strong>Preis:</strong></td><td>'.number_format($art['preis'], 2, ',', '.').' €</td></tr>';
echo '<tr><td><strong>Verfügbar:</strong></td><td>✅ Auf Lager (Mock)</td></tr>';
echo '</table>';
break;
}
}
if (!$found) {
echo '<p style="color:#e74c3c;">Artikel nicht gefunden (Mock-Datenbank enthält nur Beispieldaten)</p>';
}
?>
</div>
<?php elseif ($ids_action === 'SV'): ?>
<h2>Schnittstellenversion</h2>
<p>Unterstützte IDS Connect Version: <strong>2.5</strong></p>
<?php elseif ($ids_action === 'LI'): ?>
<h2>Login-Information</h2>
<p>Login erfolgreich (Mock-Server)</p>
<p>Kundennummer: <strong><?php echo htmlspecialchars($kndnr); ?></strong></p>
<?php endif; ?>
<hr style="margin-top:20px;">
<p style="font-size:12px; color:#999;">
IDS Connect Mock-Server v1.0 | Nur für Entwicklung und Tests |
<a href="<?php echo DOL_URL_ROOT; ?>/custom/idsconnect/idsconnectindex.php">Zurück zu Dolibarr</a>
</p>
</div>
</body>
</html>
<?php