Skip to main content

WOP Python SDK

PyPI Python 3.9+ Release Coverage Gherkin CodeRabbit Pull Request Reviews

WOP · 万联易达开放平台 官方 Python SDK —— 协议与黄金向量真源:wop-specs

WOP 网关商户侧官方 Python 客户端库:封装协议核心(套件解析 / 结构化签名 / 内容摘要 / L2 数字信封 / 验签解密)与可插拔 HTTP 适配层,使商户无需理解 canonicalRequest、 算法套件推导与线上字节格式即可安全对接网关。

  • 协议真源:crypto-strategy-spec.md(v0.3-reviewed)+ wop-sdk-spec.md(v1.0-ratified)
  • 向量真源:crypto-vectors.json(本仓 fixture 为字节级副本,禁手改)
  • Python ≥ 3.9
  • 四套件全支持:WOP-RSA2048-SHA256 / WOP-RSA3072-SHA256 / WOP-RSA4096-SHA256 / WOP-SM2-SM3
  • 密码依赖(唯一指定路径):cryptography(RSA/AES)+ gmssl ≥ 3.2.2(SM2/SM3/SM4)
  • 主包零额外依赖;HTTP 适配器以 peer 依赖交付(wop-python-sdk[httpx] / wop-python-sdk[requests])

快速开始

pip install wop-python-sdk            # 或从源码:pip install -e .
pip install 'wop-python-sdk[httpx]'   # 可选:httpx peer 适配器(另含 requests extras)
from wop_sdk import WopClient, WopConfig
from wop_sdk.transports import UrllibTransport, send_draft

client = WopClient(WopConfig(
    app_key="app_10012481831",
    suite="WOP-RSA2048-SHA256",            # 或 WOP-RSA4096-SHA256 / WOP-SM2-SM3
    merchant_private_key=MERCHANT_PRIV_PEM,  # 商户私钥(PEM 或 Base64 单行)
    platform_public_key=PLATFORM_PUB_PEM,    # 平台公钥(PEM 或 Base64 单行)
    gateway_base_url="https://wop.example.com",
))

# L0 明文请求
draft = client.build_request("POST", "/gateway/order.create", {"orderId": 42})

# 发送(任意 HTTP 栈;此处 stdlib urllib 适配器)
resp = send_draft(UrllibTransport(), client._config.gateway_base_url, draft)

# 校验平台响应(F6 固定顺序:验签 → digest 复核 → DEK 解包 → alg 族比对 → bulk 解密)
result = client.verify_response(resp.headers, resp.body, "/gateway/order.create")
if result.ok:
    print(result.plaintext)
else:
    print(result.reason)  # 验签/解密失败对外模糊(I7),格式/完整性/一致性类明确

ISV 子商户身份(ISV D-13)

代子商户调用业务 API 时,按请求传 sub_mch_id(值 = 子商户 plf_co_id):

draft = client.build_request("POST", "/gateway/order/create", body, level="L0",
                             sub_mch_id="PLF-SUB-001")
# 一站式调用:
result = client.execute("POST", "/gateway/order/create", body, level="L0",
                        sub_mch_id="PLF-SUB-001")

SDK 在签名前写入 x-wop-sub-mch-id,并自动纳入 x-wop-sign 的 signedHeaders。 首尾空白 trim 后发送;仅接受可打印 ASCII(0x20–0x7E)、无内部空白、≤128 字符, 违规抛 ConfigurationError。不传或纯空白 = 应用自身身份,头缺席,请求头集合与签名 与旧版逐字节一致(AC-20)。extra_headers 携带该头等价于参数;双来源同传构造即拒。 该头仅在网关子商户灰度放行且应用为 ISV 应用(app_type=20)时生效。

密钥准备

密钥入参为字符串(PEM 或 Base64 单行),SDK 内部解析(D12 分发契约):

套件 商户私钥 平台公钥 约束
WOP-RSA2048-SHA256 PKCS#8 DER,Base64/PEM X.509 SPKI DER,Base64/PEM 密钥必须 2048 位
WOP-RSA3072-SHA256 PKCS#8 DER,Base64/PEM X.509 SPKI DER,Base64/PEM 密钥必须 3072 位
WOP-RSA4096-SHA256 同上 同上 密钥必须 4096 位
WOP-SM2-SM3 d 标量 32 字节,Base64 未压缩点 04‖X‖Y 65 字节,Base64 点必须在 sm2p256v1 曲线上(I5)
  • RSA 公钥与私钥均接受 PEM 包装(-----BEGIN PUBLIC KEY-----)或裸 Base64;
  • SM2 材料喂给 RSA 套件(或反向)在配置期即拒绝;跨族算法组合(如 WOP-RSA3072-SM3) 在套件解析期拒绝。

L0 / L2 示例

L0(明文,摘要为唯一完整性防线)

draft = client.build_request("POST", "/gateway/order.query", {"orderId": 42})
# 有 body 必产 x-wop-content-digest 且必入 signedHeaders(D2/I1);GET 无 body 则缺席

L2(数字信封:AES-256-GCM / SM4-GCM 全文加密)

draft = client.build_request("POST", "/gateway/order.create", {"card": "6222..."}, level="L2")
# wire_body = {"encrypted":"<base64url(ciphertext||tag)>"}
# x-wop-encrypt: L2;dek=<base64url(OAEP/SM2 包装的 DEK 载荷)>
# DEK 与 IV 每次调用 CSPRNG 新生成(I4:同一密钥下 IV 永不复用)

result = client.verify_response(resp.headers, resp.body, "/gateway/order.create")
# result.plaintext = 解密后的业务报文

# 回调校验(URI 取回调 path,方法恒 POST)
cb = client.verify_callback(cb_headers, cb_body, "/callback/notify")

线上字节格式(F7/D9/D10):全部 base64url 无填充(严格拒收 =); RSA 签名 = PKCS#1 v1.5;SM2 签名 = 裸 r‖s 64 字节(禁 DER); SM2 密文 = C1C3C2 裸拼接(C1 = 未压缩点 65B);RSA-OAEP = 显式双 SHA-256 + 空 label。

向量自测

黄金向量 fixture 位于 tests/fixtures/crypto-vectors.json(与网关真源字节级一致, 禁手改)。本地复跑 conformance 套件:

pip install -e '.[httpx]' coverage
python3 -m pytest --cov=wop_sdk --cov-branch --cov-fail-under=98

覆盖:RSA2048/3072/4096 与 SM2 签名字节级断言、OAEP 包装/解包、AES-256-GCM 与 SM4-GCM 密文字节级断言、SM3/SHA-256 摘要、DEK 载荷组装、digest 头全部格式规则;负向量含 tamper / 跨族 / 63B、65B 签名 / 带 = 的 base64url / C1C2C3 旧国标顺序 / MGF1-SHA1 陷阱密文,全部必须拒绝。CI(3.9–3.14 × linux/macOS 矩阵)执行同一命令。

另消费 wop-specs 组织级 interop 样本集(tests/fixtures/interop-cases.json 字节 副本,sha256 哨兵钉死):build 方向按冻结输入复现 draft(RSA byte-exact;SM2 按 opaque 剥离签名/包装段),verify 方向 24 条冻结样本逐条对账明文与错误分类 (canonical class 映射表见 tests/test_interop.py)。

错误处理与模糊化

  • 明确(公开协议知识,帮助集成自查):套件格式/跨族、密钥材料、digest 头格式、 缺失与不匹配(D2/I1 结构前置校验)、信封 JSON 形态与各 base64url 段(F7)、 DEK alg 与套件族不符;
  • 模糊(依赖密钥参与,防 oracle,I7):签名验证失败、解密失败——对外消息不区分 tag 失败 / 密钥不符等原因细节;DEK 载荷(解包后明文)结构畸形除 alg 跨族外一律 归入解密失败(interop 合同 n13 / 故障注入手册 P3)。

🧩 WOP 生态导航 | Ecosystem

类别 组件
协议与向量真源 wop-specs —— crypto-strategy-spec · wop-sdk-spec · 黄金测试向量
官方 SDK(六语言) Java · Go · Python · PHP · .NET · TypeScript
浏览器工作台 wop-web-tools —— 密钥生成 · 报文联调 · 国密 · 六语言代码片段
Agent 技能包 wop-skills —— 零代码调用 · 联调对拍 · 62 错误码排错
平台服务(企业内部) 统一接入网关 · 核心逻辑服务 · 回调服务 · 开发者门户 · 文档中心

Metadata

Release files for wop-python-sdk 0.2.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for wop-python-sdk 0.2.0
File Size Uploaded Provenance Actions
wop_python_sdk-0.2.0.tar.gz 81.4 kB Without provenance Details for wop_python_sdk-0.2.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for wop-python-sdk 0.2.0
File Interpreter ABI Platform Actions
wop_python_sdk-0.2.0-py3-none-any.whl Python 3 none any Details for wop_python_sdk-0.2.0-py3-none-any.whl

Total release size: 130.3 kB

Release files / wop_python_sdk-0.2.0.tar.gz

Download URL wop_python_sdk-0.2.0.tar.gz
Size 81.4 kB
Tags Source
SHA-256 checksum
How to use checksums
48c4f47ff9e9e5974932f62fcf9794ecc0d98686895617b79956157ec39d2b79
BLAKE2b-256 checksum
How to use checksums
3ebae0e8b2181b8e72c9da8fde18f6fdfb7d4b079d42491a97d6d204de6471f1
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.16

Release files / wop_python_sdk-0.2.0-py3-none-any.whl

Download URL wop_python_sdk-0.2.0-py3-none-any.whl
Size 48.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
e41cd21f88d79c0ceed8e950ae5d2da2a04bc9cbdb35ecd610dd350639d1d3b7
BLAKE2b-256 checksum
How to use checksums
e5d5280f8268c49d850e13d054de4183dcf81e2ff2e4f493b9a8fbf79fb6b349
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.16

Security for wop-python-sdk 0.2.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page