🎨 新增支付动态配置&优化支付回调&新增三方支付
This commit is contained in:
@@ -5,6 +5,8 @@ import (
|
||||
"git.echol.cn/loser/lckt/model/app"
|
||||
"git.echol.cn/loser/lckt/model/app/request"
|
||||
r "git.echol.cn/loser/lckt/model/common/response"
|
||||
"git.echol.cn/loser/lckt/model/system"
|
||||
"git.echol.cn/loser/lckt/utils/pay"
|
||||
"git.echol.cn/loser/lckt/utils/user_jwt"
|
||||
"git.echol.cn/loser/lckt/utils/wechat"
|
||||
"github.com/gin-gonic/gin"
|
||||
@@ -13,6 +15,57 @@ import (
|
||||
|
||||
type OrderApi struct{}
|
||||
|
||||
// GetPayMethods 获取可用的支付方式列表(用户端)
|
||||
// @Summary 获取可用的支付方式列表
|
||||
// @Description 获取所有启用的支付配置,返回前端所需的mode字段
|
||||
// @Tags 订单
|
||||
// @Accept application/json
|
||||
// @Produce application/json
|
||||
// @Success 200 {object} r.Response{data=[]PayMethodVO} "获取成功"
|
||||
// @Router /app_order/pay_methods [get]
|
||||
func (o *OrderApi) GetPayMethods(c *gin.Context) {
|
||||
var payConfigs []system.PayConfig
|
||||
if err := global.GVA_DB.Where("enable = ?", true).
|
||||
Order("sort ASC").
|
||||
Find(&payConfigs).Error; err != nil {
|
||||
global.GVA_LOG.Error("获取支付方式列表失败", zap.Error(err))
|
||||
r.FailWithMessage("获取失败", c)
|
||||
return
|
||||
}
|
||||
|
||||
// 返回前端所需的支付方式信息
|
||||
type PayMethodVO struct {
|
||||
Name string `json:"name"` // 支付名称,如"神奇支付-主账号"
|
||||
Code string `json:"code"` // 支付配置编码,如"shenqi_main"
|
||||
Type string `json:"type"` // 支付类型: wechat/shenqi
|
||||
Modes []string `json:"modes"` // 可用的支付模式
|
||||
Remark string `json:"remark"` // 备注说明
|
||||
}
|
||||
|
||||
var methods []PayMethodVO
|
||||
for _, config := range payConfigs {
|
||||
// 使用 GetAvailableModes 方法获取实际启用的模式
|
||||
availableModes := config.GetAvailableModes()
|
||||
|
||||
// 如果没有可用模式,跳过该配置
|
||||
if len(availableModes) == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
method := PayMethodVO{
|
||||
Name: config.Name,
|
||||
Code: config.Code,
|
||||
Type: config.Type,
|
||||
Modes: availableModes,
|
||||
Remark: config.Remark,
|
||||
}
|
||||
|
||||
methods = append(methods, method)
|
||||
}
|
||||
|
||||
r.OkWithData(methods, c)
|
||||
}
|
||||
|
||||
// CreateOrder APP新建订单
|
||||
func (o *OrderApi) CreateOrder(c *gin.Context) {
|
||||
var p app.Order
|
||||
@@ -62,6 +115,83 @@ func (o *OrderApi) NotifyOrder(context *gin.Context) {
|
||||
r.OkWithMessage("微信支付回调处理成功", context)
|
||||
}
|
||||
|
||||
// ShenqiPayNotify 神奇支付回调通知
|
||||
// @Summary 神奇支付回调通知
|
||||
// @Description 处理神奇支付平台的支付结果通知
|
||||
// @Tags 订单
|
||||
// @Accept x-www-form-urlencoded
|
||||
// @Produce plain
|
||||
// @Param code path string false "支付配置编码"
|
||||
// @Success 200 {string} string "success"
|
||||
// @Failure 400 {string} string "fail"
|
||||
// @Router /app_order/shenqi/notify/{code} [get]
|
||||
func (o *OrderApi) ShenqiPayNotify(c *gin.Context) {
|
||||
// 获取支付配置编码
|
||||
payCode := c.Param("code")
|
||||
|
||||
var client *pay.Client
|
||||
var err error
|
||||
|
||||
if payCode != "" {
|
||||
// 从数据库获取配置
|
||||
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("code", payCode), zap.Error(err))
|
||||
c.String(400, "fail")
|
||||
return
|
||||
}
|
||||
|
||||
// 验证支付类型
|
||||
if config.Type != "shenqi" {
|
||||
global.GVA_LOG.Error("支付配置类型错误", zap.String("type", config.Type))
|
||||
c.String(400, "fail")
|
||||
return
|
||||
}
|
||||
|
||||
// 获取神奇支付配置
|
||||
shenqiConfig := config.GetShenqiConfig()
|
||||
|
||||
client, err = pay.NewClient(pay.Config{
|
||||
PID: shenqiConfig.PID,
|
||||
PrivateKey: shenqiConfig.PrivateKey,
|
||||
PlatformPubKey: shenqiConfig.PlatformPubKey,
|
||||
BaseURL: shenqiConfig.BaseURL,
|
||||
})
|
||||
} else {
|
||||
// 兼容旧配置:从配置文件读取
|
||||
if !global.GVA_CONFIG.ShenqiPay.Enable {
|
||||
global.GVA_LOG.Error("神奇支付未启用")
|
||||
c.String(400, "fail")
|
||||
return
|
||||
}
|
||||
|
||||
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))
|
||||
c.String(400, "fail")
|
||||
return
|
||||
}
|
||||
|
||||
// 创建回调处理器并处理通知
|
||||
handler := pay.NewNotifyHandler(client)
|
||||
_, err = handler.HandleNotify(c.Request.URL.Query())
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("神奇支付回调处理失败", zap.Error(err))
|
||||
c.String(400, "fail")
|
||||
return
|
||||
}
|
||||
|
||||
// 返回 success 告知支付平台处理成功
|
||||
c.String(200, "success")
|
||||
}
|
||||
|
||||
// GetOrderDetail 获取订单详情
|
||||
func (o *OrderApi) GetOrderDetail(context *gin.Context) {
|
||||
id := context.Param("id")
|
||||
|
||||
@@ -3,13 +3,14 @@ package app
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
common "git.echol.cn/loser/lckt/model/common/request"
|
||||
user2 "git.echol.cn/loser/lckt/model/user"
|
||||
"gorm.io/gorm"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
common "git.echol.cn/loser/lckt/model/common/request"
|
||||
user2 "git.echol.cn/loser/lckt/model/user"
|
||||
"gorm.io/gorm"
|
||||
|
||||
"git.echol.cn/loser/lckt/global"
|
||||
"git.echol.cn/loser/lckt/model/app"
|
||||
r "git.echol.cn/loser/lckt/model/common/response"
|
||||
@@ -269,19 +270,6 @@ func (*AppUserApi) PwdLogin(ctx *gin.Context) {
|
||||
}
|
||||
}()
|
||||
|
||||
adcodes := utils.CheckIPInAdcodes(loginLog.Address)
|
||||
if !adcodes {
|
||||
global.GVA_LOG.Warn("异常登录地址", zap.String("address", loginLog.Address), zap.Uint("userId", user.ID))
|
||||
|
||||
user.Status = 0
|
||||
if err := global.GVA_DB.Save(&user).Error; err != nil {
|
||||
global.GVA_LOG.Error("禁用用户失败!", zap.Error(err))
|
||||
}
|
||||
|
||||
r.Banned("用户已被禁用", ctx)
|
||||
return
|
||||
}
|
||||
|
||||
// 生成token
|
||||
token, claims, err := user_jwt.LoginToken(user)
|
||||
if err != nil {
|
||||
|
||||
@@ -23,6 +23,7 @@ type ApiGroup struct {
|
||||
AutoCodeTemplateApi
|
||||
SysParamsApi
|
||||
SysVersionApi
|
||||
PayConfigApi
|
||||
}
|
||||
|
||||
var (
|
||||
@@ -46,4 +47,5 @@ var (
|
||||
autoCodeHistoryService = service.ServiceGroupApp.SystemServiceGroup.AutoCodeHistory
|
||||
autoCodeTemplateService = service.ServiceGroupApp.SystemServiceGroup.AutoCodeTemplate
|
||||
sysVersionService = service.ServiceGroupApp.SystemServiceGroup.SysVersionService
|
||||
payConfigService = service.ServiceGroupApp.SystemServiceGroup.PayConfigService
|
||||
)
|
||||
|
||||
204
api/v1/system/sys_pay_config.go
Normal file
204
api/v1/system/sys_pay_config.go
Normal file
@@ -0,0 +1,204 @@
|
||||
package system
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
|
||||
"git.echol.cn/loser/lckt/global"
|
||||
"git.echol.cn/loser/lckt/model/common/response"
|
||||
"git.echol.cn/loser/lckt/model/system/request"
|
||||
"github.com/gin-gonic/gin"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
type PayConfigApi struct{}
|
||||
|
||||
// GetPayConfigList 获取支付配置列表
|
||||
// @Tags PayConfig
|
||||
// @Summary 获取支付配置列表
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data query request.PayConfigSearch true "分页获取支付配置列表"
|
||||
// @Success 200 {object} response.Response{data=response.PageResult,msg=string} "获取成功"
|
||||
// @Router /payConfig/list [get]
|
||||
func (p *PayConfigApi) GetPayConfigList(c *gin.Context) {
|
||||
var req request.PayConfigSearch
|
||||
if err := c.ShouldBindQuery(&req); err != nil {
|
||||
response.FailWithMessage("参数错误: "+err.Error(), c)
|
||||
return
|
||||
}
|
||||
|
||||
// 处理 enable 参数:如果参数不存在或为空字符串,设置为 nil(表示不筛选)
|
||||
enableParam := c.Query("enable")
|
||||
if enableParam == "" {
|
||||
req.Enable = nil
|
||||
}
|
||||
|
||||
if req.Page == 0 {
|
||||
req.Page = 1
|
||||
}
|
||||
if req.PageSize == 0 {
|
||||
req.PageSize = 10
|
||||
}
|
||||
|
||||
list, total, err := payConfigService.GetPayConfigList(req)
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("获取支付配置列表失败", zap.Error(err))
|
||||
response.FailWithMessage("获取失败: "+err.Error(), c)
|
||||
return
|
||||
}
|
||||
|
||||
response.OkWithDetailed(response.PageResult{
|
||||
List: list,
|
||||
Total: total,
|
||||
Page: req.Page,
|
||||
PageSize: req.PageSize,
|
||||
}, "获取成功", c)
|
||||
}
|
||||
|
||||
// GetPayConfigByID 根据ID获取支付配置
|
||||
// @Tags PayConfig
|
||||
// @Summary 根据ID获取支付配置
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param id path int true "支付配置ID"
|
||||
// @Success 200 {object} response.Response{data=system.PayConfig,msg=string} "获取成功"
|
||||
// @Router /payConfig/{id} [get]
|
||||
func (p *PayConfigApi) GetPayConfigByID(c *gin.Context) {
|
||||
idStr := c.Param("id")
|
||||
id, err := strconv.ParseUint(idStr, 10, 64)
|
||||
if err != nil {
|
||||
response.FailWithMessage("参数错误", c)
|
||||
return
|
||||
}
|
||||
|
||||
config, err := payConfigService.GetPayConfigByID(uint(id))
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("获取支付配置失败", zap.Error(err))
|
||||
response.FailWithMessage("获取失败: "+err.Error(), c)
|
||||
return
|
||||
}
|
||||
|
||||
response.OkWithData(config, c)
|
||||
}
|
||||
|
||||
// GetEnabledPayConfigs 获取启用的支付配置列表
|
||||
// @Tags PayConfig
|
||||
// @Summary 获取启用的支付配置列表
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Success 200 {object} response.Response{data=[]system.PayConfig,msg=string} "获取成功"
|
||||
// @Router /payConfig/enabled [get]
|
||||
func (p *PayConfigApi) GetEnabledPayConfigs(c *gin.Context) {
|
||||
list, err := payConfigService.GetEnabledPayConfigs()
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("获取启用的支付配置失败", zap.Error(err))
|
||||
response.FailWithMessage("获取失败: "+err.Error(), c)
|
||||
return
|
||||
}
|
||||
|
||||
response.OkWithData(list, c)
|
||||
}
|
||||
|
||||
// CreatePayConfig 创建支付配置
|
||||
// @Tags PayConfig
|
||||
// @Summary 创建支付配置
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body request.PayConfigCreate true "创建支付配置"
|
||||
// @Success 200 {object} response.Response{msg=string} "创建成功"
|
||||
// @Router /payConfig [post]
|
||||
func (p *PayConfigApi) CreatePayConfig(c *gin.Context) {
|
||||
var req request.PayConfigCreate
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
response.FailWithMessage("参数错误: "+err.Error(), c)
|
||||
return
|
||||
}
|
||||
|
||||
if err := payConfigService.CreatePayConfig(req); err != nil {
|
||||
global.GVA_LOG.Error("创建支付配置失败", zap.Error(err))
|
||||
response.FailWithMessage("创建失败: "+err.Error(), c)
|
||||
return
|
||||
}
|
||||
|
||||
response.OkWithMessage("创建成功", c)
|
||||
}
|
||||
|
||||
// UpdatePayConfig 更新支付配置
|
||||
// @Tags PayConfig
|
||||
// @Summary 更新支付配置
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body request.PayConfigUpdate true "更新支付配置"
|
||||
// @Success 200 {object} response.Response{msg=string} "更新成功"
|
||||
// @Router /payConfig [put]
|
||||
func (p *PayConfigApi) UpdatePayConfig(c *gin.Context) {
|
||||
var req request.PayConfigUpdate
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
response.FailWithMessage("参数错误: "+err.Error(), c)
|
||||
return
|
||||
}
|
||||
|
||||
if err := payConfigService.UpdatePayConfig(req); err != nil {
|
||||
global.GVA_LOG.Error("更新支付配置失败", zap.Error(err))
|
||||
response.FailWithMessage("更新失败: "+err.Error(), c)
|
||||
return
|
||||
}
|
||||
|
||||
response.OkWithMessage("更新成功", c)
|
||||
}
|
||||
|
||||
// DeletePayConfig 删除支付配置
|
||||
// @Tags PayConfig
|
||||
// @Summary 删除支付配置
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param id path int true "支付配置ID"
|
||||
// @Success 200 {object} response.Response{msg=string} "删除成功"
|
||||
// @Router /payConfig/{id} [delete]
|
||||
func (p *PayConfigApi) DeletePayConfig(c *gin.Context) {
|
||||
idStr := c.Param("id")
|
||||
id, err := strconv.ParseUint(idStr, 10, 64)
|
||||
if err != nil {
|
||||
response.FailWithMessage("参数错误", c)
|
||||
return
|
||||
}
|
||||
|
||||
if err := payConfigService.DeletePayConfig(uint(id)); err != nil {
|
||||
global.GVA_LOG.Error("删除支付配置失败", zap.Error(err))
|
||||
response.FailWithMessage("删除失败: "+err.Error(), c)
|
||||
return
|
||||
}
|
||||
|
||||
response.OkWithMessage("删除成功", c)
|
||||
}
|
||||
|
||||
// TogglePayConfig 切换支付配置状态
|
||||
// @Tags PayConfig
|
||||
// @Summary 切换支付配置状态
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body request.PayConfigToggle true "切换状态"
|
||||
// @Success 200 {object} response.Response{msg=string} "操作成功"
|
||||
// @Router /payConfig/toggle [post]
|
||||
func (p *PayConfigApi) TogglePayConfig(c *gin.Context) {
|
||||
var req request.PayConfigToggle
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
response.FailWithMessage("参数错误: "+err.Error(), c)
|
||||
return
|
||||
}
|
||||
|
||||
if err := payConfigService.TogglePayConfig(req); err != nil {
|
||||
global.GVA_LOG.Error("切换支付配置状态失败", zap.Error(err))
|
||||
response.FailWithMessage("操作失败: "+err.Error(), c)
|
||||
return
|
||||
}
|
||||
|
||||
response.OkWithMessage("操作成功", c)
|
||||
}
|
||||
Reference in New Issue
Block a user