fix: 支付回调激活套餐后异步触发停机卡自动复机

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
2026-03-31 18:12:24 +08:00
parent 8d69858413
commit 6457ffa6f9

View File

@@ -51,6 +51,7 @@ type Service struct {
wechatPayment wechat.PaymentServiceInterface
queueClient *queue.Client
logger *zap.Logger
resumeCallback packagepkg.ResumeCallback
}
func New(
@@ -95,6 +96,11 @@ func New(
}
}
// SetResumeCallback 设置复机回调,支付成功激活套餐后触发自动复机
func (s *Service) SetResumeCallback(callback packagepkg.ResumeCallback) {
s.resumeCallback = callback
}
// CreateLegacy 创建订单(已废弃)
// Deprecated: 使用 CreateAdminOrder 或 CreateH5Order 替代。保留用于回滚。
func (s *Service) CreateLegacy(ctx context.Context, req *dto.CreateOrderRequest, buyerType string, buyerID uint) (*dto.OrderResponse, error) {
@@ -1621,10 +1627,53 @@ func (s *Service) HandlePaymentCallback(ctx context.Context, orderNo string, pay
return err
}
s.tryResumeAfterPayment(ctx, order)
s.enqueueCommissionCalculation(ctx, order.ID)
return nil
}
// tryResumeAfterPayment 支付成功后检查是否应触发自动复机
// 仅当本次支付直接激活了主套餐status=1非排队时才调用复机避免虚流量已超但套餐排队时错误复机
func (s *Service) tryResumeAfterPayment(ctx context.Context, order *model.Order) {
if s.resumeCallback == nil {
return
}
var resumeCarrierType string
var resumeCarrierID uint
if order.OrderType == model.OrderTypeSingleCard && order.IotCardID != nil {
resumeCarrierType = "iot_card"
resumeCarrierID = *order.IotCardID
} else if order.OrderType == model.OrderTypeDevice && order.DeviceID != nil {
resumeCarrierType = "device"
resumeCarrierID = *order.DeviceID
}
if resumeCarrierID == 0 {
return
}
var activatedCount int64
s.db.WithContext(ctx).Model(&model.PackageUsage{}).
Where("order_id = ? AND status = ? AND master_usage_id IS NULL", order.ID, constants.PackageUsageStatusActive).
Count(&activatedCount)
if activatedCount == 0 {
return
}
go func(ct string, cid uint) {
if err := s.resumeCallback.ResumeCardIfStopped(context.Background(), ct, cid); err != nil {
s.logger.Error("支付后自动复机失败",
zap.String("carrier_type", ct),
zap.Uint("carrier_id", cid),
zap.Uint("order_id", order.ID),
zap.Error(err))
}
}(resumeCarrierType, resumeCarrierID)
}
func (s *Service) activatePackage(ctx context.Context, tx *gorm.DB, order *model.Order) error {
var items []*model.OrderItem
if err := tx.Where("order_id = ?", order.ID).Find(&items).Error; err != nil {