Skip to main content

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)

Table of built distributions (wheels) for dwy-wechatpay-notify 0.1.0
File Interpreter ABI Platform Actions
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 log

Security 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 log

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.

Release history Release notifications | RSS feed

This release

0.1.0 This release

1 release file Full provenance

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