Files
soul-yongping/soul-api/scripts/test_transfer_notify.py
2026-03-07 22:58:43 +08:00

94 lines
3.5 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
模拟微信「商家转账到零钱」结果通知回调,请求本地/远程回调接口,
用于验证1接口是否可达 2wechat_callback_logs 表是否会写入一条记录。
说明:未使用真实签名与加密,服务端会验签失败并返回 500
但仍会写入 wechat_callback_logs 一条 handler_result=fail 的记录。
运行前请确保 soul-api 已启动;运行后请查表 wechat_callback_logs 是否有新行。
"""
import json
import ssl
import sys
from datetime import datetime
from urllib.request import Request, urlopen
from urllib.error import URLError, HTTPError
# 默认请求地址(可改环境或命令行)
DEFAULT_URL = "http://localhost:8080/api/payment/wechat/transfer/notify"
def main():
args = [a for a in sys.argv[1:] if a and not a.startswith("-")]
insecure = "--insecure" in sys.argv or "-k" in sys.argv
url = args[0] if args else DEFAULT_URL
if insecure and url.startswith("https://"):
print("已启用 --insecure跳过 SSL 证书校验(仅用于本地/测试)")
ctx = ssl.create_default_context()
ctx.check_hostname = False
ctx.verify_mode = ssl.CERT_NONE
else:
ctx = None
# 模拟微信回调的请求体结构(真实场景中 resource.ciphertext 为 AEAD_AES_256_GCM 加密,这里用占位)
body = {
"id": "test-notify-id-" + datetime.now().strftime("%Y%m%d%H%M%S"),
"create_time": datetime.now().strftime("%Y-%m-%dT%H:%M:%S+08:00"),
"resource_type": "encrypt-resource",
"event_type": "MCHTRANSFER.BILL.FINISHED",
"summary": "模拟转账结果通知",
"resource": {
"original_type": "mch_payment",
"algorithm": "AEAD_AES_256_GCM",
"ciphertext": "fake-base64-ciphertext-for-test",
"nonce": "fake-nonce",
"associated_data": "mch_payment",
},
}
body_bytes = json.dumps(body, ensure_ascii=False).encode("utf-8")
headers = {
"Content-Type": "application/json",
"Wechatpay-Timestamp": str(int(datetime.now().timestamp())),
"Wechatpay-Nonce": "test-nonce-" + datetime.now().strftime("%H%M%S"),
"Wechatpay-Signature": "fake-signature-for-test",
"Wechatpay-Serial": "fake-serial-for-test",
}
req = Request(url, data=body_bytes, headers=headers, method="POST")
print(f"POST {url}")
print(f"Body (摘要): event_type={body['event_type']}, resource_type={body['resource_type']}")
print("-" * 50)
try:
with urlopen(req, timeout=10, context=ctx) as resp:
print(f"HTTP 状态: {resp.status}")
raw = resp.read().decode("utf-8", errors="replace")
try:
parsed = json.loads(raw)
print("响应 JSON:", json.dumps(parsed, ensure_ascii=False, indent=2))
except Exception:
print("响应 body:", raw[:500])
except HTTPError as e:
print(f"HTTP 状态: {e.code}")
raw = e.read().decode("utf-8", errors="replace")
try:
parsed = json.loads(raw)
print("响应 JSON:", json.dumps(parsed, ensure_ascii=False, indent=2))
except Exception:
print("响应 body:", raw[:500])
except URLError as e:
print(f"请求失败: {e.reason}")
sys.exit(1)
print("-" * 50)
print("请检查数据库表 wechat_callback_logs 是否有新记录(本次为模拟请求,预期会有一条 handler_result=fail 的记录)。")
if __name__ == "__main__":
main()