优化订单履约状态处理

This commit is contained in:
yml2213
2026-07-31 16:28:30 +08:00
parent a091806283
commit 677bdbbc1c
11 changed files with 488 additions and 52 deletions
@@ -0,0 +1,131 @@
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))
}