Files
junhong_cmp_fiber/internal/bootstrap/services.go
邹进 96771a204f
Some checks failed
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Has been cancelled
feat: 卡流量改为日快照计量并统一停复机规则
卡流量计量(按名单灰度,默认 off):
- 新增卡日快照与切换水位表(000241),按通道上游流量重置日换算自然月、重置日防旧值
- 已切换的卡按月对账产生增量,无生效中套餐只结算不发事件;第一次切换写水位
- 已切换卡读数有效即判定通道阈值,卡表本月用量用快照覆盖,日流量读快照
- 配置 JUNHONG_TRAFFIC_CALC_MODE/CARDS、JUNHONG_TRAFFIC_FLOW_SNAPSHOT_ENABLED

停复机规则(总开关 JUNHONG_STOP_RESUME_UNIFIED_RULE_ENABLED,默认关闭):
- 复机不看停机原因,持通道阈值锁仍拒绝;暂停轮询的卡不自动停复机
- 通道新增实名管控 realname_control_enabled(000242,默认 0),开启后不区分行业卡与实名策略
- 实名管控从 0 改 1 需确认,修改并入通道更新审计

OpenSpec Change: rebuild-card-traffic-metering-and-stop-resume
2026-10-20 17:49:26 +09:00

576 lines
33 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package bootstrap
import (
"context"
"go.uber.org/zap"
agentrechargeApp "github.com/break/junhong_cmp_fiber/internal/application/agentrecharge"
approvalApp "github.com/break/junhong_cmp_fiber/internal/application/approval"
assetAutoRenewalApp "github.com/break/junhong_cmp_fiber/internal/application/assetautorenewal"
cardObservationApp "github.com/break/junhong_cmp_fiber/internal/application/cardobservation"
carrierThresholdApp "github.com/break/junhong_cmp_fiber/internal/application/carrierthreshold"
distributionwithdrawalApp "github.com/break/junhong_cmp_fiber/internal/application/distributionwithdrawal"
employeecollectionApp "github.com/break/junhong_cmp_fiber/internal/application/employeecollection"
exchangeApp "github.com/break/junhong_cmp_fiber/internal/application/exchange"
merchantpayment "github.com/break/junhong_cmp_fiber/internal/application/merchantpayment"
packagetrafficalertapp "github.com/break/junhong_cmp_fiber/internal/application/packagetrafficalert"
refundapprovalApp "github.com/break/junhong_cmp_fiber/internal/application/refundapproval"
refundchannelApp "github.com/break/junhong_cmp_fiber/internal/application/refundchannel"
walletapp "github.com/break/junhong_cmp_fiber/internal/application/wallet"
approvalInfra "github.com/break/junhong_cmp_fiber/internal/infrastructure/approval"
auditInfra "github.com/break/junhong_cmp_fiber/internal/infrastructure/audit"
cardObservationInfra "github.com/break/junhong_cmp_fiber/internal/infrastructure/cardobservation"
exchangeInfra "github.com/break/junhong_cmp_fiber/internal/infrastructure/exchange"
"github.com/break/junhong_cmp_fiber/internal/infrastructure/integrationlog"
"github.com/break/junhong_cmp_fiber/internal/infrastructure/messaging/outbox"
paymentInfra "github.com/break/junhong_cmp_fiber/internal/infrastructure/payment"
prioritypollingInfra "github.com/break/junhong_cmp_fiber/internal/infrastructure/prioritypolling"
walletinfra "github.com/break/junhong_cmp_fiber/internal/infrastructure/wallet"
wecomInfra "github.com/break/junhong_cmp_fiber/internal/infrastructure/wecom"
"github.com/break/junhong_cmp_fiber/internal/polling"
assetAutoRenewalQuery "github.com/break/junhong_cmp_fiber/internal/query/assetautorenewal"
accountSvc "github.com/break/junhong_cmp_fiber/internal/service/account"
agentOpenAPISvc "github.com/break/junhong_cmp_fiber/internal/service/agent_open_api"
assetAllocationRecordSvc "github.com/break/junhong_cmp_fiber/internal/service/asset_allocation_record"
assetAuditSvc "github.com/break/junhong_cmp_fiber/internal/service/asset_audit"
authSvc "github.com/break/junhong_cmp_fiber/internal/service/auth"
carrierSvc "github.com/break/junhong_cmp_fiber/internal/service/carrier"
clientAuthSvc "github.com/break/junhong_cmp_fiber/internal/service/client_auth"
commissionCalculationSvc "github.com/break/junhong_cmp_fiber/internal/service/commission_calculation"
commissionStatsSvc "github.com/break/junhong_cmp_fiber/internal/service/commission_stats"
commissionWithdrawalSvc "github.com/break/junhong_cmp_fiber/internal/service/commission_withdrawal"
commissionWithdrawalSettingSvc "github.com/break/junhong_cmp_fiber/internal/service/commission_withdrawal_setting"
customerBindingSvc "github.com/break/junhong_cmp_fiber/internal/service/customer_binding"
"github.com/break/junhong_cmp_fiber/internal/store/postgres"
"github.com/break/junhong_cmp_fiber/pkg/config"
"github.com/break/junhong_cmp_fiber/pkg/constants"
"github.com/break/junhong_cmp_fiber/pkg/payment"
"github.com/break/junhong_cmp_fiber/pkg/queue"
"github.com/break/junhong_cmp_fiber/pkg/wechat"
assetSvc "github.com/break/junhong_cmp_fiber/internal/service/asset"
assetPackageBatchOrderSvc "github.com/break/junhong_cmp_fiber/internal/service/asset_package_batch_order"
assetWalletSvc "github.com/break/junhong_cmp_fiber/internal/service/asset_wallet"
deviceSvc "github.com/break/junhong_cmp_fiber/internal/service/device"
deviceImportSvc "github.com/break/junhong_cmp_fiber/internal/service/device_import"
enterpriseSvc "github.com/break/junhong_cmp_fiber/internal/service/enterprise"
enterpriseCardSvc "github.com/break/junhong_cmp_fiber/internal/service/enterprise_card"
enterpriseDeviceSvc "github.com/break/junhong_cmp_fiber/internal/service/enterprise_device"
exchangeSvc "github.com/break/junhong_cmp_fiber/internal/service/exchange"
exportTaskSvc "github.com/break/junhong_cmp_fiber/internal/service/export_task"
iotCardSvc "github.com/break/junhong_cmp_fiber/internal/service/iot_card"
iotCardImportSvc "github.com/break/junhong_cmp_fiber/internal/service/iot_card_import"
orderSvc "github.com/break/junhong_cmp_fiber/internal/service/order"
packageSvc "github.com/break/junhong_cmp_fiber/internal/service/package"
packageSeriesSvc "github.com/break/junhong_cmp_fiber/internal/service/package_series"
permissionSvc "github.com/break/junhong_cmp_fiber/internal/service/permission"
personalCustomerSvc "github.com/break/junhong_cmp_fiber/internal/service/personal_customer"
purchaseValidationSvc "github.com/break/junhong_cmp_fiber/internal/service/purchase_validation"
rechargeSvc "github.com/break/junhong_cmp_fiber/internal/service/recharge"
roleSvc "github.com/break/junhong_cmp_fiber/internal/service/role"
shopSvc "github.com/break/junhong_cmp_fiber/internal/service/shop"
agentRechargeSvc "github.com/break/junhong_cmp_fiber/internal/service/agent_recharge"
operationPasswordSvc "github.com/break/junhong_cmp_fiber/internal/service/operation_password"
orderPackageInvalidateSvc "github.com/break/junhong_cmp_fiber/internal/service/order_package_invalidate"
phoneAssetAssociationSvc "github.com/break/junhong_cmp_fiber/internal/service/phone_asset_association"
pollingSvc "github.com/break/junhong_cmp_fiber/internal/service/polling"
refundSvc "github.com/break/junhong_cmp_fiber/internal/service/refund"
shopBusinessOwnerImportSvc "github.com/break/junhong_cmp_fiber/internal/service/shop_business_owner_import"
shopCommissionSvc "github.com/break/junhong_cmp_fiber/internal/service/shop_commission"
shopPackageBatchAllocationSvc "github.com/break/junhong_cmp_fiber/internal/service/shop_package_batch_allocation"
shopPackageBatchPricingSvc "github.com/break/junhong_cmp_fiber/internal/service/shop_package_batch_pricing"
shopSeriesGrantSvc "github.com/break/junhong_cmp_fiber/internal/service/shop_series_grant"
trafficSvc "github.com/break/junhong_cmp_fiber/internal/service/traffic"
wechatConfigSvc "github.com/break/junhong_cmp_fiber/internal/service/wechat_config"
)
type services struct {
AccessAudit *auditInfra.Writer
Approval *approvalApp.CreationService
Account *accountSvc.Service
AssetAudit *assetAuditSvc.Service
Role *roleSvc.Service
Permission *permissionSvc.Service
PersonalCustomer *personalCustomerSvc.Service
ClientAuth *clientAuthSvc.Service
Shop *shopSvc.Service
Auth *authSvc.Service
ShopCommission *shopCommissionSvc.Service
DistributionRegistration *distributionwithdrawalApp.RegistrationService
WithdrawalQualification *distributionwithdrawalApp.QualificationService
WithdrawalApproval *distributionwithdrawalApp.WithdrawalService
CommissionWithdrawal *commissionWithdrawalSvc.Service
CommissionWithdrawalSetting *commissionWithdrawalSettingSvc.Service
CommissionCalculation *commissionCalculationSvc.Service
Enterprise *enterpriseSvc.Service
EnterpriseCard *enterpriseCardSvc.Service
EnterpriseDevice *enterpriseDeviceSvc.Service
Authorization *enterpriseCardSvc.AuthorizationService
IotCard *iotCardSvc.Service
IotCardImport *iotCardImportSvc.Service
ExportTask *exportTaskSvc.Service
Device *deviceSvc.Service
DeviceImport *deviceImportSvc.Service
AssetAllocationRecord *assetAllocationRecordSvc.Service
Carrier *carrierSvc.Service
PackageSeries *packageSeriesSvc.Service
Package *packageSvc.Service
PackageDailyRecord *packageSvc.DailyRecordService
PackageCustomerView *packageSvc.CustomerViewService
PackageTrafficAlertRule *packagetrafficalertapp.RuleService
AssetAutoRenewal *assetAutoRenewalApp.Service
ShopPackageBatchAllocation *shopPackageBatchAllocationSvc.Service
ShopPackageBatchPricing *shopPackageBatchPricingSvc.Service
ShopSeriesGrant *shopSeriesGrantSvc.Service
CommissionStats *commissionStatsSvc.Service
PurchaseValidation *purchaseValidationSvc.Service
Order *orderSvc.Service
Exchange *exchangeSvc.Service
Recharge *rechargeSvc.Service
PollingConfig *pollingSvc.ConfigService
PollingConcurrency *pollingSvc.ConcurrencyService
PollingMonitoring *pollingSvc.MonitoringService
PollingAlert *pollingSvc.AlertService
PollingCleanup *pollingSvc.CleanupService
PollingManualTrigger *pollingSvc.ManualTriggerService
PriorityPolling *pollingSvc.PriorityManualService
Asset *assetSvc.Service
AssetLifecycle *assetSvc.LifecycleService
AssetWallet *assetWalletSvc.Service
StopResumeService *iotCardSvc.StopResumeService
WechatConfig *wechatConfigSvc.Service
AgentRecharge *agentRechargeSvc.Service
AgentRechargeOnline *agentrechargeApp.OnlineCreationService
AgentRechargePaymentConfirm *agentrechargeApp.ConfirmOnlinePaymentService
AgentRechargeVoucherOCR *agentrechargeApp.PaymentVoucherOCRService
PackageActivation *packageSvc.ActivationService
Refund *refundSvc.Service
TrafficQuery *trafficSvc.QueryService
OperationPassword *operationPasswordSvc.Service
AgentOpenAPI *agentOpenAPISvc.Service
CustomerBinding *customerBindingSvc.Service
OrderPackageInvalidate *orderPackageInvalidateSvc.Service
AssetPackageBatchOrder *assetPackageBatchOrderSvc.Service
ShopBusinessOwnerImport *shopBusinessOwnerImportSvc.Service
PhoneAssetAssociation *phoneAssetAssociationSvc.Service
ObservationSeries cardObservationApp.BestEffortSeriesDispatcher
CardObservation *cardObservationApp.Service
CardObservationSeries *cardObservationApp.SeriesAttemptService
}
func initServices(s *stores, deps *Dependencies) *services {
// CustomerBinding 模块依赖最少,最先初始化
customerBinding := customerBindingSvc.New(deps.DB, s.IotCard, s.Device)
purchaseValidation := purchaseValidationSvc.New(deps.DB, s.IotCard, s.Device, s.Package, s.ShopPackageAllocation)
assetAudit := assetAuditSvc.NewService(s.AssetOperationLog, deps.DB)
auditWriter := auditInfra.NewWriter(auditInfra.NewRegistry(), nil)
customerBinding.SetAccessAudit(auditWriter)
account := accountSvc.New(s.Account, s.Role, s.AccountRole, s.ShopRole, s.Shop, s.Enterprise)
account.SetLifecycleAudit(deps.DB, auditWriter)
account.SetAccessAudit(deps.DB, deps.Redis, auditWriter)
account.SetTokenManager(deps.TokenManager)
authService := authSvc.New(s.Account, s.AccountRole, s.RolePermission, s.Permission, s.Shop, deps.TokenManager, deps.Logger)
authService.SetSecurityAudit(deps.DB, auditWriter)
// 创建 IotCard service 并设置回调
iotCard := iotCardSvc.New(
deps.DB,
s.IotCard,
s.Shop,
s.AssetAllocationRecord,
s.ShopPackageAllocation,
s.ShopSeriesAllocation,
s.PackageSeries,
deps.GatewayClient,
deps.Logger,
)
iotCard.SetAccessAudit(auditWriter)
cardObservationOutbox := outbox.NewRepository()
observationSeriesEvents := cardObservationInfra.NewSeriesEventWriter(cardObservationOutbox)
priorityEvents := prioritypollingInfra.NewPriorityEventWriter(cardObservationOutbox)
// 运营商通道流量阈值用例:达量判定嵌入流量观测事务,持锁判定注入停复机入口。
carrierThresholdService := carrierThresholdApp.NewService(deps.DB, cardObservationOutbox).SetLogger(deps.Logger)
cardObservationService := cardObservationApp.NewService(
deps.DB,
cardObservationInfra.NewEventWriter(cardObservationOutbox),
cardObservationInfra.NewCacheInvalidator(deps.Redis, deps.Logger),
)
cardObservationService.SetStateAuditWriter(iotCard)
// 运营商通道流量阈值达量判定嵌入流量观测事务:与卡流量事实同事务写周期锁与停机事件。
cardObservationService.SetChannelThresholdEvaluator(carrierThresholdService)
// 卡流量计量切换策略:启动时展开灰度名单为内存卡集合,API 与全部 Worker 必须使用一致配置。
var trafficCalcPolicy *cardObservationApp.TrafficCalcPolicy
if cfg := config.Get(); cfg != nil {
trafficCalcPolicy = cardObservationApp.BuildTrafficCalcPolicy(context.Background(), deps.DB, cfg.TrafficCalc, deps.Logger)
}
cardObservationService.SetTrafficCalcPolicy(trafficCalcPolicy, deps.Logger)
iotCard.SetCardObservationService(cardObservationService)
iotCard.SetSpeedTierIntegrationLog(integrationlog.NewRepository(deps.DB))
seriesCoordinator := cardObservationInfra.NewSeriesCoordinator(deps.Redis)
seriesIntegration := integrationlog.NewRepository(deps.DB)
seriesTrigger := cardObservationApp.NewSeriesTrigger(
seriesCoordinator,
queue.NewCardObservationSeriesScheduler(deps.QueueClient),
cardObservationInfra.NewSeriesAttemptLogger(seriesIntegration),
)
cardObservationSeries := cardObservationApp.NewSeriesAttemptService(
seriesCoordinator,
cardObservationInfra.NewSeriesRunner(deps.DB, deps.GatewayClient, cardObservationService, seriesIntegration, auditWriter),
cardObservationInfra.NewSeriesAttemptLogger(seriesIntegration),
)
observationSeries := cardObservationInfra.NewBestEffortSeriesDispatcher(seriesTrigger, deps.Logger, s.DeviceSimBinding, s.Carrier)
iotCard.SetObservationSeriesDispatcher(observationSeries)
// 使用 PollingLifecycleService 替代 APICallback:通过分片队列准确操作(修复 api_callback.go 遗漏 protect 队列的 Bug3)
pollingConfigStore := postgres.NewPollingConfigStore(deps.DB)
pollingConfigMgr := polling.NewPollingConfigManager(pollingConfigStore, deps.Redis, deps.Logger)
if err := pollingConfigMgr.Load(context.Background()); err != nil {
deps.Logger.Warn("API 进程加载轮询配置失败", zap.Error(err))
}
pollingConfigMgr.Start(context.Background())
pollingQueueMgr := polling.NewPollingQueueManager(deps.Redis, constants.PollingShardCount, deps.Logger)
pollingLifecycleSvc := polling.NewPollingLifecycleService(pollingQueueMgr, pollingConfigMgr, s.IotCard, s.DeviceSimBinding, s.Device, deps.Logger)
iotCard.SetPollingCallback(pollingLifecycleSvc)
// 创建支付配置服务(Order 和 Recharge 依赖)
wechatConfig := wechatConfigSvc.New(s.WechatConfig, s.Order, s.RechargeOrder, s.AgentRecharge, s.Payment, auditWriter, deps.Redis, deps.Logger)
// 创建支付配置动态加载器(Order 和 Recharge 依赖)
paymentLoader := payment.NewPaymentConfigLoader(s.WechatConfig, deps.Redis, deps.Logger)
packageActivation := packageSvc.NewActivationService(
deps.DB,
deps.Redis,
s.PackageUsage,
s.Package,
s.PackageUsageDailyRecord,
deps.Logger,
)
packageActivation.SetLifecycleAudit(auditWriter)
packageActivation.SetObservationSeriesEventWriter(observationSeriesEvents)
packageActivation.SetPriorityEventWriter(priorityEvents)
stopResumeService := iotCardSvc.NewStopResumeService(
deps.Redis,
s.IotCard,
s.PackageUsage,
s.DeviceSimBinding,
deps.GatewayClient,
deps.Logger,
)
stopResumeService.SetPollingCallback(pollingLifecycleSvc)
stopResumeService.SetObservationSeriesEventWriter(deps.DB, observationSeriesEvents)
stopResumeService.SetPriorityEventWriter(priorityEvents)
stopResumeService.SetUnifiedAudit(auditWriter, integrationlog.NewRepository(deps.DB))
// 持通道阈值锁的卡在周期内拒绝一切复机(自动、手动、保护期强制、机卡分离)。
stopResumeService.SetChannelThresholdLockGuard(carrierThresholdService)
iotCard.SetRealnameActivator(packageActivation)
iotCard.SetStopResumeService(stopResumeService)
iotCard.SetDeviceSimBindingStore(s.DeviceSimBinding)
iotCard.SetEnterpriseCardAuthStore(s.EnterpriseCardAuthorization)
iotCard.SetEnterpriseStore(s.Enterprise)
iotCard.SetPhoneAssetAssociationStore(s.PhoneAssetAssociation)
iotCard.SetRedisClient(deps.Redis)
device := deviceSvc.New(
deps.DB,
deps.Redis,
s.Device,
s.DeviceSimBinding,
s.IotCard,
s.Shop,
s.AssetAllocationRecord,
s.ShopPackageAllocation,
s.ShopSeriesAllocation,
s.PackageSeries,
deps.GatewayClient,
s.AssetIdentifier,
s.EnterpriseDeviceAuthorization,
s.Enterprise,
)
device.SetAccessAudit(auditWriter)
device.SetPhoneAssetAssociationStore(s.PhoneAssetAssociation)
device.SetGatewayIntegrationLog(integrationlog.NewRepository(deps.DB))
device.SetObservationSeriesEventWriter(observationSeriesEvents)
device.SetObservationSeriesDispatcher(observationSeries)
operationPassword := operationPasswordSvc.New(deps.Redis)
shopCommission := shopCommissionSvc.New(s.Shop, s.Account, s.AgentWallet, s.CommissionWithdrawalRequest, s.CommissionWithdrawalSetting, s.CommissionRecord, s.AgentWalletTransaction, deps.DB, deps.Logger)
shopCommission.SetAuditWriter(auditWriter)
packageService := packageSvc.New(s.Package, s.PackageSeries, s.ShopPackageAllocation, s.ShopSeriesAllocation)
packageService.SetAccessAudit(deps.DB, auditWriter)
packageSeriesService := packageSeriesSvc.New(s.PackageSeries, s.ShopSeriesAllocation, s.Package)
packageSeriesService.SetAccessAudit(deps.DB, auditWriter)
orderService := orderSvc.New(deps.DB, deps.Redis, s.Order, s.OrderItem, s.AgentWallet, s.AssetWallet, s.Payment, purchaseValidation, s.ShopPackageAllocation, s.ShopSeriesAllocation, s.IotCard, s.Device, s.PackageSeries, s.PackageUsage, s.Package, wechatConfig, deps.WechatPayment, paymentLoader, deps.QueueClient, deps.Logger, s.AssetIdentifier, s.PersonalCustomer, s.PersonalCustomerPhone)
// 员工代收款建账用例在订单、充值入账与退款冲销的事务内复用同一实例。
employeeCollectionBillCreation := employeecollectionApp.NewBillCreationService(auditWriter)
orderService.SetEmployeeCollectionBillCreation(employeeCollectionBillCreation)
orderService.SetResumeCallback(stopResumeService)
orderService.SetLifecycleAudit(auditWriter)
orderService.SetPaymentIntegrationLog(integrationlog.NewRepository(deps.DB))
orderService.SetObservationSeriesEventWriter(observationSeriesEvents)
orderService.SetPriorityEventWriter(priorityEvents)
walletOutbox := outbox.NewRepository()
walletDebitEvents := walletinfra.NewDebitEventWriter(walletOutbox, auditWriter)
orderService.SetAgentWalletDebitService(walletapp.NewDebitService(walletDebitEvents, nil))
orderService.SetAgentWalletReservationService(walletapp.NewReservationService(walletinfra.NewReservationEventWriter(walletOutbox, auditWriter), walletDebitEvents, nil))
agentRechargeService := agentRechargeSvc.New(
deps.DB,
s.AgentRecharge,
s.AgentWallet,
s.Shop,
wechatConfig,
operationPassword,
deps.Redis,
deps.Logger,
)
agentWalletPosting := walletapp.NewPostingService(walletinfra.NewCreditEventWriter(walletOutbox, auditWriter), nil)
agentRechargeService.SetAgentWalletPostingService(agentWalletPosting)
paymentIntegration := integrationlog.NewRepository(deps.DB)
agentRechargeOnline := agentrechargeApp.NewOnlineCreationService(
deps.DB,
merchantpayment.NewRuntimeLoader(deps.DB, deps.Redis),
paymentInfra.NewWechatWebAdapter(wechat.NewRedisCache(deps.Redis), paymentIntegration, deps.Logger),
paymentInfra.NewAlipayWapAdapter(paymentIntegration, deps.Logger),
paymentInfra.NewFuiouScanAdapter(paymentIntegration, deps.Logger),
auditWriter,
)
agentRechargePaymentConfirm := agentrechargeApp.NewConfirmOnlinePaymentService(
deps.DB,
paymentInfra.NewAgentRechargePaymentEventWriter(outbox.NewRepository()),
auditWriter,
)
// 付款凭证识别需要对象存储与 Gateway;任一缺失时不装配,接口统一返回能力未配置。
var agentRechargeVoucherOCR *agentrechargeApp.PaymentVoucherOCRService
if deps.StorageService != nil && deps.GatewayClient != nil {
agentRechargeVoucherOCR = agentrechargeApp.NewPaymentVoucherOCRService(deps.StorageService.Provider(), deps.GatewayClient)
}
refundService := refundSvc.New(
deps.DB,
s.RefundRequest,
s.Order,
s.CommissionRecord,
s.AgentWallet,
s.AgentWalletTransaction,
stopResumeService,
device,
packageActivation,
s.IotCard,
s.Device,
s.AssetWallet,
deps.Logger,
)
refundService.SetAgentWalletRefundService(walletapp.NewRefundService(walletinfra.NewRefundEventWriter(walletOutbox), nil))
refundService.SetNotificationOutbox(walletOutbox)
refundService.SetPaymentMerchantRuntime(merchantpayment.NewRuntimeLoader(deps.DB, deps.Redis))
refundService.SetLifecycleAudit(auditWriter)
// 渠道原路退款的登记与执行共用同一用例:API 侧只登记待执行事实与可靠事件,
// 真正的渠道调用由 Worker 消费该事件执行。
refundService.SetChannelRefundService(
refundchannelApp.NewService(
deps.DB,
merchantpayment.NewRuntimeLoader(deps.DB, deps.Redis),
paymentInfra.NewRefundAdapter(wechat.NewRedisCache(deps.Redis), deps.Logger),
auditWriter,
).SetLogger(deps.Logger).SetCompletionNotifier(refundService),
)
exchangeService := exchangeSvc.New(deps.DB, s.ExchangeOrder, s.IotCard, s.Device, s.AssetWallet, s.AssetWalletTransaction, s.PackageUsage, s.PackageUsageDailyRecord, s.ResourceTag, customerBinding, deps.Logger)
exchangeService.SetShippingCreatedNotifier(exchangeApp.NewShippingCreatedNotifier(exchangeInfra.NewShippingNotificationWriter(outbox.NewRepository())))
exchangeService.SetAccessAudit(auditWriter)
exchangeService.SetPhoneAssetAssociationStore(s.PhoneAssetAssociation)
assetService := assetSvc.New(deps.DB, s.Device, s.IotCard, s.PackageUsage, s.Package, s.PackageSeries, s.DeviceSimBinding, s.Shop, deps.Redis, iotCard, deps.GatewayClient, s.AssetIdentifier, s.Order, s.OrderItem, s.ExchangeOrder)
assetService.SetPhoneAssetAssociationStore(s.PhoneAssetAssociation)
assetService.SetAccessAudit(auditWriter)
agentOpenAPI := agentOpenAPISvc.New(assetService, packageService, orderService, shopCommission, stopResumeService, device, s.IotCard, s.PackageUsage, s.Package, s.PackageSeries, s.AgentWallet, s.DeviceSimBinding, s.Device)
wecomApplicationRepository := wecomInfra.NewApplicationRepository(deps.DB)
wecomSceneRepository := wecomInfra.NewSceneRepository(deps.DB)
wecomMemberRepository := wecomInfra.NewMemberRepository(deps.DB)
wecomBaseURL := ""
wecomTimeout := constants.WeComDefaultHTTPTimeout
if cfg := config.Get(); cfg != nil {
wecomBaseURL = cfg.WeCom.BaseURL
wecomTimeout = cfg.WeCom.Timeout
}
wecomIntegrationRepository := integrationlog.NewRepository(deps.DB)
wecomTokenProvider := wecomInfra.NewTokenProvider(
wecomApplicationRepository, deps.Redis, wecomIntegrationRepository,
wecomBaseURL, wecomTimeout, deps.Logger,
)
approvalCreationService := approvalApp.NewCreationService(
wecomInfra.NewApprovalProvider(
deps.DB, wecomSceneRepository, wecomApplicationRepository, wecomMemberRepository,
wecomInfra.NewTemplateClient(wecomTokenProvider, wecomIntegrationRepository, wecomBaseURL, wecomTimeout),
),
approvalInfra.NewRepositoryProvider(),
approvalInfra.NewSubmissionEventWriter(outbox.NewRepository()),
nil,
)
approvalCreationService.SetAuditWriter(auditWriter)
refundService.SetRefundApprovalCreationService(
refundapprovalApp.NewCreationService(deps.DB, approvalCreationService, auditWriter),
)
agentRechargeService.SetOfflineCreationService(
agentrechargeApp.NewOfflineCreationService(deps.DB, approvalCreationService, auditWriter),
)
agentRechargeService.SetRechargeAudit(auditWriter)
agentRechargeService.SetEmployeeCollectionBillCreation(employeeCollectionBillCreation)
refundService.SetEmployeeCollectionRefundOffset(
employeecollectionApp.NewRefundOffsetService(auditWriter),
)
recoveryPort := approvalInfra.NewRecoveryPort(deps.DB, deps.QueueClient)
refundApprovalUseCase := refundapprovalApp.NewRecoveryService(deps.DB, recoveryPort, auditWriter)
refundService.SetRefundApprovalRecoveryService(recoveryPort)
refundService.SetRefundApprovalRecoveryUseCase(refundApprovalUseCase)
roleService := roleSvc.New(s.Role, s.Permission, s.RolePermission, s.AccountRole, s.ShopRole)
roleService.SetAccessAudit(deps.DB, deps.Redis, auditWriter)
permissionService := permissionSvc.New(s.Permission, s.AccountRole, s.RolePermission, account, deps.Redis)
permissionService.SetAccessAudit(deps.DB, auditWriter)
shopService := shopSvc.New(s.Shop, s.Account, s.ShopRole, s.Role)
shopService.SetAccessAudit(deps.DB, deps.Redis, auditWriter)
commissionWithdrawal := commissionWithdrawalSvc.New(deps.DB, s.Shop, s.Account, s.AgentWallet, s.AgentWalletTransaction, s.CommissionWithdrawalRequest)
commissionWithdrawal.SetAuditWriter(auditWriter)
// 代理分销注册、提现资格与提现终审共用同一审计 Writer 与通用审批创建接缝。
distributionRegistration := distributionwithdrawalApp.NewRegistrationService(
deps.DB, deps.VerificationService, approvalCreationService, auditWriter,
)
distributionRegistration.SetRecoveryPort(recoveryPort)
withdrawalQualification := distributionwithdrawalApp.NewQualificationService(
deps.DB, approvalCreationService, auditWriter,
)
withdrawalApproval := distributionwithdrawalApp.NewWithdrawalService(
deps.DB, approvalCreationService, auditWriter,
)
shopCommission.SetWithdrawalApprovalService(withdrawalApproval)
shopService.SetWithdrawalQualificationInvalidator(withdrawalQualification)
commissionCalculation := commissionCalculationSvc.New(
deps.DB,
s.CommissionRecord,
s.Shop,
s.ShopPackageAllocation,
s.ShopSeriesAllocation,
s.PackageSeries,
s.IotCard,
s.Device,
s.AgentWallet,
s.AgentWalletTransaction,
s.Order,
s.OrderItem,
s.Package,
s.ShopSeriesCommissionStats,
commissionStatsSvc.New(s.ShopSeriesCommissionStats),
deps.Logger,
)
commissionCalculation.SetAuditWriter(auditWriter)
pollingConfigService := pollingSvc.NewConfigService(s.PollingConfig, deps.Redis, deps.Logger)
pollingConfigService.SetAudit(deps.DB, auditWriter)
pollingConcurrencyService := pollingSvc.NewConcurrencyService(s.PollingConcurrencyConfig, deps.Redis)
pollingConcurrencyService.SetAudit(deps.DB, auditWriter)
pollingAlertService := pollingSvc.NewAlertService(s.PollingAlertRule, s.PollingAlertHistory, deps.Redis, deps.Logger)
pollingAlertService.SetAudit(deps.DB, auditWriter)
pollingManualTriggerService := pollingSvc.NewManualTriggerService(s.PollingManualTriggerLog, s.IotCard, deps.Redis, deps.Logger)
pollingManualTriggerService.SetAudit(deps.DB, auditWriter)
// 人工优先轮询入口:入队、人工关闭与人工重触发;与人工触发共用同包权限判定,
// 但使用独立的优先提示通道与合并语义。
priorityPollingService := pollingSvc.NewPriorityManualService(
deps.DB, s.IotCard, s.PollingPriorityItem, pollingQueueMgr, deps.Logger,
)
priorityPollingService.SetAudit(auditWriter)
return &services{
AccessAudit: auditWriter,
Approval: approvalCreationService,
Account: account,
AssetAudit: assetAudit,
Role: roleService,
Permission: permissionService,
PersonalCustomer: personalCustomerSvc.NewService(deps.DB, s.PersonalCustomer, s.PersonalCustomerPhone, deps.Logger, auditWriter),
ClientAuth: clientAuthSvc.New(
deps.DB,
s.PersonalCustomerOpenID,
s.PersonalCustomer,
s.PersonalCustomerPhone,
s.PhoneAssetAssociation,
s.IotCard,
s.Device,
wechatConfig,
deps.VerificationService,
deps.JWTManager,
deps.Redis,
deps.Logger,
customerBinding,
auditWriter,
),
Shop: shopService,
Auth: authService,
ShopCommission: shopCommission,
DistributionRegistration: distributionRegistration,
WithdrawalQualification: withdrawalQualification,
WithdrawalApproval: withdrawalApproval,
CommissionWithdrawal: commissionWithdrawal,
CommissionWithdrawalSetting: commissionWithdrawalSettingSvc.New(deps.DB, s.Account, s.CommissionWithdrawalSetting),
CommissionCalculation: commissionCalculation,
Enterprise: enterpriseSvc.New(deps.DB, s.Enterprise, s.Shop, s.Account, auditWriter),
EnterpriseCard: enterpriseCardSvc.New(deps.DB, s.Enterprise, s.EnterpriseCardAuthorization, s.IotCard, auditWriter),
EnterpriseDevice: enterpriseDeviceSvc.New(deps.DB, s.Enterprise, s.Device, s.DeviceSimBinding, s.EnterpriseDeviceAuthorization, s.EnterpriseCardAuthorization, deps.Logger, auditWriter),
Authorization: enterpriseCardSvc.NewAuthorizationService(deps.DB, s.Enterprise, s.IotCard, s.EnterpriseCardAuthorization, deps.Logger, auditWriter),
IotCard: iotCard,
IotCardImport: iotCardImportSvc.New(deps.DB, s.IotCardImportTask, deps.QueueClient, auditWriter),
ExportTask: exportTaskSvc.New(deps.DB, s.ExportTask, deps.QueueClient, deps.StorageService, auditWriter),
Device: device,
DeviceImport: deviceImportSvc.New(deps.DB, s.DeviceImportTask, deps.QueueClient, auditWriter),
AssetAllocationRecord: assetAllocationRecordSvc.New(deps.DB, s.AssetAllocationRecord, s.Shop, s.Account),
Carrier: carrierSvc.New(s.Carrier, auditWriter),
PackageSeries: packageSeriesService,
Package: packageService,
PackageDailyRecord: packageSvc.NewDailyRecordService(deps.DB, deps.Redis, s.PackageUsageDailyRecord, deps.Logger),
PackageCustomerView: packageSvc.NewCustomerViewService(deps.DB, deps.Redis, s.PackageUsage, deps.Logger),
PackageTrafficAlertRule: packagetrafficalertapp.NewRuleService(deps.DB, s.PackageTrafficAlert, auditWriter),
AssetAutoRenewal: assetAutoRenewalApp.NewService(assetAutoRenewalApp.Dependencies{
DB: deps.DB, Redis: deps.Redis, Logger: deps.Logger,
Outbox: outbox.NewRepository(), AuditWriter: auditWriter,
PurchaseValidation: purchaseValidation,
Candidates: assetAutoRenewalQuery.NewQuery(deps.DB),
}),
ShopPackageBatchAllocation: shopPackageBatchAllocationSvc.New(deps.DB, s.Package, s.ShopPackageAllocation, s.ShopSeriesAllocation, s.Shop, auditWriter),
ShopPackageBatchPricing: shopPackageBatchPricingSvc.New(deps.DB, s.ShopPackageAllocation, s.ShopPackageAllocationPriceHistory, s.Shop, auditWriter),
ShopSeriesGrant: shopSeriesGrantSvc.New(deps.DB, s.ShopSeriesAllocation, s.ShopPackageAllocation, s.ShopPackageAllocationPriceHistory, s.Shop, s.Package, s.PackageSeries, deps.Logger, auditWriter),
CommissionStats: commissionStatsSvc.New(s.ShopSeriesCommissionStats),
PurchaseValidation: purchaseValidation,
Order: orderService,
Exchange: exchangeService,
Recharge: rechargeSvc.New(deps.DB, s.AssetWallet, s.AssetWalletTransaction, s.IotCard, s.Device, s.ShopSeriesAllocation, s.PackageSeries, s.CommissionRecord, wechatConfig, paymentLoader, deps.Logger),
PollingConfig: pollingConfigService,
PollingConcurrency: pollingConcurrencyService,
PollingMonitoring: pollingSvc.NewMonitoringServiceWithQueueMgr(deps.Redis, pollingQueueMgr, deps.Logger),
PollingAlert: pollingAlertService,
PollingCleanup: pollingSvc.NewCleanupService(s.DataCleanupConfig, s.DataCleanupLog, deps.Logger),
PollingManualTrigger: pollingManualTriggerService,
PriorityPolling: priorityPollingService,
Asset: assetService,
AssetLifecycle: assetSvc.NewLifecycleService(deps.DB, s.IotCard, s.Device, auditWriter),
AssetWallet: assetWalletSvc.New(s.AssetWallet, s.AssetWalletTransaction),
StopResumeService: stopResumeService,
WechatConfig: wechatConfig,
AgentRecharge: agentRechargeService,
AgentRechargeOnline: agentRechargeOnline,
AgentRechargePaymentConfirm: agentRechargePaymentConfirm,
AgentRechargeVoucherOCR: agentRechargeVoucherOCR,
PackageActivation: packageActivation,
TrafficQuery: trafficSvc.NewQueryService(deps.Redis, s.CardDailyUsage).WithFlowSnapshots(trafficCalcPolicy.Switched, postgres.NewCardFlowDayStore(deps.DB)),
OperationPassword: operationPassword,
AgentOpenAPI: agentOpenAPI,
Refund: refundService,
CustomerBinding: customerBinding,
OrderPackageInvalidate: orderPackageInvalidateSvc.New(s.OrderPackageInvalidateTask, deps.QueueClient, auditWriter),
AssetPackageBatchOrder: assetPackageBatchOrderSvc.New(s.AssetPackageBatchOrderTask, s.Package, deps.QueueClient, auditWriter),
ShopBusinessOwnerImport: shopBusinessOwnerImportSvc.New(s.ShopBusinessOwnerImportTask, deps.QueueClient, auditWriter),
PhoneAssetAssociation: phoneAssetAssociationSvc.New(
deps.DB, s.PhoneAssetAssociation, s.PhoneAssetUnbindImportTask,
s.AssetIdentifier, s.IotCard, s.Device, deps.QueueClient, auditWriter,
),
ObservationSeries: observationSeries,
CardObservation: cardObservationService,
CardObservationSeries: cardObservationSeries,
}
}