diff --git a/api/core/types/config.go b/api/core/types/config.go
index dda50c00..fa713e7e 100644
--- a/api/core/types/config.go
+++ b/api/core/types/config.go
@@ -57,7 +57,8 @@ type AlipayConfig struct {
PublicKey string // 用户公钥文件路径
AlipayPublicKey string // 支付宝公钥文件路径
RootCert string // Root 秘钥路径
- NotifyHost string // 通知回调地址
+ NotifyURL string // 异步通知地址
+ ReturnURL string // 同步回调地址
}
type WechatPayConfig struct {
@@ -67,16 +68,18 @@ type WechatPayConfig struct {
SerialNo string // 商户证书的证书序列号
PrivateKey string // 用户私钥文件路径
ApiV3Key string // API V3 秘钥
- NotifyHost string // 通知回调地址
+ NotifyURL string // 异步通知地址
+ ReturnURL string // 同步回调地址
}
type HuPiPayConfig struct { //虎皮椒第四方支付配置
- Enabled bool // 是否启用该支付通道
- Name string // 支付名称,如:wechat/alipay
- AppId string // App ID
- AppSecret string // app 密钥
- ApiURL string // 支付网关
- NotifyHost string // 通知回调地址
+ Enabled bool // 是否启用该支付通道
+ Name string // 支付名称,如:wechat/alipay
+ AppId string // App ID
+ AppSecret string // app 密钥
+ ApiURL string // 支付网关
+ NotifyURL string // 异步通知地址
+ ReturnURL string // 同步回调地址
}
// GeekPayConfig GEEK支付配置
@@ -85,7 +88,8 @@ type GeekPayConfig struct {
AppId string // 商户 ID
PrivateKey string // 私钥
ApiURL string // API 网关
- NotifyHost string // 通知回调地址
+ NotifyURL string // 异步通知地址
+ ReturnURL string // 同步回调地址
}
type XXLConfig struct { // XXL 任务调度配置
diff --git a/api/handler/payment_handler.go b/api/handler/payment_handler.go
index 0fba56b4..3dd3108c 100644
--- a/api/handler/payment_handler.go
+++ b/api/handler/payment_handler.go
@@ -39,6 +39,7 @@ type PaymentHandler struct {
geekPayService *payment.GeekPayService
wechatPayService *payment.WechatPayService
snowflake *service.Snowflake
+ userService *service.UserService
fs embed.FS
lock sync.Mutex
signKey string // 用来签名的随机秘钥
@@ -51,6 +52,7 @@ func NewPaymentHandler(
geekPayService *payment.GeekPayService,
wechatPayService *payment.WechatPayService,
db *gorm.DB,
+ userService *service.UserService,
snowflake *service.Snowflake,
fs embed.FS) *PaymentHandler {
return &PaymentHandler{
@@ -59,6 +61,7 @@ func NewPaymentHandler(
geekPayService: geekPayService,
wechatPayService: wechatPayService,
snowflake: snowflake,
+ userService: userService,
fs: fs,
lock: sync.Mutex{},
BaseHandler: BaseHandler{
@@ -72,12 +75,12 @@ func NewPaymentHandler(
func (h *PaymentHandler) Pay(c *gin.Context) {
payWay := c.Query("pay_way")
payType := c.Query("pay_type")
- productId := c.Query("pid")
+ productId := c.Query("product_id")
device := c.Query("device")
userId := c.Query("user_id")
var product model.Product
- err := h.DB.First(&product, productId).Error
+ err := h.DB.Debug().Where("id", productId).First(&product).Error
if err != nil {
resp.ERROR(c, "Product not found")
return
@@ -126,23 +129,20 @@ func (h *PaymentHandler) Pay(c *gin.Context) {
var payURL string
if payWay == "alipay" { // 支付宝
money := fmt.Sprintf("%.2f", order.Amount)
- notifyURL := fmt.Sprintf("%s/api/payment/notify/alipay", h.App.Config.AlipayConfig.NotifyHost)
- returnURL := fmt.Sprintf("%s/member", h.App.Config.AlipayConfig.NotifyHost)
if device == "mobile" {
payURL, err = h.alipayService.PayMobile(payment.AlipayParams{
OutTradeNo: orderNo,
Subject: product.Name,
TotalFee: money,
- ReturnURL: returnURL,
- NotifyURL: notifyURL,
+ NotifyURL: h.App.Config.AlipayConfig.NotifyURL,
})
} else {
payURL, err = h.alipayService.PayPC(payment.AlipayParams{
OutTradeNo: orderNo,
Subject: product.Name,
TotalFee: money,
- ReturnURL: returnURL,
- NotifyURL: notifyURL,
+ ReturnURL: h.App.Config.AlipayConfig.ReturnURL,
+ NotifyURL: h.App.Config.AlipayConfig.NotifyURL,
})
}
if err != nil {
@@ -155,7 +155,8 @@ func (h *PaymentHandler) Pay(c *gin.Context) {
TradeOrderId: orderNo,
TotalFee: fmt.Sprintf("%f", order.Amount),
Title: order.Subject,
- NotifyURL: fmt.Sprintf("%s/api/payment/notify/hupi", h.App.Config.HuPiPayConfig.NotifyHost),
+ NotifyURL: h.App.Config.HuPiPayConfig.NotifyURL,
+ ReturnURL: h.App.Config.HuPiPayConfig.ReturnURL,
WapName: "GeekAI助手",
}
r, err := h.huPiPayService.Pay(params)
@@ -175,8 +176,6 @@ func (h *PaymentHandler) Pay(c *gin.Context) {
c.Redirect(302, uri)
} else if order.PayWay == "geek" {
- notifyURL := fmt.Sprintf("%s/api/payment/notify/geek", h.App.Config.GeekPayConfig.NotifyHost)
- returnURL := fmt.Sprintf("%s/member", h.App.Config.GeekPayConfig.NotifyHost)
params := payment.GeekPayParams{
OutTradeNo: orderNo,
Method: "web",
@@ -185,8 +184,8 @@ func (h *PaymentHandler) Pay(c *gin.Context) {
ClientIP: c.ClientIP(),
Device: device,
Type: payType,
- ReturnURL: returnURL,
- NotifyURL: notifyURL,
+ ReturnURL: h.App.Config.GeekPayConfig.ReturnURL,
+ NotifyURL: h.App.Config.GeekPayConfig.NotifyURL,
}
res, err := h.geekPayService.Pay(params)
@@ -218,45 +217,26 @@ func (h *PaymentHandler) notify(orderNo string, tradeNo string) error {
}
var user model.User
- res = h.DB.First(&user, order.UserId)
- if res.Error != nil {
- err := fmt.Errorf("error with fetch user info: %v", res.Error)
- logger.Error(err)
- return err
+ err := h.DB.First(&user, order.UserId).Error
+ if err != nil {
+ return fmt.Errorf("error with fetch user info: %v", res.Error)
}
var remark types.OrderRemark
- err := utils.JsonDecode(order.Remark, &remark)
+ err = utils.JsonDecode(order.Remark, &remark)
if err != nil {
err := fmt.Errorf("error with decode order remark: %v", err)
logger.Error(err)
return err
}
- var opt string
- var power int
- if remark.Days > 0 { // VIP 充值
- if user.ExpiredTime >= time.Now().Unix() {
- user.ExpiredTime = time.Unix(user.ExpiredTime, 0).AddDate(0, 0, remark.Days).Unix()
- opt = "VIP充值,VIP 没到期,只延期不增加算力"
- } else {
- user.ExpiredTime = time.Now().AddDate(0, 0, remark.Days).Unix()
- user.Power += h.App.SysConfig.VipMonthPower
- power = h.App.SysConfig.VipMonthPower
- opt = "VIP充值"
- }
- user.Vip = true
- } else { // 充值点卡,直接增加次数即可
- user.Power += remark.Power
- opt = "点卡充值"
- power = remark.Power
- }
-
- // 更新用户信息
- res = h.DB.Updates(&user)
- if res.Error != nil {
- err := fmt.Errorf("error with update user info: %v", res.Error)
- logger.Error(err)
+ // 增加用户算力
+ err = h.userService.IncreasePower(int(order.UserId), remark.Power, model.PowerLog{
+ Type: types.PowerRecharge,
+ Model: order.PayWay,
+ Remark: fmt.Sprintf("充值算力,金额:%f,订单号:%s", order.Amount, order.OrderNo),
+ })
+ if err != nil {
return err
}
@@ -264,29 +244,16 @@ func (h *PaymentHandler) notify(orderNo string, tradeNo string) error {
order.PayTime = time.Now().Unix()
order.Status = types.OrderPaidSuccess
order.TradeNo = tradeNo
- res = h.DB.Updates(&order)
- if res.Error != nil {
- err := fmt.Errorf("error with update order info: %v", res.Error)
- logger.Error(err)
- return err
+ err = h.DB.Updates(&order).Error
+ if err != nil {
+ return fmt.Errorf("error with update order info: %v", err)
}
// 更新产品销量
- h.DB.Model(&model.Product{}).Where("id = ?", order.ProductId).UpdateColumn("sales", gorm.Expr("sales + ?", 1))
-
- // 记录算力充值日志
- if power > 0 {
- h.DB.Create(&model.PowerLog{
- UserId: user.Id,
- Username: user.Username,
- Type: types.PowerRecharge,
- Amount: power,
- Balance: user.Power,
- Mark: types.PowerAdd,
- Model: order.PayWay,
- Remark: fmt.Sprintf("%s,金额:%f,订单号:%s", opt, order.Amount, order.OrderNo),
- CreatedAt: time.Now(),
- })
+ err = h.DB.Model(&model.Product{}).Where("id = ?", order.ProductId).
+ UpdateColumn("sales", gorm.Expr("sales + ?", 1)).Error
+ if err != nil {
+ return fmt.Errorf("error with update product sales: %v", err)
}
return nil
diff --git a/web/src/router.js b/web/src/router.js
index e1ca5cd6..c805856b 100644
--- a/web/src/router.js
+++ b/web/src/router.js
@@ -139,9 +139,15 @@ const routes = [
{
path: '/admin/login',
name: 'admin-login',
- meta: {title: 'Geek-AI 控制台登录'},
+ meta: {title: '控制台登录'},
component: () => import('@/views/admin/Login.vue'),
},
+ {
+ path: '/payReturn',
+ name: 'pay-return',
+ meta: {title: '支付回调'},
+ component: () => import('@/views/PayReturn.vue'),
+ },
{
name: 'admin',
path: '/admin',
diff --git a/web/src/views/Member.vue b/web/src/views/Member.vue
index c64d6f86..6b5bbda9 100644
--- a/web/src/views/Member.vue
+++ b/web/src/views/Member.vue
@@ -106,6 +106,12 @@
+
+
+ 支付成功
+ 支付失败
+
+
@@ -143,6 +149,7 @@ const payWays = ref([])
const vipInfoText = ref("")
const store = useSharedStore()
const profileKey = ref(0)
+const showDialog = ref(false)
onMounted(() => {
@@ -193,8 +200,9 @@ const pay = (product, payWay) => {
user_id: user.value.id,
device: "jump"
}).then(res => {
- window.open(res.data, '_blank');
+ window.open(res.data, '_blank');
loading.value = false
+ showDialog.value = true
}).catch(e => {
setTimeout(() => {
ElMessage.error("生成支付订单失败:" + e.message)
@@ -210,6 +218,13 @@ const redeemCallback = (success) => {
}
}
+const payCallback = (success) => {
+ showDialog.value = false
+ if (success) {
+ profileKey.value += 1
+ }
+}
+