Integrate with Go
Add billing and payments to your Go application using net/http.
Install
go get github.com/commet-labs/commet-goConfigure
COMMET_API_KEY=ck_sandbox_xxx
COMMET_WEBHOOK_SECRET=whsec_xxxpackage billing
import (
"log"
"os"
commet "github.com/commet-labs/commet-go"
)
var Client *commet.Client
func Init() {
var err error
Client, err = commet.New(
os.Getenv("COMMET_API_KEY"),
commet.WithEnvironment(commet.Sandbox),
)
if err != nil {
log.Fatal(err)
}
}Subscribe
package billing
import (
"encoding/json"
"net/http"
commet "github.com/commet-labs/commet-go"
)
type subscribeRequest struct {
Email string `json:"email"`
ExternalID string `json:"external_id"`
}
func Subscribe(w http.ResponseWriter, r *http.Request) {
var req subscribeRequest
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
_, err := Client.Customers.Create(r.Context(), &commet.CreateCustomerParams{
Email: req.Email,
ExternalID: req.ExternalID,
})
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
subscription, err := Client.Subscriptions.Create(r.Context(), &commet.CreateSubscriptionParams{
ExternalID: req.ExternalID,
PlanCode: "pro",
})
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(map[string]any{"checkout_url": subscription.Data["checkout_url"]})
}Check Access
func GetSubscription(w http.ResponseWriter, r *http.Request) {
externalID := r.PathValue("externalID")
sub, err := Client.Subscriptions.Get(r.Context(), externalID)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(map[string]any{"status": sub.Data["status"]})
}
func CheckFeature(w http.ResponseWriter, r *http.Request) {
feature := r.PathValue("feature")
externalID := r.PathValue("externalID")
result, err := Client.Features.Check(r.Context(), feature, externalID)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(map[string]any{"allowed": result.Data["allowed"]})
}Track Usage
func intPtr(i int) *int { return &i }
type usageRequest struct {
ExternalID string `json:"external_id"`
}
func TrackUsage(w http.ResponseWriter, r *http.Request) {
var req usageRequest
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
_, err := Client.Usage.Track(r.Context(), &commet.TrackUsageParams{
ExternalID: req.ExternalID,
Feature: "api_calls",
Value: intPtr(1),
})
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(map[string]any{"tracked": true})
}Usage is aggregated and billed at end of period.
Customer Portal
func Portal(w http.ResponseWriter, r *http.Request) {
result, err := Client.Portal.GetURL(r.Context(), &commet.GetPortalURLParams{
ExternalID: "user_123",
})
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
http.Redirect(w, r, result.Data["portal_url"].(string), http.StatusTemporaryRedirect)
}Webhooks
package billing
import (
"io"
"net/http"
"os"
commet "github.com/commet-labs/commet-go"
)
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"),
os.Getenv("COMMET_WEBHOOK_SECRET"),
)
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}`))
}Start Server
package main
import (
"billing"
"log"
"net/http"
)
func main() {
billing.Init()
defer billing.Client.Close()
mux := http.NewServeMux()
mux.HandleFunc("POST /billing/subscribe", billing.Subscribe)
mux.HandleFunc("GET /billing/subscription/{externalID}", billing.GetSubscription)
mux.HandleFunc("GET /billing/features/{feature}/{externalID}", billing.CheckFeature)
mux.HandleFunc("POST /billing/usage", billing.TrackUsage)
mux.HandleFunc("GET /billing/portal", billing.Portal)
mux.HandleFunc("POST /webhooks/commet", billing.HandleWebhook)
log.Println("Listening on :3000")
log.Fatal(http.ListenAndServe(":3000", mux))
}Related
How is this guide?