Blog overzicht

De gemakkelijkste manier om een adres vast te leggen en te valideren

Als je een artikel voor een klant moet verzenden of ophalen, heb je mogelijk hun adres nodig. Maar hoe verifieer je of het opgegeven adres daadwerkelijk bestaat?

Adresinformatie kan bestaan uit een straat, huisnummer, postcode, postbus, stad, staat, land, etc. Met Flow.ai en de Google Maps Geocoding API, is het niet nodig om al deze informatie apart te vragen.

Ontwerp je flow en leg het adres vast

Het trainen van de AI om contextueel huisnummers en steden te extraheren met behulp van entiteiten werkt, maar het vereist veel trainingsgegevens.

Zelfs als je honderd geannoteerde voorbeelden toevoegt, krijg je nog steeds mogelijk geen 100% perfect resultaat. In plaats daarvan is het veel gemakkelijker om een Any text te gebruiken met een Entity in de Text.

Met gebruik van de Any text kun je elke gebruikersinvoer vastleggen en die binnen een codeactie gebruiken om deze naar gestructureerde gegevens te geocoderen.

Adres API

Het adres valideren met de Google API

Er zijn verschillende providers, maar voor dit voorbeeld laten we zien hoe je de Google Maps Geocoding API kunt gebruiken om gebruikersinvoer om te zetten in gestructureerde adresinformatie.

Om de Geocoding API te gebruiken heb je een API key nodig. De API-key is een unieke identificatie die wordt gebruikt om verzoeken bij Google te verifiëren voor gebruiks- en factureringsdoeleinden.

Het schrijven van de code action

De eerste stap is het verkrijgen van de adresgegevens. Any text werkt op dezelfde manier als alle andere parameters.

In het onderstaande codevoorbeeld ontvangen we eenvoudig het adres en voeren het uit naar de logboekconsole.

async payload => {
  const {
    params,
    user
  } = payload

  const { address } = params

  const lastAddress = address[address.length - 1].value

  console.info('The last address captured', lastAddress)
}

Nu we het adres hebben, kunnen we het valideren en omzetten in gestructureerde adresgegevens met behulp van de Google API.

async payload => {
  try {
    const {
      params,
      user
    } = payload

    const { address } = params

    const lastAddress = address[address.length - 1].value

    // For this example we show the API key in code
    // but best practice is to use Configuration
    // https://flow.ai/docs/actions/code_configuration
    const key='MY SECRET API KEY'

    // Construct a Google API URL
    const url=encodeURI(`https://maps.googleapis.com/maps/api/geocode/json?address=${lastAddress}&key=${key}&language=${user.profile.locale || 'en'}`)

    // Call the API
    const { data } = await request(url)
    const { status, results } = data

    console.info('The API converted the address to', results)
  } catch(err) {
    console.error('Failed to call the API', err)
  }
}

Hieronder ziet je een voorbeeld van een geocoderingsresultaat in JSON. Raadpleeg de Google documentatie voor alle details van het antwoord.

[
  {
      "address_components" : [
        {
            "long_name" : "1600",
            "short_name" : "1600",
            "types" : [ "street_number" ]
        },
        {
            "long_name" : "Amphitheatre Pkwy",
            "short_name" : "Amphitheatre Pkwy",
            "types" : [ "route" ]
        },
        {
            "long_name" : "Mountain View",
            "short_name" : "Mountain View",
            "types" : [ "locality", "political" ]
        },
        {
            "long_name" : "Santa Clara County",
            "short_name" : "Santa Clara County",
            "types" : [ "administrative_area_level_2", "political" ]
        },
        {
            "long_name" : "California",
            "short_name" : "CA",
            "types" : [ "administrative_area_level_1", "political" ]
        },
        {
            "long_name" : "United States",
            "short_name" : "US",
            "types" : [ "country", "political" ]
        },
        {
            "long_name" : "94043",
            "short_name" : "94043",
            "types" : [ "postal_code" ]
        }
      ],
      "formatted_address" : "1600 Amphitheatre Parkway, Mountain View, CA 94043, USA",
      "geometry" : {
        "location" : {
            "lat" : 37.4224764,
            "lng" : -122.0842499
        },
        "location_type" : "ROOFTOP",
        "viewport" : {
            "northeast" : {
              "lat" : 37.4238253802915,
              "lng" : -122.0829009197085
            },
            "southwest" : {
              "lat" : 37.4211274197085,
              "lng" : -122.0855988802915
            }
        }
      },
      "place_id" : "ChIJ2eUgeAK6j4ARbn5u_wAGqWA",
      "types" : [ "street_address" ]
  }
]

Behandel alle edge cases

De Google API retourneert mogelijk meerdere resultaten, dus het is goed om het geretourneerde adres met de gebruiker te bevestigen.

Hiervoor breiden we de flows uit om edge cases te behandelen zoals:

Hieronder zie je een voorbeeld hoe je uiteindelijke flow eruit zou kunnen zien.

Google API edge cases

Binnen de code-actie sturen we een carousel component om de resultaten weer te geven en vragen we de gebruiker om het adres te verifiëren.

async payload => {
  
  try {  
    const {
      params,
      user
    } = payload

    const { address } = params

    const lastAddress = address[address.length - 1].value

    // Add the API key to the configuration
    const key = await toolbelt.config.get('api_key')

    // Build url
    const url=encodeURI(`https://maps.googleapis.com/maps/api/geocode/json?address=${lastAddress}&key=${key}&language=${user.profile.locale || 'en'}`)

    const { data } = await request(url)
    const { status, results } = data
    if(status !== 'OK') {
      return trigger('INVALID_ADDRESS')
    }

    /*
     * Simple helper function to find a piece
     * of address information within the API results
     */
    const findAddressPart = (result, part) => {
      const component = result.address_components.find(c => c.types.indexOf(part) !== -1)
      if(component) {
        return component.short_name
      }

      return ""
    }

    // Create a carousel
    const carousel = new Carousel()

    for (let i = 0; i < results.length; i++) {
      const result = results[i];

      // Create a card
      const card = new Card({
        title: result.formatted_address
      })

      const params = [
        new Param('delivery_street', findAddressPart(result, 'route')),
        new Param('delivery_zipcode', findAddressPart(result, 'postal_code')),
        new Param('delivery_housenumber', findAddressPart(result, 'street_number')),
        new Param('delivery_city', findAddressPart(result, 'locality')),
        new Param('delivery_country', findAddressPart(result, 'country'))
      ]

      card.addButton(new Button({
        label: "Confirm",
        type: 'event',
        value: 'ADDRESS_CONFIRMED',
        param: params
      }))

      carousel.addCard(card)
    }

    carousel.addQuickReply(new QuickReply({
      type: 'event',
      label: 'Try again',
      value: 'DELIVERY_ADDRESS'
    }))

    return new Message('We do not support audio only').addResponse(carousel)

  } catch(err) {
    console.error('Failed to call the API', err)
    trigger('INVALID_ADDRESS')
  }
}

Zoals je kunt zien, kun je echt geavanceerde use-cases maken.

Google API test

Lees meer

Demo aanvragen