Files
order/service/payment_config.go

439 lines
13 KiB
Go
Raw Normal View History

2025-12-10 13:51:09 +08:00
package service
import (
"context"
"errors"
"time"
"order/dao"
"order/model/dto"
"order/model/entity"
2025-12-12 16:20:47 +08:00
"github.com/gogf/gf/v2/util/gconv"
"go.mongodb.org/mongo-driver/v2/bson"
2025-12-10 13:51:09 +08:00
)
type paymentConfig struct{}
// PaymentConfig 支付配置服务
var PaymentConfig = new(paymentConfig)
// CreatePaymentConfig 创建支付配置
func (s *paymentConfig) CreatePaymentConfig(ctx context.Context, req *dto.CreatePaymentConfigReq) (*dto.PaymentConfigResp, error) {
// 1. 参数验证
if req.TenantID == "" || req.PayMethod == "" {
return nil, errors.New("必填参数不能为空")
}
// 2. 检查支付方式是否已存在
exist, err := dao.PaymentConfig.GetByTenantAndMethod(ctx, req.TenantID, req.PayMethod)
if err != nil {
return nil, err
}
if exist != nil {
return nil, errors.New("该支付方式已存在配置")
}
// 3. 创建配置实体
config := parseConfigMap(req.PayMethod, req.Config)
2025-12-12 16:20:47 +08:00
config.TenantId = req.TenantID
2025-12-10 13:51:09 +08:00
config.Description = req.Remark
config.Enabled = req.IsEnabled
// 4. 保存配置
if err := dao.PaymentConfig.Create(ctx, config); err != nil {
return nil, err
}
// 5. 返回结果
resp := &dto.PaymentConfigResp{
2025-12-12 16:20:47 +08:00
ID: config.Id.Hex(),
TenantID: gconv.String(config.TenantId),
2025-12-10 13:51:09 +08:00
PayMethod: config.PayMethod,
Config: buildConfigMap(config),
IsEnabled: config.Enabled,
Remark: config.Description,
CreatedAt: time.Now(), // 暂时使用当前时间
UpdatedAt: time.Now(),
}
return resp, nil
}
// UpdatePaymentConfig 更新支付配置
func (s *paymentConfig) UpdatePaymentConfig(ctx context.Context, req *dto.UpdatePaymentConfigReq) (*dto.PaymentConfigResp, error) {
// 1. 参数验证
if req.ID == "" || req.TenantID == "" {
return nil, errors.New("必填参数不能为空")
}
// 2. 查询配置
objectID, err := bson.ObjectIDFromHex(req.ID)
if err != nil {
return nil, errors.New("无效的配置ID")
}
config, err := dao.PaymentConfig.GetByID(ctx, objectID)
if err != nil {
return nil, err
}
if config == nil {
return nil, errors.New("支付配置不存在")
}
// 3. 检查是否是租户自己的配置
2025-12-12 16:20:47 +08:00
if config.TenantId != req.TenantID {
2025-12-10 13:51:09 +08:00
return nil, errors.New("无权限操作该配置")
}
// 4. 更新配置实体
config.ConfigName = req.ConfigName
config.Description = req.Remark
config.Enabled = req.IsEnabled
// 解析配置参数
parseConfigMapToEntity(config.PayMethod, req.Config, config)
// 5. 更新配置
if err := dao.PaymentConfig.Update(ctx, config); err != nil {
return nil, err
}
// 6. 返回结果
resp := &dto.PaymentConfigResp{
2025-12-12 16:20:47 +08:00
ID: config.Id.Hex(),
TenantID: gconv.String(config.TenantId),
2025-12-10 13:51:09 +08:00
PayMethod: config.PayMethod,
ConfigName: config.ConfigName,
Remark: config.Description,
IsEnabled: config.Enabled,
Config: convertEntityToConfigMap(config),
CreatedAt: time.Unix(0, 0), // 实体中没有时间字段,使用默认值
UpdatedAt: time.Now(),
}
return resp, nil
}
// GetPaymentConfig 获取支付配置
func (s *paymentConfig) GetPaymentConfig(ctx context.Context, req *dto.QueryPaymentConfigReq) (*dto.PaymentConfigResp, error) {
// 1. 参数验证
if req.TenantID == "" {
return nil, errors.New("租户ID不能为空")
}
var config *entity.PaymentConfig
var err error
// 2. 查询配置
if req.PayMethod != "" {
// 按租户和支付方式查询
config, err = dao.PaymentConfig.GetByTenantAndMethod(ctx, req.TenantID, req.PayMethod)
} else {
// 只按租户查询(获取所有支付方式配置)
configs, err := dao.PaymentConfig.GetByTenantID(ctx, req.TenantID)
if err != nil {
return nil, err
}
if len(configs) > 0 {
config = &configs[0] // 返回第一个配置作为默认
}
}
if err != nil {
return nil, err
}
if config == nil {
return nil, errors.New("支付配置不存在")
}
// 3. 返回结果
resp := &dto.PaymentConfigResp{
2025-12-12 16:20:47 +08:00
ID: config.Id.Hex(),
TenantID: gconv.String(config.TenantId),
2025-12-10 13:51:09 +08:00
PayMethod: config.PayMethod,
ConfigName: config.ConfigName,
Remark: config.Description,
IsEnabled: config.Enabled,
Config: convertEntityToConfigMap(config),
CreatedAt: time.Unix(0, 0),
UpdatedAt: time.Now(),
}
return resp, nil
}
// GetPaymentConfigList 获取支付配置列表
func (s *paymentConfig) GetPaymentConfigList(ctx context.Context, tenantID string) ([]dto.PaymentConfigResp, error) {
// 1. 参数验证
if tenantID == "" {
return nil, errors.New("租户ID不能为空")
}
// 2. 查询配置列表
configs, err := dao.PaymentConfig.GetByTenantID(ctx, tenantID)
if err != nil {
return nil, err
}
// 3. 转换为响应格式
var resp []dto.PaymentConfigResp
for _, config := range configs {
resp = append(resp, dto.PaymentConfigResp{
2025-12-12 16:20:47 +08:00
ID: config.Id.Hex(),
TenantID: gconv.String(config.TenantId),
2025-12-10 13:51:09 +08:00
PayMethod: config.PayMethod,
ConfigName: config.ConfigName,
Remark: config.Description,
IsEnabled: config.Enabled,
Config: convertEntityToConfigMap(&config),
CreatedAt: time.Unix(0, 0),
UpdatedAt: time.Now(),
})
}
return resp, nil
}
// DeletePaymentConfig 删除支付配置
func (s *paymentConfig) DeletePaymentConfig(ctx context.Context, tenantID, configID string) error {
// 1. 参数验证
if tenantID == "" || configID == "" {
return errors.New("必填参数不能为空")
}
// 2. 查询配置
objectID, err := bson.ObjectIDFromHex(configID)
if err != nil {
return errors.New("无效的配置ID")
}
config, err := dao.PaymentConfig.GetByID(ctx, objectID)
if err != nil {
return err
}
if config == nil {
return errors.New("支付配置不存在")
}
// 3. 检查是否是租户自己的配置
2025-12-12 16:20:47 +08:00
if config.TenantId != tenantID {
2025-12-10 13:51:09 +08:00
return errors.New("无权限操作该配置")
}
// 4. 删除配置
return dao.PaymentConfig.Delete(ctx, objectID)
}
// EnablePaymentConfig 启用支付配置
func (s *paymentConfig) EnablePaymentConfig(ctx context.Context, tenantID, configID string) error {
return s.updateConfigStatus(ctx, tenantID, configID, true)
}
// DisablePaymentConfig 禁用支付配置
func (s *paymentConfig) DisablePaymentConfig(ctx context.Context, tenantID, configID string) error {
return s.updateConfigStatus(ctx, tenantID, configID, false)
}
// updateConfigStatus 更新配置状态
func (s *paymentConfig) updateConfigStatus(ctx context.Context, tenantID, configID string, enabled bool) error {
// 1. 参数验证
if tenantID == "" || configID == "" {
return errors.New("必填参数不能为空")
}
// 2. 查询配置
objectID, err := bson.ObjectIDFromHex(configID)
if err != nil {
return errors.New("无效的配置ID")
}
config, err := dao.PaymentConfig.GetByID(ctx, objectID)
if err != nil {
return err
}
if config == nil {
return errors.New("支付配置不存在")
}
// 3. 检查是否是租户自己的配置
2025-12-12 16:20:47 +08:00
if config.TenantId != tenantID {
2025-12-10 13:51:09 +08:00
return errors.New("无权限操作该配置")
}
// 4. 更新状态
config.Enabled = enabled
return dao.PaymentConfig.Update(ctx, config)
}
// WechatConfig 微信支付配置服务
var WechatConfig = new(wechatConfig)
type wechatConfig struct{}
// GetWechatConfig 获取微信支付配置
func (s *wechatConfig) GetWechatConfig(ctx context.Context, tenantID string) (*dto.WechatConfig, error) {
// 1. 获取微信支付配置
resp, err := PaymentConfig.GetPaymentConfig(ctx, &dto.QueryPaymentConfigReq{
TenantID: tenantID,
PayMethod: "wechat",
})
if err != nil {
return nil, err
}
// 2. 转换为微信配置结构体
configMap := resp.Config
wechatConfig := &dto.WechatConfig{
ID: resp.ID,
TenantID: resp.TenantID,
ConfigName: resp.ConfigName,
AppID: getString(configMap, "app_id"),
MchID: getString(configMap, "mch_id"),
APIKey: getString(configMap, "api_key"),
NotifyURL: getString(configMap, "notify_url"),
ReturnURL: getString(configMap, "return_url"),
CertPath: getString(configMap, "cert_path"),
KeyPath: getString(configMap, "key_path"),
Sandbox: getBool(configMap, "sandbox"),
GatewayURL: getString(configMap, "gateway_url"),
SupportNative: getBool(configMap, "support_native"),
SupportJSAPI: getBool(configMap, "support_jsapi"),
SupportAPP: getBool(configMap, "support_app"),
SupportH5: getBool(configMap, "support_h5"),
}
return wechatConfig, nil
}
// AlipayConfig 支付宝支付配置服务
var AlipayConfig = new(alipayConfig)
type alipayConfig struct{}
// GetAlipayConfig 获取支付宝支付配置
func (s *alipayConfig) GetAlipayConfig(ctx context.Context, tenantID string) (*dto.AlipayConfig, error) {
// 1. 获取支付宝支付配置
resp, err := PaymentConfig.GetPaymentConfig(ctx, &dto.QueryPaymentConfigReq{
TenantID: tenantID,
PayMethod: "alipay",
})
if err != nil {
return nil, err
}
// 2. 转换为支付宝配置结构体
configMap := resp.Config
alipayConfig := &dto.AlipayConfig{
ID: resp.ID,
TenantID: resp.TenantID,
ConfigName: resp.ConfigName,
AppID: getString(configMap, "app_id"),
NotifyURL: getString(configMap, "notify_url"),
ReturnURL: getString(configMap, "return_url"),
AppPrivateKey: getString(configMap, "app_private_key"),
AlipayPublicKey: getString(configMap, "alipay_public_key"),
Sandbox: getBool(configMap, "sandbox"),
GatewayURL: getString(configMap, "gateway_url"),
SupportNative: getBool(configMap, "support_native"),
SupportJSAPI: getBool(configMap, "support_jsapi"),
SupportAPP: getBool(configMap, "support_app"),
SupportH5: getBool(configMap, "support_h5"),
}
return alipayConfig, nil
}
// getString 从map中获取string值
func getString(m map[string]interface{}, key string) string {
if val, ok := m[key]; ok {
if str, ok := val.(string); ok {
return str
}
}
return ""
}
// getBool 从map中获取bool值
func getBool(m map[string]interface{}, key string) bool {
if val, ok := m[key]; ok {
if b, ok := val.(bool); ok {
return b
}
}
return false
}
// buildConfigMap 将PaymentConfig结构体转换为map
func buildConfigMap(config *entity.PaymentConfig) map[string]interface{} {
result := map[string]interface{}{
"app_id": config.AppID,
"mch_id": config.MchID,
"api_key": config.APIKey,
"notify_url": config.NotifyURL,
"return_url": config.ReturnURL,
"cert_path": config.CertPath,
"key_path": config.KeyPath,
"app_private_key": config.AppPrivateKey,
"alipay_public_key": config.AlipayPublicKey,
"sandbox": config.Sandbox,
"gateway_url": config.GatewayURL,
"support_native": config.SupportNative,
"support_jsapi": config.SupportJSAPI,
"support_app": config.SupportAPP,
"support_h5": config.SupportH5,
}
return result
}
// parseConfigMap 将map转换为PaymentConfig结构体
func parseConfigMap(payMethod string, configMap map[string]interface{}) *entity.PaymentConfig {
config := &entity.PaymentConfig{
PayMethod: payMethod,
ConfigName: payMethod + "配置",
AppID: getString(configMap, "app_id"),
MchID: getString(configMap, "mch_id"),
APIKey: getString(configMap, "api_key"),
NotifyURL: getString(configMap, "notify_url"),
ReturnURL: getString(configMap, "return_url"),
CertPath: getString(configMap, "cert_path"),
KeyPath: getString(configMap, "key_path"),
AppPrivateKey: getString(configMap, "app_private_key"),
AlipayPublicKey: getString(configMap, "alipay_public_key"),
Sandbox: getBool(configMap, "sandbox"),
GatewayURL: getString(configMap, "gateway_url"),
SupportNative: getBool(configMap, "support_native"),
SupportJSAPI: getBool(configMap, "support_jsapi"),
SupportAPP: getBool(configMap, "support_app"),
SupportH5: getBool(configMap, "support_h5"),
}
return config
}
// parseConfigMapToEntity 将map中的配置更新到实体中
func parseConfigMapToEntity(payMethod string, configMap map[string]interface{}, config *entity.PaymentConfig) {
config.AppID = getString(configMap, "app_id")
config.MchID = getString(configMap, "mch_id")
config.APIKey = getString(configMap, "api_key")
config.NotifyURL = getString(configMap, "notify_url")
config.ReturnURL = getString(configMap, "return_url")
config.CertPath = getString(configMap, "cert_path")
config.KeyPath = getString(configMap, "key_path")
config.AppPrivateKey = getString(configMap, "app_private_key")
config.AlipayPublicKey = getString(configMap, "alipay_public_key")
config.Sandbox = getBool(configMap, "sandbox")
config.GatewayURL = getString(configMap, "gateway_url")
config.SupportNative = getBool(configMap, "support_native")
config.SupportJSAPI = getBool(configMap, "support_jsapi")
config.SupportAPP = getBool(configMap, "support_app")
config.SupportH5 = getBool(configMap, "support_h5")
}
// convertEntityToConfigMap 将实体转换为配置map
func convertEntityToConfigMap(config *entity.PaymentConfig) map[string]interface{} {
return buildConfigMap(config)
}