Skip to content

Sessie 30 december 2024: Mollie Payment Crisis & Docs Reorganisatie

Doel

Critical: Mollie payment flow ghost invoices en database locks oplossen. Documentatie reorganiseren voor betere vindbaarheid.

Crisis: Ghost Invoices & Database Locks

Symptomen

  • Ghost facturen: dubbele facturen bij refresh op mollie_return pagina
  • Database locks tijdens payment processing
  • Users klikken meerdere keren op refresh → pending payments
  • Onvertrouwelijk checkout proces

Root Cause

Race condition tussen Mollie webhook en return URL

Beide endpoints probeerden tegelijk: 1. Payment status ophalen van Mollie 2. Payment entity updaten 3. Order plaatsen 4. Invoice genereren

Oplossingen Geprobeerd

Poging 1: PaymentProcessingLock Event Subscriber

  • Lock mechanism tijdens payment processing
  • Bleef hangen bij concurrent requests
  • Locks werden niet altijd vrijgegeven

Poging 2: PaymentIdempotency Event Subscriber

  • Idempotency checks op payment events
  • Voorkwam dubbele processing maar niet de locks

Poging 3: MollieWebhookInterceptor (Queueing)

  • Probeerde webhook te queueen
  • Route detection werkte niet goed
  • stopPropagation() had geen effect

Poging 4: QueuedPaymentNotifyController (Override)

  • Override van commerce_payment.notify route
  • Access denied errors (missing permissions)
  • Complexity escaleerde

Finale Oplossing: Simplificatie

Principe: Webhook doet NIETS, return URL doet ALLES

Webhook (/payment/notify/{gateway}): - Returns immediate HTTP 200 OK - Geen processing, geen database queries - Mollie is tevreden

Return URL (/mollie_return/{order}): - User komt terug na betaling - Haalt status op van Mollie API - Update payment state - Plaatst order - Genereert invoice - Redirect naar checkout completion

Implementatie:

QueuedPaymentNotifyController.php:

public function notify(Request $request, string $commerce_payment_gateway) {
  return new Response('OK', 200);
}

MollieReturnController.php:

public function returnFromMollie(OrderInterface $commerce_order) {
  // Haal payment op
  // Check status bij Mollie API
  // Update payment state
  // Place order
  // Redirect naar /checkout/{order}/complete
}

Routes (vg_commerce.routing.yml):

commerce_payment.notify.mollie:
  path: '/payment/notify/{commerce_payment_gateway}'
  defaults:
    _controller: '\Drupal\vg_commerce\Controller\QueuedPaymentNotifyController::notify'
    _title: 'Payment notification'
  requirements:
    _access: 'TRUE'

vg_commerce.mollie_return:
  path: '/mollie_return/{commerce_order}'
  defaults:
    _controller: '\Drupal\vg_commerce\Controller\MollieReturnController::returnFromMollie'
  requirements:
    _entity_access: 'commerce_order.view'

Safety Layers (behouden voor extra zekerheid): - PaymentProcessingLock event subscriber - PaymentIdempotency event subscriber

Resultaat

✅ Geen ghost invoices meer ✅ Geen database locks ✅ Snelle response (geen polling/AJAX) ✅ Vertrouwelijk checkout proces

Invoice Template Fixes

Probleem

Factuur PDF toonde geen klantgegevens, geen ordernummer

Oorzaak

  • Invoice entity heeft orders field (plural), niet getOrder() method
  • Customer profile fields waren hidden in display mode
  • Template verwachtte billing_information maar kreeg niets

Oplossing

Handmatig address extraction in preprocess:

vg25_preprocess_commerce_invoice():

$orders = $invoice->get('orders')->referencedEntities();
$order = reset($orders);
$billing_profile = $order->getBillingProfile();
$address_data = $billing_profile->get('address')->first()->getValue();

// Build address markup
$variables['customer_details'] = [
  'name' => $address_data['given_name'] . ' ' . $address_data['family_name'],
  'organization' => $address_data['organization'],
  'address' => $address_data['address_line1'],
  'postal' => $address_data['postal_code'],
  'city' => $address_data['locality'],
  'country' => $address_data['country_code'],
];

Template updates: - Klantgegevens: naam, organisatie, adres, postcode, plaats, land - Factuurnummer + Ordernummer - BTW met percentages: "BTW (9%)" / "BTW (21%)" - Betaalstatus: Betaald - Verwijderd: vervaldatum, payment terms

Resultaat

✅ Volledige factuur met alle gegevens ✅ PDF generatie werkt perfect

Checkout Completion Page

Aanpassing: Geen auto-redirect meer, maar twee buttons

Template: commerce-checkout-completion-message.html.twig - Groene checkmark - "Bedankt voor je bestelling!" - Ordernummer - "Je ontvangt een bevestiging per email" - Button: "Naar de voorpagina" (/) - Button: "Ga naar mijn account" (/user)

WWW Redirect

Probleem: www.voedingsgeneeskunde.nl → voedingsgeneeskunde.nl werkte niet

Oplossing: Apache VirtualHost split

/etc/apache2/sites-available/voedingsgeneeskunde.nl-le-ssl.conf:

# WWW redirect
<VirtualHost *:443>
    ServerName www.voedingsgeneeskunde.nl
    Redirect permanent / https://voedingsgeneeskunde.nl/
    # SSL certificates...
</VirtualHost>

# Main site
<VirtualHost *:443>
    ServerName voedingsgeneeskunde.nl
    DocumentRoot /var/www/sites/live.voedingsgeneeskunde.nl/web
    # Rest of config...
</VirtualHost>

Resultaat

curl -I https://www.voedingsgeneeskunde.nl → 301 redirect

Backup Script Fix

Probleem: ldrush command not found in script

Oorzaak: ldrush is bash alias, niet beschikbaar in script context

Oplossing: Volledig pad gebruiken

backup-script.sh:

DRUSH="/var/www/sites/live.voedingsgeneeskunde.nl/vendor/drush/drush/drush"
$DRUSH sql:dump --gzip --result-file="${BACKUP_DIR}/db-${DATE}.sql"

Script maakt backup van: - Database → db-DATUM.sql.gz - Config → config-DATUM.tar.gz - Files (optioneel) → files-DATUM.tar.gz

Locatie: /var/www/sites/docs.voedingsgeneeskunde/docs/scripts/backup-script.sh

Docs Reorganisatie

Oude structuur: Verspreid over commerce/, patches/, user-experience/, integraties/

Nieuwe structuur:

docs/
├── everlasting-todo-lijst.md    # Start elke sessie hier
├── project-traject.md            # Timeline hele project
├── sessies/                      # Chronologisch dagboek
├── documentatie/                 # Per onderwerp
│   ├── commerce.md
│   ├── user-profiles.md
│   ├── integraties.md
│   └── vgbc.md
└── scripts/                      # Backup, migration tools

Voordelen: - Blog/dagboek stijl: nieuwste sessies bovenaan - Tags: Commerce, Users, Integraties, VGBC, UX, Patches, Migration - Documentatie per onderwerp voor technische details - Scripts georganiseerd op één plek - Everlasting todo lijst voor snelle start elke sessie - Leesbaar voor mensen én AI agents

Navigatie (tabs): 1. Home - Quick links 2. Todo & Traject - Everlasting todo + project timeline 3. Sessies - Alle sessieverslagen chronologisch 4. Documentatie - Technische overzichten per onderwerp 5. Scripts - Backup, migration, config import

Config Export voor Live

Exported: config-export-for-live-20251230-1553.tar.gz (377KB)

Bevat: - Mollie payment gateway config (test keys) - Commerce settings - Tax configuration - Shipping methods - Invoice templates - User profile types - Mailchimp integration

Instructies: scripts/live-config-import-instructies.md

Technische Details

Files aangepast vandaag: - /web/modules/custom/vg_commerce/src/Controller/QueuedPaymentNotifyController.php - /web/modules/custom/vg_commerce/src/Controller/MollieReturnController.php - /web/modules/custom/vg_commerce/vg_commerce.routing.yml - /web/modules/custom/vg_commerce/src/EventSubscriber/PaymentProcessingLock.php - /web/modules/custom/vg_commerce/src/EventSubscriber/PaymentIdempotency.php - /web/themes/custom/vg25/templates/commerce-invoice/commerce-invoice.html.twig - /web/themes/custom/vg25/vg25.theme - vg25_preprocess_commerce_invoice() - /web/modules/custom/vg_commerce/templates/commerce-checkout-completion-message.html.twig - /etc/apache2/sites-available/voedingsgeneeskunde.nl-le-ssl.conf

Zensical/Docs: - zensical.toml - Updated navigation - Nieuwe docs structuur met 5 documentatie overzichten - Sessie index met alle 27+ sessies getagd

Resultaat

Critical fixes compleet: ✅ Mollie payment flow: ghost invoices opgelost ✅ Database locks verholpen
✅ Invoice template: klantgegevens + BTW percentages ✅ WWW redirect geconfigureerd ✅ Checkout completion page met buttons ✅ Backup script gereed ✅ Config export voor live (377KB) ✅ Documentatie volledig gereorganiseerd

Site is klaar voor live migration (31 dec / 1 jan)

Known Issues (Fase 3)

  • Studentenkorting per attendee (nu hele order) - VGBC tickets
  • Email templates styling
  • User profile velden optimalisatie

Tags: Commerce, Patches, Critical, Documentatie, Migration