| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104 |
- # -*- coding: utf-8 -*-
- """只读探针:订单抽屉那条新查询,在**真库**上到底会不会返回行。
- 它跑的是与新端点**同一条 SQL**(同一个 WHERE / ORDER BY),但**量具不是线上那支** ——
- 真正的端点是 MyBatis 发出去的、还要过租户拦截器与 @PreAuthorize。本脚本只能证明
- 「按 out_trade_no 能查到这几行、字段名与形态长这样」,证明不了端点本身。
- (这条区分的来历见 memory `probe-instrument-is-not-the-production-instrument`。)
- 用法: python logs/_lsy-order-refunds-probe.py <out_trade_no> [...]
- 只读:只发 SELECT。控制台 GBK ⇒ stdout 只打 ASCII,正文写 UTF-8 文件。
- """
- import io
- import os
- import re
- import sys
- import psycopg2
- ROOT = r"D:\project2\payment-platform"
- YML = os.path.join(ROOT, "java", "src", "main", "resources", "application.yml")
- OUT = os.path.join(ROOT, "logs", "_lsy-order-refunds-probe.txt")
- buf = []
- def say(s=""):
- buf.append(str(s))
- print(str(s).encode("ascii", "replace").decode())
- def db():
- y = io.open(YML, encoding="utf-8", errors="replace").read()
- url = re.search(r"(jdbc:postgresql://[^\s\"']+)", y).group(1)
- tail = y[y.index(url):]
- user = re.search(r"username:\s*(\S+)", tail).group(1)
- pwd = re.search(r"password:\s*(\S+)", tail).group(1)
- m = re.search(r"//([^:/]+):(\d+)/([^?\s]+)", url)
- return psycopg2.connect(host=m.group(1), port=int(m.group(2)), dbname=m.group(3),
- user=user, password=pwd, connect_timeout=8)
- orders = [a for a in sys.argv[1:] if not a.startswith("--")]
- if not orders:
- raise SystemExit("用法: python logs/_lsy-order-refunds-probe.py <out_trade_no> [...]")
- conn = db()
- cur = conn.cursor()
- # 后端实体字段 → 全局 SNAKE_CASE 之后前端要读的键(这是本探针要复核的那件事)
- COLS = ("out_refund_no", "refund_fee", "status", "refund_no", "finish_time")
- for o in orders:
- say("=" * 72)
- say("out_trade_no = %s" % o)
- cur.execute("""SELECT status, total_amount, refunded_amount
- FROM pay_lsy_order WHERE out_trade_no = %s""", (o,))
- row = cur.fetchone()
- say(" pay_lsy_order: %s" % (row,))
- if not row:
- say(" ! 库里没有这笔订单")
- continue
- # ↓↓↓ 与新端点 refundsOf() 同一条查询 ↓↓↓
- cur.execute("""SELECT out_refund_no, refund_fee, status, refund_no, finish_time,
- refund_trace_no, created_time
- FROM pay_lsy_refund WHERE out_trade_no = %s
- ORDER BY created_time DESC""", (o,))
- rows = cur.fetchall()
- say(" 新端点那条查询返回 %d 行" % len(rows))
- for r in rows:
- say(" " + " | ".join("%s=%s" % (c, v) for c, v in zip(
- ("out_refund_no", "refund_fee", "status", "refund_no", "finish_time",
- "refund_trace_no", "created_time"), r)))
- # ★ 下面这几行量的是**表里的列**,不是**响应里的键** —— 两回事,别把标题写成后者。
- # 列存在 ⇒ 该字段在实体上有映射(`LsyRefundEntity` 逐字段读过;`status` 来自父类
- # `PaymentBaseEntity`),SNAKE_CASE 之后键名与列名一致,故键也在。但这条推理链的
- # 最后一跳**本脚本没跑**(它不发 HTTP、不过 Jackson),真正的端到端读数得由接口给。
- cur.execute("""SELECT column_name FROM information_schema.columns
- WHERE table_name = 'pay_lsy_refund'""")
- have = set(x[0] for x in cur.fetchall())
- for c in COLS:
- say(" 表里的列 `%s` %s(响应键名同一套 SNAKE_CASE;端到端未由本脚本验证)"
- % (c, "存在" if c in have else "**不存在**"))
- # 回调轨迹那条:IN (订单 trace ∪ 每笔退款的 trace)。只数行,证明退款回调行确实存在。
- cur.execute("""SELECT pay_trace_no FROM pay_lsy_order WHERE out_trade_no = %s""", (o,))
- pt = cur.fetchone()[0]
- cur.execute("""SELECT refund_trace_no FROM pay_lsy_refund WHERE out_trade_no = %s""", (o,))
- traces = [pt] + [t[0] for t in cur.fetchall() if t[0]]
- say(" 回调轨迹的 trace 集合 = %d 个" % len(traces))
- cur.execute("""SELECT to_char(created_time,'HH24:MI:SS.MS'), trade_type, verify_status,
- process_status, pay_trace_no
- FROM pay_lsy_notify_log WHERE pay_trace_no = ANY(%s)
- ORDER BY created_time DESC""", (traces,))
- logs = cur.fetchall()
- say(" 回调轨迹命中 %d 行(改前只按订单 trace 查,命中 %d 行)"
- % (len(logs), sum(1 for l in logs if l[4] == pt)))
- for l in logs:
- say(" %s" % (l,))
- conn.close()
- io.open(OUT, "w", encoding="utf-8").write("\n".join(buf) + "\n")
- say("")
- say("正文已写入 %s" % os.path.relpath(OUT, ROOT))
|