HyoNovaDocumentation

Payment webhooks

How HyoNova receives payment provider webhooks — raw body, signature verification, deduplication, ordering, atomic processing, and which HTTP answers make providers retry.

Requires setupBuilt, but works only after a supporting service is configured for your workspace.ReferenceFor: Developers, IT & securityLast updated: Introduced:
On this page

A payment method appears only after HyoNova has set up its payment provider.

Payment providers tell HyoNova about payments and subscriptions by calling a webhook. These webhooks — not the browser coming back from a payment page — are what change a company's subscription. This page describes the receiving side. (For the webhooks Hyo Mail sends to your systems, see Webhooks.)

Endpoint#

text
POST https://<HyoNova product API host>/api/v1/webhooks/payments/<provider>

<provider> is the provider's webhook path: fastspring, triple-a or stripe. Bank transfer has no webhook. Control Center shows the exact URL on each provider instance. Unknown paths answer 404, an empty body 400. Bodies are limited to 512 KiB and the endpoint is rate limited.

Processing, step by step#

  1. Raw body. The body is read as raw bytes, because the signature covers the exact bytes. No JSON parsing happens before verification.
  2. Signature. HyoNova tries each instance of that provider (test and live can coexist) with its signing secret, using a constant-time comparison. No match → 401 WEBHOOK_SIGNATURE_INVALID and nothing is stored.
  3. Normalize. The adapter turns the payload into provider-independent canonical events. One notification can produce several events.
  4. Deduplicate. Each event is recorded by its key (provider, event id). A key already processed is a duplicate and changes nothing.
  5. Environment check. A test event never changes data of a live instance, and the reverse.
  6. Match the company from references HyoNova stored itself (checkout, subscription, payment, order, invoice or provider customer). Ids the provider echoes back are trusted only when they match a stored record.
  7. Order. An event older than the last one applied to a subscription — by the provider's sequence number when it has one, else by time — is ignored and never moves a subscription back.
  8. Apply atomically. The change, the company's billing timeline entry, the outbox event for notifications and the audit entry commit together in one transaction.

Signatures#

ProviderHeaderSigned content
FastSpringX-FS-SignatureBase64 HMAC-SHA256 of the raw body with the webhook HMAC secret
Triple-ATriplea-Signature: t=<unix>,v1=<hex>HMAC-SHA256 of <t>.<raw body> with the notification secret; 300-second tolerance
StripeStripe-Signature: t=<unix>,v1=<hex>HMAC-SHA256 of <t>.<raw body> with the endpoint secret; 300-second tolerance

HTTP answers#

AnswerWhenProvider behaviour
200Every event was processed, ignored or a duplicate. The body lists the processed event idsDone
401No instance verified the signatureNothing stored; fix the secret
500 PROCESSING_FAILEDAt least one event failed; it is stored as failed with a safe errorThe provider retries; processed events are deduplicated, the failed one runs again
404 / 400Unknown provider path / empty body—

Security notes#

  • No session or cookie is involved. The CSRF check is skipped only for this exact path pattern; the signature is the authentication.
  • Secrets are read from the secret store for verification only, never logged.
  • Failed events that stay failed appear in Control Center's reconciliation as attention items.
↑↓ to navigate · Enter to open · Esc to close