Dowiedz się, jak przejście na PWA pomogło firmie MishiPay w rozwoju.
MishiPay umożliwia klientom 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 firmy MishiPay kupujący mogą skanować kod kreskowy na produktach za pomocą własnego telefonu i za nie płacić, a następnie opuścić sklep. Badania pokazują, że roczne kolejki w sklepach kosztują globalny sektor handlu detalicznego 200 mld USD.
Nasza technologia opiera się na możliwościach sprzętowych urządzenia, takich jak czujniki GPS i kamery, które umożliwiają użytkownikom lokalizowanie sklepów obsługujących MishiPay, skanowanie kodów kreskowych produktów w sklepie stacjonarnym, a następnie płacenie wybraną cyfrową formą płatności. Pierwsze wersje naszej technologii Scan & Go były aplikacjami na iOS i Androida, a pierwsi użytkownicy bardzo je polubili. Czytaj dalej, aby dowiedzieć się, jak przejście na PWA zwiększyło liczbę transakcji 10-krotnie i pozwoliło zaoszczędzić 2,5 roku stania w kolejce.
10×
Większa liczba transakcji
2,5 roku
Kolejkowanie zostało zapisane
Wyzwanie
Użytkownicy uważają naszą technologię za bardzo przydatną podczas oczekiwania w kolejce, ponieważ pozwala im pominąć kolejkę i zapewnia płynne zakupy w sklepie. Jednak trudności związane z pobieraniem aplikacji na Androida lub iOS sprawiały, że użytkownicy nie wybierali naszej technologii pomimo jej zalet. Było to coraz większe wyzwanie dla MishiPay, dlatego musieliśmy zwiększyć liczbę użytkowników przy niższym progu wejścia.
Rozwiązanie
Dzięki stworzeniu i wdrożeniu PWA udało nam się wyeliminować problemy z instalacją i zachęcić nowych użytkowników do wypróbowania naszej technologii w sklepie stacjonarnym, pominięcia kolejki i skorzystania z wygodnych zakupów. Od momentu wprowadzenia tej funkcji odnotowaliśmy ogromny wzrost liczby użytkowników naszej progresywnej aplikacji internetowej w porównaniu z aplikacjami na poszczególne platformy.
Szczegółowe informacje techniczne
Znajdowanie sklepów obsługujących MishiPay
Aby włączyć tę funkcję, korzystamy z interfejsu API
getCurrentPosition()
oraz rozwiązania rezerwowego 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,
);
To podejście sprawdzało się w starszych wersjach aplikacji, ale później okazało się bardzo uciążliwe dla użytkowników MishiPay z tych powodów:
- Niedokładności lokalizacji w rozwiązaniach rezerwowych opartych na adresie IP.
- Rosnąca lista sklepów obsługujących MishiPay w poszczególnych regionach wymaga od użytkowników przewijania listy i znalezienia odpowiedniego sklepu.
- Użytkownicy czasami przypadkowo wybierają niewłaściwy sklep, co powoduje nieprawidłowe rejestrowanie zakupów.
Aby rozwiązać te problemy, umieściliśmy na wyświetlaczach w każdym sklepie unikalne kody QR z informacjami o lokalizacji. Umożliwiło to szybsze wprowadzanie nowych użytkowników. Użytkownicy skanują kody QR z informacjami o lokalizacji wydrukowane na materiałach marketingowych w sklepach, aby uzyskać dostęp do aplikacji internetowej Skanuj i płać.
Dzięki temu nie będą musieli wpisywać adresu internetowego mishipay.shop, aby uzyskać dostęp do usługi.
Skanowanie produktów
Podstawową funkcją aplikacji MishiPay jest skanowanie kodów kreskowych, które umożliwia użytkownikom skanowanie własnych zakupów i sprawdzanie bieżącej sumy, zanim dotrą do kasy.
Aby stworzyć możliwość skanowania w internecie, zidentyfikowaliśmy 3 podstawowe warstwy.

Strumień wideo
Za pomocą metody getUserMedia() możemy uzyskać dostęp do tylnego aparatu użytkownika z ograniczeniami wymienionymi poniżej. Wywołanie tej metody automatycznie powoduje wyświetlenie prośby o zaakceptowanie lub odrzucenie dostępu do aparatu. Gdy uzyskamy dostęp do strumienia wideo, możemy przekazać go do elementu wideo, jak pokazano poniżej:
/**
* 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 danym strumieniu wideo, musimy okresowo przechwytywać klatki i przesyłać je do warstwy dekodera. Aby przechwycić klatkę, rysujemy strumienie 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 przypadku zaawansowanych zastosowań ta warstwa wykonuje też niektóre zadania wstępnego przetwarzania, takie jak przycinanie, obracanie czy konwertowanie do skali szarości. Te zadania mogą intensywnie wykorzystywać procesor i sprawiać, że aplikacja przestanie odpowiadać, ponieważ skanowanie kodu kreskowego jest długotrwałą operacją. Za pomocą interfejsu OffscreenCanvas możemy przenieść zadanie wymagające dużej mocy obliczeniowej na wątek roboczy. Na urządzeniach obsługujących akcelerację graficzną sprzętową interfejs API WebGL i jego WebGL2RenderingContext mogą optymalizować zyski w przypadku zadań wstępnego przetwarzania wymagających dużej mocy obliczeniowej procesora.
Warstwa dekodera
Ostatnią warstwą jest warstwa dekodera, która odpowiada za dekodowanie kodów kreskowych z klatek
przechwyconych 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 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 Shape Detection API, potrzebujemy rozwiązania rezerwowego do dekodowania kodów kreskowych. Interfejs Shape Detection API udostępnia metodę getSupportedFormats(), która pomaga przełączać się między interfejsem Shape Detection API a rozwiązaniem rezerwowym.
// 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 typu open source i dla przedsiębiorstw, które można łatwo zintegrować z dowolną aplikacją internetową w celu wdrożenia skanowania. Oto niektóre biblioteki polecane przez MishiPay:
Wszystkie te biblioteki to pełnoprawne pakiety SDK, które obejmują wszystkie omówione warstwy. Udostępniają też interfejsy obsługujące różne operacje skanowania. W zależności od formatów kodów kreskowych i szybkości wykrywania wymaganych w danym przypadku biznesowym można wybrać rozwiązanie Wasm lub inne. Pomimo dodatkowych kosztów związanych z koniecznością użycia dodatkowego zasobu (Wasm) do dekodowania kodu kreskowego rozwiązania Wasm są dokładniejsze od rozwiązań bez Wasm.
Scandit był naszym pierwszym wyborem. Obsługuje wszystkie formaty kodów kreskowych wymagane w naszych przypadkach użycia biznesowego i przewyższa wszystkie dostępne biblioteki open source pod względem szybkości skanowania.
Przyszłość skanowania
Gdy interfejs Shape Detection API będzie w pełni obsługiwany przez wszystkie główne przeglądarki, możemy mieć nowy element HTML <scanner>, który będzie miał funkcje wymagane w przypadku skanera kodów kreskowych. Zespół inżynierów MishiPay uważa, że funkcja skanowania kodów kreskowych jako nowy element HTML ma solidne zastosowanie ze względu na rosnącą liczbę bibliotek open source i licencjonowanych, które umożliwiają korzystanie z funkcji takich jak Scan & Go i wielu innych.
Podsumowanie
Zmęczenie aplikacjami to problem, z którym deweloperzy spotykają się, gdy ich produkty wchodzą na rynek. Użytkownicy często chcą poznać wartość aplikacji, zanim ją pobiorą. W sklepie, w którym MishiPay oszczędza czas kupujących i poprawia ich wrażenia, czekanie na pobranie aplikacji przed jej użyciem jest sprzeczne z intuicją. W tym pomoże Ci nasza aplikacja PWA.
Dzięki wyeliminowaniu bariery wejścia zwiększyliśmy liczbę transakcji 10-krotnie i umożliwiliśmy użytkownikom zaoszczędzenie 2, 5 roku czekania w kolejce.
Podziękowania
Ten artykuł został sprawdzony przez Joe Medleya.