七月迭代短暂完结,还有很多后端的关键东西没有弄,这是一版赶时间做的东西
All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 8m26s

This commit is contained in:
2026-07-25 17:06:58 +08:00
parent ad9f613dd6
commit 73f5125d3d
249 changed files with 17137 additions and 877 deletions

View File

@@ -102,7 +102,7 @@ func (s *Service) VerifyAsset(ctx context.Context, req *dto.VerifyAssetRequest,
return nil, err
}
assetType, assetID, err := s.resolveAsset(ctx, req.Identifier)
assetType, assetID, shopID, err := s.resolveAsset(ctx, req.Identifier)
if err != nil {
return nil, err
}
@@ -116,6 +116,9 @@ func (s *Service) VerifyAsset(ctx context.Context, req *dto.VerifyAssetRequest,
return nil, errors.New(errors.CodeForbidden, "该卡绑定了设备,请使用设备的虚拟号/设备号/IMEI/SN登录")
}
}
if err := s.ensureShopClientLoginAllowed(ctx, shopID); err != nil {
return nil, err
}
assetToken, err := s.signAssetToken(assetType, assetID)
if err != nil {
@@ -407,26 +410,45 @@ func (s *Service) checkAssetVerifyRateLimit(ctx context.Context, clientIP string
return nil
}
func (s *Service) resolveAsset(ctx context.Context, identifier string) (string, uint, error) {
func (s *Service) resolveAsset(ctx context.Context, identifier string) (string, uint, *uint, error) {
var card model.IotCard
if err := s.db.WithContext(ctx).
Where("iccid = ? OR virtual_no = ? OR msisdn = ?", identifier, identifier, identifier).
First(&card).Error; err == nil {
return assetTypeIotCard, card.ID, nil
return assetTypeIotCard, card.ID, card.ShopID, nil
} else if err != gorm.ErrRecordNotFound {
return "", 0, errors.Wrap(errors.CodeInternalError, err, "查询卡资产失败")
return "", 0, nil, errors.Wrap(errors.CodeInternalError, err, "查询卡资产失败")
}
var device model.Device
if err := s.db.WithContext(ctx).
Where("virtual_no = ? OR imei = ? OR sn = ?", identifier, identifier, identifier).
First(&device).Error; err == nil {
return assetTypeDevice, device.ID, nil
return assetTypeDevice, device.ID, device.ShopID, nil
} else if err != gorm.ErrRecordNotFound {
return "", 0, errors.Wrap(errors.CodeInternalError, err, "查询设备资产失败")
return "", 0, nil, errors.Wrap(errors.CodeInternalError, err, "查询设备资产失败")
}
return "", 0, errors.New(errors.CodeAssetNotFound)
return "", 0, nil, errors.New(errors.CodeAssetNotFound)
}
// ensureShopClientLoginAllowed 在签发资产令牌前检查店铺的新登录限制。
func (s *Service) ensureShopClientLoginAllowed(ctx context.Context, shopID *uint) error {
if shopID == nil {
return nil
}
var shop model.Shop
err := s.db.WithContext(ctx).Select("client_login_disabled").First(&shop, *shopID).Error
if err == gorm.ErrRecordNotFound {
return errors.New(errors.CodeForbidden, "资产所属店铺不可用")
}
if err != nil {
return errors.Wrap(errors.CodeDatabaseError, err, "查询店铺C端登录限制失败")
}
if shop.ClientLoginDisabled {
return errors.New(errors.CodeForbidden, "该店铺暂不允许C端登录")
}
return nil
}
func (s *Service) signAssetToken(assetType string, assetID uint) (string, error) {
@@ -681,7 +703,7 @@ func (s *Service) issueLoginToken(ctx context.Context, customerID uint, assetTyp
// 根据资产标识符查找或创建测试客户并直接签发 JWT无需微信 OAuth
// ⚠️ 仅限 logging.development=true 时由路由层暴露,严禁生产环境调用
func (s *Service) DevLogin(ctx context.Context, identifier string) (string, uint, bool, error) {
assetType, assetID, err := s.resolveAsset(ctx, identifier)
assetType, assetID, _, err := s.resolveAsset(ctx, identifier)
if err != nil {
return "", 0, false, err
}