fix(v2): 回调按 SettleResult 分终态/可重试——amount_mismatch 回 200 停投,不再无限重投

This commit is contained in:
wangjia
2026-07-10 11:44:14 +08:00
parent a633b2ac0a
commit 6cbaa59db7
2 changed files with 76 additions and 6 deletions
+12 -5
View File
@@ -111,7 +111,9 @@ func (h *GatewayHandler) Cancel(c *gin.Context) {
}
// Callback POST /api/v2/callback/:method —— 渠道异步回调;经 provider.VerifyCallback → Settle。
// 已受理(含未知单/幂等/金额不符,都不需要渠道重投)一律回 200。
// 按 SettleResult 分终态/可重试:not_found/duplicate/ignored/amount_mismatch 都是终态
// (含 amount_mismatch —— Settle 对其返回非 nil err,但仍是已受理的终态),一律回 200 停投;
// SettleFailed(暂时性失败)与验签/解析失败(err!=nil 且非 amount_mismatch)是可重试态,回 400 让渠道重投。
func (h *GatewayHandler) Callback(c *gin.Context) {
method := c.Param("method")
raw, err := io.ReadAll(http.MaxBytesReader(c.Writer, c.Request.Body, maxOrderBodyBytes))
@@ -126,13 +128,18 @@ func (h *GatewayHandler) Callback(c *gin.Context) {
res, err := h.g.HandleCallback(c.Request.Context(), method, provider.CallbackInput{
Raw: raw, Headers: headers,
})
if err != nil {
// 验签失败等:回 400 让渠道按策略重投(或人工排障)。
switch {
case err == nil:
c.JSON(http.StatusOK, gin.H{"result": string(res)})
case res == gateway.SettleAmountMismatch:
// 金额/币种不符是终态,不是可重试的暂时性失败:回 200 受理,让渠道停止重投。
log.Printf("[v2 callback] method=%s 金额/币种不符(终态,已受理停投): %v", method, err)
c.JSON(http.StatusOK, gin.H{"result": string(res)})
default:
// SettleFailed/验签失败等:回 400 让渠道按策略重投(或人工排障)。
log.Printf("[v2 callback] method=%s result=%s err=%v", method, res, err)
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) {