This commit is contained in:
@@ -1778,6 +1778,106 @@ func (s *Service) HandlePaymentCallback(ctx context.Context, orderNo string, pay
|
||||
return nil
|
||||
}
|
||||
|
||||
// HandlePaymentRecordCallback 通过支付单处理套餐订单第三方支付回调。
|
||||
func (s *Service) HandlePaymentRecordCallback(ctx context.Context, paymentNo string, paymentMethod string, thirdPartyTradeNo string, actualPaidAmount int64) error {
|
||||
payment, err := s.paymentStore.GetByPaymentNo(ctx, paymentNo)
|
||||
if err != nil {
|
||||
if err == gorm.ErrRecordNotFound {
|
||||
return errors.New(errors.CodeNotFound, "支付记录不存在")
|
||||
}
|
||||
return errors.Wrap(errors.CodeDatabaseError, err, "查询支付记录失败")
|
||||
}
|
||||
if payment.OrderType != model.PaymentOrderTypePackage {
|
||||
return errors.New(errors.CodeInvalidParam, "支付记录类型不匹配")
|
||||
}
|
||||
|
||||
order, err := s.orderStore.GetByID(ctx, payment.OrderID)
|
||||
if err != nil {
|
||||
if err == gorm.ErrRecordNotFound {
|
||||
return errors.New(errors.CodeNotFound, "订单不存在")
|
||||
}
|
||||
return errors.Wrap(errors.CodeDatabaseError, err, "查询订单失败")
|
||||
}
|
||||
|
||||
now := time.Now()
|
||||
shouldResumeAfterPayment := false
|
||||
shouldEnqueueCommission := false
|
||||
err = s.db.WithContext(ctx).Transaction(func(tx *gorm.DB) error {
|
||||
paymentUpdates := map[string]any{
|
||||
"status": model.PaymentRecordStatusPaid,
|
||||
"paid_at": now,
|
||||
}
|
||||
if thirdPartyTradeNo != "" {
|
||||
paymentUpdates["third_party_trade_no"] = thirdPartyTradeNo
|
||||
}
|
||||
paymentResult := tx.Model(&model.Payment{}).
|
||||
Where("id = ? AND status = ?", payment.ID, model.PaymentRecordStatusPending).
|
||||
Updates(paymentUpdates)
|
||||
if paymentResult.Error != nil {
|
||||
return errors.Wrap(errors.CodeDatabaseError, paymentResult.Error, "更新支付记录失败")
|
||||
}
|
||||
if paymentResult.RowsAffected == 0 {
|
||||
var currentPayment model.Payment
|
||||
if err := tx.First(¤tPayment, payment.ID).Error; err != nil {
|
||||
return errors.Wrap(errors.CodeDatabaseError, err, "查询支付记录失败")
|
||||
}
|
||||
if currentPayment.Status == model.PaymentRecordStatusPaid {
|
||||
return nil
|
||||
}
|
||||
return errors.New(errors.CodeInvalidStatus, "支付记录状态不允许处理")
|
||||
}
|
||||
|
||||
result := tx.Model(&model.Order{}).
|
||||
Where("id = ? AND payment_status = ?", order.ID, model.PaymentStatusPending).
|
||||
Updates(map[string]any{
|
||||
"payment_status": model.PaymentStatusPaid,
|
||||
"payment_method": paymentMethod,
|
||||
"paid_at": now,
|
||||
"expires_at": nil,
|
||||
"actual_paid_amount": actualPaidAmount,
|
||||
})
|
||||
if result.Error != nil {
|
||||
return errors.Wrap(errors.CodeDatabaseError, result.Error, "更新订单支付状态失败")
|
||||
}
|
||||
if result.RowsAffected == 0 {
|
||||
var currentOrder model.Order
|
||||
if err := tx.First(¤tOrder, order.ID).Error; err != nil {
|
||||
return errors.Wrap(errors.CodeDatabaseError, err, "查询订单失败")
|
||||
}
|
||||
|
||||
switch currentOrder.PaymentStatus {
|
||||
case model.PaymentStatusPaid:
|
||||
return nil
|
||||
case model.PaymentStatusCancelled:
|
||||
return errors.New(errors.CodeInvalidStatus, "订单已取消,无法支付")
|
||||
case model.PaymentStatusRefunded:
|
||||
return errors.New(errors.CodeInvalidStatus, "订单已退款,无法支付")
|
||||
default:
|
||||
return errors.New(errors.CodeInvalidStatus, "订单状态异常")
|
||||
}
|
||||
}
|
||||
|
||||
actualPaidAmountSnapshot := actualPaidAmount
|
||||
order.ActualPaidAmount = &actualPaidAmountSnapshot
|
||||
shouldResumeAfterPayment = true
|
||||
shouldEnqueueCommission = true
|
||||
|
||||
return s.activatePackage(ctx, tx, order)
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if shouldResumeAfterPayment {
|
||||
s.tryResumeAfterPayment(ctx, order)
|
||||
}
|
||||
if shouldEnqueueCommission && order.CommissionStatus == model.CommissionStatusPending {
|
||||
s.enqueueCommissionCalculation(ctx, order.ID)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// tryResumeAfterPayment 支付成功后检查是否应触发自动复机
|
||||
// 仅当本次支付直接激活了主套餐(status=1,非排队)时才调用复机,避免虚流量已超但套餐排队时错误复机
|
||||
func (s *Service) tryResumeAfterPayment(ctx context.Context, order *model.Order) {
|
||||
|
||||
Reference in New Issue
Block a user