Add VietQR Checkout to Your LLM Agent in 10 Minutes
The Problem: Your AI Agent Can't Actually Get Paid
Imagine you've built a conversational AI that helps Vietnamese customers book services, enroll in courses, or buy products. The bot engages brilliantly, answers every question, and guides users to the checkout screen—but then what? The conversation ends. The agent has no way to collect payment directly. You're stuck exporting leads or building a separate payment layer that breaks the conversational flow.
This friction costs money. Studies show that 30–40% of users abandon purchases when forced to leave their current interface. For AI-first businesses in Vietnam, this gap between agent capability and payment integration has been a real blocker.
AgentPay VN solves this by embedding a checkout tool directly into your LLM agent—no separate payment page, no redirects, no friction. In the next 10 minutes, you'll have a working payment flow.
Why AgentPay VN? The Three Core Promises
Before we code, let's clarify what makes AgentPay VN different:
1. Never Holds Your Money AgentPay VN is a thin orchestration layer. When you create a payment request, the generated VietQR code points directly at your merchant bank account. The money never touches AgentPay's systems. Your bank's payment feed confirms settlement in real time.
2. Open Source & Transparent MIT license. Full code on GitHub. No surprise fees, no vendor lock-in. You control the entire flow—run it locally, self-host the MCP server, audit every line.
3. Built for AI Agents It's not a Shopify plugin or a payment gateway API. AgentPay VN ships as a Python SDK and as an MCP (Model Context Protocol) server. Claude, local LLMs, your custom agents—they all integrate in seconds.
Installation & Setup (2 Minutes)
Step 1: Install the SDK
pip install agentpay-vn
Verify the install:
python -c "import agentpay_vn; print(agentpay_vn.__version__)"
Step 2: Get Your Merchant Info
You'll need:
- Merchant ID: Your business account identifier (provided by your bank or AgentPay dashboard)
- Bank Account Number: The account where payments land
- Bank Code: VietQR bank code (e.g., 970436 for Techcombank, 970422 for Vietinbank)
If you don't have these yet, visit AgentPay VN Docs to register.
Step 3: Initialize Your Agent
Create a file called agent.py:
from agentpay_vn import AgentPayClient
# Initialize the client with your merchant details
client = AgentPayClient(
merchant_id="YOUR_MERCHANT_ID",
bank_account="123456789",
bank_code="970436"
)
print("✓ AgentPay initialized. Ready to accept payments.")
Run it:
python agent.py
You should see the success message. You're done with setup.
The 3-Line Payment Flow
AgentPay VN distills payment collection into three steps:
Step 1: Create a Payment Request
from agentpay_vn import AgentPayClient
import time
client = AgentPayClient(
merchant_id="YOUR_MERCHANT_ID",
bank_account="123456789",
bank_code="970436"
)
# Step 1: Create the payment request
payment = client.create_payment_request(
amount=250000, # VND
description="Online course: Python Mastery",
reference_id=f"course_order_{int(time.time())}", # Unique order ID
customer_name="Nguyễn Văn A",
customer_phone="0912345678"
)
print(f"Payment request created: {payment.id}")
print(f"Checkout URL: {payment.checkout_url}")
What's happening:
- amount: Price in VND (Vietnamese Dong). No decimals—250,000 VND for a course.
- reference_id: Your internal order ID. Use this to track the payment in your database.
- customer_name & customer_phone: Metadata sent with the QR. Optional but useful for reconciliation.
- Return value: A Payment object with id and checkout_url.
Step 2: Send the Checkout URL to Your User
In your LLM agent conversation:
# Inside your agent's response handler
if user_confirms_purchase:
payment = client.create_payment_request(
amount=250000,
description="Online course: Python Mastery",
reference_id=f"course_order_{user_id}_{int(time.time())}",
customer_name=user_name,
customer_phone=user_phone
)
# Send the checkout URL in the agent's message
agent_message = (
f"Great! Your course is ready. "
f"Scan this QR to pay 250,000 VND:\n\n"
f"{payment.checkout_url}"
)
print(agent_message)
# Store the payment ID for later confirmation
store_payment_id(user_id, payment.id)
The checkout_url is a dynamic QR code. The user scans it with their bank app → instant bank transfer → payment confirmed.
Step 3: Wait for Settlement
# Poll for settlement (or use webhook)
import time
payment_id = "payment_abc123"
max_wait = 600 # Wait up to 10 minutes
start_time = time.time()
while time.time() - start_time < max_wait:
status = client.await_settlement(payment_id)
if status.is_settled:
print(f"✓ Payment confirmed! Amount: {status.amount} VND")
# Unlock course access, send confirmation email, etc.
unlock_user_course(user_id)
break
print(f"Waiting for payment... (elapsed: {time.time() - start_time:.0f}s)")
time.sleep(3) # Check every 3 seconds
else:
print("Payment timeout. User will retry.")
Key detail: await_settlement is not a blocking call. It checks the bank feed and returns the current status. In production, use webhooks (AgentPay can POST to your server when payment arrives) to avoid polling.
Real-World Example: A Course-Selling Agent
Let's build a realistic scenario: a conversational bot that sells online Python courses.
from agentpay_vn import AgentPayClient
import json
import time
from datetime import datetime
client = AgentPayClient(
merchant_id="DEMO_MERCHANT",
bank_account="123456789",
bank_code="970436"
)
# Course catalog
COURSES = {
"python101": {"name": "Python 101: Beginner", "price": 150000},
"django": {"name": "Django Web Dev", "price": 350000},
"fastapi": {"name": "FastAPI Advanced", "price": 450000}
}
def agent_conversation(user_id, user_name, user_phone):
"""
Simulates an agent collecting payment.
In reality, this would be Claude or another LLM.
"""
print(f"Agent: Hi {user_name}! What course interests you?")
print("Available: python101, django, fastapi")
# User selects a course
selected_course = "django"
course_info = COURSES[selected_course]
print(f"Agent: Great choice! {course_info['name']} is 10 weeks, includes projects and mentoring.")
print(f"Price: {course_info['price']:,} VND. Ready to enroll?")
# User confirms
user_confirms = True
if user_confirms:
# Create payment
payment = client.create_payment_request(
amount=course_info["price"],
description=f"Course enrollment: {course_info['name']}",
reference_id=f"{user_id}_{selected_course}_{int(time.time())}",
customer_name=user_name,
customer_phone=user_phone
)
print(f"\nAgent: Perfect! Scan this QR to complete your payment:\n")
print(f"{payment.checkout_url}\n")
# Wait for payment (simplified)
print("Waiting for bank confirmation...")
start = time.time()
while time.time() - start < 60: # Wait 1 minute max
status = client.await_settlement(payment.id)
if status.is_settled:
print(f"\n✓ Payment received! {status.amount:,} VND confirmed.")
print(f"Agent: Enrollment complete! Welcome to {course_info['name']}.")
print(f"Check your email for login credentials and course materials.")
# Log the transaction
log_transaction(user_id, selected_course, status.amount, datetime.now())
return True
time.sleep(2)
print("Payment timeout. Please try again.")
return False
def log_transaction(user_id, course_id, amount, timestamp):
"""Record the transaction in your database."""
record = {
"user_id": user_id,
"course_id": course_id,
"amount_vnd": amount,
"timestamp": timestamp.isoformat()
}
print(f"Logged: {json.dumps(record)}")
# Run the agent
agent_conversation(
user_id="user_123",
user_name="Trần Thị B",
user_phone="0987654321"
)
Output:
Agent: Hi Trần Thị B! What course interests you?
Available: python101, django, fastapi
Agent: Great choice! Django Web Dev is 10 weeks, includes projects and mentoring.
Price: 350,000 VND. Ready to enroll?
Agent: Perfect! Scan this QR to complete your payment:
https://agentpay.servicesai.vn/checkout/pay_xyz789...
Waiting for bank confirmation...
✓ Payment received! 350,000 VND confirmed.
Agent: Enrollment complete! Welcome to Django Web Dev.
Check your email for login credentials and course materials.
Logged: {"user_id": "user_123", "course_id": "django", "amount_vnd": 350000, "timestamp": "2024-12-20T14:30:15.123456"}
Connecting to Claude with MCP
If you're using Claude or another LLM via the Model Context Protocol, no need to build custom agent code. AgentPay ships an MCP server.
Install the MCP Server
pip install agentpay-mcp
Configure Claude
Add to your Claude client config (e.g., ~/.claude/config.json or environment):
{
"mcp_servers": [
{
"name": "agentpay",
"command": "agentpay-mcp",
"env": {
"AGENTPAY_MERCHANT_ID": "YOUR_MERCHANT_ID",
"AGENTPAY_BANK_ACCOUNT": "123456789",
"AGENTPAY_BANK_CODE": "970436"
}
}
]
}
Restart Claude. Now Claude has access to:
- agentpay.create_payment_request(amount, description, reference_id, customer_name, customer_phone)
- agentpay.await_settlement(payment_id)
- agentpay.get_payment_status(payment_id)
Ask Claude: "Help me sell a course for 500,000 VND and collect payment." Claude will orchestrate the entire flow without you writing additional code.
Best Practices: Do's and Don'ts
| ✓ Do | ✗ Don't |
|---|---|
Store reference_id in your database before showing the QR |
Reuse the same reference_id for multiple payments |
| Use webhooks in production (avoid polling) | Poll more than every 2 seconds; you'll hit rate limits |
| Set a reasonable timeout (5–10 min) for user payment | Wait indefinitely; expire abandoned payments after 15 min |
| Include customer metadata (name, phone) for audits | Leave customer fields empty; you'll lose reconciliation data |
| Test with your actual merchant account first | Go live without testing settlement flow end-to-end |
| Handle both settled and failed payments gracefully | Assume all payments succeed; always check is_settled |
FAQ
Q: Does AgentPay VN hold my money? No. The VietQR code points directly to your merchant bank account. Your bank receives and confirms the transfer. AgentPay only orchestrates; it never touches the funds.
Q: Can I use this with Gemini, GPT-4, or local LLMs? Yes. Via MCP, any LLM that supports the Model Context Protocol can call AgentPay. You can also call the Python SDK directly from any agent framework (Langchain, AutoGen, etc.).
Q: How do I know when payment arrives?
Two options:
1. Polling (quick setup): Call await_settlement(payment_id) every few seconds.
2. Webhooks (production): AgentPay POSTs to your endpoint when bank confirms payment. See docs for webhook setup.
Q: What if a user scans the QR but doesn't have enough balance?
Their bank app will reject the transaction. await_settlement will return is_settled=False. Your agent can prompt them to retry or choose a lower-priced option.
Q: Can I accept international payments (not VND)? Currently, AgentPay VN is optimized for VietQR (Vietnamese domestic transfers). International support is on the roadmap.
Key Takeaways
- AgentPay VN eliminates the payment-agent gap: Customers complete purchases without leaving the conversation.
- Three-line flow:
create_payment_request→ user scans QR →await_settlementconfirms. - Money flows directly to your bank: No escrow, no holding periods, no surprise fees.
- Open source + MCP integration: Works with Claude, local LLMs, and custom agents.
- Real-time settlement: Bank transfer confirms in seconds; your agent responds immediately.
- Built-in customer metadata: Automatic reconciliation with order IDs, names, and phone numbers.
Get Started Now
You've got everything you need to add payments to your agent in the next 10 minutes.
Next steps:
- Install:
pip install agentpay-vn - Explore examples: Visit the GitHub repo for more sample agents and configurations.
- Read the full docs: AgentPay VN Docs cover webhooks, error handling, multi-currency flows, and testing.
- Join the community: Share your agent builds on GitHub Discussions. Report issues. Contribute.
Your conversational commerce engine is ready. Build something amazing.