Some checks failed
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Has been cancelled
- 支付宝查单把 ACQ.TRADE_NOT_EXIST 当成查单失败,恢复任务永远判为未知,订单停在待支付; 同一套餐再下单时旧单也关不掉,新单无法创建。改为按"渠道无此订单"处理,过支付截止后关闭 - 延期订单详情对未过期的待支付订单返回 qr_content,后台可展示二维码、H5 可继续支付 - 新增作废待支付订单:后台 POST /orders/:id/close、H5 POST /orders/:id/cancel;作废前先查单,已支付则按支付成功办理
102 lines
3.9 KiB
Go
102 lines
3.9 KiB
Go
package packagesilence
|
||
|
||
import (
|
||
"context"
|
||
"strings"
|
||
|
||
"gorm.io/gorm"
|
||
|
||
agentrechargeApp "github.com/break/junhong_cmp_fiber/internal/application/agentrecharge"
|
||
"github.com/break/junhong_cmp_fiber/internal/model"
|
||
"github.com/break/junhong_cmp_fiber/internal/model/dto"
|
||
"github.com/break/junhong_cmp_fiber/internal/store/postgres"
|
||
"github.com/break/junhong_cmp_fiber/pkg/constants"
|
||
"github.com/break/junhong_cmp_fiber/pkg/errors"
|
||
)
|
||
|
||
// CancelOrderCommand 是作废待支付延期订单的命令:Scope.CustomerID 非 0 为 H5 客户作废自己的订单,为 0 为后台运营作废。
|
||
type CancelOrderCommand struct {
|
||
OrderID uint
|
||
Scope Scope
|
||
Reason string
|
||
}
|
||
|
||
// CancelPendingOrder 作废未支付的在线延期订单,作废后同一套餐可以重新下单。
|
||
//
|
||
// 作废前先按冻结商户查单:渠道已支付则按支付成功处理(照常延期)并拒绝作废;
|
||
// 其余情况(未支付、渠道无此订单、查单失败)直接关闭。关闭后才到达的支付会进入异常并由恢复任务原路退款,不会吞款。
|
||
func (s *ExtensionService) CancelPendingOrder(ctx context.Context, command CancelOrderCommand) (*dto.SilenceExtensionOrderResponse, error) {
|
||
if command.Scope.CustomerID == 0 {
|
||
if err := s.requirePermission(ctx, constants.PermissionPackageSilenceExtend); err != nil {
|
||
return nil, err
|
||
}
|
||
}
|
||
order, err := postgres.NewPackageSilenceOrderStore(s.db).GetByID(ctx, command.OrderID)
|
||
if err != nil {
|
||
if err == gorm.ErrRecordNotFound {
|
||
return nil, errors.New(errors.CodeNotFound, "延期订单不存在")
|
||
}
|
||
return nil, errors.Wrap(errors.CodeDatabaseError, err, "查询延期订单失败")
|
||
}
|
||
if command.Scope.CustomerID != 0 && (order.CustomerID == nil || *order.CustomerID != command.Scope.CustomerID) {
|
||
return nil, errors.New(errors.CodeNotFound, "延期订单不存在")
|
||
}
|
||
if order.Status != constants.SilenceOrderStatusPendingPayment {
|
||
return nil, errors.New(errors.CodeInvalidStatus, "只有待支付的延期订单可以作废")
|
||
}
|
||
|
||
paid, err := s.confirmIfPaid(ctx, order)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
if paid {
|
||
return nil, errors.New(errors.CodeInvalidStatus, "该订单已支付,已按支付成功办理延期,不能作废")
|
||
}
|
||
|
||
reason := "手动作废"
|
||
if command.Scope.CustomerID != 0 {
|
||
reason = "客户作废"
|
||
}
|
||
if extra := strings.TrimSpace(command.Reason); extra != "" {
|
||
reason += ":" + extra
|
||
}
|
||
if err := s.closeOrder(ctx, order.ID, reason); err != nil {
|
||
return nil, err
|
||
}
|
||
current, err := postgres.NewPackageSilenceOrderStore(s.db).GetByID(ctx, order.ID)
|
||
if err != nil {
|
||
return nil, errors.Wrap(errors.CodeDatabaseError, err, "查询延期订单失败")
|
||
}
|
||
return s.orderResponse(ctx, current, false)
|
||
}
|
||
|
||
// confirmIfPaid 查询订单下待支付的支付单;渠道已支付时走支付确认并返回 true。查单失败不阻止作废。
|
||
func (s *ExtensionService) confirmIfPaid(ctx context.Context, order *model.PackageSilenceExtensionOrder) (bool, error) {
|
||
if order.PaymentMethod == model.PaymentByOffline {
|
||
return false, nil
|
||
}
|
||
var payments []model.Payment
|
||
if err := s.db.WithContext(ctx).Where("order_type = ? AND order_id = ? AND status = ?", constants.PaymentOrderTypeSilenceExtension, order.ID, model.PaymentRecordStatusPending).
|
||
Order("id DESC").Find(&payments).Error; err != nil {
|
||
return false, errors.Wrap(errors.CodeDatabaseError, err, "查询延期支付单失败")
|
||
}
|
||
for index := range payments {
|
||
payment := &payments[index]
|
||
state, query, err := s.queryPayment(ctx, payment)
|
||
if err != nil || state != agentrechargeApp.OnlinePaymentStatePaid {
|
||
continue
|
||
}
|
||
paidAt := s.now()
|
||
if query.PaidAt != nil {
|
||
paidAt = *query.PaidAt
|
||
}
|
||
if err := s.ConfirmPayment(ctx, PaymentConfirmCommand{
|
||
PaymentNo: payment.PaymentNo, ThirdPartyTradeNo: query.ThirdPartyTradeNo, Amount: query.Amount, PaidAt: paidAt,
|
||
}); err != nil {
|
||
return false, err
|
||
}
|
||
return true, nil
|
||
}
|
||
return false, nil
|
||
}
|