Dowiedz się, jak przejście na PWA pomogło firmie MishiPay.
Dzięki MishiPay kupujący mogą skanować zakupy i opłacać je za pomocą smartfonów, zamiast tracić czas w kolejce do kasy. Dzięki technologii Scan & Go firmy MishiPay kupujący mogą za pomocą telefonu zeskanować kod kreskowy na produktach, zapłacić za produkty, a następnie po prostu opuścić sklep. Badania pokazują, że pozycja w kolejkach w sklepie kosztuje w globalnym sektorze handlu detalicznego około 200 miliardów dolarów rocznie.
Nasza technologia opiera się na możliwościach sprzętowych urządzeń, takich jak czujniki GPS i aparaty fotograficzne, które pozwalają użytkownikom zlokalizować sklepy obsługujące MishiPay, skanować kody kreskowe produktów w sklepach i płacić za pomocą wybranej przez siebie cyfrowej formy płatności. Początkowe wersje naszej technologii Scan & Go były przeznaczone na konkretne platformy na iOS i Androida, a początki byli zachwyceni tą technologią. Czytaj dalej, aby dowiedzieć się, jak przejście na PWA zwiększyło 10-krotnie liczbę transakcji i zaoszczędziło 2,5 roku w kolejce.
10×
Większa liczba transakcji
2,5 roku
Kolejka została zapisana
Wyzwanie
Nasza technologia jest niezwykle przydatna dla użytkowników, którzy oczekują w kolejce lub przy kasie, ponieważ pozwalają im pominąć kolejkę i bezproblemowo płacić za zakupy w sklepach. Ale kłopotliwy pobieranie aplikacji na Androida lub iOS sprawił, że użytkownicy nie wybrali naszej technologii pomimo korzyści. Dla MishiPay było to coraz większe wyzwanie, dlatego musieliśmy zwiększyć liczbę użytkowników, ograniczając barierę dostępu.
Rozwiązanie
Wysiłki związane z opracowaniem i uruchomieniem aplikacji PWA pozwoliły nam wyeliminować kłopoty z instalacją i zachęciły nowych użytkowników do wypróbowania naszej technologii w sklepie stacjonarnym, ominięcia kolejki i sprawnego dokonywania zakupów. Od tego czasu zaobserwowaliśmy ogromny wzrost liczby użytkowników naszej progresywnej aplikacji internetowej w porównaniu z aplikacjami na poszczególnych platformach.
Szczegóły techniczne
Znajduję sklepy obsługujące MishiPay
Do włączania tej funkcji służy interfejs API getCurrentPosition()
oraz rozwiązanie zastępcze oparte 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,
);
To podejście sprawdzało się we wcześniejszych wersjach aplikacji, ale później okazało się dużym problemem dla użytkowników MishiPay z tych powodów:
- Niedokładności lokalizacji w rozwiązaniach zastępczych opartych na adresie IP.
- Coraz większa liczba sklepów obsługujących MishiPay w danym regionie wymaga od użytkowników przewijania listy i wyboru odpowiedniego sklepu.
- Użytkownicy czasami przypadkowo wybierają niewłaściwy sklep, przez co zakupy są rejestrowane nieprawidłowo.
Aby rozwiązać te problemy, umieściliśmy unikalne kody QR z lokalizacją geograficzną na ekranach w każdym sklepie. Utorował on drogę do szybszego wdrożenia. Aby uzyskać dostęp do aplikacji internetowej Scan & Go, użytkownicy muszą po prostu skanować geolokalizowane kody QR wydrukowane w materiałach marketingowych dostępnych w sklepach.
Dzięki temu nie będą musieli wpisywać adresu mishipay.shop
, aby uzyskać dostęp do usługi.
Skanuję produkty
Podstawową funkcją aplikacji MishiPay jest skanowanie kodów kreskowych, ponieważ pozwala to użytkownikom skanować własne zakupy i sprawdzać ich łączną kwotę, jeszcze zanim dotrą oni do kasy.
Aby umożliwić użytkownikom skanowanie w internecie, zidentyfikowaliśmy 3 główne warstwy.
Strumień wideo
Za pomocą metody getUserMedia()
mamy dostęp do kamery tylnej kamery użytkownika (z ograniczeniami wymienionymi poniżej). Wywołanie metody powoduje automatyczne wyświetlenie prośby o zaakceptowanie lub odmowę dostępu do kamery. Gdy mamy dostęp 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
W przypadku wykrywania kodu kreskowego w strumieniu wideo musimy co jakiś czas przechwytywać klatki i przesyłać je do warstwy dekodera. Aby przechwycić klatkę, rysujemy po prostu strumienie z VideoElement
w elemencie 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ż pewne wstępne przetwarzanie, takie jak przycinanie, obracanie i przetwarzanie w trybie szarości. Te zadania mogą być obciążające procesor i powodować, że aplikacja nie będzie reagować, ponieważ skanowanie kodów kreskowych jest procesem trwającym długo. Interfejs API OffscreenCanvas pozwala przeciążyć zadanie pracochłonne przez pracowników sieciowych. Na urządzeniach obsługujących sprzętową akcelerację graficzną interfejs WebGL API i jego WebGL2RenderingContext
mogą optymalizować korzyści wynikające z zadań wstępnego przetwarzania intensywnie obciążających procesor.
Warstwa dekodera
Ostatnia warstwa to warstwa dekodera, która odpowiada za dekodowanie kodów kreskowych z ramek przechwyconych przez warstwę przetwarzania. Interfejs shape Detection API (który nie jest jeszcze dostępny we wszystkich przeglądarkach) pozwala samodzielnie dekodować kod kreskowy z pliku ImageBitmapSource
, który może być elementem img
, elementem SVG image
, elementem video
, elementem canvas
, obiektem Blob
, obiektem ImageData
lub obiektem 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 Percent Detection API, potrzebujemy rozwiązania zastępczego, aby dekodować kody kreskowe. Interfejs Character Detection API ujawnia metodę getSupportedFormats()
, która ułatwia przełączanie się między Character 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 open source i dla firm, które można łatwo zintegrować z dowolną aplikacją internetową w celu wdrożenia skanowania. Oto niektóre biblioteki polecane przez MishiPay.
Wszystkie powyższe biblioteki to w pełni funkcjonalne pakiety SDK, które składają się ze wszystkich omówionych powyżej warstw. Udostępniają też interfejsy do obsługi różnych operacji skanowania. W zależności od formatów kodu kreskowego i szybkości wykrywania wymaganych w danej firmie dostępne są rozwiązania Wasm i inne niż Wasm. Mimo że dekodowanie kodu kreskowego wymaga dodatkowych zasobów (Wasm), rozwiązania Wasm pod względem dokładności są lepsze od rozwiązań innych niż Wasm.
Głównym wyborem był Scandit. Obsługuje wszystkie formaty kodów kreskowych wymagane w naszych firmach i pod względem szybkości skanowania przewyższa wszystkie dostępne biblioteki open source.
Przyszłość skanowania
Gdy wszystkie najpopularniejsze przeglądarki będą w pełni obsługiwać interfejs shape Detection API, możemy opracować nowy element HTML <scanner>
z funkcjami wymaganymi przez skanery kodów kreskowych. Dział techniczny MishiPay uważa, że funkcja skanowania kodów kreskowych może zostać nowym elementem HTML ze względu na rosnącą liczbę bibliotek open source i licencjonowanych bibliotek, które umożliwiają takie rozwiązania jak Scan & Go i wiele innych.
Podsumowanie
Zmęczenie aplikacją to problem, z którym borykają się deweloperzy, gdy ich produkty wkraczają na rynek. Przed pobraniem aplikacji użytkownicy często chcą poznać korzyści, jakie daje im aplikacja. W sklepie, w którym MishiPay oszczędza czas kupujących i zwiększa ich wygodę, czekanie na pobranie aplikacji przed użyciem aplikacji jest sprzeczne z intuicją. Z pomocą przychodzi nam nasza aplikacja PWA. Dzięki wyeliminowaniu bariery wejścia na rynek zwiększyliśmy liczbę transakcji dziesięciokrotnie, a użytkownikom nie trzeba czekać 2,5 roku w kolejce.
Podziękowania
Autor artykułu: Joe Medley.