I got tired of payment processors rejecting accounts and taking a 3% cut. So I built my own payment system using web3.py and USDC on Polygon.
How It Works
The core logic is surprisingly simple. USDC is an ERC-20 token, and every transfer emits a Transfer event. web3.py lets you read these events directly from the blockchain — no API key required.
from web3 import Web3
w3 = Web3(Web3.HTTPProvider("https://polygon-rpc.com"))
USDC = "0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359"
def verify_payment(tx_hash, expected_amount=9.99):
receipt = w3.eth.get_transaction_receipt(tx_hash)
for log in receipt["logs"]:
# Check Transfer event signature
if log["topics"][0].hex() == TRANSFER_TOPIC:
# Decode recipient and amount
recipient = "0x" + log["topics"][2].hex()[-40:]
amount = int(log["data"].hex(), 16) / 1e6 # USDC has 6 decimals
if recipient.lower() == MY_WALLET.lower() and amount >= expected_amount:
return True, amount
return False, 0
That's it. No Stripe SDK, no API keys, no webhooks. Just direct blockchain interaction.
Why Polygon?
- Gas fees: ~$0.01 per transaction
- Confirmation: 2-5 seconds
- USDC is stable (pegged to USD)
- Native web3.py support (EVM compatible)
The Full Stack
- Flask for the web app
- web3.py for on-chain verification
- SQLite for tracking payments
- Cloudflare Tunnel for public access
The entire payment integration is about 100 lines of Python. No third-party payment dependency.
Trade-offs
The obvious downside: users need a crypto wallet and some POL for gas. But for a developer tool audience, this is increasingly common. And the upside is massive:
- 0% processing fees
- No chargebacks
- Instant settlement
- Works globally — no country restrictions
- No account can be frozen or terminated
Live site: https://badge-market-asia-males.trycloudflare.com
Would love to hear how other indie hackers are handling payments!
Top comments (0)