對接銀行支付接口時,網絡超時、銀行端異常、簽名驗證失敗等導致調用失敗屬常態。本文梳理失敗處理原則、重試策略、事務一致性保障及第三方支付建議。
銀行接口通常采用「異步通知 + 主動查詢」雙重保障機制:
try {
HttpResponse response = httpClient.execute(request);
if (response.getStatusLine().getStatusCode() != 200) {
throw new BankGatewayException("HTTP 狀態碼異常: " + response.getStatusLine());
}
String result = EntityUtils.toString(response.getEntity());
// 解析 result,判斷是否受理成功
} catch (IOException e) {
// 網絡異常:記錄日誌,標記訂單為「待確認」,啟動異步查詢任務
orderService.markPendingConfirmation(orderId);
asyncQueryScheduler.schedule(orderId);
throw new TransientBankException("銀行網關不可用", e);
}
@PostMapping("/bank/notify")
public String notify(HttpServletRequest request) {
// 1. 驗證簽名(防偽造)
if (!verifySign(request.getParameterMap())) {
return "FAIL"; // 銀行會重試
}
// 2. 解析業務結果
String orderId = request.getParameter("out_trade_no");
String tradeStatus = request.getParameter("trade_status");
// 3. 冪等處理(防重複通知)
if (orderService.isProcessed(orderId)) {
return "SUCCESS";
}
// 4. 更新訂單狀態
if ("TRADE_SUCCESS".equals(tradeStatus)) {
orderService.paySuccess(orderId, request.getParameterMap());
} else {
orderService.payFailed(orderId, tradeStatus);
}
return "SUCCESS";
}
對「待確認」訂單,啟動定時任務輪詢銀行查詢接口:
不要在同步調用失敗時直接回滾本地事務!
創建 → 支付中 → 待確認 → 成功/失敗/關閉| 維度 | 直連銀行 | 第三方支付(如支付寶/微信/銀聯雲閃付) |
|---|---|---|
| 接入成本 | 高(每家銀行單獨對接) | 低(一套 SDK 搞定多渠道) |
| 穩定性 | 依賴單銀行 | 多通道路由、自動切換 |
| 對賬難度 | 高(格式不統一) | 低(標準化對賬單) |
| 合規風險 | 自行承擔 | 持牌機構承擔 |