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

WeChat Pay MPM

รับชำระเงินแบบออฟไลน์ในร้านค้าผ่าน WeChat Pay โดยใช้โหมด Merchant-Presented Mode (MPM) ที่ลูกค้าสแกน QR Code ที่แสดงโดยร้านค้า ณ จุดชำระเงิน

ตัวเลือก WeChat Pay อื่นๆ

สำหรับการชำระเงินออนไลน์ ดูที่ WeChat Pay สำหรับการสแกนบาร์โค้ดที่ลูกค้าแสดง ดูที่ WeChat Pay UPM

ภาพรวม

WeChat Pay Merchant-Presented Mode (MPM) หรือที่เรียกว่า "C scan B" (ลูกค้าสแกนร้านค้า) เป็นวิธีการชำระเงินแบบออฟไลน์ที่ร้านค้าสร้างและแสดง QR Code เฉพาะสำหรับแต่ละธุรกรรม จากนั้นลูกค้าสแกน QR Code นี้โดยใช้แอป WeChat เพื่อทำการชำระเงิน

รูปแบบนี้เหมาะสำหรับสภาพแวดล้อมร้านค้าปลีก ร้านอาหาร และจุดขายทางกายภาพใดๆ ที่ร้านค้าควบคุมกระบวนการชำระเงินและแสดง QR Code สำหรับการชำระเงินบนเครื่องเทอร์มินัล แท็บเล็ต หรือใบเสร็จที่พิมพ์

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

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

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

ภูมิภาคสกุลเงินจำนวนขั้นต่ำจำนวนสูงสุดเวอร์ชัน API
ไทยTHB20.00 (2,000 สตางค์)150,000.00 (15,000,000 สตางค์)2017-11-02

หากต้องการเปิดใช้งาน WeChat Pay MPM ส่งอีเมลไปที่ support@omise.co เพื่อขอใช้งานฟีเจอร์นี้

การชำระเงินข้ามพรมแดน

WeChat Pay MPM มีคุณค่าอย่างยิ่งสำหรับร้านค้าที่มุ่งเป้าไปที่นักท่องเที่ยวชาวจีน ลูกค้าจ่ายเป็น CNY จากกระเป๋าเงิน WeChat และคุณได้รับการชำระเงินเป็น THB

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

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

  1. ร้านค้าสร้างการเรียกเก็บเงินผ่าน Omise API ด้วยประเภทแหล่งที่มา wechat_pay_mpm
  2. QR Code แสดงบนเครื่องเทอร์มินัล POS แท็บเล็ต หรือพิมพ์ออกมา
  3. ลูกค้าเปิดแอป WeChat และไปที่ "Scan"
  4. ลูกค้าสแกน QR Code ที่ร้านค้าแสดง
  5. ลูกค้าตรวจสอบรายละเอียดธุรกรรมและยืนยันการชำระเงิน
  6. ร้านค้าได้รับการแจ้งเตือน Webhook ยืนยันการชำระเงิน
  7. ร้านค้าให้ใบเสร็จหรือการยืนยันแก่ลูกค้า

เวลาที่ใช้โดยทั่วไป: 30 วินาที - 2 นาที

การใช้งาน

ขั้นตอนที่ 1: สร้างการเรียกเก็บเงินพร้อม Source

สำหรับ WeChat Pay MPM คุณสามารถสร้าง source และ charge ในการเรียก API ครั้งเดียวหรือแยกกันได้

# Create source
curl https://api.omise.co/sources \
-u $OMISE_SECRET_KEY: \
-d "type=wechat_pay_mpm" \
-d "amount=150000" \
-d "currency=THB"

# Create charge with source
curl https://api.omise.co/charges \
-u $OMISE_SECRET_KEY: \
-d "amount=150000" \
-d "currency=THB" \
-d "source=src_test_xxx"

Response:

{
"object": "charge",
"id": "chrg_test_5rt6s9vah5lkvi1rh9c",
"amount": 150000,
"currency": "THB",
"status": "pending",
"source": {
"object": "source",
"id": "src_test_5rt6s9vah5lkvi1rh9c",
"type": "wechat_pay_mpm",
"flow": "offline",
"amount": 150000,
"currency": "THB",
"scannable_code": {
"type": "qr",
"image": {
"download_uri": "https://api.omise.co/charges/chrg_test_.../documents/qr_code.png"
}
}
},
"expires_at": "2024-01-15T14:30:00Z"
}

ขั้นตอนที่ 2: แสดง QR Code บน POS

แสดง QR Code จาก charge.source.scannable_code.image.download_uri บนเครื่องเทอร์มินัล POS ของคุณ

// POS Terminal Display Logic
async function displayPaymentQR(orderId, amount) {
try {
// Create charge
const response = await fetch('/api/create-wechat-mpm-charge', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
order_id: orderId,
amount: amount
})
});

const data = await response.json();

// Display QR code on POS terminal
const qrDisplay = document.getElementById('pos-qr-display');
qrDisplay.innerHTML = `
<div class="payment-screen">
<h2>Scan to Pay with WeChat</h2>
<img src="${data.qr_code_url}" alt="WeChat Pay QR" />
<p class="amount">Amount: ฿${(amount / 100).toFixed(2)}</p>
<p class="timer">Expires in: <span id="countdown">2:00:00</span></p>
</div>
`;

// Start expiration countdown
startCountdown(data.expires_at, 'countdown');

// Start polling for payment status
pollPaymentStatus(data.charge_id);

} catch (error) {
showError('Failed to create payment. Please try again.');
}
}

ขั้นตอนที่ 3: จัดการการแจ้งเตือน Webhook

const express = require('express');
const app = express();

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

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

if (charge.source.type === 'wechat_pay_mpm') {
if (charge.status === 'successful') {
// Payment successful
notifyPOSTerminal(charge.metadata.terminal_id, {
status: 'success',
charge_id: charge.id,
amount: charge.amount
});

// Print receipt
printReceipt(charge);

// Update order status
updateOrderStatus(charge.metadata.order_id, 'paid');

} else if (charge.status === 'failed') {
// Payment failed
notifyPOSTerminal(charge.metadata.terminal_id, {
status: 'failed',
failure_code: charge.failure_code,
failure_message: charge.failure_message
});
}
}
}

res.sendStatus(200);
});

การแสดง QR Code

ข้อกำหนดการแสดงผล

เพื่อประสิทธิภาพการสแกนที่ดีที่สุด ปฏิบัติตามแนวทางเหล่านี้:

ข้อกำหนดคำแนะนำ
ขนาดขั้นต่ำ3cm x 3cm (1.2" x 1.2")
ขนาดที่แนะนำ5cm x 5cm (2" x 2") หรือใหญ่กว่า
ความละเอียด300 DPI สำหรับการพิมพ์
ความคมชัดQR สีเข้มบนพื้นหลังสีขาว
พื้นที่ว่างขอบสีขาวขั้นต่ำ 4 โมดูล

ตัวอย่างเครื่องเทอร์มินัล POS

<style>
.wechat-mpm-display {
background: #fff;
padding: 30px;
text-align: center;
border-radius: 10px;
max-width: 400px;
margin: 0 auto;
}
.wechat-mpm-display .qr-container {
background: #fff;
padding: 20px;
border: 3px solid #09BB07;
border-radius: 8px;
display: inline-block;
margin: 20px 0;
}
.wechat-mpm-display .qr-code {
width: 200px;
height: 200px;
}
.wechat-mpm-display .amount {
font-size: 28px;
font-weight: bold;
color: #333;
}
.wechat-mpm-display .timer {
color: #666;
font-size: 16px;
}
.wechat-mpm-display .timer.warning {
color: #ff6600;
}
.wechat-mpm-display .timer.expired {
color: #ff0000;
}
.wechat-logo {
width: 50px;
height: 50px;
}
</style>

<div class="wechat-mpm-display">
<img src="/images/wechat-pay-logo.svg" class="wechat-logo" alt="WeChat Pay" />
<h2>Scan to Pay</h2>

<div class="qr-container">
<img id="qr-code" class="qr-code" src="" alt="WeChat Pay QR Code" />
</div>

<p class="amount">฿<span id="display-amount">1,500.00</span></p>
<p class="timer">Expires in: <span id="countdown">2:00:00</span></p>

<div class="instructions">
<p>1. Open WeChat</p>
<p>2. Tap "Discover" then "Scan"</p>
<p>3. Scan this QR code</p>
</div>
</div>

การกำหนดค่าวันหมดอายุ

โดยค่าเริ่มต้น การเรียกเก็บเงิน WeChat Pay MPM จะหมดอายุหลังจาก 2 ชั่วโมง คุณสามารถปรับแต่งเวลาหมดอายุได้เมื่อสร้าง source

การหมดอายุแบบกำหนดเอง

curl https://api.omise.co/sources \
-u $OMISE_SECRET_KEY: \
-d "type=wechat_pay_mpm" \
-d "amount=150000" \
-d "currency=THB" \
-d "expires_at=2024-01-15T15:00:00Z"

ขีดจำกัดการหมดอายุ

การตั้งค่าค่า
ขั้นต่ำ1 นาที
สูงสุด2 ชั่วโมง
ค่าเริ่มต้น2 ชั่วโมง

การใช้งานกับการหมดอายุแบบกำหนดเอง

const source = await omise.sources.create({
type: 'wechat_pay_mpm',
amount: 150000,
currency: 'THB',
// Expire in 30 minutes
expires_at: new Date(Date.now() + 30 * 60 * 1000).toISOString()
});
แนวทางปฏิบัติที่ดีที่สุดสำหรับการหมดอายุ

สำหรับสภาพแวดล้อมร้านค้าปลีกที่มีผู้คนพลุกพล่าน พิจารณาเวลาหมดอายุที่สั้นลง (5-15 นาที) เพื่อหลีกเลี่ยงไม่ให้ลูกค้าพยายามสแกน QR Code ที่หมดอายุแล้ว ควรแสดงตัวนับเวลาถอยหลังที่มองเห็นได้เสมอ

ค่าสถานะการเรียกเก็บเงิน

สถานะคำอธิบาย
pendingQR Code แสดงแล้ว รอลูกค้าสแกนและชำระเงิน
successfulการชำระเงินเสร็จสมบูรณ์
failedการชำระเงินล้มเหลวหรือถูกปฏิเสธ
expiredQR Code หมดอายุก่อนที่จะชำระเงินเสร็จ
reversedการชำระเงินถูกย้อนกลับ (ยกเลิก)

รหัสความล้มเหลว

รหัสคำอธิบายการดำเนินการที่แนะนำ
payment_expiredQR Code หมดอายุก่อนที่ลูกค้าจะชำระเงินเสร็จสร้าง QR Code ใหม่
payment_rejectedการชำระเงินถูกปฏิเสธโดย WeChat/ธนาคารผู้ออกขอให้ลูกค้าตรวจสอบกระเป๋าเงิน WeChat
insufficient_fundลูกค้ามียอดเงินไม่เพียงพอขอให้ลูกค้าเติมเงินหรือใช้วิธีอื่น
failed_processingข้อผิดพลาดในการประมวลผลทั่วไปลองใหม่หรือติดต่อฝ่ายสนับสนุน
invalid_accountปัญหาบัญชี WeChat Pay ของลูกค้าขอให้ลูกค้ายืนยันสถานะบัญชี

การจัดการความล้มเหลว

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

if (event.key === 'charge.complete' && event.data.status === 'failed') {
const charge = event.data;
const failureCode = charge.failure_code;

switch (failureCode) {
case 'payment_expired':
// Offer to generate new QR code
notifyPOS('QR expired. Generate new payment?');
break;

case 'insufficient_fund':
// Suggest alternative payment
notifyPOS('Insufficient funds. Suggest another payment method.');
break;

case 'payment_rejected':
// Customer may need to verify account
notifyPOS('Payment rejected. Ask customer to check WeChat wallet.');
break;

default:
notifyPOS(`Payment failed: ${charge.failure_message}`);
}
}

res.sendStatus(200);
});

การคืนเงิน

WeChat Pay MPM รองรับ การคืนเงินเต็มจำนวนและบางส่วน ภายใน 90 วัน นับจากธุรกรรมเดิม

สร้างการคืนเงิน

# Full refund
curl https://api.omise.co/charges/chrg_test_xxx/refunds \
-u $OMISE_SECRET_KEY: \
-d "amount=150000"

# Partial refund
curl https://api.omise.co/charges/chrg_test_xxx/refunds \
-u $OMISE_SECRET_KEY: \
-d "amount=50000"

นโยบายการคืนเงิน

คุณสมบัติรายละเอียด
ระยะเวลาคืนเงิน90 วันนับจากวันที่ทำธุรกรรม
คืนเงินเต็มจำนวนรองรับ
คืนเงินบางส่วนรองรับ
คืนเงินหลายครั้งรองรับ (ไม่เกินจำนวนเงินเดิม)
เวลาดำเนินการ1-3 วันทำการ
ปลายทางการคืนเงิน

การคืนเงินจะถูกส่งกลับไปยังกระเป๋าเงิน WeChat Pay ของลูกค้า ลูกค้าจะได้รับการแจ้งเตือนในแอป WeChat เมื่อการคืนเงินถูกประมวลผล

แนวทางปฏิบัติที่ดีที่สุดสำหรับการรวม POS

1. แสดง QR Code ที่ชัดเจน

function displayQRCode(qrUrl, amount) {
// Ensure QR code is prominently displayed
return `
<div class="pos-payment-screen">
<div class="qr-wrapper" style="
background: white;
padding: 20px;
border: 4px solid #09BB07;
display: inline-block;
">
<img src="${qrUrl}"
alt="Scan to Pay"
style="width: 250px; height: 250px;" />
</div>
<h2 style="color: #09BB07;">Scan with WeChat</h2>
<p class="amount">฿${(amount / 100).toFixed(2)}</p>
</div>
`;
}

2. ใช้งานตัวนับเวลาถอยหลัง

function startCountdown(expiresAt, elementId) {
const expiryTime = new Date(expiresAt).getTime();

const timer = setInterval(() => {
const now = Date.now();
const timeLeft = expiryTime - now;

if (timeLeft <= 0) {
clearInterval(timer);
document.getElementById(elementId).textContent = 'EXPIRED';
document.getElementById(elementId).classList.add('expired');
handleExpiredQR();
return;
}

const hours = Math.floor(timeLeft / (1000 * 60 * 60));
const minutes = Math.floor((timeLeft % (1000 * 60 * 60)) / (1000 * 60));
const seconds = Math.floor((timeLeft % (1000 * 60)) / 1000);

document.getElementById(elementId).textContent =
`${hours}:${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`;

// Warning when less than 5 minutes remain
if (timeLeft < 5 * 60 * 1000) {
document.getElementById(elementId).classList.add('warning');
}
}, 1000);

return timer;
}

3. ตรวจสอบสถานะการชำระเงินแบบ Polling (สำรอง)

แม้ว่า Webhook จะเป็นวิธีการแจ้งเตือนหลัก แต่ควรใช้ polling เป็นการสำรอง:

async function pollPaymentStatus(chargeId, interval = 3000, maxAttempts = 40) {
let attempts = 0;

const poll = setInterval(async () => {
attempts++;

try {
const response = await fetch(`/api/charge-status/${chargeId}`);
const data = await response.json();

if (data.status === 'successful') {
clearInterval(poll);
handlePaymentSuccess(data);
} else if (data.status === 'failed') {
clearInterval(poll);
handlePaymentFailure(data);
} else if (data.status === 'expired') {
clearInterval(poll);
handleExpiredQR();
} else if (attempts >= maxAttempts) {
clearInterval(poll);
// Max attempts reached, rely on webhook
}
} catch (error) {
console.error('Status check error:', error);
}
}, interval);

return poll;
}

4. จัดการปัญหาเครือข่าย

async function createChargeWithRetry(orderData, maxRetries = 3) {
for (let i = 0; i < maxRetries; i++) {
try {
const response = await fetch('/api/create-wechat-mpm-charge', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(orderData)
});

if (response.ok) {
return await response.json();
}
} catch (error) {
if (i === maxRetries - 1) {
throw new Error('Failed to create charge after multiple attempts');
}
// Wait before retry
await new Promise(resolve => setTimeout(resolve, 1000 * (i + 1)));
}
}
}

5. ให้ตัวเลือกยกเลิก/สร้างใหม่

function showPaymentControls(chargeId) {
return `
<div class="payment-controls">
<button onclick="cancelPayment('${chargeId}')" class="btn-cancel">
Cancel Payment
</button>
<button onclick="regenerateQR()" class="btn-regenerate">
New QR Code
</button>
</div>
`;
}

async function cancelPayment(chargeId) {
// Note: Cannot cancel pending charge, but can expire/void
if (confirm('Cancel this payment and return to checkout?')) {
// Clear display and return to order entry
clearPaymentScreen();
returnToOrderEntry();
}
}

6. บันทึกธุรกรรมทั้งหมด

function logTransaction(charge, status) {
const logEntry = {
timestamp: new Date().toISOString(),
charge_id: charge.id,
order_id: charge.metadata?.order_id,
terminal_id: charge.metadata?.terminal_id,
amount: charge.amount,
currency: charge.currency,
status: status,
failure_code: charge.failure_code || null
};

// Store in local DB for reconciliation
saveToLocalLog(logEntry);

// Send to central logging system
sendToLoggingService(logEntry);
}

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

Merchant-Presented Mode (MPM) คืออะไร?

MPM หรือที่เรียกว่า "C scan B" (ลูกค้าสแกนร้านค้า) เป็นวิธีการชำระเงินแบบออฟไลน์ที่ร้านค้าแสดง QR Code และลูกค้าสแกนด้วยแอปกระเป๋าเงิน นี่คือรูปแบบมาตรฐานสำหรับธุรกรรม WeChat Pay ในร้านค้าที่ร้านค้าควบคุมประสบการณ์การชำระเงิน

ความแตกต่างระหว่าง WeChat Pay MPM และ WeChat Pay (ออนไลน์) คืออะไร?

WeChat Pay (ออนไลน์) ได้รับการออกแบบสำหรับอีคอมเมิร์ซและการชำระเงินเว็บ ซึ่งลูกค้าจะถูกเปลี่ยนเส้นทางไปยัง WeChat เพื่อทำการชำระเงิน WeChat Pay MPM ได้รับการออกแบบสำหรับสภาพแวดล้อมจุดขายจริงที่ QR Code แสดงบนเครื่องเทอร์มินัลและลูกค้าสแกนในร้าน

คุณสมบัติWeChat Pay (ออนไลน์)WeChat Pay MPM
กรณีการใช้งานอีคอมเมิร์ซPOS ในร้านค้า
รูปแบบRedirectOffline QR
ประเภท Sourcewechat_paywechat_pay_mpm
ความแตกต่างระหว่าง MPM และ UPM คืออะไร?

ใน MPM (Merchant-Presented Mode) ร้านค้าแสดง QR Code และลูกค้าสแกน ใน UPM (User-Presented Mode) ลูกค้าแสดงบาร์โค้ดจากแอป WeChat และร้านค้าสแกนด้วยเครื่องอ่านบาร์โค้ด UPM โดยทั่วไปจะเร็วกว่าแต่ต้องใช้ฮาร์ดแวร์สแกนบาร์โค้ด

QR Code มีอายุใช้งานนานเท่าไหร่?

QR Code หมดอายุหลังจาก 2 ชั่วโมง โดยค่าเริ่มต้น คุณสามารถปรับแต่งเวลาหมดอายุระหว่าง 1 นาทีถึง 2 ชั่วโมงเมื่อสร้าง source ควรแสดงตัวนับเวลาถอยหลังเสมอเพื่อแจ้งให้พนักงานและลูกค้าทราบเวลาที่เหลือ

สามารถยกเลิกหรือคืนเงินธุรกรรม MPM ได้หรือไม่?

ได้ WeChat Pay MPM รองรับทั้งการคืนเงินเต็มจำนวนและบางส่วนภายใน 90 วันนับจากธุรกรรมเดิม การคืนเงินจะถูกประมวลผลภายใน 1-3 วันทำการและส่งกลับไปยังกระเป๋าเงิน WeChat Pay ของลูกค้า

ต้องใช้ฮาร์ดแวร์พิเศษสำหรับ MPM หรือไม่?

ไม่ต้องใช้ฮาร์ดแวร์พิเศษสำหรับ MPM คุณสามารถแสดง QR Code บนหน้าจอใดก็ได้ (เครื่องเทอร์มินัล POS แท็บเล็ต จอมอนิเตอร์) หรือแม้แต่พิมพ์ออกมา ลูกค้าใช้โทรศัพท์ของตัวเองพร้อมแอป WeChat เพื่อสแกนและชำระเงิน

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