Dowiedz się, jak przejście na PWA pomogło firmie MishiPay.
MishiPay umożliwia kupującym skanowanie i płacenie za zakupy za pomocą smartfonów, dzięki czemu nie muszą tracić czasu na stanie w kolejce do kasy. Dzięki technologii Scan & Go dostępnej w MishiPay klienci mogą za pomocą własnego telefonu zeskanować kod kreskowy produktu i zapłacić za niego, a następnie po prostu wyjść ze sklepu. Badania pokazują, że kolejka w sklepach stacjonarnych pochłania ok. 200 miliardów dolarów rocznie w przypadku globalnego sektora handlu detalicznego.
Nasza technologia opiera się na możliwościach sprzętowych urządzenia, takich jak czujniki GPS i kamery, które umożliwiają użytkownikom znajdowanie sklepów obsługujących MishiPay, skanowanie kodów kreskowych produktów w sklepie stacjonarnym, a następnie płacenie za pomocą wybranej formy płatności cyfrowej. Początkowe wersje technologii Skanuj i jedź były aplikacjami na iOS i Androida. Na początku spodobały się one użytkownikom. Przeczytaj artykuł, aby dowiedzieć się, jak przejście na PWA zwiększyło liczbę transakcji 10-krotnie i zaoszczędziło 2,5 roku oczekiwania w kolejce.
10×
Wzrost liczby transakcji
2,5 roku
Kolejka została zapisana
Wyzwanie
Użytkownicy uważają, że nasza technologia jest bardzo przydatna, gdy czekają w kolejce lub przy kasie, ponieważ pozwala im pominąć kolejkę i płynnie poruszać się po sklepie. Jednak konieczność pobrania aplikacji na Androida lub iOS sprawiła, że użytkownicy nie wybrali naszej technologii, mimo jej wartości. Było to coraz większe wyzwanie dla MishiPay, ponieważ musieliśmy zwiększyć liczbę użytkowników przy jednoczesnym obniżeniu progu wejścia.
Rozwiązanie
Dzięki wysiłkom włożonym w stworzenie i uruchomienie aplikacji internetowej udało nam się wyeliminować problemy związane z instalacją. Zachęciliśmy nowych użytkowników do wypróbowania naszej technologii w sklepie stacjonarnym, pominięcia kolejki i skorzystania z bezproblemowego procesu zakupowego. Od momentu wprowadzenia tej usługi obserwujemy ogromny wzrost wykorzystania naszej aplikacji PWA w porównaniu z aplikacjami przeznaczonymi wyłącznie na tę platformę.
Szczegółowa analiza techniczna
Znajdowanie sklepów obsługujących MishiPay
Aby włączyć tę funkcję, korzystamy z interfejsu API getCurrentPosition()
oraz rozwiązania zapasowego opartego na adresie 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,
);
Takie podejście sprawdzało się w wcześniejszych wersjach aplikacji, ale później okazało się, że jest bardzo uciążliwe dla użytkowników MishiPay z tych powodów:
- niedokładne lokalizacje w przypadku rozwiązań zapasowych opartych na adresie IP;
- Coraz większa liczba sklepów obsługujących MishiPay w poszczególnych regionach wymaga od użytkowników przewinięcia listy i zidentyfikowania odpowiedniego sklepu.
- Czasami użytkownicy przypadkowo wybierają niewłaściwy sklep, co powoduje nieprawidłowe rejestrowanie zakupów.
Aby rozwiązać te problemy, w ramach każdego sklepu umieściliśmy na wyświetlaczach w sklepie stacjonarnym unikalne kody QR z lokalizacją. Dzięki temu proces wprowadzania w użycie jest szybszy. Użytkownicy skanują kody QR z lokalizacją geograficzną wydrukowane na materiałach marketingowych w sklepach, aby uzyskać dostęp do aplikacji internetowej Skanuj i idź.
Dzięki temu nie muszą wpisywać adresu internetowego mishipay.shop
, aby uzyskać dostęp do usługi.
Skanowanie produktów
Podstawową funkcją aplikacji MishiPay jest skanowanie kodów kreskowych, ponieważ umożliwia użytkownikom skanowanie własnych zakupów i sprawdzanie łącznej kwoty jeszcze przed dotarciem do kasy.
Aby ułatwić skanowanie w internecie, zidentyfikowaliśmy 3 podstawowe warstwy.
Strumień wideo
Za pomocą metody getUserMedia()
możemy uzyskać dostęp do tylnej kamery użytkownika z ograniczeniami wymienionymi poniżej. Wywołanie tej metody automatycznie powoduje wyświetlenie użytkownikowi prośby o przyznanie lub odmowę dostępu do aparatu. Po uzyskaniu dostępu do strumienia wideo możemy przekazać go do elementu wideo w ten sposób:
/**
* 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!!`);
}
}
Warstwa przetwarzania
Aby wykryć kod kreskowy w strumieniu wideo, musimy okresowo rejestrować klatki i przesyłać je do warstwy dekodera. Aby uchwycić kadr, po prostu rysujemy strumień z VideoElement
na HTMLCanvasElement
za pomocą metody drawImage()
interfejsu Canvas API.
/**
* 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');
}
}
W zaawansowanych przypadkach użycia ta warstwa wykonuje też niektóre zadania wstępnego przetwarzania danych, takie jak przycinanie, obracanie czy przekształcanie w skalę szarości. Te zadania mogą być wymagające pod względem procesora i mogą spowodować, że aplikacja przestanie odpowiadać, ponieważ skanowanie kodów kreskowych to długotrwała operacja. Za pomocą interfejsu OffscreenCanvas możemy przekazać zadanie mocno angażujące procesor do web workera. Na urządzeniach, które obsługują akcelerację graficzną sprzętową, interfejs WebGL API i WebGL2RenderingContext
mogą optymalizować korzyści płynące z zadań wstępnych przetwarzania, które wymagają intensywnego wykorzystania procesora.
Warstwa dekodera
Ostatnią warstwą jest warstwa dekodera, która odpowiada za dekodowanie kodów kreskowych z klatek przechwycionych przez warstwę przetwarzania. Dzięki interfejsowi Shape Detection API (który nie jest jeszcze dostępny we wszystkich przeglądarkach) przeglądarka sama dekoduje kod kreskowy z elementu ImageBitmapSource
, który może być elementem img
, image
, video
, canvas
, obiektem Blob
, ImageData
lub ImageBitmap
.
/**
* 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;
}
}
W przypadku urządzeń, które nie obsługują jeszcze interfejsu Shape Detection API, potrzebujemy rozwiązania zapasowego do dekodowania kodów kreskowych. Interfejs Machine Detection API udostępnia metodę getSupportedFormats()
, która ułatwia przełączanie się między interfejsem Status Detection API a rozwiązaniem zastępczym.
// Feature detection.
if (!('BarceodeDetector' in window)) {
return;
}
// Check supported barcode formats.
BarcodeDetector.getSupportedFormats()
.then((supportedFormats) => {
supportedFormats.forEach((format) => console.log(format));
});
Rozwiązanie zastępcze
Dostępnych jest kilka bibliotek skanowania open source i firmowych, które można łatwo zintegrować z dowolną aplikacją internetową, aby wdrożyć skanowanie. Oto niektóre z bibliotek rekomendowanych przez MishiPay.
Wszystkie powyższe biblioteki to w pełni funkcjonalne pakiety SDK, które składają się na wszystkie omówione powyżej warstwy. Udostępniają też interfejsy do obsługi różnych operacji skanowania. W zależności od formatów kodu kreskowego oraz szybkości wykrywania wymaganej w danym przypadku można podjąć decyzję o rozwiązaniach Wasm lub innych niż Wasm. Pomimo konieczności użycia dodatkowego zasobu (Wasm) do dekodowania kodu kreskowego, rozwiązania Wasm wygrywają z rozwiązaniami bez Wasm pod względem dokładności.
Naszym głównym wyborem był Scandit. Obsługuje wszystkie formaty kodów kreskowych wymagane w przypadku zastosowań biznesowych; pod względem szybkości skanowania przewyższa wszystkie dostępne biblioteki open source.
Przyszłość skanowania
Gdy interfejs Machine Detection API będzie w pełni obsługiwany przez wszystkie popularne przeglądarki, być może udostępnimy nowy element HTML <scanner>
z funkcjami wymaganymi przez skaner kodów kreskowych. Zespół inżynierów w MishiPay uważa, że funkcja skanowania kodów kreskowych stanie się nowym elementem HTML ze względu na rosnącą liczbę bibliotek open source i licencjonowanych, które umożliwiają korzystanie z takich rozwiązań jak Scan &Go.
Podsumowanie
Zmęczenie aplikacjami to problem, z którym deweloperzy mierzą się, gdy ich produkty trafiają na rynek. Użytkownicy często chcą zrozumieć, co daje im aplikacja, zanim ją pobiorą. W sklepie, gdzie aplikacja MishiPay pozwala zaoszczędzić czas i poprawić wrażenia klientów, nielogicznym jest czekanie na pobranie aplikacji przed jej użyciem. Właśnie w tym przypadku przydatne są strony internetowe oparte na aplikacji internetowej. Dzięki usunięciu bariery wejścia liczba naszych transakcji wzrosła 10-krotnie, a użytkownicy zaoszczędzili 2,5 roku oczekiwania w kolejce.
Podziękowania
Ten artykuł został zrecenzowany przez Joe Medley.