Commet
  • Pricing
Log InTry out
Introduction

Quickstart

Integrate with GoIntegrate with Encore

Learn

Resources

SDK ReferenceError HandlingTestingCLI

Plugins

Better Auth
DocumentationKnowledge BaseBuild with AIAPI ReferenceWebhooks

Integrate with Encore

Add billing and payments to your Encore application.

Install

encore app create --example=hello-world myapp
cd myapp
go get github.com/commet-labs/commet-go

Configure

Store secrets using Encore's secret manager instead of environment variables:

encore secret set --type dev,local,pr,prod CommetAPIKey
encore secret set --type dev,local,pr,prod CommetWebhookSecret
billing/billing.go
package billing

import (
	commet "github.com/commet-labs/commet-go"
)

var secrets struct {
	CommetAPIKey       string
	CommetWebhookSecret string
}

var client *commet.Client

func initClient() error {
	var err error
	client, err = commet.New(
		secrets.CommetAPIKey,
		commet.WithEnvironment(commet.Sandbox),
	)
	return err
}

Subscribe

billing/billing.go
import "context"

type SubscribeParams struct {
	Email      string `json:"email"`
	ExternalID string `json:"external_id"`
}

type SubscribeResponse struct {
	CheckoutURL string `json:"checkout_url"`
}

//encore:api public method=POST path=/billing/subscribe
func Subscribe(ctx context.Context, req *SubscribeParams) (*SubscribeResponse, error) {
	if err := initClient(); err != nil {
		return nil, err
	}

	_, err := client.Customers.Create(ctx, &commet.CreateCustomerParams{
		Email:      req.Email,
		ExternalID: req.ExternalID,
	})
	if err != nil {
		return nil, err
	}

	subscription, err := client.Subscriptions.Create(ctx, &commet.CreateSubscriptionParams{
		ExternalID: req.ExternalID,
		PlanCode:   "pro",
	})
	if err != nil {
		return nil, err
	}

	return &SubscribeResponse{
		CheckoutURL: subscription.Data["checkout_url"].(string),
	}, nil
}

Check Access

billing/billing.go
type SubscriptionResponse struct {
	Status string `json:"status"`
}

//encore:api public method=GET path=/billing/subscription/:externalID
func GetSubscription(ctx context.Context, externalID string) (*SubscriptionResponse, error) {
	if err := initClient(); err != nil {
		return nil, err
	}

	sub, err := client.Subscriptions.Get(ctx, externalID)
	if err != nil {
		return nil, err
	}

	return &SubscriptionResponse{
		Status: sub.Data["status"].(string),
	}, nil
}

type FeatureResponse struct {
	Allowed bool `json:"allowed"`
}

//encore:api public method=GET path=/billing/features/:feature/:externalID
func CheckFeature(ctx context.Context, feature string, externalID string) (*FeatureResponse, error) {
	if err := initClient(); err != nil {
		return nil, err
	}

	result, err := client.Features.Check(ctx, feature, externalID)
	if err != nil {
		return nil, err
	}

	return &FeatureResponse{
		Allowed: result.Data["allowed"].(bool),
	}, nil
}

Track Usage

billing/billing.go
func intPtr(i int) *int { return &i }

type UsageParams struct {
	ExternalID string `json:"external_id"`
}

type UsageResponse struct {
	Tracked bool `json:"tracked"`
}

//encore:api public method=POST path=/billing/usage
func TrackUsage(ctx context.Context, req *UsageParams) (*UsageResponse, error) {
	if err := initClient(); err != nil {
		return nil, err
	}

	_, err := client.Usage.Track(ctx, &commet.TrackUsageParams{
		ExternalID: req.ExternalID,
		Feature:    "api_calls",
		Value:      intPtr(1),
	})
	if err != nil {
		return nil, err
	}

	return &UsageResponse{Tracked: true}, nil
}

Usage is aggregated and billed at end of period.

Webhooks

billing/webhooks.go
package billing

import (
	"net/http"

	commet "github.com/commet-labs/commet-go"
)

//encore:api public raw method=POST path=/webhooks/commet
func HandleWebhook(w http.ResponseWriter, r *http.Request) {
	rawBody, err := io.ReadAll(r.Body)
	if err != nil {
		http.Error(w, "Failed to read body", http.StatusBadRequest)
		return
	}

	webhooks := &commet.Webhooks{}
	payload, err := webhooks.VerifyAndParse(
		string(rawBody),
		r.Header.Get("x-commet-signature"),
		secrets.CommetWebhookSecret,
	)
	if err != nil {
		http.Error(w, "Invalid signature", http.StatusUnauthorized)
		return
	}

	switch payload["event"] {
	case "subscription.activated":
		// handle activation
	}

	w.Header().Set("Content-Type", "application/json")
	w.Write([]byte(`{"ok":true}`))
}

Run

encore run

Related

  • Subscriptions
  • Track Usage
  • Customer Portal
  • SDK Reference

How is this guide?

Integrate with Go

Add billing and payments to your Go application using net/http.

Integrate with PHP

Install and configure the Commet PHP SDK.

On this page

Install
Configure
Subscribe
Check Access
Track Usage
Webhooks
Run
Related