PWA от MishiPay увеличивает количество транзакций в 10 раз и экономит 2,5 года ожидания в очереди

Узнайте, как переход на PWA помог бизнесу MishiPay.

MishiPay позволяет покупателям сканировать и оплачивать покупки с помощью смартфонов, а не тратить время на ожидание в очереди на кассе. Благодаря технологии Scan & Go от MishiPay покупатели могут использовать свой собственный телефон для сканирования штрихкода на товарах и оплаты, а затем просто покинуть магазин. Исследования показывают, что очереди в магазинах обходятся мировому розничному сектору примерно в 200 миллиардов долларов в год.

Наша технология основана на аппаратных возможностях устройств, таких как датчики GPS и камеры, которые позволяют пользователям находить магазины с поддержкой MishiPay, сканировать штрихкоды товаров в физическом магазине, а затем платить с помощью выбранного ими цифрового платежного метода. Первоначальные версии нашей технологии Scan & Go представляли собой платформенно-зависимые приложения для iOS и Android, и первым пользователям эта технология понравилась. Читайте дальше, чтобы узнать, как переход на PWA увеличил количество транзакций в 10 раз и сэкономил 2,5 года очередей!

    10 ×

    Увеличение транзакций

    2,5 года

    Очередь сохранена

Испытание

Пользователи считают нашу технологию чрезвычайно полезной при ожидании в очереди или на кассе, поскольку она позволяет им избежать очереди и получить гладкий опыт в магазине. Но хлопоты по загрузке приложения Android или iOS заставили пользователей не выбирать нашу технологию, несмотря на ее ценность. Это было растущей проблемой для MishiPay, и нам нужно было увеличить принятие пользователями с более низким порогом входа.

Решение

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

Наглядное сравнение непосредственного запуска PWA (слева, быстрее) с установкой и запуском приложения Android (справа, медленнее).
Транзакции по платформам. ¡OS: 16397 (3,98%). Android: 13769 (3,34%). Web: 382184 (92,68%).
Большинство всех транзакций происходит в Интернете.

Техническое глубокое погружение

Поиск магазинов с поддержкой MishiPay

Для включения этой функции мы используем API getCurrentPosition() вместе с резервным решением на основе IP.

const geoOptions = {
  timeout: 10 * 1000,
  enableHighAccuracy: true,
  maximumAge: 0,
};

window.navigator.geolocation.getCurrentPosition(
  (position) => {
    const cords = position.coords;
    console.log(`Latitude :  ${cords.latitude}`);
    console.log(`Longitude :  ${cords.longitude}`);
  },
  (error) => {
    console.debug(`Error: ${error.code}:${error.message}`);
    /**
     * Invoke the IP based location services
     * to fetch the latitude and longitude of the user.
     */
  },
  geoOptions,
);

Такой подход хорошо работал в более ранних версиях приложения, но позже оказалось, что он стал большой проблемой для пользователей MishiPay по следующим причинам:

  • Неточности определения местоположения в резервных решениях на основе IP.
  • Растущий список магазинов, поддерживающих MishiPay, в каждом регионе требует от пользователей прокрутки списка и поиска нужного магазина.
  • Пользователи иногда случайно выбирают не тот магазин, в результате чего покупки регистрируются неправильно.

Чтобы решить эти проблемы, мы встроили уникальные геолокационные QR-коды на витрины в каждом магазине. Это проложило путь к более быстрому процессу регистрации. Пользователи просто сканируют геолокационные QR-коды, напечатанные на маркетинговых материалах, представленных в магазинах, чтобы получить доступ к веб-приложению Scan & Go. Таким образом, им не нужно вводить веб-адрес mishipay.shop для доступа к сервису.

Опыт сканирования в магазине с использованием PWA.

Сканирование продуктов

Основной функцией приложения MishiPay является сканирование штрихкода, поскольку это позволяет нашим пользователям сканировать свои покупки и видеть текущую сумму еще до того, как они доберутся до кассы.

Для создания процесса сканирования в Интернете мы выделили три основных уровня.

Диаграмма, показывающая три основных уровня потоков: видеопоток, уровень обработки и уровень декодера.

Видео поток

С помощью метода getUserMedia() мы можем получить доступ к камере заднего вида пользователя с ограничениями, перечисленными ниже. Вызов метода автоматически запускает запрос для пользователей на разрешение или запрет доступа к их камере. Получив доступ к видеопотоку, мы можем передать его в элемент video, как показано ниже:

/**
 * Video Stream Layer
 * https://developer.mozilla.org/docs/Web/API/MediaDevices/getUserMedia
 */
const canvasEle = document.getElementById('canvas');
const videoEle = document.getElementById('videoElement');
const canvasCtx = canvasEle.getContext('2d');
fetchVideoStream();
function fetchVideoStream() {
  let constraints = { video: { facingMode: 'environment' } };
  if (navigator.mediaDevices !== undefined) {
    navigator.mediaDevices
      .getUserMedia(constraints)
      .then((stream) => {
        videoEle.srcObject = stream;
        videoStream = stream;
        videoEle.play();
        // Initiate frame capture - Processing Layer.
      })
      .catch((error) => {
        console.debug(error);
        console.warn(`Failed to access the stream:${error.name}`);
      });
  } else {
    console.warn(`getUserMedia API not supported!!`);
  }
}

Уровень обработки

Для обнаружения штрихкода в данном видеопотоке нам нужно периодически захватывать кадры и передавать их в слой декодера. Чтобы захватить кадр, мы просто рисуем потоки из VideoElement на HTMLCanvasElement с помощью метода drawImage() API Canvas .

/**
 * Processing Layer - Frame Capture
 * https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API/Manipulating_video_using_canvas
 */
async function captureFrames() {
  if (videoEle.readyState === videoEle.HAVE_ENOUGH_DATA) {
    const canvasHeight = (canvasEle.height = videoEle.videoHeight);
    const canvasWidth = (canvasEle.width = videoEle.videoWidth);
    canvasCtx.drawImage(videoEle, 0, 0, canvasWidth, canvasHeight);
    // Transfer the `canvasEle` to the decoder for barcode detection.
    const result = await decodeBarcode(canvasEle);
  } else {
    console.log('Video feed not available yet');
  }
}

Для расширенных вариантов использования этот уровень также выполняет некоторые задачи предварительной обработки, такие как обрезка, поворот или преобразование в оттенки серого. Эти задачи могут быть ресурсоемкими и приводить к тому, что приложение перестает отвечать, учитывая, что сканирование штрихкода — это длительная операция. С помощью API OffscreenCanvas мы можем переложить ресурсоемкую задачу на веб-работника. На устройствах, поддерживающих аппаратное графическое ускорение, API WebGL и его WebGL2RenderingContext могут оптимизировать выигрыш в ресурсоемких задачах предварительной обработки.

Декодерный слой

Последний слой — это слой декодера, который отвечает за декодирование штрихкодов из кадров, захваченных слоем обработки. Благодаря API определения формы (который пока доступен не во всех браузерах) браузер сам декодирует штрихкод из ImageBitmapSource , который может быть элементом img , элементом image SVG, элементом video , элементом canvas , объектом Blob , объектом ImageData или объектом ImageBitmap .

Диаграмма, показывающая три основных уровня потока: видеопоток, уровень обработки и API обнаружения формы.

/**
 * Barcode Decoder with Shape Detection API
 * https://web.dev/shape-detection/
 */
async function decodeBarcode(canvas) {
  const formats = [
    'aztec',
    'code_128',
    'code_39',
    'code_93',
    'codabar',
    'data_matrix',
    'ean_13',
    'ean_8',
    'itf',
    'pdf417',
    'qr_code',
    'upc_a',
    'upc_e',
  ];
  const barcodeDetector = new window.BarcodeDetector({
    formats,
  });
  try {
    const barcodes = await barcodeDetector.detect(canvas);
    console.log(barcodes);
    return barcodes.length > 0 ? barcodes[0]['rawValue'] : undefined;
  } catch (e) {
    throw e;
  }
}

Для устройств, которые пока не поддерживают API определения формы, нам нужно резервное решение для декодирования штрихкодов. API определения формы предоставляет метод getSupportedFormats() , который помогает переключаться между API определения формы и резервным решением.

// Feature detection.
if (!('BarceodeDetector' in window)) {
  return;
}
// Check supported barcode formats.
BarcodeDetector.getSupportedFormats()
.then((supportedFormats) => {
  supportedFormats.forEach((format) => console.log(format));
});

Блок-схема, показывающая, как в зависимости от поддержки Barcode Detector и поддерживаемых форматов штрихкодов используется API распознавания формы или резервное решение.

Запасное решение

Доступно несколько библиотек сканирования с открытым исходным кодом и корпоративного уровня, которые можно легко интегрировать с любым веб-приложением для реализации сканирования. Вот некоторые из библиотек, которые рекомендует MishiPay.

Название библиотеки Тип Решение Wasm Форматы штрих-кода
QuaggaJs Открытый исходный код Нет 1D
ZxingJs Открытый исходный код Нет 1D и 2D (Ограничено)
КодКорп Предприятие Да 1D и 2D
Скандит Предприятие Да 1D и 2D
Сравнение библиотек сканирования штрихкодов с открытым исходным кодом и коммерческих библиотек

Все вышеперечисленные библиотеки являются полноценными SDK, которые составляют все слои, обсуждаемые выше. Они также предоставляют интерфейсы для поддержки различных операций сканирования. В зависимости от форматов штрихкодов и скорости обнаружения, необходимых для бизнес-кейса, можно сделать выбор между решениями Wasm и не-Wasm. Несмотря на накладные расходы, требующие дополнительного ресурса (Wasm) для декодирования штрихкода, решения Wasm превосходят решения не-Wasm с точки зрения точности.

Scandit был нашим основным выбором. Он поддерживает все форматы штрихкодов, необходимые для наших бизнес-кейсов; он превосходит все доступные библиотеки с открытым исходным кодом по скорости сканирования.

Будущее сканирования

Как только API распознавания формы будет полностью поддерживаться всеми основными браузерами, у нас потенциально может появиться новый элемент HTML <scanner> , обладающий возможностями, необходимыми для сканера штрихкодов. Инженеры MishiPay считают, что есть веский вариант использования функциональности сканирования штрихкодов в качестве нового элемента HTML из-за растущего числа библиотек с открытым исходным кодом и лицензированных библиотек, которые обеспечивают такие возможности, как Scan & Go и многие другие.

Заключение

Усталость от приложений — это проблема, с которой сталкиваются разработчики, когда их продукты выходят на рынок. Пользователи часто хотят понять ценность, которую приложение им дает, прежде чем они его загрузят. В магазине, где MishiPay экономит время покупателей и улучшает их опыт, нелогично ждать загрузки, прежде чем они смогут использовать приложение. Вот тут-то и помогает наше PWA. Устранив барьер для входа, мы увеличили количество транзакций в 10 раз и позволили нашим пользователям сэкономить 2,5 года ожидания в очереди.

Благодарности

Эту статью рецензировал Джо Медли .