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

GrabPay

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

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

GrabPay Payment Flow

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

ภาพรวม

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

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

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

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

RegionCurrencyMin AmountMax AmountAPI Version
SingaporeSGD$1.00$5,000.002017-11-02
MalaysiaMYRRM1.00RM1,500.002017-11-02

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

สิงคโปร์ (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

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

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

  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'];
if (!supportedCurrencies.includes(currency)) {
return res.status(400).json({
error: 'GrabPay supports SGD and MYR only'
});
}

// Validate amount by currency
const limits = {
SGD: { min: 100, max: 500000 },
MYR: { min: 100, max: 150000 }
};

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: 100, max: 500000 },
MYR: { min: 100, max: 150000 }
};

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

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

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

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: 100, max: 500000, label: '$' },
MYR: { min: 100, max: 150000, label: 'RM' }
};

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: 100,
maxAmount: 500000,
displayName: 'GrabPay (สิงคโปร์)'
},
MY: {
currency: 'MYR',
minAmount: 100,
maxAmount: 150000,
displayName: 'GrabPay (มาเลเซีย)'
}
};

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

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

GrabPay ใช้งานได้ในสิงคโปร์และมาเลเซียผ่าน Omise

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

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

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

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

  • สิงคโปร์: $1.00 - $5,000.00 ต่อรายการ
  • มาเลเซีย: RM1.00 - RM1,500.00 ต่อรายการ

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

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

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

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

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

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

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

  • บัตรเครดิต/เดบิต
  • โอนเงินผ่านธนาคาร
  • ช่องทางเงินสดอื่นๆ

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

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

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

การทดสอบ

โหมดทดสอบ

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

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

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

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

  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'];

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. เปิดใช้งานจริง