mirror of
https://github.com/hanzoai/agent.git
synced 2026-09-11 21:08:51 +00:00
- BillingService client calls Commerce API for balance checks and debits - Balance gate in prepareExecution blocks $0 balance with HTTP 402 - Post-execution billing in completeExecution/failExecution debits actual cost - Balance proxy endpoint at GET /api/v1/billing/balance - DB migration adds billing fields to executions table - K8s deployment wired with BILLING_COMMERCE_URL and admin token secret Co-authored-by: Hanzo Dev <[email protected]>
45 lines
1.2 KiB
Go
45 lines
1.2 KiB
Go
package handlers
|
|
|
|
import (
|
|
"net/http"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
|
|
"github.com/hanzoai/agents/control-plane/internal/services"
|
|
)
|
|
|
|
// BillingBalanceHandler proxies balance queries to Commerce, scoped to
|
|
// the authenticated user. The control-plane adds the admin token so
|
|
// the frontend never needs direct Commerce credentials.
|
|
//
|
|
// GET /api/v1/billing/balance?user=<iam-user-id>¤cy=usd
|
|
func BillingBalanceHandler(billing *services.BillingService) gin.HandlerFunc {
|
|
return func(c *gin.Context) {
|
|
if billing == nil {
|
|
c.JSON(http.StatusServiceUnavailable, gin.H{"error": "billing not configured"})
|
|
return
|
|
}
|
|
|
|
userID := c.Query("user")
|
|
if userID == "" {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": "user query parameter is required"})
|
|
return
|
|
}
|
|
|
|
available, err := billing.CheckBalance(c.Request.Context(), userID)
|
|
if err != nil {
|
|
if err == services.ErrCommerceUnavailable {
|
|
c.JSON(http.StatusServiceUnavailable, gin.H{"error": "billing service unavailable"})
|
|
return
|
|
}
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
|
|
c.JSON(http.StatusOK, gin.H{
|
|
"available": available,
|
|
"currency": "usd",
|
|
})
|
|
}
|
|
}
|