Includes: - Backend services: ingestion (:8001), weather API (:8002), gateway (:8003), billing (:8004) with BTCPay integration - Shared asyncpg pool, TimescaleDB hypertable, Redis, Mosquitto MQTT - React frontend: Dashboard (MapLibre) and Messaging (chat UI) - Bridge daemon for Pi + Meshtastic (Serial/TCP T-Deck support) - Production Docker Compose, Nginx reverse proxy, ops scripts - DEPLOY.md with step-by-step deployment guide
3.9 KiB
KosmoConnect Billing Service
Integrates with BTCPay Server (pay.cqre.net) for subscription payments.
What It Does
- Invoice Creation: Generates BTCPay invoices for plan purchases (Wanderer, Guardian, Sanctuary)
- Webhook Handling: Listens to BTCPay Server webhooks and updates subscription status on payment
- Subscription Activation: On
InvoiceSettled, extends the user's active subscription in PostgreSQL - Invoice History: Lets users view their past invoices and payment status
Why BTCPay Server?
The Church of Kosmo operates its own payment infrastructure at pay.cqre.net. BTCPay Server is a self-hosted, open-source Bitcoin payment processor. It enables sovereign, censorship-resistant payments without relying on third-party card processors.
Plan Pricing
| Plan | Monthly Price | Messages | Scope |
|---|---|---|---|
| Wanderer | $5.00 | 50/month | Any node on the mesh |
| Guardian | $12.00 | 500/month | Only whitelisted nodes |
| Sanctuary | $50.00 | Unlimited | Any node + API/webhooks |
Prices are denominated in USD and paid via BTCPay Server (settled in BTC or Lightning, depending on store configuration).
Running Locally
cd backend
export BTCPAY_URL=https://pay.cqre.net
export BTCPAY_API_KEY=your_api_key_here
export BTCPAY_STORE_ID=your_store_id_here
export WEBHOOK_SECRET=your_webhook_secret_here
./run-dev.sh billing
BTCPay Server Setup Checklist
-
Create an API Key in your BTCPay Server instance with the following permissions:
Create invoiceView invoicesModify store webhooks
-
Create a Webhook in your BTCPay store pointing to:
https://your-kosmoconnect-instance/api/v1/billing/webhooks/btcpayEnable events:
Invoice createdInvoice received paymentInvoice processingInvoice expiredInvoice settledInvoice invalid
-
Set the Webhook Secret in the billing service (
WEBHOOK_SECRET) to verify webhook signatures.
API Endpoints
| Method | Path | Description |
|---|---|---|
| POST | /api/v1/billing/invoices |
Create a new invoice for a plan |
| GET | /api/v1/billing/invoices |
List user's invoices |
| GET | /api/v1/billing/invoices/{invoice_id} |
Get invoice details + sync status |
| POST | /api/v1/billing/webhooks/btcpay |
BTCPay webhook receiver |
Example: Create an Invoice
curl -X POST http://localhost:8004/api/v1/billing/invoices \
-H "Content-Type: application/json" \
-H "X-User-ID: 11111111-1111-1111-1111-111111111111" \
-d '{"plan_type": "wanderer", "redirect_url": "https://kosmoconnect.local/thank-you"}'
Response:
{
"invoice_id": "...",
"checkout_url": "https://pay.cqre.net/i/...",
"amount": 5.0,
"currency": "USD",
"plan_type": "wanderer"
}
Webhook Payload
The billing service expects standard BTCPay Server webhook payloads. On InvoiceSettled, it:
- Looks up the invoice in
btcpay_invoices - Deactivates the user's previous subscription
- Inserts a new active subscription with
valid_from = NOW()andvalid_until = NOW() + 30 days - Resets
messages_usedto0
Testing Webhooks Locally
If you can't expose localhost to BTCPay, you can simulate a webhook:
curl -X POST http://localhost:8004/api/v1/billing/webhooks/btcpay \
-H "Content-Type: application/json" \
-d '{
"type": "InvoiceSettled",
"invoiceId": "your-test-invoice-id",
"status": "Settled"
}'
Note: Webhook signature verification is skipped if WEBHOOK_SECRET is not set.
Troubleshooting
- "BTCPay not configured": Set
BTCPAY_URL,BTCPAY_API_KEY, andBTCPAY_STORE_IDenvironment variables. - 403 on webhook: Check that
WEBHOOK_SECRETmatches the secret configured in BTCPay Server. - Invoice not found on webhook: Ensure the invoice was created through the billing service (so the
btcpay_invoice_idexists in the database).