fix: 资产钱包自动创建机制 — 修复C端购买时钱包不存在报错
All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 7m8s

- client_order: 新增 getOrCreateWallet 兜底,钱包不存在时自动创建
- device_import: 设备导入事务内同步创建设备钱包
- iot_card_import: IoT卡批量导入后批量创建卡钱包
- queue/handler: 传递 AssetWalletStore 给两个导入 handler
- migration 000098: 为存量IoT卡和设备补建资产钱包
This commit is contained in:
2026-03-30 11:37:41 +08:00
parent 40809d11c5
commit f339fb1987
36 changed files with 1811 additions and 26 deletions

View File

@@ -333,12 +333,9 @@ func (s *Service) createForceRechargeOrder(
return nil, err
}
wallet, err := s.walletStore.GetByResourceTypeAndID(ctx, resourceType, resourceID)
wallet, err := s.getOrCreateWallet(ctx, resourceType, resourceID, resolveSellerShopID(validationResult))
if err != nil {
if err == gorm.ErrRecordNotFound {
return nil, errors.New(errors.CodeWalletNotFound, "钱包不存在")
}
return nil, errors.Wrap(errors.CodeDatabaseError, err, "查询资产钱包失败")
return nil, err
}
linkedPackageIDs, err := sonic.Marshal(extractPackageIDs(validationResult.Packages))
@@ -558,6 +555,46 @@ func buildLinkedPackageInfo(result *purchase_validation.PurchaseValidationResult
}
}
// getOrCreateWallet 获取或自动创建资产钱包
// 兜底机制:当钱包不存在时自动创建,避免因钱包未提前创建导致业务中断
func (s *Service) getOrCreateWallet(ctx context.Context, resourceType string, resourceID uint, shopIDTag uint) (*model.AssetWallet, error) {
wallet, err := s.walletStore.GetByResourceTypeAndID(ctx, resourceType, resourceID)
if err == nil {
return wallet, nil
}
if err != gorm.ErrRecordNotFound {
return nil, errors.Wrap(errors.CodeDatabaseError, err, "查询资产钱包失败")
}
// 钱包不存在,自动创建空钱包
s.logger.Info("资产钱包不存在,自动创建",
zap.String("resource_type", resourceType),
zap.Uint("resource_id", resourceID),
zap.Uint("shop_id_tag", shopIDTag),
)
newWallet := &model.AssetWallet{
ResourceType: resourceType,
ResourceID: resourceID,
Balance: 0,
FrozenBalance: 0,
Currency: "CNY",
Status: constants.AssetWalletStatusNormal,
Version: 0,
ShopIDTag: shopIDTag,
}
if createErr := s.walletStore.Create(ctx, newWallet); createErr != nil {
return nil, errors.Wrap(errors.CodeDatabaseError, createErr, "自动创建资产钱包失败")
}
// 重新查询获取完整数据(含数据库生成的字段)
wallet, err = s.walletStore.GetByResourceTypeAndID(ctx, resourceType, resourceID)
if err != nil {
return nil, errors.Wrap(errors.CodeDatabaseError, err, "查询资产钱包失败")
}
return wallet, nil
}
func resolveWalletResource(result *purchase_validation.PurchaseValidationResult) (string, uint, error) {
if result.Card != nil {
return constants.AssetWalletResourceTypeIotCard, result.Card.ID, nil