ข้ามไปยังเนื้อหาหลัก

GrabPay

รับชำระเงินจาก GrabPay กระเป๋าเงินดิจิทัลชั้นนำของเอเชียตะวันออกเฉียงใต้ มีผู้ใช้ 187 ล้านคนใน 8 ประเทศ ได้แก่ สิงคโปร์ มาเลเซีย ไทย อินโดนีเซีย ฟิลิปปินส์ เวียดนาม เมียนมาร์ และกัมพูชา

ขั้นตอนการชำระเงิน

GrabPay Payment Flow

ภาพประกอบกระบวนการชำระเงินแบบ redirect ที่สมบูรณ์ รวมถึงการกรอกหมายเลขโทรศัพท์ การยืนยัน OTP การเลือกวิธีการชำระเงิน และการยืนยันขั้นสุดท้าย

ภาพรวม

GrabPay เป็นกระเป๋าเงินชำระเงินที่รวมอยู่ในแอปซูเปอร์ Grab ซึ่งให้บริการเรียกรถ จัดส่งอาหาร และบริการทางการเงินทั่วเอเชียตะวันออกเฉียงใต้ ลูกค้าสามารถชำระเงินโดยใช้ยอดเงิน GrabPay พร้อมการยืนยันทันที

คุณสมบัติหลัก:

  • การเข้าถึงที่กว้างขวาง - ผู้ใช้ 187 ล้านคนใน 8 ประเทศ
  • การยืนยันที่รวดเร็ว - การตรวจสอบการชำระเงินแบบเกือบเรียลไทม์ (โดยทั่วไปภายในไม่กี่วินาที)
  • มือถือเป็นหลัก - ปรับแต่งสำหรับผู้ใช้สมาร์ทโฟน
  • แบรนด์ที่เชื่อถือได้ - เป็นส่วนหนึ่งของระบบนิเวศ Grab
  • ไม่มีความขัดแย้งในการชำระเงิน - การชำระเงินแบบแตะเดียวในแอป Grab
  • การครอบคลุมในภูมิภาค - รองรับหลายประเทศ

ภูมิภาคที่รองรับ

ภูมิภาคสกุลเงินจำนวนเงินขั้นต่ำจำนวนเงินสูงสุดวงเงินต่อวัน
สิงคโปร์SGD$0.50$500$5,000*
มาเลเซียMYRRM1.00RM1,500RM5,000*
ไทยTHB฿20.00฿50,000฿200,000*

*วงเงินต่อวันแตกต่างกันตามระดับการยืนยันตัวตนของกระเป๋าเงินลูกค้า

ข้อจำกัดการทำรายการตามประเทศ

สิงคโปร์ (SGD)

ระดับการยืนยันตัวตนต่อรายการวงเงินต่อวันวงเงินต่อเดือน
Basic (เบอร์โทรศัพท์อย่างเดียว)$500$2,000$5,000
Plus (ยืนยัน ID แล้ว)$500$5,000$30,000

มาเลเซีย (MYR)

ระดับการยืนยันตัวตนต่อรายการวงเงินต่อวันวงเงินต่อเดือน
Basic (เบอร์โทรศัพท์อย่างเดียว)RM1,500RM1,500RM3,000
Plus (ยืนยัน ID แล้ว)RM1,500RM5,000RM10,000

ไทย (THB)

ระดับการยืนยันตัวตนต่อรายการวงเงินต่อวันวงเงินต่อเดือน
Basic (เบอร์โทรศัพท์อย่างเดียว)฿50,000฿50,000฿200,000
Plus (ยืนยัน ID แล้ว)฿50,000฿200,000฿500,000

วิธีการทำงาน

ประสบการณ์ลูกค้า:

  1. ลูกค้าเลือก GrabPay ที่หน้าชำระเงิน
  2. ถูก redirect ไปยังหน้าอนุมัติ GrabPay
  3. เปิดแอป Grab (deep link)
  4. ตรวจสอบรายละเอียดการชำระเงิน
  5. ยืนยันด้วย PIN/ชีวมิติ
  6. กลับไปยังเว็บไซต์ผู้ค้า

เวลาในการทำรายการโดยทั่วไป: 1-2 นาที

การใช้งาน

ขั้นตอนที่ 1: สร้าง GrabPay Source

curl https://api.omise.co/sources \
-u skey_test_YOUR_SECRET_KEY: \
-d "type=grabpay" \
-d "amount=10000" \
-d "currency=SGD"

ผลลัพธ์:

{
"object": "source",
"id": "src_test_5rt6s9vah5lkvi1rh9c",
"type": "grabpay",
"flow": "redirect",
"amount": 10000,
"currency": "SGD"
}

ขั้นตอนที่ 2: สร้าง Charge

curl https://api.omise.co/charges \
-u skey_test_YOUR_SECRET_KEY: \
-d "amount=10000" \
-d "currency=SGD" \
-d "source=src_test_5rt6s9vah5lkvi1rh9c" \
-d "return_uri=https://yourdomain.com/payment/callback"

ขั้นตอนที่ 3: Redirect ลูกค้า

app.post('/checkout/grabpay', async (req, res) => {
try {
const { amount, currency, order_id } = req.body;

// Validate currency
const supportedCurrencies = ['SGD', 'MYR', 'THB'];
if (!supportedCurrencies.includes(currency)) {
return res.status(400).json({
error: 'GrabPay supports SGD, MYR, and THB only'
});
}

// Validate amount by currency
const limits = {
SGD: { min: 50, max: 50000 },
MYR: { min: 100, max: 150000 },
THB: { min: 2000, max: 5000000 }
};

if (amount < limits[currency].min || amount > limits[currency].max) {
return res.status(400).json({
error: `Amount out of range for ${currency}`
});
}

// Create source
const source = await omise.sources.create({
type: 'grabpay',
amount: amount,
currency: currency
});

// Create charge
const charge = await omise.charges.create({
amount: amount,
currency: currency,
source: source.id,
return_uri: `${process.env.BASE_URL}/payment/callback`,
metadata: {
order_id: order_id
}
});

// Redirect to GrabPay
res.redirect(charge.authorize_uri);

} catch (error) {
console.error('GrabPay error:', error);
res.status(500).json({ error: error.message });
}
});

ขั้นตอนที่ 4: จัดการ Return

app.get('/payment/callback', async (req, res) => {
try {
const chargeId = req.query.charge_id;
const charge = await omise.charges.retrieve(chargeId);

if (charge.status === 'successful') {
// Payment successful
await processOrder(charge.metadata.order_id);
res.redirect('/payment-success');
} else if (charge.status === 'failed') {
// Payment failed
res.redirect('/payment-failed?reason=' + charge.failure_message);
} else {
// Still pending
res.redirect('/payment-pending');
}
} catch (error) {
res.redirect('/payment-error');
}
});

ขั้นตอนที่ 5: จัดการ Webhook

app.post('/webhooks/omise', (req, res) => {
const event = req.body;

if (event.key === 'charge.complete' && event.data.source.type === 'grabpay') {
const charge = event.data;

if (charge.status === 'successful') {
processOrder(charge.metadata.order_id);
} else if (charge.status === 'failed') {
handleFailedPayment(charge.metadata.order_id);
}
}

res.sendStatus(200);
});

ตัวอย่างการใช้งานแบบสมบูรณ์

// Express.js server
const express = require('express');
const omise = require('omise')({
secretKey: process.env.OMISE_SECRET_KEY
});

const app = express();
app.use(express.json());

// Amount limits by currency
const LIMITS = {
SGD: { min: 50, max: 50000 },
MYR: { min: 100, max: 150000 },
THB: { min: 2000, max: 5000000 }
};

// Checkout page
app.post('/checkout/grabpay', async (req, res) => {
try {
const { amount, currency, order_id } = req.body;

// Validate currency
if (!['SGD', 'MYR', 'THB'].includes(currency)) {
return res.status(400).json({
error: 'GrabPay only supports SGD, MYR, and THB'
});
}

// Validate amount
const { min, max } = LIMITS[currency];
if (amount < min || amount > max) {
return res.status(400).json({
error: `Amount must be between ${min} and ${max} ${currency}`
});
}

// Create source
const source = await omise.sources.create({
type: 'grabpay',
amount: amount,
currency: currency
});

// Create charge
const charge = await omise.charges.create({
amount: amount,
currency: currency,
source: source.id,
return_uri: `${process.env.BASE_URL}/payment/callback`,
metadata: {
order_id: order_id,
payment_method: 'grabpay'
}
});

// Return authorization URL
res.json({
authorize_uri: charge.authorize_uri,
charge_id: charge.id
});

} catch (error) {
console.error('GrabPay error:', error);
res.status(500).json({ error: error.message });
}
});

// Callback handler
app.get('/payment/callback', async (req, res) => {
try {
const chargeId = req.query.charge_id;
const charge = await omise.charges.retrieve(chargeId);

if (charge.status === 'successful') {
res.redirect(`/order-success?order=${charge.metadata.order_id}`);
} else {
res.redirect(`/payment-failed?charge=${chargeId}`);
}
} catch (error) {
res.redirect('/payment-error');
}
});

// Webhook handler
app.post('/webhooks/omise', (req, res) => {
const event = req.body;

if (event.key === 'charge.complete') {
const charge = event.data;

if (charge.source.type === 'grabpay') {
if (charge.status === 'successful') {
updateOrderStatus(charge.metadata.order_id, 'paid');
sendConfirmation(charge.metadata.customer_email);
} else {
updateOrderStatus(charge.metadata.order_id, 'failed');
}
}
}

res.sendStatus(200);
});

app.listen(3000);

การรองรับ Void และการคืนเงิน

การยกเลิก Charge

GrabPay รองรับการยกเลิกภายใน 24 ชั่วโมง หลังจากสร้าง charge:

// Void immediately (full amount only)
const refund = await omise.charges.refund('chrg_test_...', {
amount: 10000 // Full amount
});

if (refund.voided) {
console.log('Charge was voided (within 24 hours)');
}

การคืนเงิน

รองรับการคืนเงินเต็มจำนวนและบางส่วน ภายใน 30 วัน:

// Full refund
const fullRefund = await omise.charges.refund('chrg_test_...', {
amount: 10000
});

// Partial refund
const partialRefund = await omise.charges.refund('chrg_test_...', {
amount: 5000 // Half refund
});
การรองรับการคืนเงิน

GrabPay รองรับทั้งการคืนเงินเต็มจำนวนและบางส่วนภายใน 30 วันหลังจากทำรายการเดิม

ปัญหาทั่วไปและการแก้ไข

ปัญหา: ลูกค้าไม่มีแอป Grab

สาเหตุ: ลูกค้าเลือก GrabPay แต่ไม่ได้ติดตั้งแอป Grab

วิธีแก้:

  • แสดงคำแนะนำที่ชัดเจนก่อนการชำระเงิน
  • ตรวจสอบแพลตฟอร์ม (iOS/Android)
  • จัดหาลิงก์ดาวน์โหลดแอป
function checkGrabApp() {
const isIOS = /iPhone|iPad|iPod/i.test(navigator.userAgent);
const isAndroid = /Android/i.test(navigator.userAgent);

if (!isIOS && !isAndroid) {
alert('GrabPay requires the Grab mobile app. Please use a mobile device.');
return false;
}

return true;
}

ปัญหา: ยอดเงินไม่เพียงพอ

ข้อผิดพลาด: การชำระเงินถูกปฏิเสธ

วิธีแก้:

  • แสดงข้อความแสดงข้อผิดพลาดที่ชัดเจน
  • อนุญาตให้ลูกค้าเติมเงินกระเป๋าเงิน GrabPay
  • เสนอวิธีการชำระเงินทางเลือก
if (charge.failure_code === 'insufficient_balance') {
showMessage('ยอดเงิน GrabPay ไม่เพียงพอ กรุณาเติมเงินหรือใช้วิธีการชำระเงินอื่น');
}

ปัญหา: สกุลเงินไม่ตรงกัน

ข้อผิดพลาด: สกุลเงินที่ไม่รองรับ

วิธีแก้:

function validateGrabPayCurrency(currency, country) {
const currencyMap = {
'SG': 'SGD',
'MY': 'MYR',
'TH': 'THB'
};

const expectedCurrency = currencyMap[country];
if (currency !== expectedCurrency) {
throw new Error(`Use ${expectedCurrency} for ${country}`);
}
}

ปัญหา: หมดเวลาการชำระเงิน

สาเหตุ: ลูกค้าไม่ทำการชำระเงินให้เสร็จสิ้นภายในเวลาที่กำหนด

วิธีแก้:

  • ตั้งค่าหมดเวลา 15 นาที
  • อนุญาตให้ลองใหม่ด้วย charge ใหม่
  • ส่งคำเตือน
const TIMEOUT = 15 * 60 * 1000; // 15 minutes

setTimeout(() => {
if (!paymentConfirmed) {
showTimeoutMessage();
allowRetry();
}
}, TIMEOUT);

แนวทางปฏิบัติที่ดีที่สุด

1. แสดงคำแนะนำที่ชัดเจน

<div class="grabpay-instructions">
<h3>ชำระเงินด้วย GrabPay</h3>
<ol>
<li>ตรวจสอบให้แน่ใจว่าคุณมีแอป Grab ติดตั้งแล้ว</li>
<li>ตรวจสอบว่ามียอดเงินเพียงพอในกระเป๋าเงิน GrabPay ของคุณ</li>
<li>คุณจะถูก redirect ไปที่แอป Grab</li>
<li>ยืนยันตัวตนและยืนยันการชำระเงิน</li>
</ol>
<p>ยอดเงินไม่พอหรือ? <a href="https://grab.com/sg/pay/">เติมเงินเลย</a></p>
</div>
function openGrabApp(authorizeUri) {
if (/iPhone|iPad|iPod|Android/i.test(navigator.userAgent)) {
window.location = authorizeUri;

// Check if app opened
setTimeout(() => {
if (!document.hidden) {
showInstallAppMessage();
}
}, 2000);
} else {
alert('GrabPay ใช้งานได้เฉพาะบนอุปกรณ์มือถือเท่านั้น');
}
}

3. ตรวจสอบจำนวนเงินตามสกุลเงิน

function validateAmount(amount, currency) {
const limits = {
SGD: { min: 50, max: 50000, label: '$' },
MYR: { min: 100, max: 150000, label: 'RM' },
THB: { min: 2000, max: 5000000, label: '฿' }
};

const { min, max, label } = limits[currency];

if (amount < min) {
return `จำนวนเงินขั้นต่ำคือ ${label}${min / 100}`;
}

if (amount > max) {
return `จำนวนเงินสูงสุดคือ ${label}${max / 100}`;
}

return null; // Valid
}

4. ใช้ Webhook

// Webhook is primary notification
app.post('/webhooks/omise', handleWebhook);

// Callback is backup
app.get('/payment/callback', handleCallback);

5. จัดการความแตกต่างในแต่ละภูมิภาค

const GRABPAY_CONFIG = {
SG: {
currency: 'SGD',
minAmount: 50,
maxAmount: 50000,
displayName: 'GrabPay (สิงคโปร์)'
},
MY: {
currency: 'MYR',
minAmount: 100,
maxAmount: 150000,
displayName: 'GrabPay (มาเลเซีย)'
},
TH: {
currency: 'THB',
minAmount: 2000,
maxAmount: 5000000,
displayName: 'GrabPay (ไทย)'
}
};

คำถามที่พบบ่อย

GrabPay รองรับประเทศไหนบ้าง?

GrabPay ใช้งานได้ในสิงคโปร์ มาเลเซีย และไทยผ่าน Omise แม้ว่า Grab จะดำเนินการใน 8 ประเทศทั้งหมด แต่การรวมระบบการชำระเงินปัจจุบันใช้งานได้สำหรับสามตลาดนี้

ลูกค้าต้องมีบัญชี Grab หรือไม่?

ใช่ ลูกค้าต้องติดตั้งแอป Grab และเปิดใช้งานกระเป๋าเงิน GrabPay แอปฟรีและใช้งานได้ทั้งบน iOS และ Android

ข้อจำกัดการทำรายการเป็นเท่าไร?

ข้อจำกัดแตกต่างกันตามประเทศ:

  • สิงคโปร์: $0.50 - $500 ต่อรายการ
  • มาเลเซีย: RM1.00 - RM1,500 ต่อรายการ
  • ไทย: ฿20 - ฿50,000 ต่อรายการ

วงเงินต่อวันและต่อเดือนขึ้นอยู่กับระดับการยืนยันตัวตนของลูกค้า

การชำระบัญชีใช้เวลานานเท่าไร?

การชำระบัญชี GrabPay โดยทั่วไปเกิดขึ้นภายใน 1-3 วันทำการ ตรวจสอบแดชบอร์ด Omise ของคุณสำหรับกำหนดการชำระบัญชีเฉพาะสำหรับบัญชีของคุณ

สามารถคืนเงินการชำระเงิน GrabPay ได้หรือไม่?

ได้ GrabPay รองรับทั้งการคืนเงินเต็มจำนวนและบางส่วนภายใน 30 วันหลังจากทำรายการเดิม การยกเลิกใช้งานได้ภายใน 24 ชั่วโมง

ถ้าลูกค้ามียอดเงินไม่เพียงพอจะเกิดอะไรขึ้น?

การชำระเงินจะถูกปฏิเสธ ลูกค้าสามารถเติมเงินกระเป๋าเงิน GrabPay ผ่าน:

  • บัตรเครดิต/เดบิต
  • โอนเงินผ่านธนาคาร
  • 7-Eleven, FamilyMart (ในไทย)
  • ช่องทางเงินสดอื่นๆ

จัดให้มีข้อความแสดงข้อผิดพลาดที่ชัดเจนและเสนอวิธีการชำระเงินทางเลือก

GrabPay ทำงานบนเดสก์ท็อปหรือไม่?

GrabPay ต้องการแอป Grab บนมือถือ ดังนั้นจึงใช้งานได้เฉพาะบนมือถือเท่านั้น ผู้ใช้เดสก์ท็อปควรได้รับแสดงวิธีการชำระเงินทางเลือก

การทดสอบ

โหมดทดสอบ

GrabPay สามารถทดสอบในโหมดทดสอบโดยใช้ API key ทดสอบของคุณ ในโหมดทดสอบ:

ข้อมูลประจำตัวสำหรับทดสอบ:

  • ใช้ API key ทดสอบ (skey_test_xxx)
  • ทดสอบประเทศที่รองรับทั้งหมด: สิงคโปร์ มาเลเซีย ไทย
  • ทดสอบสกุลเงินต่างๆ: SGD, MYR, THB

ขั้นตอนการทดสอบ:

  1. สร้าง source และ charge ด้วย API key ทดสอบ
  2. redirect ลูกค้าไปยัง authorize_uri ทดสอบ
  3. หน้าอนุมัติทดสอบจะถูกแสดง
  4. ใช้ Actions ของแดชบอร์ดเพื่อจำลองความสำเร็จ/ความล้มเหลวของการชำระเงิน
  5. ตรวจสอบการส่ง webhook และการจัดการ return_uri

การทดสอบการใช้งาน:

// Test GrabPay for different countries
const testCountries = ['SG', 'MY', 'TH'];

for (const country of testCountries) {
const config = countryConfig[country];

const source = await omise.sources.create({
type: 'grabpay',
amount: config.minAmount,
currency: config.currency
});

const charge = await omise.charges.create({
amount: config.minAmount,
currency: config.currency,
source: source.id,
return_uri: 'https://example.com/callback'
});

console.log(`Test ${country}:`, charge.authorize_uri);
}

สถานการณ์การทดสอบ:

  • การชำระเงินสำเร็จ: ตรวจสอบเวิร์กโฟลว์การทำรายการให้เสร็จสิ้น
  • การชำระเงินล้มเหลว: ทดสอบการจัดการข้อผิดพลาดและกลไกการลองใหม่
  • หลายประเทศ: ทดสอบแต่ละประเทศที่รองรับแยกกัน
  • ข้อจำกัดจำนวนเงิน: ตรวจสอบว่าข้อจำกัดเฉพาะประเทศถูกบังคับใช้
  • การตรวจสอบสกุลเงิน: ตรวจสอบสกุลเงินที่เหมาะสมสำหรับแต่ละประเทศ
  • ขั้นตอนมือถือ: ทดสอบ redirect และ deep linking บนมือถือ
  • หมดเวลา: ทดสอบการจัดการการชำระเงินที่ถูกละทิ้ง

หมายเหตุสำคัญ:

  • โหมดทดสอบจะไม่เชื่อมต่อกับเซิร์ฟเวอร์ Grab จริง
  • ใช้แดชบอร์ด Omise เพื่อทำเครื่องหมาย charge ทดสอบเป็นสำเร็จ/ล้มเหลว
  • ทดสอบแต่ละชุดประเทศ/สกุลเงินก่อนเปิดใช้งานจริง
  • ตรวจสอบว่าได้รับ webhook สำหรับการเปลี่ยนแปลงสถานะทั้งหมด
  • ทดสอบทั้งบน iOS และ Android หากรองรับมือถือ

สำหรับแนวทางการทดสอบที่ครอบคลุม โปรดดูเอกสารการทดสอบ

แหล่งข้อมูลที่เกี่ยวข้อง

ขั้นตอนถัดไป

  1. สร้าง GrabPay source
  2. ใช้งาน redirect flow
  3. ตั้งค่าการจัดการ webhook
  4. ทดสอบขั้นตอนการชำระเงิน
  5. เปิดใช้งานจริง