🎨 新增支付动态配置&优化支付回调&新增三方支付

This commit is contained in:
2025-12-09 21:47:22 +08:00
parent eaa5cdc100
commit 854c16e11c
26 changed files with 2963 additions and 72 deletions

View File

@@ -2,7 +2,6 @@ package app
import (
"fmt"
"git.echol.cn/loser/lckt/model/vip"
"strconv"
"strings"
"time"
@@ -10,7 +9,11 @@ import (
"git.echol.cn/loser/lckt/global"
"git.echol.cn/loser/lckt/model/app"
"git.echol.cn/loser/lckt/model/app/request"
"git.echol.cn/loser/lckt/model/system"
userM "git.echol.cn/loser/lckt/model/user"
"git.echol.cn/loser/lckt/model/vip"
"git.echol.cn/loser/lckt/utils/pay"
payReq "git.echol.cn/loser/lckt/utils/pay/request"
"git.echol.cn/loser/lckt/utils/wechat"
"github.com/gin-gonic/gin"
"go.uber.org/zap"
@@ -32,23 +35,204 @@ func (s *OrderService) Pay(p request.PayReq, ctx *gin.Context) (interface{}, err
return "", fmt.Errorf("订单已过期")
}
if p.Mode == "h5" {
payConf, err := wechat.H5Pay(&order, ctx)
if err != nil {
global.GVA_LOG.Error("微信支付订单失败", zap.Error(err))
return "", err
}
return payConf, nil
} else if p.Mode == "jsapi" {
payConf, err := wechat.JSAPIPay(&order, ctx)
if err != nil {
global.GVA_LOG.Error("微信支付订单失败", zap.Error(err))
return "", err
}
return payConf, nil
if order.Status == 2 {
global.GVA_LOG.Error("订单已支付", zap.Int64("order_id", int64(order.ID)))
return "", fmt.Errorf("订单已支付")
}
return "", nil
// 如果指定了支付编码,优先使用数据库配置
if p.PayCode != "" {
return s.payByCode(&order, p.PayCode, p.Mode, ctx)
}
// 兼容旧的支付方式
switch p.Mode {
case "h5":
payConf, err := wechat.H5Pay(&order, ctx)
if err != nil {
global.GVA_LOG.Error("微信H5支付失败", zap.Error(err))
return "", err
}
return payConf, nil
case "jsapi":
payConf, err := wechat.JSAPIPay(&order, ctx)
if err != nil {
global.GVA_LOG.Error("微信JSAPI支付失败", zap.Error(err))
return "", err
}
return payConf, nil
case "shenqi", "shenqi_alipay", "shenqi_wxpay":
// 兼容旧配置:从配置文件读取
return s.shenqiPayFromConfig(&order, p.Mode, ctx)
default:
return "", fmt.Errorf("不支持的支付方式: %s", p.Mode)
}
}
// payByCode 根据支付编码发起支付
func (s *OrderService) payByCode(order *app.Order, payCode, mode string, ctx *gin.Context) (interface{}, error) {
// 获取支付配置
var config system.PayConfig
if err := global.GVA_DB.Where("code = ? AND enable = ?", payCode, true).First(&config).Error; err != nil {
global.GVA_LOG.Error("获取支付配置失败", zap.String("pay_code", payCode), zap.Error(err))
return "", fmt.Errorf("支付配置不存在或未启用")
}
// 根据支付类型调用不同的支付方法
switch config.Type {
case "shenqi":
return s.shenqiPay(order, payCode, mode, ctx)
case "wechat":
// TODO: 实现微信支付从数据库配置
return "", fmt.Errorf("微信支付数据库配置暂未实现")
case "alipay":
// TODO: 实现支付宝支付
return "", fmt.Errorf("支付宝支付暂未实现")
default:
return "", fmt.Errorf("不支持的支付类型: %s", config.Type)
}
}
// shenqiPayFromConfig 从配置文件读取神奇支付配置(兼容旧逻辑)
func (s *OrderService) shenqiPayFromConfig(order *app.Order, mode string, ctx *gin.Context) (interface{}, error) {
// 检查神奇支付是否启用
if !global.GVA_CONFIG.ShenqiPay.Enable {
return "", fmt.Errorf("神奇支付未启用")
}
// 创建客户端
client, err := pay.NewClient(pay.Config{
PID: global.GVA_CONFIG.ShenqiPay.PID,
PrivateKey: global.GVA_CONFIG.ShenqiPay.PrivateKey,
PlatformPubKey: global.GVA_CONFIG.ShenqiPay.PlatformPubKey,
BaseURL: global.GVA_CONFIG.ShenqiPay.BaseURL,
})
if err != nil {
global.GVA_LOG.Error("创建神奇支付客户端失败", zap.Error(err))
return "", fmt.Errorf("支付初始化失败: %v", err)
}
// 确定支付方式
payType := pay.PayTypeAlipay
if mode == "shenqi_wxpay" {
payType = pay.PayTypeWxpay
}
// 金额转换 (数据库存储的是分,神奇支付需要元)
money := fmt.Sprintf("%.2f", float64(order.Price)/100.0)
// 创建订单
resp, err := client.CreateOrder(&payReq.CreateOrder{
Method: pay.MethodWeb,
Device: pay.DeviceMobile,
Type: payType,
OutTradeNo: order.OrderNo,
NotifyURL: global.GVA_CONFIG.ShenqiPay.NotifyURL,
ReturnURL: global.GVA_CONFIG.ShenqiPay.ReturnURL,
Name: order.Name,
Money: money,
ClientIP: ctx.ClientIP(),
Param: fmt.Sprintf("order_id=%d", order.ID),
})
if err != nil {
global.GVA_LOG.Error("神奇支付下单失败", zap.Error(err))
return "", fmt.Errorf("支付下单失败: %v", err)
}
if !resp.IsSuccess() {
global.GVA_LOG.Error("神奇支付下单失败", zap.String("msg", resp.Msg))
return "", fmt.Errorf("支付下单失败: %s", resp.Msg)
}
global.GVA_LOG.Info("神奇支付下单成功",
zap.String("order_no", order.OrderNo),
zap.String("trade_no", resp.TradeNo),
zap.String("pay_type", resp.PayType))
// 返回支付信息
return map[string]interface{}{
"trade_no": resp.TradeNo,
"pay_type": resp.PayType,
"pay_info": resp.PayInfo,
}, nil
}
// shenqiPay 神奇支付
// payCode: 支付配置编码,用于从数据库获取配置
// mode: 支付模式,如 alipay, wxpay
func (s *OrderService) shenqiPay(order *app.Order, payCode, mode string, ctx *gin.Context) (interface{}, error) {
// 从数据库获取支付配置
var config system.PayConfig
if err := global.GVA_DB.Where("code = ? AND enable = ?", payCode, true).First(&config).Error; err != nil {
global.GVA_LOG.Error("获取神奇支付配置失败", zap.String("pay_code", payCode), zap.Error(err))
return "", fmt.Errorf("支付配置不存在或未启用")
}
// 验证是否是神奇支付类型
if config.Type != "shenqi" {
return "", fmt.Errorf("该配置不是神奇支付类型")
}
// 获取神奇支付配置
shenqiConfig := config.GetShenqiConfig()
// 创建客户端
client, err := pay.NewClient(pay.Config{
PID: shenqiConfig.PID,
PrivateKey: shenqiConfig.PrivateKey,
PlatformPubKey: shenqiConfig.PlatformPubKey,
BaseURL: shenqiConfig.BaseURL,
})
if err != nil {
global.GVA_LOG.Error("创建神奇支付客户端失败", zap.Error(err))
return "", fmt.Errorf("支付初始化失败: %v", err)
}
// 确定支付方式
payType := pay.PayTypeAlipay
if mode == "wxpay" || strings.HasSuffix(mode, "_wxpay") {
payType = pay.PayTypeWxpay
}
// 金额转换 (数据库存储的是分,神奇支付需要元)
money := fmt.Sprintf("%.2f", float64(order.Price)/100.0)
// 创建订单
resp, err := client.CreateOrder(&payReq.CreateOrder{
Method: pay.MethodWeb,
Device: pay.DeviceMobile,
Type: payType,
OutTradeNo: order.OrderNo,
NotifyURL: shenqiConfig.NotifyURL,
ReturnURL: shenqiConfig.ReturnURL,
Name: order.Name,
Money: money,
ClientIP: ctx.ClientIP(),
Param: fmt.Sprintf("order_id=%d&pay_code=%s", order.ID, payCode),
})
if err != nil {
global.GVA_LOG.Error("神奇支付下单失败", zap.Error(err))
return "", fmt.Errorf("支付下单失败: %v", err)
}
if !resp.IsSuccess() {
global.GVA_LOG.Error("神奇支付下单失败", zap.String("msg", resp.Msg))
return "", fmt.Errorf("支付下单失败: %s", resp.Msg)
}
global.GVA_LOG.Info("神奇支付下单成功",
zap.String("order_no", order.OrderNo),
zap.String("trade_no", resp.TradeNo),
zap.String("pay_type", resp.PayType))
// 返回支付信息
return map[string]interface{}{
"trade_no": resp.TradeNo,
"pay_type": resp.PayType,
"pay_info": resp.PayInfo,
}, nil
}
func (s *OrderService) Create(o *app.Order) (*app.Order, error) {