七月迭代短暂完结,还有很多后端的关键东西没有弄,这是一版赶时间做的东西
All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 8m26s
All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 8m26s
This commit is contained in:
@@ -15,6 +15,7 @@ import (
|
||||
customerBinding "github.com/break/junhong_cmp_fiber/internal/service/customer_binding"
|
||||
packagepkg "github.com/break/junhong_cmp_fiber/internal/service/package"
|
||||
"github.com/break/junhong_cmp_fiber/internal/service/packageprice"
|
||||
rechargeSvc "github.com/break/junhong_cmp_fiber/internal/service/recharge"
|
||||
"github.com/break/junhong_cmp_fiber/internal/store"
|
||||
"github.com/break/junhong_cmp_fiber/internal/store/postgres"
|
||||
"github.com/break/junhong_cmp_fiber/pkg/constants"
|
||||
@@ -39,6 +40,21 @@ type ClientAssetHandler struct {
|
||||
db *gorm.DB
|
||||
logger *zap.Logger
|
||||
observationSeries cardObservationApp.BestEffortSeriesDispatcher
|
||||
paymentMethodPolicy ClientPaymentMethodPolicy
|
||||
forceRechargeChecker ClientForceRechargeChecker
|
||||
}
|
||||
|
||||
// ClientPaymentMethodPolicy 提供 C 端支付方式读取和校验能力。
|
||||
type ClientPaymentMethodPolicy interface {
|
||||
AllowedMethods(ctx context.Context, assetType string) ([]string, error)
|
||||
AllowedRechargeMethods(ctx context.Context, assetType string) ([]string, error)
|
||||
EnsureAllowed(ctx context.Context, assetType, paymentMethod string) error
|
||||
EnsureRechargeAllowed(ctx context.Context, assetType, paymentMethod string) error
|
||||
}
|
||||
|
||||
// ClientForceRechargeChecker 提供 C 端资产当前强充资格的统一判定。
|
||||
type ClientForceRechargeChecker interface {
|
||||
GetRechargeCheck(ctx context.Context, resourceType string, resourceID uint) (*rechargeSvc.ForceRechargeRequirement, error)
|
||||
}
|
||||
|
||||
// SetObservationSeriesDispatcher 注入读取型后台观测序列端口。
|
||||
@@ -46,6 +62,16 @@ func (h *ClientAssetHandler) SetObservationSeriesDispatcher(dispatcher cardObser
|
||||
h.observationSeries = dispatcher
|
||||
}
|
||||
|
||||
// SetPaymentMethodPolicy 注入 C 端支付方式策略。
|
||||
func (h *ClientAssetHandler) SetPaymentMethodPolicy(policy ClientPaymentMethodPolicy) {
|
||||
h.paymentMethodPolicy = policy
|
||||
}
|
||||
|
||||
// SetForceRechargeChecker 注入复用现有一次性佣金状态语义的强充判定服务。
|
||||
func (h *ClientAssetHandler) SetForceRechargeChecker(checker ClientForceRechargeChecker) {
|
||||
h.forceRechargeChecker = checker
|
||||
}
|
||||
|
||||
// NewClientAssetHandler 创建 C 端资产信息处理器
|
||||
func NewClientAssetHandler(
|
||||
assetService *asset.Service,
|
||||
@@ -158,6 +184,34 @@ func (h *ClientAssetHandler) GetAssetInfo(c *fiber.Ctx) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
currentPackageID, err := h.getCurrentPackageID(resolved.SkipPermissionCtx, resolved.Asset.CurrentPackageUsageID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if h.paymentMethodPolicy == nil {
|
||||
return errors.New(errors.CodeNoPaymentConfig)
|
||||
}
|
||||
if h.forceRechargeChecker == nil {
|
||||
return errors.New(errors.CodeNoPaymentConfig)
|
||||
}
|
||||
resourceType := resolved.Asset.AssetType
|
||||
if resourceType == "card" {
|
||||
resourceType = constants.ResourceTypeIotCard
|
||||
}
|
||||
forceRecharge, err := h.forceRechargeChecker.GetRechargeCheck(resolved.SkipPermissionCtx, resourceType, resolved.Asset.AssetID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
allowedPaymentMethods, err := h.paymentMethodPolicy.AllowedMethods(resolved.SkipPermissionCtx, resolved.Asset.AssetType)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if forceRecharge.NeedForceRecharge {
|
||||
allowedPaymentMethods, err = h.paymentMethodPolicy.AllowedRechargeMethods(resolved.SkipPermissionCtx, resolved.Asset.AssetType)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
phone, _ := middleware.GetCustomerPhone(c)
|
||||
|
||||
@@ -172,11 +226,16 @@ func (h *ClientAssetHandler) GetAssetInfo(c *fiber.Ctx) error {
|
||||
StatusName: resolved.Asset.StatusName,
|
||||
RealNameStatus: resolved.Asset.RealNameStatus,
|
||||
RealNameStatusName: constants.GetRealNameStatusName(resolved.Asset.RealNameStatus),
|
||||
RealnamePolicy: resolved.Asset.RealnamePolicy,
|
||||
EffectiveRealnamePolicy: resolved.Asset.RealnamePolicy,
|
||||
RealnameRequired: resolved.Asset.RealnamePolicy != constants.RealnamePolicyNone,
|
||||
CarrierName: resolved.Asset.CarrierName,
|
||||
Generation: strconv.Itoa(resolved.Generation),
|
||||
WalletBalance: resolved.WalletBalance,
|
||||
AllowedPaymentMethods: allowedPaymentMethods,
|
||||
ActivatedAt: resolved.Asset.ActivatedAt,
|
||||
CurrentPackage: resolved.Asset.CurrentPackage,
|
||||
CurrentPackageID: currentPackageID,
|
||||
CurrentPackageUsageID: resolved.Asset.CurrentPackageUsageID,
|
||||
CurrentPackageActivatedAt: resolved.Asset.CurrentPackageActivatedAt,
|
||||
CurrentPackageExpiresAt: resolved.Asset.CurrentPackageExpiresAt,
|
||||
@@ -226,6 +285,20 @@ func (h *ClientAssetHandler) GetAssetInfo(c *fiber.Ctx) error {
|
||||
return response.Success(c, resp)
|
||||
}
|
||||
|
||||
func (h *ClientAssetHandler) getCurrentPackageID(ctx context.Context, usageID *uint) (uint, error) {
|
||||
if usageID == nil || *usageID == 0 {
|
||||
return 0, nil
|
||||
}
|
||||
var usage model.PackageUsage
|
||||
if err := h.db.WithContext(ctx).Select("package_id").First(&usage, *usageID).Error; err != nil {
|
||||
if err == gorm.ErrRecordNotFound {
|
||||
return 0, nil
|
||||
}
|
||||
return 0, errors.Wrap(errors.CodeDatabaseError, err, "查询当前套餐引用失败")
|
||||
}
|
||||
return usage.PackageID, nil
|
||||
}
|
||||
|
||||
func (h *ClientAssetHandler) dispatchAssetReadObservations(ctx context.Context, asset *dto.AssetResolveResponse) {
|
||||
if h.observationSeries == nil || asset == nil {
|
||||
return
|
||||
@@ -301,8 +374,9 @@ func (h *ClientAssetHandler) GetAvailablePackages(c *fiber.Ctx) error {
|
||||
PageSize: constants.MaxPageSize,
|
||||
OrderBy: "id DESC",
|
||||
}, map[string]any{
|
||||
"series_id": *resolved.Asset.SeriesID,
|
||||
"status": constants.StatusEnabled,
|
||||
"series_id": *resolved.Asset.SeriesID,
|
||||
"status": constants.StatusEnabled,
|
||||
"shelf_status": constants.ShelfStatusOn,
|
||||
})
|
||||
if err != nil {
|
||||
return errors.Wrap(errors.CodeDatabaseError, err, "查询可购套餐失败")
|
||||
|
||||
@@ -45,6 +45,12 @@ type ClientWalletHandler struct {
|
||||
db *gorm.DB
|
||||
iotCardStore *postgres.IotCardStore
|
||||
deviceStore *postgres.DeviceStore
|
||||
paymentMethodPolicy ClientPaymentMethodPolicy
|
||||
}
|
||||
|
||||
// SetPaymentMethodPolicy 注入 C 端支付方式策略。
|
||||
func (h *ClientWalletHandler) SetPaymentMethodPolicy(policy ClientPaymentMethodPolicy) {
|
||||
h.paymentMethodPolicy = policy
|
||||
}
|
||||
|
||||
// NewClientWalletHandler 创建 C 端钱包处理器
|
||||
@@ -243,14 +249,22 @@ func (h *ClientWalletHandler) GetRechargeCheck(c *fiber.Ctx) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if h.paymentMethodPolicy == nil {
|
||||
return errors.New(errors.CodeNoPaymentConfig)
|
||||
}
|
||||
allowedPaymentMethods, err := h.paymentMethodPolicy.AllowedRechargeMethods(resolved.SkipPermissionCtx, resolved.Asset.AssetType)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
resp := &dto.ClientRechargeCheckResponse{
|
||||
NeedForceRecharge: check.NeedForceRecharge,
|
||||
ForceRechargeAmount: check.ForceRechargeAmount,
|
||||
TriggerType: check.TriggerType,
|
||||
MinAmount: check.MinAmount,
|
||||
MaxAmount: check.MaxAmount,
|
||||
Message: check.Message,
|
||||
NeedForceRecharge: check.NeedForceRecharge,
|
||||
ForceRechargeAmount: check.ForceRechargeAmount,
|
||||
TriggerType: check.TriggerType,
|
||||
MinAmount: check.MinAmount,
|
||||
MaxAmount: check.MaxAmount,
|
||||
Message: check.Message,
|
||||
AllowedPaymentMethods: allowedPaymentMethods,
|
||||
}
|
||||
|
||||
return response.Success(c, resp)
|
||||
@@ -273,6 +287,12 @@ func (h *ClientWalletHandler) CreateRecharge(c *fiber.Ctx) error {
|
||||
if resolved.Asset.RealnamePolicy == constants.RealnamePolicyBeforeOrder && resolved.Asset.RealNameStatus != 1 {
|
||||
return errors.New(errors.CodeNeedRealname)
|
||||
}
|
||||
if h.paymentMethodPolicy == nil {
|
||||
return errors.New(errors.CodeNoPaymentConfig)
|
||||
}
|
||||
if err := h.paymentMethodPolicy.EnsureRechargeAllowed(resolved.SkipPermissionCtx, resolved.Asset.AssetType, req.PaymentMethod); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
wallet, err := h.getOrCreateWallet(resolved)
|
||||
if err != nil {
|
||||
@@ -302,9 +322,10 @@ func (h *ClientWalletHandler) CreateRecharge(c *fiber.Ctx) error {
|
||||
switch req.PaymentMethod {
|
||||
case constants.RechargeMethodAlipay:
|
||||
return h.createAlipayRecharge(c, resolved, config, wallet, req)
|
||||
default:
|
||||
// 微信充值(默认):app_type 必填
|
||||
case constants.RechargeMethodWechat:
|
||||
return h.createWechatRecharge(c, resolved, config, wallet, req)
|
||||
default:
|
||||
return errors.New(errors.CodePaymentMethodUnavailable)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -585,7 +606,6 @@ func (h *ClientWalletHandler) resolveAssetFromIdentifier(c *fiber.Ctx, identifie
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
||||
func (h *ClientWalletHandler) getAssetGeneration(ctx context.Context, assetType string, assetID uint) (int, error) {
|
||||
switch assetType {
|
||||
case "card":
|
||||
|
||||
Reference in New Issue
Block a user