• erio's avatar
    fix(payment): ack unknown-order webhooks with 2xx to stop provider retries · 75e1b40f
    erio authored
    Introduce a sentinel ErrOrderNotFound in the payment service layer so the
    webhook handler can distinguish "the out_trade_no does not exist in our DB"
    from other fulfillment failures, and downgrade the former to a WARN log +
    success response.
    
    Background
    - Providers (Stripe, Alipay, Wxpay, EasyPay, ...) retry webhooks whenever
      we answer non-2xx. When a webhook endpoint is misconfigured (e.g. a
      foreign environment points at us) or our orders table has been wiped,
      we return 500 forever and the provider retries for days, spamming logs.
    - The old code also collapsed "order not found" and "DB query failed" into
      the same branch — a DB blip would be reported as "order not found" and
      swallowed.
    
    Service layer (payment_fulfillment.go)
    - Add `var ErrOrderNotFound = errors.New("payment order not found")`.
    - In HandlePaymentNotification, distinguish the two error paths:
      * dbent.IsNotFound(err) → wrap with ErrOrderNotFound so callers can
        errors.Is(...) it.
      * anything else → wrap the original err with %w so it still bubbles up
        as 500 and the provider retries (DB hiccup should be retried).
    
    Handler layer (payment_webhook_handler.go)
    - Before returning 500, check errors.Is(err, service.ErrOrderNotFound):
      emit a WARN (with provider / outTradeNo / tradeNo for discoverability),
      then call writeSuccessResponse so the provider sees its expected 2xx
      body (Stripe empty body / Wxpay JSON / others "success").
    - Other errors retain the existing 500 behavior.
    
    Monitoring note: because this path now swallows unknown-order webhooks
    silently from the provider's perspective, the WARN log line is the only
    signal. Alert on "unknown order, acking to stop retries" if you want
    visibility into misrouted webhooks or accidental data loss.
    75e1b40f
payment_fulfillment.go 14.9 KB