fix
This commit is contained in:
@@ -174,14 +174,13 @@ func (s *ApiApplicationServiceImpl) CallApi(ctx context.Context, cmd *commands.A
|
||||
}
|
||||
// apiCall.ResponseData = &encryptedResponse
|
||||
|
||||
// 8. 更新订阅使用次数
|
||||
subscription.IncrementAPIUsage(1)
|
||||
err = s.productSubscriptionService.SaveSubscription(txCtx, subscription)
|
||||
if err != nil {
|
||||
s.logger.Error("保存订阅失败", zap.Error(err))
|
||||
businessError = ErrSystem
|
||||
return ErrSystem
|
||||
}
|
||||
// 8. 更新订阅使用次数(使用乐观锁)
|
||||
// err = s.productSubscriptionService.IncrementSubscriptionAPIUsage(txCtx, subscription.ID, 1)
|
||||
// if err != nil {
|
||||
// s.logger.Error("更新订阅使用次数失败", zap.Error(err))
|
||||
// businessError = ErrSystem
|
||||
// return ErrSystem
|
||||
// }
|
||||
|
||||
// 9. 扣钱
|
||||
err = s.walletService.Deduct(txCtx, apiUser.UserId, subscription.Price, apiCall.ID, transactionId, product.ID)
|
||||
|
||||
@@ -102,6 +102,13 @@ type AlipayRechargeOrderResponse struct {
|
||||
|
||||
// RechargeConfigResponse 充值配置响应
|
||||
type RechargeConfigResponse struct {
|
||||
MinAmount string `json:"min_amount"` // 最低充值金额
|
||||
MaxAmount string `json:"max_amount"` // 最高充值金额
|
||||
MinAmount string `json:"min_amount"` // 最低充值金额
|
||||
MaxAmount string `json:"max_amount"` // 最高充值金额
|
||||
AlipayRechargeBonus []AlipayRechargeBonusRuleResponse `json:"alipay_recharge_bonus"`
|
||||
}
|
||||
|
||||
// AlipayRechargeBonusRuleResponse 支付宝充值赠送规则响应
|
||||
type AlipayRechargeBonusRuleResponse struct {
|
||||
RechargeAmount float64 `json:"recharge_amount"`
|
||||
BonusAmount float64 `json:"bonus_amount"`
|
||||
}
|
||||
|
||||
@@ -113,15 +113,15 @@ func (s *FinanceApplicationServiceImpl) CreateAlipayRechargeOrder(ctx context.Co
|
||||
}
|
||||
|
||||
// 从配置中获取充值限制
|
||||
minAmount, err := decimal.NewFromString(s.config.Recharge.MinAmount)
|
||||
minAmount, err := decimal.NewFromString(s.config.Wallet.MinAmount)
|
||||
if err != nil {
|
||||
s.logger.Error("配置中的最低充值金额格式错误", zap.String("min_amount", s.config.Recharge.MinAmount), zap.Error(err))
|
||||
s.logger.Error("配置中的最低充值金额格式错误", zap.String("min_amount", s.config.Wallet.MinAmount), zap.Error(err))
|
||||
return nil, fmt.Errorf("系统配置错误: %w", err)
|
||||
}
|
||||
|
||||
maxAmount, err := decimal.NewFromString(s.config.Recharge.MaxAmount)
|
||||
maxAmount, err := decimal.NewFromString(s.config.Wallet.MaxAmount)
|
||||
if err != nil {
|
||||
s.logger.Error("配置中的最高充值金额格式错误", zap.String("max_amount", s.config.Recharge.MaxAmount), zap.Error(err))
|
||||
s.logger.Error("配置中的最高充值金额格式错误", zap.String("max_amount", s.config.Wallet.MaxAmount), zap.Error(err))
|
||||
return nil, fmt.Errorf("系统配置错误: %w", err)
|
||||
}
|
||||
|
||||
@@ -643,8 +643,16 @@ func (s *FinanceApplicationServiceImpl) GetAdminRechargeRecords(ctx context.Cont
|
||||
|
||||
// GetRechargeConfig 获取充值配置
|
||||
func (s *FinanceApplicationServiceImpl) GetRechargeConfig(ctx context.Context) (*responses.RechargeConfigResponse, error) {
|
||||
bonus := make([]responses.AlipayRechargeBonusRuleResponse, 0, len(s.config.Wallet.AliPayRechargeBonus))
|
||||
for _, rule := range s.config.Wallet.AliPayRechargeBonus {
|
||||
bonus = append(bonus, responses.AlipayRechargeBonusRuleResponse{
|
||||
RechargeAmount: rule.RechargeAmount,
|
||||
BonusAmount: rule.BonusAmount,
|
||||
})
|
||||
}
|
||||
return &responses.RechargeConfigResponse{
|
||||
MinAmount: s.config.Recharge.MinAmount,
|
||||
MaxAmount: s.config.Recharge.MaxAmount,
|
||||
MinAmount: s.config.Wallet.MinAmount,
|
||||
MaxAmount: s.config.Wallet.MaxAmount,
|
||||
AlipayRechargeBonus: bonus,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -0,0 +1,138 @@
|
||||
package product
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"tyapi-server/internal/application/product/dto/commands"
|
||||
"tyapi-server/internal/application/product/dto/responses"
|
||||
"tyapi-server/internal/domains/product/entities"
|
||||
"tyapi-server/internal/domains/product/services"
|
||||
)
|
||||
|
||||
// DocumentationApplicationServiceInterface 文档应用服务接口
|
||||
type DocumentationApplicationServiceInterface interface {
|
||||
// CreateDocumentation 创建文档
|
||||
CreateDocumentation(ctx context.Context, cmd *commands.CreateDocumentationCommand) (*responses.DocumentationResponse, error)
|
||||
|
||||
// UpdateDocumentation 更新文档
|
||||
UpdateDocumentation(ctx context.Context, id string, cmd *commands.UpdateDocumentationCommand) (*responses.DocumentationResponse, error)
|
||||
|
||||
// GetDocumentation 获取文档
|
||||
GetDocumentation(ctx context.Context, id string) (*responses.DocumentationResponse, error)
|
||||
|
||||
// GetDocumentationByProductID 通过产品ID获取文档
|
||||
GetDocumentationByProductID(ctx context.Context, productID string) (*responses.DocumentationResponse, error)
|
||||
|
||||
// DeleteDocumentation 删除文档
|
||||
DeleteDocumentation(ctx context.Context, id string) error
|
||||
|
||||
// GetDocumentationsByProductIDs 批量获取文档
|
||||
GetDocumentationsByProductIDs(ctx context.Context, productIDs []string) ([]responses.DocumentationResponse, error)
|
||||
}
|
||||
|
||||
// DocumentationApplicationService 文档应用服务
|
||||
type DocumentationApplicationService struct {
|
||||
docService *services.ProductDocumentationService
|
||||
}
|
||||
|
||||
// NewDocumentationApplicationService 创建文档应用服务实例
|
||||
func NewDocumentationApplicationService(docService *services.ProductDocumentationService) *DocumentationApplicationService {
|
||||
return &DocumentationApplicationService{
|
||||
docService: docService,
|
||||
}
|
||||
}
|
||||
|
||||
// CreateDocumentation 创建文档
|
||||
func (s *DocumentationApplicationService) CreateDocumentation(ctx context.Context, cmd *commands.CreateDocumentationCommand) (*responses.DocumentationResponse, error) {
|
||||
// 创建文档实体
|
||||
doc := &entities.ProductDocumentation{
|
||||
RequestURL: cmd.RequestURL,
|
||||
RequestMethod: cmd.RequestMethod,
|
||||
BasicInfo: cmd.BasicInfo,
|
||||
RequestParams: cmd.RequestParams,
|
||||
ResponseFields: cmd.ResponseFields,
|
||||
ResponseExample: cmd.ResponseExample,
|
||||
ErrorCodes: cmd.ErrorCodes,
|
||||
}
|
||||
|
||||
// 调用领域服务创建文档
|
||||
err := s.docService.CreateDocumentation(ctx, cmd.ProductID, doc)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 返回响应
|
||||
resp := responses.NewDocumentationResponse(doc)
|
||||
return &resp, nil
|
||||
}
|
||||
|
||||
// UpdateDocumentation 更新文档
|
||||
func (s *DocumentationApplicationService) UpdateDocumentation(ctx context.Context, id string, cmd *commands.UpdateDocumentationCommand) (*responses.DocumentationResponse, error) {
|
||||
// 调用领域服务更新文档
|
||||
err := s.docService.UpdateDocumentation(ctx, id,
|
||||
cmd.RequestURL,
|
||||
cmd.RequestMethod,
|
||||
cmd.BasicInfo,
|
||||
cmd.RequestParams,
|
||||
cmd.ResponseFields,
|
||||
cmd.ResponseExample,
|
||||
cmd.ErrorCodes,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 获取更新后的文档
|
||||
doc, err := s.docService.GetDocumentation(ctx, id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 返回响应
|
||||
resp := responses.NewDocumentationResponse(doc)
|
||||
return &resp, nil
|
||||
}
|
||||
|
||||
// GetDocumentation 获取文档
|
||||
func (s *DocumentationApplicationService) GetDocumentation(ctx context.Context, id string) (*responses.DocumentationResponse, error) {
|
||||
doc, err := s.docService.GetDocumentation(ctx, id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 返回响应
|
||||
resp := responses.NewDocumentationResponse(doc)
|
||||
return &resp, nil
|
||||
}
|
||||
|
||||
// GetDocumentationByProductID 通过产品ID获取文档
|
||||
func (s *DocumentationApplicationService) GetDocumentationByProductID(ctx context.Context, productID string) (*responses.DocumentationResponse, error) {
|
||||
doc, err := s.docService.GetDocumentationByProductID(ctx, productID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 返回响应
|
||||
resp := responses.NewDocumentationResponse(doc)
|
||||
return &resp, nil
|
||||
}
|
||||
|
||||
// DeleteDocumentation 删除文档
|
||||
func (s *DocumentationApplicationService) DeleteDocumentation(ctx context.Context, id string) error {
|
||||
return s.docService.DeleteDocumentation(ctx, id)
|
||||
}
|
||||
|
||||
// GetDocumentationsByProductIDs 批量获取文档
|
||||
func (s *DocumentationApplicationService) GetDocumentationsByProductIDs(ctx context.Context, productIDs []string) ([]responses.DocumentationResponse, error) {
|
||||
docs, err := s.docService.GetDocumentationsByProductIDs(ctx, productIDs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var docResponses []responses.DocumentationResponse
|
||||
for _, doc := range docs {
|
||||
docResponses = append(docResponses, responses.NewDocumentationResponse(doc))
|
||||
}
|
||||
|
||||
return docResponses, nil
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package commands
|
||||
|
||||
// CreateDocumentationCommand 创建文档命令
|
||||
type CreateDocumentationCommand struct {
|
||||
ProductID string `json:"product_id" binding:"required" validate:"required"`
|
||||
RequestURL string `json:"request_url" binding:"required" validate:"required"`
|
||||
RequestMethod string `json:"request_method" binding:"required" validate:"required"`
|
||||
BasicInfo string `json:"basic_info" validate:"required"`
|
||||
RequestParams string `json:"request_params" validate:"required"`
|
||||
ResponseFields string `json:"response_fields"`
|
||||
ResponseExample string `json:"response_example"`
|
||||
ErrorCodes string `json:"error_codes"`
|
||||
}
|
||||
|
||||
// UpdateDocumentationCommand 更新文档命令
|
||||
type UpdateDocumentationCommand struct {
|
||||
RequestURL string `json:"request_url"`
|
||||
RequestMethod string `json:"request_method"`
|
||||
BasicInfo string `json:"basic_info"`
|
||||
RequestParams string `json:"request_params"`
|
||||
ResponseFields string `json:"response_fields"`
|
||||
ResponseExample string `json:"response_example"`
|
||||
ErrorCodes string `json:"error_codes"`
|
||||
}
|
||||
@@ -36,6 +36,13 @@ type GetProductQuery struct {
|
||||
Code string `form:"code" binding:"omitempty,product_code" comment:"产品编号"`
|
||||
}
|
||||
|
||||
// GetProductDetailQuery 获取产品详情查询(支持可选文档)
|
||||
type GetProductDetailQuery struct {
|
||||
ID string `uri:"id" binding:"omitempty,uuid" comment:"产品ID"`
|
||||
Code string `form:"code" binding:"omitempty,product_code" comment:"产品编号"`
|
||||
WithDocument *bool `form:"with_document" comment:"是否包含文档信息"`
|
||||
}
|
||||
|
||||
// GetProductsByIDsQuery 根据ID列表获取产品查询
|
||||
type GetProductsByIDsQuery struct {
|
||||
IDs []string `form:"ids" binding:"required,dive,uuid" comment:"产品ID列表"`
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
package responses
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"tyapi-server/internal/domains/product/entities"
|
||||
)
|
||||
|
||||
// DocumentationResponse 文档响应
|
||||
type DocumentationResponse struct {
|
||||
ID string `json:"id"`
|
||||
ProductID string `json:"product_id"`
|
||||
RequestURL string `json:"request_url"`
|
||||
RequestMethod string `json:"request_method"`
|
||||
BasicInfo string `json:"basic_info"`
|
||||
RequestParams string `json:"request_params"`
|
||||
ResponseFields string `json:"response_fields"`
|
||||
ResponseExample string `json:"response_example"`
|
||||
ErrorCodes string `json:"error_codes"`
|
||||
Version string `json:"version"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
}
|
||||
|
||||
// NewDocumentationResponse 从实体创建响应
|
||||
func NewDocumentationResponse(doc *entities.ProductDocumentation) DocumentationResponse {
|
||||
return DocumentationResponse{
|
||||
ID: doc.ID,
|
||||
ProductID: doc.ProductID,
|
||||
RequestURL: doc.RequestURL,
|
||||
RequestMethod: doc.RequestMethod,
|
||||
BasicInfo: doc.BasicInfo,
|
||||
RequestParams: doc.RequestParams,
|
||||
ResponseFields: doc.ResponseFields,
|
||||
ResponseExample: doc.ResponseExample,
|
||||
ErrorCodes: doc.ErrorCodes,
|
||||
Version: doc.Version,
|
||||
CreatedAt: doc.CreatedAt,
|
||||
UpdatedAt: doc.UpdatedAt,
|
||||
}
|
||||
}
|
||||
@@ -100,10 +100,19 @@ type ProductAdminInfoResponse struct {
|
||||
// 组合包信息
|
||||
PackageItems []*PackageItemResponse `json:"package_items,omitempty" comment:"组合包项目列表"`
|
||||
|
||||
// 文档信息
|
||||
Documentation *DocumentationResponse `json:"documentation,omitempty" comment:"产品文档"`
|
||||
|
||||
CreatedAt time.Time `json:"created_at" comment:"创建时间"`
|
||||
UpdatedAt time.Time `json:"updated_at" comment:"更新时间"`
|
||||
}
|
||||
|
||||
// ProductInfoWithDocumentResponse 包含文档的产品详情响应
|
||||
type ProductInfoWithDocumentResponse struct {
|
||||
ProductInfoResponse
|
||||
Documentation *DocumentationResponse `json:"documentation,omitempty" comment:"产品文档"`
|
||||
}
|
||||
|
||||
// ProductAdminListResponse 管理员产品列表响应
|
||||
type ProductAdminListResponse struct {
|
||||
Total int64 `json:"total" comment:"总数"`
|
||||
|
||||
@@ -22,10 +22,10 @@ type ProductApplicationService interface {
|
||||
|
||||
// 管理员专用方法
|
||||
ListProductsForAdmin(ctx context.Context, filters map[string]interface{}, options interfaces.ListOptions) (*responses.ProductAdminListResponse, error)
|
||||
GetProductByIDForAdmin(ctx context.Context, query *queries.GetProductQuery) (*responses.ProductAdminInfoResponse, error)
|
||||
GetProductByIDForAdmin(ctx context.Context, query *queries.GetProductDetailQuery) (*responses.ProductAdminInfoResponse, error)
|
||||
|
||||
// 用户端专用方法
|
||||
GetProductByIDForUser(ctx context.Context, query *queries.GetProductQuery) (*responses.ProductInfoResponse, error)
|
||||
GetProductByIDForUser(ctx context.Context, query *queries.GetProductDetailQuery) (*responses.ProductInfoWithDocumentResponse, error)
|
||||
|
||||
// 业务查询
|
||||
GetSubscribableProducts(ctx context.Context, query *queries.GetSubscribableProductsQuery) ([]*responses.ProductInfoResponse, error)
|
||||
|
||||
@@ -21,6 +21,7 @@ type ProductApplicationServiceImpl struct {
|
||||
productManagementService *product_service.ProductManagementService
|
||||
productSubscriptionService *product_service.ProductSubscriptionService
|
||||
productApiConfigAppService ProductApiConfigApplicationService
|
||||
documentationAppService DocumentationApplicationServiceInterface
|
||||
logger *zap.Logger
|
||||
}
|
||||
|
||||
@@ -29,12 +30,14 @@ func NewProductApplicationService(
|
||||
productManagementService *product_service.ProductManagementService,
|
||||
productSubscriptionService *product_service.ProductSubscriptionService,
|
||||
productApiConfigAppService ProductApiConfigApplicationService,
|
||||
documentationAppService DocumentationApplicationServiceInterface,
|
||||
logger *zap.Logger,
|
||||
) ProductApplicationService {
|
||||
return &ProductApplicationServiceImpl{
|
||||
productManagementService: productManagementService,
|
||||
productSubscriptionService: productSubscriptionService,
|
||||
productApiConfigAppService: productApiConfigAppService,
|
||||
documentationAppService: documentationAppService,
|
||||
logger: logger,
|
||||
}
|
||||
}
|
||||
@@ -411,18 +414,28 @@ func (s *ProductApplicationServiceImpl) ListProductsForAdmin(ctx context.Context
|
||||
|
||||
// GetProductByIDForAdmin 根据ID获取产品(管理员专用)
|
||||
// 业务流程:1. 获取产品信息 2. 构建管理员响应数据
|
||||
func (s *ProductApplicationServiceImpl) GetProductByIDForAdmin(ctx context.Context, query *appQueries.GetProductQuery) (*responses.ProductAdminInfoResponse, error) {
|
||||
func (s *ProductApplicationServiceImpl) GetProductByIDForAdmin(ctx context.Context, query *appQueries.GetProductDetailQuery) (*responses.ProductAdminInfoResponse, error) {
|
||||
product, err := s.productManagementService.GetProductWithCategory(ctx, query.ID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return s.convertToProductAdminInfoResponse(product), nil
|
||||
response := s.convertToProductAdminInfoResponse(product)
|
||||
|
||||
// 如果需要包含文档信息
|
||||
if query.WithDocument != nil && *query.WithDocument {
|
||||
doc, err := s.documentationAppService.GetDocumentationByProductID(ctx, query.ID)
|
||||
if err == nil && doc != nil {
|
||||
response.Documentation = doc
|
||||
}
|
||||
}
|
||||
|
||||
return response, nil
|
||||
}
|
||||
|
||||
// GetProductByIDForUser 根据ID获取产品(用户端专用)
|
||||
// 业务流程:1. 获取产品信息 2. 验证产品可见性 3. 构建用户响应数据
|
||||
func (s *ProductApplicationServiceImpl) GetProductByIDForUser(ctx context.Context, query *appQueries.GetProductQuery) (*responses.ProductInfoResponse, error) {
|
||||
func (s *ProductApplicationServiceImpl) GetProductByIDForUser(ctx context.Context, query *appQueries.GetProductDetailQuery) (*responses.ProductInfoWithDocumentResponse, error) {
|
||||
product, err := s.productManagementService.GetProductWithCategory(ctx, query.ID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -433,7 +446,19 @@ func (s *ProductApplicationServiceImpl) GetProductByIDForUser(ctx context.Contex
|
||||
return nil, fmt.Errorf("产品不存在或不可见")
|
||||
}
|
||||
|
||||
return s.convertToProductInfoResponse(product), nil
|
||||
response := &responses.ProductInfoWithDocumentResponse{
|
||||
ProductInfoResponse: *s.convertToProductInfoResponse(product),
|
||||
}
|
||||
|
||||
// 如果需要包含文档信息
|
||||
if query.WithDocument != nil && *query.WithDocument {
|
||||
doc, err := s.documentationAppService.GetDocumentationByProductID(ctx, query.ID)
|
||||
if err == nil && doc != nil {
|
||||
response.Documentation = doc
|
||||
}
|
||||
}
|
||||
|
||||
return response, nil
|
||||
}
|
||||
|
||||
// convertToProductInfoResponse 转换为产品信息响应
|
||||
|
||||
Reference in New Issue
Block a user