WeChat Pay Python SDK

2.0.1 · active · verified Sat Feb 28

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.

Warnings

Install

Imports

Quickstart

All amounts are in fen (smallest CNY unit). 100 fen = 1 CNY. NOTIFY_URL must be a publicly accessible HTTPS endpoint — localhost will not work. cert_dir should point to a persistent directory in production to avoid re-downloading platform certificates on every restart.

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

view raw JSON →