Australia Post API — Location & Postcode Predictive Search

Last Updated: 22nd Sep, 2020

In this article, I'm writing about auto-suggesting postcode, the suburb of Australia with Australia Post API while filling up the address form.

I was recently working with an Australian client, it was an e-commerce platform to sell their products online.

I've also integrated shipping services like Temando, Transdirect, Auspost to calculate the postage cost in real-time. To protect their customer from not making mistake while filling up address form, they were interested in integrating real-time postcode, suburb auto-suggest. The idea was just for making the real-time postage cost calculation more consistent with the valid location.

1. Grab API Key

Before starting to build the feature and to make an API call, firstly we need to grab an API key from the Auspost developers center.Auspost API Key

2. Workflow

  • A customer starts typing at suburb, or postcode field in an HTML input box.
  • A twitter typeahead library detects the text change and fires an AJAX request, the server-side script again makes an API call behind the scene to get data from Auspost API.
  • The API call receives JSON data from Auspost API server, and it will be rendered as an auto-suggest popup.

3. Coding

I'm going to integrate this feature on top of Laravel framework v5.6, you are free to utilize it with any type of PHP project.

Adding new routes to display form, and for AJAX API call to the backend.

routes/web.php

Route::get('/postcode/search', [
    'name' => 'Australia Post Postcode Search',
    'as' => 'app.postcode.search',
    'uses' => 'AustraliaPostController@index',
]);

Route::get('/postcode/api/search', [
    'name' => 'Australia Post Postcode Search',
    'as' => 'app.postcode.api.search',
    'uses' => 'AustraliaPostController@search',
]);

app/Http/Controllers/AustraliaPostController.php

<?php

namespace App\Http\Controllers;

use App\Auspost\Request as Auspost;
use Illuminate\Http\Request;

/**
 * Class AustraliaPostController
 * @package App\Http\Controllers
 */
class AustraliaPostController extends Controller
{
    /**
     * @param Request $request
     */
    public function __construct(Request $request)
    {
        $this->request = $request;
    }

    /**
     * Australia Post API search form.
     *
     * @return mixed
     */
    public function index()
    {
        return view('auspost.search');
    }

    /**
     * @return array
     */
    public function search()
    {
        $parameters = [
            'q' => $this->request->get('query'),
        ];

        $response = with(new Auspost(config('auspost.auth_key')))
            ->send($parameters);

        $localities = collect($response['localities']['locality'] ?? []);

        if ($localities->count()) {
            $collection = is_array($localities->first()) ? $localities : [$localities];

            return response()->json($collection);
        }

        return [];
    }
}

config/auspost.php

<?php

// replace xx with your real Auth Key sent by Auspost developers centre.

return [
    'auth_key' => 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx',
];

app/Auspost/Request.php

<?php

namespace App\Auspost;

use GuzzleHttp\Client;
use GuzzleHttp\ClientInterface;

/**
 * Class Request
 * @package App\Auspost
 */
class Request
{
    const END_POINT = 'https://digitalapi.auspost.com.au/postcode/search.json';

    /**
     * The API token.
     *
     * @var string
     */
    protected $token;

    /**
     * The guzzle http client.
     *
     * @var \GuzzleHttp\ClientInterface
     */
    protected $client;

    /**
     * Create a new request instance.
     *
     * @param string $token
     */
    public function __construct($token)
    {
        $this->token = $token;
        $this->client = new Client();
    }

    public function getEndpoint()
    {
        return self::END_POINT;
    }

    /**
     * Retrive data via API call from Auspost server.
     *
     * @param array $parameters
     * @param $method
     *
     * @return App\Auspost\Response
     */
    public function send(array $parameters = [], $method = 'get')
    {
        $url = $this->getEndpoint() . '?' . http_build_query($parameters);

        $parameters = [
            'headers' => [
                'Content-Type' => 'application/json',
                'Auth-Key' => $this->token,
            ],
        ];

        try {
            $response = $this->client->request($method, $url, $parameters);

        } catch (ClientException $exception) {
            return $exception;
        }

        return with(new Response($response))->toArray();
    }
}

app/Auspost/Response.php

<?php

namespace App\Auspost;

use GuzzleHttp\Psr7\Response as GuzzleResponse;

/**
 * Class Response.
 * @package App\Auspost
 */
class Response extends GuzzleResponse
{
    /**
     * The guzzle http client response.
     *
     * @var \GuzzleHttp\Message\Response
     */
    protected $response;

    /**
     * Create a new response instance.
     *
     * @param GuzzleResponse $response
     */
    public function __construct(GuzzleResponse $response)
    {
        $this->response = $response;
    }

    /**
     * @return mixed
     */
    public function toJson()
    {
        return (string) $this->response->getBody();
    }

    /**
     * @return mixed
     */
    public function toArray()
    {
        return json_decode($this->toJson(), true);
    }
}

resources/views/search.blade.php

<div class="card-body">
    <form method="POST" action="/register">
        @csrf

        <div class="form-group row">
            <label for="search" class="col-md-4 col-form-label text-md-right">Postcode</label>
            <div class="col-md-8">
                <input id="search" type="text" data-suggest-postcode="{{ route('app.postcode.api.search') }}" class="form-control" name="email">
            </div>
        </div>
    </form>
</div>

I have only shown a small block of code above for the form, to view the full source code for the above tutorial feel free to visit the repository on github.

Also, view the last updated code here with another pull request in GitHub.

4. Preview

Auspost API Search PreviewNote: To run the above example, it requires twitter typeahead javascript library v0.11.1, Laravel 5.6, guzzle 6.*, but you could still use it with lower version of Laravel and guzzle library.

Conclusion

Thanks for reading the full article up to the end, feel free to leave your feedback if you are happy reading it.

Happy Coding!