Accept Binance QR code, Bitcoin, USDT, USDC Pay directly into your wallet โ no merchant account, no KYC, 10-minute Python integration
Project description
๐ช Binance & Crypto Payment Gateway for Python
Accept Bitcoin, USDT, USDC, ETH, and BNB payments directly into your wallet โ no middleman, no merchant account, no KYC required.
Powered by PayerURL โ the direct-to-wallet crypto payment processor for Python developers.
๐ด LIVE DEMO | ๐ Get API Key | ๐ฌ Telegram Support
โ Why Developers Choose This Package
| Feature | Detail |
|---|---|
| ๐ฆ No merchant account needed | Payments go directly to your crypto wallet |
| ๐ 169+ fiat currencies | USD, EUR, GBP, CAD and more โ converted at live rates |
| โก 10-minute integration | Simple API, clear docs, copy-paste code |
| ๐ No KYC for withdrawals | Basic accounts withdraw without identity verification |
| ๐ฑ Binance QR Code payments | Customers scan and pay without leaving your app |
| ๐ธ Zero hidden fees | No network surcharges or platform fees |
| ๐ ๏ธ Django, Flask & FastAPI ready | Works with any Python web framework |
๐ฆ Installation
pip install binance-and-crypto-payment python-dotenv
๐ Get Your API Key (Free)
- Sign up at dash.payerurl.com
- Go to Dashboard โ Get API Credentials
- Copy your Public Key and Secret Key
๐ Registration is free and takes under 2 minutes. No credit card required.
๐ Secure Configuration
Create a .env file in your project root:
PAYERURL_PUBLIC_KEY=your_public_key
PAYERURL_SECRET_KEY=your_secret_key
BASE_URL=https://yourdomain.com
Add .env to .gitignore โ never commit your keys:
.env
In production โ skip the
.envfile entirely. Set these variables directly in your hosting dashboard (Railway, Render, Heroku, VPS).os.getenv()reads them automatically.
๐ Quick Start
import os
import time
from dotenv import load_dotenv
from binance_and_crypto_payment import CryptoPaymentClient
load_dotenv()
client = CryptoPaymentClient(
public_key=os.getenv("PAYERURL_PUBLIC_KEY"),
secret_key=os.getenv("PAYERURL_SECRET_KEY")
)
BASE_URL = os.getenv("BASE_URL", "http://localhost:8000").rstrip("/")
response = client.payment(
invoice_id=f"PYP-{int(time.time())}",
amount=10.00,
currency="USD",
items=[{"name": "Product", "qty": "1", "price": "10.00"}],
data={
"first_name": "John",
"last_name": "Doe",
"email": "john@example.com",
"redirect_url": f"{BASE_URL}/payment/success/",
"notify_url": f"{BASE_URL}/payment/notify/",
"cancel_url": f"{BASE_URL}/payment/cancel/",
}
)
print(response)
# {'status': True, 'redirect_to': 'https://api-v2.payerurl.com/web-payment-option/PYP...'}
# Redirect the customer to the payment page
payment_url = response["redirect_to"]
๐ Supported Cryptocurrencies & Networks
| Currency | Networks |
|---|---|
| USDT | TRC20 (Tron), ERC20 (Ethereum), BEP20 (BSC) |
| USDC | ERC20 (Ethereum), BEP20 (BSC) |
| Bitcoin (BTC) | Bitcoin Network |
| Ethereum (ETH) | ERC20 |
| BNB | BEP20 (BSC) |
| Binance Pay | Binance QR Code |
๐ Django Integration
# views.py
import os
import time
import logging
from dotenv import load_dotenv
from django.shortcuts import redirect, render
from django.http import JsonResponse, HttpResponse
from django.views import View
from django.views.decorators.csrf import csrf_exempt
from django.views.decorators.http import require_POST
from binance_and_crypto_payment import CryptoPaymentClient, CryptoPaymentNotify, CryptoPaymentException
load_dotenv()
PUBLIC_KEY = os.getenv("PAYERURL_PUBLIC_KEY")
SECRET_KEY = os.getenv("PAYERURL_SECRET_KEY")
BASE_URL = os.getenv("BASE_URL", "http://localhost:8000").rstrip("/")
if not PUBLIC_KEY or not SECRET_KEY:
raise ValueError("PAYERURL_PUBLIC_KEY and PAYERURL_SECRET_KEY must be set in .env")
logger = logging.getLogger(__name__)
# โโ Checkout โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
class CheckoutView(View):
def post(self, request):
client = CryptoPaymentClient(public_key=PUBLIC_KEY, secret_key=SECRET_KEY)
response = client.payment(
invoice_id=f"PYP-{int(time.time())}",
amount=float(request.POST.get("amount", 10.00)),
currency="USD",
items=[{
"name": request.POST.get("product", "Order"),
"qty": "1",
"price": request.POST.get("amount", "10.00"),
}],
data={
"first_name": request.user.first_name,
"last_name": request.user.last_name,
"email": request.user.email,
"redirect_url": f"{BASE_URL}/payment/success/",
"notify_url": f"{BASE_URL}/payment/notify/",
"cancel_url": f"{BASE_URL}/payment/cancel/",
}
)
return redirect(response["redirect_to"])
# โโ Success Callback โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
def payment_success(request):
order_id = request.GET.get("order_id", "")
# YOUR LOGIC HERE โ e.g. show order confirmation page
return HttpResponse(f"Payment successful! Order: {order_id}")
# โโ Cancel Callback โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
def payment_cancel(request):
order_id = request.GET.get("order_id", "")
# YOUR LOGIC HERE โ e.g. show cancel page or redirect to cart
return HttpResponse(f"Payment cancelled. Order: {order_id}")
# โโ Notify (Webhook) โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
@csrf_exempt
@require_POST
def notify_payerurl(request):
notify = CryptoPaymentNotify(public_key=PUBLIC_KEY, secret_key=SECRET_KEY)
try:
result = notify.process(request)
except CryptoPaymentException as e:
logger.warning(f"[NOTIFY] Failed: {e.code} | {e.message}")
return JsonResponse({"status": e.code, "message": e.message}, status=200)
except Exception as e:
logger.exception(f"[NOTIFY] Unexpected error: {e}")
return JsonResponse({"status": 5000, "message": "Internal error"}, status=200)
if result["type"] == "cancelled":
logger.info(f"[NOTIFY] Cancelled: {result['data'].get('order_id')}")
return JsonResponse({"status": 20000, "message": "Order cancelled"}, status=200)
data = result["data"]
logger.info(f"[NOTIFY] Success: {data}")
try:
# data["order_id"] โ your invoice ID
# data["transaction_id"] โ gateway transaction ID
# data["confirm_rcv_amnt"] โ amount received
# data["coin_rcv_amnt"] โ crypto amount
# data["txn_time"] โ transaction time
# YOUR BUSINESS LOGIC HERE
# e.g. update your DB, send email, activate subscription, etc.
return JsonResponse({"status": 2040, "message": "Payment processed successfully"}, status=200)
except Exception as e:
logger.exception(f"[NOTIFY] Business logic error: {e}")
return JsonResponse({"status": 5000, "message": "Internal error"}, status=200)
# urls.py
from django.urls import path
from .views import CheckoutView, payment_success, payment_cancel, notify_payerurl
urlpatterns = [
path("payment/checkout/", CheckoutView.as_view(), name="checkout"),
path("payment/success/", payment_success, name="payment_success"),
path("payment/cancel/", payment_cancel, name="payment_cancel"),
path("payment/notify/", notify_payerurl, name="payment_notify"),
]
๐ Flask Integration
# app.py
import os
import time
from dotenv import load_dotenv
from flask import Flask, request, redirect, jsonify
from binance_and_crypto_payment import CryptoPaymentClient, CryptoPaymentNotify, CryptoPaymentException
load_dotenv()
PUBLIC_KEY = os.getenv("PAYERURL_PUBLIC_KEY")
SECRET_KEY = os.getenv("PAYERURL_SECRET_KEY")
BASE_URL = os.getenv("BASE_URL", "http://localhost:5000").rstrip("/")
if not PUBLIC_KEY or not SECRET_KEY:
raise ValueError("PAYERURL_PUBLIC_KEY and PAYERURL_SECRET_KEY must be set in .env")
app = Flask(__name__)
# โโ Checkout โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
@app.route("/payment/checkout/", methods=["POST"])
def checkout():
client = CryptoPaymentClient(public_key=PUBLIC_KEY, secret_key=SECRET_KEY)
response = client.payment(
invoice_id=f"PYP-{int(time.time())}",
amount=float(request.form.get("amount", 10.00)),
currency="USD",
items=[{
"name": request.form.get("product", "Order"),
"qty": "1",
"price": request.form.get("amount", "10.00"),
}],
data={
"first_name": request.form.get("first_name"),
"last_name": request.form.get("last_name"),
"email": request.form.get("email"),
"redirect_url": f"{BASE_URL}/payment/success/",
"notify_url": f"{BASE_URL}/payment/notify/",
"cancel_url": f"{BASE_URL}/payment/cancel/",
}
)
return redirect(response["redirect_to"])
# โโ Success Callback โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
@app.route("/payment/success/")
def payment_success():
order_id = request.args.get("order_id", "")
# YOUR LOGIC HERE โ e.g. show order confirmation page
return f"Payment successful! Order: {order_id}"
# โโ Cancel Callback โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
@app.route("/payment/cancel/")
def payment_cancel():
order_id = request.args.get("order_id", "")
# YOUR LOGIC HERE โ e.g. show cancel page or redirect to cart
return f"Payment cancelled. Order: {order_id}"
# โโ Notify (Webhook) โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
@app.route("/payment/notify/", methods=["POST"])
def notify_payerurl():
notify = CryptoPaymentNotify(public_key=PUBLIC_KEY, secret_key=SECRET_KEY)
try:
result = notify.process(request)
except CryptoPaymentException as e:
return jsonify({"status": e.code, "message": e.message}), 200
except Exception:
return jsonify({"status": 5000, "message": "Internal error"}), 200
if result["type"] == "cancelled":
return jsonify({"status": 20000, "message": "Order cancelled"}), 200
data = result["data"]
# data["order_id"] โ your invoice ID
# data["transaction_id"] โ gateway transaction ID
# data["confirm_rcv_amnt"] โ amount received
# data["coin_rcv_amnt"] โ crypto amount
# data["txn_time"] โ transaction time
# YOUR BUSINESS LOGIC HERE
# e.g. update your DB, send email, activate subscription, etc.
return jsonify({"status": 2040, "message": "Payment processed successfully"}), 200
if __name__ == "__main__":
app.run(debug=True)
๐ FastAPI Integration
# main.py
import os
import time
from dotenv import load_dotenv
from fastapi import FastAPI, Request, Form
from fastapi.responses import JSONResponse, RedirectResponse, PlainTextResponse
from binance_and_crypto_payment import CryptoPaymentClient, CryptoPaymentNotify, CryptoPaymentException
load_dotenv()
PUBLIC_KEY = os.getenv("PAYERURL_PUBLIC_KEY")
SECRET_KEY = os.getenv("PAYERURL_SECRET_KEY")
BASE_URL = os.getenv("BASE_URL", "http://localhost:8000").rstrip("/")
if not PUBLIC_KEY or not SECRET_KEY:
raise ValueError("PAYERURL_PUBLIC_KEY and PAYERURL_SECRET_KEY must be set in .env")
app = FastAPI()
# โโ Checkout โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
@app.post("/payment/checkout/")
async def checkout(
amount: float = Form(...),
first_name: str = Form(...),
last_name: str = Form(...),
email: str = Form(...),
product: str = Form("Order"),
):
client = CryptoPaymentClient(public_key=PUBLIC_KEY, secret_key=SECRET_KEY)
response = client.payment(
invoice_id=f"PYP-{int(time.time())}",
amount=amount,
currency="USD",
items=[{"name": product, "qty": "1", "price": str(amount)}],
data={
"first_name": first_name,
"last_name": last_name,
"email": email,
"redirect_url": f"{BASE_URL}/payment/success/",
"notify_url": f"{BASE_URL}/payment/notify/",
"cancel_url": f"{BASE_URL}/payment/cancel/",
}
)
return RedirectResponse(url=response["redirect_to"])
# โโ Success Callback โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
@app.get("/payment/success/")
async def payment_success(order_id: str = ""):
# YOUR LOGIC HERE โ e.g. return confirmation page
return PlainTextResponse(f"Payment successful! Order: {order_id}")
# โโ Cancel Callback โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
@app.get("/payment/cancel/")
async def payment_cancel(order_id: str = ""):
# YOUR LOGIC HERE โ e.g. return cancel page or redirect to cart
return PlainTextResponse(f"Payment cancelled. Order: {order_id}")
# โโ Notify (Webhook) โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
@app.post("/payment/notify/")
async def notify_payerurl(request: Request):
notify = CryptoPaymentNotify(public_key=PUBLIC_KEY, secret_key=SECRET_KEY)
try:
result = notify.process(request)
except CryptoPaymentException as e:
return JSONResponse({"status": e.code, "message": e.message}, status_code=200)
except Exception:
return JSONResponse({"status": 5000, "message": "Internal error"}, status_code=200)
if result["type"] == "cancelled":
return JSONResponse({"status": 20000, "message": "Order cancelled"}, status_code=200)
data = result["data"]
# data["order_id"] โ your invoice ID
# data["transaction_id"] โ gateway transaction ID
# data["confirm_rcv_amnt"] โ amount received
# data["coin_rcv_amnt"] โ crypto amount
# data["txn_time"] โ transaction time
# YOUR BUSINESS LOGIC HERE
# e.g. update your DB, send email, activate subscription, etc.
return JSONResponse({"status": 2040, "message": "Payment processed successfully"}, status_code=200)
Run:
uvicorn main:app --reload
๐ Handling Webhooks (notify_url)
When a payment completes, PayerURL sends a POST request to your notify_url. The CryptoPaymentNotify class handles all validation automatically โ auth check, signature verification, and status detection.
result = notify.process(request)
# result["type"] โ "success" or "cancelled"
# result["data"] โ full webhook payload
Callback URL Summary
| URL | Trigger | Method |
|---|---|---|
redirect_url |
Customer paid successfully | GET (browser redirect) |
cancel_url |
Customer cancelled payment | GET (browser redirect) |
notify_url |
Gateway confirms payment server-side | POST (webhook) |
redirect_urlandcancel_urlare browser redirects โ use them to show the customer a page.notify_urlis a server-side webhook โ use it to update your database.
Webhook Payload Fields
| Field | Description |
|---|---|
order_id |
Your original invoice ID |
transaction_id |
Blockchain transaction hash |
status_code |
200 = completed, 20000 = cancelled |
confirm_rcv_amnt |
Amount received in fiat |
confirm_rcv_amnt_curr |
Fiat currency (e.g. USD) |
coin_rcv_amnt |
Amount received in crypto |
coin_rcv_amnt_curr |
Crypto symbol (e.g. USDT) |
txn_time |
Transaction timestamp |
Notify Response Codes
| Code | Meaning |
|---|---|
2040 |
Payment processed successfully |
2030 |
Auth error (key mismatch or missing) |
2031 |
Auth format error (invalid base64) |
2050 |
Validation error (missing fields or incomplete order) |
20000 |
Order cancelled |
5000 |
Internal server error |
Always return HTTP
200for all responses โ including errors. PayerURL reads the JSONstatusfield, not the HTTP status code. Returning non-200 HTTP status will cause the gateway to retry indefinitely.
๐ฒ How the Binance QR Payment Works
- Your app calls the API and gets a payment URL
- Customer is redirected to a secure checkout page
- Customer scans the QR code with their Binance app
- Payment is confirmed and funds land directly in your wallet
- Your
notify_urlreceives a webhook with the order status
No bank accounts. No intermediaries. No waiting.
๐ก๏ธ Security & Privacy
- โ Payments go directly to your wallet โ PayerURL never holds your funds
- โ No mandatory KYC for basic accounts
- โ
HMAC-SHA256 signature verification on all webhook calls via
CryptoPaymentNotify - โ MIT licensed โ fully open source, audit it yourself
- โ No personal identity verification required to get started
๐ Supported Fiat Currencies (169+)
USD, EUR, GBP, CAD, AUD, JPY, SGD, AED, INR, BRL, MXN, NGN, PKR, BDT, and 150+ more.
All fiat amounts are automatically converted to the equivalent crypto amount at live market rates.
๐ Full Payment Flow
Your App โโโบ PayerURL API โโโบ Checkout Page โโโบ Customer Pays
โ
Your Wallet โโโ Funds (instant) โโโ Blockchain Confirmed โ
โ โ
redirect_url (success/cancel) โโโโโโโโโ โ
notify_url (webhook) โโโโโโโโโโโโโโโโโโ
๐ Compared to Other Solutions
| PayerURL (This Package) | Stripe / PayPal | Coinbase Commerce | |
|---|---|---|---|
| No merchant account | โ | โ | โ |
| Direct to your wallet | โ | โ | Partial |
| No KYC required | โ (Basic) | โ | โ |
| Binance QR support | โ | โ | โ |
| Python SDK | โ | โ | โ |
| Django / Flask / FastAPI | โ | โ | โ |
| 169+ fiat currencies | โ | Partial | โ |
| Zero platform fees | โ | โ | โ |
| Webhook support | โ | โ | โ |
โ FAQ
Do I need a Binance account? Yes, to accept Binance QR payments. For USDT/BTC/ETH/USDC, you only need the corresponding wallet address configured in your PayerURL dashboard.
Is there a transaction fee? No platform fees from PayerURL. Standard blockchain network fees may apply depending on the coin and network.
Can I use this without KYC? Yes. Basic accounts can receive and withdraw crypto without mandatory identity verification.
What should my notify_url return?
Return {"status": 2040, "message": "Payment processed successfully"} with HTTP 200. Always return HTTP 200 for all responses โ the gateway reads the JSON status field.
What is the difference between redirect_url and notify_url?
redirect_url is a browser redirect shown to the customer after payment. notify_url is a server-side webhook used to update your database โ it fires independently of what the customer does.
How do I identify errors from the notify response?
Check the status field in the JSON body. 2030/2031 = auth errors, 2050 = validation error, 20000 = cancelled, 2040 = success, 5000 = internal error.
Does this work with Django REST Framework / FastAPI? Yes โ it is a pure Python client that works with any Python web framework.
What Python versions are supported? Python 3.8 and above (3.8, 3.9, 3.10, 3.11, 3.12, 3.13).
๐ฌ Support
| Channel | Link |
|---|---|
| ๐ฌ Telegram | t.me/Payerurl |
| ๐ Website | payerurl.com |
| ๐ Dashboard | dash.payerurl.com |
| ๐ด Live Demo | python.payerurl.com |
๐ License
MIT License โ free for personal and commercial use.
๐ Keywords
crypto bitcoin ethereum binance coinbase usdt usdc bnb tron payment payment-gateway crypto-payment-gateway cryptocurrency-payment bitcoin-payment binance-pay binance-api accept-crypto crypto-checkout django-payment flask-payment fastapi-payment usdt-trc20 usdt-erc20 no-kyc-payment instant-settlement crypto-webhook direct-to-wallet credit-card-to-crypto
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file binance_and_crypto_payment-0.1.24.tar.gz.
File metadata
- Download URL: binance_and_crypto_payment-0.1.24.tar.gz
- Upload date:
- Size: 16.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.15
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
568e20de09dda8e11e3daff6e2a527fafd183cac877c3857a22cff5502b6996a
|
|
| MD5 |
b10f0bd76cc3d3caf705b766dc55d55f
|
|
| BLAKE2b-256 |
e091465246d483bf514aa393cdb91a26b9022e01811c70de3bf2983c87d1b133
|
File details
Details for the file binance_and_crypto_payment-0.1.24-py3-none-any.whl.
File metadata
- Download URL: binance_and_crypto_payment-0.1.24-py3-none-any.whl
- Upload date:
- Size: 11.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.15
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d0e51b9a30befdaba0328db0dc4a72cfa5c0e7f6ad68b041875dba205538cc96
|
|
| MD5 |
c524cf83b59607598adebe301a2e5973
|
|
| BLAKE2b-256 |
3554f03740bdd1cebe2f30609ecbf05d4c26066e4d0538805d78c4d9d6d7c93f
|