支付,OSS 服务重构完成

This commit is contained in:
GeekMaster
2025-08-24 19:32:45 +08:00
parent 7fb0aad3c7
commit 536b4b8056
57 changed files with 1663 additions and 1358 deletions

View File

@@ -19,9 +19,10 @@ import (
"geekai/store/vo"
"geekai/utils"
"geekai/utils/resp"
"time"
"github.com/go-redis/redis/v8"
"github.com/golang-jwt/jwt/v5"
"time"
"github.com/gin-gonic/gin"
"gorm.io/gorm"
@@ -72,7 +73,7 @@ func (h *ManagerHandler) Login(c *gin.Context) {
return
}
if h.App.SysConfig.EnabledVerify {
if h.App.SysConfig.Base.EnabledVerify {
var check bool
if data.X != 0 {
check = h.captcha.SlideCheck(data)

View File

@@ -47,7 +47,6 @@ func (h *ConfigHandler) RegisterRoutes() {
group.GET("get", h.Get)
group.POST("active", h.Active)
group.POST("test", h.Test)
group.GET("fixData", h.FixData)
group.GET("license", h.GetLicense)
}
@@ -70,7 +69,7 @@ func (h *ConfigHandler) Update(c *gin.Context) {
resp.ERROR(c, "系统配置解析失败: "+err.Error())
return
}
if (sys.Copyright != payload.ConfigBak.Copyright) && !h.licenseService.GetLicense().Configs.DeCopy {
if (sys.Base.Copyright != payload.ConfigBak.Base.Copyright) && !h.licenseService.GetLicense().Configs.DeCopy {
resp.ERROR(c, "您无权修改版权信息,请先联系作者获取授权")
return
}
@@ -162,69 +161,3 @@ func (h *ConfigHandler) GetLicense(c *gin.Context) {
license := h.licenseService.GetLicense()
resp.SUCCESS(c, license)
}
// FixData 修复数据
func (h *ConfigHandler) FixData(c *gin.Context) {
resp.ERROR(c, "当前升级版本没有数据需要修正!")
//var fixed bool
//version := "data_fix_4.1.4"
//err := h.levelDB.Get(version, &fixed)
//if err == nil || fixed {
// resp.ERROR(c, "当前版本数据修复已完成,请不要重复执行操作")
// return
//}
//tx := h.DB.Begin()
//var users []model.User
//err = tx.Find(&users).Error
//if err != nil {
// resp.ERROR(c, err.Error())
// return
//}
//for _, user := range users {
// if user.Email != "" || user.Mobile != "" {
// continue
// }
// if utils.IsValidEmail(user.Username) {
// user.Email = user.Username
// } else if utils.IsValidMobile(user.Username) {
// user.Mobile = user.Username
// }
// err = tx.Save(&user).Error
// if err != nil {
// resp.ERROR(c, err.Error())
// tx.Rollback()
// return
// }
//}
//
//var orders []model.Order
//err = h.DB.Find(&orders).Error
//if err != nil {
// resp.ERROR(c, err.Error())
// return
//}
//for _, order := range orders {
// if order.PayWay == "支付宝" {
// order.PayWay = "alipay"
// order.PayType = "alipay"
// } else if order.PayWay == "微信支付" {
// order.PayWay = "wechat"
// order.PayType = "wxpay"
// } else if order.PayWay == "hupi" {
// order.PayType = "wxpay"
// }
// err = tx.Save(&order).Error
// if err != nil {
// resp.ERROR(c, err.Error())
// tx.Rollback()
// return
// }
//}
//tx.Commit()
//err = h.levelDB.Put(version, true)
//if err != nil {
// resp.ERROR(c, err.Error())
// return
//}
//resp.SUCCESS(c)
}

View File

@@ -76,16 +76,16 @@ func (h *OrderHandler) List(c *gin.Context) {
order.Id = item.Id
order.CreatedAt = item.CreatedAt.Unix()
order.UpdatedAt = item.UpdatedAt.Unix()
payMethod, ok := types.PayMethods[item.PayWay]
payChannel, ok := types.PayChannel[item.Channel]
if !ok {
payMethod = item.PayWay
payChannel = item.Channel
}
payName, ok := types.PayNames[item.PayType]
payWays, ok := types.PayWays[item.PayWay]
if !ok {
payName = item.PayWay
payWays = item.PayWay
}
order.PayMethod = payMethod
order.PayName = payName
order.ChannelName = payChannel
order.PayName = payWays
list = append(list, order)
} else {
logger.Error(err)

View File

@@ -41,7 +41,7 @@ func (h *UploadHandler) Upload(c *gin.Context) {
return
}
if h.App.SysConfig.MaxFileSize > 0 && f.Size > int64(h.App.SysConfig.MaxFileSize)*1024*1024 {
if h.App.SysConfig.Base.MaxFileSize > 0 && f.Size > int64(h.App.SysConfig.Base.MaxFileSize)*1024*1024 {
resp.ERROR(c, "文件大小超过限制")
return
}

View File

@@ -21,11 +21,11 @@ import (
type CaptchaHandler struct {
App *core.AppServer
service *service.CaptchaService
config *types.CaptchaConfig
config types.CaptchaConfig
}
func NewCaptchaHandler(app *core.AppServer, s *service.CaptchaService, config *types.CaptchaConfig) *CaptchaHandler {
return &CaptchaHandler{App: app, service: s, config: config}
func NewCaptchaHandler(app *core.AppServer, s *service.CaptchaService, sysConfig *types.SystemConfig) *CaptchaHandler {
return &CaptchaHandler{App: app, service: s, config: sysConfig.GeekAPI.Captcha}
}
// RegisterRoutes 注册路由

View File

@@ -244,9 +244,9 @@ func (h *ChatHandler) sendMessage(ctx context.Context, input ChatInput, c *gin.C
// 加载聊天上下文
chatCtx := make([]any, 0)
messages := make([]any, 0)
if h.App.SysConfig.EnableContext {
if h.App.SysConfig.Base.EnableContext {
_ = utils.JsonDecode(input.ChatRole.Context, &messages)
if h.App.SysConfig.ContextDeep > 0 {
if h.App.SysConfig.Base.ContextDeep > 0 {
var historyMessages []model.ChatMessage
dbSession := h.DB.Session(&gorm.Session{}).Where("chat_id", input.ChatId)
if input.LastMsgId > 0 { // 重新生成逻辑
@@ -254,7 +254,7 @@ func (h *ChatHandler) sendMessage(ctx context.Context, input ChatInput, c *gin.C
// 删除对应的聊天记录
h.DB.Debug().Where("chat_id", input.ChatId).Where("id >= ?", input.LastMsgId).Delete(&model.ChatMessage{})
}
err = dbSession.Limit(h.App.SysConfig.ContextDeep).Order("id DESC").Find(&historyMessages).Error
err = dbSession.Limit(h.App.SysConfig.Base.ContextDeep).Order("id DESC").Find(&historyMessages).Error
if err == nil {
for i := len(historyMessages) - 1; i >= 0; i-- {
msg := historyMessages[i]
@@ -282,7 +282,7 @@ func (h *ChatHandler) sendMessage(ctx context.Context, input ChatInput, c *gin.C
}
// 上下文的深度超出了模型的最大上下文深度
if len(chatCtx) >= h.App.SysConfig.ContextDeep {
if len(chatCtx) >= h.App.SysConfig.Base.ContextDeep {
break
}

View File

@@ -88,7 +88,7 @@ func (h *DallJobHandler) Image(c *gin.Context) {
Quality: data.Quality,
Size: data.Size,
Style: data.Style,
TranslateModelId: h.App.SysConfig.AssistantModelId,
TranslateModelId: h.App.SysConfig.Base.AssistantModelId,
Power: chatModel.Power,
}
job := model.DallJob{

View File

@@ -197,7 +197,7 @@ func (h *FunctionHandler) Dall3(c *gin.Context) {
return
}
if user.Power < h.App.SysConfig.DallPower {
if user.Power < h.App.SysConfig.Base.DallPower {
resp.ERROR(c, "创建 DALL-E 绘图任务失败,算力不足")
return
}
@@ -209,17 +209,17 @@ func (h *FunctionHandler) Dall3(c *gin.Context) {
Prompt: prompt,
ModelId: 0,
ModelName: "dall-e-3",
TranslateModelId: h.App.SysConfig.AssistantModelId,
TranslateModelId: h.App.SysConfig.Base.AssistantModelId,
N: 1,
Quality: "standard",
Size: "1024x1024",
Style: "vivid",
Power: h.App.SysConfig.DallPower,
Power: h.App.SysConfig.Base.DallPower,
}
job := model.DallJob{
UserId: user.Id,
Prompt: prompt,
Power: h.App.SysConfig.DallPower,
Power: h.App.SysConfig.Base.DallPower,
TaskInfo: utils.JsonEncode(task),
}
err := h.DB.Create(&job).Error

View File

@@ -39,7 +39,7 @@ func (h *MenuHandler) List(c *gin.Context) {
session := h.DB.Session(&gorm.Session{})
session = session.Where("enabled", true)
if index {
session = session.Where("id IN ?", h.App.SysConfig.IndexNavs)
session = session.Where("id IN ?", h.App.SysConfig.Base.IndexNavs)
}
res := session.Order("sort_num ASC").Find(&items)
if res.Error == nil {

View File

@@ -65,7 +65,7 @@ func (h *MidJourneyHandler) preCheck(c *gin.Context) bool {
return false
}
if user.Power < h.App.SysConfig.MjPower {
if user.Power < h.App.SysConfig.Base.MjPower {
resp.ERROR(c, "当前用户剩余算力不足以完成本次绘画!")
return false
}
@@ -171,8 +171,8 @@ func (h *MidJourneyHandler) Image(c *gin.Context) {
Params: params,
UserId: userId,
ImgArr: data.ImgArr,
Mode: h.App.SysConfig.MjMode,
TranslateModelId: h.App.SysConfig.AssistantModelId,
Mode: h.App.SysConfig.Base.MjMode,
TranslateModelId: h.App.SysConfig.Base.AssistantModelId,
}
job := model.MidJourneyJob{
Type: data.TaskType,
@@ -181,7 +181,7 @@ func (h *MidJourneyHandler) Image(c *gin.Context) {
TaskInfo: utils.JsonEncode(task),
Progress: 0,
Prompt: fmt.Sprintf("%s %s", data.Prompt, params),
Power: h.App.SysConfig.MjPower,
Power: h.App.SysConfig.Base.MjPower,
CreatedAt: time.Now(),
}
opt := "绘图"
@@ -244,7 +244,7 @@ func (h *MidJourneyHandler) Upscale(c *gin.Context) {
Index: data.Index,
MessageId: data.MessageId,
MessageHash: data.MessageHash,
Mode: h.App.SysConfig.MjMode,
Mode: h.App.SysConfig.Base.MjMode,
}
job := model.MidJourneyJob{
Type: types.TaskUpscale.String(),
@@ -252,7 +252,7 @@ func (h *MidJourneyHandler) Upscale(c *gin.Context) {
TaskId: taskId,
TaskInfo: utils.JsonEncode(task),
Progress: 0,
Power: h.App.SysConfig.MjActionPower,
Power: h.App.SysConfig.Base.MjActionPower,
CreatedAt: time.Now(),
}
if res := h.DB.Create(&job); res.Error != nil || res.RowsAffected == 0 {
@@ -299,7 +299,7 @@ func (h *MidJourneyHandler) Variation(c *gin.Context) {
ChannelId: data.ChannelId,
MessageId: data.MessageId,
MessageHash: data.MessageHash,
Mode: h.App.SysConfig.MjMode,
Mode: h.App.SysConfig.Base.MjMode,
}
job := model.MidJourneyJob{
Type: types.TaskVariation.String(),
@@ -308,7 +308,7 @@ func (h *MidJourneyHandler) Variation(c *gin.Context) {
TaskId: taskId,
TaskInfo: utils.JsonEncode(task),
Progress: 0,
Power: h.App.SysConfig.MjActionPower,
Power: h.App.SysConfig.Base.MjActionPower,
CreatedAt: time.Now(),
}
if res := h.DB.Create(&job); res.Error != nil || res.RowsAffected == 0 {

View File

@@ -55,20 +55,21 @@ func (h *OrderHandler) List(c *gin.Context) {
order.Id = item.Id
order.CreatedAt = item.CreatedAt.Unix()
order.UpdatedAt = item.UpdatedAt.Unix()
payMethod, ok := types.PayMethods[item.PayWay]
payChannel, ok := types.PayChannel[item.Channel]
if !ok {
payMethod = item.PayWay
payChannel = item.PayWay
}
payName, ok := types.PayNames[item.PayType]
payWays, ok := types.PayWays[item.PayWay]
if !ok {
payName = item.PayWay
payWays = item.PayWay
}
order.PayMethod = payMethod
order.PayName = payName
order.ChannelName = payChannel
order.PayName = payWays
list = append(list, order)
} else {
logger.Error(err)
}
}
}
resp.SUCCESS(c, vo.NewPage(total, page, pageSize, list))

View File

@@ -9,8 +9,10 @@ package handler
import (
"embed"
"errors"
"fmt"
"geekai/core"
"geekai/core/midware"
"geekai/core/types"
"geekai/service"
"geekai/service/payment"
@@ -33,63 +35,143 @@ type PayWay struct {
// PaymentHandler 支付服务回调 handler
type PaymentHandler struct {
BaseHandler
alipayService *payment.AlipayService
huPiPayService *payment.HuPiPayService
geekPayService *payment.GeekPayService
wechatPayService *payment.WechatPayService
snowflake *service.Snowflake
userService *service.UserService
fs embed.FS
lock sync.Mutex
signKey string // 用来签名的随机秘钥
alipayService *payment.AlipayService
epayService *payment.EPayService
wxpayService *payment.WxPayService
snowflake *service.Snowflake
userService *service.UserService
fs embed.FS
lock sync.Mutex
config *types.PaymentConfig
}
func NewPaymentHandler(
server *core.AppServer,
alipayService *payment.AlipayService,
huPiPayService *payment.HuPiPayService,
geekPayService *payment.GeekPayService,
wechatPayService *payment.WechatPayService,
geekPayService *payment.EPayService,
wxpayService *payment.WxPayService,
db *gorm.DB,
userService *service.UserService,
snowflake *service.Snowflake,
fs embed.FS) *PaymentHandler {
fs embed.FS,
sysConfig *types.SystemConfig) *PaymentHandler {
return &PaymentHandler{
alipayService: alipayService,
huPiPayService: huPiPayService,
geekPayService: geekPayService,
wechatPayService: wechatPayService,
snowflake: snowflake,
userService: userService,
fs: fs,
lock: sync.Mutex{},
alipayService: alipayService,
epayService: geekPayService,
wxpayService: wxpayService,
snowflake: snowflake,
userService: userService,
fs: fs,
lock: sync.Mutex{},
BaseHandler: BaseHandler{
App: server,
DB: db,
},
signKey: utils.RandString(32),
config: &sysConfig.Payment,
}
}
// RegisterRoutes 注册路由
func (h *PaymentHandler) RegisterRoutes() {
group := h.App.Engine.Group("/api/payment/")
group.POST("doPay", h.Pay)
group.GET("payWays", h.GetPayWays)
group.POST("notify/alipay", h.AlipayNotify)
group.GET("notify/geek", h.GeekPayNotify)
group.POST("notify/wechat", h.WechatPayNotify)
group.POST("notify/hupi", h.HuPiPayNotify)
rg := h.App.Engine.Group("/api/payment/")
// 支付回调接口(公开)
rg.POST("notify/alipay", h.AlipayNotify)
rg.GET("notify/geek", h.GeekPayNotify)
rg.POST("notify/wechat", h.WechatPayNotify)
// 需要用户登录的接口
rg.Use(midware.UserAuthMiddleware(h.App.Config.Session.SecretKey, h.App.Redis))
{
rg.POST("create", h.Pay)
}
// 同步订单状态
h.StartSyncOrders()
}
func (h *PaymentHandler) StartSyncOrders() {
go func() {
for {
err := h.SyncOrders()
if err != nil {
logger.Error(err)
}
time.Sleep(time.Second * 5)
}
}()
}
// SyncOrders 同步订单状态
func (h *PaymentHandler) SyncOrders() error {
defer func() {
if err := recover(); err != nil {
logger.Errorf("同步订单状态发生异常: %v", err)
}
}()
var orders []model.Order
err := h.DB.Where("status", types.OrderNotPaid).Where("checked", false).Find(&orders).Error
if err != nil {
return err
}
for _, order := range orders {
// 超时15分钟的订单直接标记为已关闭
if time.Now().After(order.CreatedAt.Add(time.Minute * 15)) {
h.DB.Model(&model.Order{}).Where("id", order.Id).Update("checked", true)
return errors.New("订单超时")
}
// 查询订单状态
var res payment.OrderInfo
switch order.Channel {
case payment.PayChannelEpay:
res, err = h.epayService.Query(order.OrderNo)
if err != nil {
return fmt.Errorf("error with query order info: %v", err)
}
// 微信支付
case payment.PayChannelWX:
res, err = h.wxpayService.Query(order.OrderNo)
if err != nil {
return fmt.Errorf("error with query order info: %v", err)
}
case payment.PayChannelAL:
res, err = h.alipayService.Query(order.OrderNo)
if err != nil {
return fmt.Errorf("error with query order info: %v", err)
}
}
// 订单已关闭
if res.Closed() {
h.DB.Model(&model.Order{}).Where("id", order.Id).Updates(map[string]any{
"checked": true,
"status": types.OrderPaidFailed,
})
return errors.New("订单已关闭")
}
// 订单未支付,不处理,继续轮询
if !res.Success() {
return nil
}
// 订单支付成功
err = h.paySuccess(res)
if err != nil {
return fmt.Errorf("error with deal order: %v", err)
}
}
return nil
}
func (h *PaymentHandler) Pay(c *gin.Context) {
var data struct {
PayWay string `json:"pay_way"`
PayType string `json:"pay_type"`
ProductId int `json:"product_id"`
UserId int `json:"user_id"`
Device string `json:"device"`
Host string `json:"host"`
PayWay string `json:"pay_way,omitempty"` // 支付方式:支付宝,微信
Pid int `json:"pid,omitempty"`
Device string `json:"device,omitempty"`
Domain string `json:"domain,omitempty"` // 支付回调域名
Channel string `json:"channel,omitempty"`
}
if err := c.ShouldBindJSON(&data); err != nil {
resp.ERROR(c, types.InvalidArgs)
@@ -97,7 +179,7 @@ func (h *PaymentHandler) Pay(c *gin.Context) {
}
var product model.Product
err := h.DB.Where("id", data.ProductId).First(&product).Error
err := h.DB.Where("id", data.Pid).First(&product).Error
if err != nil {
resp.ERROR(c, "Product not found")
return
@@ -108,136 +190,118 @@ func (h *PaymentHandler) Pay(c *gin.Context) {
resp.ERROR(c, "error with generate trade no: "+err.Error())
return
}
userId := h.GetLoginUserId(c)
var user model.User
err = h.DB.Where("id", data.UserId).First(&user).Error
err = h.DB.Where("id", userId).First(&user).Error
if err != nil {
resp.NotAuth(c)
return
}
amount := product.Discount
var payURL, returnURL, notifyURL string
amount := product.Price
var payURL, notifyURL string
switch data.PayWay {
case "alipay":
if h.App.Config.AlipayConfig.NotifyURL != "" { // 用于本地调试支付
notifyURL = h.App.Config.AlipayConfig.NotifyURL
} else {
notifyURL = fmt.Sprintf("%s/api/payment/notify/alipay", data.Host)
}
if h.App.Config.AlipayConfig.ReturnURL != "" { // 用于本地调试支付
returnURL = h.App.Config.AlipayConfig.ReturnURL
} else {
returnURL = fmt.Sprintf("%s/payReturn", data.Host)
}
money := fmt.Sprintf("%.2f", amount)
if data.Device == "wechat" {
payURL, err = h.alipayService.PayMobile(payment.AlipayParams{
case "wxpay":
logger.Debugf("微信支付,%+v", data)
data.Channel = payment.PayChannelWX
// 优先使用微信官方支付
if h.config.WxPay.Enabled {
data.Channel = "wxpay"
if h.config.WxPay.Domain != "" {
data.Domain = h.config.WxPay.Domain
}
notifyURL = fmt.Sprintf("%s/api/payment/notify/wechat", data.Domain)
payURL, err = h.wxpayService.Pay(payment.PayRequest{
OutTradeNo: orderNo,
Subject: product.Name,
TotalFee: money,
ReturnURL: returnURL,
NotifyURL: notifyURL,
})
} else {
payURL, err = h.alipayService.PayPC(payment.AlipayParams{
OutTradeNo: orderNo,
Subject: product.Name,
TotalFee: money,
ReturnURL: returnURL,
NotifyURL: notifyURL,
})
}
if err != nil {
resp.ERROR(c, "error with generate pay url: "+err.Error())
return
}
break
case "wechat":
if h.App.Config.WechatPayConfig.NotifyURL != "" {
notifyURL = h.App.Config.WechatPayConfig.NotifyURL
} else {
notifyURL = fmt.Sprintf("%s/api/payment/notify/wechat", data.Host)
}
if data.Device == "wechat" {
payURL, err = h.wechatPayService.PayUrlH5(payment.WechatPayParams{
OutTradeNo: orderNo,
TotalFee: int(amount * 100),
TotalFee: fmt.Sprintf("%d", int(amount*100)),
Subject: product.Name,
NotifyURL: notifyURL,
ClientIP: c.ClientIP(),
Device: data.Device,
PayWay: payment.PayWayWX,
})
} else {
payURL, err = h.wechatPayService.PayUrlNative(payment.WechatPayParams{
if err != nil {
resp.ERROR(c, err.Error())
return
}
} else if h.config.Epay.Enabled { // 聚合支付
logger.Debugf("聚合支付%+v", data)
data.Channel = payment.PayChannelEpay
if h.config.Epay.Domain != "" {
data.Domain = h.config.Epay.Domain
}
notifyURL = fmt.Sprintf("%s/api/payment/notify/geek", data.Domain)
params := payment.PayRequest{
OutTradeNo: orderNo,
TotalFee: int(amount * 100),
Subject: product.Name,
TotalFee: fmt.Sprintf("%f", amount),
ClientIP: c.ClientIP(),
Device: data.Device,
PayWay: payment.PayWayWX,
NotifyURL: notifyURL,
}
r, err := h.epayService.Pay(params)
logger.Debugf("请求支付结果,%+v", r)
if err != nil {
resp.ERROR(c, err.Error())
return
} else {
payURL = r
}
} else {
resp.ERROR(c, "系统没有配置可用的支付渠道!")
return
}
case "alipay":
if h.config.Alipay.Enabled {
logger.Debugf("支付宝,%+v", data)
data.Channel = payment.PayChannelAL
if h.config.Alipay.Domain != "" { // 用于本地调试支付
data.Domain = h.config.Alipay.Domain
}
notifyURL = fmt.Sprintf("%s/api/payment/notify/alipay", data.Domain)
money := fmt.Sprintf("%.2f", amount)
payURL, err = h.alipayService.Pay(payment.PayRequest{
Device: data.Device,
OutTradeNo: orderNo,
Subject: product.Name,
TotalFee: money,
NotifyURL: notifyURL,
})
}
if err != nil {
resp.ERROR(c, err.Error())
return
}
break
case "hupi":
if h.App.Config.HuPiPayConfig.NotifyURL != "" {
notifyURL = h.App.Config.HuPiPayConfig.NotifyURL
} else {
notifyURL = fmt.Sprintf("%s/api/payment/notify/hupi", data.Host)
}
if h.App.Config.HuPiPayConfig.ReturnURL != "" {
returnURL = h.App.Config.HuPiPayConfig.ReturnURL
} else {
returnURL = fmt.Sprintf("%s/payReturn", data.Host)
}
r, err := h.huPiPayService.Pay(payment.HuPiPayParams{
Version: "1.1",
TradeOrderId: orderNo,
TotalFee: fmt.Sprintf("%f", amount),
Title: product.Name,
NotifyURL: notifyURL,
ReturnURL: returnURL,
WapName: "GeekAI助手",
})
if err != nil {
resp.ERROR(c, err.Error())
return
}
payURL = r.URL
break
case "geek":
if h.App.Config.GeekPayConfig.NotifyURL != "" {
notifyURL = h.App.Config.GeekPayConfig.NotifyURL
} else {
notifyURL = fmt.Sprintf("%s/api/payment/notify/geek", data.Host)
}
if h.App.Config.GeekPayConfig.ReturnURL != "" {
data.Host = utils.GetBaseURL(h.App.Config.GeekPayConfig.ReturnURL)
}
if data.Device == "wechat" { // 微信客户端打开,调回手机端用户中心页面
returnURL = fmt.Sprintf("%s/mobile/profile", data.Host)
} else {
returnURL = fmt.Sprintf("%s/payReturn", data.Host)
}
params := payment.GeekPayParams{
OutTradeNo: orderNo,
Method: "web",
Name: product.Name,
Money: fmt.Sprintf("%f", amount),
ClientIP: c.ClientIP(),
Device: data.Device,
Type: data.PayType,
ReturnURL: returnURL,
NotifyURL: notifyURL,
}
res, err := h.geekPayService.Pay(params)
if err != nil {
resp.ERROR(c, err.Error())
if err != nil {
resp.ERROR(c, "error with generate pay url: "+err.Error())
return
}
} else if h.config.Epay.Enabled { // 聚合支付
logger.Debugf("聚合支付,%+v", data)
data.Channel = payment.PayChannelEpay
if h.config.Epay.Domain != "" {
data.Domain = h.config.Epay.Domain
}
notifyURL = fmt.Sprintf("%s/api/payment/notify/geek", data.Domain)
params := payment.PayRequest{
OutTradeNo: orderNo,
Subject: product.Name,
TotalFee: fmt.Sprintf("%f", amount),
ClientIP: c.ClientIP(),
Device: data.Device,
PayWay: data.PayWay,
NotifyURL: notifyURL,
}
r, err := h.epayService.Pay(params)
if err != nil {
resp.ERROR(c, err.Error())
return
} else {
payURL = r
}
} else {
resp.ERROR(c, "系统没有配置可用的支付渠道!")
return
}
payURL = res.PayURL
default:
resp.ERROR(c, "不支持的支付渠道")
return
@@ -245,43 +309,41 @@ func (h *PaymentHandler) Pay(c *gin.Context) {
// 创建订单
remark := types.OrderRemark{
Days: product.Days,
Power: product.Power,
Name: product.Name,
Price: product.Price,
Discount: product.Discount,
Days: product.Days,
Power: product.Power,
Name: product.Name,
Price: product.Price,
}
order := model.Order{
UserId: user.Id,
Username: user.Username,
ProductId: product.Id,
OrderNo: orderNo,
Subject: product.Name,
Amount: amount,
Status: types.OrderNotPaid,
PayWay: data.PayWay,
PayType: data.PayType,
Remark: utils.JsonEncode(remark),
UserId: user.Id,
Username: user.Username,
OrderNo: orderNo,
Subject: product.Name,
Amount: amount,
Status: types.OrderNotPaid,
PayWay: data.PayWay,
Channel: data.Channel,
Remark: utils.JsonEncode(remark),
}
err = h.DB.Create(&order).Error
if err != nil {
resp.ERROR(c, "error with create order: "+err.Error())
return
}
resp.SUCCESS(c, payURL)
resp.SUCCESS(c, gin.H{"pay_url": payURL, "order_no": orderNo})
}
// 异步通知回调公共逻辑
func (h *PaymentHandler) notify(orderNo string, tradeNo string) error {
// 支付成功处理
func (h *PaymentHandler) paySuccess(info payment.OrderInfo) error {
h.lock.Lock()
defer h.lock.Unlock()
var order model.Order
err := h.DB.Where("order_no = ?", orderNo).First(&order).Error
err := h.DB.Where("order_no", info.OutTradeNo).First(&order).Error
if err != nil {
return fmt.Errorf("error with fetch order: %v", err)
}
h.lock.Lock()
defer h.lock.Unlock()
// 已支付订单,直接返回
if order.Status == types.OrderPaidSuccess {
return nil
@@ -301,18 +363,20 @@ func (h *PaymentHandler) notify(orderNo string, tradeNo string) error {
// 增加用户算力
err = h.userService.IncreasePower(order.UserId, remark.Power, model.PowerLog{
Type: types.PowerRecharge,
Model: order.PayWay,
Remark: fmt.Sprintf("充值算力,金额:%f订单号%s", order.Amount, order.OrderNo),
Type: types.PowerRecharge,
Model: order.Subject,
Remark: fmt.Sprintf("充值算力,金额:%f订单号%s", order.Amount, order.OrderNo),
CreatedAt: time.Now(),
})
if err != nil {
return err
}
// 更新订单状态
order.PayTime = time.Now().Unix()
order.PayTime = utils.Str2stamp(info.PayTime)
order.Status = types.OrderPaidSuccess
order.TradeNo = tradeNo
order.TradeNo = info.TradeId
order.Checked = true
err = h.DB.Updates(&order).Error
if err != nil {
return fmt.Errorf("error with update order info: %v", err)
@@ -328,54 +392,6 @@ func (h *PaymentHandler) notify(orderNo string, tradeNo string) error {
return nil
}
// GetPayWays 获取支付方式
func (h *PaymentHandler) GetPayWays(c *gin.Context) {
payWays := make([]gin.H, 0)
if h.App.Config.AlipayConfig.Enabled {
payWays = append(payWays, gin.H{"pay_way": "alipay", "pay_type": "alipay"})
}
if h.App.Config.HuPiPayConfig.Enabled {
payWays = append(payWays, gin.H{"pay_way": "hupi", "pay_type": "wxpay"})
}
if h.App.Config.GeekPayConfig.Enabled {
for _, v := range h.App.Config.GeekPayConfig.Methods {
payWays = append(payWays, gin.H{"pay_way": "geek", "pay_type": v})
}
}
if h.App.Config.WechatPayConfig.Enabled {
payWays = append(payWays, gin.H{"pay_way": "wechat", "pay_type": "wxpay"})
}
resp.SUCCESS(c, payWays)
}
// HuPiPayNotify 虎皮椒支付异步回调
func (h *PaymentHandler) HuPiPayNotify(c *gin.Context) {
err := c.Request.ParseForm()
if err != nil {
c.String(http.StatusOK, "fail")
return
}
orderNo := c.Request.Form.Get("trade_order_id")
tradeNo := c.Request.Form.Get("open_order_id")
logger.Infof("收到虎皮椒订单支付回调,%+v", c.Request.Form)
if err = h.huPiPayService.Check(orderNo); err != nil {
logger.Error("订单校验失败:", err)
c.String(http.StatusOK, "fail")
return
}
err = h.notify(orderNo, tradeNo)
if err != nil {
logger.Error(err)
c.String(http.StatusOK, "fail")
return
}
c.String(http.StatusOK, "success")
}
// AlipayNotify 支付宝支付回调
func (h *PaymentHandler) AlipayNotify(c *gin.Context) {
err := c.Request.ParseForm()
@@ -384,16 +400,15 @@ func (h *PaymentHandler) AlipayNotify(c *gin.Context) {
return
}
result := h.alipayService.TradeVerify(c.Request)
logger.Infof("收到支付宝商号订单支付回调:%+v", result)
if !result.Success() {
logger.Error("订单校验失败:", result.Message)
orderInfo, err := h.alipayService.Query(c.Request.Form.Get("out_trade_no"))
logger.Infof("收到支付宝商号订单支付回调:%+v", orderInfo)
if !orderInfo.Success() {
logger.Errorf("订单校验失败:%v", err)
c.String(http.StatusOK, "fail")
return
}
tradeNo := c.Request.Form.Get("trade_no")
err = h.notify(result.OutTradeNo, tradeNo)
err = h.paySuccess(orderInfo)
if err != nil {
logger.Error(err)
c.String(http.StatusOK, "fail")
@@ -411,20 +426,27 @@ func (h *PaymentHandler) GeekPayNotify(c *gin.Context) {
}
logger.Infof("收到GeekPay订单支付回调%+v", params)
// 检查支付状态
// 检查支付状态, 如果未支付,则返回成功
if params["trade_status"] != "TRADE_SUCCESS" {
c.String(http.StatusOK, "success")
return
}
sign := h.geekPayService.Sign(params)
sign := h.epayService.Sign(params)
if sign != c.Query("sign") {
logger.Errorf("签名验证失败, %s, %s", sign, c.Query("sign"))
c.String(http.StatusOK, "fail")
return
}
// 查询订单状态
order, err := h.epayService.Query(params["out_trade_no"])
if err != nil {
logger.Error(err)
c.String(http.StatusOK, "fail")
return
}
err := h.notify(params["out_trade_no"], params["trade_no"])
err = h.paySuccess(order)
if err != nil {
logger.Error(err)
c.String(http.StatusOK, "fail")
@@ -442,18 +464,15 @@ func (h *PaymentHandler) WechatPayNotify(c *gin.Context) {
return
}
result := h.wechatPayService.TradeVerify(c.Request)
logger.Infof("收到微信商号订单支付回调:%+v", result)
if !result.Success() {
logger.Error("订单校验失败:", err)
c.JSON(http.StatusBadRequest, gin.H{
"code": "FAIL",
"message": err.Error(),
})
orderInfo, err := h.wxpayService.TradeVerify(c.Request)
logger.Infof("收到微信商号订单支付回调:%+v", orderInfo)
if err != nil {
logger.Errorf("订单校验失败:%v", err)
c.JSON(http.StatusBadRequest, gin.H{"code": "FAIL"})
return
}
err = h.notify(result.OutTradeNo, result.TradeId)
err = h.paySuccess(orderInfo)
if err != nil {
logger.Error(err)
c.String(http.StatusOK, "fail")

View File

@@ -57,15 +57,15 @@ func (h *PromptHandler) Lyric(c *gin.Context) {
resp.ERROR(c, types.InvalidArgs)
return
}
content, err := utils.OpenAIRequest(h.DB, fmt.Sprintf(service.LyricPromptTemplate, data.Prompt), h.App.SysConfig.AssistantModelId)
content, err := utils.OpenAIRequest(h.DB, fmt.Sprintf(service.LyricPromptTemplate, data.Prompt), h.App.SysConfig.Base.AssistantModelId)
if err != nil {
resp.ERROR(c, err.Error())
return
}
if h.App.SysConfig.PromptPower > 0 {
if h.App.SysConfig.Base.PromptPower > 0 {
userId := h.GetLoginUserId(c)
err = h.userService.DecreasePower(userId, h.App.SysConfig.PromptPower, model.PowerLog{
err = h.userService.DecreasePower(userId, h.App.SysConfig.Base.PromptPower, model.PowerLog{
Type: types.PowerConsume,
Model: h.getPromptModel(),
Remark: "生成歌词",
@@ -88,14 +88,14 @@ func (h *PromptHandler) Image(c *gin.Context) {
resp.ERROR(c, types.InvalidArgs)
return
}
content, err := utils.OpenAIRequest(h.DB, fmt.Sprintf(service.ImagePromptOptimizeTemplate, data.Prompt), h.App.SysConfig.AssistantModelId)
content, err := utils.OpenAIRequest(h.DB, fmt.Sprintf(service.ImagePromptOptimizeTemplate, data.Prompt), h.App.SysConfig.Base.AssistantModelId)
if err != nil {
resp.ERROR(c, err.Error())
return
}
if h.App.SysConfig.PromptPower > 0 {
if h.App.SysConfig.Base.PromptPower > 0 {
userId := h.GetLoginUserId(c)
err = h.userService.DecreasePower(userId, h.App.SysConfig.PromptPower, model.PowerLog{
err = h.userService.DecreasePower(userId, h.App.SysConfig.Base.PromptPower, model.PowerLog{
Type: types.PowerConsume,
Model: h.getPromptModel(),
Remark: "生成绘画提示词",
@@ -117,15 +117,15 @@ func (h *PromptHandler) Video(c *gin.Context) {
resp.ERROR(c, types.InvalidArgs)
return
}
content, err := utils.OpenAIRequest(h.DB, fmt.Sprintf(service.VideoPromptTemplate, data.Prompt), h.App.SysConfig.AssistantModelId)
content, err := utils.OpenAIRequest(h.DB, fmt.Sprintf(service.VideoPromptTemplate, data.Prompt), h.App.SysConfig.Base.AssistantModelId)
if err != nil {
resp.ERROR(c, err.Error())
return
}
if h.App.SysConfig.PromptPower > 0 {
if h.App.SysConfig.Base.PromptPower > 0 {
userId := h.GetLoginUserId(c)
err = h.userService.DecreasePower(userId, h.App.SysConfig.PromptPower, model.PowerLog{
err = h.userService.DecreasePower(userId, h.App.SysConfig.Base.PromptPower, model.PowerLog{
Type: types.PowerConsume,
Model: h.getPromptModel(),
Remark: "生成视频脚本",
@@ -167,9 +167,9 @@ func (h *PromptHandler) MetaPrompt(c *gin.Context) {
}
func (h *PromptHandler) getPromptModel() string {
if h.App.SysConfig.AssistantModelId > 0 {
if h.App.SysConfig.Base.AssistantModelId > 0 {
var chatModel model.ChatModel
h.DB.Where("id", h.App.SysConfig.AssistantModelId).First(&chatModel)
h.DB.Where("id", h.App.SysConfig.Base.AssistantModelId).First(&chatModel)
return chatModel.Value
}
return "gpt-4o"

View File

@@ -160,7 +160,7 @@ func (h *RealtimeHandler) VoiceChat(c *gin.Context) {
return
}
if user.Power < h.App.SysConfig.AdvanceVoicePower {
if user.Power < h.App.SysConfig.Base.AdvanceVoicePower {
resp.ERROR(c, "当前用户算力不足,无法使用该功能")
return
}
@@ -204,7 +204,7 @@ func (h *RealtimeHandler) VoiceChat(c *gin.Context) {
h.DB.Model(&apiKey).UpdateColumn("last_used_at", time.Now().Unix())
// 扣减算力
err = h.userService.DecreasePower(userId, h.App.SysConfig.AdvanceVoicePower, model.PowerLog{
err = h.userService.DecreasePower(userId, h.App.SysConfig.Base.AdvanceVoicePower, model.PowerLog{
Type: types.PowerConsume,
Model: "advanced-voice",
Remark: "实时语音通话",

View File

@@ -73,7 +73,7 @@ func (h *SdJobHandler) preCheck(c *gin.Context) bool {
return false
}
if user.Power < h.App.SysConfig.SdPower {
if user.Power < h.App.SysConfig.Base.SdPower {
resp.ERROR(c, "当前用户剩余算力不足以完成本次绘画!")
return false
}
@@ -141,7 +141,7 @@ func (h *SdJobHandler) Image(c *gin.Context) {
HdSteps: data.HdSteps,
},
UserId: userId,
TranslateModelId: h.App.SysConfig.AssistantModelId,
TranslateModelId: h.App.SysConfig.Base.AssistantModelId,
}
job := model.SdJob{
@@ -152,7 +152,7 @@ func (h *SdJobHandler) Image(c *gin.Context) {
TaskInfo: utils.JsonEncode(task),
Prompt: data.Prompt,
Progress: 0,
Power: h.App.SysConfig.SdPower,
Power: h.App.SysConfig.Base.SdPower,
CreatedAt: time.Now(),
}
res := h.DB.Create(&job)

View File

@@ -25,7 +25,7 @@ const CodeStorePrefix = "/verify/codes/"
type SmsHandler struct {
BaseHandler
redis *redis.Client
sms *sms.ServiceManager
sms *sms.SmsManager
smtp *service.SmtpService
captcha *service.CaptchaService
}
@@ -33,7 +33,7 @@ type SmsHandler struct {
func NewSmsHandler(
app *core.AppServer,
client *redis.Client,
sms *sms.ServiceManager,
sms *sms.SmsManager,
smtp *service.SmtpService,
captcha *service.CaptchaService) *SmsHandler {
return &SmsHandler{
@@ -62,7 +62,7 @@ func (h *SmsHandler) SendCode(c *gin.Context) {
resp.ERROR(c, types.InvalidArgs)
return
}
if h.App.SysConfig.EnabledVerify {
if h.App.SysConfig.Base.EnabledVerify {
var check bool
if data.X != 0 {
check = h.captcha.SlideCheck(data)
@@ -78,14 +78,14 @@ func (h *SmsHandler) SendCode(c *gin.Context) {
code := utils.RandomNumber(6)
var err error
if strings.Contains(data.Receiver, "@") { // email
if !utils.Contains(h.App.SysConfig.RegisterWays, "email") {
if !utils.Contains(h.App.SysConfig.Base.RegisterWays, "email") {
resp.ERROR(c, "系统已禁用邮箱注册!")
return
}
// 检查邮箱后缀是否在白名单
if len(h.App.SysConfig.EmailWhiteList) > 0 {
if len(h.App.SysConfig.Base.EmailWhiteList) > 0 {
inWhiteList := false
for _, suffix := range h.App.SysConfig.EmailWhiteList {
for _, suffix := range h.App.SysConfig.Base.EmailWhiteList {
if strings.HasSuffix(data.Receiver, suffix) {
inWhiteList = true
break
@@ -98,7 +98,7 @@ func (h *SmsHandler) SendCode(c *gin.Context) {
}
err = h.smtp.SendVerifyCode(data.Receiver, code)
} else {
if !utils.Contains(h.App.SysConfig.RegisterWays, "mobile") {
if !utils.Contains(h.App.SysConfig.Base.RegisterWays, "mobile") {
resp.ERROR(c, "系统已禁用手机号注册!")
return
}

View File

@@ -82,7 +82,7 @@ func (h *SunoHandler) Create(c *gin.Context) {
return
}
if user.Power < h.App.SysConfig.SunoPower {
if user.Power < h.App.SysConfig.Base.SunoPower {
resp.ERROR(c, "您的算力不足,请充值后再试!")
return
}
@@ -130,7 +130,7 @@ func (h *SunoHandler) Create(c *gin.Context) {
RefSongId: data.RefSongId,
RefTaskId: data.RefTaskId,
ExtendSecs: data.ExtendSecs,
Power: h.App.SysConfig.SunoPower,
Power: h.App.SysConfig.Base.SunoPower,
SongId: utils.RandString(32),
}
if data.Lyrics != "" {

View File

@@ -4,19 +4,20 @@ import (
"geekai/core"
"geekai/service"
"geekai/service/payment"
"net/http"
"github.com/gin-gonic/gin"
"gorm.io/gorm"
"net/http"
)
type TestHandler struct {
App *core.AppServer
db *gorm.DB
snowflake *service.Snowflake
js *payment.GeekPayService
js *payment.EPayService
}
func NewTestHandler(app *core.AppServer, db *gorm.DB, snowflake *service.Snowflake, js *payment.GeekPayService) *TestHandler {
func NewTestHandler(app *core.AppServer, db *gorm.DB, snowflake *service.Snowflake, js *payment.EPayService) *TestHandler {
return &TestHandler{App: app, db: db, snowflake: snowflake, js: js}
}

View File

@@ -20,8 +20,6 @@ import (
"strings"
"time"
"github.com/imroc/req/v3"
"github.com/go-redis/redis/v8"
"github.com/golang-jwt/jwt/v5"
@@ -98,7 +96,7 @@ func (h *UserHandler) Register(c *gin.Context) {
return
}
if h.App.SysConfig.EnabledVerify && data.RegWay == "username" {
if h.App.SysConfig.Base.EnabledVerify && data.RegWay == "username" {
var check bool
if data.X != 0 {
check = h.captcha.SlideCheck(data)
@@ -163,7 +161,7 @@ func (h *UserHandler) Register(c *gin.Context) {
ChatRoles: utils.JsonEncode([]string{"gpt"}), // 默认只订阅通用助手角色
ChatConfig: "{}",
ChatModels: "{}",
Power: h.App.SysConfig.InitPower,
Power: h.App.SysConfig.Base.InitPower,
}
// check if the username is existing
@@ -188,13 +186,13 @@ func (h *UserHandler) Register(c *gin.Context) {
// 被邀请人也获得赠送算力
if data.InviteCode != "" {
user.Power += h.App.SysConfig.InvitePower
user.Power += h.App.SysConfig.Base.InvitePower
}
if h.licenseService.GetLicense().Configs.DeCopy {
user.Nickname = fmt.Sprintf("用户@%d", utils.RandomNumber(6))
} else {
defaultNickname := h.App.SysConfig.DefaultNickname
defaultNickname := h.App.SysConfig.Base.DefaultNickname
if defaultNickname == "" {
defaultNickname = "极客学长"
}
@@ -211,11 +209,11 @@ func (h *UserHandler) Register(c *gin.Context) {
if data.InviteCode != "" {
// 增加邀请数量
h.DB.Model(&model.InviteCode{}).Where("code = ?", data.InviteCode).UpdateColumn("reg_num", gorm.Expr("reg_num + ?", 1))
if h.App.SysConfig.InvitePower > 0 {
err := h.userService.IncreasePower(inviteCode.UserId, h.App.SysConfig.InvitePower, model.PowerLog{
if h.App.SysConfig.Base.InvitePower > 0 {
err := h.userService.IncreasePower(inviteCode.UserId, h.App.SysConfig.Base.InvitePower, model.PowerLog{
Type: types.PowerInvite,
Model: "Invite",
Remark: fmt.Sprintf("邀请用户注册奖励,金额:%d邀请码%s新用户%s", h.App.SysConfig.InvitePower, inviteCode.Code, user.Username),
Remark: fmt.Sprintf("邀请用户注册奖励,金额:%d邀请码%s新用户%s", h.App.SysConfig.Base.InvitePower, inviteCode.Code, user.Username),
})
if err != nil {
tx.Rollback()
@@ -230,7 +228,7 @@ func (h *UserHandler) Register(c *gin.Context) {
UserId: user.Id,
Username: user.Username,
InviteCode: inviteCode.Code,
Remark: fmt.Sprintf("奖励 %d 算力", h.App.SysConfig.InvitePower),
Remark: fmt.Sprintf("奖励 %d 算力", h.App.SysConfig.Base.InvitePower),
}).Error
if err != nil {
tx.Rollback()
@@ -276,7 +274,7 @@ func (h *UserHandler) Login(c *gin.Context) {
verifyKey := fmt.Sprintf("users/verify/%s", data.Username)
needVerify, err := h.redis.Get(c, verifyKey).Bool()
if h.App.SysConfig.EnabledVerify && needVerify {
if h.App.SysConfig.Base.EnabledVerify && needVerify {
var check bool
if data.X != 0 {
check = h.captcha.SlideCheck(data)
@@ -353,150 +351,128 @@ func (h *UserHandler) Logout(c *gin.Context) {
// CLogin 第三方登录请求二维码
func (h *UserHandler) CLogin(c *gin.Context) {
returnURL := h.GetTrim(c, "return_url")
var res types.BizVo
apiURL := fmt.Sprintf("%s/api/clogin/request", h.App.Config.ApiConfig.ApiURL)
r, err := req.C().R().SetBody(gin.H{"login_type": "wx", "return_url": returnURL}).
SetHeader("AppId", h.App.Config.ApiConfig.AppId).
SetHeader("Authorization", fmt.Sprintf("Bearer %s", h.App.Config.ApiConfig.Token)).
SetSuccessResult(&res).
Post(apiURL)
if err != nil {
resp.ERROR(c, err.Error())
return
}
if r.IsErrorState() {
resp.ERROR(c, "error with login http status: "+r.Status)
return
}
if res.Code != types.Success {
resp.ERROR(c, "error with http response: "+res.Message)
return
}
resp.SUCCESS(c, res.Data)
}
// CLoginCallback 第三方登录回调
func (h *UserHandler) CLoginCallback(c *gin.Context) {
loginType := c.Query("login_type")
code := c.Query("code")
userId := h.GetInt(c, "user_id", 0)
action := c.Query("action")
// loginType := c.Query("login_type")
// code := c.Query("code")
// userId := h.GetInt(c, "user_id", 0)
// action := c.Query("action")
var res types.BizVo
apiURL := fmt.Sprintf("%s/api/clogin/info", h.App.Config.ApiConfig.ApiURL)
r, err := req.C().R().SetBody(gin.H{"login_type": loginType, "code": code}).
SetHeader("AppId", h.App.Config.ApiConfig.AppId).
SetHeader("Authorization", fmt.Sprintf("Bearer %s", h.App.Config.ApiConfig.Token)).
SetSuccessResult(&res).
Post(apiURL)
if err != nil {
resp.ERROR(c, err.Error())
return
}
if r.IsErrorState() {
resp.ERROR(c, "error with login http status: "+r.Status)
return
}
// var res types.BizVo
// apiURL := fmt.Sprintf("%s/api/clogin/info", h.App.Config.ApiConfig.ApiURL)
// r, err := req.C().R().SetBody(gin.H{"login_type": loginType, "code": code}).
// SetHeader("AppId", h.App.Config.ApiConfig.AppId).
// SetHeader("Authorization", fmt.Sprintf("Bearer %s", h.App.Config.ApiConfig.Token)).
// SetSuccessResult(&res).
// Post(apiURL)
// if err != nil {
// resp.ERROR(c, err.Error())
// return
// }
// if r.IsErrorState() {
// resp.ERROR(c, "error with login http status: "+r.Status)
// return
// }
if res.Code != types.Success {
resp.ERROR(c, "error with http response: "+res.Message)
return
}
// if res.Code != types.Success {
// resp.ERROR(c, "error with http response: "+res.Message)
// return
// }
// login successfully
data := res.Data.(map[string]interface{})
var user model.User
if action == "bind" && userId > 0 {
err = h.DB.Where("openid", data["openid"]).First(&user).Error
if err == nil {
resp.ERROR(c, "该微信已经绑定其他账号,请先解绑")
return
}
// // login successfully
// data := res.Data.(map[string]interface{})
// var user model.User
// if action == "bind" && userId > 0 {
// err = h.DB.Where("openid", data["openid"]).First(&user).Error
// if err == nil {
// resp.ERROR(c, "该微信已经绑定其他账号,请先解绑")
// return
// }
err = h.DB.Where("id", userId).First(&user).Error
if err != nil {
resp.ERROR(c, "绑定用户不存在")
return
}
// err = h.DB.Where("id", userId).First(&user).Error
// if err != nil {
// resp.ERROR(c, "绑定用户不存在")
// return
// }
err = h.DB.Model(&user).UpdateColumn("openid", data["openid"]).Error
if err != nil {
resp.ERROR(c, "更新用户信息失败,"+err.Error())
return
}
// err = h.DB.Model(&user).UpdateColumn("openid", data["openid"]).Error
// if err != nil {
// resp.ERROR(c, "更新用户信息失败,"+err.Error())
// return
// }
resp.SUCCESS(c, gin.H{"token": ""})
return
}
// resp.SUCCESS(c, gin.H{"token": ""})
// return
// }
session := gin.H{}
tx := h.DB.Where("openid", data["openid"]).First(&user)
if tx.Error != nil {
// create new user
var totalUser int64
h.DB.Model(&model.User{}).Count(&totalUser)
if h.licenseService.GetLicense().Configs.UserNum > 0 && int(totalUser) >= h.licenseService.GetLicense().Configs.UserNum {
resp.ERROR(c, "当前注册用户数已达上限,请请升级 License")
return
}
// session := gin.H{}
// tx := h.DB.Where("openid", data["openid"]).First(&user)
// if tx.Error != nil {
// // create new user
// var totalUser int64
// h.DB.Model(&model.User{}).Count(&totalUser)
// if h.licenseService.GetLicense().Configs.UserNum > 0 && int(totalUser) >= h.licenseService.GetLicense().Configs.UserNum {
// resp.ERROR(c, "当前注册用户数已达上限,请请升级 License")
// return
// }
salt := utils.RandString(8)
password := fmt.Sprintf("%d", utils.RandomNumber(8))
user = model.User{
Username: fmt.Sprintf("%s@%d", loginType, utils.RandomNumber(10)),
Password: utils.GenPassword(password, salt),
Avatar: fmt.Sprintf("%s", data["avatar"]),
Salt: salt,
Status: true,
ChatRoles: utils.JsonEncode([]string{"gpt"}), // 默认只订阅通用助手角色
Power: h.App.SysConfig.InitPower,
OpenId: fmt.Sprintf("%s", data["openid"]),
Nickname: fmt.Sprintf("%s", data["nickname"]),
}
// salt := utils.RandString(8)
// password := fmt.Sprintf("%d", utils.RandomNumber(8))
// user = model.User{
// Username: fmt.Sprintf("%s@%d", loginType, utils.RandomNumber(10)),
// Password: utils.GenPassword(password, salt),
// Avatar: fmt.Sprintf("%s", data["avatar"]),
// Salt: salt,
// Status: true,
// ChatRoles: utils.JsonEncode([]string{"gpt"}), // 默认只订阅通用助手角色
// Power: h.App.SysConfig.InitPower,
// OpenId: fmt.Sprintf("%s", data["openid"]),
// Nickname: fmt.Sprintf("%s", data["nickname"]),
// }
tx = h.DB.Create(&user)
if tx.Error != nil {
resp.ERROR(c, "保存数据失败")
logger.Error(tx.Error)
return
}
session["username"] = user.Username
session["password"] = password
} else { // login directly
// 更新最后登录时间和IP
user.LastLoginIp = c.ClientIP()
user.LastLoginAt = time.Now().Unix()
h.DB.Model(&user).Updates(user)
// tx = h.DB.Create(&user)
// if tx.Error != nil {
// resp.ERROR(c, "保存数据失败")
// logger.Error(tx.Error)
// return
// }
// session["username"] = user.Username
// session["password"] = password
// } else { // login directly
// // 更新最后登录时间和IP
// user.LastLoginIp = c.ClientIP()
// user.LastLoginAt = time.Now().Unix()
// h.DB.Model(&user).Updates(user)
h.DB.Create(&model.UserLoginLog{
UserId: user.Id,
Username: user.Username,
LoginIp: c.ClientIP(),
LoginAddress: utils.Ip2Region(h.searcher, c.ClientIP()),
})
}
// h.DB.Create(&model.UserLoginLog{
// UserId: user.Id,
// Username: user.Username,
// LoginIp: c.ClientIP(),
// LoginAddress: utils.Ip2Region(h.searcher, c.ClientIP()),
// })
// }
// 创建 token
token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{
"user_id": user.Id,
"expired": time.Now().Add(time.Second * time.Duration(h.App.Config.Session.MaxAge)).Unix(),
})
tokenString, err := token.SignedString([]byte(h.App.Config.Session.SecretKey))
if err != nil {
resp.ERROR(c, "Failed to generate token, "+err.Error())
return
}
// 保存到 redis
key := fmt.Sprintf("users/%d", user.Id)
if _, err := h.redis.Set(c, key, tokenString, 0).Result(); err != nil {
resp.ERROR(c, "error with save token: "+err.Error())
return
}
session["token"] = tokenString
resp.SUCCESS(c, session)
// // 创建 token
// token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{
// "user_id": user.Id,
// "expired": time.Now().Add(time.Second * time.Duration(h.App.Config.Session.MaxAge)).Unix(),
// })
// tokenString, err := token.SignedString([]byte(h.App.Config.Session.SecretKey))
// if err != nil {
// resp.ERROR(c, "Failed to generate token, "+err.Error())
// return
// }
// // 保存到 redis
// key := fmt.Sprintf("users/%d", user.Id)
// if _, err := h.redis.Set(c, key, tokenString, 0).Result(); err != nil {
// resp.ERROR(c, "error with save token: "+err.Error())
// return
// }
// session["token"] = tokenString
// resp.SUCCESS(c, session)
}
// Session 获取/验证会话
@@ -760,11 +736,11 @@ func (h *UserHandler) SignIn(c *gin.Context) {
// 签到
h.levelDB.Put(key, true)
if h.App.SysConfig.DailyPower > 0 {
h.userService.IncreasePower(userId, h.App.SysConfig.DailyPower, model.PowerLog{
if h.App.SysConfig.Base.DailyPower > 0 {
h.userService.IncreasePower(userId, h.App.SysConfig.Base.DailyPower, model.PowerLog{
Type: types.PowerSignIn,
Model: "SignIn",
Remark: fmt.Sprintf("每日签到奖励,金额:%d", h.App.SysConfig.DailyPower),
Remark: fmt.Sprintf("每日签到奖励,金额:%d", h.App.SysConfig.Base.DailyPower),
})
}
resp.SUCCESS(c)

View File

@@ -78,7 +78,7 @@ func (h *VideoHandler) LumaCreate(c *gin.Context) {
return
}
if user.Power < h.App.SysConfig.LumaPower {
if user.Power < h.App.SysConfig.Base.LumaPower {
resp.ERROR(c, "您的算力不足,请充值后再试!")
return
}
@@ -95,14 +95,14 @@ func (h *VideoHandler) LumaCreate(c *gin.Context) {
Type: types.VideoLuma,
Prompt: data.Prompt,
Params: params,
TranslateModelId: h.App.SysConfig.AssistantModelId,
TranslateModelId: h.App.SysConfig.Base.AssistantModelId,
}
// 插入数据库
job := model.VideoJob{
UserId: uint(userId),
Type: types.VideoLuma,
Prompt: data.Prompt,
Power: h.App.SysConfig.LumaPower,
Power: h.App.SysConfig.Base.LumaPower,
TaskInfo: utils.JsonEncode(task),
}
tx := h.DB.Create(&job)
@@ -157,7 +157,7 @@ func (h *VideoHandler) KeLingCreate(c *gin.Context) {
// 计算当前任务所需算力
key := fmt.Sprintf("%s_%s_%s", data.Model, data.Mode, data.Duration)
power := h.App.SysConfig.KeLingPowers[key]
power := h.App.SysConfig.Base.KeLingPowers[key]
if power == 0 {
resp.ERROR(c, "当前模型暂不支持")
return
@@ -191,7 +191,7 @@ func (h *VideoHandler) KeLingCreate(c *gin.Context) {
Type: types.VideoKeLing,
Prompt: data.Prompt,
Params: params,
TranslateModelId: h.App.SysConfig.AssistantModelId,
TranslateModelId: h.App.SysConfig.Base.AssistantModelId,
Channel: data.Channel,
}
// 插入数据库