diff --git a/internal/handler/app/client_realname.go b/internal/handler/app/client_realname.go index eb9fa41..1281ded 100644 --- a/internal/handler/app/client_realname.go +++ b/internal/handler/app/client_realname.go @@ -107,6 +107,17 @@ func (h *ClientRealnameHandler) GetRealnameLink(c *fiber.Ctx) error { return err } + // after_order 策略:必须先有充值或订单才能实名 + if asset.RealnamePolicy == constants.RealnamePolicyAfterOrder { + hasValid, checkErr := h.assetService.HasValidRechargeOrPaidOrder(ctx, asset.AssetType, asset.AssetID) + if checkErr != nil { + logger.GetAppLogger().Warn("检查资产有效充值或订单失败", zap.Error(checkErr)) + } + if !hasValid { + return errors.New(errors.CodeRealnameNotAvailable) + } + } + // 6. 检查实名状态 if targetCard.RealNameStatus == constants.RealNameStatusVerified { return errors.New(errors.CodeInvalidStatus, "该卡已完成实名") diff --git a/internal/handler/app/client_wallet.go b/internal/handler/app/client_wallet.go index 69e4cc5..ae79daf 100644 --- a/internal/handler/app/client_wallet.go +++ b/internal/handler/app/client_wallet.go @@ -230,6 +230,11 @@ func (h *ClientWalletHandler) GetRechargeCheck(c *fiber.Ctx) error { return err } + // before_order 策略:必须先实名才能充值 + if resolved.Asset.RealnamePolicy == constants.RealnamePolicyBeforeOrder && resolved.Asset.RealNameStatus != 1 { + return errors.New(errors.CodeNeedRealname) + } + check, err := h.rechargeService.GetRechargeCheck(resolved.SkipPermissionCtx, resolved.ResourceType, resolved.Asset.AssetID) if err != nil { return err @@ -264,6 +269,11 @@ func (h *ClientWalletHandler) CreateRecharge(c *fiber.Ctx) error { return err } + // before_order 策略:必须先实名才能充值 + if resolved.Asset.RealnamePolicy == constants.RealnamePolicyBeforeOrder && resolved.Asset.RealNameStatus != 1 { + return errors.New(errors.CodeNeedRealname) + } + wallet, err := h.getOrCreateWallet(resolved) if err != nil { return err diff --git a/internal/service/client_order/service.go b/internal/service/client_order/service.go index 98e5c6e..82c46c4 100644 --- a/internal/service/client_order/service.go +++ b/internal/service/client_order/service.go @@ -140,11 +140,10 @@ func (s *Service) CreateOrder(ctx context.Context, customerID uint, req *dto.Cli return nil, err } - // 暂不做实名认证拦截,由网关侧处理 - // REALNAME-03: 普通卡需要实名,行业卡不需要,待后续业务明确后按卡类型分支启用 - // if assetInfo.CardCategory == "normal" && assetInfo.RealNameStatus != constants.RealNameStatusVerified { - // return nil, errors.New(errors.CodeNeedRealname) - // } + // before_order 策略:必须先实名才能购买套餐 + if assetInfo.RealnamePolicy == constants.RealnamePolicyBeforeOrder && assetInfo.RealNameStatus != 1 { + return nil, errors.New(errors.CodeNeedRealname) + } // 先判断是否需要强充,避免普通下单时不必要地校验微信配置 forceRecharge := s.checkForceRechargeRequirement(skipCtx, validationResult) @@ -945,6 +944,30 @@ func (s *Service) PayOrder(ctx context.Context, customerID uint, orderID uint, r return nil, errors.New(errors.CodeInvalidStatus, "订单状态不允许支付") } + // before_order 策略:必须先实名才能支付订单 + var assetRealnamePolicy string + var assetRealnameStatus int + if order.OrderType == model.OrderTypeSingleCard && order.IotCardID != nil { + card, err := s.iotCardStore.GetByID(skipCtx, *order.IotCardID) + if err == nil && card != nil { + assetRealnamePolicy = card.RealnamePolicy + assetRealnameStatus = card.RealNameStatus + } + } else if order.OrderType == model.OrderTypeDevice && order.DeviceID != nil { + device, err := s.deviceStore.GetByID(skipCtx, *order.DeviceID) + if err == nil && device != nil { + assetRealnamePolicy = device.RealnamePolicy + // 设备的 RealNameStatus 需要通过 Resolve 获取(从当前卡派生) + resolved, resolveErr := s.assetService.Resolve(skipCtx, device.VirtualNo) + if resolveErr == nil && resolved != nil { + assetRealnameStatus = resolved.RealNameStatus + } + } + } + if assetRealnamePolicy == constants.RealnamePolicyBeforeOrder && assetRealnameStatus != 1 { + return nil, errors.New(errors.CodeNeedRealname) + } + switch req.PaymentMethod { case model.PaymentMethodWallet: if err := s.orderPaymentService.WalletPay(skipCtx, orderID, model.BuyerTypePersonal, customerID); err != nil {