אפליקציית MishiPay' מגדילה את מספר העסקאות פי 10 וחוסכת 2.5 שנים של המתנה בתור

איך המעבר לאפליקציית PWA עזר לעסק של MishiPay?

MishiPay מאפשרת לקונים לסרוק את הפריטים ולשלם עליהם באמצעות הסמארטפונים שלהם, במקום לבזבז זמן בתור בקופה. בעזרת הטכנולוגיה של MishiPay לסריקה ויציאה, הקונים יכולים להשתמש בטלפון שלהם כדי לסרוק את הברקוד של הפריטים ולשלם עליהם, ואז פשוט לצאת מהחנות. מחקרים מראים שהמתנה בתור בחנות פיזית עולה לענף הקמעונאות העולמי כ-200 מיליארד דולר בשנה.

הטכנולוגיה שלנו מתבססת על יכולות החומרה של המכשיר, כמו חיישני GPS ומצלמות, שמאפשרות למשתמשים לאתר חנויות שתומכות ב-MishiPay, לסרוק את הקודים הביומטריים של הפריטים בחנות הפיזית ואז לשלם באמצעות אמצעי התשלום הדיגיטלי שבחרתם. הגרסאות הראשונות של הטכנולוגיה שלנו ל'סריקה ורכישה' היו אפליקציות ספציפיות לפלטפורמות iOS ו-Android, והמשתמשים הראשונים אהבו את הטכנולוגיה. בהמשך מוסבר איך המעבר לאפליקציה לנייד מבוססת-דפדפן הגדיל את מספר העסקאות פי 10 וחיסך 2.5 שנים של המתנה בתור.

    10×

    יותר עסקאות

    שנתיים וחצי

    שמירת הבקשה בתור

האתגר

המשתמשים מוצאים שהטכנולוגיה שלנו מועילה מאוד כשהם ממתינים בתור או בתור לקופה, כי היא מאפשרת להם לדלג על התור וליהנות מחוויית קנייה חלקה בחנות. אבל הטרחה של הורדת אפליקציה ל-Android או ל-iOS גרמה למשתמשים לא לבחור בטכנולוגיה שלנו, למרות הערך שהיא מספקת. זה היה אתגר הולך וגדל עבור MishiPay, והיינו צריכים להגדיל את השימוש בשירות על ידי הפחתת מחסום הכניסה.

פתרון

המאמצים שלנו לפתח ולהשיק את אפליקציית ה-PWA עזרו לנו להסיר את הטרחה של ההתקנה, ועודדו משתמשים חדשים לנסות את הטכנולוגיה שלנו בחנות פיזית, לדלג על התור וליהנות מחוויית קנייה חלקה. מאז ההשקה, ראינו עלייה משמעותית בשימוש של המשתמשים באפליקציית ה-PWA שלנו בהשוואה לאפליקציות הספציפיות לפלטפורמות.

השוואה בין הפעלה ישירה של אפליקציית ה-PWA (בצד ימין, מהירה יותר) לבין התקנה והפעלה של אפליקציית Android (בצד ימין, איטית יותר).
עסקאות לפי פלטפורמה. ¡OS: ‏ 16,397 (3.98%). Android: ‏ 13,769 (3.34%). אינטרנט: 382,184 (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 הממוקמים גיאוגרפית שמודפסים על חומרים שיווקיים בחנויות. כך הם יוכלו להימנע מהקלדה של כתובת האינטרנט mishipay.shop כדי לגשת לשירות.

חוויית הסריקה בחנות באמצעות אפליקציית ה-PWA.

סריקה של מוצרים

תכונה מרכזית באפליקציית MishiPay היא סריקה של ברקודים, כי היא מאפשרת למשתמשים לסרוק את הרכישות שלהם ולראות את הסכום הכולל עוד לפני שהם מגיעים לקופה.

כדי ליצור חוויית סריקה באינטרנט, זיהינו שלוש שכבות ליבה.

תרשים שבו מוצגות שלוש השכבות הראשיות של השרשור: וידאו סטרימינג, שכבת עיבוד ושכבת מפענח.

וידאו בסטרימינג

בעזרת השיטה getUserMedia(), אנחנו יכולים לגשת למצלמת הנסיעה לאחור של המשתמש בכפוף למגבלות שמפורטות בהמשך. קריאה ל-method מפעילה באופן אוטומטי הודעה למשתמשים לאשר או לדחות את הגישה למצלמה שלהם. אחרי שנקבל גישה לסטרימינג של הסרטון, נוכל להעביר אותו לרכיב וידאו, כפי שמוצג בהמשך:

/**
 * 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() של 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');
  }
}

בתרחישי שימוש מתקדמים, השכבה הזו מבצעת גם כמה משימות של עיבוד מקדים, כמו חיתוך, כיוון או המרה לגווני אפור. המשימות האלה יכולות להיות עתירות מעבד, וכתוצאה מכך האפליקציה לא תגיב, כי סריקת ברקודים היא פעולה ממושכת. בעזרת ה-API של OffscreenCanvas, אנחנו יכולים להעביר את המשימה שמשתמשת ב-CPU באופן אינטנסיבי ל-web worker. במכשירים שתומכים בהאצת גרפיקה בחומרה, אפשר להשתמש ב-WebGL API וב-WebGL2RenderingContext כדי לבצע אופטימיזציה של היתרון במשימות העיבוד המקדימות שמתבצעות במעבד.

שכבת המפענח

השכבה האחרונה היא שכבת המפענח, שאחראית לפענוח ברקודים מהפריימים ששכבת העיבוד תיעדה. בעזרת Shape Detection API (שעדיין לא זמין בכל הדפדפנים), הדפדפן עצמו מפענח את הברקוד מ-ImageBitmapSource, שיכול להיות אלמנט img, אלמנט SVG image, אלמנט video, אלמנט canvas, אובייקט Blob, אובייקט ImageData או אובייקט ImageBitmap.

תרשים שבו מוצגות שלוש השכבות הראשיות של ה-thread: סטרימינג של וידאו, שכבת עיבוד ו-Shape Detection 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;
  }
}

במכשירים שעדיין לא תומכים ב-Shape Detection API, אנחנו זקוקים לפתרון חלופי לפענוח הברקודים. ב-Shape Detection API מוצגת השיטה getSupportedFormats() שעוזרת לעבור בין Shape Detection API לפתרון החלופי.

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

תרשים תהליך שבו מוצג איך, בהתאם לתמיכה ב-Barcode Detector ולפורמטים הנתמכים של ברקודים, נעשה שימוש ב-Shape Detection API או בפתרון החלופי.

פתרון חלופי

יש כמה ספריות סריקה בקוד פתוח ובארגונים שאפשר לשלב בקלות עם כל אפליקציית אינטרנט כדי להטמיע סריקה. ריכזנו כאן כמה מהספריות שמומלצות על ידי MishiPay.

שם הספרייה סוג פתרון Wasm פורמטים של ברקודים
QuaggaJs קוד פתוח לא יום
ZxingJs קוד פתוח לא 1D ו-2D (מוגבלת)
CodeCorp ארגונים כן 1D ו-2D
Scandit ארגונים כן 1D ו-2D
השוואה בין ספריות קוד פתוח לספריות מסחריות לסריקה של ברקודים

כל הספריות שלמעלה הן ערכות SDK מלאות שמכילות את כל השכבות שצוינו למעלה. הם גם חושפים ממשקים שתומכים בפעולות סריקה שונות. בהתאם לפורמטים של הקודים והמהירות הנדרשת לזיהוי לצורך הניתוח העסקי, אפשר לבחור בין פתרונות Wasm לבין פתרונות שאינם Wasm. למרות העלויות הנלוות שנובעות מהצורך במשאב נוסף (Wasm) כדי לפענח את הברקוד, פתרונות Wasm עדיפים על פתרונות ללא Wasm מבחינת הדיוק.

Scandit הייתה הבחירה הראשית שלנו. היא תומכת בכל הפורמטים של קודי מ barras הנדרשים לתרחישי השימוש העסקיים שלנו, והיא מהירה יותר מכל הספריות הזמינות בקוד פתוח.

העתיד של הסריקה

אחרי ש-Shape Detection API יקבל תמיכה מלאה בכל הדפדפנים העיקריים, יכול להיות שיהיה לנו רכיב HTML חדש <scanner> עם היכולות הנדרשות לסורק ברקודים. מהנדסי MishiPay סבורים שיש תרחיש לדוגמה שבו הפונקציונליות של סריקת ברקודים יכולה להיות רכיב HTML חדש, בגלל מספר ההולך וגדל של ספריות קוד פתוח ורישיונות שמאפשרות חוויות כמו 'סריקה ורכישה' ועוד רבות.

סיכום

מפתחים נתקלים בבעיה של 'תשישות מאפליקציות' כשהמוצרים שלהם נכנסים לשוק. לרוב, משתמשים רוצים להבין מה הערך שהאפליקציה מספקת להם לפני שהם מורידים אותה. בחנות, שבה MishiPay חוסך לקונים זמן ומשפר את חוויית הקנייה שלהם, לא הגיוני לחכות להורדה לפני שהם יכולים להשתמש באפליקציה. כאן נכנסת לתמונה אפליקציית ה-PWA שלנו. בעקבות הסרת מחסום הכניסה, הגדילנו את מספר העסקאות פי 10 והמשתמשים שלנו חוסכים 2.5 שנים של המתנה בתור.

תודות

המאמר הזה נבדק על ידי Joe Medley.