WeChat Pay Python SDK
raw JSON → 2.0.1 verified Tue May 12 auth: no python install: verified quickstart: stale
Community Python SDK for WeChat Pay API v3 — the de-facto standard for WeChat Pay v3 integration in Python. Covers direct merchant mode and service provider (partner) mode. Handles RSA signature generation, platform certificate auto-download and rotation, sensitive field encryption, and callback verification/decryption automatically. IMPORTANT: Multiple competing packages exist on PyPI (wechat_pay, pywechatpay, wechatpy, pywe-pay). Only 'wechatpayv3' targets the v3 API and is actively maintained. NOTE: This is a community SDK — WeChat Pay has no official Python SDK.
pip install wechatpayv3 Warnings
breaking WeChat Pay requires a Chinese business entity or a licensed overseas merchant partner to obtain merchant credentials (MCHID, API keys, certificates). Individual developers and non-Chinese companies cannot register directly. Overseas merchants must integrate via an authorized payment service provider (e.g. Stripe, Adyen, or a local aggregator) who handles the WeChat Pay merchant relationship. ↓
fix Verify merchant eligibility before starting integration. If you are a non-Chinese business, engage a WeChat Pay licensed partner. Integration code will work once valid credentials are obtained.
breaking v2.0.0 (Jul 2025) introduced breaking changes from v1.3.x. The jump from 1.3.11 to 2.0.0 occurred in a single day (Jul 29–30, 2025) with no deprecation period. ↓
fix Pin to 2.0.1: pip install wechatpayv3==2.0.1. Review changelog at github.com/minibear2021/wechatpay-python before upgrading from v1.x.
gotcha Multiple PyPI packages share similar names: 'wechat_pay' (v2-era, abandoned), 'pywechatpay' (community v3, different API), 'wechatpy' (WeChat platform SDK, not Pay-specific), 'pywe-pay' (unmaintained). Only 'wechatpayv3' targets the v3 API and is actively maintained. ↓
fix Install only 'wechatpayv3'. Verify with: pip show wechatpayv3 — author should be 'minibear'.
gotcha NOTIFY_URL must be a publicly accessible HTTPS URL. WeChat Pay servers will POST payment results to this endpoint. HTTP (non-TLS) is rejected. localhost, 127.0.0.1, and private IPs will silently fail — your callback will never fire. ↓
fix Use a real domain with valid TLS in production. For local development use ngrok or similar tunneling.
gotcha All monetary amounts are in fen (分), the smallest CNY unit. 1 CNY = 100 fen. Passing amounts in CNY (e.g. 10.00 instead of 1000) will result in payments 100x smaller than intended with no error thrown. ↓
fix Always convert to fen before passing to the SDK: amount_fen = int(amount_cny * 100).
gotcha Official WeChat Pay documentation is Chinese-first (zh-CN). The English translation at pay.weixin.qq.com lags behind and is incomplete — some v3 endpoints and error codes are only documented in Chinese. ↓
fix Use the Chinese docs at pay.weixin.qq.com as the source of truth. For error codes, refer to the zh-CN error code reference directly.
gotcha cert_dir set to None disables local certificate caching. On every WeChatPay instantiation, the SDK will re-download platform certificates from WeChat servers. In production or serverless environments with frequent cold starts, this causes latency and risks hitting WeChat's certificate download rate limits. ↓
fix Always set cert_dir to a persistent directory path in production. In serverless (Lambda, Cloud Run), use a shared volume or pre-cache certificates at build time.
breaking The SDK requires merchant credentials (MCHID, serial_no, apiv3_key, private_key) to be provided at runtime, typically via environment variables or a configuration file. Failing to set these will result in a KeyError or similar configuration error, preventing the SDK from initializing. ↓
fix Ensure all required environment variables (WECHAT_MCHID, WECHAT_SERIAL_NO, WECHAT_APIV3_KEY, WECHAT_PRIVATE_KEY) are correctly set before running the application. Alternatively, pass these credentials directly to the WeChatPay constructor during initialization.
breaking Essential credentials such as MCHID (Merchant ID), API key, and certificate path are required for the SDK to initialize. These are typically loaded from environment variables (e.g., WECHAT_MCHID) or a configuration file. Failure to provide them will result in a KeyError or similar configuration error upon application startup. ↓
fix Ensure that all necessary WeChat Pay credentials (MCHID, API key, certificate and private key paths) are correctly configured and accessible to your application, either through environment variables (as expected by the script) or other secure configuration methods.
Install
pip install wechatpayv3==2.0.1 pip install wechatpayv3[async] Install compatibility verified last tested: 2026-05-12
python os / libc variant status wheel install import disk
3.10 alpine (musl) wechatpayv3 - - 0.34s 37.6M
3.10 alpine (musl) wechatpayv3==2.0.1 - - 0.31s 37.6M
3.10 alpine (musl) async - - 0.35s 40.6M
3.10 slim (glibc) wechatpayv3 - - 0.25s 38M
3.10 slim (glibc) wechatpayv3==2.0.1 - - 0.21s 38M
3.10 slim (glibc) async - - 0.24s 41M
3.11 alpine (musl) wechatpayv3 - - 0.63s 40.1M
3.11 alpine (musl) wechatpayv3==2.0.1 - - 0.57s 40.1M
3.11 alpine (musl) async - - 0.63s 43.8M
3.11 slim (glibc) wechatpayv3 - - 0.52s 40M
3.11 slim (glibc) wechatpayv3==2.0.1 - - 0.49s 40M
3.11 slim (glibc) async - - 0.52s 44M
3.12 alpine (musl) wechatpayv3 - - 0.43s 31.7M
3.12 alpine (musl) wechatpayv3==2.0.1 - - 0.41s 31.7M
3.12 alpine (musl) async - - 0.44s 35.3M
3.12 slim (glibc) wechatpayv3 - - 0.47s 32M
3.12 slim (glibc) wechatpayv3==2.0.1 - - 0.45s 32M
3.12 slim (glibc) async - - 0.47s 36M
3.13 alpine (musl) wechatpayv3 - - 0.42s 31.4M
3.13 alpine (musl) wechatpayv3==2.0.1 - - 0.37s 31.4M
3.13 alpine (musl) async - - 0.41s 34.7M
3.13 slim (glibc) wechatpayv3 - - 0.45s 32M
3.13 slim (glibc) wechatpayv3==2.0.1 - - 0.39s 32M
3.13 slim (glibc) async - - 0.43s 35M
3.9 alpine (musl) wechatpayv3 - - 0.30s 37.7M
3.9 alpine (musl) wechatpayv3==2.0.1 - - 0.27s 37.7M
3.9 alpine (musl) async - - 0.30s 40.6M
3.9 slim (glibc) wechatpayv3 - - 0.28s 38M
3.9 slim (glibc) wechatpayv3==2.0.1 - - 0.28s 38M
3.9 slim (glibc) async - - 0.28s 41M
Imports
- WeChatPay, WeChatPayType wrong
from wechatpay import WeChatPaycorrectfrom wechatpayv3 import WeChatPay, WeChatPayType
Quickstart stale last tested: 2026-05-12
import os
from wechatpayv3 import WeChatPay, WeChatPayType
# Required credentials — all must be obtained from WeChat Pay Merchant Platform
MCHID = os.environ['WECHAT_MCHID'] # Merchant ID
PRIVATE_KEY = os.environ['WECHAT_PRIVATE_KEY'] # RSA private key (PEM string)
CERT_SERIAL_NO = os.environ['WECHAT_CERT_SERIAL_NO'] # Certificate serial number
APPID = os.environ['WECHAT_APPID'] # WeChat App ID
APIV3_KEY = os.environ['WECHAT_APIV3_KEY'] # API v3 key (32 bytes)
NOTIFY_URL = os.environ['WECHAT_NOTIFY_URL'] # Publicly accessible HTTPS endpoint
# Initialize — cert_dir caches platform certificates locally
wxpay = WeChatPay(
wechatpay_type=WeChatPayType.NATIVE, # QR code pay
mchid=MCHID,
private_key=PRIVATE_KEY,
cert_serial_no=CERT_SERIAL_NO,
apiv3_key=APIV3_KEY,
appid=APPID,
notify_url=NOTIFY_URL,
cert_dir='./cert' # Set to None during initial debug only
)
# Native pay (QR code) — returns code_url, convert to QR for user to scan
code, message = wxpay.pay(
description='Order description',
out_trade_no='YOUR_UNIQUE_ORDER_ID',
amount={'total': 100}, # Amount in fen (1 CNY = 100 fen)
pay_type=WeChatPayType.NATIVE
)
# JSAPI pay (in WeChat app / WeChat browser) — requires user openid
code, message = wxpay.pay(
description='Order description',
out_trade_no='YOUR_UNIQUE_ORDER_ID',
amount={'total': 100},
pay_type=WeChatPayType.JSAPI,
payer={'openid': 'USER_OPENID'}
)
# Query order
code, message = wxpay.query(out_trade_no='YOUR_UNIQUE_ORDER_ID')
# Refund
code, message = wxpay.refund(
out_refund_no='YOUR_UNIQUE_REFUND_ID',
out_trade_no='YOUR_UNIQUE_ORDER_ID',
amount={'refund': 100, 'total': 100, 'currency': 'CNY'}
)
# Async usage (FastAPI example)
from wechatpayv3 import AsyncWeChatPay, WeChatPayType
async def create_payment():
wxpay = AsyncWeChatPay(
wechatpay_type=WeChatPayType.NATIVE,
mchid=MCHID,
private_key=PRIVATE_KEY,
cert_serial_no=CERT_SERIAL_NO,
apiv3_key=APIV3_KEY,
appid=APPID,
notify_url=NOTIFY_URL
)
code, message = await wxpay.pay(
description='Order description',
out_trade_no='YOUR_UNIQUE_ORDER_ID',
amount={'total': 100},
pay_type=WeChatPayType.NATIVE
)
return code, message