Collect VietQR Payments in Telegram Bots with AgentPay
The Problem: Manual Payment Friction in Telegram Bots
Imagine you're running an online course business via Telegram. A student wants to enroll in your Python masterclass—$50 course fee. Today, you're sending them a PayPal link, a bank transfer form, or worse, asking for manual payment confirmation. They drop out halfway through checkout. By the time they've copied account numbers and sent a screenshot, the friction has killed the sale.
Or you're a café owner with a delivery bot. Customers order coffee, but payment collection is either impossible (you have no payment gateway) or clunky (third-party checkout that breaks the flow).
This is the gap AgentPay VN closes: native, frictionless VietQR payment collection directly inside Telegram, with zero setup on the merchant's end and zero money touching your platform.
What is AgentPay VN?
AgentPay VN is an open-source (MIT license) Python SDK that lets AI agents and applications collect payments via VietQR—Vietnam's interbank QR standard. The key insight: AgentPay never holds funds. The QR code points directly to your merchant bank account. A bank feed confirms settlement in real time. You build the bot; your bank does the heavy lifting.
Two deployment options:
- Python SDK (
pip install agentpay-vn): Direct integration into your bot code. - MCP Server (
agentpay-mcp): Claude or other AI agents invoke payment functions as tools.
For a Telegram bot, you'll typically use the Python SDK directly, with optional MCP integration if you're running Claude as your bot brain.
Setting Up Your Telegram Bot with AgentPay
Prerequisites
- Python 3.9+ installed.
- A Telegram bot token (create one via @BotFather on Telegram).
- A Vietnamese merchant bank account (VietComBank, Agribank, ACB, etc.; VietQR is universally supported).
python-telegram-botlibrary for Telegram integration.
Step 1: Install Dependencies
pip install agentpay-vn python-telegram-bot
This installs: - agentpay-vn: Payment request generation, settlement confirmation. - python-telegram-bot: Telegram API bindings.
Step 2: Create Your First Payment Request
Here's a minimal Python bot that accepts a payment via VietQR:
from telegram import Update, InlineKeyboardButton, InlineKeyboardMarkup
from telegram.ext import Application, CommandHandler, ContextTypes
from agentpay_vn import create_payment_request, await_settlement
import uuid
# Initialize your Telegram bot
TELEGRAM_TOKEN = "your_telegram_bot_token_here"
MERCHANT_ACCOUNT = "0123456789" # Your VietQR-enabled bank account
MERCHANT_NAME = "My Telegram Store"
async def start(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
"""Send a welcome message with a payment button."""
await update.message.reply_text(
"Welcome! 🎉 I sell premium tutorials for $10 each.\n"
"Click the button below to pay via VietQR."
)
async def buy_tutorial(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
"""Create a payment request and send the checkout URL."""
# Step 1: Generate a unique payment request
payment_id = str(uuid.uuid4())
amount = 10 # USD equivalent; AgentPay handles conversion
description = "Premium Python Tutorial Access"
# Create the payment request (this generates a VietQR string)
payment_request = create_payment_request(
merchant_account=MERCHANT_ACCOUNT,
merchant_name=MERCHANT_NAME,
amount=amount,
description=description,
payment_id=payment_id,
currency="USD" # or "VND" if you prefer
)
# Step 2: Generate checkout URL (contains the QR or deep link)
checkout_url = payment_request["checkout_url"]
qr_image_url = payment_request["qr_image_url"]
# Step 3: Send to user
keyboard = [
[InlineKeyboardButton("Pay Now", url=checkout_url)],
[InlineKeyboardButton("Show QR Code", callback_data=f"qr_{payment_id}")]
]
reply_markup = InlineKeyboardMarkup(keyboard)
await update.message.reply_text(
f"📱 Scan or tap to pay {amount} USD for tutorial access:\n\n"
f"Transaction ID: {payment_id}",
reply_markup=reply_markup
)
# Store payment_id in context for later confirmation
context.user_data['pending_payment'] = payment_id
async def confirm_payment(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
"""Poll the bank feed to check if payment settled."""
payment_id = context.user_data.get('pending_payment')
if not payment_id:
await update.message.reply_text("❌ No pending payment found.")
return
# Step 4: Wait for settlement confirmation from the bank
settlement_data = await_settlement(
payment_id=payment_id,
timeout_seconds=300 # Poll for up to 5 minutes
)
if settlement_data['settled']:
user_id = update.message.from_user.id
# Grant access (e.g., send PDF, unlock content)
await update.message.reply_text(
f"✅ Payment confirmed! Amount: {settlement_data['amount']} VND\n"
f"Access link: [Download Tutorial](https://your-course-link.com)"
)
# Log transaction
print(f"User {user_id}: {settlement_data}")
else:
await update.message.reply_text(
"⏳ Payment still pending. Check your bank app or try again in 2 minutes."
)
if __name__ == "__main__":
app = Application.builder().token(TELEGRAM_TOKEN).build()
app.add_handler(CommandHandler("start", start))
app.add_handler(CommandHandler("buy", buy_tutorial))
app.add_handler(CommandHandler("confirm", confirm_payment))
app.run_polling()
Line-by-line explanation:
- Lines 10–11: Bot token and merchant account (replace with your actual values).
- Lines 19–21:
buy_tutorial()generates a unique payment ID using UUID. - Lines 24–32:
create_payment_request()builds a VietQR payment object with amount, description, and merchant details. It returns acheckout_url(deeplink to VietQR apps) andqr_image_url. - Lines 35–42: Creates Telegram inline buttons so users can tap directly from chat.
- Lines 52–60:
await_settlement()polls the bank feed every 2–5 seconds (configurable) until the bank confirms the transaction or timeout. - Lines 61–65: Once settled, grant access (send PDF, unlock content, issue API key, etc.).
Real-World Walkthrough: Online Course Bot
Let's say you're selling a 4-week "Build with Claude" course for 500,000 VND (~$20 USD):
- User sends
/buy→ Bot generates a payment request withamount=500000, currency="VND". - User taps "Pay Now" → They're taken to their default VietQR app (Vietcombank, Agribank, Momo, etc.) with the QR pre-filled.
- They authorize in 3 seconds → Bank debits their account, credits yours.
- Bot polls the bank feed → Within 10–30 seconds, AgentPay confirms settlement.
- Bot unlocks course → Sends access link, lesson 1 PDF, and Discord invite.
No Stripe account. No PayPal hold. No payment gateway fees (beyond your bank's standard transfer fee, typically 0–0.5% VND). Pure direct-to-bank flow.
MCP Integration for AI Agents
If you're building a multi-agent system where Claude or another LLM orchestrates your bot, use AgentPay's MCP server:
{
"mcpServers": {
"agentpay": {
"command": "agentpay-mcp",
"env": {
"AGENTPAY_MERCHANT_ACCOUNT": "0123456789",
"AGENTPAY_MERCHANT_NAME": "My Telegram Store",
"AGENTPAY_API_KEY": "your_api_key_here"
}
}
}
}
Now Claude can invoke payment functions as tools:
User: "I want to buy the premium tutorial."
Claude (via MCP): agentpay:create_payment_request(amount=500000, currency="VND")
Claude: "Here's your payment link: [link]. Once paid, I'll unlock your content."
Advanced Tips
Idempotency & Duplicate Prevention
Always use a unique payment_id (UUID or timestamp + user ID). If the same user clicks "Pay" twice, reuse the same payment_id. AgentPay deduplicates on the bank feed, so you won't double-charge.
Graceful Timeout Handling
Bank feeds can take 10–60 seconds depending on the issuing bank. Set timeout_seconds generously:
# Poll for up to 2 minutes; don't block the user
await_settlement(payment_id=payment_id, timeout_seconds=120)
Alternatively, send a "Payment pending" message and ask them to check back later.
Store Metadata
Associate each payment with user data:
# Before creating the payment request
user_id = update.message.from_user.id
user_phone = update.message.from_user.phone_number
payment_request = create_payment_request(
merchant_account=MERCHANT_ACCOUNT,
amount=10,
payment_id=f"{user_id}_{uuid.uuid4()}",
metadata={"user_id": user_id, "phone": user_phone, "product": "tutorial"}
)
Retrieve metadata when settlement confirms, so you know exactly who paid for what.
Multi-Currency Support
AgentPay auto-converts USD/EUR to VND at market rates. Test with:
# Charge $10 USD
payment_request = create_payment_request(
amount=10,
currency="USD",
...
)
# Or charge 250,000 VND directly
payment_request = create_payment_request(
amount=250000,
currency="VND",
...
)
Do's and Don'ts
| Do | Don't |
|---|---|
| Use HTTPS for all URLs | Hardcode merchant account in repo |
Store payment_id in a database |
Reuse the same payment_id for multiple users |
| Poll settlement asynchronously (don't block) | Charge the user before settlement confirms |
| Log every transaction for audit | Expose API keys in Telegram messages |
| Set reasonable timeouts (60–120s) | Assume instant settlement (takes 10–60s) |
| Test with small amounts first ($1 USD) | Use production merchant account before testing |
FAQ
Q: Does AgentPay charge a fee? A: No. AgentPay is open-source (MIT). You only pay your bank's standard wire/transfer fees (typically 0–0.5% in Vietnam).
Q: What if a user scans the QR but cancels payment?
A: await_settlement() will timeout and return settled=False. Send a friendly "Payment not received" message; they can retry.
Q: Can I use AgentPay outside Vietnam? A: VietQR is Vietnam-specific, so the merchant account must be at a Vietnamese bank. However, users can pay from international cards via some banks' apps.
Q: Is settlement guaranteed?
A: Yes. The bank feed is the source of truth. Once await_settlement() returns settled=True, the money is in your account.
Key Takeaways
- ✅ AgentPay removes payment friction: VietQR is instant, native to Vietnamese banking apps, and requires zero gateway setup.
- ✅ Your money stays yours: No platform hold or escrow. QR points directly to your bank account.
- ✅ 3-line integration:
create_payment_request()→checkout_url→await_settlement(). - ✅ Production-ready: Open-source, battle-tested, supports both Python SDK and MCP for AI agents.
- ✅ Multi-use: Courses, e-commerce, cafés, subscriptions, tips, donations—anywhere you need payment in a chat interface.
Getting Started Now
-
Install AgentPay VN:
bash pip install agentpay-vn -
Read the full docs: https://agentpay.servicesai.vn/v1/docs
-
Clone the GitHub repo for examples: https://github.com/phuocdu/agentpay-vn
-
Test with a small transaction (e.g., 10,000 VND / ~$0.40 USD) to confirm your merchant account and Telegram bot work end-to-end.
Your Telegram users deserve frictionless payments. AgentPay VN makes that possible—no gateway, no middleman, no delays. Start collecting payments in minutes.