Adresse-autocomplete i Magento 2-checkout

Installér Danadresse-modulet til autocomplete i checkout og adressetjek af hver ordre, eller kobl widget'en på selv med et theme-script og en CSP-whitelist.

5 min Niveau: Øvet ✓ Kode testet

Der findes et Magento-modul til Danadresse: lynbro/module-danadresse (modulnavn Lynbro_Danadresse, MIT-licens) til Magento Open Source og Adobe Commerce 2.4.4–2.4.8 på PHP 8.1–8.4. Det giver checkout'en og kundens adressebog adresse-autocomplete, udfylder vej, postnr., by og den danske region, og tjekker adressen på hver ny ordre. Kan du ikke installere moduler, viser anden halvdel af guiden, hvordan du kobler widget'en på med din egen theme-kode.

1. Opret to nøgler

Under Nøgler:

  • en browsernøgle til butikkens sider. Tilføj butikkens domæner under Tilladte domæner, fx minbutik.dk, www.minbutik.dk, og staging-domænet, hvis du tester der. En domænelåst nøgle virker kun på de domæner, så den kan stå i sidens kildekode. Se Browsernøgler og tilladte domæner.
  • en servernøgle uden domæner til ordretjekket. Magento gemmer den krypteret, og den når aldrig browseren.

2. Installér modulet

Hent lynbro-module-danadresse-<version>.zip på download-siden (version, SHA-256 og ændringslog står der). Composer læser zip-filen direkte som artifact-repository — pak den ikke ud: læg den i et artifacts/-katalog i Magento-roden, kør composer config repositories.danadresse artifact ./artifacts og composer require lynbro/module-danadresse. Uden Composer pakker du zip-filen ud i app/code/Lynbro/Danadresse/. Kør derefter:

Shell#module-install
bin/magento module:enable Lynbro_Danadresse
bin/magento setup:upgrade
bin/magento setup:di:compile                          # kun i production mode
bin/magento setup:static-content:deploy da_DK en_US   # kun i production mode
bin/magento cache:flush

setup:upgrade tilføjer to kolonner, der må være tomme, til sales_order (danadresse_status, danadresse_suggestion) og én til sales_order_grid. Intet andet ændres.

3. Opsætning

Gå til Stores → Configuration → LynBro → Danadresse — danske adresser:

  • Generelt: slå Aktivér adresse-autocomplete til (fra som standard), og sæt browsernøglen ind.
  • Butik: autocomplete i checkout, i kundens adressebog og ved oprettelse, tjek af indtastede adresser ("Mente du …?") og Udfyld by ud fra postnummer er slået til som standard.
  • Ordrevalidering: slå Valider adresser på nye ordrer til, sæt servernøglen ind, og vælg levering, fakturering eller begge. Resultatet tilføjes som intern ordrekommentar. Standard-timeout er 3 sekunder.

Alt kan sættes pr. website eller butiksvisning, fx kun i den danske butik.

Modulet tillader selv https://api.danadresse.dk i checkout'ens Content Security Policy, og scriptet hentes fra dine egne statiske filer.

4. Test

  1. Læg en vare i kurven, og åbn checkout.
  2. Skriv Rentemestervej 8 i Gadenavn, og vælg forslaget.
  3. Postnr. 2400, by København NV og regionen Hovedstaden bliver udfyldt.
  4. Gennemfør ordren. Under Salg → Ordrer står der Gyldig i kolonnen Adressetjek.

API refused the request (403) i browserens konsol betyder, at butikkens domæne mangler på browsernøglen. 401 betyder, at nøglen mangler eller er skrevet forkert. Ikke tjekket (API-fejl) på en ordre betyder, at servernøglen er forkert, eller at API'et ikke svarede inden for timeout.

Med et Hyvä-theme virker modulet på theme-siderne (adressebog, oprettelse) og i Luma-checkout'en, som Hyvä falder tilbage til. På Hyvä Checkout (Magewire) finder scriptet felterne via navn og autocomplete-attributter, men det er ikke testet på en live Hyvä Checkout. Test det, før du går live.

Uden modulet: din egen theme-kode

Magento 2's standard-checkout (Luma) tegner adressefelterne med Knockout, efter siden er indlæst. Felterne er almindelige input-elementer, så widget'en kan kobles på, men scriptet skal vente på dem og sende en change-event, så Knockout gemmer værdien. Fra Magento 2.4.7 kører checkout-siden desuden med en streng Content Security Policy, så vores domæner skal tillades, og Danmark har obligatoriske regioner: koden nedenfor sætter ikke regionen, så kunden vælger den selv.

Init-scriptet

Læg filen i dit theme som app/design/frontend/<Vendor>/<theme>/web/js/danadresse-init.js.

JavaScript#init-js
const API_KEY = "DIN_BROWSER_NØGLE";

function setField(el, value, events) {
  if (!el || value == null) return;
  const setter = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(el), "value").set;
  setter.call(el, value);
  for (const type of events || ["input", "change"]) {
    el.dispatchEvent(new Event(type, { bubbles: true }));
  }
}

function streetLine(a) {
  let line = a.vejnavn + " " + a.husnr;
  if (a.etage) line += ", " + a.etage + ".";
  if (a["dør"]) line += " " + a["dør"];
  return line;
}

function bind(input) {
  const form = input.form || document;
  DanadresseAutocomplete.attach(input, {
    apiKey: API_KEY,
    onSelect(a) {
      // change får Knockout til at opdatere sin observable
      setField(input, streetLine(a), ["change"]);
      setField(form.querySelector('input[name="postcode"]'), a.postnr);
      setField(form.querySelector('input[name="city"]'), a.postnrnavn);
    },
  });
}

function bindAll() {
  document.querySelectorAll('input[name="street[0]"]').forEach(bind);
}

function start() {
  bindAll();
  // Leverings- og betalingsadressen tegnes senere og kan tegnes igen.
  new MutationObserver(bindAll).observe(document.body, { childList: true, subtree: true });
}

if (document.readyState === "loading") document.addEventListener("DOMContentLoaded", start);
else start();

street[0], postcode og city er feltnavnene i Luma-checkout'en for både leverings- og betalingsadresse. Koden udfylder postnr. og by i den formular, kunden skriver i.

Indlæs scripts på checkout-siden

Opret Magento_Checkout/layout/checkout_index_index.xml i dit theme:

XML#layout-xml
<?xml version="1.0"?>
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
    <head>
        <script src="https://danadresse.dk/static/js/danadresse-autocomplete-1.0.0.js" src_type="url"/>
        <script src="js/danadresse-init.js"/>
    </head>
</page>

Kør bin/magento setup:static-content:deploy og tøm cachen.

Tillad domænerne i CSP

Uden denne fil blokerer Magento scriptet eller API-kaldene på checkout-siden. CSP-whitelists ligger i et modul, ikke i et theme, så læg den i et lille modul, fx app/code/Vendor/Danadresse/etc/csp_whitelist.xml:

XML#csp-whitelist
<?xml version="1.0"?>
<csp_whitelist xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
               xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Csp:etc/csp_whitelist.xsd">
    <policies>
        <policy id="script-src">
            <values>
                <value id="danadresse-script" type="host">https://danadresse.dk</value>
            </values>
        </policy>
        <policy id="connect-src">
            <values>
                <value id="danadresse-api" type="host">https://api.danadresse.dk</value>
            </values>
        </policy>
    </policies>
</csp_whitelist>

Test i checkout med browserens konsol åben. En CSP-fejl nævner det domæne, der mangler. 403 origin_not_allowed betyder, at domænet mangler på nøglen.

Tjek adressen, når ordren gemmes

I samme modul kan en observer på sales_order_place_before (registreret i etc/events.xml) tjekke leveringsadressen med servernøglen. Eksemplet stopper ikke ordren. Det skriver en kommentar på ordren, så nogen kan kigge på den.

PHP#observer-php
<?php
declare(strict_types=1);

namespace Vendor\Danadresse\Observer;

use Magento\Framework\Event\Observer;
use Magento\Framework\Event\ObserverInterface;

class CheckAddress implements ObserverInterface
{
    public function execute(Observer $observer): void
    {
        $order = $observer->getEvent()->getOrder();
        $address = $order->getShippingAddress() ?: $order->getBillingAddress();
        if (!$address || $address->getCountryId() !== 'DK') {
            return;
        }
        // Vej og husnr. (før første komma) + postnr.: tjekker bygningen
        $street = trim((string) strtok((string) ($address->getStreet()[0] ?? ''), ','));
        $url = 'https://api.danadresse.dk/datavask/adgangsadresser?'
            . http_build_query(['betegnelse' => $street . ', ' . $address->getPostcode()]);

        $ch = curl_init($url);
        curl_setopt_array($ch, [
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_TIMEOUT => 5,
            CURLOPT_HTTPHEADER => ['X-Api-Key: ' . getenv('DANADRESSE_API_KEY')],
        ]);
        $body = curl_exec($ch);
        $status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        curl_close($ch);
        if ($body === false || $status !== 200) {
            return; // API'et svarer ikke: ordren går igennem
        }
        $vask = json_decode($body, true);
        if (($vask['kategori'] ?? '') === 'C') {
            $order->addCommentToStatusHistory('Danadresse: adressen kunne ikke verificeres (kategori C).');
        }
    }
}

Kategorierne er forklaret i Datavask i checkout.

Næste skridt

Relaterede guides

Markdown-kilde Fejl i guiden? Skriv til os API-reference (Swagger)

Prøv det med en gratis nøgle

2 000 kald/måned på gratisplanen. Intet kreditkort.

Opret konto →