wechatpayv3


Namewechatpayv3 JSON
Version 1.3.5 PyPI version JSON
download
home_pagehttps://github.com/minibear2021/wechatpayv3
Summary微信支付 API v3 Python SDK(python sdk for wechatpay v3)
upload_time2024-11-06 01:19:43
maintainerNone
docs_urlNone
authorminibear
requires_pythonNone
licenseMIT
keywords python sdk wechatpay api v3 微信支付
VCS
bugtrack_url
requirements requests cryptography
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # 微信支付 API v3 Python SDK

[![PyPI version](https://badge.fury.io/py/wechatpayv3.svg)](https://badge.fury.io/py/wechatpayv3)
[![Download count](https://img.shields.io/pypi/dm/wechatpayv3)](https://img.shields.io/pypi/dm/wechatpayv3)

**当前代码库中只有后端的演示代码,欢迎大家贡献前端各个类型应用调起支付的演示代码。**

## 介绍

微信支付接口 V3 版 python 库。

欢迎微信支付开发者扫码进 QQ 群(群号:973102221)讨论,欢迎提交代码,欢迎star、follow、fork:

![image](docs/qq.png)

## 适用对象

**wechatpayv3**同时支持微信支付[直连模式](https://pay.weixin.qq.com/wiki/doc/apiv3/index.shtml)及[服务商模式](https://pay.weixin.qq.com/wiki/doc/apiv3_partner/index.shtml),接口说明详见官网。

## 特性

1. 平台证书自动更新,无需开发者关注平台证书有效性,无需手动下载更新,自动验证签名(微信支付平台证书模式);
2. 支持本地缓存平台证书,初始化时指定平台证书保存目录即可(微信支付平台证书模式);
3. 敏感信息直接传入明文参数,SDK 内部自动加密,无需手动处理;
4. 回调通知自动验证回调消息,自动解密 resource 对象,并返回解密后的数据;
5. 已适配[直连模式](https://pay.weixin.qq.com/wiki/doc/apiv3/apis/index.shtml)和[服务商模式](https://pay.weixin.qq.com/wiki/doc/apiv3_partner/apis/index.shtml)中除“电商收付通”以外所有 v3 版接口;
6. 兼容通过平台证书模式和平台公钥模式(2024年09月后启用)初始化,兼容证书模式向公钥模式过渡。

## 源码

[github](https://github.com/minibear2021/wechatpayv3)

[gitee](https://gitee.com/minibear2021/wechatpayv3)

## 安装

```sh
pip install wechatpayv3
```

## 使用方法

### 准备

参考微信官方文档准备好密钥, 证书文件和配置([证书/密钥/签名介绍](https://pay.weixin.qq.com/wiki/doc/apiv3/wechatpay/wechatpay3_0.shtml))

- **商户 API 证书私钥:PRIVATE_KEY**。商户申请商户 API 证书时,会生成商户私钥,并保存在本地证书文件夹的文件 apiclient_key.pem 中。
  > :warning: 不要把私钥文件暴露在公共场合,如上传到 Github,写在客户端代码等。
- **商户 API 证书序列号:CERT_SERIAL_NO**。每个证书都有一个由 CA 颁发的唯一编号,即证书序列号。扩展阅读 [如何查看证书序列号](https://wechatpay-api.gitbook.io/wechatpay-api-v3/chang-jian-wen-ti/zheng-shu-xiang-guan#ru-he-cha-kan-zheng-shu-xu-lie-hao)。
- **微信支付 APIv3 密钥:APIV3_KEY**,是在回调通知和微信支付平台证书下载接口中,为加强数据安全,对关键信息 `AES-256-GCM` 解密时使用的对称加密密钥。

在2024年09月后申请开通的微信支付可能[无法使用接口下载平台证书](docs/Q&A.md#下载平台证书时解析失败),这种情况下,需要从微信支付后台的“API安全”菜单中下载/复制以下两项,使用公钥模式初始化WechatPay。

- **微信支付公钥:PUBLIC_KEY**,微信支付后台“API安全-微信支付公钥”菜单中下载的微信支付公钥。
- **微信支付公钥ID:PUBLIC_KEY_ID**,微信支付后台“API安全-微信支付公钥”菜单中复制的微信支付公钥ID,形如:PUB_KEY_ID_1234567890...。


### 一个最小的后端

[examples.py](examples/server/examples.py) 演示了一个带有[Native 支付下单](https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_4_1.shtml)接口和[支付通知](https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_4_5.shtml)接口的后端。
首先,修改 **examplys.py** 里以下几项配置参数:

```python
# 微信支付商户号,服务商模式下为服务商户号,即官方文档中的sp_mchid。
MCHID = '1230000109'

# 商户证书私钥,此文件不要放置在下面设置的CERT_DIR目录里。
with open('path_to_mch_private_key/apiclient_key.pem') as f:
    PRIVATE_KEY = f.read()

# 商户证书序列号
CERT_SERIAL_NO = '444F4864EA9B34415...'

# API v3密钥, https://pay.weixin.qq.com/wiki/doc/apiv3/wechatpay/wechatpay3_2.shtml
APIV3_KEY = 'MIIEvwIBADANBgkqhkiG9w0BAQE...'

# APPID,应用ID,服务商模式下为服务商应用ID,即官方文档中的sp_appid,也可以在调用接口的时候覆盖。
APPID = 'wxd678efh567hg6787'

# 回调地址,也可以在调用接口的时候覆盖。
NOTIFY_URL = 'https://www.xxxx.com/notify'

# 微信支付平台证书缓存目录,初始调试的时候可以设为None,首次使用确保此目录为空目录。
# 注:2024年09月后新申请的微信支付账号使用公钥模式初始化,此参数无需配置。
CERT_DIR = './cert'

# 日志记录器,记录web请求和回调细节,便于调试排错。
logging.basicConfig(filename=os.path.join(os.getcwd(), 'demo.log'), level=logging.DEBUG, filemode='a', format='%(asctime)s - %(process)s - %(levelname)s: %(message)s')
LOGGER = logging.getLogger("demo")

# 接入模式:False=直连商户模式,True=服务商模式。
PARTNER_MODE = False

# 代理设置,None或者{"https": "http://10.10.1.10:1080"},详细格式参见[https://requests.readthedocs.io/en/latest/user/advanced/#proxies](https://requests.readthedocs.io/en/latest/user/advanced/#proxies)
PROXY = None

# 请求超时时间配置
TIMEOUT = (10, 30) # 建立连接最大超时时间是10s,读取响应的最大超时时间是30s

# 微信支付平台公钥
# 注:2024年09月后新申请的微信支付账号使用公钥模式初始化,需配置此参数。
with open('path_to_wechat_pay_public_key/pub_key.pem') as f:
    PUBLIC_KEY = f.read()

# 微信支付平台公钥ID
# 注:2024年09月后新申请的微信支付账号使用公钥模式初始化,需配置此参数。
PUBLIC_KEY_ID = 'PUB_KEY_ID_444F4864EA9B34415...'
```

接下来初始化 WechatPay 实例并配置一个合适的接口:

```python
wxpay = WeChatPay(
    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,
    cert_dir=CERT_DIR,
    logger=LOGGER,
    partner_mode=PARTNER_MODE,
    proxy=PROXY,
    timeout=TIMEOUT)

# 微信支付平台公钥模式初始化,2024年09月之后申请的账号参考使用此模式。
# 平台证书模式向公钥模式切换期间也请使用此方式初始化。
wxpay = WeChatPay(
    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,
    logger=LOGGER,
    partner_mode=PARTNER_MODE,
    proxy=PROXY,
    timeout=TIMEOUT,
    public_key=PUBLIC_KEY,
    public_key_id=PUBLIC_KEY_ID)

app = Flask(__name__)

@app.route('/pay')
def pay():
    # 以native下单为例,下单成功后即可获取到'code_url',将'code_url'转换为二维码,并用微信扫码即可进行支付测试。
    out_trade_no = ''.join(sample(ascii_letters + digits, 8))
    description = 'demo-description'
    amount = 1
    code, message = wxpay.pay(
        description=description,
        out_trade_no=out_trade_no,
        amount={'total': amount},
        pay_type=WeChatPayType.NATIVE
    )
    return jsonify({'code': code, 'message': message})
```

检查一下参数无误,现在就可以用 python 解释器来运行:

```shell
$ python examples.py
 * Serving Flask app "examples" (lazy loading)
 * Environment: production
   WARNING: This is a development server. Do not use it in a production deployment.
   Use a production WSGI server instead.
 * Debug mode: off
 * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
```

现在访问 <http://127.0.0.1:5000/pay> ,如果一切正常,你会看到下面一串 json 字符串:

```python
{
  "code": 200,
  "message": "{\"code_url\":\"weixin://wxpay/bizpayurl?pr=abcdefghi\"}"
}
```

到这一步统一下单的后端就完成了,现在将 code_url 的值即"weixin://wxpay/bizpayurl?pr=abcdefghi"用[草料](https://cli.im/)转换为二维码即可用微信扫码进行支付测试。

**以上步骤如果不能正确执行,务必仔细检查各项初始化参数,必要的情况下,登录微信支付后台,将所有参数重置。**

Native 支付调试最简单便捷,调试通过没有问题证明初始化参数正确之后,如果需要采用其他(小程序、H5、JSAPI、APP)支付下单,可继续参考 examples.py。

## 常见问题

日常开发对接中的常见问题(**特别是回调验证失败的处理**)请见[这里](docs/Q&A.md)。

## 接口清单

已适配的微信支付 V3 版 API 接口列表明细详见[这里](docs/apis.md)。

部分接口的具体调用方法可以参考[这里](docs/interface.md)。

所有接口的参数类型和值**强烈建议**仔细看一下官方的接口文档。

### 接口函数参数

参数类型对照参考下表:

| 微信支付官方文档声明 | **wechatpayv3 python sdk** |
| -------------------- | -------------------------- |
| string | str |
| int| int |
| object | dict: {} |
| array| list: [] |
| boolean| bool: True, False |
| message| bytes|

### 接口函数返回值

每个接口均同步返回 code 和 message,code 为 web 请求得到的 HTTP 状态码,message 为服务器返回的 json 字符串。
例外:

1. 回调通知(callback)接口将收到的参数解密后返回,回调验证不合规或解密失败则返回 None;
2. 下载账单(download_bill)和消费者投诉 2.0 的图片下载(complaint_image_download)接口返回的 message 为 bytes 类型,直接将 message 写入磁盘即可获得对应的目标文件。
3. 账单下载接口默认返回的是gzip格式的文件,可用gzip库解压后获取实际的账单文件。

            

Raw data

            {
    "_id": null,
    "home_page": "https://github.com/minibear2021/wechatpayv3",
    "name": "wechatpayv3",
    "maintainer": null,
    "docs_url": null,
    "requires_python": null,
    "maintainer_email": null,
    "keywords": "python sdk wechatpay api v3 \u5fae\u4fe1\u652f\u4ed8",
    "author": "minibear",
    "author_email": null,
    "download_url": "https://files.pythonhosted.org/packages/38/80/f40c7d12073df371b8bb53aacfc46f56e2b62e5c90137d6ca2f51682d17b/wechatpayv3-1.3.5.tar.gz",
    "platform": null,
    "description": "# \u5fae\u4fe1\u652f\u4ed8 API v3 Python SDK\n\n[![PyPI version](https://badge.fury.io/py/wechatpayv3.svg)](https://badge.fury.io/py/wechatpayv3)\n[![Download count](https://img.shields.io/pypi/dm/wechatpayv3)](https://img.shields.io/pypi/dm/wechatpayv3)\n\n**\u5f53\u524d\u4ee3\u7801\u5e93\u4e2d\u53ea\u6709\u540e\u7aef\u7684\u6f14\u793a\u4ee3\u7801\uff0c\u6b22\u8fce\u5927\u5bb6\u8d21\u732e\u524d\u7aef\u5404\u4e2a\u7c7b\u578b\u5e94\u7528\u8c03\u8d77\u652f\u4ed8\u7684\u6f14\u793a\u4ee3\u7801\u3002**\n\n## \u4ecb\u7ecd\n\n\u5fae\u4fe1\u652f\u4ed8\u63a5\u53e3 V3 \u7248 python \u5e93\u3002\n\n\u6b22\u8fce\u5fae\u4fe1\u652f\u4ed8\u5f00\u53d1\u8005\u626b\u7801\u8fdb QQ \u7fa4(\u7fa4\u53f7\uff1a973102221)\u8ba8\u8bba\uff0c\u6b22\u8fce\u63d0\u4ea4\u4ee3\u7801\uff0c\u6b22\u8fcestar\u3001follow\u3001fork\uff1a\n\n![image](docs/qq.png)\n\n## \u9002\u7528\u5bf9\u8c61\n\n**wechatpayv3**\u540c\u65f6\u652f\u6301\u5fae\u4fe1\u652f\u4ed8[\u76f4\u8fde\u6a21\u5f0f](https://pay.weixin.qq.com/wiki/doc/apiv3/index.shtml)\u53ca[\u670d\u52a1\u5546\u6a21\u5f0f](https://pay.weixin.qq.com/wiki/doc/apiv3_partner/index.shtml)\uff0c\u63a5\u53e3\u8bf4\u660e\u8be6\u89c1\u5b98\u7f51\u3002\n\n## \u7279\u6027\n\n1. \u5e73\u53f0\u8bc1\u4e66\u81ea\u52a8\u66f4\u65b0\uff0c\u65e0\u9700\u5f00\u53d1\u8005\u5173\u6ce8\u5e73\u53f0\u8bc1\u4e66\u6709\u6548\u6027\uff0c\u65e0\u9700\u624b\u52a8\u4e0b\u8f7d\u66f4\u65b0\uff0c\u81ea\u52a8\u9a8c\u8bc1\u7b7e\u540d\uff08\u5fae\u4fe1\u652f\u4ed8\u5e73\u53f0\u8bc1\u4e66\u6a21\u5f0f\uff09\uff1b\n2. \u652f\u6301\u672c\u5730\u7f13\u5b58\u5e73\u53f0\u8bc1\u4e66\uff0c\u521d\u59cb\u5316\u65f6\u6307\u5b9a\u5e73\u53f0\u8bc1\u4e66\u4fdd\u5b58\u76ee\u5f55\u5373\u53ef\uff08\u5fae\u4fe1\u652f\u4ed8\u5e73\u53f0\u8bc1\u4e66\u6a21\u5f0f\uff09\uff1b\n3. \u654f\u611f\u4fe1\u606f\u76f4\u63a5\u4f20\u5165\u660e\u6587\u53c2\u6570\uff0cSDK \u5185\u90e8\u81ea\u52a8\u52a0\u5bc6\uff0c\u65e0\u9700\u624b\u52a8\u5904\u7406\uff1b\n4. \u56de\u8c03\u901a\u77e5\u81ea\u52a8\u9a8c\u8bc1\u56de\u8c03\u6d88\u606f\uff0c\u81ea\u52a8\u89e3\u5bc6 resource \u5bf9\u8c61\uff0c\u5e76\u8fd4\u56de\u89e3\u5bc6\u540e\u7684\u6570\u636e\uff1b\n5. \u5df2\u9002\u914d[\u76f4\u8fde\u6a21\u5f0f](https://pay.weixin.qq.com/wiki/doc/apiv3/apis/index.shtml)\u548c[\u670d\u52a1\u5546\u6a21\u5f0f](https://pay.weixin.qq.com/wiki/doc/apiv3_partner/apis/index.shtml)\u4e2d\u9664\u201c\u7535\u5546\u6536\u4ed8\u901a\u201d\u4ee5\u5916\u6240\u6709 v3 \u7248\u63a5\u53e3\uff1b\n6. \u517c\u5bb9\u901a\u8fc7\u5e73\u53f0\u8bc1\u4e66\u6a21\u5f0f\u548c\u5e73\u53f0\u516c\u94a5\u6a21\u5f0f\uff082024\u5e7409\u6708\u540e\u542f\u7528\uff09\u521d\u59cb\u5316\uff0c\u517c\u5bb9\u8bc1\u4e66\u6a21\u5f0f\u5411\u516c\u94a5\u6a21\u5f0f\u8fc7\u6e21\u3002\n\n## \u6e90\u7801\n\n[github](https://github.com/minibear2021/wechatpayv3)\n\n[gitee](https://gitee.com/minibear2021/wechatpayv3)\n\n## \u5b89\u88c5\n\n```sh\npip install wechatpayv3\n```\n\n## \u4f7f\u7528\u65b9\u6cd5\n\n### \u51c6\u5907\n\n\u53c2\u8003\u5fae\u4fe1\u5b98\u65b9\u6587\u6863\u51c6\u5907\u597d\u5bc6\u94a5, \u8bc1\u4e66\u6587\u4ef6\u548c\u914d\u7f6e([\u8bc1\u4e66/\u5bc6\u94a5/\u7b7e\u540d\u4ecb\u7ecd](https://pay.weixin.qq.com/wiki/doc/apiv3/wechatpay/wechatpay3_0.shtml))\n\n- **\u5546\u6237 API \u8bc1\u4e66\u79c1\u94a5\uff1aPRIVATE_KEY**\u3002\u5546\u6237\u7533\u8bf7\u5546\u6237 API \u8bc1\u4e66\u65f6\uff0c\u4f1a\u751f\u6210\u5546\u6237\u79c1\u94a5\uff0c\u5e76\u4fdd\u5b58\u5728\u672c\u5730\u8bc1\u4e66\u6587\u4ef6\u5939\u7684\u6587\u4ef6 apiclient_key.pem \u4e2d\u3002\n  > :warning: \u4e0d\u8981\u628a\u79c1\u94a5\u6587\u4ef6\u66b4\u9732\u5728\u516c\u5171\u573a\u5408\uff0c\u5982\u4e0a\u4f20\u5230 Github\uff0c\u5199\u5728\u5ba2\u6237\u7aef\u4ee3\u7801\u7b49\u3002\n- **\u5546\u6237 API \u8bc1\u4e66\u5e8f\u5217\u53f7\uff1aCERT_SERIAL_NO**\u3002\u6bcf\u4e2a\u8bc1\u4e66\u90fd\u6709\u4e00\u4e2a\u7531 CA \u9881\u53d1\u7684\u552f\u4e00\u7f16\u53f7\uff0c\u5373\u8bc1\u4e66\u5e8f\u5217\u53f7\u3002\u6269\u5c55\u9605\u8bfb [\u5982\u4f55\u67e5\u770b\u8bc1\u4e66\u5e8f\u5217\u53f7](https://wechatpay-api.gitbook.io/wechatpay-api-v3/chang-jian-wen-ti/zheng-shu-xiang-guan#ru-he-cha-kan-zheng-shu-xu-lie-hao)\u3002\n- **\u5fae\u4fe1\u652f\u4ed8 APIv3 \u5bc6\u94a5\uff1aAPIV3_KEY**\uff0c\u662f\u5728\u56de\u8c03\u901a\u77e5\u548c\u5fae\u4fe1\u652f\u4ed8\u5e73\u53f0\u8bc1\u4e66\u4e0b\u8f7d\u63a5\u53e3\u4e2d\uff0c\u4e3a\u52a0\u5f3a\u6570\u636e\u5b89\u5168\uff0c\u5bf9\u5173\u952e\u4fe1\u606f `AES-256-GCM` \u89e3\u5bc6\u65f6\u4f7f\u7528\u7684\u5bf9\u79f0\u52a0\u5bc6\u5bc6\u94a5\u3002\n\n\u57282024\u5e7409\u6708\u540e\u7533\u8bf7\u5f00\u901a\u7684\u5fae\u4fe1\u652f\u4ed8\u53ef\u80fd[\u65e0\u6cd5\u4f7f\u7528\u63a5\u53e3\u4e0b\u8f7d\u5e73\u53f0\u8bc1\u4e66](docs/Q&A.md#\u4e0b\u8f7d\u5e73\u53f0\u8bc1\u4e66\u65f6\u89e3\u6790\u5931\u8d25)\uff0c\u8fd9\u79cd\u60c5\u51b5\u4e0b\uff0c\u9700\u8981\u4ece\u5fae\u4fe1\u652f\u4ed8\u540e\u53f0\u7684\u201cAPI\u5b89\u5168\u201d\u83dc\u5355\u4e2d\u4e0b\u8f7d/\u590d\u5236\u4ee5\u4e0b\u4e24\u9879\uff0c\u4f7f\u7528\u516c\u94a5\u6a21\u5f0f\u521d\u59cb\u5316WechatPay\u3002\n\n- **\u5fae\u4fe1\u652f\u4ed8\u516c\u94a5\uff1aPUBLIC_KEY**\uff0c\u5fae\u4fe1\u652f\u4ed8\u540e\u53f0\u201cAPI\u5b89\u5168-\u5fae\u4fe1\u652f\u4ed8\u516c\u94a5\u201d\u83dc\u5355\u4e2d\u4e0b\u8f7d\u7684\u5fae\u4fe1\u652f\u4ed8\u516c\u94a5\u3002\n- **\u5fae\u4fe1\u652f\u4ed8\u516c\u94a5ID\uff1aPUBLIC_KEY_ID**\uff0c\u5fae\u4fe1\u652f\u4ed8\u540e\u53f0\u201cAPI\u5b89\u5168-\u5fae\u4fe1\u652f\u4ed8\u516c\u94a5\u201d\u83dc\u5355\u4e2d\u590d\u5236\u7684\u5fae\u4fe1\u652f\u4ed8\u516c\u94a5ID\uff0c\u5f62\u5982\uff1aPUB_KEY_ID_1234567890...\u3002\n\n\n### \u4e00\u4e2a\u6700\u5c0f\u7684\u540e\u7aef\n\n[examples.py](examples/server/examples.py) \u6f14\u793a\u4e86\u4e00\u4e2a\u5e26\u6709[Native \u652f\u4ed8\u4e0b\u5355](https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_4_1.shtml)\u63a5\u53e3\u548c[\u652f\u4ed8\u901a\u77e5](https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_4_5.shtml)\u63a5\u53e3\u7684\u540e\u7aef\u3002\n\u9996\u5148\uff0c\u4fee\u6539 **examplys.py** \u91cc\u4ee5\u4e0b\u51e0\u9879\u914d\u7f6e\u53c2\u6570\uff1a\n\n```python\n# \u5fae\u4fe1\u652f\u4ed8\u5546\u6237\u53f7\uff0c\u670d\u52a1\u5546\u6a21\u5f0f\u4e0b\u4e3a\u670d\u52a1\u5546\u6237\u53f7\uff0c\u5373\u5b98\u65b9\u6587\u6863\u4e2d\u7684sp_mchid\u3002\nMCHID = '1230000109'\n\n# \u5546\u6237\u8bc1\u4e66\u79c1\u94a5\uff0c\u6b64\u6587\u4ef6\u4e0d\u8981\u653e\u7f6e\u5728\u4e0b\u9762\u8bbe\u7f6e\u7684CERT_DIR\u76ee\u5f55\u91cc\u3002\nwith open('path_to_mch_private_key/apiclient_key.pem') as f:\n    PRIVATE_KEY = f.read()\n\n# \u5546\u6237\u8bc1\u4e66\u5e8f\u5217\u53f7\nCERT_SERIAL_NO = '444F4864EA9B34415...'\n\n# API v3\u5bc6\u94a5\uff0c https://pay.weixin.qq.com/wiki/doc/apiv3/wechatpay/wechatpay3_2.shtml\nAPIV3_KEY = 'MIIEvwIBADANBgkqhkiG9w0BAQE...'\n\n# APPID\uff0c\u5e94\u7528ID\uff0c\u670d\u52a1\u5546\u6a21\u5f0f\u4e0b\u4e3a\u670d\u52a1\u5546\u5e94\u7528ID\uff0c\u5373\u5b98\u65b9\u6587\u6863\u4e2d\u7684sp_appid\uff0c\u4e5f\u53ef\u4ee5\u5728\u8c03\u7528\u63a5\u53e3\u7684\u65f6\u5019\u8986\u76d6\u3002\nAPPID = 'wxd678efh567hg6787'\n\n# \u56de\u8c03\u5730\u5740\uff0c\u4e5f\u53ef\u4ee5\u5728\u8c03\u7528\u63a5\u53e3\u7684\u65f6\u5019\u8986\u76d6\u3002\nNOTIFY_URL = 'https://www.xxxx.com/notify'\n\n# \u5fae\u4fe1\u652f\u4ed8\u5e73\u53f0\u8bc1\u4e66\u7f13\u5b58\u76ee\u5f55\uff0c\u521d\u59cb\u8c03\u8bd5\u7684\u65f6\u5019\u53ef\u4ee5\u8bbe\u4e3aNone\uff0c\u9996\u6b21\u4f7f\u7528\u786e\u4fdd\u6b64\u76ee\u5f55\u4e3a\u7a7a\u76ee\u5f55\u3002\n# \u6ce8\uff1a2024\u5e7409\u6708\u540e\u65b0\u7533\u8bf7\u7684\u5fae\u4fe1\u652f\u4ed8\u8d26\u53f7\u4f7f\u7528\u516c\u94a5\u6a21\u5f0f\u521d\u59cb\u5316\uff0c\u6b64\u53c2\u6570\u65e0\u9700\u914d\u7f6e\u3002\nCERT_DIR = './cert'\n\n# \u65e5\u5fd7\u8bb0\u5f55\u5668\uff0c\u8bb0\u5f55web\u8bf7\u6c42\u548c\u56de\u8c03\u7ec6\u8282\uff0c\u4fbf\u4e8e\u8c03\u8bd5\u6392\u9519\u3002\nlogging.basicConfig(filename=os.path.join(os.getcwd(), 'demo.log'), level=logging.DEBUG, filemode='a', format='%(asctime)s - %(process)s - %(levelname)s: %(message)s')\nLOGGER = logging.getLogger(\"demo\")\n\n# \u63a5\u5165\u6a21\u5f0f\uff1aFalse=\u76f4\u8fde\u5546\u6237\u6a21\u5f0f\uff0cTrue=\u670d\u52a1\u5546\u6a21\u5f0f\u3002\nPARTNER_MODE = False\n\n# \u4ee3\u7406\u8bbe\u7f6e\uff0cNone\u6216\u8005{\"https\": \"http://10.10.1.10:1080\"}\uff0c\u8be6\u7ec6\u683c\u5f0f\u53c2\u89c1[https://requests.readthedocs.io/en/latest/user/advanced/#proxies](https://requests.readthedocs.io/en/latest/user/advanced/#proxies)\nPROXY = None\n\n# \u8bf7\u6c42\u8d85\u65f6\u65f6\u95f4\u914d\u7f6e\nTIMEOUT = (10, 30) # \u5efa\u7acb\u8fde\u63a5\u6700\u5927\u8d85\u65f6\u65f6\u95f4\u662f10s\uff0c\u8bfb\u53d6\u54cd\u5e94\u7684\u6700\u5927\u8d85\u65f6\u65f6\u95f4\u662f30s\n\n# \u5fae\u4fe1\u652f\u4ed8\u5e73\u53f0\u516c\u94a5\n# \u6ce8\uff1a2024\u5e7409\u6708\u540e\u65b0\u7533\u8bf7\u7684\u5fae\u4fe1\u652f\u4ed8\u8d26\u53f7\u4f7f\u7528\u516c\u94a5\u6a21\u5f0f\u521d\u59cb\u5316\uff0c\u9700\u914d\u7f6e\u6b64\u53c2\u6570\u3002\nwith open('path_to_wechat_pay_public_key/pub_key.pem') as f:\n    PUBLIC_KEY = f.read()\n\n# \u5fae\u4fe1\u652f\u4ed8\u5e73\u53f0\u516c\u94a5ID\n# \u6ce8\uff1a2024\u5e7409\u6708\u540e\u65b0\u7533\u8bf7\u7684\u5fae\u4fe1\u652f\u4ed8\u8d26\u53f7\u4f7f\u7528\u516c\u94a5\u6a21\u5f0f\u521d\u59cb\u5316\uff0c\u9700\u914d\u7f6e\u6b64\u53c2\u6570\u3002\nPUBLIC_KEY_ID = 'PUB_KEY_ID_444F4864EA9B34415...'\n```\n\n\u63a5\u4e0b\u6765\u521d\u59cb\u5316 WechatPay \u5b9e\u4f8b\u5e76\u914d\u7f6e\u4e00\u4e2a\u5408\u9002\u7684\u63a5\u53e3\uff1a\n\n```python\nwxpay = WeChatPay(\n    wechatpay_type=WeChatPayType.NATIVE,\n    mchid=MCHID,\n    private_key=PRIVATE_KEY,\n    cert_serial_no=CERT_SERIAL_NO,\n    apiv3_key=APIV3_KEY,\n    appid=APPID,\n    notify_url=NOTIFY_URL,\n    cert_dir=CERT_DIR,\n    logger=LOGGER,\n    partner_mode=PARTNER_MODE,\n    proxy=PROXY,\n    timeout=TIMEOUT)\n\n# \u5fae\u4fe1\u652f\u4ed8\u5e73\u53f0\u516c\u94a5\u6a21\u5f0f\u521d\u59cb\u5316\uff0c2024\u5e7409\u6708\u4e4b\u540e\u7533\u8bf7\u7684\u8d26\u53f7\u53c2\u8003\u4f7f\u7528\u6b64\u6a21\u5f0f\u3002\n# \u5e73\u53f0\u8bc1\u4e66\u6a21\u5f0f\u5411\u516c\u94a5\u6a21\u5f0f\u5207\u6362\u671f\u95f4\u4e5f\u8bf7\u4f7f\u7528\u6b64\u65b9\u5f0f\u521d\u59cb\u5316\u3002\nwxpay = WeChatPay(\n    wechatpay_type=WeChatPayType.NATIVE,\n    mchid=MCHID,\n    private_key=PRIVATE_KEY,\n    cert_serial_no=CERT_SERIAL_NO,\n    apiv3_key=APIV3_KEY,\n    appid=APPID,\n    notify_url=NOTIFY_URL,\n    logger=LOGGER,\n    partner_mode=PARTNER_MODE,\n    proxy=PROXY,\n    timeout=TIMEOUT,\n    public_key=PUBLIC_KEY,\n    public_key_id=PUBLIC_KEY_ID)\n\napp = Flask(__name__)\n\n@app.route('/pay')\ndef pay():\n    # \u4ee5native\u4e0b\u5355\u4e3a\u4f8b\uff0c\u4e0b\u5355\u6210\u529f\u540e\u5373\u53ef\u83b7\u53d6\u5230'code_url'\uff0c\u5c06'code_url'\u8f6c\u6362\u4e3a\u4e8c\u7ef4\u7801\uff0c\u5e76\u7528\u5fae\u4fe1\u626b\u7801\u5373\u53ef\u8fdb\u884c\u652f\u4ed8\u6d4b\u8bd5\u3002\n    out_trade_no = ''.join(sample(ascii_letters + digits, 8))\n    description = 'demo-description'\n    amount = 1\n    code, message = wxpay.pay(\n        description=description,\n        out_trade_no=out_trade_no,\n        amount={'total': amount},\n        pay_type=WeChatPayType.NATIVE\n    )\n    return jsonify({'code': code, 'message': message})\n```\n\n\u68c0\u67e5\u4e00\u4e0b\u53c2\u6570\u65e0\u8bef\uff0c\u73b0\u5728\u5c31\u53ef\u4ee5\u7528 python \u89e3\u91ca\u5668\u6765\u8fd0\u884c\uff1a\n\n```shell\n$ python examples.py\n * Serving Flask app \"examples\" (lazy loading)\n * Environment: production\n   WARNING: This is a development server. Do not use it in a production deployment.\n   Use a production WSGI server instead.\n * Debug mode: off\n * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)\n```\n\n\u73b0\u5728\u8bbf\u95ee <http://127.0.0.1:5000/pay> \uff0c\u5982\u679c\u4e00\u5207\u6b63\u5e38\uff0c\u4f60\u4f1a\u770b\u5230\u4e0b\u9762\u4e00\u4e32 json \u5b57\u7b26\u4e32\uff1a\n\n```python\n{\n  \"code\": 200,\n  \"message\": \"{\\\"code_url\\\":\\\"weixin://wxpay/bizpayurl?pr=abcdefghi\\\"}\"\n}\n```\n\n\u5230\u8fd9\u4e00\u6b65\u7edf\u4e00\u4e0b\u5355\u7684\u540e\u7aef\u5c31\u5b8c\u6210\u4e86\uff0c\u73b0\u5728\u5c06 code_url \u7684\u503c\u5373\"weixin://wxpay/bizpayurl?pr=abcdefghi\"\u7528[\u8349\u6599](https://cli.im/)\u8f6c\u6362\u4e3a\u4e8c\u7ef4\u7801\u5373\u53ef\u7528\u5fae\u4fe1\u626b\u7801\u8fdb\u884c\u652f\u4ed8\u6d4b\u8bd5\u3002\n\n**\u4ee5\u4e0a\u6b65\u9aa4\u5982\u679c\u4e0d\u80fd\u6b63\u786e\u6267\u884c\uff0c\u52a1\u5fc5\u4ed4\u7ec6\u68c0\u67e5\u5404\u9879\u521d\u59cb\u5316\u53c2\u6570\uff0c\u5fc5\u8981\u7684\u60c5\u51b5\u4e0b\uff0c\u767b\u5f55\u5fae\u4fe1\u652f\u4ed8\u540e\u53f0\uff0c\u5c06\u6240\u6709\u53c2\u6570\u91cd\u7f6e\u3002**\n\nNative \u652f\u4ed8\u8c03\u8bd5\u6700\u7b80\u5355\u4fbf\u6377\uff0c\u8c03\u8bd5\u901a\u8fc7\u6ca1\u6709\u95ee\u9898\u8bc1\u660e\u521d\u59cb\u5316\u53c2\u6570\u6b63\u786e\u4e4b\u540e\uff0c\u5982\u679c\u9700\u8981\u91c7\u7528\u5176\u4ed6\uff08\u5c0f\u7a0b\u5e8f\u3001H5\u3001JSAPI\u3001APP\uff09\u652f\u4ed8\u4e0b\u5355\uff0c\u53ef\u7ee7\u7eed\u53c2\u8003 examples.py\u3002\n\n## \u5e38\u89c1\u95ee\u9898\n\n\u65e5\u5e38\u5f00\u53d1\u5bf9\u63a5\u4e2d\u7684\u5e38\u89c1\u95ee\u9898\uff08**\u7279\u522b\u662f\u56de\u8c03\u9a8c\u8bc1\u5931\u8d25\u7684\u5904\u7406**\uff09\u8bf7\u89c1[\u8fd9\u91cc](docs/Q&A.md)\u3002\n\n## \u63a5\u53e3\u6e05\u5355\n\n\u5df2\u9002\u914d\u7684\u5fae\u4fe1\u652f\u4ed8 V3 \u7248 API \u63a5\u53e3\u5217\u8868\u660e\u7ec6\u8be6\u89c1[\u8fd9\u91cc](docs/apis.md)\u3002\n\n\u90e8\u5206\u63a5\u53e3\u7684\u5177\u4f53\u8c03\u7528\u65b9\u6cd5\u53ef\u4ee5\u53c2\u8003[\u8fd9\u91cc](docs/interface.md)\u3002\n\n\u6240\u6709\u63a5\u53e3\u7684\u53c2\u6570\u7c7b\u578b\u548c\u503c**\u5f3a\u70c8\u5efa\u8bae**\u4ed4\u7ec6\u770b\u4e00\u4e0b\u5b98\u65b9\u7684\u63a5\u53e3\u6587\u6863\u3002\n\n### \u63a5\u53e3\u51fd\u6570\u53c2\u6570\n\n\u53c2\u6570\u7c7b\u578b\u5bf9\u7167\u53c2\u8003\u4e0b\u8868\uff1a\n\n| \u5fae\u4fe1\u652f\u4ed8\u5b98\u65b9\u6587\u6863\u58f0\u660e | **wechatpayv3 python sdk** |\n| -------------------- | -------------------------- |\n| string | str |\n| int| int |\n| object | dict: {} |\n| array| list: [] |\n| boolean| bool: True, False |\n| message| bytes|\n\n### \u63a5\u53e3\u51fd\u6570\u8fd4\u56de\u503c\n\n\u6bcf\u4e2a\u63a5\u53e3\u5747\u540c\u6b65\u8fd4\u56de code \u548c message\uff0ccode \u4e3a web \u8bf7\u6c42\u5f97\u5230\u7684 HTTP \u72b6\u6001\u7801\uff0cmessage \u4e3a\u670d\u52a1\u5668\u8fd4\u56de\u7684 json \u5b57\u7b26\u4e32\u3002\n\u4f8b\u5916\uff1a\n\n1. \u56de\u8c03\u901a\u77e5\uff08callback\uff09\u63a5\u53e3\u5c06\u6536\u5230\u7684\u53c2\u6570\u89e3\u5bc6\u540e\u8fd4\u56de\uff0c\u56de\u8c03\u9a8c\u8bc1\u4e0d\u5408\u89c4\u6216\u89e3\u5bc6\u5931\u8d25\u5219\u8fd4\u56de None\uff1b\n2. \u4e0b\u8f7d\u8d26\u5355\uff08download_bill\uff09\u548c\u6d88\u8d39\u8005\u6295\u8bc9 2.0 \u7684\u56fe\u7247\u4e0b\u8f7d\uff08complaint_image_download\uff09\u63a5\u53e3\u8fd4\u56de\u7684 message \u4e3a bytes \u7c7b\u578b\uff0c\u76f4\u63a5\u5c06 message \u5199\u5165\u78c1\u76d8\u5373\u53ef\u83b7\u5f97\u5bf9\u5e94\u7684\u76ee\u6807\u6587\u4ef6\u3002\n3. \u8d26\u5355\u4e0b\u8f7d\u63a5\u53e3\u9ed8\u8ba4\u8fd4\u56de\u7684\u662fgzip\u683c\u5f0f\u7684\u6587\u4ef6\uff0c\u53ef\u7528gzip\u5e93\u89e3\u538b\u540e\u83b7\u53d6\u5b9e\u9645\u7684\u8d26\u5355\u6587\u4ef6\u3002\n",
    "bugtrack_url": null,
    "license": "MIT",
    "summary": "\u5fae\u4fe1\u652f\u4ed8 API v3 Python SDK(python sdk for wechatpay v3)",
    "version": "1.3.5",
    "project_urls": {
        "Homepage": "https://github.com/minibear2021/wechatpayv3"
    },
    "split_keywords": [
        "python",
        "sdk",
        "wechatpay",
        "api",
        "v3",
        "\u5fae\u4fe1\u652f\u4ed8"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "7a9e9f45390a129f15cd194fe6865c20aa6be011c1ffe42495bf761ad08a192c",
                "md5": "53de512210a4e0b5a23a210f4fb4703d",
                "sha256": "8adb92a9324cec3a27daad8209eace347efa6cad94b8079c72537d272b1c4ed1"
            },
            "downloads": -1,
            "filename": "wechatpayv3-1.3.5-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "53de512210a4e0b5a23a210f4fb4703d",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": null,
            "size": 57930,
            "upload_time": "2024-11-06T01:19:42",
            "upload_time_iso_8601": "2024-11-06T01:19:42.156893Z",
            "url": "https://files.pythonhosted.org/packages/7a/9e/9f45390a129f15cd194fe6865c20aa6be011c1ffe42495bf761ad08a192c/wechatpayv3-1.3.5-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "3880f40c7d12073df371b8bb53aacfc46f56e2b62e5c90137d6ca2f51682d17b",
                "md5": "9dc2e8c80543932161b34e9ff320137c",
                "sha256": "4902fe5555999aacc98c6ce1e5650592751ec4b5aa6786260d95341fb0baa1b5"
            },
            "downloads": -1,
            "filename": "wechatpayv3-1.3.5.tar.gz",
            "has_sig": false,
            "md5_digest": "9dc2e8c80543932161b34e9ff320137c",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": null,
            "size": 51525,
            "upload_time": "2024-11-06T01:19:43",
            "upload_time_iso_8601": "2024-11-06T01:19:43.470137Z",
            "url": "https://files.pythonhosted.org/packages/38/80/f40c7d12073df371b8bb53aacfc46f56e2b62e5c90137d6ca2f51682d17b/wechatpayv3-1.3.5.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2024-11-06 01:19:43",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "minibear2021",
    "github_project": "wechatpayv3",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "requirements": [
        {
            "name": "requests",
            "specs": [
                [
                    ">=",
                    "2.21.0"
                ]
            ]
        },
        {
            "name": "cryptography",
            "specs": [
                [
                    ">=",
                    "35.0.0"
                ]
            ]
        }
    ],
    "lcname": "wechatpayv3"
}
        
Elapsed time: 1.09362s