PWA của MishiPay tăng số lượng giao dịch lên 10 lần và tiết kiệm 2,5 năm xếp hàng

Tìm hiểu cách việc chuyển sang PWA đã giúp ích cho hoạt động kinh doanh của MishiPay.

MishiPay giúp người mua sắm quét và thanh toán cho giao dịch mua sắm bằng điện thoại thông minh thay vì lãng phí thời gian xếp hàng tại quầy thanh toán. Với công nghệ Quét và thanh toán của MishiPay, người mua sắm có thể dùng điện thoại của mình để quét mã vạch trên các mặt hàng và thanh toán, sau đó rời khỏi cửa hàng. Các nghiên cứu cho thấy mỗi năm, việc xếp hàng tại cửa hàng khiến ngành bán lẻ toàn cầu tiêu tốn 200 tỷ USD.

Công nghệ của chúng tôi dựa vào các chức năng phần cứng của thiết bị (chẳng hạn như cảm biến GPS và camera) để cho phép người dùng xác định vị trí của các cửa hàng có hỗ trợ MishiPay, quét mã vạch của mặt hàng trong cửa hàng thực tế, sau đó thanh toán bằng phương thức thanh toán kỹ thuật số mà họ chọn. Các phiên bản ban đầu của công nghệ Scan & Go là các ứng dụng dành riêng cho nền tảng iOS và Android, đồng thời được những người dùng sớm sử dụng yêu thích. Hãy đọc tiếp để tìm hiểu cách việc chuyển sang PWA đã giúp tăng số lượng giao dịch lên gấp 10 lần và tiết kiệm 2,5 năm chờ đợi!

    10×

    Tăng số lượng giao dịch

    2,5 năm

    Đã lưu hàng đợi

Thách thức

Người dùng nhận thấy công nghệ của chúng tôi vô cùng hữu ích khi họ đang chờ trong hàng đợi hoặc hàng thanh toán, vì công nghệ này cho phép họ bỏ qua hàng đợi và có trải nghiệm mượt mà tại cửa hàng. Nhưng sự phiền toái khi tải ứng dụng Android hoặc iOS xuống khiến người dùng không chọn công nghệ của chúng tôi mặc dù công nghệ này có giá trị. Đây là một thách thức ngày càng lớn đối với MishiPay và chúng tôi cần tăng mức độ chấp nhận của người dùng với rào cản gia nhập thấp hơn.

Giải pháp

Nỗ lực xây dựng và ra mắt PWA đã giúp chúng tôi loại bỏ phiền toái khi cài đặt, đồng thời khuyến khích người dùng mới dùng thử công nghệ của chúng tôi trong cửa hàng thực tế, bỏ qua hàng đợi và có trải nghiệm mua sắm liền mạch. Kể từ khi ra mắt, chúng tôi nhận thấy số lượng người dùng sử dụng PWA tăng đột biến so với các ứng dụng dành riêng cho nền tảng của chúng tôi.

So sánh song song giữa việc khởi chạy trực tiếp PWA (bên trái, nhanh hơn) so với việc cài đặt và khởi chạy ứng dụng Android (bên phải, chậm hơn).
Giao dịch theo nền tảng. ¡OS: 16397 (3,98%). Android: 13769 (3,34%). Web: 382.184 (92,68%).
Đa số giao dịch diễn ra trên web.

Thảo luận chuyên sâu về kỹ thuật

Tìm cửa hàng có hỗ trợ MishiPay

Để bật tính năng này, chúng tôi dựa vào API getCurrentPosition() cùng với một giải pháp dự phòng dựa trên 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,
);

Phương pháp này hoạt động hiệu quả trong các phiên bản trước của ứng dụng, nhưng sau đó được chứng minh là một điểm bất cập lớn đối với người dùng của MishiPay vì những lý do sau:

  • Vị trí không chính xác trong các giải pháp dự phòng dựa trên IP.
  • Danh sách ngày càng tăng các cửa hàng có hỗ trợ MishiPay theo khu vực yêu cầu người dùng phải cuộn danh sách và xác định cửa hàng phù hợp.
  • Đôi khi, người dùng vô tình chọn nhầm cửa hàng, khiến giao dịch mua bị ghi lại không chính xác.

Để giải quyết những vấn đề này, chúng tôi đã nhúng mã QR định vị địa lý duy nhất vào màn hình tại cửa hàng cho mỗi cửa hàng. Điều này mở đường cho trải nghiệm tham gia nhanh hơn. Người dùng quét mã QR được định vị địa lý in trên tài liệu tiếp thị có trong cửa hàng để truy cập vào ứng dụng web Scan & Go. Như vậy, họ có thể tránh phải nhập địa chỉ trang web mishipay.shop để truy cập vào dịch vụ.

Trải nghiệm quét tại cửa hàng bằng PWA.

Quét sản phẩm

Tính năng cốt lõi trong ứng dụng MishiPay là quét mã vạch. Tính năng này cho phép người dùng quét các giao dịch mua của chính họ và xem tổng số tiền ngay cả trước khi họ đến quầy thanh toán.

Để tạo trải nghiệm quét trên web, chúng tôi đã xác định 3 lớp cốt lõi.

Sơ đồ minh hoạ 3 lớp luồng chính: luồng video, lớp xử lý và lớp giải mã.

Luồng video

Với sự trợ giúp của phương thức getUserMedia(), chúng ta có thể truy cập vào camera quan sát phía sau của người dùng với các ràng buộc được liệt kê bên dưới. Việc gọi phương thức này sẽ tự động kích hoạt lời nhắc để người dùng chấp nhận hoặc từ chối quyền truy cập vào camera của họ. Sau khi có quyền truy cập vào luồng video, chúng ta có thể chuyển tiếp luồng đó đến một phần tử video như minh hoạ dưới đây:

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

Lớp xử lý

Để phát hiện mã vạch trong một luồng video nhất định, chúng ta cần định kỳ chụp các khung hình và chuyển chúng đến lớp giải mã. Để chụp một khung hình, chúng ta vẽ các luồng từ VideoElement lên một HTMLCanvasElement bằng phương thức drawImage() của 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');
  }
}

Đối với các trường hợp sử dụng nâng cao, lớp này cũng thực hiện một số tác vụ tiền xử lý như cắt, xoay hoặc chuyển đổi sang thang độ xám. Những tác vụ này có thể tiêu tốn nhiều CPU và khiến ứng dụng không phản hồi do quá trình quét mã vạch là một thao tác diễn ra trong thời gian dài. Với sự trợ giúp của API OffscreenCanvas, chúng ta có thể chuyển nhiệm vụ sử dụng nhiều CPU sang một web worker. Trên các thiết bị hỗ trợ tính năng tăng tốc đồ hoạ bằng phần cứng, API WebGL và WebGL2RenderingContext của API này có thể tối ưu hoá mức tăng trên các tác vụ tiền xử lý sử dụng nhiều CPU.

Lớp giải mã

Lớp cuối cùng là lớp giải mã, chịu trách nhiệm giải mã mã vạch từ các khung hình do lớp xử lý chụp. Nhờ Shape Detection API (hiện chưa có trên tất cả các trình duyệt), chính trình duyệt sẽ giải mã mã vạch từ một ImageBitmapSource, có thể là một phần tử img, một phần tử SVG image, một phần tử video, một phần tử canvas, một đối tượng Blob, một đối tượng ImageData hoặc một đối tượng ImageBitmap.

Sơ đồ cho thấy 3 lớp luồng chính: luồng video, lớp xử lý và API Phát hiện hình dạng.

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

Đối với những thiết bị chưa hỗ trợ Shape Detection API, chúng ta cần một giải pháp dự phòng để giải mã mã vạch. Shape Detection API cung cấp một phương thức getSupportedFormats() giúp chuyển đổi giữa Shape Detection API và giải pháp dự phòng.

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

Sơ đồ quy trình cho thấy cách sử dụng Shape Detection API hoặc giải pháp dự phòng, tuỳ thuộc vào khả năng hỗ trợ của Barcode Detector và các định dạng mã vạch được hỗ trợ.

Giải pháp dự phòng

Có một số thư viện quét mã nguồn mở và doanh nghiệp mà bạn có thể dễ dàng tích hợp với mọi ứng dụng web để triển khai tính năng quét. Sau đây là một số thư viện mà MishiPay đề xuất.

Tên thư viện Loại Giải pháp Wasm Định dạng mã vạch
QuaggaJs Nguồn mở Không 1N
ZxingJs Nguồn mở Không 1D và 2D (Bị hạn chế)
CodeCorp Doanh nghiệp 1D và 2D
Scandit Doanh nghiệp 1D và 2D
So sánh các thư viện quét mã vạch nguồn mở và thương mại

Tất cả các thư viện này đều là SDK đầy đủ, bao gồm tất cả các lớp đã thảo luận. Chúng cũng hiển thị các giao diện để hỗ trợ nhiều thao tác quét. Tuỳ thuộc vào định dạng mã vạch và tốc độ phát hiện cần thiết cho trường hợp kinh doanh, bạn có thể đưa ra quyết định giữa giải pháp Wasm và giải pháp không phải Wasm. Mặc dù có chi phí phát sinh khi yêu cầu thêm một tài nguyên (Wasm) để giải mã mã vạch, nhưng các giải pháp Wasm vẫn hoạt động hiệu quả hơn giải pháp không phải Wasm về độ chính xác.

Scandit là lựa chọn chính của chúng tôi. Thư viện này hỗ trợ tất cả các định dạng mã vạch cần thiết cho các trường hợp sử dụng trong hoạt động kinh doanh của chúng tôi; thư viện này có tốc độ quét nhanh hơn tất cả các thư viện nguồn mở hiện có.

Tương lai của hoạt động quét

Sau khi tất cả các trình duyệt chính hỗ trợ đầy đủ Shape Detection API, chúng ta có thể có một phần tử HTML mới <scanner> có các chức năng cần thiết cho một trình đọc mã vạch. Nhóm kỹ thuật tại MishiPay tin rằng chức năng quét mã vạch là một trường hợp sử dụng vững chắc cho một phần tử HTML mới do số lượng thư viện nguồn mở và được cấp phép ngày càng tăng, cho phép các trải nghiệm như Quét và đi và nhiều trải nghiệm khác.

Kết luận

Mệt mỏi với ứng dụng là một vấn đề mà nhà phát triển gặp phải khi sản phẩm của họ xuất hiện trên thị trường. Người dùng thường muốn hiểu rõ giá trị mà một ứng dụng mang lại cho họ trước khi tải ứng dụng đó xuống. Trong một cửa hàng, nơi MishiPay giúp người mua sắm tiết kiệm thời gian và cải thiện trải nghiệm của họ, việc chờ đợi tải xuống trước khi họ có thể sử dụng một ứng dụng là điều không hợp lý. Đây là lúc PWA của chúng tôi phát huy tác dụng.

Bằng cách loại bỏ rào cản gia nhập, chúng tôi đã tăng số lượng giao dịch lên gấp 10 lần và giúp người dùng tiết kiệm được 2,5 năm chờ đợi trong hàng đợi.

Lời cảm ơn

Bài viết này được Joe Medley xem xét.