package service import ( "crypto/sha256" "encoding/hex" "encoding/json" "errors" "time" "affiliate_dash/internal/model" ) type fulfillmentTransitionKind string const ( fulfillmentTransitionUpdate fulfillmentTransitionKind = "update" fulfillmentTransitionShipNotify fulfillmentTransitionKind = "ship_notify" fulfillmentTransitionTimeout fulfillmentTransitionKind = "timeout" ) type orderRequestFingerprintPayload struct { ClientOrderNo string `json:"client_order_no"` SKU string `json:"sku"` Quantity int64 `json:"quantity"` BuyerReference string `json:"buyer_reference"` RequestData string `json:"request_data"` } func orderRequestFingerprint(in CreateFulfillmentOrderInput, requestData string) string { raw, _ := json.Marshal(orderRequestFingerprintPayload{ ClientOrderNo: in.ClientOrderNo, SKU: in.SKU, Quantity: in.Quantity, BuyerReference: in.BuyerReference, RequestData: requestData, }) sum := sha256.Sum256(raw) return hex.EncodeToString(sum[:]) } func storedOrderRequestFingerprint(order *model.FulfillmentOrder) string { if order == nil { return "" } if order.RequestFingerprint != "" { return order.RequestFingerprint } return orderRequestFingerprint(CreateFulfillmentOrderInput{ ClientOrderNo: order.ClientOrderNo, SKU: order.ProductSKU, Quantity: order.Quantity, BuyerReference: order.BuyerReference, }, order.RequestData) } func ensureSameIdempotentOrder(existing *model.FulfillmentOrder, fingerprint string) error { if existing == nil { return errors.New("订单不存在") } if storedOrderRequestFingerprint(existing) != fingerprint { return errors.New("client_order_no 已存在,但本次请求参数与原订单不一致") } return nil } func validateFulfillmentTransition(order *model.FulfillmentOrder, next string, kind fulfillmentTransitionKind) error { if order == nil { return errors.New("订单不存在") } if order.PaymentStatus != model.PaymentStatusPaid { return errors.New("订单未支付,不能履约") } if order.FulfillmentStatus == next { return nil } switch order.FulfillmentStatus { case model.FulfillmentStatusCancelled: return errors.New("订单已取消,不能更新履约状态") case model.FulfillmentStatusSucceeded: return errors.New("订单已履约成功,不能回退状态") } switch next { case model.FulfillmentStatusProcessing: if order.FulfillmentStatus == model.FulfillmentStatusPending || order.FulfillmentStatus == model.FulfillmentStatusFailed { return nil } case model.FulfillmentStatusSucceeded: if order.FulfillmentStatus == model.FulfillmentStatusPending || order.FulfillmentStatus == model.FulfillmentStatusFailed || order.FulfillmentStatus == model.FulfillmentStatusProcessing { return nil } case model.FulfillmentStatusFailed: if kind == fulfillmentTransitionTimeout && order.FulfillmentStatus != model.FulfillmentStatusProcessing { return errors.New("只有履约中的订单可以标记超时") } if order.FulfillmentStatus == model.FulfillmentStatusPending || order.FulfillmentStatus == model.FulfillmentStatusFailed || order.FulfillmentStatus == model.FulfillmentStatusProcessing { return nil } } return errors.New("订单当前状态不允许该履约变更") } func canCancelOrder(order *model.FulfillmentOrder) error { if order == nil { return errors.New("订单不存在") } if order.FulfillmentStatus == model.FulfillmentStatusCancelled { return nil } if order.PaymentStatus != model.PaymentStatusPaid { return errors.New("订单未支付或已退款,不能取消") } switch order.FulfillmentStatus { case model.FulfillmentStatusPending, model.FulfillmentStatusFailed: return nil case model.FulfillmentStatusProcessing, model.FulfillmentStatusSucceeded: return errors.New("订单已进入履约流程,不能取消") default: return errors.New("订单当前状态不能取消") } } func processingTimedOut(order *model.FulfillmentOrder, timeout time.Duration, now time.Time) bool { if order == nil || timeout <= 0 { return false } return order.FulfillmentStatus == model.FulfillmentStatusProcessing && order.UpdatedAt.Before(now.Add(-timeout)) }