AI Agent VietQR Payments in Python: Step-by-Step Guide
The Problem: Your AI Agent Needs to Get Paid
You've built a smart chatbot that sells online courses. It answers questions, builds trust, and users are ready to buy—but then they hit a wall. Your AI agent has no way to collect payment. You could bolt on Stripe or PayPal, but those charge 2-3% + fixed fees, add foreign exchange friction, and lock your Vietnamese customers into USD workflows. Even worse, you'd need to hold user funds temporarily, creating compliance headaches.
For Vietnamese merchants and global businesses serving Vietnam, there's a better way: VietQR—a bank-agnostic QR code standard that routes payments directly to your bank account in seconds. And now, your AI agent can handle the entire flow natively.
Enter AgentPay VN: an MIT-licensed Python SDK that lets any AI agent create VietQR payment requests, send checkout URLs, and confirm settlement—all without touching money. In this tutorial, you'll learn exactly how to make your Python agent a payment-collecting machine.
What Is AgentPay VN and Why Use It?
AgentPay VN is a lightweight open-source SDK + MCP server purpose-built for integrating VietQR payments into AI workflows. Here's what makes it different:
- No fund holding: QR codes point straight to your merchant bank account. AgentPay VN never touches money—it's a coordinator, not a wallet.
- Instant settlement: Bank feeds confirm payment in seconds to minutes, not days.
- AI-native: Works seamlessly with Claude, ChatGPT, and other LLM-based agents through the included MCP server.
- Python-first: Simple 3-line payment flow that's easy to reason about.
- MIT-licensed: Fully open source. No vendor lock-in.
Why this matters: Your AI agent can now say, "Great! Here's your payment link," collect the money, and fulfill the order—all in one conversation. No manual reconciliation. No payment gateway fees eating your margins. No currency conversion losses.
Getting Started: Installation and Basic Setup
Step 1: Install the SDK
Open your terminal and install AgentPay VN via pip:
pip install agentpay-vn
That's it. No environment variables, no complex initialization—yet.
Step 2: Understand the 3-Line Payment Flow
Before you write code, understand the mental model:
- create_payment_request – Generate a payment request with an amount, description, and merchant details.
- send checkout_url – Deliver that request as a clickable VietQR URL to your user.
- await_settlement – Listen for bank confirmation that the payment landed.
That's the entire cycle. Your agent asks for money, sends a link, waits for confirmation. Done.
Building Your First Payment-Enabled Agent
Real-World Example: A Vietnamese Language Course Bot
Imagine you're selling a 5-week Vietnamese language course for ₫500,000 (about $20 USD). A customer finishes the preview lesson and is ready to enroll. Here's how your agent handles it:
from agentpay_vn import PaymentClient, PaymentRequest
import asyncio
# Initialize the client with your merchant info
# In production, load these from environment variables
client = PaymentClient(
merchant_id="YOUR_MERCHANT_ID", # Your unique ID
merchant_name="Vietnamese Learning Co", # Display name
bank_account="1234567890", # Your bank account
bank_code="970432" # VietComBank (VCCB)
)
# Step 1: Create a payment request
payment_req = PaymentRequest(
amount=500000, # ₫500,000
description="5-week Vietnamese A1 course",
reference_id="course_001_user_jane", # Track this order
callback_url="https://yourdomain.com/webhook" # Optional: get notified
)
# Step 2: Generate the VietQR checkout URL
checkout_url = client.create_payment_request(payment_req)
print(f"Send this to the customer: {checkout_url}")
# Output: https://vietqr.io/checkout?token=abc123xyz...
# Step 3: Wait for settlement confirmation
async def wait_for_payment(request_id: str, timeout_seconds: 300):
settlement = await client.await_settlement(
request_id=request_id,
timeout=timeout_seconds
)
if settlement.confirmed:
print(f"✓ Payment confirmed! {settlement.amount} VND from {settlement.payer_name}")
# Trigger course enrollment
enroll_user_in_course("jane", "course_001")
return True
else:
print(f"✗ Payment expired or cancelled")
return False
# Run the async settlement check
result = asyncio.run(wait_for_payment("course_001_user_jane", timeout_seconds=600))
Line-by-line breakdown:
- Lines 1-2: Import the SDK and asyncio for non-blocking waits.
- Lines 5-9: Initialize with your merchant ID (from your bank), name, and bank account. The
bank_codeis standard: 970432 for Vietcombank, 970405 for Techcombank, etc. (Full list in docs.) - Lines 12-17: Create a
PaymentRequestobject. Theamountis in Vietnamese Dong (₫).reference_idis crucial—use it to match payments to orders in your system. - Lines 20-22: Generate the checkout URL. This is the link you send to the customer. It's a short-lived, one-time-use QR code.
- Lines 25-34: An async function that waits for the bank to confirm the payment.
await_settlementblocks until either the payment lands or the timeout expires (default 5 minutes). When confirmed, you trigger your business logic (enroll the user, send an API key, etc.). - Lines 37: Execute the payment wait. In a real agent, this runs in the background while your agent continues the conversation.
Error Handling and Edge Cases
In production, things go wrong. Here's a robust version:
from agentpay_vn import PaymentClient, PaymentRequest, SettlementError
async def safe_payment_flow(user_id: str, course_id: str, amount: int):
client = PaymentClient(
merchant_id="YOUR_MERCHANT_ID",
merchant_name="Vietnamese Learning Co",
bank_account="1234567890",
bank_code="970432"
)
try:
# Create request
req = PaymentRequest(
amount=amount,
description=f"Enrollment: {course_id}",
reference_id=f"{user_id}_{course_id}_{int(time.time())}"
)
url = client.create_payment_request(req)
# Wait for settlement (5-minute default timeout)
settlement = await client.await_settlement(
request_id=req.reference_id,
timeout=300
)
if settlement.confirmed:
return {"status": "success", "amount": settlement.amount}
else:
return {"status": "expired", "message": "User didn't pay in time"}
except SettlementError as e:
# Network issue, bank unreachable, etc.
return {"status": "error", "message": str(e)}
except ValueError as e:
# Invalid merchant config or request
return {"status": "invalid", "message": str(e)}
This wraps the payment flow in try-except blocks. If the bank feed is temporarily down, you'll catch it and retry.
Integrating with AI Agent Frameworks (MCP Server)
If you're using Claude or another agent that supports MCP (Model Context Protocol), AgentPay VN provides a drop-in MCP server. This lets your agent call payment functions just like any other tool.
Step 1: Start the MCP Server
agentpay-mcp --merchant-id YOUR_ID --bank-account 1234567890 --bank-code 970432
The server starts on stdio by default (compatible with Claude Desktop).
Step 2: Configure Claude to Use It
Edit your Claude Desktop config file:
macOS/Linux: ~/.config/Claude/claude_desktop_config.json
Windows: %APPDATA%\Claude\claude_desktop_config.json
{
"mcpServers": {
"agentpay-vn": {
"command": "agentpay-mcp",
"args": [
"--merchant-id", "YOUR_MERCHANT_ID",
"--bank-account", "1234567890",
"--bank-code", "970432",
"--callback-url", "https://yourdomain.com/webhook"
],
"env": {
"LOG_LEVEL": "info"
}
}
}
}
Restart Claude. It will now have three new tools:
- create_payment_request(amount, description, reference_id)
- get_payment_status(reference_id)
- await_settlement(reference_id, timeout_seconds)
Now your agent can natively handle payments in conversation:
User: "I want to buy the advanced course."
Agent: "Great! That's ₫750,000. Let me create a payment request for you."
[Agent calls create_payment_request tool]
Agent: "Here's your payment link: [QR code URL]. Scan it with any banking app. I'll confirm once the payment lands."
[Agent calls await_settlement tool]
Agent: "✓ Payment received! I'm adding you to the course now. You'll get an email with your login in 2 minutes."
Do's and Don'ts: Best Practices
| ✅ Do | ❌ Don't |
|---|---|
Use unique reference_id for each order (include user ID + timestamp) |
Reuse the same reference_id for multiple payments |
| Store the checkout URL in your database before sending it | Assume the URL is permanent; generate fresh ones per request |
| Set timeout to 5-10 minutes for user-initiated payments | Use a 60+ minute timeout (users expect instant feedback) |
| Log settlement confirmations for reconciliation | Trust in-memory state; always persist to a database |
Handle SettlementError exceptions explicitly |
Let errors crash your agent silently |
| Load merchant ID and bank account from env vars in production | Hardcode credentials in source code |
| Implement idempotency: check if order already exists before creating a new request | Create duplicate payment requests on network retry |
Advanced: Webhook Notifications
Instead of polling with await_settlement, you can register a webhook to get instant notifications:
from agentpay_vn import PaymentRequest
payment_req = PaymentRequest(
amount=500000,
description="Course enrollment",
reference_id="user_123_course_a",
callback_url="https://yourdomain.com/agentpay/webhook" # Your endpoint
)
url = client.create_payment_request(payment_req)
When the payment settles, AgentPay VN will POST a signed JSON payload to your webhook:
{
"event": "settlement_confirmed",
"reference_id": "user_123_course_a",
"amount": 500000,
"payer_bank": "vietcombank",
"payer_name": "Jane Tran",
"timestamp": "2025-01-15T10:32:00Z",
"signature": "hmac_sha256_signature"
}
Verify the signature using your merchant secret (provided on setup) and process the order. This is faster and more reliable than polling for high-volume scenarios.
Walkthrough: Building a Café Ordering Bot
Let's imagine a Vietnamese coffee café in HCMC that uses an AI agent to handle online orders:
- Customer starts chat: "I'd like 2 iced coffees and a pastry."
- Agent confirms order: "That's 2 x Cà Phê Đá (35K) + 1 x Croissant (45K) = 115,000 VND. Ready to pay?"
- Agent creates payment request for ₫115,000 with
reference_id="order_cafe_2025_0115_001". - Agent sends QR code: "Scan this with your banking app to pay."
- Customer scans and pays via their bank app (VietComBank, Techcombank, etc.). The money goes directly to the café's account.
- Bank confirms settlement in 15-30 seconds. AgentPay VN receives the confirmation.
- Agent confirms: "✓ Payment received! Your order will be ready in 10 minutes. Pickup at counter A."
- Agent logs the order to the café's kitchen system and sends an SMS.
No payment processor. No fees. No fraud risk. Money lands straight in the café's account.
FAQ
Q: Does AgentPay VN hold my money?
A: Absolutely not. AgentPay VN never touches user funds. The VietQR code points directly to your bank account. AgentPay VN only coordinates the request and confirms settlement. Your bank holds the money for 0-2 business days (standard settlement), not AgentPay VN.
Q: What if a payment fails or times out?
A: If the customer doesn't pay within the timeout (default 5 minutes), await_settlement returns confirmed=False. You can then offer to regenerate a new payment link or suggest alternative payment methods. No money is charged.
Q: Which banks does AgentPay VN support?
A: It works with any Vietnamese bank that supports VietQR (the standard QR code format). That includes Vietcombank, Techcombank, ACB, Agribank, VP Bank, and 40+ others. Use the bank code (e.g., 970432 for Vietcombank) when initializing the client.
Q: Can I use AgentPay VN for international agents (like GPT-4)?
A: Yes! The Python SDK works anywhere. The MCP server works with any agent that supports MCP (Claude, upcoming integrations). If you're building a custom agent, just call the SDK—no framework required.
Key Takeaways
- AgentPay VN is a lightweight payment coordinator for AI agents selling to Vietnamese customers. It never holds money; QR codes route payments to your bank.
- Installation is 1 command (
pip install agentpay-vn). Setup is 4 lines of Python code. - The payment flow is 3 steps: create request → send URL → await confirmation. Timeouts are short (5 minutes default), keeping UX snappy.
- MCP integration lets Claude and similar agents handle payments natively with no custom tooling.
- VietQR settlement is fast (15-30 seconds typically) and your bank account receives the funds directly, with no foreign exchange friction.
- Best practice: use unique reference IDs, store URLs in your database, handle errors explicitly, and load secrets from environment variables.
Get Started Now
Your AI agent can accept VietQR payments today. Here's how:
-
Install the SDK:
bash pip install agentpay-vn -
Grab your merchant ID from your bank or sign up at https://agentpay.servicesai.vn/v1/docs.
-
Follow the examples above in your agent code or MCP config.
-
Read the full docs at https://agentpay.servicesai.vn/v1/docs for bank codes, webhook signatures, and more.
-
Contribute or report issues on GitHub: https://github.com/phuocdu/agentpay-vn.
Your AI agent is now a payment-collecting machine. Go build something incredible.