Как реализовать решение для быстрой регистрации и подтверждения

Обзор

API: веб, , iOS

Платформа Google Карт совместима как с веб-приложениями (JS, TS), так и с приложениями для Android и iOS. Кроме того, она предоставляет API веб-сервисов для получения сведений о местах, маршрутах и расстояниях. В этом руководстве содержатся примеры для одной платформы, а для остальных приводятся ссылки на документацию по внедрению.

Создание кода

Код JavaScript для автоматического заполнения форм с адресом можно создать с помощью интерактивного инструмента Quick Builder в Google Cloud Console.

Пользователи привыкли к тому, что в цифровом мире все делается быстро, удобно и безопасно – эти возможности уже стали нормой. Подавая заявку на кредит или банковскую карту, мы ожидаем, что зарегистрироваться будет легко, а результатов не придется ждать долго.

Чем больше данных нужно вводить вручную, тем больше шансов потерять клиента, особенно если одни и те же сведения приходится указывать повторно. Функции быстрой регистрации и подтверждения сделают ваш сайт удобнее для пользователей и помогут их удержать.

Когда пользователям приходится указывать адреса вручную, вы получаете меньше конверсий, в вашу систему CRM чаще попадают неправильные данные, а ошибки при доставке товаров могут приносить большие убытки. Благодаря решению для быстрой регистрации и подтверждения, пользователю будет достаточно ввести несколько символов, чтобы появились находящиеся поблизости адреса. Нажав на один из них, клиент увидит маркер на карте и сразу поймет, правильно ли он выбрал. Сравнение адреса с текущим местоположением также помогает предотвращать мошеннические действия и повышает доверие пользователей к вашему сервису. Если вы предлагаете виртуальные и кредитные карты, подтверждение адреса поможет вам с большей уверенностью мгновенно одобрять заявки.

В этом руководстве приводятся рекомендации для разработчиков, желающих реализовать решение для быстрой регистрации и подтверждения с помощью платформы Google Карт. Поскольку пользователи чаще всего регистрируются с мобильных устройств, многие примеры реализации приведены для Android. Полный исходный код решения-образца доступен здесь. С помощью SDK для iOS можно реализовать аналогичное решение.

На схеме ниже показаны основные API, используемые в решении. Нажмите на рисунок, чтобы увеличить его.

Включение API

Чтобы реализовать рекомендуемое решение, нужно включить в Google Cloud Console следующие API:

Подробная информация приведена в статье Начало работы с платформой Google Карт.

Разделы рекомендаций

Ниже перечислены рекомендации, рассматриваемые в этой статье.

  • Флажком отмечены основные рекомендации.
  • Звездочкой отмечены второстепенные рекомендации, которые открывают дополнительные возможности.
Автозаполнение в полях ввода Настройте автозаполнение в полях адреса, чтобы людям было удобнее оформлять покупки на любых устройствах и чтобы адрес был указан точно при минимальном количестве нажатий на клавиатуре или экране.
Визуальное подтверждение адреса Показывайте маркер на карте, чтобы пользователь сразу видел, правильно ли он ввел адрес.
Сравнение адреса, введенного пользователем, с местоположением устройства Проверяйте, находится ли пользователь по указанному им адресу. Эта функция будет работать только в случаях, когда люди регистрируются из дома.
Рекомендации по улучшению решения для быстрой регистрации и подтверждения Вы можете реализовать дополнительные улучшения: например, изменить дизайн виджета автозаполнения или добавить поиск адреса по названию компании или достопримечательности.

Автозаполнение в полях ввода

Используется в примере: Places SDK для Android Также доступно: iOS | JavaScript

Сервис Place Autocomplete позволяет упростить ввод адреса в приложении, повысив удобство для пользователей и коэффициент конверсии. Поле быстрого ввода позволяет указать первые несколько букв и выбрать нужный адрес из предложенных вариантов. Этот адрес автоматически подставляется в форму для регистрации. Внедрение сервиса Place Autocomplete в форму регистрации позволяет:

  • уменьшить количество случаев, когда пользователи неправильно указывают адрес;
  • уменьшить количество шагов при регистрации;
  • упростить ввод адреса на мобильных и носимых устройствах;
  • значительно сократить общее время, которое клиенты тратят на регистрацию.

Когда пользователь начинает вводить адрес в поле с автозаполнением, он видит список вариантов.

Когда пользователь выбирает один из этих вариантов, вы подтверждаете адрес и получаете сведения о местоположении на основании ответа сервера. Затем поля адресной формы заполняются подтвержденными сведениями, как показано на рисунке ниже.

Видео: как улучшить форму адреса с помощью Place Autocomplete

Форма адреса

Android

iOS

Веб

Платформа Google Карт позволяет добавить на сайт или в мобильное приложение виджет Place Autocomplete, представляющий собой диалоговое окно с функцией автозаполнения (см. рисунки выше). Вы также можете добавить поддержку поиска с учетом текущего местоположения.

В этом разделе рассказывается, как реализовать виджет Place Autocomplete для быстрой регистрации и подтверждения.

Добавление виджета Place Autocomplete

В приложение для Android можно добавить этот виджет с помощью намерения Autocomplete, запускающего Place Autocomplete в поле первой строки адреса (где пользователь начинает вводить адрес). Указав первые несколько символов, можно будет выбрать адрес из предлагаемого функцией Autocomplete списка.

Сначала с помощью ActivityResultLauncher подготовьте средство запуска объекта activity, которое будет прослушивать результат запускаемого объекта activity. Результат будет представлять собой обратный вызов, содержащий объект Place, который соответствует адресу, выбранному пользователем из подсказок функции Autocomplete.

    private final ActivityResultLauncher<Intent> startAutocomplete = registerForActivityResult(
            new ActivityResultContracts.StartActivityForResult(),
            result -> {
                if (result.getResultCode() == Activity.RESULT_OK) {
                    Intent intent = result.getData();
                    if (intent != null) {
                        Place place = Autocomplete.getPlaceFromIntent(intent);

                        // Write a method to read the address components from the Place
                        // and populate the form with the address components
                        Log.d(TAG, "Place: " + place.getAddressComponents());
                        fillInAddress(place);
                    }
                } else if (result.getResultCode() == Activity.RESULT_CANCELED) {
                    // The user canceled the operation.
                    Log.i(TAG, "User canceled autocomplete");
                }
            });

Затем определите свойства, соответствующие полям, местоположению и типу, в объекте intent, и запустите этот объект с помощью Autocomplete.IntentBuilder. И наконец, запустите объект intent с помощью ActivityResultLauncher, определенного в примере кода выше.

    private void startAutocompleteIntent() {

        // Set the fields to specify which types of place data to
        // return after the user has made a selection.
        List<Place.Field> fields = Arrays.asList(Place.Field.ADDRESS_COMPONENTS,
                Place.Field.LAT_LNG, Place.Field.VIEWPORT);

        // Build the autocomplete intent with field, country, and type filters applied
        Intent intent = new Autocomplete.IntentBuilder(AutocompleteActivityMode.OVERLAY, fields)
                .setCountries(Arrays.asList("US"))
                .setTypesFilter(new ArrayList<String>() {{
                    add(TypeFilter.ADDRESS.toString().toLowerCase());
                }})
                .build(this);
        startAutocomplete.launch(intent);
    }

Обработка адреса, возвращаемого функцией Place Autocomplete

Определение ActivityResultLauncher (см. выше) также регламентирует, что должно происходить, когда объект activity возвращает результат с помощью обратного вызова. Если пользователь выбрал один из предлагаемых вариантов, этот вариант содержится в объекте intent, который, в свою очередь, содержится в объекте результата. Поскольку объект intent был построен объектом Autocomplete.IntentBuilder, метод Autocomplete.getPlaceFromIntent() может извлечь из него объект Place.

    private final ActivityResultLauncher<Intent> startAutocomplete = registerForActivityResult(
            new ActivityResultContracts.StartActivityForResult(),
            result -> {
                if (result.getResultCode() == Activity.RESULT_OK) {
                    Intent intent = result.getData();
                    if (intent != null) {
                        Place place = Autocomplete.getPlaceFromIntent(intent);

                        // Write a method to read the address components from the Place
                        // and populate the form with the address components
                        Log.d(TAG, "Place: " + place.getAddressComponents());
                        fillInAddress(place);
                    }
                } else if (result.getResultCode() == Activity.RESULT_CANCELED) {
                    // The user canceled the operation.
                    Log.i(TAG, "User canceled autocomplete");
                }
            });

После этого вызовите метод Place.getAddressComponents() и сопоставьте каждый компонент адреса с соответствующим полем ввода в адресной форме, чтобы заполнить эту форму значениями для выбранного пользователем места.

Извлечение адресов из предлагаемых вариантов, а не вводимых вручную данных, обеспечивает важные преимущества. Вы получаете более точные адреса (система подтверждает, что они существуют и могут использоваться для доставки), а пользователям нужно меньше печатать.

Что нужно учитывать при настройке Place Autocomplete

Сервис Place Autocomplete предусматривает гибкую реализацию с большим количеством вариантов для тех, кто хочет использовать не только виджет. Вы можете создавать различные комбинации сервисов в соответствии со своими нуждами.

  • Если вы хотите, чтобы в качестве подсказок использовались только полные почтовые адреса, присвойте параметру types значение address. Подробнее о типах, поддерживаемых в запросах Place Autocomplete

  • Если нет необходимости искать подходящие адреса по всему миру, задайте соответствующие ограничения и предпочтения. Вам доступен целый ряд параметров, позволяющих подбирать варианты, относящиеся только к определенным регионам.

    • Параметр RectangularBounds позволяет задать прямоугольную область, а параметр setLocationRestriction() – возвращать только те адреса, которые входят в нее.

    • Параметр setCountries() позволяет возвращать только те варианты, которые относятся к заданному списку стран.

  • Оставьте пользователю возможность вручную редактировать поля (для случаев, когда в предлагаемом варианте адреса отсутствуют значения некоторых полей). В адресах, возвращаемых сервисом Place Autocomplete, обычно отсутствует номер квартиры или офиса. Поэтому вы можете автоматически установить курсор на вторую строку адреса – это подскажет пользователю, что нужно указать недостающую информацию.

Визуальное подтверждение адреса

Используется в примере: Maps SDK для Android Также доступно: iOS | JavaScript

В диалоговом окне ввода адреса можно показывать маркер места на карте. Так пользователю будет проще проверить, правильно ли он указал адрес.

На рисунке ниже представлен пример карты с маркером.

В следующем примере рассматриваются основные шаги по добавлению карты в приложение для Android. Более подробные сведения доступны в документации.

Добавление фрагмента SupportMapFragment

Сначала добавьте фрагмент SupportMapFragment в XML-файл макета.

    <fragment
        android:name="com.google.android.gms.maps.SupportMapFragment"
        android:id="@+id/confirmation_map"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

Затем программно добавьте фрагмент, если он ещё не существует.

    private void showMap(Place place) {
        coordinates = place.getLatLng();

        // It isn't possible to set a fragment's id programmatically so we set a tag instead and
        // search for it using that.
        mapFragment = (SupportMapFragment)
                getSupportFragmentManager().findFragmentByTag(MAP_FRAGMENT_TAG);

        // We only create a fragment if it doesn't already exist.
        if (mapFragment == null) {
            mapPanel = ((ViewStub) findViewById(R.id.stub_map)).inflate();
            GoogleMapOptions mapOptions = new GoogleMapOptions();
            mapOptions.mapToolbarEnabled(false);

            // To programmatically add the map, we first create a SupportMapFragment.
            mapFragment = SupportMapFragment.newInstance(mapOptions);

            // Then we add it using a FragmentTransaction.
            getSupportFragmentManager()
                    .beginTransaction()
                    .add(R.id.confirmation_map, mapFragment, MAP_FRAGMENT_TAG)
                    .commit();
            mapFragment.getMapAsync(this);
        } else {
            updateMap(coordinates);
        }
    }

Получение дескриптора фрагмента и регистрация обратного вызова

  1. Чтобы получить дескриптор фрагмента, вызовите метод FragmentManager.findFragmentById и передайте ему идентификатор ресурса для фрагмента в файле макета. Если вы добавили фрагмент динамически, пропустите этот этап, поскольку вы уже получили дескриптор.

  2. Вызовите метод getMapAsync, чтобы задать обратный вызов для фрагмента.

Например, если вы добавили фрагмент статически, используйте следующий код:

Java


SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
    .findFragmentById(R.id.map);
mapFragment.getMapAsync(this);

      

Kotlin


val mapFragment = supportFragmentManager
    .findFragmentById(R.id.map) as SupportMapFragment
mapFragment.getMapAsync(this)

      

Настройка стилей и добавление маркера на карту

Когда карта будет готова, настройте стиль, задайте позицию камеры и добавьте маркер в точке, соответствующей указанному адресу. В приведенном ниже коде используется стиль, определенный в объекте JSON. Вместо этого вы можете загрузить идентификатор карты, определенный с помощью облачных ресурсов для работы со стилями.

    @Override
    public void onMapReady(@NonNull GoogleMap googleMap) {
        map = googleMap;
        try {
            // Customise the styling of the base map using a JSON object defined
            // in a string resource.
            boolean success = map.setMapStyle(
                    MapStyleOptions.loadRawResourceStyle(this, R.raw.style_json));

            if (!success) {
                Log.e(TAG, "Style parsing failed.");
            }
        } catch (Resources.NotFoundException e) {
            Log.e(TAG, "Can't find style. Error: ", e);
        }
        map.moveCamera(CameraUpdateFactory.newLatLngZoom(coordinates, 15f));
        marker = map.addMarker(new MarkerOptions().position(coordinates));
    }

См. полный пример кода.

Отключение элементов управления карты

Рекомендуем отключить на карте элементы управления (компас, панель инструментов и т. п.), которые в данном случае не нужны. В приложении для Android также можно включить упрощенный режим, ограничивающий функциональные возможности карты.

Сравнение адреса, введенного пользователем, с местоположением устройства

Получить доказательства того, что пользователь действительно проживает по указанному адресу, бывает непросто. Это может осложняться такими факторами, как отдаленное местоположение пользователя и недавние переезды. У некоторых компаний (например, цифровых банков) нет офиса, где пользователь может предъявить коммунальные счета или другие документы. Цифровые средства для подтверждения адреса позволяют сделать процесс регистрации более быстрым и удобным.

При проверке адреса, особенно во время цифровой регистрации, меры по обеспечению безопасности играют важную роль. В этом разделе приводятся рекомендации и примеры, которые помогут определить, соответствует ли фактическое местоположение пользователя тому адресу, который он указал как свой.

Сравнение указанного пользователем адреса с фактическим местоположением устройства выполняется в несколько этапов:

  1. Преобразование адреса, указанного пользователем, в географические координаты.
  2. Запрос разрешения пользователя на доступ к данным о местоположении устройства.
  3. Вычисление расстояния между указанным адресом и местоположением устройства. Вы сами задаете максимально допустимое расстояние.

На рисунке ниже показан пример диалогового окна, предлагающего пользователю подтвердить указанный адрес, проверив текущее местоположение устройства.

Преобразование адреса, указанного пользователем, в географические координаты

Используется в примере: Places SDK для Android Также доступно: iOS | JavaScript | Geocoding API

Когда пользователь соглашается на проверку адреса, выбрав вариант "Verify I'm there now" (Подтвердить, что я сейчас там) на рисунке выше, начинается процедура сравнения. Ее первый этап – преобразование указанного адреса в географические координаты.

Если при вводе адреса пользователь выбрал одну из подсказок функции Place Autocomplete, запросите Place.Field.LAT_LNG в списке полей Place Autocomplete, как показано в примере кода в этом разделе. Затем вызовите метод Place.getLatLng(), чтобы получить географические координаты выбранного адреса.

coordinates = place.getLatLng();

Если пользователь указал адрес вручную или изменил его после того, как поля были заполнены функцией Place Autocomplete, найдите координаты, соответствующие адресу, с помощью сервиса Geocoder для Android или Geocoding API.

Пример

https://maps.googleapis.com/maps/api/geocode/json?address=1600%20Amphitheatre%2BParkway%2C%20Mountain%20View%2C%20CA%2094043&key=YOUR_API_KEY

При вызове Geocoding API обязательно выполните кодирование URL.

Краткая справка по кодированию URL: %20 – пробел ( ), %2B – плюс (+), %2C – запятая (,).

Запрос разрешения пользователя на доступ к данным о местоположении устройства

Чтобы узнать местоположение устройства, нужно запросить разрешение пользователя на доступ к геоданным. В соответствии с рекомендациями по созданию приложений для Android с поддержкой геолокации, реализуйте следующую схему:

  • Приложение запрашивает разовый доступ к точным данным о местоположении (ACCESS_FINE_LOCATION).

  • Если пользователь предоставил доступ, приложение получает данные о местоположении.

  • Если пользователь отклонил запрос, приложение корректно обрабатывает отказ. Например, можно показать следующее сообщение (если в приложении не хранятся данные о текущем местоположении пользователя):

    "Если вы не предоставите доступ к точным данным о местоположении, нужно будет подтвердить ваш адрес с помощью почты, чтобы активировать аккаунт. [ОК]"

На рисунке ниже показан пример всплывающего окна, запрашивающего разрешение пользователя на доступ к геоданным.

Чтобы проверить разрешение на доступ к геоданным, с помощью ActivityResultLauncher подготовьте средство запуска объекта activity, которое будет прослушивать результат запускаемого объекта activity. Обратный вызов с результатом будет содержать строку, указывающую, предоставил ли пользователь разрешение.

    // Register the permissions callback, which handles the user's response to the
    // system permissions dialog. Save the return value, an instance of
    // ActivityResultLauncher, as an instance variable.
    private final ActivityResultLauncher<String> requestPermissionLauncher =
            registerForActivityResult(new ActivityResultContracts.RequestPermission(), isGranted -> {
                if (isGranted) {
                    // Since ACCESS_FINE_LOCATION is the only permission in this sample,
                    // run the location comparison task once permission is granted.
                    // Otherwise, check which permission is granted.
                    getAndCompareLocations();
                } else {
                    // Fallback behavior if user denies permission
                    Log.d(TAG, "User denied permission");
                }
            });

Затем проверьте, есть ли у приложения разрешение ACCESS_FINE_LOCATION. Если разрешение отсутствует, запросите его у пользователя с помощью средства запуска, созданного на предыдущем шаге.

    private void checkLocationPermissions() {
        if (ContextCompat.checkSelfPermission(this, ACCESS_FINE_LOCATION)
                == PackageManager.PERMISSION_GRANTED) {
            getAndCompareLocations();
        } else {
            requestPermissionLauncher.launch(
                    ACCESS_FINE_LOCATION);
        }
    }

Когда разрешение ACCESS_FINE_LOCATION будет получено, с помощью поставщика геоданных из нескольких источников получите последнее известное местоположение устройства и создайте объект LatLng с его координатами.

        FusedLocationProviderClient fusedLocationClient =
                LocationServices.getFusedLocationProviderClient(this);

        fusedLocationClient.getLastLocation()
                .addOnSuccessListener(this, location -> {
                    // Got last known location. In some rare situations this can be null.
                    if (location == null) {
                        return;
                    }

                    deviceLocation = new LatLng(location.getLatitude(), location.getLongitude());
                    // ...
                });
    }

Вычисление расстояния между указанным адресом и местоположением устройства

С помощью математических функций вычислите расстояние между двумя точками с известными координатами (адресом, который указал пользователь, и местоположением устройства). В библиотеке утилит Maps SDK для Android с открытым исходным кодом есть полезные методы для вычисления геодезического расстояния между двумя точками на поверхности Земли.

Сначала установите библиотеку утилит Maps SDK для Android, добавив в файл build.gradle своего приложения следующую зависимость:

dependencies {
    implementation 'com.google.maps.android:android-maps-utils:3.4.0'

}

Затем в файле объекта activity после получения последнего известного местоположения устройства задайте радиус (в метрах), в пределах которого два местоположения будут считаться совпадающими. Этот радиус должен быть достаточно большим, чтобы учитывались вариации точности позиционирования GPS и размеров зданий, адрес которых указывают пользователи. Пример:

private static final double acceptableProximity = 150;

Затем с помощью метода computeDistanceBetween() из библиотеки утилит вычислите расстояние между местоположением устройства и адресом, который указал пользователь. Если расстояние не превышает радиус, заданный на предыдущем шаге, считайте, что местоположения совпадают.

// Use the computeDistanceBetween function in the Maps SDK for Android Utility Library
// to use spherical geometry to compute the distance between two Lat/Lng points.
double distanceInMeters = computeDistanceBetween(deviceLocation, enteredLocation);
if (distanceInMeters <= acceptedProximity) {
    Log.d(TAG, "location matched");
    // TODO: Display UI based on the locations matching
} else {
    Log.d(TAG, "location not matched");
    // TODO: Display UI based on the locations not matching
}

См. полный пример кода.

Если адрес и местоположение устройства совпадают, отобразите подтверждение, как показано на рисунке ниже.

Рекомендации по улучшению решения для быстрой регистрации и подтверждения

Добавьте возможность найти адрес по названию компании или объекта инфраструктуры. Подсказки доступны не только для адресов, но также для названий организаций и ориентиров. Чтобы пользователи могли вводить как адреса, так и названия организаций, удалите свойство types из определения Autocomplete.

Настройте внешний вид поля с автозаполнением. Если вместо стандартного виджета Place Autocomplete от Google вы хотите использовать собственный стиль, вы можете обращаться к сервису Place Autocomplete программно, а пользовательский интерфейс создать самостоятельно.