ดูว่าการเปลี่ยนไปใช้ PWA ส่งผลต่อธุรกิจของ MishiPay อย่างไร
MishiPay ช่วยให้ผู้เลือกซื้อสแกนและชำระเงินสำหรับการช็อปปิ้งด้วยสมาร์ทโฟนได้โดยไม่ต้องเสียเวลาต่อคิวที่จุดชำระเงิน เทคโนโลยี Scan & Go ของ MishiPay ช่วยให้ผู้เลือกซื้อสามารถใช้โทรศัพท์ของตนเองเพื่อสแกนบาร์โค้ดของสินค้าและชำระเงิน จากนั้นออกจากร้านค้าได้ การศึกษาพบว่าการต่อคิวที่ร้านค้าทำให้ภาคค้าปลีกทั่วโลกสูญเสียรายได้ประมาณ 6.6 ล้านล้านบาทต่อปี
เทคโนโลยีของเราอาศัยความสามารถของฮาร์ดแวร์อุปกรณ์ เช่น เซ็นเซอร์ GPS และกล้อง ซึ่งช่วยให้ผู้ใช้ค้นหาร้านค้าที่เปิดใช้ MishiPay, สแกนบาร์โค้ดสินค้าภายในร้านค้าจริง แล้วชำระเงินโดยใช้วิธีการชำระเงินดิจิทัลที่ตนเลือก เทคโนโลยีสแกนแล้วจ่ายเวอร์ชันแรกๆ ของเราเป็นแอปพลิเคชัน iOS และ Android สำหรับแพลตฟอร์มโดยเฉพาะ และผู้ใช้กลุ่มแรกๆ ชื่นชอบเทคโนโลยีนี้ อ่านต่อเพื่อดูว่าการเปลี่ยนไปใช้ PWA ช่วยเพิ่มธุรกรรมได้ 10 เท่าและประหยัดเวลารอคิวได้ 2.5 ปี
10×
ธุรกรรมที่เพิ่มขึ้น
2.5 ปี
บันทึกการจัดคิวแล้ว
ความท้าทาย
ผู้ใช้พบว่าเทคโนโลยีของเรามีประโยชน์อย่างยิ่งเมื่อต้องรอคิวหรือต่อแถวชำระเงิน เนื่องจากช่วยให้ผู้ใช้ข้ามคิวและได้รับประสบการณ์ที่ราบรื่นในร้านค้า แต่ความยุ่งยากในการดาวน์โหลดแอปพลิเคชัน Android หรือ iOS ทำให้ผู้ใช้ไม่เลือกเทคโนโลยีของเรา แม้ว่าจะมีคุณค่าก็ตาม ปัญหานี้ทวีความรุนแรงขึ้นเรื่อยๆ สําหรับ MishiPay และเราจําเป็นต้องเพิ่มการใช้งานของผู้ใช้ด้วยอุปสรรคในการเข้าร่วมที่ต่ำลง
โซลูชัน
ความพยายามของเราในการสร้างและเปิดตัว PWA ช่วยให้เราขจัดความยุ่งยากในการติดตั้งและส่งเสริมให้ผู้ใช้ใหม่ลองใช้เทคโนโลยีของเราในกิจการที่มีหน้าร้านจริง โดยไม่ต้องต่อคิว และได้รับประสบการณ์การช็อปปิ้งที่ราบรื่น ตั้งแต่เปิดตัว เราพบว่าผู้ใช้มีการใช้งาน PWA เพิ่มขึ้นอย่างมากเมื่อเทียบกับแอปพลิเคชันเฉพาะแพลตฟอร์ม
เจาะลึกทางเทคนิค
ค้นหาร้านค้าที่เปิดใช้ 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 คือการสแกนบาร์โค้ดเนื่องจากช่วยให้ผู้ใช้ของเราสามารถสแกนการซื้อของตนเองและดูยอดรวมทั้งหมดก่อนที่จะไปถึงเครื่องเก็บเงินได้
เราได้ระบุเลเยอร์หลัก 3 เลเยอร์เพื่อสร้างประสบการณ์การสแกนบนเว็บ
สตรีมวิดีโอ
การใช้เมธอด 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 API ช่วยให้เราส่งงานที่ใช้ CPU มากไปยัง Web Worker ได้ ในอุปกรณ์ที่รองรับการเร่งกราฟิกด้วยฮาร์ดแวร์ นั้น WebGL API และ WebGL2RenderingContext
สามารถเพิ่มประสิทธิภาพให้กับงานการประมวลผลล่วงหน้าที่ใช้ CPU มากได้
เลเยอร์ตัวถอดรหัส
ชั้นสุดท้ายคือชั้นตัวถอดรหัส ซึ่งมีหน้าที่ถอดรหัสบาร์โค้ดจากเฟรมที่ชั้นการประมวลผลจับภาพไว้ เบราว์เซอร์จะถอดรหัสบาร์โค้ดจาก ImageBitmapSource
ได้ด้วย Shape Detection API (ซึ่งยังไม่พร้อมใช้งานในบางเบราว์เซอร์) ซึ่งอาจเป็นองค์ประกอบ img
, องค์ประกอบ SVG image
, องค์ประกอบ video
, องค์ประกอบ canvas
, ออบเจ็กต์ Blob
, ออบเจ็กต์ ImageData
หรือออบเจ็กต์ 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;
}
}
สำหรับอุปกรณ์ที่ยังไม่รองรับ 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));
});
โซลูชันสำรอง
มีไลบรารีการสแกนแบบโอเพนซอร์สและระดับองค์กรหลายรายการรวมอยู่ด้วย ซึ่งผสานรวมกับเว็บแอปพลิเคชันเพื่อใช้การสแกนได้ง่ายๆ ตัวอย่างห้องสมุดที่ MishiPay แนะนำมีดังนี้
ไลบรารีทั้งหมดข้างต้นเป็น SDK ที่สมบูรณ์ ซึ่งประกอบด้วยเลเยอร์ทั้งหมดที่พูดถึงข้างต้น และยังแสดงอินเทอร์เฟซเพื่อรองรับการดำเนินการสแกนต่างๆ ด้วย การตัดสินใจอาจใช้โซลูชัน Wasm หรือโซลูชันที่ไม่ใช่ Wasm ทั้งนี้ขึ้นอยู่กับรูปแบบบาร์โค้ดและความเร็วในการตรวจจับที่จำเป็นสำหรับกรณีธุรกิจ แม้ว่าจะต้องใช้ทรัพยากรเพิ่มเติม (Wasm) เพื่อถอดรหัสบาร์โค้ด แต่โซลูชัน Wasm ก็ยังมีประสิทธิภาพเหนือกว่าโซลูชันที่ไม่ใช่ Wasm ในแง่ของความแม่นยำ
Scandit เป็นตัวเลือกหลักของเรา รองรับรูปแบบบาร์โค้ดทั้งหมดที่จำเป็นสำหรับกรณีการใช้งานทางธุรกิจของเรา ซึ่งมีประสิทธิภาพเหนือกว่าไลบรารีโอเพนซอร์สทั้งหมดที่มีในความเร็วในการสแกน
อนาคตของการสแกน
เมื่อเบราว์เซอร์หลักๆ ทั้งหมดรองรับ Shape Detection API อย่างสมบูรณ์แล้ว เราอาจมีองค์ประกอบ HTML ใหม่ <scanner>
ที่มีความสามารถที่จำเป็นสำหรับเครื่องสแกนบาร์โค้ด ทีมวิศวกรของ MishiPay เชื่อว่าฟังก์ชันการสแกนบาร์โค้ดเป็นองค์ประกอบ HTML ใหม่ที่ควรมี Use Case ที่ชัดเจน เนื่องจากมีไลบรารีโอเพนซอร์สและไลบรารีที่ได้รับอนุญาตจำนวนมากที่เปิดโอกาสให้ผู้ใช้ได้รับประสบการณ์การใช้งาน เช่น สแกนแล้วจ่าย และอื่นๆ อีกมากมาย
บทสรุป
ความเบื่อหน่ายของแอปเป็นปัญหาที่นักพัฒนาแอปต้องเผชิญเมื่อผลิตภัณฑ์ของตนเข้าสู่ตลาด ผู้ใช้มักต้องการเข้าใจคุณค่าที่แอปพลิเคชันมอบให้ก่อนที่จะดาวน์โหลด ในร้านค้าที่ MishiPay ช่วยประหยัดเวลาของผู้เลือกซื้อและปรับปรุงประสบการณ์ของผู้เลือกซื้อ การที่ผู้เลือกซื้อต้องรอการดาวน์โหลดก่อนจึงจะใช้แอปพลิเคชันได้นั้นขัดกับความรู้สึก PWA ของเราจะช่วยแก้ปัญหานี้ การยกเลิกข้อจำกัดในการเข้าร่วมทำให้ธุรกรรมเพิ่มขึ้น 10 เท่าและช่วยให้ผู้ใช้ไม่ต้องรอคิวนานถึง 2.5 ปี
ขอขอบคุณ
บทความนี้ผ่านการตรวจสอบโดย Joe Medley