Sell Digital Products via AI Chatbot Without Holding Funds
The Problem: Your AI Chatbot Can't Sell Anything
You've trained an AI chatbot to answer questions, close leads, and guide customers through your digital product catalog. It's sharp. It converts. But the moment someone says "I want to buy," the bot hits a dead end.
The painful reality: most AI frameworks have zero integration with payment processors. You either:
- Redirect to a third-party checkout (losing context, breaking flow, watching abandonment spike)
- Build custom payment code (complexity, security risk, maintenance burden)
- Abandon the sale (losing revenue)
Even if you integrate Stripe or PayPal, you're swimming in PCI compliance, webhook debugging, and fund management. For merchants in Vietnam who need VietQR, the situation is worse—no native support in popular frameworks.
What if your bot could collect payment directly into your bank account, no middleman, no funds held, in three lines of code?
Introducing AgentPay VN: Payment Requests for AI Agents
AgentPay VN is a lightweight, open-source (MIT licensed) Python SDK + MCP server designed for one job: let your AI agent request payments and confirm they landed in your merchant account.
Core principle: You never hold the money. The QR code points straight at your bank. A bank feed confirms settlement. Your agent stays in control of the conversation while payment flows directly to you.
It's built in Python, integrates with Claude via MCP (Model Context Protocol), and requires zero merchant account setup beyond your existing bank.
How AgentPay VN Actually Works: The 3-Line Flow
Every payment request follows the same pattern:
1. create_payment_request() → generates checkout_url
2. send checkout_url → user scans VietQR
3. await_settlement() → confirm payment in your bank
That's it. No webhooks to configure, no payment gateway accounts to open, no fund reconciliation.
Step-by-Step: Install and Configure
Installation
Start with pip:
pip install agentpay-vn
If you're running the MCP server (for Claude integration):
pip install agentpay-mcp
Configure Your Bank Details
AgentPay reads your merchant bank account from environment variables. Set these once:
export AGENTPAY_MERCHANT_ACCOUNT="1234567890"
export AGENTPAY_MERCHANT_NAME="Acme Digital Products"
export AGENTPAY_BANK_CODE="MB" # Techcombank = MB, VietcomBank = VCB, etc.
export AGENTPAY_BANK_WEBHOOK_URL="https://your-domain.com/webhook" # Optional
That's all. No API keys, no third-party accounts. Your bank, your account.
Building Your First Payment-Collecting Chatbot
Real-World Scenario: A Python Course Bot
Imagine you sell a Python certification course for 499,000 VND. A student chats with your bot:
Student: "I want to enroll in the advanced Python course."
Bot: "Perfect! That's 499,000 VND. Let me generate your payment link."
Bot sends QR → Student scans → Money arrives in your account → Bot confirms enrollment.
Here's the code:
from agentpay_vn import AgentPay
# Initialize
pay = AgentPay(
merchant_account="1234567890",
merchant_name="Python Academy VN",
bank_code="MB"
)
# Student wants to enroll
student_id = "student_12345"
course_price_vnd = 499000
course_name = "Advanced Python Fundamentals"
# Step 1: Create payment request
payment_req = pay.create_payment_request(
amount=course_price_vnd,
order_id=f"course_{student_id}_{int(time.time())}",
description=f"Enrollment: {course_name}",
metadata={"student_id": student_id, "course": course_name}
)
# Step 2: Share checkout URL with student
checkout_url = payment_req.checkout_url
print(f"Student, scan this QR or visit: {checkout_url}")
# Step 3: Wait for settlement confirmation
settlement = pay.await_settlement(
order_id=payment_req.order_id,
timeout_seconds=300 # Wait up to 5 minutes
)
if settlement.confirmed:
print(f"✓ Payment received! Enrolling student {student_id}...")
# Trigger your enrollment logic
enroll_student(student_id, course_name)
else:
print(f"✗ Payment not received within timeout.")
Line-by-line breakdown:
- Lines 1–6: Import AgentPay and initialize with your merchant details. No authentication token needed—you own the account.
- Lines 8–11: Define what you're selling (student ID, price in VND, description).
- Lines 13–19:
create_payment_request()generates a unique order and returns acheckout_url. This URL encodes the VietQR code. - Lines 21–23: Send the
checkout_urlto your student (display as QR or link). - Lines 25–29:
await_settlement()polls your bank feed (or webhook) until it confirms the 499,000 VND arrived. It's blocking, so wrap it in async if needed. - Lines 31–37: Once confirmed, trigger your business logic (send course access, email credentials, etc.).
Handling Async Workflows
In production, you don't want to block the chatbot while waiting for payment. Use async:
import asyncio
from agentpay_vn import AgentPay
pay = AgentPay(
merchant_account="1234567890",
merchant_name="Python Academy VN",
bank_code="MB"
)
async def handle_enrollment(student_id: str, course_name: str, price: int):
"""Non-blocking payment + enrollment flow."""
# Create payment request
payment_req = pay.create_payment_request(
amount=price,
order_id=f"course_{student_id}_{int(time.time())}",
description=f"Enrollment: {course_name}"
)
print(f"Checkout: {payment_req.checkout_url}")
# Don't block—store the order ID and check later
async def verify_and_enroll():
settlement = await pay.await_settlement_async(
order_id=payment_req.order_id,
timeout_seconds=600
)
if settlement.confirmed:
enroll_student(student_id, course_name)
send_email(student_id, "Enrollment confirmed!")
# Fire and forget
asyncio.create_task(verify_and_enroll())
return {"status": "checkout_sent", "url": payment_req.checkout_url}
# Usage
asyncio.run(handle_enrollment("student_12345", "Advanced Python", 499000))
Now your chatbot immediately returns the checkout URL and doesn't stall. Payment verification happens in the background.
Integrate AgentPay with Claude via MCP
If you're running Claude as your AI backbone, use the MCP server for seamless integration.
MCP Server Configuration
Start the MCP server:
agentpay-mcp --port 8765
Then configure Claude's claude_desktop_config.json:
{
"mcpServers": {
"agentpay": {
"command": "agentpay-mcp",
"args": ["--port", "8765"],
"env": {
"AGENTPAY_MERCHANT_ACCOUNT": "1234567890",
"AGENTPAY_MERCHANT_NAME": "Python Academy VN",
"AGENTPAY_BANK_CODE": "MB"
}
}
}
}
Now in your Claude prompt, you can directly call:
User: "I want to buy the advanced course."
Claude (with MCP): I'll create a payment request for you.
[Uses agentpay.create_payment_request(amount=499000, ...)]
Scan this QR code: [checkout_url]
[Waits for settlement via agentpay.await_settlement()]
✓ Payment confirmed! Sending your course access...
The MCP server exposes three core functions:
- create_payment_request(amount, order_id, description, metadata)
- get_payment_status(order_id)
- await_settlement(order_id, timeout_seconds)
Claude can call them naturally, no custom glue code needed.
Real-World Walkthrough: An Online Course Store Bot
Let's trace a complete flow: a customer discovers your bot, browses courses, and buys.
Step 1: Bot Greets & Lists Courses
Bot: "Welcome! I sell 3 courses:
1. Python Basics (149K VND)
2. Advanced Python (499K VND)
3. Machine Learning Mastery (899K VND)
Which interests you?"
Step 2: Customer Chooses
Customer: "I want Advanced Python."
Bot: "Great choice! Let me create your checkout."
Step 3: Bot Creates Payment Request
Backend calls create_payment_request(amount=499000, ...). Returns checkout URL.
Step 4: Bot Shows QR
Bot: "Scan this QR with your banking app:
[QR image: https://vietqr.io/...]
Or visit: https://checkout.agentpay.vn/..."
Step 5: Customer Scans & Pays
Customer opens their VietcomBank app, scans QR, confirms 499K VND transfer to your account. Takes 10 seconds.
Step 6: Bot Detects Settlement
await_settlement() polls your bank feed (via webhook or API). Within 30 seconds, it confirms the 499K arrived.
Step 7: Bot Grants Access
Bot: "✓ Payment received!
Your course access is active: [link]
Login: yourname@example.com
Password: [generated]
Start lesson 1 now?"
Step 8: Post-Sale
Your webhook/background task triggers: - Send welcome email with course materials - Update your database (user enrolled) - Log the transaction - No manual reconciliation needed
Do's and Don'ts with AgentPay
| Do | Don't |
|---|---|
Use unique order_id per request (append timestamp) |
Reuse order_id across multiple payments |
Set realistic timeout_seconds (300–600 for most cases) |
Wait forever with timeout_seconds=999999 |
Store order_id in your DB for auditing |
Lose track of orders—you won't match payments to customers |
Use metadata to tag orders (student_id, course, etc.) |
Ignore metadata—you'll regret it during debugging |
| Test in dev first with small amounts | Go live without testing the settlement flow |
| Validate amount > 0 before calling create_payment_request | Accept negative or zero amounts |
| Handle async settlement in production | Block your chatbot waiting for payment |
Troubleshooting & Advanced Tips
Issue: Settlement Never Confirms
Root cause: Bank feed isn't connected, or webhook URL is wrong.
Fix:
# Verify your bank details
print(pay.merchant_account) # Should match your actual account
print(pay.bank_code) # Correct bank code?
# Check webhook
print(pay.webhook_url) # Is it publicly accessible? HTTPS?
Issue: Customer Scans QR but Nothing Happens
Root cause: Customer's banking app doesn't support VietQR, or the QR is malformed.
Fix:
# Always offer a fallback text/link
print(f"QR: {payment_req.checkout_url}")
print(f"or visit: {payment_req.fallback_url}")
Batch Enrollments for Bulk Buyers
If one customer buys 10 course licenses for a team:
team_size = 10
total_price = 499000 * team_size
payment_req = pay.create_payment_request(
amount=total_price,
order_id=f"bulk_order_{company_id}_{int(time.time())}",
description=f"Bulk license: {team_size}x Advanced Python",
metadata={
"company_id": company_id,
"team_size": team_size,
"licenses": team_size
}
)
# After settlement confirms:
for i in range(team_size):
enroll_student(f"{company_id}_user_{i}", "Advanced Python")
FAQ
Q: Does AgentPay hold my money?
A: Never. The VietQR points directly to your merchant bank account. AgentPay only facilitates the request and confirms settlement—it's a bridge, not an escrow.
Q: What if my internet goes down mid-payment?
A: The payment still reaches your bank. When your internet returns, await_settlement() will detect it. Your bank is the source of truth, not AgentPay.
Q: Is AgentPay PCI-compliant?
A: AgentPay never handles card data—VietQR is bank-to-bank transfer. Your customer's banking app handles authentication. No PCI scope for you.
Q: Can I use AgentPay with other banks besides Techcombank?
A: Yes. AgentPay supports all Vietnamese banks via VietQR. Set bank_code to your bank's code ("VCB" for VietcomBank, "ACB" for ACB, etc.).
Key Takeaways
- AgentPay VN is a 3-line Python SDK:
create_payment_request()→ send URL →await_settlement() - No fund escrow. Money goes straight to your merchant account; AgentPay confirms settlement via bank feed.
- Dead simple. VietQR + your existing bank account = zero friction for customers.
- AI-native. Built for chatbots and agents. Claude integrates via MCP in one config.
- Open-source (MIT). Audit the code, self-host the MCP server, own your payment flow.
- Production-ready. Async support, metadata tagging, webhook confirmations, timeout handling.
Getting Started Now
Ready to let your AI agent sell? Here's your next step:
# 1. Install
pip install agentpay-vn
# 2. Set env vars with your bank account
export AGENTPAY_MERCHANT_ACCOUNT="your_account_number"
export AGENTPAY_MERCHANT_NAME="Your Business"
export AGENTPAY_BANK_CODE="MB"
# 3. Copy the course bot code from above
# 4. Run it
python your_bot.py
Full documentation, code examples, and the MCP server config live at https://agentpay.servicesai.vn/v1/docs.
GitHub repository for issues, PRs, and community support: https://github.com/phuocdu/agentpay-vn.
Your chatbot is ready to collect real revenue. Start with one course. Scale to many.