DEV Community

Anna lilith
Anna lilith

Posted on

How to Accept Bitcoin Payments in Your Python Application

How to Accept Bitcoin Payments in Your Python Application

Last updated: July 2026

Accepting Bitcoin payments in your Python application is straightforward with the right tools. This guide shows you how to integrate BTC payments that work globally, with no middlemen.

Why Accept Bitcoin?

  • No chargebacks: Transactions are final
  • Global reach: Anyone can pay, anywhere
  • Low fees: Typically 1-3% vs 2.5-3.5% for cards
  • Privacy: No need to collect personal financial data
  • Instant settlement: No waiting for bank transfers

Option 1: Direct Integration (No Third Party)

The simplest approach - accept BTC directly to your wallet:

import requests
import time

def get_btc_balance(address):
    """Check BTC balance using Blockstream API."""
    url = f"https://blockstream.info/api/address/{address}"
    resp = requests.get(url, timeout=10)
    data = resp.json()

    # Calculate balance from UTXOs
    balance = 0
    for tx in data.get("chain_stats", []):
        balance += tx.get("funded_txo_sum", 0)
        balance -= tx.get("spent_txo_sum", 0)

    return balance / 100_000_000  # Convert from satoshis

def create_invoice(amount_btc, product_id):
    """Create a payment invoice."""
    return {
        "invoice_id": f"inv_{int(time.time())}",
        "amount": amount_btc,
        "product": product_id,
        "status": "pending",
        "created_at": time.time()
    }

def check_payment(invoice_id, address):
    """Check if invoice has been paid."""
    balance = get_btc_balance(address)
    return balance > 0
Enter fullscreen mode Exit fullscreen mode

Option 2: Using BTCPay Server (Self-Hosted)

BTCPay Server is free, open-source, and self-hosted:

import requests

BTCPAY_URL = "https://your-btcpay-server.com"
BTCPAY_TOKEN = "your_api_token"

def create_btcpay_invoice(amount_sats, product_id):
    """Create invoice via BTCPay Server."""
    resp = requests.post(
        f"{BTCPAY_URL}/api/v1/invoices",
        headers={"Authorization": f"token {BTCPAY_TOKEN}"},
        json={
            "amount": amount_sats,
            "currency": "BTC",
            "metadata": {"product_id": product_id}
        }
    )
    return resp.json()

def check_btcpay_status(invoice_id):
    """Check invoice status."""
    resp = requests.get(
        f"{BTCPAY_URL}/api/v1/invoices/{invoice_id}",
        headers={"Authorization": f"token {BTCPAY_TOKEN}"}
    )
    return resp.json()["status"] == "complete"
Enter fullscreen mode Exit fullscreen mode

Option 3: Using a Payment Processor

Services like BitPay or CoinGate handle everything:

# Example with a generic processor
def create_processor_invoice(amount_usd, product_id):
    """Create invoice via payment processor."""
    resp = requests.post(
        "https://api.processor.com/invoices",
        headers={"Authorization": "Bearer your_key"},
        json={
            "price_amount": amount_usd,
            "price_currency": "USD",
            "receive_currency": "BTC",
            "order_id": product_id
        }
    )
    return resp.json()
Enter fullscreen mode Exit fullscreen mode

Complete Payment Flow

import hashlib

class BitcoinPaymentHandler:
    def __init__(self, btc_address):
        self.btc_address = btc_address
        self.payments = {}

    def create_payment(self, user_id, amount_btc, product_id):
        """Create a new payment request."""
        payment_id = hashlib.sha256(
            f"{user_id}-{product_id}-{int(time.time())}".encode()
        ).hexdigest()[:16]

        self.payments[payment_id] = {
            "user_id": user_id,
            "amount": amount_btc,
            "product": product_id,
            "address": self.btc_address,
            "status": "pending",
            "created_at": time.time()
        }

        return payment_id

    def check_payment(self, payment_id):
        """Check if payment was received."""
        payment = self.payments.get(payment_id)
        if not payment:
            return False

        # Check blockchain
        balance = get_btc_balance(payment["address"])
        if balance >= payment["amount"]:
            payment["status"] = "paid"
            return True

        return False

    def get_payment_status(self, payment_id):
        """Get current payment status."""
        payment = self.payments.get(payment_id)
        if not payment:
            return "not_found"

        # Auto-expire after 24 hours
        if time.time() - payment["created_at"] > 86400:
            payment["status"] = "expired"

        return payment["status"]
Enter fullscreen mode Exit fullscreen mode

Security Best Practices

  1. Never reuse addresses: Generate a new address for each payment
  2. Wait for confirmations: At least 1 confirmation for small amounts, 3+ for large
  3. Validate amounts: Check the exact amount sent, not just "any" payment
  4. Log everything: Keep detailed records for accounting
  5. Use HTTPS: Never transmit payment info over HTTP

Get the Production-Ready Version

We have a complete Bitcoin payment integration at our store.

What's included:

  • Bitcoin and Monero support
  • Automatic payment verification
  • Invoice management
  • Webhook support
  • Easy integration with any Python app

Browse the collection →

Top comments (0)