Magento 2 + Exact Online: real-time synchronisatie
Terug naar blog

Magento 2 + Exact Online: real-time synchronisatie

AuthorRuthger Idema
29 april 202611 min leestijd

Orders, voorraad, debiteuren — als Magento en Exact Online niet synchroon lopen, loopt je bedrijfsvoering mis. Hoe je een betrouwbare middleware-architectuur bouwt die foutafhandeling en retry-logica serieus neemt.

Magento 2 + Exact Online: real-time synchronisatie

Elke dag dat Magento en Exact Online niet synchroon lopen, neemt je team handmatig werk over dat de integratie zou moeten doen. Orders overtypen, voorraden handmatig aanpassen, klantgegevens dubbel bijhouden — het is verspilling van tijd die je beter kunt besteden.

De koppeling tussen Magento 2 en Exact Online is technisch haalbaar via de Exact Online REST API. Maar "het werkt" is niet genoeg. Een integratie zonder goede foutafhandeling en retry-logica is een tijdbom. Dit artikel legt uit hoe je het goed aanpakt.

Wat je leert in dit artikel

  • Welke data er gesynchroniseerd moet worden en in welke richting
  • Hoe de Exact Online REST API werkt
  • Middleware-architectuur voor betrouwbare synchronisatie
  • Foutafhandeling en retry-strategie
  • Specifieke valkuilen bij de Magento–Exact koppeling

Wat moet er gesynchroniseerd worden?

Voordat je begint, breng je de datastroom in kaart. Magento en Exact Online bevatten overlappende data — maar de master wisselt per dataset.

DataMasterRichting
Producten / artikelenExact Online (of PIM)→ Magento
VoorraadniveausExact Online of WMS→ Magento
OrdersMagento→ Exact Online
Klanten / debiteurenMagento (nieuw) / Exact (bestaand)Bidirectioneel
FacturenExact Online→ Magento (optioneel)
BetalingsstatusExact Online→ Magento (optioneel)

Bidirectionele synchronisatie van klantgegevens is de meest complexe stap. Nieuwe klanten registreren in Magento moeten als debiteur in Exact worden aangemaakt. Bestaande debiteuren in Exact moeten in Magento als klant beschikbaar zijn voor B2B-orders.

Definieer dit vooraf. Onduidelijkheid over wie master is, leidt tot conflicten en overschreven data.

De Exact Online REST API

Exact Online biedt een REST API op basis van OData. De endpoints zijn te vinden op developer.exactonline.com.

Authenticatie: OAuth 2.0 met de Authorization Code flow. Je hebt een Exact Online App Center-applicatie nodig met client ID en secret. Access tokens verlopen na 10 minuten. Refresh tokens na 30 dagen.
php
// Token ophalen en opslaan
$tokenData = $this->oauthClient->getAccessToken(
    'authorization_code',
    ['code' => $authCode]
);

// Token opslaan met expiratie
Cache::put('exact_access_token', $tokenData->getToken(), 590); // 590 seconden
Cache::put('exact_refresh_token', $tokenData->getRefreshToken(), 30 * 24 * 3600);
Rate limiting: Exact Online heeft een limiet van 5.000 API-calls per dag per token. Bij grote catalogi of hoge ordervolumes is dit een serieuze beperking. Bulkoperaties en caching zijn noodzakelijk. Divisienummer: Elke Exact Online omgeving heeft een divisienummer dat in elk API-verzoek moet worden meegestuurd.
php
// Voorbeeld: orders ophalen
$response = Http::withToken($accessToken)
    ->get("https://start.exactonline.nl/api/v1/{$division}/salesorder/SalesOrders", [
        '$filter' => "Status eq 20", // Bevestigde orders
        '$top' => 100,
        '$select' => 'OrderID,OrderNumber,OrderDate,TotalAmountDC',
    ]);

Middleware-architectuur

Directe synchronisatie — Magento roept Exact aan, Exact roept Magento aan — is fragiel. Als één systeem tijdelijk niet beschikbaar is, gaat data verloren.

De betrouwbare aanpak is een middleware-laag die als buffer fungeert.

Magento 2 (order geplaatst)
   Event: sales_order_place_after
   Middleware queue: order-job aanmaken
   Worker: Exact Online API aanroepen
   Succes: Exact order-ID opslaan in Magento
   Fout: job opnieuw proberen met exponential backoff
Laravel als middleware is hier een uitstekende keuze. Laravel Queues met een Redis-driver geven je:
  • Betrouwbare job-queue met persistentie
  • Automatische retry bij fouten
  • Job-monitoring via Laravel Horizon
  • Exponential backoff zodat tijdelijke Exact-storingen geen cascade veroorzaken
php
// Job aanmaken bij nieuwe order
class SyncOrderToExact implements ShouldQueue
{
    use InteractsWithQueue, Queueable, SerializesModels;

    public $tries = 5;
    public $backoff = [30, 120, 300, 600, 1800]; // Seconden tussen pogingen

    public function __construct(private int $orderId) {}

    public function handle(ExactOnlineService $exactService): void
    {
        $order = Order::findOrFail($this->orderId);

        // Controleer of order al gesynchroniseerd is
        if ($order->exact_order_id) {
            return;
        }

        $exactOrderId = $exactService->createSalesOrder($order);
        $order->update(['exact_order_id' => $exactOrderId]);
    }

    public function failed(\Throwable $e): void
    {
        // Alert sturen bij definitieve mislukking
        Notification::route('mail', config('exact.alert_email'))
            ->notify(new ExactSyncFailedNotification($this->orderId, $e));
    }
}

Orders synchroniseren

Een Magento-order omzetten naar een Exact Online verkooporder vereist mapping van meerdere entiteiten.

Stap 1: Debiteur vinden of aanmaken. Elk Exact-verkooporder heeft een debiteur nodig. Zoek op e-mailadres of KvK-nummer of maak een nieuwe debiteur aan. Stap 2: Orderregels mappen. Elk Magento-orderitem wordt een SalesOrderLine in Exact. Zorg dat het artikelnummer (SKU) overeenkomt met het Exact artikelnummer. Stap 3: Betaalwijze en leveringsadres meesturen. Exact Online heeft velden voor betaalconditie en leveringsadres.
php
public function createSalesOrder(Order $order): string
{
    $debtor = $this->findOrCreateDebtor($order->getCustomerEmail());

    $orderLines = [];
    foreach ($order->getAllVisibleItems() as $item) {
        $orderLines[] = [
            'Item' => $item->getSku(),
            'Description' => $item->getName(),
            'Quantity' => $item->getQtyOrdered(),
            'UnitPrice' => $item->getPrice(),
            'VATCode' => $this->resolveVatCode($item->getTaxPercent()),
        ];
    }

    $response = $this->exactClient->post('salesorder/SalesOrders', [
        'OrderedBy' => $debtor['ID'],
        'DeliverTo' => $debtor['ID'],
        'PaymentCondition' => $this->resolvePaymentCondition($order),
        'SalesOrderLines' => $orderLines,
    ]);

    return $response['d']['OrderID'];
}

Voorraadupdates

Voorraadsynchronisatie van Exact naar Magento is een polling-operatie. Exact Online biedt geen webhooks voor voorraadupdates.

php
// Elke 15 minuten draaien via scheduler
public function syncInventory(): void
{
    $items = $this->exactClient->get('inventory/ItemWarehouses', [
        '$filter' => "Modified gt datetime'" . now()->subMinutes(20)->toIso8601String() . "'",
        '$select' => 'Item,QuantityInStock,CurrentStock',
    ]);

    foreach ($items as $item) {
        $this->magentoInventoryService->updateStock(
            sku: $item['ItemCode'],
            qty: $item['CurrentStock']
        );
    }
}

Let op de 20-minuten filter bij een 15-minuten cron interval. De overlap zorgt dat je nooit een update mist bij een trage API-respons.

Klanten en debiteuren

Nieuwe Magento-klanten moeten als debiteur in Exact Online worden aangemaakt. Bestaande Exact-debiteuren moeten beschikbaar zijn in Magento voor B2B-bestellingen.

Deduplicatie is het kernprobleem. Dezelfde persoon kan al bestaan in Exact (als debiteur) én in Magento (als klant). Match op e-mailadres en KvK-nummer. Sla het Exact debiteur-ID op in Magento's customer_attribute tabel.
php
public function findOrCreateDebtor(string $email): array
{
    // Zoek op e-mailadres in Exact
    $existing = $this->exactClient->get('crm/Accounts', [
        '$filter' => "Email eq '{$email}'",
        '$top' => 1,
    ]);

    if (!empty($existing)) {
        return $existing[0];
    }

    // Nieuw debiteur aanmaken
    return $this->exactClient->post('crm/Accounts', [
        'Email' => $email,
        'Name' => $this->getNameFromEmail($email),
        'IsSupplier' => false,
        'IsCustomer' => true,
    ]);
}

Foutafhandeling: het verschil tussen goed en slecht

Een integratie zonder foutafhandeling faalt stil. Dat is het slechtste scenario — je ontdekt de misalignment pas wanneer een klant belt dat zijn order niet verwerkt is.

Categoriseer fouten:
  • Tijdelijke fouten (netwerktimeout, Exact tijdelijk down): retry met backoff
  • Validatiefouten (ontbrekend SKU, ongeldige btw-code): alert naar operations-team, handmatig oplossen
  • Authenticatiefouten (verlopen token): automatisch token vernieuwen en opnieuw proberen
php
public function handle(): void
{
    try {
        $this->syncOrderToExact();
    } catch (TokenExpiredException $e) {
        $this->tokenService->refresh();
        $this->release(5); // Over 5 seconden opnieuw proberen
    } catch (ValidationException $e) {
        // Niet opnieuw proberen, alert sturen
        Log::error('Exact validation error', [
            'order_id' => $this->orderId,
            'error' => $e->getMessage(),
        ]);
        $this->fail($e);
    } catch (ConnectException $e) {
        // Tijdelijk, opnieuw proberen
        $this->release($this->attempts() * 60);
    }
}

Monitoring

Stel een dashboard in dat toont:

  • Aantal jobs in de queue
  • Jobs die falen (en hoe vaak)
  • Gemiddelde sync-vertraging (tijd tussen order in Magento en order in Exact)
  • Voorraadupdates: wanneer was de laatste succesvolle sync?

Laravel Horizon geeft dit out-of-the-box voor queue-jobs. Voor een compleet beeld, voeg Sentry of Bugsnag toe voor fout-tracking.

Veelgemaakte fouten

1. Geen idempotentie inbouwen. Een job die twee keer wordt uitgevoerd moet niet twee orders aanmaken in Exact. Controleer altijd of een entiteit al gesynchroniseerd is vóór aanmaak. 2. Rate limit niet respecteren. 5.000 calls per dag klinkt veel. Bij een initiële bulk-sync of hoog ordervolume is het bereikbaar. Implementeer een rate-limit counter. 3. Exact als real-time systeem behandelen. Exact Online is geen real-time API. Polling-intervallen van minder dan 5 minuten zijn zinloos en verbruiken je dagelijkse call-budget. 4. Tokenvernieuwing niet afhandelen. Access tokens verlopen na 10 minuten. Als je middleware niet automatisch ververst, stopt de sync.

Conclusie

Een Magento 2 + Exact Online koppeling die echt betrouwbaar werkt vereist meer dan een API-verbinding. Het vraagt om een doordachte middleware-architectuur, heldere masterdata-afspraken en robuuste foutafhandeling.

De inspanning loont: geen handmatig orderwerk, actuele voorraadniveaus en debiteuren die automatisch worden aangemaakt. Dat is direct herstelbare tijd voor je team.

Lees ook ons artikel over ERP koppelen aan Magento 2 voor een breder overzicht van ERP-integratieopties. Voor middleware-oplossingen, bekijk onze Alumio integratie-pagina. Voor technische vragen over implementatie, ga naar onze Magento pagina.


Werkt je huidige Exact Online koppeling niet naar verwachting? Neem contact op — wij analyseren wat er mis is en bouwen het opnieuw.
Ruthger Idema

Geschreven door Ruthger Idema

15+ jaar ervaring in e-commerce development. Gespecialiseerd in Magento, Shopify en Laravel maatwerk.

Meer over ons team →
Deel dit artikel:

Wil je jouw e-commerce naar het volgende niveau?

Plan een vrijblijvend gesprek met onze experts over Magento, Shopify of Laravel maatwerk.

Plan een Tech Check