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:
@@ -51,6 +51,7 @@ type Service struct {
|
|||||||
wechatPayment wechat.PaymentServiceInterface
|
wechatPayment wechat.PaymentServiceInterface
|
||||||
queueClient *queue.Client
|
queueClient *queue.Client
|
||||||
logger *zap.Logger
|
logger *zap.Logger
|
||||||
|
resumeCallback packagepkg.ResumeCallback
|
||||||
}
|
}
|
||||||
|
|
||||||
func New(
|
func New(
|
||||||
@@ -95,6 +96,11 @@ func New(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetResumeCallback 设置复机回调,支付成功激活套餐后触发自动复机
|
||||||
|
func (s *Service) SetResumeCallback(callback packagepkg.ResumeCallback) {
|
||||||
|
s.resumeCallback = callback
|
||||||
|
}
|
||||||
|
|
||||||
// CreateLegacy 创建订单(已废弃)
|
// CreateLegacy 创建订单(已废弃)
|
||||||
// Deprecated: 使用 CreateAdminOrder 或 CreateH5Order 替代。保留用于回滚。
|
// Deprecated: 使用 CreateAdminOrder 或 CreateH5Order 替代。保留用于回滚。
|
||||||
func (s *Service) CreateLegacy(ctx context.Context, req *dto.CreateOrderRequest, buyerType string, buyerID uint) (*dto.OrderResponse, error) {
|
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
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
s.tryResumeAfterPayment(ctx, order)
|
||||||
s.enqueueCommissionCalculation(ctx, order.ID)
|
s.enqueueCommissionCalculation(ctx, order.ID)
|
||||||
return nil
|
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 {
|
func (s *Service) activatePackage(ctx context.Context, tx *gorm.DB, order *model.Order) error {
|
||||||
var items []*model.OrderItem
|
var items []*model.OrderItem
|
||||||
if err := tx.Where("order_id = ?", order.ID).Find(&items).Error; err != nil {
|
if err := tx.Where("order_id = ?", order.ID).Find(&items).Error; err != nil {
|
||||||
|
|||||||
Reference in New Issue
Block a user