🎨 新增支付动态配置&优化支付回调&新增三方支付
This commit is contained in:
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user