AI Agent VietQR Payments in Python: Complete Guide
The Problem: AI Agents That Can't Actually Get Paid
You've built an impressive AI agent—maybe it sells online courses, manages a virtual café, or offers consulting services. Your Claude-powered chatbot charms customers, answers questions, and closes deals beautifully. But then comes the awkward moment: a customer says "I'm ready to pay," and your agent freezes. It has no way to collect money without you manually processing payments or routing users to a third-party checkout page.
This breaks the flow. The customer abandons the chat, opens a browser, and half the time, never comes back. Your agent becomes a glorified sales funnel instead of an autonomous business tool.
What if your AI agent could accept VietQR payments directly? No merchant account delays, no holding customer money, no third-party friction. Just a QR code that points straight to your bank account, settlement confirmation in seconds, and your agent continues the conversation.
That's exactly what AgentPay VN does.
What Is AgentPay VN?
AgentPay VN is an open-source (MIT license) Python SDK and MCP server that lets AI agents collect VietQR payments instantly. Here's what makes it different:
- Zero custody: AgentPay VN never touches customer money. The QR points directly to your merchant's bank account.
- Instant settlement confirmation: A bank feed integration tells your agent the moment payment arrives.
- AI-native: Designed for Claude and other AI agents via Model Context Protocol (MCP).
- 3-line flow:
create_payment_request→send_checkout_url→await_settlement—that's it. - MIT licensed: Fork it, modify it, deploy it however you need.
Whether you're in Hanoi, Ho Chi Minh City, or anywhere with Vietnamese banking, your AI agent can now be a full-service merchant.
Step 1: Install and Set Up AgentPay VN
Installation
Start with the Python package:
pip install agentpay-vn
This gives you the SDK. If you're also running the MCP server locally (for Claude Desktop or custom deployments), install that too:
pip install agentpay-mcp
Environment Setup
Your agent needs credentials to create payments. Create a .env file in your project:
AGENTPAY_MERCHANT_ID=your_merchant_id_here
AGENTPAY_BANK_ACCOUNT=your_vietqr_account
AGENTPAY_API_KEY=your_api_key_here
You'll get these from the AgentPay VN dashboard when you register. The merchant ID identifies your business; the bank account is your target VietQR-compatible account; the API key authenticates requests.
Load these in your Python code:
import os
from dotenv import load_dotenv
load_dotenv()
merchant_id = os.getenv('AGENTPAY_MERCHANT_ID')
bank_account = os.getenv('AGENTPAY_BANK_ACCOUNT')
api_key = os.getenv('AGENTPAY_API_KEY')
Step 2: Build Your First Payment Flow
Let's walk through the core 3-line pattern with a real example: a bot selling a Python course for 299,000 VND.
Code Example: Create Payment & Wait for Settlement
from agentpay_vn import PaymentClient, PaymentRequest, SettlementWatcher
import asyncio
# Initialize the payment client with your credentials
client = PaymentClient(
merchant_id='your_merchant_id',
api_key='your_api_key',
bank_account='your_vietqr_account'
)
async def sell_course_to_customer(customer_name, customer_email, course_name):
"""
Step 1: Create a payment request
This generates a unique payment ID and amount tied to this customer.
"""
payment_req = PaymentRequest(
amount_vnd=299000, # Course price
description=f"Python Fundamentals Course - {customer_name}",
customer_id=customer_email, # Use email as unique ID
metadata={'course': course_name, 'customer': customer_name}
)
# Create the payment on AgentPay's system
payment = await client.create_payment_request(payment_req)
"""
Step 2: Send the checkout URL to customer
The payment object includes a checkout_url with the VietQR code.
Your agent sends this to the customer via chat, email, or SMS.
"""
checkout_url = payment.checkout_url
qr_data = payment.qr_code # Raw QR image data if needed
agent_message = f"""
Perfect! Your course is ready. Scan this QR code or click the link to pay:
{checkout_url}
Amount: 299,000 VND
Course: {course_name}
"""
print(agent_message) # Agent sends this to customer
"""
Step 3: Wait for settlement confirmation
The bank feed integration watches your account. When the payment arrives,
await_settlement resolves and returns the settlement confirmation.
"""
settlement = await client.await_settlement(
payment_id=payment.payment_id,
timeout_seconds=600 # Wait up to 10 minutes
)
if settlement.confirmed:
completion_message = f"""
🎉 Payment received! Your course access is unlocked.
Transaction ID: {settlement.transaction_id}
Amount confirmed: {settlement.amount_vnd} VND
Check your email for course materials.
"""
print(completion_message)
return {'status': 'success', 'course_access': True}
else:
print("Payment not received. Please try again.")
return {'status': 'failed', 'course_access': False}
# Run the flow
result = asyncio.run(sell_course_to_customer(
customer_name='Nguyen Van A',
customer_email='a@example.com',
course_name='Python Fundamentals'
))
Line-by-line breakdown:
PaymentClient: Initializes with your merchant credentials. This is your agent's payment wallet.PaymentRequest: Defines what you're selling—amount, description, customer ID, and metadata (useful for tracking which product/course this is).create_payment_request: Sends the request to AgentPay's servers, gets back a payment object with acheckout_url(the VietQR link) and uniquepayment_id.- Checkout URL: This is what your agent shows the customer. It's a QR code that points to the merchant's bank account (your account), not AgentPay's.
await_settlement: Polls the bank feed and waits for confirmation that money landed. Once it does, your agent unlocks the course, sends credentials, or triggers next steps.
Step 3: Integrate with Claude via MCP
If you're using Claude (via Claude Desktop, API, or a custom client), the MCP server exposes AgentPay functions as tools Claude can call directly.
MCP Configuration
Add this to your Claude client's MCP config file (usually ~/.claude/mcp.json or the config in your client):
{
"mcpServers": {
"agentpay": {
"command": "python",
"args": ["-m", "agentpay_mcp"],
"env": {
"AGENTPAY_MERCHANT_ID": "your_merchant_id",
"AGENTPAY_API_KEY": "your_api_key",
"AGENTPAY_BANK_ACCOUNT": "your_vietqr_account"
}
}
}
}
Once this is configured, Claude automatically sees three tools:
create_payment_request: Takes amount, description, and customer ID. Returns payment URL and QR.await_settlement: Takes payment ID and timeout. Returns confirmation when money arrives.get_payment_status: Checks the current status of a payment without blocking.
Claude Prompt Example
Tell Claude what you want:
You are a course sales agent. When a customer wants to buy the "Advanced Python"
course (4,990,000 VND), use the agentpay create_payment_request tool to generate
a payment link. Send the link to the customer. Then use await_settlement to wait
for payment. Once settled, send them the course access code.
Now Claude can autonomously handle the entire sales transaction, from pitch to delivery, without leaving the chat.
Real-World Walkthrough: Virtual Café Bot
Imagine a WhatsApp chatbot for a Hanoi coffee shop. Customers order coffee, pay with VietQR, and get a pickup code.
from agentpay_vn import PaymentClient
import asyncio
client = PaymentClient(
merchant_id='cafe_hanoi_001',
api_key='sk_live_xxxxx',
bank_account='cafe_hanoi_vietqr'
)
async def process_coffee_order(phone, order_items):
"""
Customer: "I want 2 cappuccinos and 1 iced tea."
Bot processes order and requests payment.
"""
# Calculate total
prices = {'cappuccino': 45000, 'iced_tea': 35000}
total = sum(prices.get(item, 0) for item in order_items)
order_id = f"order_{phone}_{int(time.time())}"
# Create payment
payment = await client.create_payment_request({
'amount_vnd': total,
'description': f"Coffee order: {', '.join(order_items)}",
'customer_id': phone,
'metadata': {'order_id': order_id, 'items': order_items}
})
# Send to customer
print(f"Pay here: {payment.checkout_url}")
print(f"Total: {total:,} VND")
# Wait for payment
settlement = await client.await_settlement(payment.payment_id, timeout_seconds=300)
if settlement.confirmed:
pickup_code = f"CAFE{order_id[-6:]}"
print(f"✓ Payment confirmed! Your pickup code: {pickup_code}")
print("Your order will be ready in 5 minutes.")
else:
print("Payment not received. Order cancelled.")
# Usage
asyncio.run(process_coffee_order(
phone='+84901234567',
order_items=['cappuccino', 'cappuccino', 'iced_tea']
))
Flow: Customer scans QR → pays from their bank app → 5 seconds later, bot confirms payment and gives them a pickup code. No cash, no manual approval, fully autonomous.
Common Patterns & Best Practices
DO ✅
| Pattern | Reason |
|---|---|
Store payment_id in your database |
You need it to check settlement status later or handle timeouts |
| Set realistic timeouts (5–10 minutes) | Customers take time to complete mobile payments |
| Include order/course info in metadata | Track which product caused which payment for analytics |
Use customer email or ID in customer_id |
Prevents duplicate payments from the same person |
| Log settlement confirmations | For accounting and debugging |
DON'T ❌
| Anti-Pattern | Problem |
|---|---|
| Block the chat indefinitely waiting for payment | Timeout and let customer retry |
| Create multiple payment requests for the same order | Customer might pay twice |
| Assume the user will scan immediately | Always offer a fallback (email the link, SMS, etc.) |
| Skip error handling on await_settlement | Network glitches happen; always catch exceptions |
| Reuse payment IDs across different transactions | Each sale needs a unique payment ID |
Advanced Tips
Handling Timeouts & Retries
Not all customers pay within 10 minutes. Handle gracefully:
async def sell_with_retry(amount, description, customer_id, max_attempts=3):
for attempt in range(max_attempts):
try:
payment = await client.create_payment_request({
'amount_vnd': amount,
'description': description,
'customer_id': customer_id
})
settlement = await client.await_settlement(
payment.payment_id,
timeout_seconds=300 # 5 minutes per attempt
)
if settlement.confirmed:
return {'success': True, 'payment_id': payment.payment_id}
except asyncio.TimeoutError:
print(f"Attempt {attempt + 1} timed out. Retrying...")
continue
return {'success': False, 'message': 'Payment not received after 3 attempts'}
Webhooks (Advanced)
For high-volume scenarios, instead of blocking on await_settlement, register a webhook. AgentPay will POST settlement data to your server:
# Configure webhook in your agent code or dashboard
client.register_webhook(
url='https://yourdomain.com/agentpay-webhook',
events=['payment.settled', 'payment.failed']
)
Then handle the POST:
from flask import Flask, request
app = Flask(__name__)
@app.route('/agentpay-webhook', methods=['POST'])
def settlement_webhook():
data = request.json
if data['event'] == 'payment.settled':
payment_id = data['payment_id']
amount = data['amount_vnd']
# Unlock course, send email, etc.
print(f"Payment {payment_id} settled for {amount:,} VND")
return {'ok': True}, 200
Multi-Currency (Future-Proofing)
Currently, AgentPay VN handles VND. For USD or international customers, consider converting at purchase time:
exchange_rate = 25000 # 1 USD = 25,000 VND (example)
usd_price = 12
vnd_price = int(usd_price * exchange_rate)
payment = await client.create_payment_request({
'amount_vnd': vnd_price,
'description': f'Purchase (${usd_price} USD)',
'customer_id': customer_email,
'metadata': {'original_currency': 'USD', 'original_amount': usd_price}
})
FAQ
Q: Does AgentPay hold my money?
A: No. The QR code points directly to your merchant's bank account. AgentPay VN is a facilitator only—it never touches customer funds. Settlement happens between the customer's bank and your bank.
Q: How quickly does settlement confirm?
A: Settlement typically confirms within 10–30 seconds via the bank feed. await_settlement polls and resolves the moment confirmation arrives. If no confirmation within your timeout, it returns confirmed=False and you can retry or escalate to manual review.
Q: Can I use this with Claude Desktop?
A: Yes. Configure the MCP server in your mcp.json, restart Claude Desktop, and Claude will see the AgentPay tools. You can then instruct Claude to handle payments autonomously.
Q: What if the customer's bank app doesn't support VietQR?
A: VietQR is supported by all major Vietnamese banks (Vietcombank, BIDV, Techcombank, etc.). If a customer's bank doesn't support it, they can't pay via this method—provide an alternative (traditional transfer, cash). This is rare in Vietnam as of 2024.
Q: How do I handle currency conversion for international customers?
A: Convert to VND at the time of payment using a reliable exchange rate API. Store both the original amount (USD, EUR, etc.) and VND amount in metadata for accounting.
Key Takeaways
- AgentPay VN turns AI agents into merchants: Your Claude bot can now autonomously collect payment and deliver services—no manual intervention.
- Three-line flow is bulletproof:
create_payment_request→send_checkout_url→await_settlement. That's the entire transaction. - Zero custody = zero risk: Money goes straight to your bank account. AgentPay VN is infrastructure, not a payment processor.
- MCP integration = Claude-native: Configure once, and Claude automatically sees payment tools. No custom code needed in your prompt.
- Real-world use cases are everywhere: Courses, coffee shops, consulting, services, digital products. Any agent that closes deals can now collect money.
- Open source (MIT): You can fork, modify, self-host, or integrate deeply. No vendor lock-in.
- Bank feed confirmation is instant: Unlike some payment APIs that poll for hours, AgentPay VN confirms settlement in seconds via bank feeds.
Get Started Now
Your AI agent is ready to get paid. Here's what to do:
- Install AgentPay VN:
pip install agentpay-vn - Get credentials: Register at https://agentpay.servicesai.vn/v1/docs and grab your merchant ID and API key.
- Copy the payment flow code above into your agent.
- For Claude integration: Set up the MCP server following the config example.
- Test with a small amount: 10,000 VND to confirm everything works.
- Deploy and scale: Your agent is now a fully autonomous merchant.
Full documentation and examples are at https://agentpay.servicesai.vn/v1/docs. Source code is on GitHub: https://github.com/phuocdu/agentpay-vn.
Your agent has the ability to serve customers, close sales, and collect payment—all without you lifting a finger. Make it happen.