sbt-aws-moesif
v0.1.2
Published
This module extends the AWS SaaS Builder Toolkit (SBT) to support usage-based billing through Moesif.
Downloads
2
Readme
Moesif API Monetization for AWS SBT
This module extends the AWS SaaS Builder Toolkit (SBT) to support usage-based billing through Moesif.
SaaS Builder Toolkit for AWS (SBT) is an open-source developer toolkit to implement SaaS best practices. SBT attempts to codify several control plane and application plane concepts such as tenant and user management, billing, and onboarding into reusable components, promoting reuse and reducing boilerplate code.
Moesif API Monetization provides a cloud-based solution for usage-based billing such as billing on API transactions, compute resources, or unique users. Then, you can invoice and collect payments automatically through popular payment providers like Stripe, Zuora, or custom invoicing solutions.
How it works
Event Ingestion
The project deploys an Amazon Data Firehose to ingest your raw usage events. Events can be API Calls such as from an Amazon API Gateway instance or custom actions triggered within your application. The firehose will send all events to Moesif's Collection API for metering and analytics.
For more info on how the MoesifFirehoseConstruct
works, view Moesif docs on ingesting actions via Firehose
User and Tenant Management
The project also deploys a Lambda Function for user and tenant management. The lambda will listen to events like provisionSuccess
to create companies and subscriptions in Moesif and your payment provider. Similarly, when receiving a deprovisionSuccess
event, all subscriptions will be canceled for the tenant. You can inspect the code here.
|SBT Entity|Moesif Entity|Description|Parent| |----------|-------------|-----------|-----------| |Tenant|Company|Your customer that you provisioned resources for.|None| |Tenant|Subscription|A single subscription for a company/tenant.|Company| |User|User|End users of your customer who login to your SaaS.|Company|
How to use
Prerequisites
- If you don't already have a SBT project deployed, follow AWS SBT's tutorial to deploy the sample
hello-cdk
project with aControlPlane
andCoreApplicationPlane
. - You already have a Moesif account. You can sign up for a trial on moesif.com
1. Install the NPM package
Within your SBT project directory, install sbt-aws-moesif
via the following command:
npm install --save sbt-aws-moesif
2. Add MoesifBilling to your ControlPlane
Instantiate the MoesifBilling construct like below. You will need to set some properties to authenticate with Moesif.
export class ControlPlaneStack extends Stack {
public readonly regApiGatewayUrl: string;
public readonly eventBusArn: string;
constructor(scope: Construct, id: string, props: any) {
super(scope, id, props);
const cognitoAuth = new CognitoAuth(this, 'CognitoAuth', {
idpName: 'COGNITO',
systemAdminRoleName: 'SystemAdmin',
systemAdminEmail: '<<Your Admin Email>>',
});
const moesifBilling = new MoesifBilling(stack, 'MoesifBilling', {
moesifApplicationId: '<<Your Moesif Application Id>>',
moesifManagementAPIKey: '<<Your Moesif Management API Key>>',
billingProviderSlug: BillingProviderSlug.STRIPE,
billingProviderSecretKey: '<<Your Billing Provider\'s Secret Such as for Stripe>>'
}
);
const controlPlane = new ControlPlane(this, 'ControlPlane', {
auth: cognitoAuth,
billing: moesifBilling,
});
this.eventBusArn = controlPlane.eventBusArn;
this.regApiGatewayUrl = controlPlane.controlPlaneAPIGatewayUrl;
}
}
Moesif Billing Properties
|Property Name|Type|Required|Description|Default| |-------------|----|--------|-----------|-------| |moesifApplicationId|string|Required|Collector Application Id from your Moesif account for event ingestion|| |moesifManagementAPIKey|string|Required|Management API Key from your Moesif account. The key must have the following scopes: create:companies create:subscriptions create:users delete:companies delete:subscriptions delete:users|| |moesifManagementAPIBaseUrl|string||Override the base URL for the Moesif Mangaement API. For most setups, you don't need to set this.|https://api.moesif.com| |moesifCollectorAPIBaseUrl|string||Override the base URL for the Moesif Collector API. For most setups, you don't need to set this.|https://api.moesif.net| |billingProviderSlug|BillingProviderSlug|Required| Slug for Billing Provider / Payment Gateway|| |billingProviderSecretKey|string|Required|Secret Key for Billing Provider / Payment Gateway selected by billingProviderSlug|| |billingProviderClientId|string|Only if Zuora|Client Id for Billing Provider / Payment Gateway. Only used when billingProviderSlug is Zuora|| |billingProviderBaseUrl|string|Only if Chargebee or Zuora|Base URL for Billing Provider / Payment Gateway. Only used when billingProviderSlug is Zuora or Chargebee|| |tenantPlanField|string||Tenant object's field name that contains the plan id used when creating new subscriptions. Only used when billingProviderSlug is Zuora|planId| |tenantPriceField|string||Tenant object's field name that contains the price id used when creating new subscriptions.|priceId| |firehoseName|string||The name of the Kinesis Firehose delivery stream. By default, a unique name will be generated.|| |bucketName|string||The name of the S3 bucket for backup. By default, a unique name will be generated.|| |schema|string||Moesif Event Schema for data ingestion. By default, Moesif actions||
3. Provision a Tenant
Once you deploy your updated stack, create a tenant in your AWS SBT setup using the SBT APIs.
When you create a tenant, you must also set the price id to be used for creating subscriptions, By default, the field name is priceId
, but this can be overridden via the above options. If you are using Zuora, you must also set the plan id. The field email
must also be set.
If your provider is set to Zuora, you must also set these fields
If you're running the hello-cdk
project, this can be done by running this script to onboard a new tenant. Modify, the script to also include the price (and plan if required).
To find your plan id and price id, you can log into Moesif UI and go to Product Catalog or log into your billing provider.
DATA=$(jq --null-input \
--arg tenantEmail "$TENANT_EMAIL" \
--arg tenantId "$TENANT_ID" \
'{
"email": $tenantEmail,
"tenantId": $tenantId,
"priceId": "price_1MoBy5LkdIwHu7ixZhnattbh"
}')
echo "creating tenant..."
curl --request POST \
--url "${CONTROL_PLANE_API_ENDPOINT}tenants" \
--header "Authorization: Bearer ${ID_TOKEN}" \
--header 'content-type: application/json' \
--data "$DATA"
Once done, you should see the company show up in the Moesif UI. There should also be a subscription for the company in the "active" status.
The tenant will be subscribed to the price defined by defaultPriceId
.
This can be expanded to allow more customization.
4. Ingest Events
Now that you created a tenant, you should ingest some actions in you're newly created firehose. Actions have an action name (like "Signed Up", "API Request", or "Finished Job") which represents the usage event. You can also include arbitrary metadata with an action, which enables you to create billable metrics, usage reporting, and more. For more info, see docs on actions
You'll want to set a few fields like below:
action_name
is a string and should include name of the event such as "Processed Payment Transaction"company_id
is your tenant identifier. See companiestransaction_id
should be a random UUID for this event which Moesif uses for deduplication. Docs on Moesif idempotency.request.time
represents the transaction time as an ISO formatted string.metadata
is an object which includes any custom properties for this event. By setting metadata, you can bill on arbitrary metrics, create metrics on them, etc. For example, if the action name is "Processed Payment Transaction", you can include an amount and the currency to bill on the total amount.
For full schema and available fields, see Actions API Reference
An example action is below:
{
"action_name": "Processed Payment Transaction",
"request": {
"time": "2024-03-01T04:45:42.914"
},
"company_id": "12345", // This is your tenant id
"transaction_id": "a3765025-46ec-45dd-bc83-b136c8d1d257",
"metadata": {
"amount": 24.6,
"currency": "USD",
"time_seconds": 66.3
}
}
In the above example, the action is created whenever a payment is processed. There are also two metrics we are tracking as part of the action (the amount of the payment and how long the job took). You can create billable metrics and usage reports from these attributes.
If your events are API calls, we recommend changing the MoesifEventSchema to
API_CALL
which provides a different schema than the above actions. See API Calls
5. Create a Billing Meter
Now that the tenant is created, follow these steps to create a billing meter in Moesif. The billing meter can filter or aggregate on any of the metadata fields you included with your action.
You should also select the provider and price defined by billingProviderSlug
and defaultPriceId
.
Provider Specific Requirements
Zuora
If you are using Zuora, the following fields must be set when creating a new tenant:
{
"email": "<Customer email address>",
"firstName": "<First name of customer contact>",
"lastName": "<Last name of customer contact>",
"currency": "<Three-letter ISO currency code>",
"address": {
"state": "<State or providence of the contact's address>",
"country": "<The country of the contact's address>"
}
}
Limitations
sbt-aws-moesif
is in preview. Development is still ongoing. There are limitations to be aware of.
- Deprovisioning a tenant will cancel all subscriptions but does not delete objects in case a subscription should be reactivated.
Useful commands
npm run build
compile typescript to jsnpm run watch
watch for changes and compilenpm run test
perform the jest unit tests