AI Agents Accept VietQR Payments in Python – AgentPay VN
The Problem: Your AI Agent Needs Real Money
You've built an impressive AI agent—maybe it's a course-selling chatbot, a ticket reservation system, or a service marketplace. Users love it. But when it comes time to collect payment, you hit a wall.
Your options are grim: - Integrate Stripe or PayPal? Complex, slow, and fees eat 3-5% of every transaction. - Build custom bank integration? That's weeks of compliance work, PCI audits, and infrastructure headaches. - Use a payment processor that holds your money? Now you're managing settlement delays and trust issues.
What if your AI agent could accept payments instantly, directly into your bank account, with zero holding periods? That's what AgentPay VN solves.
AgentPay VN is an open-source Python SDK (MIT license) that turns your AI agent into a payment collector using VietQR—Vietnam's unified QR payment standard. The magic: the QR code points straight at your merchant bank account. No middleman. No held funds. A bank feed confirms settlement in real time.
Why VietQR? Why Now?
VietQR is infrastructure that's already everywhere in Vietnam. Over 60 million users, all major banks participating, and near-instant settlement. If you're building for Vietnam or serving Vietnamese customers, this is the payment highway you didn't know you needed.
But integrating VietQR yourself is painful—EMV QR specs, checksum algorithms, bank API quirks. AgentPay VN handles all that. You focus on your agent logic.
Architecture: How AgentPay VN Works
AgentPay VN sits at the intersection of three things:
- Python SDK: A lightweight library (
agentpay-vn) that wraps VietQR payment request creation and settlement tracking. - MCP Server: A Claude AI integration layer that lets your Claude instance directly call payment operations.
- Bank Settlement: A webhook-based feed that confirms when money arrives—no polling, no guessing.
The three-line flow looks deceptively simple:
create_payment_request() → send_checkout_url_to_user() → await_settlement()
But behind that simplicity is rock-solid cryptography, bank-compliant QR generation, and settlement verification.
Getting Started: Installation & Setup
Step 1: Install the SDK
Open your terminal and run:
pip install agentpay-vn
That's it. No complex dependencies, no C extensions. Pure Python, ready to import.
Step 2: Configure Your Merchant Credentials
You'll need: - Merchant ID: Assigned by your VietQR provider (or test ID if using sandbox). - API Key: Your secret key (keep this in an environment variable, not in Git). - Settlement account details: Your bank account number and bank code.
Store these in a .env file:
AGENTPAY_MERCHANT_ID=your_merchant_id
AGENTPAY_API_KEY=your_api_key
AGENTPAY_BANK_ACCOUNT=your_account_number
AGENTPAY_BANK_CODE=970 # VCB, for example
Step 3: Load Credentials in Python
import os
from dotenv import load_dotenv
load_dotenv()
MERCHANT_ID = os.getenv("AGENTPAY_MERCHANT_ID")
API_KEY = os.getenv("AGENTPAY_API_KEY")
Now you're ready to create payments.
Building Your First Payment Flow
Let's build a concrete example: an online course platform where users pay via VietQR to unlock lessons.
Step 1: Create a Payment Request
from agentpay_vn import AgentPayClient
# Initialize the AgentPay client
client = AgentPayClient(
merchant_id=MERCHANT_ID,
api_key=API_KEY,
bank_account="1234567890",
bank_code="970" # Vietcombank
)
# Create a payment request for a course purchase
payment = client.create_payment_request(
amount=299000, # 299,000 VND (typical course price)
description="Advanced Python Course Access",
order_id="course_py_advanced_001",
customer_email="student@example.com",
expiry_minutes=30 # QR code valid for 30 minutes
)
print(f"QR Code URL: {payment.qr_code_url}")
print(f"Checkout Link: {payment.checkout_url}")
print(f"Payment ID: {payment.payment_id}")
What's happening here:
create_payment_request(): Generates a VietQR payment request with your merchant details baked in.amount: Always in VND (Vietnamese Dong). No currency conversion headaches.order_id: Your internal identifier. Essential for matching settlements.expiry_minutes: QR code self-destructs after 30 minutes—security + UX.qr_code_url&checkout_url: Two flavors. QR for mobile, checkout URL for web.
Step 2: Send the Checkout URL to Your User
def send_checkout_to_user(user_email, payment):
"""Send the payment checkout link via email."""
email_body = f"""
Hi there!
Your course is ready. Click below to pay:
{payment.checkout_url}
Or scan this QR code with your banking app:
{payment.qr_code_url}
Payment expires in 30 minutes.
"""
# Your email service (sendgrid, ses, mailgun)
send_email(to=user_email, body=email_body)
return payment.payment_id
# Trigger it when a user clicks "Enroll"
payment_id = send_checkout_to_user(
"student@example.com",
payment
)
Step 3: Await Settlement Confirmation
Now the tricky part: you need to know when money actually lands in your account.
import asyncio
from agentpay_vn import await_settlement
async def monitor_payment(payment_id, max_wait_seconds=1800):
"""
Poll for settlement confirmation.
Returns True if settled, False if timeout/failed.
"""
try:
settlement = await await_settlement(
payment_id=payment_id,
client=client,
timeout_seconds=max_wait_seconds
)
if settlement.status == "settled":
print(f"✓ Payment {payment_id} settled!")
print(f" Amount: {settlement.amount} VND")
print(f" Bank ref: {settlement.bank_reference}")
# Update your database: mark course as PAID
grant_course_access(payment.customer_email)
return True
except TimeoutError:
print(f"✗ Payment {payment_id} not settled within timeout.")
return False
# In your main agent loop
if __name__ == "__main__":
asyncio.run(monitor_payment(payment_id))
Key insight: This is async and non-blocking. Your agent doesn't freeze waiting for settlement. You can serve other users while monitoring backgrounds.
Integrating with Claude via MCP
If you're using Claude as your AI backbone, AgentPay VN ships with an MCP server. This lets Claude directly invoke payment operations without you writing any glue code.
Install the MCP Server
pip install agentpay-mcp
Configure Claude to Use AgentPay MCP
In your Claude configuration (or Claude Desktop config), add:
{
"mcpServers": {
"agentpay": {
"command": "python",
"args": ["-m", "agentpay_mcp"],
"env": {
"AGENTPAY_MERCHANT_ID": "your_merchant_id",
"AGENTPAY_API_KEY": "your_api_key",
"AGENTPAY_BANK_ACCOUNT": "1234567890",
"AGENTPAY_BANK_CODE": "970"
}
}
}
}
Now Claude can run natural-language payment flows:
User: "I want to enroll in the Python course. How much does it cost?"
Claude (internally): 1. Creates payment request via MCP 2. Generates QR code 3. Sends URL to user 4. Monitors settlement in background 5. Confirms to user: "Payment processed! Lessons unlocked."
Real-World Walkthrough: An Online Café Shop
Let's build a Vietnamese café that takes online orders with VietQR payments.
The Scenario
- Customer visits a chatbot, orders 1 iced coffee (45,000 VND) + 1 milk tea (50,000 VND)
- Total: 95,000 VND
- They want instant confirmation before heading to the shop
The Code
from agentpay_vn import AgentPayClient
import asyncio
class CafeOrderBot:
def __init__(self, merchant_id, api_key):
self.client = AgentPayClient(
merchant_id=merchant_id,
api_key=api_key,
bank_account="9999999999",
bank_code="970"
)
self.pending_orders = {}
def create_order(self, customer_id, items, phone):
"""Create an order and generate payment QR."""
total = sum(item["price"] for item in items)
payment = self.client.create_payment_request(
amount=total,
description=f"Cafe Order: {', '.join(i['name'] for i in items)}",
order_id=f"cafe_order_{customer_id}_{int(time.time())}",
customer_email=phone, # Use phone as identifier
expiry_minutes=15
)
self.pending_orders[payment.payment_id] = {
"customer_id": customer_id,
"items": items,
"total": total,
"phone": phone
}
return payment
async def wait_for_payment(self, payment_id):
"""Wait for payment, then confirm order."""
try:
settlement = await self.client.await_settlement(
payment_id=payment_id,
timeout_seconds=900 # 15 minutes
)
if settlement.status == "settled":
order = self.pending_orders[payment_id]
print(f"✓ Order confirmed for {order['phone']}")
print(f" Items: {[i['name'] for i in order['items']]}")
print(f" Total: {order['total']} VND")
# Notify shop: print order ticket
self.print_order_ticket(order)
return True
except Exception as e:
print(f"Payment failed: {e}")
return False
def print_order_ticket(self, order):
"""Send to kitchen printer."""
ticket = f"""
========== CAFE ORDER ==========
Customer: {order['phone']}
{chr(10).join(f"- {item['name']}: {item['price']} VND" for item in order['items'])}
TOTAL: {order['total']} VND
Status: PAID ✓
================================
"""
print(ticket)
# In production: send to POS system
# Usage
bot = CafeOrderBot(MERCHANT_ID, API_KEY)
# Customer interaction
payment = bot.create_order(
customer_id="cust_123",
items=[
{"name": "Iced Coffee", "price": 45000},
{"name": "Milk Tea", "price": 50000}
],
phone="0901234567"
)
print(f"Pay here: {payment.checkout_url}")
# Backend waits for settlement
result = asyncio.run(bot.wait_for_payment(payment.payment_id))
Do's and Don'ts
| ✅ Do | ❌ Don't |
|---|---|
Store payment_id in your database for reconciliation |
Assume payment succeeded without calling await_settlement() |
| Use environment variables for API keys | Hardcode credentials in source code |
Set realistic expiry_minutes (15-30) |
Leave QR codes open indefinitely (security risk) |
| Log settlement confirmations for audit | Forget to update your database on settlement |
| Test with sandbox credentials first | Go live without testing the full flow |
| Implement exponential backoff on API retries | Hammer the API with polling every 100ms |
Advanced Tips
Webhook Settlement Confirmation
Instead of polling with await_settlement(), you can register a webhook. AgentPay will POST to your endpoint when money lands:
client.register_webhook(
url="https://yoursite.com/webhooks/agentpay",
events=["settlement.confirmed"]
)
# In your Flask/FastAPI app:
@app.post("/webhooks/agentpay")
def handle_settlement(payload):
payment_id = payload["payment_id"]
amount = payload["amount"]
bank_ref = payload["bank_reference"]
# Update your database immediately
mark_payment_settled(payment_id, amount, bank_ref)
return {"status": "ok"}
This is faster and more reliable than polling.
Handling Payment Failures
async def handle_failed_payment(payment_id):
"""Called if payment expires or is rejected."""
# Option 1: Generate a new QR with same order_id
payment = client.create_payment_request(
amount=order_amount,
order_id=original_order_id, # Same ID
expiry_minutes=30
)
# Option 2: Refund workflow
# Email customer: "Payment failed. Refund or retry?"
# Option 3: Free trial or grace period
# Grant temporary access, remind user to pay later
Multi-Currency Support (Future)
Currently AgentPay VN uses VND only. If you're selling globally:
# Get current USD->VND rate
usd_amount = 10 # $10 USD
vnd_rate = get_usd_to_vnd_rate() # e.g., 24500
vnd_amount = int(usd_amount * vnd_rate) # 245,000 VND
payment = client.create_payment_request(
amount=vnd_amount,
description=f"${usd_amount} USD Course Access",
order_id=order_id
)
FAQ
Q: Does AgentPay hold my money? No. The QR code points directly at your bank account. Settlement happens bank-to-bank. AgentPay only manages the request/confirmation flow.
Q: What if a payment fails midway?
You can re-generate a payment request with the same order_id. The system treats it as a retry, not a duplicate.
Q: Is the SDK production-ready? Yes. It's MIT licensed, open-source, and used in production by Vietnamese fintech startups. Check GitHub for latest releases and issues.
Q: Can I use this outside Vietnam? VietQR is Vietnam-only. If your users aren't in Vietnam or your bank isn't Vietnamese-registered, you'll need a different payment method.
Key Takeaways
- AgentPay VN is an open-source Python SDK that lets AI agents collect VietQR payments with zero payment holding.
- Installation is one command:
pip install agentpay-vn. - The flow is three steps:
create_payment_request()→ send URL →await_settlement(). - MCP integration lets Claude AI invoke payments directly without boilerplate.
- Real-world apps: course platforms, cafés, ticketing, freelance marketplaces—any agent that needs instant, verified payments.
- Security: Keep API keys in environment variables, use webhooks over polling, set QR expiry times.
- Bank settlement is confirmed via bank feed, not third-party APIs. You control the money flow.
Get Started Now
Your AI agent is ready to accept payments. Here's your next move:
-
Install AgentPay VN:
bash pip install agentpay-vn -
Read the full docs: https://agentpay.servicesai.vn/v1/docs
-
Explore the source code: https://github.com/phuocdu/agentpay-vn
-
Try the examples in the repo—they cover course platforms, e-commerce, and marketplace use cases.
Monetize your AI agents. Today.