אפליקציית 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 (ימינה, לאט יותר).
עסקאות לפי פלטפורמה. מערכת הפעלה: 16397 (3.98%). Android: 13769 (3.34%). אינטרנט: 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 היא סריקת הברקוד, כי היא מאפשרת למשתמשים לסרוק את הרכישות שלהם ולראות את הסכום הכולל עוד לפני שהם היו מגיעים לרישום במזומן.

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

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

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

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

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

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

שכבת המפענח

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

תרשים שמוצגות בו שלוש השכבות הראשיות של ה-thread: וידאו בסטרימינג, שכבת עיבוד וממשק 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, אנחנו צריכים פתרון חלופי לפענוח הברקודים. ה-Form 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));
});

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

פתרון חלופי

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

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

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

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

עתיד הסריקה

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

סיכום

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

אישורים

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