docs(v2): P2 计划 settle 代码段同步 T5 修复(瞬时读库错误→SettleFailed)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013nMthbVEmQquxBRKb9Fj8u
This commit is contained in:
@@ -1321,7 +1321,9 @@ func (g *Gateway) Settle(ctx context.Context, ev *provider.PaidEvent) (SettleRes
|
|||||||
if errors.Is(err, store.ErrAttemptNotFound) {
|
if errors.Is(err, store.ErrAttemptNotFound) {
|
||||||
return SettleNotFound, nil
|
return SettleNotFound, nil
|
||||||
}
|
}
|
||||||
return SettleNotFound, err
|
// 读库瞬时失败是可重试态(SettleFailed),不能与"查无此单"(终态,ack 即弃)
|
||||||
|
// 混淆——否则按 result 决定 ack 的调用方会让渠道停止重投,已付单永不入账。
|
||||||
|
return SettleFailed, err
|
||||||
}
|
}
|
||||||
// 金额/币种核对:币种须一致,实付须 ≥ 应收(允许 crypto 多付,拒少付)。
|
// 金额/币种核对:币种须一致,实付须 ≥ 应收(允许 crypto 多付,拒少付)。
|
||||||
if ev.PaidCurrency != att.Currency || ev.PaidAmountMinor < att.AmountMinor {
|
if ev.PaidCurrency != att.Currency || ev.PaidAmountMinor < att.AmountMinor {
|
||||||
@@ -2158,13 +2160,19 @@ func (h *GatewayHandler) Callback(c *gin.Context) {
|
|||||||
res, err := h.g.HandleCallback(c.Request.Context(), method, provider.CallbackInput{
|
res, err := h.g.HandleCallback(c.Request.Context(), method, provider.CallbackInput{
|
||||||
Raw: raw, Headers: headers,
|
Raw: raw, Headers: headers,
|
||||||
})
|
})
|
||||||
if err != nil {
|
// 按 SettleResult(而非只看 err)分终态/可重试:amount_mismatch 是终态——
|
||||||
// 验签失败等:回 400 让渠道按策略重投(或人工排障)。
|
// 重投同一回调永远解决不了,必须回 200 让渠道停投(差错单归 P6 对账/人工);
|
||||||
|
// SettleFailed/验签失败才是可重试态,回 400 让渠道重投。
|
||||||
|
switch {
|
||||||
|
case err == nil:
|
||||||
|
c.JSON(http.StatusOK, gin.H{"result": string(res)})
|
||||||
|
case res == gateway.SettleAmountMismatch:
|
||||||
|
log.Printf("[v2 callback] method=%s 金额/币种不符(终态,已受理停投): %v", method, err)
|
||||||
|
c.JSON(http.StatusOK, gin.H{"result": string(res)})
|
||||||
|
default:
|
||||||
log.Printf("[v2 callback] method=%s result=%s err=%v", method, res, err)
|
log.Printf("[v2 callback] method=%s result=%s err=%v", method, res, err)
|
||||||
util.RespondError(c, http.StatusBadRequest, "callback_failed", "回调处理失败")
|
util.RespondError(c, http.StatusBadRequest, "callback_failed", "回调处理失败")
|
||||||
return
|
|
||||||
}
|
}
|
||||||
c.JSON(http.StatusOK, gin.H{"result": string(res)})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *GatewayHandler) writeCreateErr(c *gin.Context, action, method string, err error) {
|
func (h *GatewayHandler) writeCreateErr(c *gin.Context, action, method string, err error) {
|
||||||
|
|||||||
Reference in New Issue
Block a user