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>
85 lines
2.0 KiB
Go
85 lines
2.0 KiB
Go
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,
|
|
}
|
|
}
|