Tìm hiểu việc chuyển sang PWA đã giúp ích như thế nào 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 bằng điện thoại thông minh, thay vì mất thời gian xếp hàng thanh toán. Với công nghệ Quét và đi của MishiPay, người mua sắm có thể sử dụng điện thoại của riêng mình để quét mã vạch trên các mặt hàng và thanh toán, sau đó chỉ cần rời khỏi cửa hàng. Các nghiên cứu cho thấy việc xếp hàng tại cửa hàng khiến ngành bán lẻ trên toàn cầu mất khoảng 200 tỷ đô la mỗi năm.
Công nghệ của chúng tôi dựa vào các tính năng phần cứng của thiết bị như cảm biến GPS và máy ảnh, cho phép người dùng xác định vị trí của các cửa hàng hỗ trợ MishiPay, quét mã vạch 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ệ Quét và thanh toán là các ứng dụng iOS và Android dành riêng cho nền tảng. Những người dùng sớm đã rất yêu thích công nghệ này. Hãy đọc tiếp để tìm hiểu cách chuyển sang PWA đã giúp tăng số giao dịch lên gấp 10 lần và tiết kiệm 2,5 năm xếp hàng!
10×
Tăng số lượt giao dịch
2,5 năm
Đã lưu hàng đợi
Thách thức
Người dùng thấy công nghệ của chúng tôi cực kỳ hữu ích khi chờ đợi hoặc 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. Tuy nhiên, sự phiền hà 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 độ sử dụng của người dùng với rào cản gia nhập thấp hơn.
Giải pháp
Nhờ nỗ lực xây dựng và ra mắt PWA, chúng tôi đã loại bỏ được sự phiền hà khi cài đặt và khuyến khích người dùng mới dùng thử công nghệ của chúng tôi tại 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 mạnh so với các ứng dụng dành riêng cho nền tảng.
Tìm hiểu chuyên sâu về kỹ thuật
Tìm các 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 tốt 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 gây phiền toái lớn cho người dùng MishiPay vì những lý do sau:
- Thông tin vị trí không chính xác trong các giải pháp dự phòng dựa trên địa chỉ IP.
- Danh sách ngày càng tăng của các cửa hàng hỗ trợ MishiPay theo khu vực yêu cầu người dùng cuộn danh sách và xác định đúng cửa hàng.
- Đôi khi, người dùng vô tình chọn sai 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 các mã QR có vị trí địa lý riêng biệt trên màn hình tại cửa hàng cho từng cửa hàng. Điều này đã mở đường cho trải nghiệm làm quen nhanh hơn. Người dùng chỉ cần quét các mã QR được định vị địa lý được 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 Quét và Chuyển.
Bằng cách này, họ có thể tránh nhập địa chỉ web mishipay.shop
để truy cập vào dịch vụ.
Quét sản phẩm
Một tính năng cốt lõi trong ứng dụng MishiPay là quét mã vạch, vì tính năng này cho phép người dùng quét mã vạch đã mua và xem tổng số tiền đang diễn ra ngay cả trước khi họ đến được máy tính tiền.
Để xây dựng trải nghiệm quét trên web, chúng tôi đã xác định 3 lớp cốt lõi.
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 sau của người dùng thông qua các quy tắ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 máy ảnh 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 chụp định kỳ các khung hình và chuyển các khung hình đó đến lớp bộ giải mã. Để chụp một khung hình, chúng ta chỉ cần vẽ các luồng từ VideoElement
lên 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ố thao tác xử lý trước như cắt, xoay hoặc chuyển đổi sang thang màu xám. Các tác vụ này có thể tốn nhiều CPU và khiến ứng dụng không phản hồi vì quét mã vạch là một hoạt động diễn ra trong thời gian dài. Với sự trợ giúp của API OffscreenCanvas, chúng ta có thể giảm tải tác vụ nặng về CPU cho một worker web. Trên các thiết bị hỗ trợ tính năng tăng tốc đồ hoạ phần cứng, API WebGL và WebGL2RenderingContext
của API này có thể tối ưu hoá lợi ích trên các tác vụ xử lý trước chuyên sâu về CPU.
Lớp bộ giải mã
Lớp cuối cùng là lớp bộ giải mã chịu trách nhiệm giải mã mã vạch từ các khung mà lớp xử lý thu thập. Nhờ API phát hiện hình dạng (chưa có trên tất cả trình duyệt), chính trình duyệt sẽ giải mã mã vạch từ ImageBitmapSource
. Đây có thể là phần tử img
, phần tử image
SVG, phần tử video
, phần tử canvas
, đối tượng Blob
, đối tượng ImageData
hoặc đối tượng 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;
}
}
Đối với các thiết bị chưa hỗ trợ API Phát hiện hình dạng, chúng ta cần có một giải pháp dự phòng để giải mã mã vạch. API Phát hiện hình dạng hiển thị một phương thức getSupportedFormats()
giúp chuyển đổi giữa API Phát hiện hình dạng 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));
});
Giải pháp dự phòng
Có một số thư viện quét nguồn mở và dành cho doanh nghiệp 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ất cả thư viện trên đều là SDK đầy đủ, bao gồm tất cả các lớp đã thảo luận ở trên. Các thư viện này cũng cho thấy các giao diện hỗ trợ nhiều hoạt động 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, quyết định giữa Wasm và các giải pháp không phải là Wasm. Mặc dù có thêm chi phí khi yêu cầu tài nguyên bổ sung (Wasm) để giải mã mã vạch, nhưng các giải pháp Wasm lại 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. Trình bổ trợ này hỗ trợ mọi định dạng mã vạch cần thiết cho các trường hợp sử dụng của doanh nghiệp. Tốc độ quét này vượt trội hơn mọi thư viện nguồn mở hiện có.
Tương lai của tính năng quét
Một khi API Phát hiện hình dạng được tất cả các trình duyệt chính hỗ trợ đầy đủ, có thể chúng tôi sẽ có một phần tử HTML mới <scanner>
có các tính năng cần thiết cho trình quét mã vạch. Nhóm kỹ sư tại MishiPay tin rằng có một trường hợp sử dụng chắc chắn cho chức năng quét mã vạch để trở thành 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
Sự mệt mỏi về ứng dụng là vấn đề mà nhà phát triển gặp phải khi sản phẩm của họ ra mắt thị trường. Người dùng thường muốn nắm được giá trị mà ứ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ờ tải xuống trước khi có thể sử dụng ứng dụng là điều không hợp lý. Đây là nơi PWA hỗ trợ. Bằng cách loại bỏ rào cản tham gia, chúng tôi đã tăng số giao dịch lên gấp 10 lần và giúp người dùng tiết kiệm 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.