Files
junhong_cmp_fiber/internal/bootstrap/services.go
邹进 42e881576d
All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 9m33s
feat: 卡网关按运营商账户限流并记录停复机调用
- 新增网关限流:按本系统运营商账户(卡 carrier_id)→ 限流组 → 操作限制每秒请求数,每次 HTTP 尝试计量,默认限流、仅后台人工点击/通道阈值/自动续费/手动刷新豁免;支持只统计与拦截两种模式,默认只统计
- Asynq 遇限流不计失败、固定短延迟重试;轮询任务与停复机业务重试遇限流短延迟重排
- 停机、复机不再使用网关内部重试,只发一次请求
- 网关返回结构化错误;新增上游错误分类规则表与测试接口
- 新增按月分区的停复机记录表:系统自动停复机只写记录,不再写统一审计与集成日志;普通轮询查询不再写集成日志
- 新增限流组、错误分类、停复机记录、按账户调用统计与枚举后台接口
- 迁移 000243~000246;同步 OpenSpec 提案(含后续 6 个 change)与技术方案、工程约束
2026-10-24 15:06:41 +09:00

582 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))
if deps.GatewayLimit != nil {
stopResumeService.SetStopResumeRecorder(deps.GatewayLimit.Recorder)
}
// 持通道阈值锁的卡在周期内拒绝一切复机(自动、手动、保护期强制、机卡分离)。
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)
if deps.GatewayLimit != nil {
device.SetStopResumeRecorder(deps.GatewayLimit.Recorder)
}
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,
}
}