Product feedback

Add Dodo Payments Integration
Native payment provider integration for usage-based billing. Why We Want to Integrate with Lago? Dodo Payments serves global markets with Merchant of Record capabilities. This integration would: • Complement Lago's existing providers (Stripe, Adyen, GoCardless) with coverage in underserved regions. • Follow the partnership model established with MoneyHash for regional payment processors. Be maintained long-term by the Dodo Payments team. This aligns with Lago's stated goal of supporting local payment processors alongside global providers. Summary: This issue tracks building a first-class integration between Lago (usage-based billing) and Dodo Payments to support automatic invoice charging, realtime webhook sync, and refunds. The integration should be usable either as a native Ruby (Rails) plugin for Lago or as a lightweight TypeScript/Bun microservice. Goals: • Create payment intents in Dodo when Lago emits invoice.created . • Update Lago invoice/payment state on Dodo webhook events ( payment.succeeded , payment.failed , payment.refunded ). • Support refund flows by creating Lago credit notes when Dodo reports refunds. • Provide secure, idempotent webhook handling with HMAC verification. • Provide clear setup docs and example code for both native and microservice approaches. Acceptance Criteria • When an invoice is created in Lago, a Dodo payment intent is created with lago_invoice_id in metadata. • payment.succeeded marks the Lago invoice as paid . • payment.failed marks the Lago invoice as failed and triggers retry logic per config. • payment.refunded creates a Lago credit note and links to the original invoice. • All webhooks validated via HMAC; log & retry on transient failures. • Integration can be deployed as a Docker container and run with env vars only. • README and docs include setup, testing, and troubleshooting steps. Requirements Lago >= v1.0 Microservice: Bun >= 1.0 / Node 18+ (TypeScript) PostgreSQL 14+ (for microservice if persistence needed) Dodo API & webhook keys (sandbox/live) TLS/HTTPS for webhook endpoints Auth / Headers: Dodo: Authorization: Bearer DODO_API_KEY Lago: Authorization: Bearer LAGO_API_KEY Webhook mapping: Source: Lago • Event: invoice.created • Action: Create a Dodo payment intent (with metadata lago_invoice_id) Source: Dodo • Event: payment.succeeded • Action: Mark the Lago invoice as paid Source: Dodo • Event: payment.failed • Action: Mark the Lago invoice as failed and trigger retry logic Source: Dodo • Event: payment.refunded • Action: Create a Lago credit note and link it to the invoice Webhook endpoints: • Dodo → Integration: POST https://<HOST>/webhooks/dodo • Lago → Integration: POST https://<HOST>/webhooks/lago Retry & Idempotency: • Persist dodo_payment_id ↔ lago_invoice_id mapping to prevent double-processing. • Use Dodo idempotency keys for create payment intent requests (e.g., Idempotency-Key: lago-inv-<id> ). • Webhook handler should: • Verify HMAC signature. • Check if event has been processed (by event id). • Acknowledge 2xx on success; return 5xx for transient errors to allow retries. Security: • Validate webhooks using Dodo's HMAC signature and configured secret. • Store API keys in env variables / secrets manager (never commit). • Minimum permissions for API keys: only required scopes for payments and webhooks. Implementation tasks (checklist): • Design DB schema for mapping and event dedupe (microservice). • Implement invoice.created handler → create Dodo payment intent. • Implement Dodo webhook handler with HMAC verification. • Implement Lago API updates for payment status and credit notes. • Add retry/exponential backoff for transient failures. • Add configuration entries to Lago admin UI (API key, mode, webhook secret). • Write unit & integration tests (bun test / rspec). • Create Dockerfile & Helm chart (optional) for deployment. • Write README / install & troubleshooting docs. Testing: • Run local service and expose with localtunnel (or use sandbox webhook tools). • Test flow: 1. Create a test invoice in Lago (sandbox). 2. Verify integration creates a Dodo payment intent (checkout URL). 3. Complete the sandbox payment; check Dodo emits payment.succeeded . 4. Verify Lago invoice updates to paid . • Commands: bun test npx localtunnel --port 3000
0
Subscription status based on payment status
A key lacking feature I have always encountered when integrating with Stripe, GoCardless etc is easily determining the status of a customer account. Lago (and Stripe, GoCardless etc) efficiently drive the creation of invoices/payments etc, but I always need to implement complex logic when it comes to answering these questions Does a customer have any failed/overdue payments, and what is their overdue balance? I need to disable their access if they have a failed payment older than "x days" or overdue balance greater than "x amount", and re-enable it accordingly. Sometimes payments get reversed, so I need to recalculate when payment state changes. When a customer activates a subscription, I need to wait until the payment is confirmed before activating their access. E.g. the payment was "created" and the subscription is "active", but did the payment actually succeed? This especially applies to GoCardless, where DirectDebit payments take several working days to confirm, only to fail because they made a typo in the bank account. When a subscription is cancelled, the "active state" should remain active up until the period that the customer has prepaid elapses Technically all of this is possible with APIs to list all payments and filter by status, and webhooks to listen to any change in payment state. But this can be a complex logic to implement. And this sort "subscription/payment state" logic is almost always needed in the end-application, so it would be a create tool to provide. I would love for Lago to finally be the billing engine that can include this logic. Provide a "subscription state" that reflects the state of the subscription based on the actual state of any pending/failed payments Ability to define opt-in rules for the subscription state like "restrict after x days" or "x amount overdue" or "immediately" Also provide this status at the "customer" level (e.g. restrict all access for a customer when any subscription is overdue)
13
Load More