Add VietQR Checkout to Your LLM Agent in 10 Minutes
The Problem: Your AI Agent Can't Close Sales
You've built a brilliant LLM agent—maybe it books appointments, generates invoices, or sells digital products. It can talk, reason, and solve problems. But when a customer says "I want to buy," your agent hits a wall. It can't actually collect money.
You could pipe users to Stripe, but that breaks the agent's autonomy and creates friction. You could implement Momo or bank transfers manually, but those need polling, callbacks, and complex state management. What you really need is a dead-simple payment tool that your agent can invoke like any other function—no webhooks, no mess, no money touching your infrastructure.
That's where AgentPay VN comes in.
What Is AgentPay VN?
AgentPay VN is an open-source Python SDK and MCP server (MIT licensed) that gives your LLM agent the ability to create and settle VietQR payments in seconds. Here's what makes it special:
- Zero-trust architecture: Your agent never holds money. Payments go directly from customer to merchant's bank account.
- Bank-verified settlement: A real bank feed confirms when money arrives—no guessing, no delays.
- Three-line flow: Create a payment request → send the checkout URL → wait for settlement. That's it.
- Built for agents: Works seamlessly with Claude, GPT-4, and any LLM via MCP (Model Context Protocol).
- No payment processing fees on AgentPay's side—you pay only what your bank charges.
In the next 10 minutes, you'll have a working checkout flow in your agent.
Installation: One Command
First, install the SDK:
pip install agentpay-vn
If you're using AgentPay via MCP (recommended for Claude Desktop or similar), also install:
pip install agentpay-mcp
That's step one. No API keys to hunt down, no registration forms. AgentPay uses your bank's VietQR infrastructure directly.
The 3-Step Payment Flow Explained
Step 1: Create a Payment Request
Your agent calls create_payment_request() with a few details: amount, description, and customer info. AgentPay generates a dynamic VietQR code (or checkout URL) that points straight to your merchant bank account.
Step 2: Send the Checkout URL
Your agent shares the checkout URL with the customer (via chat, SMS, email, whatever). The customer scans the QR code with their phone's banking app and pays. No redirect, no third-party login.
Step 3: Await Settlement
Your agent calls await_settlement() and waits (typically 30 seconds to a few minutes) for the bank to confirm the deposit. Once confirmed, your agent knows the payment succeeded and can proceed—deliver the product, send the invoice, update the database.
Code Example: A Simple Payment Agent
Let's build a minimal agent that sells a digital course. Here's how it works:
from agentpay_vn import create_payment_request, await_settlement
import json
# Your merchant bank details (usually set via env or config)
MERCHANT_ACCOUNT = "0712345678"
MERCHANT_BANK = "970422" # Example: Techcombank
MERCHANT_NAME = "AI Academy"
def sell_course(course_name: str, price: int, customer_email: str) -> dict:
"""
Process a course sale. Agent calls this when customer agrees to buy.
"""
# Step 1: Create payment request
request = create_payment_request(
amount=price,
description=f"Course: {course_name}",
merchant_account=MERCHANT_ACCOUNT,
merchant_bank=MERCHANT_BANK,
merchant_name=MERCHANT_NAME,
order_id=f"course_{course_name}_{int(time.time())}",
customer_email=customer_email
)
# Step 2: Share checkout URL with customer
checkout_url = request["checkout_url"]
payment_id = request["payment_id"]
print(f"Send this link to customer: {checkout_url}")
print(f"QR code generated. Payment ID: {payment_id}")
# Step 3: Wait for settlement (blocks until payment arrives or timeout)
settlement = await_settlement(
payment_id=payment_id,
timeout_seconds=300 # Wait up to 5 minutes
)
if settlement["status"] == "settled":
# Payment confirmed! Deliver the course.
return {
"success": True,
"message": f"Payment received! Sending {course_name} to {customer_email}.",
"amount": settlement["amount"],
"transaction_id": settlement["transaction_id"]
}
else:
return {
"success": False,
"message": "Payment not received within timeout.",
"payment_id": payment_id
}
# Example usage from an agent
result = sell_course(
course_name="Python for LLMs",
price=299000, # 299k VND
customer_email="student@example.com"
)
print(json.dumps(result, indent=2))
Line-by-line breakdown:
- Imports:
create_payment_requestandawait_settlementare the two main functions you'll use. - Merchant config: Your bank account, bank code, and name (usually from env variables in production).
create_payment_request(): Generates a unique VietQR checkout for this transaction. Returns acheckout_urlandpayment_id.await_settlement(): Polls the bank feed until the exact amount arrives. Blocks your agent's execution until settlement is confirmed or timeout is reached.- Conditional delivery: Once settled, your agent can deliver the product, unlock access, send confirmation emails, etc.
Setting Up Your Agent with MCP (Claude Example)
If you're using Claude Desktop or another MCP-compatible client, you can expose AgentPay as a tool. Here's the config:
{
"mcpServers": {
"agentpay-vn": {
"command": "python",
"args": ["-m", "agentpay_mcp"],
"env": {
"MERCHANT_ACCOUNT": "0712345678",
"MERCHANT_BANK": "970422",
"MERCHANT_NAME": "Your Business Name"
}
}
}
}
Add this to your Claude Desktop claude_desktop_config.json file. Restart Claude, and AgentPay functions will appear in your agent's tool menu. Claude can now call create_payment_request and await_settlement directly, without you writing integration code.
Real-World Example: An Online Café Bot
Imagine a WhatsApp bot for a local café. The bot takes orders, recommends drinks, and handles payment.
Scenario: A customer orders a cold brew (85,000 VND).
- Bot: "I've prepared your order. That's 85,000 VND. Here's your checkout link: [QR code]."
- Customer: Scans QR with banking app, pays 85,000 VND.
- Bot (via
await_settlement()): Detects the deposit within 30 seconds. "Payment confirmed! Your order is ready for pickup in 5 minutes. Thanks!" - Backend: Prints the order, updates inventory, logs the transaction.
No Stripe account. No Momo delays. The café's bank account gets the money directly, and the bot's execution doesn't break.
Do's and Don'ts
| Do | Don't |
|---|---|
Use await_settlement() with a reasonable timeout (60–300 sec). |
Leave await_settlement() running indefinitely. |
Store payment_id for reconciliation. |
Assume payment succeeded without calling await_settlement(). |
| Handle timeout gracefully (retry or ask customer to try again). | Assume the bank feed is instant—it can take 30 sec to a few min. |
| Keep merchant account details in env variables. | Hardcode credentials in source code. |
| Test with small amounts first. | Go live without testing end-to-end. |
Advanced: Webhook-Style Polling with Async
For higher-throughput scenarios (e.g., a marketplace with many simultaneous orders), you might not want to block on await_settlement(). Here's an async pattern:
import asyncio
from agentpay_vn import create_payment_request, check_settlement_status
async def process_payment_async(amount: int, description: str) -> str:
"""
Non-blocking payment processing. Fire and forget.
"""
# Create the request
request = create_payment_request(
amount=amount,
description=description,
merchant_account=MERCHANT_ACCOUNT,
merchant_bank=MERCHANT_BANK,
merchant_name=MERCHANT_NAME,
order_id=f"order_{int(time.time())}"
)
payment_id = request["payment_id"]
checkout_url = request["checkout_url"]
# Return immediately. Customer pays at their own pace.
print(f"Payment request created: {payment_id}")
print(f"Checkout URL: {checkout_url}")
# In the background, keep checking for settlement.
asyncio.create_task(wait_for_settlement_async(payment_id))
return payment_id
async def wait_for_settlement_async(payment_id: str, max_attempts: int = 60):
"""
Poll for settlement every 5 seconds, up to 5 minutes.
"""
for attempt in range(max_attempts):
status = check_settlement_status(payment_id)
if status["is_settled"]:
print(f"[{payment_id}] Payment settled! Amount: {status['amount']} VND")
# Trigger delivery, send email, etc.
break
await asyncio.sleep(5) # Check every 5 seconds
else:
print(f"[{payment_id}] Settlement timeout.")
# Usage
async def main():
payment_id = await process_payment_async(
amount=500000,
description="Premium subscription (1 month)"
)
# Agent continues with other tasks while payment settles in background.
asyncio.run(main())
This is useful if your agent handles multiple customer interactions simultaneously.
Frequently Asked Questions
Q: Does AgentPay hold my money?
A: No. AgentPay is a facilitator, not a payment processor. The VietQR points directly at your merchant bank account. Money never touches AgentPay's systems. A bank feed confirms settlement.
Q: What happens if the customer doesn't pay within the timeout?
A: await_settlement() returns with status: "timeout". Your agent can retry (generate a new checkout) or ask the customer to try again. No money is lost.
Q: Can I use AgentPay with GPT-4, Gemini, or just Claude?
A: The SDK is bank-agnostic Python. The MCP server works with any MCP-compatible LLM client (Claude, custom agents, etc.). You can also call AgentPay functions directly in your own agent code.
Q: Is there a cost?
A: AgentPay is open-source (MIT). No fees from AgentPay. You pay only standard bank charges for VietQR transfers (typically 0% or minimal).
Key Takeaways
- AgentPay VN gives your LLM agent autonomous checkout capability in under 10 minutes.
- Three-step flow: Create request → share URL → await settlement. No webhooks, no complexity.
- Direct bank routing: Money goes straight to your account; AgentPay never touches it.
- MCP integration: For Claude and other agents, add AgentPay as an MCP server and let your agent call payment functions like any other tool.
- Real-world ready: Works for courses, services, products, subscriptions—any scenario where your agent needs to close a sale.
- Testing: Start with small amounts to verify the flow, then scale.
Next Steps
- Install:
pip install agentpay-vn - Read the docs: https://agentpay.servicesai.vn/v1/docs
- Explore the repo: https://github.com/phuocdu/agentpay-vn
- Integrate into your agent: Use the code examples above or configure MCP.
- Test end-to-end: Create a payment request, scan the QR, and confirm settlement.
Your AI agent is now ready to sell.