package channel import ( "context" "errors" "fmt" "sync" ) // MockChannel 联调用模拟渠道:订单创建即返回二维码内容, // 通过 MarkMockPaid 模拟"车主已付款",QueryOrder 才会返回已支付。 type MockChannel struct { mu sync.Mutex paid map[string]string // orderNo -> mock transaction id } func NewMockChannel() *MockChannel { return &MockChannel{paid: map[string]string{}} } func (m *MockChannel) Code() string { return ChannelMock } func (m *MockChannel) CreateOrder(ctx context.Context, req CreateOrderRequest) (CreateOrderResult, error) { // 二维码内容对 mock 无真实意义,保证同一订单稳定即可。 return CreateOrderResult{CodeURL: fmt.Sprintf("mockpay:order:%s:%.2f", req.OrderNo, req.Amount)}, nil } func (m *MockChannel) QueryOrder(ctx context.Context, orderNo string) (QueryOrderResult, error) { m.mu.Lock() defer m.mu.Unlock() if txn, ok := m.paid[orderNo]; ok { return QueryOrderResult{Status: QueryPaid, TransactionID: txn}, nil } return QueryOrderResult{Status: QueryPending}, nil } // MarkMockPaid 模拟渠道侧支付成功(调试端点调用)。 func (m *MockChannel) MarkMockPaid(orderNo string) { m.mu.Lock() defer m.mu.Unlock() m.paid[orderNo] = "MOCK" + orderNo } // MarkMockPaid 从注册表取 mock 渠道并模拟支付成功。 func MarkMockPaid(orderNo string) error { ch, err := Get(ChannelMock) if err != nil { return err } mock, ok := ch.(*MockChannel) if !ok { return errors.New("mock 渠道不可用") } mock.MarkMockPaid(orderNo) return nil }