Skip to main content
Wildo.ai Coming soon

Billing and subscriptions

Keep billing logic separate from the vendor

Application billing speaks one shared contract for customers, purchases and subscription changes. A provider adapter translates that contract into the vendor’s API, keeping vendor-specific request shapes out of everyday application code.

The application requests a subscription change with its items and proration policy. The selected adapter translates that request into the provider’s update call.

Keep billing logic separate from the vendor

Application billing speaks one shared contract for customers, purchases and subscription changes. A provider adapter translates that contract into the vendor’s API, keeping vendor-specific request shapes out of everyday application code.

Example — Change a plan through one contract

The application requests a subscription change with its items and proration policy. The selected adapter translates that request into the provider’s update call.

For engineers

StandardBilling_Interface is the backend adapter contract. The runtime resolves the billing provider from the authored backend scope and gives billing services that interface. Stripe is the shipped implementation; a different vendor needs a complete adapter, an SDK-package entry in the engine billing adapter registry and provider registration, not just a different providerRef string.

The Stripe implementation’s update path shows the boundary. The complete method below maps metadata, proration and subscription items:

The following selected excerpt is from stripe-standard-billing-provider.backend.service.ts; the surrounding module and explanatory source comments are omitted.

async updateSubscription(providerSubscriptionId: string, request: StandardBilling_UpdateSubscriptionRequest): Promise<void> {
    await this.getStripe().subscriptions.update(providerSubscriptionId, {
      metadata: request.metadata,
      ...(request.prorationBehavior && { proration_behavior: request.prorationBehavior }),
      ...(request.providerPromotionCodeId && { promotion_code: request.providerPromotionCodeId }),
      ...(request.items && {
        items: request.items.map((item) => ({
          ...(item.providerSubscriptionItemId ? { id: item.providerSubscriptionItemId } : {}),
          price: item.providerPriceId,
          quantity: item.quantity,
        })),
      }),
    });
  }

The application chooses the product and policy. The billing operation constructs StandardBilling_UpdateSubscriptionRequest; the adapter names the provider’s fields. A contract field only has an effect when that adapter implements its meaning.

What a new provider must connect

ResponsibilityIntegration required
Outgoing operationsCustomer, product, price, subscription, checkout and portal methods used by billing
Incoming stateSignature verification, provider-event normalization and customer-to-account scope resolution
DiscoveryProvider capability, protocol and runtime module available to the backend
DeploymentSDK dependencies, secrets and reachable webhook delivery

Use the mock billing provider for application tests that need deterministic billing responses. Such tests exercise application behavior; they do not establish that a live vendor accepts every translated request. Switching an existing deployment also requires deciding how its provider customer, price and subscription identifiers migrate.

Building a B2B product or an internal tool?

Wildo is not self-service yet. Tell us what you have in mind and we will say plainly whether it fits, and what happens next.