import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.ResultSetMetaData; import java.sql.SQLException; import java.sql.Statement; /** * 一次性只读探针:定位 2026-09-24 那笔支付创建 409 的通道原始回执。 * *
只跑 select,不写库。输出同时打到 stdout 与 UTF-8 文件(Git Bash 控制台编码不可靠)。 */ public class Payment409Probe { private static final String[] DATABASES = { "talent_card2", "talent_card", "talent_card_verify1", "talent_card_dryrun" }; public static void main(String[] args) throws Exception { Path out = Path.of(args.length > 0 ? args[0] : ".scratch/payment-409-probe/out.txt"); Files.createDirectories(out.getParent()); StringBuilder text = new StringBuilder(); String base = "jdbc:mysql://127.0.0.1:8134/?useUnicode=true&characterEncoding=utf8" + "&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&useSSL=false"; try (Connection connection = DriverManager.getConnection(base, "root", "123456")) { for (String database : DATABASES) { section(text, "===== " + database + " ====="); try (Statement statement = connection.createStatement()) { statement.execute("use `" + database + "`"); } catch (SQLException exception) { text.append("数据库不可用:").append(exception.getMessage()).append('\n'); continue; } dump(text, connection, "最近的支付流水", "select payment_no, order_no, amount, status, provider_huifu_id, " + "provider_response_code, provider_response_message, created_at, paid_at " + "from payment_transaction order by id desc limit 15"); dump(text, connection, "今天创建的支付流水(金额/状态/回执)", "select payment_no, order_no, amount, status, provider_response_code, provider_response_message, created_at " + "from payment_transaction where created_at >= '2026-09-24 00:00:00' order by id desc limit 20"); dump(text, connection, "最近的对账问题记录", "select issue_type, business_no, status, expected_value, actual_value, amount, description, created_at " + "from payment_reconciliation_issue order by id desc limit 15"); dump(text, connection, "商户微信阶段快照", "select application_id, sync_owner, last_synced_at, sync_error, stages_json " + "from merchant_onboarding_progress order by id desc limit 8"); } } System.out.println(text); Files.writeString(out, text.toString(), StandardCharsets.UTF_8); System.out.println("\nwritten to " + out.toAbsolutePath()); } private static void section(StringBuilder text, String title) { text.append('\n').append(title).append('\n'); } private static void dump(StringBuilder text, Connection connection, String title, String sql) { text.append("\n--- ").append(title).append(" ---\n"); try (Statement statement = connection.createStatement(); ResultSet rs = statement.executeQuery(sql)) { ResultSetMetaData meta = rs.getMetaData(); int columns = meta.getColumnCount(); int rows = 0; while (rs.next()) { rows++; for (int i = 1; i <= columns; i++) { text.append(meta.getColumnLabel(i)).append('=').append(value(rs.getObject(i))).append(" "); } text.append('\n'); } if (rows == 0) text.append("(空)\n"); } catch (SQLException exception) { text.append("查询失败:").append(exception.getMessage()).append('\n'); } } private static String value(Object raw) { if (raw == null) return "NULL"; String text = String.valueOf(raw).trim(); return text.isEmpty() ? "\"\"" : text; } }