package service import ( "net/http" "strings" "time" "affiliate_dash/internal/model" ) const defaultDeliveryBFFBaseURL = "https://www.jxya.top/bff" // 发货提交阶段,持久化在 result_data.provider_order_stage 中,供排障与补偿扫描区分处理。 const ( deliveryStageClaimed = "claimed" // 已锁定订单,尚未建 queue deliveryStageQueueCreated = "queue_created" // 已在上游建 queue,尚未生成正式订单 deliveryStageSubmitted = "submitted" // 已在上游创建正式订单 deliveryStageBindVerify = "bind_verify" // 绑定账号校验失败 deliveryStageBindMismatch = "bind_mismatch" // 玩家编号与绑定账号不一致 deliveryStageCreateQueue = "create_queue" // 创建上游 queue 失败 deliveryStagePatchQueue = "patch_queue" // 补充 queue 账号信息失败 deliveryStageCreateOrder = "create_upstream" // 创建上游正式订单失败 deliverySubmissionStaleTimeout = 10 * time.Minute // 第一平台创建正式订单常态约 11 秒,15 秒上限会在偶发变慢时提前断开。 deliveryUpstreamTimeout = 30 * time.Second ) // deliverySubmittedUpstream 判断订单是否已成功提交到上游正式订单。 // 已提交上游的失败订单禁止自动重发,避免重复发货。 func deliverySubmittedUpstream(order *model.FulfillmentOrder) bool { if order == nil { return false } if strings.TrimSpace(order.ProviderOrderNo) != "" { return true } m := resultDataMap(order.ResultData) if _, ok := m["delivery"]; ok { return true } if _, ok := m["upstream_order"]; ok { // 兼容历史数据 return true } return resultDataString(order.ResultData, "provider_order_stage") == deliveryStageSubmitted } type DeliveryService struct { fulfillment *FulfillmentService bffBaseURL string channel string linkBaseURL string linkSecret string linkTTL time.Duration httpClient *http.Client router *FulfillmentRouter } func NewDeliveryService(fulfillment *FulfillmentService, bffBaseURL, channel, linkBaseURL, linkSecret string, linkTTLMinutes int) *DeliveryService { bffBaseURL = strings.TrimRight(strings.TrimSpace(bffBaseURL), "/") if bffBaseURL == "" { bffBaseURL = defaultDeliveryBFFBaseURL } channel = strings.TrimSpace(channel) if channel == "" { channel = "dlc" } linkBaseURL = strings.TrimRight(strings.TrimSpace(linkBaseURL), "/") linkSecret = strings.TrimSpace(linkSecret) if linkSecret == "" { linkSecret = "affiliate-dash-delivery-link-secret" } // linkTTLMinutes <= 0 表示链接永久有效(0 为默认值)。 if linkTTLMinutes < 0 { linkTTLMinutes = 0 } client := &http.Client{Timeout: deliveryUpstreamTimeout} dlc := NewDLCProvider(bffBaseURL, channel, client) router := NewFulfillmentRouter(dlc) return &DeliveryService{ fulfillment: fulfillment, bffBaseURL: bffBaseURL, channel: channel, linkBaseURL: linkBaseURL, linkSecret: linkSecret, linkTTL: time.Duration(linkTTLMinutes) * time.Minute, httpClient: client, router: router, } } func (s *DeliveryService) SetHTTPClient(client *http.Client) { if client != nil { s.httpClient = client if dlc, ok := s.router.GetProvider(ProviderDLC).(*DLCProvider); ok && dlc != nil { dlc.httpClient = client } } } func (s *DeliveryService) SetRouter(router *FulfillmentRouter) { if router != nil { s.router = router } } func (s *DeliveryService) RegisterProvider(provider FulfillmentProvider) { if s.router == nil { s.router = NewFulfillmentRouter(provider) } else if provider != nil { s.router.providers[provider.Name()] = provider } } // CancelUpstream 取消订单时同步取消已锁定/已建单的上游履约渠道。