Subscription management#

Skalio ID integrates with payment gateways to allow persons to purchase and manage subscriptions for an organization. The responsibilities are clearly separated:

  • The payment gateway service handles the complete purchasing and payment process. It manages subscriptions and informs Skalio ID of updates. Such updates may be triggered by direct actions of a person (e.g. upgrade) or resulting from a subscription timeout (e.g. after cancellation).
  • Skalio ID manages the organization with its members and privileges. Skalio ID records subscription updates in its database and informs registered Skalio services, such as TeamBeam Transfer, of subscription updates.
  • Registered Skalio services receive subscription updates and implement changes relevant to their data model.
  • Skalio ID also notifies persons of subscription updates via the event stream and via email.

Data model considerations#

See the entity relationship diagram for a detailed mapping of the entities.

  • Subscriptions are owned by an organization. A subscription can have multiple subscription items, which are applied cumulatively.
  • A subscription item defines limitations, such as the number of organization members.
  • An organization matches a customer.
  • A person can manage the subscriptions of their organization, provided they have the necessary privileges.

Payment gateway integrations#

The following payment gateways are supported:

Subscription state diagram#

Image

The following states exist:

  • No subscription: the customer does not have any active subscriptions and is not member of an organization.
  • Active subscription: a subscription exists. The state is active. The subscription has no expiration date. The customer can use the purchased tier.
  • Cancelled subscription: a subscription exists. The state is active, but an expiration date exists. The customer can still use the purchased tier until the subscription expires.

The following actions alter the state of a subscription:

  • initial purchase: Completing a checkout creates an active subscription where there was none before.
  • product change: The customer may upgrade or downgrade the product attached to the subscription using the customer portal. The subscription remains active.
  • cancellation: The customer cancels the subscription at Stripe. It remains active, but has an expiration date.
  • reactivation: A cancelled subscription is reactivated at Stripe. The expiration date is removed.
  • expiration: The expiration date of the cancelled subscription has passed. The subscription is deleted.

Unpaid invoices#

Manual payment#

Customers with subscriptions without automatic payment collection receive an invoice via email. The invoice has a due date of 30 days in the future. A 5-day grace period allows overdue invoices before service is blocked.

Image

  1. While a subscription is active, Stripe creates invoices as per the collection interval. The invoice is sent to the billing contact. The invoice is in state open. Payment is due 30 days after the invoice is created.
  2. Three days before the invoice is due, a Stripe automation triggers the backend, and an invoice-warning notification email is sent to all organization-admins and the stripe billing contact.
  3. After the invoice is due but no payment has been received, it enters state past_due. The subscription status changes to past_due, but service remains available.
  4. Five days later, a Stripe automation changes subscription status to unpaid. Service is blocked, and a notification email is sent to all organization-admins and the stripe billing contact.
  5. When the customer pays the invoice, its status changes to paid.
  6. When all overdue invoices are paid, the subscription status changes to active and the service is available again. A notification email is sent to all organization-admins and the stripe billing contact.

The Stripe automations are configured in the dashboard under "Revenue recovery > Automations":

Image

Automatic payment#

Customers with automatic payment collection need to pay their invoice when it is issued. A grace period of one week allows for retries before service is blocked.

Image

  1. While a subscription is active, Stripe creates invoices as per the collection interval. The invoice is sent to the billing contact. The invoice is in state open. Payment is attempted immediately, using the configured payment method.
  2. If the collection fails, it is retried four times over a period of seven days.
  3. After all retries are exhausted, Stripe changes the subscription status to unpaid. Service is blocked, and a notification email is sent to all organization-admins and the stripe billing contact.
  4. When the customer successfully configures a new payment method, the invoice is paid. The subscription status changes to active and the service is available again. A notification email is sent to all organization-admins and the stripe billing contact.

The Stripe logic is configured in the dashboard under "Settings > Billing > Subscriptions":

Image

Stripe integration#

Webhook endpoint registration#

To receive events, the local API endpoint must be registered with Stripe once. The stripe webhook register command can be used for this. It returns the webhook signature signing secret, which must be added to the configuration setting stripe.webhookSigningSecret.

skalio-id> stripe webhook register
Registration of a new webhook with Stripe

In order to register a new webhook, you need to provide the name of this environment, such as
'databeam' or 'production', etc. You also need to provide the external URL where the webhook
is reachable.
After successful registration, the command returns a `secret` that is used to verify the signature
of incoming events. This value must be entered into the configuration.

Suggested Webhook endpoint: https://id.databeam.de/id/v1/subscriptions/stripe/webhook

Environment name     > databeam
Webhook endpoint URL > https://id.databeam.de/id/v1/subscriptions/stripe/webhook
Confirm (y/N)? y

Making request towards stripe ... Success!

New webhook signing secret: whsec_3KMYzDacmL0g79M54yyw513uGUoOo5FD
Please update the configuration parameter stripe.webhookSigningSecret with this value!

Checkout#

The Stripe Checkout flow is used to purchase a product and create the initial subscription. In this flow, the customer registers himself within Stripe and provides payment information. It is only available if the person is not member of a paid organization.

Skalio ID sends a PURCHASE_PENDING event to indicate that a purchase process is taking place when a checkout.session.completed event is received from Stripe . Services using Skalio ID can use this event to show a loading state until they receive a SUBSCRIPTION_UPDATED event.

Image

Customer portal#

Once a subscription exists, a person must request a Stripe Customer Portal session to manage his subscription as well as access billing information. This routes the person to a Stripe-managed website.

Image

Events#

Stripe communicates updates and changes by posting webhook events to Skalio ID. These events are received and parsed by Skalio ID. Only events that pass signature verification will be accepted for processing. Event processing occurs in a deferred fashion and may change the order in which they are being processed.

If this results in changes to a subscription, a SignalingEvent is sent to each person who has admin privileges in the affected organization. Subscription updates are also published to registered Skalio services. See the event stream for details.

Image

Events remain in the database until they are expired automatically. Already processed events are not processed again.

Example events sent from Stripe to the Skalio ID webhook endpoint#

Organization removal#

When a person removes the organization from Skalio ID, this has wide-ranging consequences. All related entities and data are being removed, and the delete operation is cascaded to other Skalio services.

The Stripe entities customer and subscription are both mapped to a Skalio ID subscription. When the organization is removed, all Stripe subscriptions are cancelled and the Stripe customers are deleted.

Image

Stripe sends webhook events as a result of this operation, but typically the database has removed the related entities already.

Skalio service integration#

Subscription changes are propagated from Skalio ID to other Skalio services by publishing a message on the broker in the {brokerPrefix}.updatedEntity queue. The message is of type SubscriptionUpdateJson, carrying an ISubscriptionUpdate payload.

The consequences of the subscription change are to be handled by each Skalio service individually. This may include increasing limits on resources or granting or revoking access to features.

ISubscriptionUpdate payload#

  • orgUid (string, required): The unique ID of the organization.
  • createdAt (string, required): The timestamp when the subscription was initially created.
  • updatedAt (string, required): The timestamp when the update became effective.
  • expiresAt (string, optional): The timestamp when the subscription is being cancelled; null otherwise.
  • domain (string, optional): The product domain. Values:
    • spaces: Novospace
    • skp: TeamBeam
    • null: Subscription does not yet reference a product.
  • productId (string, optional): The ID of the product, null if the subscription does not yet reference a product.
  • displayName (string, optional): A user-presentable name for the product, null if the subscription does not yet reference a product.
  • status (string, optional): The subscription status. Values:
    • active
    • trialing
    • canceled
    • unpaid
    • past_due
    • incomplete
    • incomplete_expired
    • null: no product yet

Example:

{
  "orgUid" : "pep6umv2hzzhhj64",
  "updatedAt" : "2022-07-13T11:50:52.085287Z",
  "expiresAt" : null,
  "domain" : "spaces",
  "productId" : "business",
  "status" : "active"
}