Просмотр исходного кода

test(乐收赢): 补上下单腿的两发原始应答与探针 —— 它们是已入库那几个探针的输入

不是新证据,是把**已经被引用**的东西补进来。已入库的 _lsy-query-probe.py 与
_lsy-query-by-{tradeno,traceno}-probe.py 都在开头 SRC_BIN 读这两个 .bin,
而它们不在库里 ⇒ 那三个探针 checkout 之后**跑不起来**,引用的读数也复现不了。

  _lsy-qrpay-probe.{py,txt} + -resp.bin / -resp-run1.bin   主扫 /v3/qrpay 两发独立样本
                                                            (均为 12 字段、**无 trade_no**)
  _lsy-h5pay-probe.{py,txt} + -resp.bin                    H5 /v3/h5pay 一发(29 字段,**有 trade_no**)

后一件是「查询腿走哪条分支」这个判决的全部依据:LsyQueryService.queryOrder 的逻辑是
「有 trade_no 用 trade_no,否则用 pay_trace_no + pay_time」,所以要判主扫/H5 各自走哪条腿,
得先量到**上游给不给 trade_no** —— 主扫不给(走 trace 分支)、H5 给(走 tradeno 分支)。
这条区分不是读代码能得出的:代码里那句注释原本写「qrpay 与 h5pay 那两个路径传的 patch
本来就没有 trade_no」,与实测不符(H5 有),已在更早的提交里订正。

密钥体检(_lsy-key-scan.py,递归版):本轮 9 个文件全部在已扫的 78 个之内,
含密钥的 3 个仍是那三个上游文档抓取件,本批一个都不含。
alphaH 2 недель назад
Родитель
Сommit
db039aebe3

+ 176 - 0
logs/_lsy-h5pay-probe.py

@@ -0,0 +1,176 @@
+# -*- coding: utf-8 -*-
+"""乐收赢测试环境 **H5 下单** 探针:向上游发一次真实的 /v3/h5pay。
+
+为什么单列一发:被扫(/v3/pay)与主扫(/v3/qrpay)都已真跑过,这是**第三条**
+也是最后一条未碰过的出站腿。字段集不同(必须显式 pay_type,不接受 000 AUTO)。
+
+★ 与生产代码的关系(别把本探针当生产量具):
+  报文逐字段抄自 `LsyOrderService.createH5Order`(2026-09-28 读法,第 316-336 行):
+    mch_no / [shop_no] / pay_type / pay_trace_no / pay_time / total_amount
+    / [order_body] / [attach] / [notify_url]  + inst_no + sign(client 自动补)
+  本探针是**另一支量具**:证明「这个字段集被上游接受」,不是「Java 客户端发的字节被接受」。
+
+★ 不传 notify_url(同上:传了会让上游测试环境回调我们,是有副作用的动作)。
+★ 凭据(GC3/GC5):密钥只从 application.yml 就地读,只打印长度与来源。
+"""
+import json
+import os
+import re
+import sys
+import time
+import urllib.request
+import urllib.error
+from hashlib import md5
+
+YML = "java/src/main/resources/application.yml"
+VAR = re.compile(r"^\$\{([A-Za-z0-9_]+):(.*)\}$")
+OUT = "logs/_lsy-h5pay-probe.txt"
+RESP_BIN = "logs/_lsy-h5pay-resp.bin"
+
+PAY_TYPE = sys.argv[1] if len(sys.argv) > 1 else "300"   # 300 支付宝 / 400 微信
+
+buf = []
+
+
+def say(s=""):
+    buf.append(s)
+    print(s.encode("ascii", "replace").decode())
+
+
+def read_block(path, top):
+    lines = open(path, encoding="utf-8", errors="replace").read().split("\n")
+    start = None
+    for i, ln in enumerate(lines):
+        if re.match(r"^%s:\s*$" % re.escape(top), ln):
+            start = i
+            break
+    if start is None:
+        raise SystemExit("找不到顶层段 %s:" % top)
+    out = {}
+    for j in range(start + 1, len(lines)):
+        ln = lines[j]
+        if ln.strip() == "" or ln.lstrip().startswith("#"):
+            continue
+        if not ln.startswith((" ", "\t")):
+            break
+        m = re.match(r"^\s+([A-Za-z0-9_.\-]+):\s*(.*)$", ln)
+        if m:
+            v = re.split(r"\s+#", m.group(2), maxsplit=1)[0].strip().strip("'\"")
+            out[m.group(1)] = v
+    return out
+
+
+def resolve(raw):
+    m = VAR.match(raw)
+    if not m:
+        return raw, "application.yml 字面量"
+    var, default = m.group(1), m.group(2)
+    if os.environ.get(var):
+        return os.environ[var], "环境变量 %s" % var
+    return default, "application.yml 默认值(键 %s)" % var
+
+
+cfg = read_block(YML, "leshouying")
+base_url, base_src = resolve(cfg["base-url"])
+inst_no, inst_src = resolve(cfg["inst-no"])
+key, key_src = resolve(cfg["key"])
+
+say("── 取值来源(不含密钥值)──")
+say("  base-url = %s   [%s]" % (base_url, base_src))
+say("  inst-no  = %s             [%s]" % (inst_no, inst_src))
+say("  key      = <len=%d>        [%s]" % (len(key), key_src))
+say()
+
+now = time.strftime("%Y%m%d%H%M%S")
+trace = "probe" + now + "h5"
+payload = {
+    "inst_no": inst_no,
+    "mch_no": "Y52211090004",
+    "pay_type": PAY_TYPE,            # ★ H5 必须显式指定,不接受 000
+    "pay_trace_no": trace,
+    "pay_time": now,
+    "total_amount": "1",
+    "order_body": "联调探针-H5",
+    # shop_no / attach / notify_url 生产侧「非 null 才发」,此处留空不传
+}
+
+A = "&".join("%s=%s" % (k, payload[k]) for k in sorted(payload))
+sign = md5((A + "&key=" + key).encode("utf-8")).hexdigest().lower()
+payload["sign"] = sign
+
+say("── 将发送(不含密钥;sign 打码)──")
+say("  A = %s" % A)
+say()
+body = json.dumps(payload, ensure_ascii=False).encode("utf-8")
+shown = json.loads(body.decode("utf-8"))
+shown["sign"] = "<len=%d>" % len(sign)
+say("  body = %s" % json.dumps(shown, ensure_ascii=False, indent=2))
+say()
+say("  字段清单(= 生产 createH5Order 发的集合):%s" % ", ".join(sorted(payload)))
+say()
+
+url = base_url.rstrip("/") + "/v3/h5pay"
+say("── 出站 ──")
+say("  POST %s" % url)
+say("  Content-Type: application/json;charset=utf-8")
+say("  bytes = %d" % len(body))
+say()
+
+req = urllib.request.Request(
+    url, data=body,
+    headers={"Content-Type": "application/json;charset=utf-8"},
+    method="POST",
+)
+try:
+    with urllib.request.urlopen(req, timeout=30) as r:
+        code, raw = r.status, r.read()
+except urllib.error.HTTPError as e:
+    code, raw = e.code, e.read()
+except Exception as e:
+    say("!! 请求未完成: %r" % (e,))
+    open(OUT, "w", encoding="utf-8").write("\n".join(buf))
+    sys.exit(1)
+
+open(RESP_BIN, "wb").write(raw)
+say("── 上游应答 ──")
+say("  http_code = %s" % code)
+say("  bytes     = %d" % len(raw))
+say("  原始字节已落 %s" % RESP_BIN)
+say()
+
+try:
+    resp = json.loads(raw.decode("utf-8"))
+    say("  解码 = utf-8 成功")
+except Exception as e:
+    say("  utf-8 解码失败: %r" % (e,))
+    open(OUT, "w", encoding="utf-8").write("\n".join(buf))
+    sys.exit(1)
+
+for k in sorted(resp):
+    v = resp[k]
+    if v is None:
+        say("  %-16s = null" % k)
+    else:
+        say("  %-16s = %r" % (k, v))
+say()
+
+rkey = resp.get("sign")
+if rkey:
+    nonnull = {k: v for k, v in resp.items() if k != "sign" and v is not None}
+    A2 = "&".join("%s=%s" % (k, nonnull[k]) for k in sorted(nonnull))
+    mine = md5((A2 + "&key=" + key).encode("utf-8")).hexdigest().lower()
+    say("── 入站验签(null 不参与)──")
+    say("  参与签名的字段数 = %d / 应答字段数 %d" % (len(nonnull), len(resp) - 1))
+    say("  A = %s" % A2)
+    say("  重算 == 上游 sign : %s" % (mine == rkey))
+else:
+    say("── 应答里没有 sign 字段 ──")
+say()
+
+say("── 判读线索(脚本不下结论)──")
+say("  return_code = %s" % resp.get("return_code"))
+say("  return_msg  = %s" % resp.get("return_msg"))
+say("  result_code = %s" % resp.get("result_code"))
+say()
+
+open(OUT, "w", encoding="utf-8").write("\n".join(buf))

+ 71 - 0
logs/_lsy-h5pay-probe.txt

@@ -0,0 +1,71 @@
+── 取值来源(不含密钥值)──
+  base-url = https://test.gdyfsk.com/yfpay   [application.yml 字面量]
+  inst-no  = 900112             [application.yml 默认值(键 LESHOUYING_INST_NO)]
+  key      = <len=32>        [application.yml 默认值(键 LESHOUYING_KEY)]
+
+── 将发送(不含密钥;sign 打码)──
+  A = inst_no=900112&mch_no=Y52211090004&order_body=联调探针-H5&pay_time=20260928160450&pay_trace_no=probe20260928160450h5&pay_type=300&total_amount=1
+
+  body = {
+  "inst_no": "900112",
+  "mch_no": "Y52211090004",
+  "pay_type": "300",
+  "pay_trace_no": "probe20260928160450h5",
+  "pay_time": "20260928160450",
+  "total_amount": "1",
+  "order_body": "联调探针-H5",
+  "sign": "<len=32>"
+}
+
+  字段清单(= 生产 createH5Order 发的集合):inst_no, mch_no, order_body, pay_time, pay_trace_no, pay_type, sign, total_amount
+
+── 出站 ──
+  POST https://test.gdyfsk.com/yfpay/v3/h5pay
+  Content-Type: application/json;charset=utf-8
+  bytes = 235
+
+── 上游应答 ──
+  http_code = 200
+  bytes     = 785
+  原始字节已落 logs/_lsy-h5pay-resp.bin
+
+  解码 = utf-8 成功
+  ali_trade_no     = null
+  appId            = null
+  attach           = null
+  code_url         = 'https://yyfweb.postar.cn/postalpay/p/generateCode/cloud?threeOrderNo=200001070X4326092816045010002&agetId=FWH000012501&orderDate=20260928'
+  coupon_amount    = null
+  discount_amount  = null
+  mch_name         = '建行小店基本休息修改'
+  mch_no           = 'Y52211090004'
+  mem_data         = null
+  miniapp_data     = null
+  nonceStr         = null
+  packages         = null
+  paySign          = null
+  pay_amount       = null
+  pay_time         = '20260928160450'
+  pay_trace_no     = 'probe20260928160450h5'
+  pay_type         = '300'
+  receipt_amount   = null
+  result_code      = 'PAY_SUCCESS'
+  return_code      = 'SUCCESS'
+  return_msg       = '预支付成功'
+  shop_name        = ''
+  shop_no          = ''
+  sign             = '261c9e764f3cb8d59a67b486acd2d629'
+  signType         = null
+  timeStamp        = null
+  total_amount     = '1'
+  trade_no         = '200001070X4326092816045010002'
+  trade_state      = null
+
+── 入站验签(null 不参与)──
+  参与签名的字段数 = 13 / 应答字段数 28
+  A = code_url=https://yyfweb.postar.cn/postalpay/p/generateCode/cloud?threeOrderNo=200001070X4326092816045010002&agetId=FWH000012501&orderDate=20260928&mch_name=建行小店基本休息修改&mch_no=Y52211090004&pay_time=20260928160450&pay_trace_no=probe20260928160450h5&pay_type=300&result_code=PAY_SUCCESS&return_code=SUCCESS&return_msg=预支付成功&shop_name=&shop_no=&total_amount=1&trade_no=200001070X4326092816045010002
+  重算 == 上游 sign : True
+
+── 判读线索(脚本不下结论)──
+  return_code = SUCCESS
+  return_msg  = 预支付成功
+  result_code = PAY_SUCCESS

+ 1 - 0
logs/_lsy-h5pay-resp.bin

@@ -0,0 +1 @@
+{"return_code":"SUCCESS","return_msg":"预支付成功","result_code":"PAY_SUCCESS","pay_type":"300","mch_name":"建行小店基本休息修改","shop_name":"","mch_no":"Y52211090004","shop_no":"","pay_trace_no":"probe20260928160450h5","pay_time":"20260928160450","total_amount":"1","trade_no":"200001070X4326092816045010002","appId":null,"timeStamp":null,"nonceStr":null,"packages":null,"signType":null,"paySign":null,"ali_trade_no":null,"attach":null,"code_url":"https://yyfweb.postar.cn/postalpay/p/generateCode/cloud?threeOrderNo=200001070X4326092816045010002&agetId=FWH000012501&orderDate=20260928","sign":"261c9e764f3cb8d59a67b486acd2d629","trade_state":null,"pay_amount":null,"coupon_amount":null,"receipt_amount":null,"discount_amount":null,"miniapp_data":null,"mem_data":null}

+ 176 - 0
logs/_lsy-qrpay-probe.py

@@ -0,0 +1,176 @@
+# -*- coding: utf-8 -*-
+"""乐收赢测试环境 **主扫下单** 探针:向上游发一次真实的 /v3/qrpay,拿 code_url。
+
+为什么要打这一发(前面已经验过签名了):
+  - 之前那条只读 /v3/queryorder 证明了「签名规则 + 信封」对;
+  - 但**下单**才走完整的业务校验(mch_no 是否有效、shop_no 要不要、pay_trace_no 唯一性、
+    total_amount 形态、time_expire 取值)——这些都是「签名对」证明不了的。
+  - 2026-09-28 用户已与上游确认:文档里的示例参数可用于测试。
+
+★ 与生产代码的关系(重要,别把本探针当生产量具):
+  报文**逐字段抄自** `LsyOrderService.createQrOrder`(主扫那条腿)在 2026-09-28 的读法:
+    mch_no / [shop_no] / pay_trace_no / pay_time / total_amount / time_expire
+    / [order_body] / [attach] / [notify_url]    + inst_no + sign(由 client 自动补)
+  本脚本会把**实际发出去的 body** 原样打出来,好让人把它与上面那份字段清单逐格对
+  —— 转写件必须能被核对,否则它只是一段漂亮的猜测。
+  但本探针仍是**另一支量具**:它证明的是「这个字段集被上游接受」,不是「Java 客户端发出的字节被接受」。
+
+★ 不传 notify_url:上游文档说「不传取机构默认配置回调」。传了就等于让上游的测试环境
+  去回调我们的地址,那是一个**有副作用**的动作,本次不需要。
+
+★ 凭据(GC3/GC5):机构密钥只从 application.yml 就地读,只打印长度与来源,绝不落文件、不上命令行。
+★ 出站 body 里的 sign 打码(它是这一笔的鉴权件)——字段形状仍然完整可见。
+"""
+import json
+import os
+import re
+import sys
+import time
+import urllib.request
+import urllib.error
+from hashlib import md5
+
+YML = "java/src/main/resources/application.yml"
+VAR = re.compile(r"^\$\{([A-Za-z0-9_]+):(.*)\}$")
+OUT = "logs/_lsy-qrpay-probe.txt"
+RESP_BIN = "logs/_lsy-qrpay-resp.bin"
+
+buf = []
+
+
+def say(s=""):
+    buf.append(s)
+    print(s.encode("ascii", "replace").decode())
+
+
+def read_block(path, top):
+    lines = open(path, encoding="utf-8", errors="replace").read().split("\n")
+    start = None
+    for i, ln in enumerate(lines):
+        if re.match(r"^%s:\s*$" % re.escape(top), ln):
+            start = i
+            break
+    if start is None:
+        raise SystemExit("找不到顶层段 %s:" % top)
+    out = {}
+    for j in range(start + 1, len(lines)):
+        ln = lines[j]
+        if ln.strip() == "" or ln.lstrip().startswith("#"):
+            continue
+        if not ln.startswith((" ", "\t")):
+            break
+        m = re.match(r"^\s+([A-Za-z0-9_.\-]+):\s*(.*)$", ln)
+        if m:
+            v = re.split(r"\s+#", m.group(2), maxsplit=1)[0].strip().strip("'\"")
+            out[m.group(1)] = v
+    return out
+
+
+def resolve(raw):
+    m = VAR.match(raw)
+    if not m:
+        return raw, "application.yml 字面量"
+    var, default = m.group(1), m.group(2)
+    if os.environ.get(var):
+        return os.environ[var], "环境变量 %s" % var
+    return default, "application.yml 默认值(键 %s)" % var
+
+
+cfg = read_block(YML, "leshouying")
+base_url, base_src = resolve(cfg["base-url"])
+inst_no, inst_src = resolve(cfg["inst-no"])
+key, key_src = resolve(cfg["key"])
+expire_min = resolve(cfg.get("default-qr-expire-minutes", "15"))[0]
+
+say("── 取值来源(不含密钥值)──")
+say("  base-url                 = %s   [%s]" % (base_url, base_src))
+say("  inst-no                  = %s             [%s]" % (inst_no, inst_src))
+say("  key                      = <len=%d>        [%s]" % (len(key), key_src))
+say("  default-qr-expire-minutes= %s            [取自 application.yml]" % expire_min)
+say()
+
+# ── 组报文:字段集逐格抄自 LsyOrderService.createQrOrder ─────────────────
+now = time.strftime("%Y%m%d%H%M%S")
+trace = "probe" + now + "qr"
+payload = {
+    "inst_no": inst_no,                      # client 的 signedPayload 自动补
+    "mch_no": "Y52211090004",                # 文档测试商户号
+    "pay_trace_no": trace,                   # 上游要求商户系统内唯一;本探针每跑一次都不同
+    "pay_time": now,                         # yyyyMMddHHmmss
+    "total_amount": "1",                     # 1 分
+    "time_expire": str(expire_min),
+    "order_body": "联调探针-主扫",
+    # shop_no / attach / notify_url 生产侧都是「非 null 才发」,此处留空不传
+}
+
+A = "&".join("%s=%s" % (k, payload[k]) for k in sorted(payload))
+sign = md5((A + "&key=" + key).encode("utf-8")).hexdigest().lower()
+payload["sign"] = sign
+
+say("── 将发送(不含密钥;sign 打码)──")
+say("  A = %s" % A)
+say()
+body = json.dumps(payload, ensure_ascii=False).encode("utf-8")
+shown = json.loads(body.decode("utf-8"))
+shown["sign"] = "<len=%d>" % len(sign)
+say("  body = %s" % json.dumps(shown, ensure_ascii=False, indent=2))
+say()
+say("  字段清单(= 生产 createQrOrder 发的集合):%s" % ", ".join(sorted(payload)))
+say()
+
+url = base_url.rstrip("/") + "/v3/qrpay"
+say("── 出站 ──")
+say("  POST %s" % url)
+say("  Content-Type: application/json;charset=utf-8")
+say("  bytes = %d" % len(body))
+say()
+
+req = urllib.request.Request(
+    url, data=body,
+    headers={"Content-Type": "application/json;charset=utf-8"},
+    method="POST",
+)
+try:
+    with urllib.request.urlopen(req, timeout=30) as r:
+        code, raw = r.status, r.read()
+except urllib.error.HTTPError as e:
+    code, raw = e.code, e.read()
+except Exception as e:
+    say("!! 请求未完成: %r" % (e,))
+    open(OUT, "w", encoding="utf-8").write("\n".join(buf))
+    sys.exit(1)
+
+open(RESP_BIN, "wb").write(raw)
+say("── 上游应答 ──")
+say("  http_code = %s" % code)
+say("  bytes     = %d" % len(raw))
+say("  原始字节已落 %s" % RESP_BIN)
+say()
+
+try:
+    resp = json.loads(raw.decode("utf-8"))
+    say("  解码 = utf-8 成功")
+except Exception as e:
+    say("  utf-8 解码失败: %r" % (e,))
+    open(OUT, "w", encoding="utf-8").write("\n".join(buf))
+    sys.exit(1)
+
+say("  return_code = %s" % resp.get("return_code"))
+say("  return_msg  = %s" % resp.get("return_msg"))
+say("  result_code = %s" % resp.get("result_code"))
+say("  code_url    = %s" % resp.get("code_url"))
+say()
+
+# ── 入站验签:用上一条已经实证过的「null 不参与」读法 ─────────────────
+rkey = resp.get("sign")
+if rkey:
+    nonnull = {k: v for k, v in resp.items() if k != "sign" and v is not None}
+    A2 = "&".join("%s=%s" % (k, nonnull[k]) for k in sorted(nonnull))
+    mine = md5((A2 + "&key=" + key).encode("utf-8")).hexdigest().lower()
+    say("── 入站验签(null 不参与)──")
+    say("  参与签名的字段数 = %d / 应答字段数 %d" % (len(nonnull), len(resp) - 1))
+    say("  A = %s" % A2)
+    say("  重算 == 上游 sign : %s" % (mine == rkey))
+    say()
+
+open(OUT, "w", encoding="utf-8").write("\n".join(buf))

+ 42 - 0
logs/_lsy-qrpay-probe.txt

@@ -0,0 +1,42 @@
+── 取值来源(不含密钥值)──
+  base-url                 = https://test.gdyfsk.com/yfpay   [application.yml 字面量]
+  inst-no                  = 900112             [application.yml 默认值(键 LESHOUYING_INST_NO)]
+  key                      = <len=32>        [application.yml 默认值(键 LESHOUYING_KEY)]
+  default-qr-expire-minutes= 15            [取自 application.yml]
+
+── 将发送(不含密钥;sign 打码)──
+  A = inst_no=900112&mch_no=Y52211090004&order_body=联调探针-主扫&pay_time=20260928152205&pay_trace_no=probe20260928152205qr&time_expire=15&total_amount=1
+
+  body = {
+  "inst_no": "900112",
+  "mch_no": "Y52211090004",
+  "pay_trace_no": "probe20260928152205qr",
+  "pay_time": "20260928152205",
+  "total_amount": "1",
+  "time_expire": "15",
+  "order_body": "联调探针-主扫",
+  "sign": "<len=32>"
+}
+
+  字段清单(= 生产 createQrOrder 发的集合):inst_no, mch_no, order_body, pay_time, pay_trace_no, sign, time_expire, total_amount
+
+── 出站 ──
+  POST https://test.gdyfsk.com/yfpay/v3/qrpay
+  Content-Type: application/json;charset=utf-8
+  bytes = 241
+
+── 上游应答 ──
+  http_code = 200
+  bytes     = 370
+  原始字节已落 logs/_lsy-qrpay-resp.bin
+
+  解码 = utf-8 成功
+  return_code = SUCCESS
+  return_msg  = 聚合码请求成功!
+  result_code = PAY_SUCCESS
+  code_url    = https://test.gdyfsk.com/yfpay/s/s-00002
+
+── 入站验签(null 不参与)──
+  参与签名的字段数 = 11 / 应答字段数 11
+  A = code_url=https://test.gdyfsk.com/yfpay/s/s-00002&mch_name=建行小店基本休息修改&mch_no=Y52211090004&pay_time=20260928152205&pay_trace_no=probe20260928152205qr&result_code=PAY_SUCCESS&return_code=SUCCESS&return_msg=聚合码请求成功!&shop_name=&shop_no=&total_amount=1
+  重算 == 上游 sign : True

+ 12 - 0
logs/_lsy-qrpay-resp-fields.txt

@@ -0,0 +1,12 @@
+return_code    = 'SUCCESS'
+return_msg     = '聚合码请求成功!'
+result_code    = 'PAY_SUCCESS'
+mch_name       = '建行小店基本休息修改'
+shop_name      = ''
+mch_no         = 'Y52211090004'
+shop_no        = ''
+pay_trace_no   = 'probe20260928152205qr'
+pay_time       = '20260928152205'
+total_amount   = '1'
+code_url       = 'https://test.gdyfsk.com/yfpay/s/s-00002'
+sign           = '00f5d5cb5c37a81ea40a5c35471ad0aa'

+ 1 - 0
logs/_lsy-qrpay-resp-run1.bin

@@ -0,0 +1 @@
+{"return_code":"SUCCESS","return_msg":"聚合码请求成功!","result_code":"PAY_SUCCESS","mch_name":"建行小店基本休息修改","shop_name":"","mch_no":"Y52211090004","shop_no":"","pay_trace_no":"probe20260928152114qr","pay_time":"20260928152114","total_amount":"1","code_url":"https://test.gdyfsk.com/yfpay/s/s-00001","sign":"9c2bd815a651ad8d62ab666e314e6581"}

+ 1 - 0
logs/_lsy-qrpay-resp.bin

@@ -0,0 +1 @@
+{"return_code":"SUCCESS","return_msg":"聚合码请求成功!","result_code":"PAY_SUCCESS","mch_name":"建行小店基本休息修改","shop_name":"","mch_no":"Y52211090004","shop_no":"","pay_trace_no":"probe20260928152205qr","pay_time":"20260928152205","total_amount":"1","code_url":"https://test.gdyfsk.com/yfpay/s/s-00002","sign":"00f5d5cb5c37a81ea40a5c35471ad0aa"}

+ 14 - 0
logs/_lsy-qrpay-resp.bin.pretty.json

@@ -0,0 +1,14 @@
+{
+  "return_code": "SUCCESS",
+  "return_msg": "聚合码请求成功!",
+  "result_code": "PAY_SUCCESS",
+  "mch_name": "建行小店基本休息修改",
+  "shop_name": "",
+  "mch_no": "Y52211090004",
+  "shop_no": "",
+  "pay_trace_no": "probe20260928152205qr",
+  "pay_time": "20260928152205",
+  "total_amount": "1",
+  "code_url": "https://test.gdyfsk.com/yfpay/s/s-00002",
+  "sign": "00f5d5cb5c37a81ea40a5c35471ad0aa"
+}