DEV Community

How I Built a Telegram Bot That Sells Digital Products (Complete Guide)

From Zero to Revenue-Generating Bot

I built a Telegram bot that sells 26+ digital products with Telegram Stars payments. Here's the complete technical breakdown.

Tech Stack

  • Python 3.11 + pyTelegramBotAPI
  • SQLite for user tracking
  • fpdf2 for PDF generation
  • Telegram Stars for payments (no Stripe needed!)

Step 1: Bot Setup

import telebot
from telebot.types import LabeledPrice

BOT_TOKEN = "your_token_here"
bot = telebot.TeleBot(BOT_TOKEN)

@bot.message_handler(commands=['start'])
def start(message):
    bot.send_message(
        message.chat.id,
        "Welcome to SwiftUI Dev Shop!\n"
        "Browse products with /catalog"
    )
Enter fullscreen mode Exit fullscreen mode

Step 2: Product Catalog

PRODUCTS = {
    "swiftui_starter": {
        "name": "SwiftUI Starter Kit Pro",
        "description": "Complete project templates, network layer, auth flow",
        "price_stars": 65,
        "file": "products/swiftui_starter.pdf"
    },
    # ... more products
}

@bot.message_handler(commands=['catalog'])
def catalog(message):
    for key, product in PRODUCTS.items():
        text = f"*{product['name']}*\n{product['description']}\nPrice: {product['price_stars']} Stars"
        markup = telebot.types.InlineKeyboardMarkup()
        markup.add(telebot.types.InlineKeyboardButton(
            "Buy Now", callback_data=f"buy_{key}"
        ))
        bot.send_message(message.chat.id, text, parse_mode="Markdown", reply_markup=markup)
Enter fullscreen mode Exit fullscreen mode

Step 3: Telegram Stars Payment

This is the key part. Telegram Stars is a built-in payment system — no external payment provider needed.

@bot.callback_query_handler(func=lambda call: call.data.startswith("buy_"))
def handle_buy(call):
    product_key = call.data.replace("buy_", "")
    product = PRODUCTS[product_key]

    prices = [LabeledPrice(label=product['name'], amount=product['price_stars'])]

    bot.send_invoice(
        call.message.chat.id,
        title=product['name'],
        description=product['description'],
        invoice_payload=f"buy_{product_key}",
        provider_token="",  # Empty for Stars!
        currency="XTR",     # Telegram Stars currency
        prices=prices
    )

@bot.pre_checkout_query_handler(func=lambda query: True)
def pre_checkout(query):
    bot.answer_pre_checkout_query(query.id, ok=True)

@bot.message_handler(content_types=['successful_payment'])
def successful_payment(message):
    payload = message.successful_payment.invoice_payload
    product_key = payload.replace("buy_", "")
    product = PRODUCTS[product_key]

    with open(product['file'], 'rb') as f:
        bot.send_document(message.chat.id, f)

    bot.send_message(message.chat.id, "Thank you for your purchase!")
Enter fullscreen mode Exit fullscreen mode

Step 4: User Tracking with SQLite

import sqlite3

def init_db():
    conn = sqlite3.connect('shop.db')
    c = conn.cursor()
    c.execute('''CREATE TABLE IF NOT EXISTS users (
        user_id INTEGER PRIMARY KEY,
        username TEXT,
        first_name TEXT,
        joined_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
    )''')
    c.execute('''CREATE TABLE IF NOT EXISTS payments (
        id INTEGER PRIMARY KEY AUTOINCREMENT,
        user_id INTEGER,
        product_key TEXT,
        amount INTEGER,
        created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
    )''')
    conn.commit()
    conn.close()
Enter fullscreen mode Exit fullscreen mode

Step 5: PDF Product Generation

I use fpdf2 with custom fonts to generate professional-looking PDF products from Markdown files.

from fpdf import FPDF

class ProductPDF(FPDF):
    def header(self):
        self.set_font("DejaVu", "I", 8)
        self.cell(0, 10, "SwiftUI Dev Shop", align="C")

    def footer(self):
        self.set_y(-15)
        self.set_font("DejaVu", "I", 8)
        self.cell(0, 10, f"Page {self.page_no()}", align="R")
Enter fullscreen mode Exit fullscreen mode

Results

  • 26 products in the catalog
  • 3 bundles with discounts
  • Automated delivery — no manual work
  • Revenue tracking via SQLite

Key Takeaways

  1. Telegram Stars removes payment friction — users already have Stars
  2. Python + SQLite is enough — no need for complex backends
  3. PDF products have near-zero marginal cost — create once, sell forever
  4. Automation is everything — the bot runs 24/7 without my input

Want to build your own? Ask questions in the comments!

Follow me: @SwiftUIDaily on Telegram

Top comments (0)