AI Chatbot Payment Collection Without Fund Risk
The Hidden Cost of AI-Powered Sales
You've built an intelligent chatbot that recommends and sells your digital products—online courses, templates, design files, software licenses. It works beautifully. Customers flow through, they're ready to pay, your bot closes deals automatically at 2 AM while you sleep.
Then reality hits: Where does the money go?
If you're like most developers, you've either:
- Struggled with traditional payment gateways that impose high fees for recurring verification, require complex PCI compliance, or demand you hold customer funds in an intermediate account.
- Used a third-party payment aggregator and watched 3–5% of every transaction disappear before it reaches your bank.
- Avoided AI-driven commerce entirely because the liability felt too high—what if the payment system crashed mid-transaction?
This is where AgentPay VN changes the game. It's an open-source Python SDK and MCP server that lets your AI agents collect VietQR payments directly into your merchant bank account—without ever touching the money. No holding funds. No escrow accounts. No intermediary risk.
What Is AgentPay VN, and Why Should You Care?
AgentPay VN is a lightweight, MIT-licensed toolkit built specifically for AI agents to initiate and manage payments in Vietnam using VietQR—a unified QR payment standard that connects every major Vietnamese bank.
Here's what makes it different:
- No fund custody: The QR code points directly to your bank account. Settlement is confirmed via bank feed.
- Agent-native: Designed as both a Python SDK and an MCP (Model Context Protocol) server, so Claude, other LLMs, and autonomous agents can call payment functions natively.
- MIT open-source: You own the code. No vendor lock-in. Transparency and community-driven development.
- Three-line flow: Create a payment request → send the checkout URL to the customer → await settlement confirmation.
Installation is instant:
pip install agentpay-vn
For MCP integration with Claude:
agentpay-mcp
Real-World Scenario: The Online Course Bot
Imagine you run an AI coaching platform. A prospect chatbot qualifies leads and offers a course: "Advanced Prompt Engineering for Founders ($49)". A human would need to:
- Generate a payment link.
- Send it via email or chat.
- Wait for confirmation.
- Manually unlock the course.
With AgentPay VN, this becomes fully autonomous:
- The bot detects purchase intent.
- It calls
create_payment_request(amount=49, product_id="prompt-eng-101")and receives a checkout URL. - The checkout URL is delivered instantly to the customer.
- Once the customer scans the VietQR code and confirms payment at their bank,
await_settlement()returns True. - The bot automatically enrolls the student and sends download links—all in seconds.
Revenue impact: You're no longer losing 3–5% to intermediaries, and your AI agents operate 24/7 without manual intervention.
Step 1: Set Up Your Environment
Before you write a single line of payment code, ensure you have:
- Python 3.8+ installed.
- A merchant VietQR account (contact your Vietnamese bank; major ones include VCB, Techcombank, MB, BIDV).
- AgentPay VN SDK installed (see above).
- API credentials from AgentPay (available on the docs site at https://agentpay.servicesai.vn/v1/docs).
Set your credentials as environment variables:
export AGENTPAY_MERCHANT_ID="your_merchant_id"
export AGENTPAY_API_KEY="your_api_key"
export AGENTPAY_WEBHOOK_SECRET="your_webhook_secret"
Step 2: Create Your First Payment Request
Here's a real, working Python example:
from agentpay_vn import AgentPayClient, PaymentStatus
import asyncio
# Initialize the client with your credentials
client = AgentPayClient(
merchant_id="your_merchant_id",
api_key="your_api_key"
)
async def sell_course_to_customer(customer_email, course_id, price_vnd):
"""
Initiates a payment request for a digital product.
Args:
customer_email: The buyer's email
course_id: Unique identifier for the course
price_vnd: Price in Vietnamese Dong
Returns:
checkout_url: The VietQR payment link to send to the customer
"""
# Step 1: Create a payment request
# This generates a unique invoice tied to your merchant account
payment_request = await client.create_payment_request(
amount=price_vnd,
description=f"Course: {course_id}",
customer_email=customer_email,
reference_id=f"COURSE_{course_id}_{int(time.time())}"
)
# The response includes a checkout URL pointing to your bank's VietQR
checkout_url = payment_request["checkout_url"]
payment_id = payment_request["payment_id"]
print(f"Checkout URL: {checkout_url}")
print(f"Payment ID: {payment_id}")
# Step 2: Send this URL to the customer via email or chat
# In production, integrate with your email service or chatbot platform
return {
"checkout_url": checkout_url,
"payment_id": payment_id,
"message": f"Here's your secure payment link: {checkout_url}"
}
# Run the async function
if __name__ == "__main__":
result = asyncio.run(
sell_course_to_customer(
customer_email="student@example.com",
course_id="prompt-eng-101",
price_vnd=1_190_000 # ~$49 USD
)
)
print(result)
Line-by-line breakdown:
- Lines 1–2: Import the SDK and async utilities.
- Lines 5–8: Initialize the AgentPayClient with your credentials (loaded from environment variables).
- Lines 10–32: Define an async function that accepts customer details and course metadata.
- Lines 18–23: Call
create_payment_request()with the amount, description, customer email, and a unique reference ID (critical for reconciliation). - Lines 26–27: Extract the checkout URL and payment ID from the response.
- Lines 30–35: Return a dictionary ready to send to your customer.
Step 3: Await Settlement Confirmation
Once the customer pays, you need to confirm and unlock their access:
async def unlock_course_after_payment(payment_id, course_id, customer_email):
"""
Polls for payment settlement and unlocks the course upon confirmation.
Args:
payment_id: The payment ID from the create_payment_request response
course_id: The course to unlock
customer_email: Where to send the download link
"""
# Step 1: Wait for settlement with a timeout of 10 minutes (typical for VietQR)
settlement = await client.await_settlement(
payment_id=payment_id,
timeout_seconds=600
)
# Step 2: Check if payment was successful
if settlement["status"] == PaymentStatus.SETTLED:
print(f"✓ Payment {payment_id} confirmed!")
print(f" Amount: {settlement['amount']} VND")
print(f" Timestamp: {settlement['settled_at']}")
# Step 3: Unlock the course (your application logic)
unlock_result = await grant_course_access(
email=customer_email,
course_id=course_id
)
# Step 4: Send download link via email
await send_email(
to=customer_email,
subject=f"Welcome to {course_id}!",
body=f"Download your course materials here: {unlock_result['download_url']}"
)
return {"success": True, "download_url": unlock_result['download_url']}
elif settlement["status"] == PaymentStatus.PENDING:
print(f"⏳ Payment still pending. Customer may still be completing the transaction.")
return {"success": False, "reason": "pending"}
else:
print(f"✗ Payment failed or cancelled.")
return {"success": False, "reason": "failed"}
# Usage: Call this after the customer scans the QR code
if __name__ == "__main__":
result = asyncio.run(
unlock_course_after_payment(
payment_id="pay_abc123xyz",
course_id="prompt-eng-101",
customer_email="student@example.com"
)
)
print(result)
Key points:
await_settlement()blocks until the bank confirms the payment (or times out after 10 minutes).PaymentStatus.SETTLEDmeans money has hit your account; proceed with unlocking.PaymentStatus.PENDINGmeans the customer initiated the payment but hasn't finished at their bank yet.PaymentStatus.FAILEDor other statuses mean you should not grant access and may want to retry or refund (if applicable).
Connecting to Claude and AI Agents via MCP
If you want Claude or another LLM to call AgentPay functions directly, configure it as an MCP server:
MCP Configuration (JSON):
{
"mcpServers": {
"agentpay": {
"command": "agentpay-mcp",
"env": {
"AGENTPAY_MERCHANT_ID": "your_merchant_id",
"AGENTPAY_API_KEY": "your_api_key",
"AGENTPAY_WEBHOOK_SECRET": "your_webhook_secret"
}
}
}
}
Add this to your Claude Desktop configuration (typically ~/.claude_desktop_config.json). Restart Claude, and you'll have native tools:
agentpay:create_payment_requestagentpay:await_settlementagentpay:check_payment_status
Now Claude can autonomously manage payments in your custom instructions or API calls without needing you to write Python code for every interaction.
Real-World Walkthrough: A Café Loyalty Bot
Let's build a concrete example: a café selling digital gift cards.
Scenario: A customer messages your Telegram bot: "Can I buy a 500k VND gift card?"
Flow:
- Bot detects purchase intent.
- Bot calls `create_payment_request(amount=500_000, description="Café Gift Card", customer_email="user@telegram.com", reference_id="GIFTCARD_telegram_user_123").
- Bot receives a VietQR checkout URL:
https://checkout.agentpay.servicesai.vn/?payment_id=pay_xyz789. - Bot sends the URL to the customer: "Scan this code to pay 500k VND for your gift card."
- Customer opens their bank app, scans the QR code, and pays.
- Bot's
await_settlement()call returns successfully within 2–5 seconds (most VietQR payments settle almost instantly). - Bot immediately sends the customer a digital gift card code:
CAFE_5K_ABC123DEF456. - Money is already in your café's bank account. Settlement is confirmed via your bank's feed (no guesswork).
Result: Zero friction, zero fund custody risk, instant gratification for the customer.
Do's and Don'ts
| Do | Don't |
|---|---|
Store payment_id and reference_id in your database for reconciliation |
Rely solely on webhook notifications; always verify with check_payment_status() |
Set a reasonable timeout (300–600 seconds) for await_settlement() |
Hard-fail immediately; VietQR can take 5–10 seconds, especially during peak hours |
Use unique reference_id for each transaction (include timestamp or UUID) |
Reuse the same reference ID; it will cause duplicate-payment errors |
| Implement idempotent unlock logic (check if already unlocked before granting access) | Assume payment succeeded without confirming status; implement retry logic |
| Log all payment events (create, settle, fail) for debugging | Ignore failed payments; follow up with the customer to retry or troubleshoot |
Advanced Tips
Webhook Integration for Real-Time Updates
Instead of polling with await_settlement(), register a webhook endpoint to receive instant notifications:
from fastapi import FastAPI, Request
import hmac
import hashlib
app = FastAPI()
@app.post("/webhook/agentpay")
async def handle_agentpay_webhook(request: Request):
"""
Receives real-time payment settlement notifications from AgentPay.
"""
body = await request.json()
signature = request.headers.get("X-AgentPay-Signature")
# Verify the signature to ensure the webhook is authentic
expected_signature = hmac.new(
key=os.getenv("AGENTPAY_WEBHOOK_SECRET").encode(),
msg=str(body).encode(),
digestmod=hashlib.sha256
).hexdigest()
if signature != expected_signature:
return {"error": "Invalid signature"}, 401
# Process the webhook
if body["event"] == "payment.settled":
payment_id = body["payment_id"]
amount = body["amount"]
reference_id = body["reference_id"]
# Unlock course or gift card based on reference_id
await unlock_product(reference_id, amount)
return {"status": "ok"}
Webhooks eliminate latency and give you a more reactive system.
Handling Refunds
If a customer requests a refund (though rare for digital goods), AgentPay supports it:
async def refund_payment(payment_id, refund_reason):
refund = await client.refund_payment(
payment_id=payment_id,
reason=refund_reason
)
if refund["status"] == "refunded":
print(f"Refund {refund['refund_id']} processed. Amount: {refund['amount']} VND")
# Revoke course access or gift card
await revoke_access(payment_id)
return refund
FAQ
Q: Does AgentPay hold my customer's money? A: No. AgentPay generates a VietQR code that points directly to your merchant bank account. Your bank processes the payment and deposits it directly to you. AgentPay only facilitates the transaction, never touches funds.
Q: What happens if the customer's payment times out?
A: If await_settlement() times out after the specified duration (e.g., 600 seconds), the payment is still pending at the customer's bank. The transaction isn't lost—the customer can retry from your chat history, or you can create a new payment request with the same or different amount. AgentPay's bank reconciliation ensures you don't double-charge.
Q: Can I use AgentPay outside Vietnam or for non-VND currencies? A: Currently, AgentPay VN is optimized for Vietnam and VND payments via VietQR. If you need international or multi-currency support, refer to the GitHub repo (https://github.com/phuocdu/agentpay-vn) for roadmap updates or community contributions.
Q: What are the fees? A: AgentPay itself is open-source and free. Your bank will charge standard merchant VietQR fees (typically 0.5–1% per transaction), which is significantly lower than traditional payment gateway fees and you pay it once—not per integration.
Key Takeaways
- AgentPay VN eliminates intermediaries: Money goes straight to your bank account. No escrow, no holding periods, no vendor risk.
- Three-line payment flow:
create_payment_request()→ send checkout URL →await_settlement(). That's it. - AI-agent native: Works seamlessly with Claude and other LLMs via MCP, enabling fully autonomous sales bots.
- MIT open-source: Own the code, contribute to the project, no licensing costs.
- Real-time settlement: VietQR payments often settle in seconds to minutes, not days.
- Built for Vietnam's fintech landscape: Leverages VietQR's bank-agnostic standard supported by every major Vietnamese bank.
- Webhook support: Real-time notifications mean your bot doesn't have to poll—it reacts instantly to payments.
Getting Started Now
You're three commands away from integrating payments into your AI agent:
pip install agentpay-vn
export AGENTPAY_MERCHANT_ID="your_id"
export AGENTPAY_API_KEY="your_key"
Then copy the course-selling example above, customize it for your product, and deploy.
Learn more:
- Full SDK Documentation: https://agentpay.servicesai.vn/v1/docs
- GitHub Repository: https://github.com/phuocdu/agentpay-vn (star it, contribute, or file issues)
- MCP Server: Run agentpay-mcp to expose payment functions to Claude and other LLMs.
Your AI chatbot can now close sales, collect payment, and unlock digital products—all without you touching customer money. That's the power of AgentPay VN.