Tags: python discord-bot stripe automation
âAutomation isnât about replacing people â itâs about freeing them to do the work that truly matters.â â Anonymous
If youâre running a SaaS product that serves AI developers, crypto enthusiasts, or dataâanalysis teams, you already know the biggest bottleneck is getting the word out. A daily reminder in the right Discord communities can be a gameâchanger, especially when you pair it with a readyâtoâpay Stripe Checkout link. In this article Iâll walk you through a complete, productionâready Discord bot (named discord_bot.py) that:
- Securely loads your Discord token from the environment.
- Targets specific servers/channels (e.g., âAI Devâ, âFreelanceâ, âDev Communitiesâ).
- Generates Stripe Checkout URLs for two pricing tiers (test mode â live mode).
- Crafts a concise promotional message.
- Handles Discord rate limits with exponential backâoff.
- Logs every sent message (timestamp + server ID) for conversion tracking.
- Posts the promo once per day per server, forever.
-
Provides an onâdemand
!pricecommand that replies with the product details.
All the code is selfâcontained, uses only wellâmaintained libraries (discord.py, stripe, pythonâdotenv), and follows best practices for reliability and security.
đŻ Why This Bot Matters
- AI & Crypto Communities are fastâmoving. A single wellâtimed reminder can push a curious member from âmaybeâ to âbuy nowâ.
- Stripe Checkout handles PCI compliance, tax calculations, and receipt generation for you. All you need is a URL.
- Exponential backâoff guarantees your bot respects Discordâs rateâlimit policy, preventing bans.
- Logging each dispatch gives you the data you need to calculate ROI (clickâthrough â conversion).
đ ď¸ Prerequisites
| Requirement | How to Install |
|---|---|
| PythonâŻ3.10+ |
sudo apt-get install python3 (or your favourite package manager) |
discord.py (v2.x) |
pip install -U discord.py |
stripe SDK |
pip install stripe |
python-dotenv (for env files) |
pip install python-dotenv |
| A Discord Bot token | Create a bot on the Discord Developer Portal and invite it to your servers with bot + applications.commands scopes. |
| Stripe account (test & live) | Signâup at https://stripe.com, get your Publishable and Secret keys. |
Create a .env file in the same folder as discord_bot.py:
DISCORD_TOKEN=YOUR_DISCORD_BOT_TOKEN
STRIPE_SECRET_KEY=sk_test_XXXXXXXXXXXXXXXXXXXXXXXX
STRIPE_PUBLISHABLE_KEY=pk_test_XXXXXXXXXXXXXXXXXXXXXXXX
STRIPE_MODE=TEST # Change to LIVE when youâre ready to go live
Tip: Never commit
.envto version control. Add it to.gitignore.
đ The Full Script â discord_bot.py
python
#!/usr/bin/env python3
"""
discord_bot.py
A dailyâposting Discord bot that advertises two Stripeâcheckout products.
"""
import os
import asyncio
import logging
from datetime import datetime
from typing import List, Tuple
import discord
from discord.ext import tasks, commands
import stripe
from dotenv import load_dotenv
# -------------------------------------------------
# 1ď¸âŁ Load environment variables & configure Stripe
# -------------------------------------------------
load_dotenv()
DISCORD_TOKEN = os.getenv("DISCORD_TOKEN")
STRIPE_SECRET_KEY = os.getenv("STRIPE_SECRET_KEY")
STRIPE_MODE = os.getenv("STRIPE_MODE", "TEST").upper()
if not DISCORD_TOKEN or not STRIPE_SECRET_KEY:
raise RuntimeError("Missing DISCORD_TOKEN or STRIPE_SECRET_KEY in .env")
stripe.api_key = STRIPE_SECRET_KEY
# -------------------------------------------------
# 2ď¸âŁ Target server & channel IDs (replace with your own)
# -------------------------------------------------
# Structure: List[Tuple[GuildID, ChannelID]]
TARGETS: List[Tuple[int, int]] = [
# AI Development community
(123456789012345678, 987654321098765432), # (guild_id, channel_id)
# Freelance dev hub
(234567890123456789, 876543210987654321),
# General dev community
(345678901234567890, 765432109876543210),
]
# -------------------------------------------------
# 3ď¸âŁ Stripe product & price configuration
# -------------------------------------------------
# These IDs can be created manually in the Stripe Dashboard or via the API.
# For demo purposes weâll create them onâtheâfly in test mode.
PRODUCTS = {
"basic": {
"name": "AIâAssist Starter",
"description": "Access to the core AIâassist API (1000 calls/mo).",
"price_cents": 999, # $9.99
},
"pro": {
"name": "AIâAssist Pro",
"description": "Unlimited calls + priority support.",
"price_cents": 4999, # $49.99
},
}
def create_checkout_session(product_key: str) -> str:
"""
Returns a Stripe Checkout URL for the given product.
In TEST mode we use the test mode URL; in LIVE we rely on the same URL
because Stripe automatically routes based on the secret key.
"""
product = PRODUCTS[product_key]
session = stripe.checkout.Session.create(
payment_method_types=["card"],
line_items=[{
"price_data": {
"currency": "usd",
"product_data": {
"name": product["name"],
"description": product["description"],
},
"unit_amount": product["price_cents"],
},
"quantity": 1,
}],
mode="payment",
success_url="https://yourdomain.com/success?session_id={CHECKOUT_SESSION_ID}",
cancel_url="https://yourdomain.com/cancel",
)
return session.url # This is a fullyâqualified HTTPS URL
# Preâgenerate URLs once on startâup (theyâre static for a given price)
CHECKOUT_URLS = {
"basic": create_checkout_session("basic"),
"pro": create_checkout_session("pro"),
}
# -------------------------------------------------
# 4ď¸âŁ Compose promotional message (keep it short)
# -------------------------------------------------
PROMO_MESSAGE = (
"**đ Boost Your AI Workflow Today!**\n"
"⢠**Starter** â $9.99/month â 1,000 calls\n"
"⢠**Pro** â $49.99/month â Unlimited + priority support\n"
"Ready to level up? Grab a plan now:\n"
f"đš **Starter:** {CHECKOUT_URLS['basic']}\n"
f"đš **Pro:** {CHECKOUT_URLS['pro']}\n"
"*Limitedâtime discount for Discord community members!*"
)
# -------------------------------------------------
# 5ď¸âŁ Bot definition with exponential backâoff
# -------------------------------------------------
intents = discord.Intents.default()
intents.message_content = True # Needed for commands that read content
bot = commands.Bot(command_prefix="!", intents=intents)
# Simple exponential backâoff helper
async def safe_send(channel: discord.TextChannel, content: str, max_retries: int = 5):
delay = 1 # start with 1 second
for attempt in range(max_retries):
try:
await channel.send(content)
return True
except discord.HTTPException as exc:
# 429 = rateâlimit
if exc.status == 429:
logging.warning(
f"Rate limited on attempt {attempt+1}. Backâoff {delay}s."
)
await asyncio.sleep(delay)
delay = min(delay * 2, 60) # cap at 60s
else:
logging.error(f"Failed to send message: {exc}")
Top comments (0)