Tìm hiểu cách 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 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 đã 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 trong hàng đợ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 suôn sẻ 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 đã bật MishiPay
Để bật tính năng này, chúng ta dựa vào API getCurrentPosition()
cùng với 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 mã QR được định vị theo vị trí đị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 Quét và thanh toá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à tính năng quét mã vạch, vì tính năng này cho phép người dùng quét các giao dịch mua của riêng họ và xem tổng số tiền đang chạy ngay cả trước khi họ đến quầy thu ngâ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 lùi của người dùng với 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 khung hình định kỳ và chuyển các khung hình đó sang lớp 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ố tác vụ 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ể tiêu tốn nhiều CPU và khiến ứng dụng không phản hồi do việc quét mã vạch là một thao tác chạy 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 giải mã, chịu trách nhiệm giải mã mã vạch từ các khung được lớp xử lý chụp lại. 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 lớp này cũng hiển thị 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 các giải pháp Wasm và không phải 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. 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 kinh doanh của chúng tôi; thư viện này vượt trội hơn tất cả các thư viện nguồn mở hiện có về tốc độ quét.
Tương lai của tính năng quét
Khi tất cả trình duyệt chính đều hỗ trợ đầy đủ API Phát hiện hình dạng, 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áy 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 hiểu được 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ờ tải ứng dụng xuống trước khi có thể sử dụng là điều không hợp lý. Đây là lúc PWA phát huy tác dụng. 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.