Payment Gateway VN — VNPay, MoMo, Casso, Stripe khác nhau thế nào
VNPay là 'cổng thanh toán bank Việt Nam', MoMo là 'ví điện tử', Casso là 'auto-verify chuyển khoản', Stripe là 'cổng quốc tế'. Hiểu 4 lựa chọn để chọn đúng cho ecommerce VN — tiết kiệm 30-70% phí transaction và rút ngắn integration từ 3 tuần xuống 3 ngày.
Mục lục bài viết(25)

Thị trường payment gateway toàn cầu — các nhà cung cấp cổng thanh toán online phân theo region, transaction volume, target customer. Việt Nam có hệ sinh thái payment riêng (VNPay, MoMo, ZaloPay, Casso) tách biệt khá rõ với Stripe/PayPal phổ biến quốc tế. Hiểu landscape giúp chọn đúng combo cho audience VN vs quốc tế. Nguồn: Wikimedia Commons (CC BY-SA 4.0).
Hiểu đơn giản nhất
Bạn mở quán cafe online. Khách đặt 1 cốc 50k VND. Bạn cần nhận tiền + biết chính xác ai trả + giao đúng đơn.
4 cách phổ biến ở VN:
| Cách | Analogy | Phí transaction | UX cho khách |
|---|---|---|---|
| VNPay | Quầy thu ngân có máy POS — cà thẻ là xong | 1.1-1.65% | 1 click, redirect sang VNPay, nhập OTP |
| MoMo | Ví QR — quét + nhập PIN | 1.1-2.2% | App MoMo scan QR → confirm |
| Casso | Hộp đựng tiền + sổ ghi chép — khách chuyển khoản, bạn check | 200-500 VND/giao dịch | Khách quét VietQR + bank app → bạn nhận webhook |
| Stripe | Máy POS quốc tế Visa/Master | 2.9% + $0.3 | 1 click, form thẻ inline |
4 thuật ngữ cần phân biệt:
| Thuật ngữ | Là gì |
|---|---|
| Payment Gateway | Cổng kết nối web bạn → mạng thanh toán (VNPay, Stripe) |
| Payment Processor | Backend xử lý giao dịch (Napas cho VN, Visa/Master cho quốc tế) |
| Acquiring Bank | Bank của bạn nhận tiền (Vietcombank, BIDV...) |
| Issuing Bank | Bank của khách phát thẻ |
User → gateway → processor → acquiring bank → tiền vào tài khoản bạn.
Tại sao bạn cần biết
- Chọn sai gateway tốn 10x phí. SaaS 1000 đơn/tháng AOV 1tr → VNPay phí 1.5% = 15tr/tháng. Casso 200 VND × 1000 = 200k/tháng. Tiết kiệm 14.8tr/tháng = 178tr/năm.
- Integration 3 ngày vs 3 tuần. VNPay docs cũ, có docs tiếng Việt nhưng convoluted. Stripe docs world-class. Casso docs medium. Chuẩn bị trước = không stuck.
- Compliance/PCI-DSS = avoid PCI-DSS audit ($5-50k/năm) bằng cách dùng hosted payment page.
- Webhook security critical. Audit vietcodex.com mới phát hiện M6 — non-constant-time compare cho Casso webhook. Hacker có thể fake webhook 'đã thanh toán' nếu không verify đúng.
- UX = conversion. 1-click VNPay/MoMo có conversion 50-70%. Casso (yêu cầu quét QR + note đúng) chỉ 30-50% — phù hợp B2B không phù hợp impulse buy.
VNPay — cổng thanh toán thẻ VN
VNPay = aggregator kết nối web bạn với mọi bank VN. Thành lập 2007, partner với 40+ ngân hàng VN, thị phần > 50% ecommerce VN.
Methods VNPay hỗ trợ
| Method | Mô tả | Phí |
|---|---|---|
| ATM/Internet Banking | Login Internet Banking, OTP | 1.1% |
| QR Code (VietQR) | Scan QR bằng app banking | 0.8-1.1% |
| Thẻ tín dụng nội địa | Napas | 1.65% |
| Thẻ quốc tế Visa/Master | International | 2.95% |
Integration flow
- Đăng ký merchant tại vnpay.vn — KYC giấy phép kinh doanh, mất 5-10 ngày
- Nhận credentials:
vnp_TmnCode+vnp_HashSecret - Backend tạo URL redirect với params +
vnp_SecureHashHMAC-SHA512 - Redirect user → vnpay.vn → khách thanh toán
- VNPay redirect về
vnp_ReturnUrlcủa bạn với status (success/fail) - VNPay gửi IPN (Instant Payment Notification) webhook → bạn verify + update DB
Code snippet
import { createHmac } from "node:crypto";
const params = {
vnp_Version: "2.1.0",
vnp_Command: "pay",
vnp_TmnCode: process.env.VNPAY_TMN_CODE,
vnp_Amount: 100000 * 100, // VND × 100 (đơn vị xu)
vnp_CurrCode: "VND",
vnp_TxnRef: "ORDER_12345",
vnp_OrderInfo: "Thanh toan don VC2026000001",
vnp_OrderType: "other",
vnp_Locale: "vn",
vnp_ReturnUrl: "https://vietcodex.com/thanh-toan/vnpay-return",
vnp_IpAddr: clientIp,
vnp_CreateDate: format(new Date(), "yyyyMMddHHmmss"),
};
const sortedKeys = Object.keys(params).sort();
const queryString = sortedKeys.map(k => `${k}=${encodeURIComponent(params[k])}`).join("&");
const signature = createHmac("sha512", process.env.VNPAY_HASH_SECRET)
.update(queryString)
.digest("hex");
const paymentUrl = `https://sandbox.vnpayment.vn/paymentv2/vpcpay.html?${queryString}&vnp_SecureHash=${signature}`;
// Redirect user to paymentUrl⚠️ Khi verify IPN webhook, dùng timingSafeEqual (xem audit M6 vietcodex.com).
MoMo — ví điện tử dẫn đầu VN
MoMo = mobile wallet 30M+ user. Mạnh nhất Gen Z + millennials.
Methods
- QR App MoMo — scan trong cart, confirm trong app
- Number phone — nhập số ĐT MoMo của khách
- Token — khách lưu method trong app, click 1 lần xong
Integration
Tương tự VNPay nhưng API khác. Docs developer.momo.vn — tiếng Anh + Việt.
Lý do dùng MoMo
- Customer 18-35 tuổi mua hàng tiện lợi
- F&B, grocery, transport (đã có precedent Grab/Be)
- Cashback campaign — MoMo subsidize cashback cho merchant tham gia
Casso — auto-reconcile chuyển khoản bank
Casso là tool VN giải quyết bài toán: web không tự biết khách đã chuyển khoản chưa. Cách thủ công = bạn check sao kê bank mỗi giờ. Cách Casso = webhook tự báo.
Flow
- Setup: Đăng ký casso.vn, link tài khoản Vietcombank/Techcombank/BIDV (Casso đăng nhập IB của bạn để đọc sao kê)
- Web hiển thị VietQR cho khách + nội dung
VC2026000001(mã đơn) - Khách chuyển khoản từ bank app với nội dung đó
- Bank notify Casso (Casso check sao kê mỗi 30 giây - 5 phút)
- Casso webhook → server bạn kèm secret token
- Server verify token + match order theo nội dung chuyển → mark PAID
Code snippet (vietcodex.com đang dùng)
// app/api/webhook/casso/route.ts
import { timingSafeEqual } from "node:crypto";
export async function POST(req: Request) {
const secret = process.env.CASSO_WEBHOOK_SECRET;
const auth = req.headers.get("secure-token") || "";
// M6 fix: constant-time compare
if (!safeTokenMatch(auth, secret)) {
return new Response("Unauthorized", { status: 401 });
}
const body = await req.json();
for (const tx of body.data) {
const match = tx.description.match(/VC[\d]+/);
if (!match) continue;
const order = await db.query.orders.findFirst({
where: sql`UPPER(REPLACE(order_number, '-', '')) = ${match[0]}`,
});
if (order && tx.amount >= order.total) {
await markOrderPaid(order.id, tx.id);
}
}
return new Response("OK", { status: 200 });
}Pricing
- Free tier: 100 transaction/tháng
- Paid: 200-500 VND/transaction (rẻ hơn VNPay 50-100x)
- Annual: discount khi mua trước
Khi nào nên dùng Casso
✅ B2B service/SaaS, AOV > 500k ✅ Tech-savvy customer ✅ Không khẩn cấp confirm thanh toán (1-5 phút lag OK) ✅ Cần invoice chính thức (chuyển khoản bank có sao kê rõ)
❌ B2C impulse buy < 200k (khách lười QR + note sai) ❌ Real-time critical (game top-up, đặt vé giờ chót)
Stripe — cổng quốc tế
Stripe dominant ở US/EU. Documentation engineering xuất sắc, developer experience top-tier.
Tại sao Stripe khó dùng ở VN
- Không nhận pháp nhân VN (cần US/UK/SG entity)
- Không support thẻ ATM VN nội địa (chỉ Visa/Master quốc tế)
- Payout USD/EUR (chịu phí FX convert 1-3%)
Stripe Atlas — workaround cho founder VN
- Stripe + LLC Delaware US + Mercury bank account
- Setup $500 + $100/năm maintain
- Ưu: chuyên nghiệp quốc tế, accept toàn thế giới
- Nhược: tax US + accounting US (phải hire CPA $1-3k/năm)
Khi nào dùng Stripe
✅ SaaS bán quốc tế, customer paying USD ✅ Subscription billing (Stripe Billing world-class) ✅ Marketplace platform (Stripe Connect) ✅ Có entity quốc tế hoặc willing setup Atlas
ZaloPay, ShopeePay, ViettelMoney
| Provider | Strength | Use case |
|---|---|---|
| ZaloPay | Tích hợp Zalo OA, mini-app | App có user base Zalo, chatbot order |
| ShopeePay | Internal Shopee/SEA group | Marketplace seller |
| ViettelMoney | Viettel telco network | Mass market, low income demographic |
Ít phổ biến hơn VNPay/MoMo nhưng có niche.
Decision matrix
| Bạn bán | Khuyến nghị stack |
|---|---|
| SaaS B2B VN < 100 đơn/tháng | Casso + VietQR display |
| SaaS B2B VN > 100 đơn/tháng | VNPay + Casso (backup) |
| E-commerce B2C VN food/lifestyle | MoMo + VNPay (mặc định) |
| E-commerce B2C VN >5000 đơn/tháng | VNPay + MoMo + ZaloPay |
| SaaS bán quốc tế VND | VNPay + Stripe Atlas |
| SaaS bán quốc tế USD | Stripe (Atlas LLC) |
| Marketplace platform | Stripe Connect (US LLC) |
| Đào tạo, coaching B2C VN | VNPay + Casso |
| Service freelancer quốc tế | Wise + Payoneer |
Ví dụ thực tế: vietcodex.com payment flow
vietcodex bán web design 5-50tr/dự án, AOV cao, customer B2B → Casso là chọn đúng.
Customer flow:
1. Customer chọn package (vd "Web service business 8tr")
2. Web tạo order với mã VC2026000001, status PENDING_PAYMENT
3. Web hiện VietQR + nội dung "VC2026000001" + bank info
4. Customer chuyển khoản qua app Vietcombank/Techcombank
5. Casso check sao kê → match "VC2026000001"
6. Casso webhook → server vietcodex.com
7. Server verify token (M6 timing-safe) → mark PAID
8. Server provision tenant tự động (template website)
9. Telegram notify admin
10. Customer thấy status update "Đã thanh toán, đang triển khai"
Time: 30 giây - 5 phút sau khi chuyển khoản
Phí: 200 VND × 1 đơn = 200 VND (vs VNPay 8tr × 1.5% = 120.000 VND)
Tiết kiệm 99.8% phí.
Cái gì có thể sai
| Vấn đề | Triệu chứng | Cách fix |
|---|---|---|
| Khách chuyển khoản nhưng không nhận noti | Casso link bank bị disconnect | Re-link account Casso, set webhook URL đúng |
| Webhook bị fake (đơn ship hàng nhưng không có tiền) | Không verify secret | Implement timing-safe compare + check transaction id unique |
| VNPay redirect about return URL sai | Config trong VNPay merchant portal | Match exactly vnp_ReturnUrl trong API call |
| Double charge customer | Không idempotent check | Add unique constraint trên transaction_id |
| Stripe payout chậm 7-14 ngày | Account mới hoặc risk flag | KYC đầy đủ + verify identity |
| MoMo callback timeout | Server bạn xử lý > 5s | Push job vào queue + trả 200 ngay |
| FX rate Stripe cao 4-5% | Default Stripe FX | Connect Wise bank account để FX rate thấp hơn |
| Khách phàn nàn không có MoMo | Demographic Gen Z | Add MoMo dù phí cao hơn — UX justifies |
Tóm tắt 1 dòng
4 lựa chọn VN: VNPay (cổng thẻ + IB, 1.1-1.65%, UX 1-click) — default cho ecommerce mass. MoMo (ví Gen Z, 1.1-2.2%) — pair VNPay cho coverage tối đa. Casso (auto-reconcile bank, 200-500đ/giao dịch) — best cho B2B AOV cao, tiết kiệm 50-100x phí. Stripe (quốc tế, cần Atlas LLC) — SaaS bán USD. Stack tốt nhất 2026 cho ecommerce VN: VNPay + MoMo + Casso (backup). Verify webhook bằng timing-safe compare + idempotency check trên transaction_id.
Đọc tiếp
- Webhook là gì — cách Casso, Stripe, Zalo "gõ cửa" web của bạn — payment dùng webhook để notify status
- API là gì? Tại sao mọi app, mọi web hiện đại đều cần — gateway cung cấp REST API tích hợp
- HTTPS, SSL, TLS — vì sao web không có ổ khoá xanh thì khách bỏ chạy — payment URL bắt buộc HTTPS
- No-code vs Low-code vs Custom code — chọn đường nào theo budget — Shopify có payment built-in, custom code cần integrate