feat(server): API relay gateway backend M0-M4
Gin + GORM + pure-Go SQLite. Users/auth (JWT), API key management with quotas, proxy gateway with weighted channel failover and health checks, usage/billing ledger, cross-protocol conversion (Anthropic Messages / OpenAI Chat Completions / OpenAI Responses), and channel/model admin API. Channels declare native API formats and auto-convert the rest. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
b0c7439c01
commit
d0e31b198f
@@ -0,0 +1,84 @@
|
||||
package recharge
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/shopspring/decimal"
|
||||
"go.uber.org/zap"
|
||||
"gorm.io/gorm"
|
||||
|
||||
"openteam/server/internal/pkg/httpx"
|
||||
"openteam/server/internal/store"
|
||||
"openteam/server/internal/user"
|
||||
)
|
||||
|
||||
// Handler exposes the reserved recharge order endpoints.
|
||||
type Handler struct {
|
||||
db *gorm.DB
|
||||
log *zap.Logger
|
||||
}
|
||||
|
||||
func NewHandler(db *gorm.DB, log *zap.Logger) *Handler {
|
||||
return &Handler{db: db, log: log}
|
||||
}
|
||||
|
||||
type CreateInput struct {
|
||||
Amount decimal.Decimal `json:"amount" binding:"required"`
|
||||
Remark string `json:"remark"`
|
||||
}
|
||||
|
||||
// Create handles POST /api/v1/recharges — creates a pending manual order.
|
||||
func (h *Handler) Create(c *gin.Context) {
|
||||
u := user.Current(c)
|
||||
var in CreateInput
|
||||
if !httpx.Bind(c, &in) {
|
||||
return
|
||||
}
|
||||
if in.Amount.LessThanOrEqual(decimal.Zero) {
|
||||
httpx.Fail(c, http.StatusBadRequest, "amount must be positive")
|
||||
return
|
||||
}
|
||||
order := &store.RechargeOrder{
|
||||
UserID: u.ID,
|
||||
Amount: in.Amount,
|
||||
Status: "pending",
|
||||
Method: "manual",
|
||||
Remark: in.Remark,
|
||||
}
|
||||
if err := h.db.Create(order).Error; err != nil {
|
||||
h.log.Warn("create recharge order failed", zap.Error(err))
|
||||
httpx.Fail(c, http.StatusInternalServerError, "create order failed")
|
||||
return
|
||||
}
|
||||
httpx.Created(c, orderDTO(order))
|
||||
}
|
||||
|
||||
// List handles GET /api/v1/recharges.
|
||||
func (h *Handler) List(c *gin.Context) {
|
||||
u := user.Current(c)
|
||||
var orders []store.RechargeOrder
|
||||
if err := h.db.Where("user_id = ?", u.ID).Order("id DESC").Find(&orders).Error; err != nil {
|
||||
h.log.Warn("list recharge orders failed", zap.Error(err))
|
||||
httpx.Fail(c, http.StatusInternalServerError, "list orders failed")
|
||||
return
|
||||
}
|
||||
out := make([]gin.H, 0, len(orders))
|
||||
for i := range orders {
|
||||
out = append(out, orderDTO(&orders[i]))
|
||||
}
|
||||
httpx.OK(c, out)
|
||||
}
|
||||
|
||||
func orderDTO(o *store.RechargeOrder) gin.H {
|
||||
return gin.H{
|
||||
"id": o.ID,
|
||||
"amount": o.Amount.String(),
|
||||
"status": o.Status,
|
||||
"method": o.Method,
|
||||
"remark": o.Remark,
|
||||
"reviewedBy": o.ReviewedBy,
|
||||
"reviewedAt": o.ReviewedAt,
|
||||
"createdAt": o.CreatedAt,
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user