dwy-wechatpay-notify
独立微信支付来源包(0.1.0):复用 wechatpayv3[async]==2.0.4 的公开 callback(headers, body) 验签解密,把付款和退款结果转成 dwy_notify.events.NotificationEvent。不依赖宿主支付模块,不实现 RSA/AES、业务账本、权益变更或群消息发送。
本包采用 MIT License。微信支付 SDK wechatpayv3==2.0.4 同样采用 MIT,具体版权声明以各发行包为准。
已有支付后台
已有官方回调入口的项目直接使用 verifier,不重复注册本包路由。SDK 客户端、商户私钥、APIv3 密钥、公钥/平台证书全部由宿主配置;在 SDK 客户端有效上下文内注入它的同步公开 callback。本包不读取环境变量、不复制密钥、不调用 SDK 私有 core。
from dwy_wechatpay_notify import (
PaymentNotificationContext,
WechatPayNotificationVerifier,
WechatPayNotifyConfig,
wechatpay_notification_event,
)
async def handle_callback(headers, raw_body, sdk_client, payment_service, durable_sink):
"""由宿主传入已打开的 SDK 客户端、原始 bytes 和持久接收器。"""
config = WechatPayNotifyConfig(mchid="1900000001", appid="wx123", scope="shop-production")
verified = await WechatPayNotificationVerifier(config, callback=sdk_client.callback).verify(headers, raw_body)
# 宿主核对本地订单/金额并完成业务提交;持久 outbox 应与业务事务一起写入。
confirmed = await payment_service.apply_verified_notification(verified)
event = wechatpay_notification_event(
confirmed,
scope=config.scope,
context=PaymentNotificationContext(description="基础版月付", outcome="权益已确认"),
)
await durable_sink(event)
payment_service 与 durable_sink 是宿主注入对象,示例不定义业务账本。主动查单、补单或对账时构造 ConfirmedWechatPayResult:付款需 event_type="TRANSACTION.SUCCESS"、order_no、transaction_id、整数分 amount_fen、trade_type、trade_state="SUCCESS";退款另需 refund_no、refund_id、refund_fen、与事件一致的 refund_status。查单没有官方回调 ID 时保持 provider_event_id=None。
收到已验证官方事件不证明本地已入账。宿主必须核对订单、币种、原金额与状态,并由自己的事务确定权益。REFUND.ABNORMAL、REFUND.CLOSED 只表示异常/关闭,不能当作退款成功。退款回调可能没有 appid,始终核验 mchid;有 appid 时同时核验。
新项目:可选 FastAPI 安装器
安装包的 [fastapi] extra 后调用以下装配函数;生产必须传入持久化 EventSink,不得用只发 HTTP 群消息的函数替代持久接受。sink(event) 返回 True 表示新接受,False 表示之前已接受的重复,二者均确认;异常返回 HTTP 503,微信可重试。本模块不在验签前用内存 receipt 吞掉业务重试。
from dwy_wechatpay_notify import (
WechatPayNotificationVerifier,
WechatPayNotifyConfig,
install_wechatpay_notifications,
)
def configure_callbacks(app, sdk_client, durable_sink):
"""宿主 lifespan 保持 SDK 客户端存活,关闭资源仍由宿主负责。"""
config = WechatPayNotifyConfig(mchid="1900000001", appid="wx123", scope="shop-production")
install_wechatpay_notifications(
app,
config,
verifier=WechatPayNotificationVerifier(config, callback=sdk_client.callback),
sink=durable_sink,
)
默认接收地址示例:http://localhost:8000/webhooks/wechatpay;生产应配置真实公网 HTTPS,例如 https://payments.example.com:443/webhooks/wechatpay。可通过 config.path 更改。安装器流式读取请求,默认最多 65536 bytes;超限 HTTP 413,验签/身份/协议失败 HTTP 400,持久接受成功或重复 HTTP 204。只交给 SDK 一次原始 bytes,不改变宿主 lifespan、不启动或关闭其他应用。
安全与幂等
- 配置显式注入,商户/应用身份非空,scope 最长 128 字符;不同商户/应用必须使用不同 scope。
- 付款键
wechat:payment:{order_no}:success;退款键wechat:refund:{refund_no}:{SUCCESS|ABNORMAL|CLOSED}。回调与主动查单使用同一业务键;sink 按 source、scope、event_id 持久幂等。 - 事件 data 仅包含类型化白名单字段;不转发 payer/openid、邮箱、手机号、密钥、签名或原文。
PaymentNotificationContext仅接安全商品快照/已确认业务结果,不接受任意字典;调用方不能在这些文字里填个人信息或凭据。 - 通知正文严格不超过 1800 UTF8 bytes;放不下的商品/业务结果整项省略,不截断金融标识。金额用整数分格式化。
WECHATPAY/SIGNTEST/不是交易,安全拒绝;SDK 的异常统一转成WechatPayVerificationError,不携带原文或密钥。宿主不得给 SDK 配置记录回调原文的日志器。
开发与验收
执行本目录 pytest 运行全部用例,使用固定测试驱动与本地临时 RSA 密钥/AESGCM,均不访问微信/企微网络。tests/TEST_CASES.md 记录覆盖边界。tests/wheel_smoke.py 面向已安装 wheel,验证独立核心导入及事件合同。正式发行必须使用 GitHub Actions OIDC;本地构建仅做临时 wheel 验收,不替代发布工作流。
Metadata
Release files for dwy-wechatpay-notify 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| dwy_wechatpay_notify-0.1.0-py3-none-any.whl | Python 3 | none | any | Details for dwy_wechatpay_notify-0.1.0-py3-none-any.whl |
Release files / dwy_wechatpay_notify-0.1.0-py3-none-any.whl
| Download URL | dwy_wechatpay_notify-0.1.0-py3-none-any.whl |
|---|---|
| Size | 12.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
f0df6e5b4650e9486fa3cf5884a065852f74fb5eaafd80a74c9217b4ddb05e3e
|
|
BLAKE2b-256 checksum How to use checksums |
4a6c36d63b73e7b03c9128f2946352acd9027907925deb97b946ea08bab72326
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
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.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Nov 2, 2026.
Transparency logSecurity for dwy-wechatpay-notify 0.1.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.
Full provenance
All 1 file in this release has been uploaded with provenance metadata.
Attestation for dwy_wechatpay_notify-0.1.0-py3-none-any.whl
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Nov 2, 2026.
Transparency logA 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.