Привет! Меня зовут Виктор, я Frontend-разработчик в Clevertec. Сейчас мы с командой разрабатываем веб-версию банкинга с использованием React. Чтобы дать пользователям доступ к функциям, привычным в нативных приложениях, и добавить новые, мы используем Web API. Подробно расскажу о них в этой статье и раскрою некоторые тонкости.
Web Share API
Web Share API позволяет веб-приложениям обмениваться ссылками, текстом и файлами с другими приложениями, установленными на устройстве, так же, как это делают нативные приложения. Например, можно быстро поделиться чеком об оплате в мессенджере, не выходя из банковского приложения.

Web Share API имеет следующие возможности и ограничения:
-
Только сайты с протоколом HTTPS могут использовать Web Share API. Кроме того, для облегчения разработки API работает на localhost.
-
Может запускаться только по определенным действиям, например, на клик. Он не может быть запущен при загрузке страницы или через setTimeout().
-
С его помощью можно делиться URL-адресами, текстом или файлами.
-
Возможность делиться ресурсами доступна как на десктопных, так и на мобильных устройствах.
Чтобы поделиться ссылками и текстом, используйте метод share() на основе промисов с обязательным объектом свойств. Чтобы браузер не генерировал TypeError, объект должен содержать хотя бы одно из следующих свойств: title, text, url или files.
К примеру, можно поделиться текстом без URL-адреса или наоборот. Указание всех трех параметров расширяет гибкость вариантов использования. Допустим, после выполнения приведенного ниже кода пользователь выбрал приложение электронной почты в качестве цели. Параметр title может стать темой письма, text — телом сообщения, а файлы — вложениями.
if(navigator.share) {
navigator.share({
title: 'web.dev',
text: 'Открой для себя web.dev',
url: 'https://web.dev/'
})
.then(() => console.log('Удалось поделиться'))
.catch((error) => console.log('Не удалось поделиться', error));
}
Чтобы поделиться файлами, сначала проверьте и вызовите navigator.canShare(). Затем включите массив файлов в вызов navigator.share():
if(navigator.canShare && navigator.canShare({ files: filesArray })) {
navigator.share({
files: filesArray,
title: 'web.dev',
text: 'Открой для себя web.dev',
})
.then(() => console.log('Удалось поделиться'))
.catch((error) => console.log('Не удалось поделиться', error));
} else {
console.log('Ваша система не поддерживает обмен файлами');
}
Важно: в этом примере обнаружение функций реализуется путем проверки navigator.canShare(), а не navigator.share(). Объект данных, передаваемый в canShare(), поддерживает только свойство files. Если navigator.canShare() возвращает true, то возможность поделиться массивом файлов filesArray поддерживается.
Поддержка Web Share API на разных устройствах, операционных системах и браузерах на данный момент:
-
IOS: Safari, Chrome
-
Android: Chrome, Yandex, Edge
-
Windows: Chrome, Yandex, Edge, Opera
-
macOS: Safari
Не поддерживается:
-
Android: Firefox, Samsung browser, Opera (файлы шарить нельзя, только ссылки и текст)
-
Windows: Firefox
-
macOS: Chrome
Contact Picker API
API выбора контактов предоставляет пользователям простой способ поделиться контактами из своего списка. В поле ввода номера телефона или рядом с ним добавляется кнопка, при клике на которую открывается книга контактов устройства, из которой удобно выбрать нужный.

Чтобы проверить, поддерживается ли API выбора контактов, используйте:
const supported = ('contacts' in navigator && 'ContactsManager' in window)
На данный момент API поддерживается только на мобильных устройствах. На Android это Chrome, на IOS – Safari. Перед разработкой и тестированием API выбора контактов необходимо включить поддержку этой функции на устройстве. На Android он теперь доступен в Chrome 80 или более поздней версии по умолчанию.
Но если вы работаете с iOS, API выбора контактов считается экспериментальной функцией, и вам необходимо следовать этим инструкциям:
-
Зайти в «Настройки», прокрутить вниз и выбрать Safari
-
Прокрутить вниз, нажать «Дополнительно»
-
Выбрать меню «Experimental Features и переключить Contact Picker API
У объекта contacts есть методы getProperties() и select(). Метод getProperties() возвращает свойства, доступные на пользовательском устройстве.
Существует определенный список свойств, которые могут быть возвращены: имена, номера телефонов, адреса электронной почты, адреса и аватарка контакта:
const supported = ('contacts' in navigator && 'ContactsManager' in window)
interface ContactsManager {
getProperties: () => Promise<ContactProperty[]>;
}
enum ContactProperty {
"address" = "address",
"email" = "email",
"icon" = "icon",
"name" = "name",
"tel" = "tel",
}
async function checkPropertiesSupport(): Promise<void> {
try {
const supportedProperties = await navigator.contacts.getProperties();
setContactProperties(supportedProperties);
} catch {
console.warn(
"This browser doesn't support the Contact Picker API"
);
}
}
Список поддерживаемых свойств будет возвращен в виде массива. Например в приведенном выше случае мы могли бы получить массив типа ["email", "name", "tel"].
Метод select() принимает два аргумента:
1. Массив свойств контакта, например ( ["email", "name", "tel"] )
2. Объект с параметром multiple, который может быть true или false. Если установлен в true, то можно выбрать несколько контактов за один раз.
interface ContactsManager {
select: (
properties: ContactProperty[],
options?: ContactSelectOptions
) => Promise<ContactInfo[]>;
}
interface ContactInfo {
address: Array<ContactAddress>;
email: Array<string>;
icon: Blob;
name: Array<string>;
tel: Array<string>;
};
async function selectContacts () {
const contacts = await navigator.contacts.select(['name', 'tel'], { multiple: true });
if (!contacts.length) {
// нет выбранных контактов
return;
}
return contacts;
}
selectContacts();
Безопасность использования API выбора контактов:
1. Доступ осуществляется только на уровне браузера.
2. Работает только по протоколу HTTPS.
3. Не может быть активировано программным способом. Пользователь должен разрешить выбор из контактов, как если бы это происходило в нативном приложении.
Это дополнительный уровень безопасности, чтобы предотвратить ненужное или злонамеренное использование API без разрешения пользователя. Эти меры помогают обеспечить безопасность и конфиденциальность данных пользователей при использовании этого API.
Media Capture and Streams API
Это API позволяет веб-приложениям получать доступ к возможностям захвата мультимедиа на устройстве. Например, можно активировать камеру, считать штрихкод и редиректнуть пользователя по определенной ссылке.

В наше приложение интегрирована система приёма электронных платежей, в которой можно оплатить что-либо, отсканировав QR-код. После нажатия на “Сканировать QR” открывается окошко с камерой. Далее камера обнаруживает QR-код – и пользователя редиректит в дерево электронных платежей.
Для реализации использовали библиотеку html5-qrcode. Под капотом она использует Media Capture and Streams API. Работает как на десктопных, так и на мобильных устройствах, поддерживается всеми основными браузерами. Достаточно легковесная – 56 Kb.
После импорта стартуем работу камеры девайса с помощью html5QrCode.start()
import { Html5Qrcode } from 'html5-qrcode';
const html5QrCode = new Html5Qrcode("reader");
html5QrCode.start(
cameraId,
{
fps: 10,
qrbox: 250
},
qrCodeMessage => {
// сделать что то когда код прочитан
},
errorMessage => {
// если ошибка при чтении
})
.catch(err => {
// обработка ошибки
});
Этот метод возвращает промис с инициализацией сканирования QR-кода.
После проведения необходимых манипуляций останавливаем сканирование QR-кода с помощью метода html5QrCode.stop(), который возвращает промис для остановки сканирования.
html5QrCode.stop().then(ignore => {
// остановлено сканирование QR-кода
}).catch(err => {
// обработка ошибки
});
Саммари
Главное, что дают нам Web API – возможность предоставить бесшовный переход от использования нативного приложения к веб-версии. Если мобильное приложение недоступно – есть веб-версия, в которой благодаря технологиям мы обеспечиваем комфортную работу и максимально сокращаем шаги для выполнения рутинных действий.
Где-то они позволяют интегрироваться с нативными приложениями. Для пользователя это значит, что не нужно разбираться в новом и можно пользоваться привычными инструментами.
Из планов на будущее: WEB OTP API
В финале решил поделиться планами. WEB OTP API мы хотим внедрить на проекте. Это позволит автоматически вставлять код из смс.

Для подтверждения оплаты на телефон приходит сообщение. Внизу экрана появляется модальное окно с подтверждением вставки. И после нажатия на “Разрешить” код будет подставлен в поле ввода.
Если у вас есть успешный опыт использования Web OTP API и знание нюансов – поделитесь в комментариях :)
Автор: ViRFront