تطبيق PWA الخاص بشركة MishiPay يزيد من المعاملات 10 مرات ويتيح إضافة الفيديوهات إلى "قائمة المحتوى التالي" لمدة سنتين ونصف

تعرَّف على كيف ساعد التحوّل إلى تطبيق ويب تقدّمي في تطوير أعمال MishiPay.

تتيح MishiPay للمتسوّقين مسح المنتجات ضوئيًا ودفع ثمنها باستخدام هواتفهم الذكية، بدلاً من إضاعة الوقت في الانتظار في طوابير الدفع. باستخدام تكنولوجيا المسح الضوئي والدفع من MishiPay، يمكن للمتسوّقين استخدام هواتفهم لمسح الرمز الشريطي على السلع ضوئيًا ودفع ثمنها، ثم مغادرة المتجر. تشير الدراسات إلى أنّ الانتظار في الطوابير داخل المتاجر يكلّف قطاع البيع بالتجزئة العالمي 200 مليار دولار أمريكي سنويًا.

تعتمد تقنيتنا على إمكانات أجهزة المستخدمين، مثل أجهزة استشعار نظام تحديد المواقع العالمي (GPS) والكاميرات التي تتيح للمستخدمين تحديد مواقع المتاجر التي تتيح استخدام MishiPay، ومسح الرموز الشريطية للمنتجات داخل المتجر، ثم الدفع باستخدام طريقة الدفع الرقمية التي يختارونها. كانت الإصدارات الأولية من تكنولوجيا "الدفع السريع" عبارة عن تطبيقات خاصة بمنصتَي iOS وAndroid، وقد نالت إعجاب المستخدمين الأوائل. يمكنك الاطّلاع على التفاصيل أدناه لمعرفة كيف أدّى الانتقال إلى تطبيق ويب تقدّمي إلى زيادة عدد المعاملات بمقدار 10 مرات وتوفير وقت الانتظار الذي كان سيستغرق 2.5 سنة.

    10×

    زيادة عدد المعاملات

    عامان ونصف

    تم حفظ قائمة الانتظار

التحدي

يجد المستخدمون أنّ التكنولوجيا التي نقدّمها مفيدة للغاية أثناء الانتظار في طابور أو صف الدفع، لأنّها تتيح لهم تخطّي الطابور والاستمتاع بتجربة سلسة داخل المتجر. ومع ذلك، كان عناء تنزيل تطبيق Android أو iOS يدفع المستخدمين إلى عدم اختيار التكنولوجيا التي نقدّمها على الرغم من قيمتها. كان ذلك تحديًا متزايدًا بالنسبة إلى MishiPay، وكان علينا زيادة معدّل استخدام التطبيق مع تسهيل عملية التسجيل.

الحل

وقد ساعدتنا جهودنا في إنشاء تطبيق الويب التقدّمي وإطلاقه على إزالة متاعب التثبيت، كما شجّعنا المستخدمين الجدد على تجربة تقنيتنا داخل متجر فعلي، وتخطّي قائمة الانتظار، والاستمتاع بتجربة تسوّق سلسة. منذ إطلاق التطبيق، لاحظنا ارتفاعًا كبيرًا في عدد المستخدمين الذين يفضّلون استخدام تطبيق الويب التقدّمي مقارنةً بالتطبيقات الخاصة بمنصات معيّنة.

مقارنة جنبًا إلى جنب بين تشغيل تطبيق الويب التقدّمي (PWA) مباشرةً (على اليمين، أسرع) وتثبيت تطبيق Android وتشغيله (على اليسار، أبطأ)
المعاملات حسب المنصة ‫¡OS: 16397 (3.98%). ‫Android: ‏13769 (3.34%). الويب: 382184 (‫92.68%).
تتمّ معظم المعاملات على الويب.

التفاصيل الفنية

تحديد موقع المتاجر التي تتيح استخدام MishiPay

لتفعيل هذه الميزة، نعتمد على getCurrentPosition() API بالإضافة إلى حل احتياطي يستند إلى عنوان 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 في كل منطقة أن يتصفّح المستخدمون قائمة ويحدّدوا المتجر الصحيح.
  • يختار المستخدمون أحيانًا المتجر الخطأ عن طريق الخطأ، ما يؤدي إلى تسجيل عمليات الشراء بشكل غير صحيح.

ولحلّ هذه المشاكل، تضمّنت شاشات العرض داخل المتاجر رموز استجابة سريعة فريدة ومحدّدة جغرافيًا لكل متجر. وقد مهّد ذلك الطريق لتوفير تجربة إعداد أسرع. يمسح المستخدمون رموز الاستجابة السريعة المحدّدة جغرافيًا والمطبوعة على المواد التسويقية المتوفرة في المتاجر للوصول إلى تطبيق الويب "امسح وانطلق". بهذه الطريقة، يمكنهم تجنُّب كتابة عنوان الويب mishipay.shop للوصول إلى الخدمة.

تجربة المسح الضوئي داخل المتجر باستخدام تطبيق الويب التقدّمي

مسح المنتجات ضوئيًا

تتمثّل إحدى الميزات الأساسية في تطبيق MishiPay في إمكانية مسح الرمز الشريطي، ما يتيح للمستخدمين مسح عمليات الشراء بأنفسهم والاطّلاع على الإجمالي الجاري حتى قبل الوصول إلى صندوق الدفع.

لتوفير تجربة مسح ضوئي على الويب، حدّدنا ثلاث طبقات أساسية.

مخطّط بياني يعرض طبقات سلسلة المحادثات الرئيسية الثلاث: بث الفيديو وطبقة المعالجة وطبقة فك الترميز

فيديو مضمّن

باستخدام طريقة 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) وتؤدي إلى عدم استجابة التطبيق لأنّ عملية مسح الرمز الشريطي هي عملية طويلة الأمد. باستخدام واجهة برمجة التطبيقات OffscreenCanvas، يمكننا نقل المهمة التي تتطلّب استخدامًا مكثّفًا لوحدة المعالجة المركزية إلى عامل ويب. على الأجهزة التي تتوافق مع تسريع رسومات الأجهزة، يمكن لواجهة برمجة التطبيقات WebGL وWebGL2RenderingContext تحسين المكاسب في مهام المعالجة المسبقة التي تتطلّب استخدامًا مكثفًا لوحدة المعالجة المركزية.

طبقة فك الترميز

الطبقة الأخيرة هي طبقة فك الترميز المسؤولة عن فك ترميز الرموز الشريطية من اللقطات التي تم التقاطها بواسطة طبقة المعالجة. بفضل Shape Detection API (الذي لم يتوفّر بعد على جميع المتصفحات)، يفك المتصفح نفسه ترميز الرمز الشريطي من ImageBitmapSource، والذي يمكن أن يكون عنصر img أو عنصر SVG image أو عنصر video أو عنصر canvas أو كائن Blob أو كائن ImageData أو كائن ImageBitmap.

مخطّط بياني يعرض طبقات سلسلة التعليمات الرئيسية الثلاث: بث الفيديو وطبقة المعالجة و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));
});

مخطّط انسيابي يوضّح كيفية استخدام واجهة برمجة التطبيقات Shape Detection API أو الحلّ الاحتياطي، وذلك حسب توفّر ميزة "أداة رصد الرموز الشريطية" وتنسيقات الرموز الشريطية المتوافقة.

الحلّ الاحتياطي

تتوفّر العديد من مكتبات المسح الضوئي المفتوحة المصدر والمخصّصة للمؤسسات، ويمكن دمجها بسهولة مع أي تطبيق ويب لتنفيذ عملية المسح الضوئي. في ما يلي بعض المكتبات التي تنصح بها MishiPay.

اسم المكتبة النوع Wasm Solution تنسيقات الرموز الشريطية
QuaggaJs برنامج مفتوح المصدر لا يوم واحد
ZxingJs برنامج مفتوح المصدر لا 1D & 2D (Limited)
CodeCorp للمؤسسات نعم 1D & 2D
Scandit للمؤسسات نعم 1D & 2D
مقارنة بين مكتبات مسح الرموز الشريطية التجارية والمفتوحة المصدر

جميع هذه المكتبات هي حِزم تطوير برامج (SDK) متكاملة تتألف من جميع الطبقات التي تمت مناقشتها. وتوفّر أيضًا واجهات لدعم عمليات المسح الضوئي المختلفة. بناءً على تنسيقات الرموز الشريطية وسرعة الرصد المطلوبة لحالة الاستخدام، يمكن الاختيار بين حلول Wasm وغير Wasm. على الرغم من التكلفة الإضافية التي تتطلّبها إضافة مورد آخر (Wasm) لفك ترميز الرمز الشريطي، تتفوّق حلول Wasm على الحلول غير المستندة إلى Wasm من حيث الدقة.

كانت Scandit خيارنا الأساسي. يتوافق مع جميع تنسيقات الرموز الشريطية المطلوبة لحالات الاستخدام في نشاطنا التجاري، ويتفوّق على جميع مكتبات المصادر المفتوحة المتاحة من حيث سرعة المسح الضوئي.

مستقبل المسح الضوئي

بعد أن تصبح واجهة برمجة التطبيقات Shape Detection API متوافقة تمامًا مع جميع المتصفحات الرئيسية، قد يتوفّر عنصر HTML جديد <scanner> يتضمّن الإمكانات المطلوبة لماسح الرموز الشريطية. يرى فريق الهندسة في MishiPay أنّ هناك حالة استخدام قوية لوظيفة مسح الرموز الشريطية لتكون عنصر HTML جديدًا، وذلك بسبب العدد المتزايد من المكتبات المفتوحة المصدر والمرخّصة التي تتيح تجارب مثل "المسح الضوئي والدفع" وغيرها الكثير.

الخاتمة

تُعدّ حالة الملل من التطبيقات مشكلة يواجهها المطوّرون عند طرح منتجاتهم في السوق. يريد المستخدمون غالبًا معرفة قيمة التطبيق قبل تنزيله. في المتاجر، حيث يوفّر تطبيق MishiPay وقت المتسوّقين ويحسّن تجربتهم، من غير المنطقي أن ينتظروا اكتمال التنزيل قبل أن يتمكّنوا من استخدام التطبيق. وهنا يأتي دور تطبيق الويب التقدّمي.

من خلال إزالة عائق الدخول، تمكّنا من زيادة عدد معاملاتنا بمقدار 10 أضعاف، كما أتحنا للمستخدمين توفير وقت الانتظار في قائمة الانتظار لمدة عامين ونصف.

الإقرارات

راجع هذه المقالة جو ميدلي.