Skip to main content

Webhook

๐Ÿ“– Overviewโ€‹

internal/api/v1/billing/services/webhook.service.js handles Stripe webhook payloads for the billing domain. It normalises charge, invoice, customer, subscription, refund, dispute, and product events, keeps Mongo projections in sync, and notifies other services (CRM, Support, Queue Manager) about billing updates.

Primary Controller: webhook.controller.js

๐Ÿ—„๏ธ Collections & Modelsโ€‹

  • billing.charges, billing.subscriptions, billing.disputes, billing.refunds, billing.products, billing.customers.
  • crm.contacts โ€“ Updates or creates contacts based on Stripe customer data.
  • support.* collections โ€“ Opens conversations and logs payment activity.
  • currency โ€“ Retrieves symbols for notification messages.

๐Ÿ”— External Dependenciesโ€‹

  • Stripe โ€“ Expanded retrieves for charges, disputes, invoices, and subscriptions.
  • Socket Emit Utility โ€“ Sends real-time updates to Support UI (emit-socket).
  • Logger Utility โ€“ Records success/failure of downstream operations.
  • withTransaction โ€“ Ensures atomic creation of support conversations, rooms, and messages.
  • Stripe Config Utility โ€“ Hydrates Stripe client for connected accounts.

๐Ÿ”„ Event Flowโ€‹

flowchart TD
Stripe[Stripe Webhooks] --> Controller
Controller --> Service
Service --> Mongo[(MongoDB)]
Service --> CRM[CRM Contacts]
Service --> SupportSockets[Support Sockets]
Service --> QueueManager
Service --> Logger

๐Ÿง  Key Behavioursโ€‹

  • Upserts Stripe entities into Mongo models to maintain a searchable cache.
  • Applies connected-account context (stripe_user_id) to every persisted entity for multi-tenant separation.
  • Mirrors subscription metadata onto invoices and charges to maintain CRM attribution.
  • Generates support-room system messages on successful invoice payments, even creating conversations when none exist.
  • Uses getMapping to translate Stripe customer fields into CRM contact schemas when mappings are configured.

๐Ÿงฉ Event Handlersโ€‹

Chargesโ€‹

  • newCharge({ chargeDetails, stripeBilling })
    • Retrieves expanded charge from Stripe (customer, subscription, balance transaction) and inserts into billing.charges.
    • Handles duplicate key errors gracefully (ignored as idempotent replay).
  • updateCharge({ chargeDetails, stripeBilling })
    • Upserts existing charge documents with latest payload.

Invoicesโ€‹

  • newInvoice({ invoice, stripeBilling })
    • Propagates invoice metadata to associated charge.
  • paidInvoice({ invoice, stripeBilling })
    • When status = 'paid', locates or creates CRM contact and support conversation.
    • Emits socket events to join/create rooms and logs system messages with formatted payment amount.

Disputes & Refundsโ€‹

  • newDispute, updateDispute, closeDispute
    • Persist dispute lifecycle into billing.disputes, expanding charge references for context.
  • createRefund, updateRefund
    • Track refunds in billing.refunds, storing amount, currency, and status.

Customersโ€‹

  • newCustomer
    • Inserts Stripe customer snapshot and updates or creates CRM contact based on mapping configuration. Supports auto-creation when stripeBilling.new_contact flag is set.
  • updateCustomer
    • Upserts customer document and re-applies mapping updates to CRM contact.
  • deleteCustomer
    • Marks customer as deleted and unsets stripe_customer_id from linked contacts.

Subscriptionsโ€‹

  • createSubscription, updateSubscription, deleteSubscription
    • Persist subscription details, mirror metadata to latest invoice and charge, and upsert in billing.subscriptions.
    • deleteSubscription stores latest payload to track final status.

Productsโ€‹

  • createProduct, updateProduct, deleteProduct
    • Synchronise Stripe product catalogue into billing.products for local caching.

๐Ÿงช Testing Notesโ€‹

  • Simulate webhook payloads in unit tests to confirm idempotent upserts across duplicate deliveries.
  • Validate support socket emissions with integration tests that stub emit-socket to avoid side effects.
  • Ensure mapping logic is covered with fixtures that include stripeBilling.mappings.

โš ๏ธ Operational Considerationsโ€‹

  • All handlers guard against duplicate Stripe deliveries by upserting on stripe_id + stripe_user_id.
  • Long-running operations (support room creation) execute within withTransaction; monitor Mongo transaction timeouts.
  • Stripe connection errors are surfaced via custom helper for consistent error reporting upstream.
๐Ÿ’ฌ

Documentation Assistant

Ask me anything about the docs

Hi! I'm your documentation assistant. Ask me anything about the docs!

I can help you with:
- Code examples
- Configuration details
- Troubleshooting
- Best practices

Try asking: How do I configure the API?
09:31 AM