VietQR Payment Automation for AI Agents
The Problem: AI Agents Need Direct Bank Payments in Vietnam
You've built an AI agent that sells courses, processes café orders, or handles micro-transactions. It works flawlessly in the US, where Stripe handles everything. But when your Vietnamese users try to pay, they hit a wall: Stripe doesn't accept VietQR—the national QR standard that 99% of Vietnamese banks support. Your agent sits idle, unable to collect payment.
You're not alone. Every AI builder targeting Vietnam faces the same choice: integrate a fragmented patchwork of local payment gateways, or abandon the market entirely. There's been no standard way for autonomous systems to request and verify VietQR payments until now.
Enter AgentPay VN: an MIT-licensed Python SDK that lets AI agents request VietQR payments directly, pointing straight to your merchant bank account—no middleman holding your money.
Why AgentPay VN, Not Stripe or Local Gateways?
The Hidden Costs of Alternatives
Stripe in Vietnam: - ❌ Does not support VietQR (the payment method 95%+ of Vietnamese users prefer) - ❌ Requires complex pre-approval for Vietnam operations - ❌ Higher fees for cross-border settlement (2–3% + FX margin) - ❌ Integrations take 2–4 weeks of back-and-forth
Local Vietnamese Payment Gateways (Zalopay, Momo, etc.): - ❌ Each requires separate API documentation and contract - ❌ Fragmented wallets (users must install multiple apps) - ❌ Less suitable for AI agents (built for web checkout, not autonomous systems) - ❌ Slower settlement (T+2 or later)
AgentPay VN:
- ✅ Native VietQR support—use the payment method users already have
- ✅ Open-source (MIT), so you own the integration
- ✅ Zero money custody—QR points directly to your bank account
- ✅ Instant bank feed confirmation of payment
- ✅ Built specifically for AI agents and autonomous systems
- ✅ One-line install: pip install agentpay-vn
How AgentPay VN Works: The 3-Step Flow
Unlike traditional payment gateways that hold funds and manage reconciliation, AgentPay VN is deliberately simple:
- Your AI agent creates a payment request (amount, description, metadata)
- AgentPay generates a VietQR code and checkout URL pointing to your merchant account
- Your agent awaits a bank settlement confirmation via real-time bank feed
That's it. No intermediate accounts. No settlement delays. No surprise disputes.
Installation & Setup (5 Minutes)
Step 1: Install the SDK
pip install agentpay-vn
Step 2: Configure Your Merchant Bank Account
You'll need:
- A Vietnamese bank account (most major banks supported: Vietcombank, Techcombank, VPBank, etc.)
- Bank account holder name
- Bank account number
- Bank code (e.g., 970010 for Vietcombank)
Store these securely in environment variables:
export AGENTPAY_MERCHANT_NAME="Your Business Name"
export AGENTPAY_BANK_ACCOUNT="1234567890"
export AGENTPAY_BANK_CODE="970010" # Vietcombank
Step 3: Verify Your Setup
from agentpay_vn import AgentPayClient
client = AgentPayClient()
status = client.verify_merchant()
print(f"Merchant verified: {status.is_active}")
Building Your First AI Agent Payment Flow
Real-World Scenario: AI Tutoring Bot
Imagine an AI tutoring chatbot that helps Vietnamese students practice English. A student asks to unlock premium lessons (₫50,000 = ~$2 USD). The agent should:
- Generate a unique payment request
- Show the user a VietQR code to scan
- Wait for bank confirmation
- Unlock the content
Here's how your agent does it:
from agentpay_vn import AgentPayClient, PaymentRequest
import uuid
import time
from datetime import datetime
# Initialize the client (reads env variables automatically)
client = AgentPayClient()
def create_premium_unlock(student_id: str, course_title: str) -> dict:
"""
AI agent function to request payment for course unlock.
"""
# Step 1: Create a unique payment request
request_id = f"course_{student_id}_{uuid.uuid4().hex[:8]}"
payment = PaymentRequest(
request_id=request_id,
amount_vnd=50000, # ₫50,000
description=f"Premium access: {course_title}",
merchant_reference=student_id, # Link to student DB
metadata={
"course_id": course_title,
"student_email": "student@example.com",
"timestamp": datetime.utcnow().isoformat()
},
expires_in_seconds=600 # QR valid for 10 minutes
)
# Step 2: Generate VietQR checkout
qr_response = client.create_payment_request(payment)
return {
"request_id": request_id,
"qr_code_url": qr_response.qr_image_url, # PNG or SVG
"checkout_url": qr_response.checkout_url, # For mobile web
"amount": payment.amount_vnd,
"expires_at": qr_response.expires_at
}
def wait_for_payment_settlement(request_id: str, timeout_seconds: int = 300) -> bool:
"""
AI agent polls for payment confirmation.
In production, use webhooks instead of polling.
"""
start_time = time.time()
while time.time() - start_time < timeout_seconds:
settlement = client.await_settlement(request_id)
if settlement.is_settled:
print(f"✅ Payment confirmed! Amount: ₫{settlement.amount_received}")
print(f" Bank reference: {settlement.bank_transaction_id}")
return True
if settlement.is_expired:
print("❌ QR code expired. Request new payment.")
return False
# Check every 2 seconds
time.sleep(2)
print("⏱️ Payment timeout. User may still pay within bank window.")
return False
# Usage in your agent:
if __name__ == "__main__":
# Student requests premium access
payment_info = create_premium_unlock(
student_id="student_12345",
course_title="Advanced English Conversation"
)
print(f"📱 Ask user to scan QR code: {payment_info['qr_code_url']}")
print(f"🔗 Or open in mobile: {payment_info['checkout_url']}")
print(f"⏰ Valid until: {payment_info['expires_at']}")
# Wait for payment
if wait_for_payment_settlement(payment_info['request_id']):
print("🎉 Unlocking premium lessons...")
# Trigger your course unlock logic here
else:
print("💳 Payment failed. Please try again.")
Line-by-line explanation:
- Line 17–31: Create a
PaymentRequestobject with amount (in VND), description, and custom metadata for your database. Therequest_idis unique per transaction. - Line 33:
client.create_payment_request()generates a VietQR code (binary image) and a shareable checkout URL. - Line 42–67:
await_settlement()polls the bank feed. When the user scans and pays, AgentPay immediately confirms via the bank. Returnsis_settled = True. - Line 54–55: Bank confirms the exact amount received and provides a transaction ID for reconciliation.
Integrating AgentPay with Claude (MCP Server)
If you're using Claude as your AI backbone, use the AgentPay MCP (Model Context Protocol) server to give Claude native payment capabilities.
Configure Claude Desktop
Edit ~/.config/Claude/claude_desktop_config.json:
{
"mcpServers": {
"agentpay": {
"command": "python",
"args": ["-m", "agentpay_mcp"],
"env": {
"AGENTPAY_MERCHANT_NAME": "Your Business Name",
"AGENTPAY_BANK_ACCOUNT": "1234567890",
"AGENTPAY_BANK_CODE": "970010"
}
}
}
}
Now Claude Can Call Payment Tools Directly
Inside Claude, you can now say:
"Create a payment request for ₫100,000 for a course license, then wait for settlement."
Claude automatically:
1. Calls create_payment_request() via MCP
2. Generates the QR code
3. Shows it to the user
4. Polls await_settlement() until payment arrives
Real-World Walkthrough: AI Course-Selling Bot
Let's build a complete example: an AI bot that sells Vietnamese language courses.
Flow:
- User: "I want to buy the advanced Hanoi dialect course."
- Bot: "That's ₫150,000. Let me create a payment link for you."
- Bot: Generates VietQR, displays checkout URL
- User: Scans QR with their banking app, pays
- Bot: "Payment confirmed! Here's your course access link."
The Complete Code:
from agentpay_vn import AgentPayClient
from datetime import datetime
import json
class CourseBot:
COURSES = {
"hanoi_dialect": {"name": "Advanced Hanoi Dialect", "price": 150000},
"business_vn": {"name": "Business Vietnamese", "price": 200000},
"poetry": {"name": "Vietnamese Poetry", "price": 100000}
}
def __init__(self):
self.client = AgentPayClient()
def sell_course(self, course_key: str, user_id: str) -> dict:
course = self.COURSES[course_key]
# Create payment
qr = self.client.create_payment_request(
PaymentRequest(
request_id=f"course_{course_key}_{user_id}_{int(datetime.now().timestamp())}",
amount_vnd=course["price"],
description=f"Course: {course['name']}",
merchant_reference=user_id
)
)
# Return checkout details
return {
"course": course["name"],
"price": f"₫{course['price']:,}",
"qr_image": qr.qr_image_url,
"checkout_url": qr.checkout_url,
"request_id": qr.request_id
}
def confirm_purchase(self, request_id: str) -> bool:
settlement = self.client.await_settlement(request_id, timeout_seconds=300)
return settlement.is_settled
# Usage
bot = CourseBot()
payment = bot.sell_course("hanoi_dialect", "user_999")
print(f"Checkout ready: {payment['checkout_url']}")
if bot.confirm_purchase(payment["request_id"]):
print("✅ Course access granted!")
AgentPay vs. Alternatives: Quick Comparison
| Feature | AgentPay VN | Stripe | Zalopay | MoMo |
|---|---|---|---|---|
| VietQR Support | ✅ Native | ❌ No | ⚠️ Via QR | ⚠️ Via QR |
| Vietnam Bank Setup | ✅ Simple (bank account only) | ❌ Complex (approval needed) | ⚠️ Moderate | ⚠️ Moderate |
| Settlement Speed | ✅ Real-time | ⚠️ T+1 to T+2 | ⚠️ T+1 | ⚠️ T+1 |
| Custody Risk | ✅ None (direct to bank) | ⚠️ Medium (holds funds) | ⚠️ Medium | ⚠️ Medium |
| AI Agent Native | ✅ Yes | ⚠️ Web-first | ❌ Web-only | ❌ Web-only |
| Open Source | ✅ MIT | ❌ Proprietary | ❌ Proprietary | ❌ Proprietary |
| Monthly Fee | $0 | ⚠️ $29+ | ⚠️ ~1.5% | ⚠️ ~1.5% |
| Per-Transaction Fee | ~0.5–1.5% | 2.9% + $0.30 | 1.5–2.5% | 1.5–2.5% |
Do's and Don'ts
✅ DO
- Store merchant secrets in environment variables (not hardcoded)
- Use webhooks (not polling) in production to detect payment settlement
- Set a reasonable timeout (5–10 minutes) for QR expiration
- Log request_id and transaction_id for reconciliation
- Test with small amounts (₫1,000–₫10,000) before going live
❌ DON'T
- Hardcode bank account details in your repository
- Trust polling for high-frequency payments (use bank feeds / webhooks)
- Create multiple requests for the same order (reuse request_id until settled or expired)
- Assume settlement without bank confirmation (always check
is_settled) - Ignore QR expiration (always respect
expires_atand regenerate if needed)
FAQ
Q: Does AgentPay VN hold my money?
A: No. AgentPay VN never touches your funds. The QR code points directly to your merchant bank account. Your bank confirms the payment, and AgentPay relays that confirmation to your agent. Settlement is instant (within seconds, not hours).
Q: Which Vietnamese banks are supported?
A: All major banks that support VietQR, including Vietcombank (970010), Techcombank (970023), VPBank (970432), MB Bank (970422), Agribank (970405), and 30+ others. Check your bank code at napas.com.vn.
Q: Can I use AgentPay VN outside Vietnam?
A: Currently, AgentPay VN is optimized for Vietnam bank accounts. If you need to accept payments from international cards, combine it with a cross-border provider (e.g., for USD → VND conversion first).
Q: What if a customer scans the QR but doesn't complete payment?
A: The QR code expires (default 10 minutes). Your agent's await_settlement() will return is_expired = True. You can generate a new request and show a fresh QR code.
Q: How do I handle refunds?
A: Since AgentPay VN never holds funds, refunds are direct bank-to-bank transfers using your merchant account. You'd initiate the refund from your bank's API or dashboard (outside AgentPay).
Advanced: Webhook Integration for Production
Polling every 2 seconds works for demos, but in production, subscribe to bank settlement webhooks:
from agentpay_vn import AgentPayClient, WebhookHandler
client = AgentPayClient()
# Register your webhook endpoint
client.register_webhook(
url="https://your-domain.com/webhooks/agentpay",
events=["payment.settled", "payment.failed"]
)
# Your webhook handler
def handle_settlement_webhook(event):
if event["type"] == "payment.settled":
request_id = event["data"]["request_id"]
amount = event["data"]["amount"]
bank_ref = event["data"]["bank_transaction_id"]
# Unlock course, deliver digital product, etc.
print(f"Settled: {request_id} for ₫{amount}")
Webhooks eliminate polling latency and are 100x more efficient for high-volume agents.
Key Takeaways
- 🎯 AgentPay VN solves the "Vietnam payments for AI agents" problem that Stripe and local gateways leave unsolved
- 💰 Zero custody risk: money goes straight to your bank account; AgentPay only confirms settlement
- ⚡ 3-line implementation:
create_payment_request()→ show QR →await_settlement() - 🏦 All major Vietnamese banks supported, including Vietcombank, Techcombank, VPBank
- 🤖 MCP integration with Claude lets your AI agents request payments naturally
- 🔐 Open-source (MIT), so you control the code and security
- 📊 Real-world tested: tutoring bots, e-learning platforms, micro-transactions all working in Vietnam
Get Started Now
- Install:
pip install agentpay-vn - Read the docs: https://agentpay.servicesai.vn/v1/docs
- Explore the code: https://github.com/phuocdu/agentpay-vn
- Join the community: Star the repo, open issues, share your integrations
Your AI agents are ready to collect Vietnamese payments. Let's build.