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

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

@@ -0,0 +1,96 @@
package request
import (
"fmt"
"git.echol.cn/loser/lckt/model/common/request"
)
// PayConfigSearch 支付配置搜索请求
type PayConfigSearch struct {
request.PageInfo
Name string `json:"name" form:"name"` // 支付名称
Code string `json:"code" form:"code"` // 支付编码
Type string `json:"type" form:"type"` // 支付类型
Enable *bool `json:"enable" form:"enable"` // 是否启用
}
// PayConfigCreate 创建支付配置请求
type PayConfigCreate struct {
Name string `json:"name" binding:"required"` // 支付名称
Code string `json:"code" binding:"required"` // 支付编码
Type string `json:"type" binding:"required"` // 支付类型: wechat/shenqi
Enable bool `json:"enable"` // 是否启用
EnabledModes []string `json:"enabledModes"` // 启用的支付模式,如 ["h5","jsapi"] 或 ["alipay","wxpay"]
Sort int `json:"sort"` // 排序
Remark string `json:"remark"` // 备注
// ========== 微信支付配置 ==========
WechatAppID string `json:"wechatAppId"` // 微信AppID
WechatMchID string `json:"wechatMchId"` // 微信商户号
WechatMchApiV3Key string `json:"wechatMchApiV3Key"` // 微信API V3密钥
WechatPrivateKey string `json:"wechatPrivateKey"` // 微信商户私钥
WechatSerialNo string `json:"wechatSerialNo"` // 微信证书序列号
WechatNotifyURL string `json:"wechatNotifyUrl"` // 微信回调地址
// ========== 神奇支付配置 ==========
ShenqiPID int `json:"shenqiPid"` // 神奇支付商户ID
ShenqiPrivateKey string `json:"shenqiPrivateKey"` // 神奇支付商户私钥
ShenqiPlatformPubKey string `json:"shenqiPlatformPubKey"` // 神奇支付平台公钥
ShenqiNotifyURL string `json:"shenqiNotifyUrl"` // 神奇支付回调地址
ShenqiReturnURL string `json:"shenqiReturnUrl"` // 神奇支付同步跳转地址
ShenqiBaseURL string `json:"shenqiBaseUrl"` // 神奇支付API地址
}
// PayConfigUpdate 更新支付配置请求
type PayConfigUpdate struct {
ID uint `json:"id" binding:"required"` // ID
Name string `json:"name"` // 支付名称
Code string `json:"code"` // 支付编码
Type string `json:"type"` // 支付类型
Enable *bool `json:"enable"` // 是否启用
EnabledModes *[]string `json:"enabledModes"` // 启用的支付模式(使用指针来区分不传和传空数组)
Sort *int `json:"sort"` // 排序
Remark string `json:"remark"` // 备注
// ========== 微信支付配置 ==========
WechatAppID *string `json:"wechatAppId"` // 微信AppID
WechatMchID *string `json:"wechatMchId"` // 微信商户号
WechatMchApiV3Key *string `json:"wechatMchApiV3Key"` // 微信API V3密钥
WechatPrivateKey *string `json:"wechatPrivateKey"` // 微信商户私钥
WechatSerialNo *string `json:"wechatSerialNo"` // 微信证书序列号
WechatNotifyURL *string `json:"wechatNotifyUrl"` // 微信回调地址
// ========== 神奇支付配置 ==========
ShenqiPID *int `json:"shenqiPid"` // 神奇支付商户ID
ShenqiPrivateKey *string `json:"shenqiPrivateKey"` // 神奇支付商户私钥
ShenqiPlatformPubKey *string `json:"shenqiPlatformPubKey"` // 神奇支付平台公钥
ShenqiNotifyURL *string `json:"shenqiNotifyUrl"` // 神奇支付回调地址
ShenqiReturnURL *string `json:"shenqiReturnUrl"` // 神奇支付同步跳转地址
ShenqiBaseURL *string `json:"shenqiBaseUrl"` // 神奇支付API地址
}
// PayConfigToggle 切换支付状态请求
type PayConfigToggle struct {
ID uint `json:"id" binding:"required"` // ID
Enable bool `json:"enable"` // 是否启用
}
// Validate 验证创建请求
func (req *PayConfigCreate) Validate() error {
switch req.Type {
case "wechat":
if req.WechatAppID == "" || req.WechatMchID == "" || req.WechatMchApiV3Key == "" ||
req.WechatPrivateKey == "" || req.WechatSerialNo == "" || req.WechatNotifyURL == "" {
return fmt.Errorf("微信支付配置不完整")
}
case "shenqi":
if req.ShenqiPID == 0 || req.ShenqiPrivateKey == "" || req.ShenqiPlatformPubKey == "" ||
req.ShenqiNotifyURL == "" || req.ShenqiReturnURL == "" {
return fmt.Errorf("神奇支付配置不完整")
}
default:
return fmt.Errorf("不支持的支付类型: %s", req.Type)
}
return nil
}

View File

@@ -0,0 +1,161 @@
package system
import (
"database/sql/driver"
"encoding/json"
"git.echol.cn/loser/lckt/global"
)
// StringArray 字符串数组类型用于存储JSON数组
type StringArray []string
// Scan 实现 sql.Scanner 接口
func (s *StringArray) Scan(value interface{}) error {
if value == nil {
*s = nil
return nil
}
bytes, ok := value.([]byte)
if !ok {
*s = nil
return nil
}
// 空字符串或 "null" 视为 nil
if len(bytes) == 0 || string(bytes) == "null" {
*s = nil
return nil
}
return json.Unmarshal(bytes, s)
}
// Value 实现 driver.Valuer 接口
func (s StringArray) Value() (driver.Value, error) {
// 如果是 nil slice返回 NULL
if s == nil {
return nil, nil
}
// 否则序列化为 JSON包括空数组 []
return json.Marshal(s)
}
// MarshalJSON 实现 json.Marshaler 接口
func (s StringArray) MarshalJSON() ([]byte, error) {
if s == nil {
return []byte("[]"), nil
}
return json.Marshal([]string(s))
}
// PayConfig 支付配置模型
type PayConfig struct {
global.GVA_MODEL
// Name 支付名称(用于显示)
Name string `gorm:"column:name;type:varchar(50);not null;comment:支付名称" json:"name"`
// Code 支付编码(唯一标识)
Code string `gorm:"column:code;type:varchar(50);not null;uniqueIndex;comment:支付编码" json:"code"`
// Type 支付类型: wechat微信支付, shenqi神奇支付
Type string `gorm:"column:type;type:varchar(20);not null;comment:支付类型" json:"type"`
// Enable 是否启用
Enable bool `gorm:"column:enable;default:false;comment:是否启用" json:"enable"`
// EnabledModes 启用的支付模式JSON数组如 ["h5","jsapi"] 或 ["alipay","wxpay"]
EnabledModes StringArray `gorm:"column:enabled_modes;type:json;comment:启用的支付模式" json:"enabledModes"`
// Sort 排序
Sort int `gorm:"column:sort;default:0;comment:排序" json:"sort"`
// Remark 备注
Remark string `gorm:"column:remark;type:varchar(255);comment:备注" json:"remark"`
// ========== 微信支付配置字段 ==========
WechatAppID string `gorm:"column:wechat_app_id;type:varchar(50);comment:微信AppID" json:"wechatAppId"`
WechatMchID string `gorm:"column:wechat_mch_id;type:varchar(50);comment:微信商户号" json:"wechatMchId"`
WechatMchApiV3Key string `gorm:"column:wechat_mch_api_v3_key;type:varchar(255);comment:微信APIV3密钥" json:"wechatMchApiV3Key"`
WechatPrivateKey string `gorm:"column:wechat_private_key;type:text;comment:微信商户私钥" json:"wechatPrivateKey"`
WechatSerialNo string `gorm:"column:wechat_serial_no;type:varchar(100);comment:微信证书序列号" json:"wechatSerialNo"`
WechatNotifyURL string `gorm:"column:wechat_notify_url;type:varchar(255);comment:微信回调地址" json:"wechatNotifyUrl"`
// ========== 神奇支付配置字段 ==========
ShenqiPID int `gorm:"column:shenqi_pid;comment:神奇支付商户ID" json:"shenqiPid"`
ShenqiPrivateKey string `gorm:"column:shenqi_private_key;type:text;comment:神奇支付商户私钥" json:"shenqiPrivateKey"`
ShenqiPlatformPubKey string `gorm:"column:shenqi_platform_pub_key;type:text;comment:神奇支付平台公钥" json:"shenqiPlatformPubKey"`
ShenqiNotifyURL string `gorm:"column:shenqi_notify_url;type:varchar(255);comment:神奇支付回调地址" json:"shenqiNotifyUrl"`
ShenqiReturnURL string `gorm:"column:shenqi_return_url;type:varchar(255);comment:神奇支付同步跳转地址" json:"shenqiReturnUrl"`
ShenqiBaseURL string `gorm:"column:shenqi_base_url;type:varchar(255);comment:神奇支付API地址" json:"shenqiBaseUrl"`
}
func (PayConfig) TableName() string {
return "sys_pay_config"
}
// GetAvailableModes 获取可用的支付模式
// 如果 EnabledModes 为空,返回该支付类型的所有默认模式
func (p *PayConfig) GetAvailableModes() []string {
// 如果已配置启用的模式,直接返回
if len(p.EnabledModes) > 0 {
return p.EnabledModes
}
// 否则返回默认的所有模式
switch p.Type {
case "wechat":
return []string{"h5", "jsapi"}
case "shenqi":
return []string{"alipay", "wxpay"}
default:
return []string{}
}
}
// IsModeEnabled 检查指定模式是否启用
func (p *PayConfig) IsModeEnabled(mode string) bool {
availableModes := p.GetAvailableModes()
for _, m := range availableModes {
if m == mode {
return true
}
}
return false
}
// GetWechatConfig 获取微信支付配置
func (p *PayConfig) GetWechatConfig() *WechatPayConfig {
return &WechatPayConfig{
AppID: p.WechatAppID,
MchID: p.WechatMchID,
MchApiV3Key: p.WechatMchApiV3Key,
PrivateKey: p.WechatPrivateKey,
SerialNo: p.WechatSerialNo,
NotifyURL: p.WechatNotifyURL,
}
}
// GetShenqiConfig 获取神奇支付配置
func (p *PayConfig) GetShenqiConfig() *ShenqiPayConfig {
return &ShenqiPayConfig{
PID: p.ShenqiPID,
PrivateKey: p.ShenqiPrivateKey,
PlatformPubKey: p.ShenqiPlatformPubKey,
NotifyURL: p.ShenqiNotifyURL,
ReturnURL: p.ShenqiReturnURL,
BaseURL: p.ShenqiBaseURL,
}
}
// WechatPayConfig 微信支付配置
type WechatPayConfig struct {
AppID string `json:"appId"` // 小程序/公众号AppID
MchID string `json:"mchId"` // 商户号
MchApiV3Key string `json:"mchApiV3Key"` // API V3密钥
PrivateKey string `json:"privateKey"` // 商户私钥
SerialNo string `json:"serialNo"` // 证书序列号
NotifyURL string `json:"notifyUrl"` // 回调地址
}
// ShenqiPayConfig 神奇支付配置
type ShenqiPayConfig struct {
PID int `json:"pid"` // 商户ID
PrivateKey string `json:"privateKey"` // 商户私钥
PlatformPubKey string `json:"platformPubKey"` // 平台公钥
NotifyURL string `json:"notifyUrl"` // 回调地址
ReturnURL string `json:"returnUrl"` // 同步跳转地址
BaseURL string `json:"baseUrl"` // API地址
}