微信支付接口V3版python库

Overview

wechatpayv3

PyPI version Download count

介绍

微信支付接口V3版python库。

适用对象

wechatpayv3支持微信支付直连商户,接口说明详见 官网

特性

  1. 平台证书自动更新,无需开发者关注平台证书有效性,无需手动下载更新;
  2. 支持本地缓存平台证书,初始化时指定平台证书保存目录即可。

适配进度

微信支付V3版API接口

其中:

基础支付

JSAPI支付 已适配
APP支付 已适配
H5支付 已适配
Native支付 已适配
小程序支付 已适配
合单支付 已适配
付款码支付 待官网更新
刷脸支付 无需适配

行业方案

智慧商圈 已适配

需要的接口适配怎么办?

由于wechatpayv3包内核心的core.py已经封装了请求签名和消息验证过程,开发者无需关心web请求细节,直接根据官方文档参考以下基础支付的申请退款接口代码自行适配,测试OK的话,欢迎提交代码。 必填的参数建议加上空值检查,可选的参数默认传入None。参数类型对照参考下表:

文档声明 wechatpayv3
string string
int int
object dict: {}
array list: []
boolean bool: True, False
def refund(self,
           out_refund_no,
           amount,
           transaction_id=None,
           out_trade_no=None,
           reason=None,
           funds_account=None,
           goods_detail=None,
           notify_url=None):
    """申请退款
    :param out_refund_no: 商户退款单号,示例值:'1217752501201407033233368018'
    :param amount: 金额信息,示例值:{'refund':888, 'total':888, 'currency':'CNY'}
    :param transaction_id: 微信支付订单号,示例值:'1217752501201407033233368018'
    :param out_trade_no: 商户订单号,示例值:'1217752501201407033233368018'
    :param reason: 退款原因,示例值:'商品已售完'
    :param funds_account: 退款资金来源,示例值:'AVAILABLE'
    :param goods_detail: 退款商品,示例值:{'merchant_goods_id':'1217752501201407033233368018', 'wechatpay_goods_id':'1001', 'goods_name':'iPhone6s 16G', 'unit_price':528800, 'refund_amount':528800, 'refund_quantity':1}
    :param notify_url: 通知地址,示例值:'https://www.weixin.qq.com/wxpay/pay.php'
    """
    params = {}
    params['notify_url'] = notify_url or self._notify_url
    # 
    if out_refund_no:
        params.update({'out_refund_no': out_refund_no})
    else:
        raise Exception('out_refund_no is not assigned.')
    if amount:
        params.update({'amount': amount})
    else:
        raise Exception('amount is not assigned.')
    if transaction_id:
        params.update({'transaction_id': transaction_id})
    if out_trade_no:
        params.update({'out_trade_no': out_trade_no})
    if reason:
        params.update({'reason': reason})
    if funds_account:
        params.update({'funds_account': funds_account})
    if goods_detail:
        params.update({'goods_detail': goods_detail})
    path = '/v3/refund/domestic/refunds'
    return self._core.request(path, method=RequestType.POST, data=params)

源码

github

gitee

安装

$ pip install wechatpayv3

使用方法

准备

参考微信官方文档准备好密钥, 证书文件和配置(证书/密钥/签名介绍)

初始化

from wechatpayv3 import WeChatPay, WeChatPayType

# 微信支付商户号
MCHID = '1230000109'
# 商户证书私钥
PRIVATE_KEY = 'MIIEvwIBADANBgkqhkiG9w0BAQE...'
# 商户证书序列号
CERT_SERIAL_NO = '444F4864EA9B34415...'
# API v3密钥, https://pay.weixin.qq.com/wiki/doc/apiv3/wechatpay/wechatpay3_2.shtml
APIV3_KEY = 'MIIEvwIBADANBgkqhkiG9w0BAQE...'
# APPID
APPID = 'wxd678efh567hg6787'
# 回调地址,也可以在调用接口的时候覆盖
NOTIFY_URL = 'https://www.weixin.qq.com/wxpay/pay.php'

wxpay = WeChatPay(
    wechatpay_type=WeChatPayType.MINIPROG,
    mchid=MCHID,
    parivate_key=PRIVATE_KEY,
    cert_serial_no=CERT_SERIAL_NO,
    apiv3_key=APIV3_KEY,
    appid=APPID,
    notify_url=NOTIFY_URL)

接口

# 统一下单
def pay():
    code, message = wxpay.pay(
        description='demo-description',
        out_trade_no='demo-trade-no',
        amount={'total': 100},
        payer={'openid': 'demo-openid'})
    print('code: %s, message: %s' % (code, message))

# 订单查询
def query():
    code, message = wxpay.query(transaction_id='demo-transation-id')
    print('code: %s, message: %s' % (code, message))

# 关闭订单
def close():
    code, message = wxpay.close(out_trade_no='demo-out-trade-no')
    print('code: %s, message: %s' % (code, message))

# 申请退款
def refund():
    code, message=wxpay.refund(
        out_refund_no='demo-out-refund-no',
        amount={'refund': 100, 'total': 100, 'currency': 'CNY'},
        transaction_id='1217752501201407033233368018')
    print('code: %s, message: %s' % (code, message))

# 退款查询
def query_refund():
    code, message = wxpay.query_refund(out_refund_no='demo-out-refund-no')
    print('code: %s, message: %s' % (code, message))

# 申请交易账单
def trade_bill():
    code, message = wxpay.trade_bill(bill_date='2021-04-01')
    print('code: %s, message: %s' % (code, message))

# 申请资金流水账单
def fundflow_bill():
    code, message = wxpay.fundflow_bill(bill_date='2021-04-01')
    print('code: %s, message: %s' % (code, message))

# 下载账单
def download_bill():
    code, message = wxpay.download_bill(url='https://api.mch.weixin.qq.com/v3/billdownload/file?token=demo-token')
    print('code: %s, message: %s' % (code, message))

# 合单支付下单
def combine_pay():
    code, message = wxpay.combine_pay(
        combine_out_trade_no='demo_out_trade_no',
        sub_orders=[{'mchid':'1900000109',
                     'attach':'深圳分店',
                     'amount':{'total_amount':100,'currency':'CNY'},
                     'out_trade_no':'20150806125346',
                     'description':'腾讯充值中心-QQ会员充值',
                     'settle_info':{'profit_sharing':False, 'subsidy_amount':10}}])
    print('code: %s, message: %s' % (code, message))

# 合单订单查询
def combine_query():
    code, message = wxpay.combine_query(combine_out_trade_no='demo_out_trade_no')
    print('code: %s, message: %s' % (code, message))

# 合单订单关闭
def combine_close():
    code, message = wxpay.combine_close(
        combine_out_trade_no='demo_out_trade_no', 
        sub_orders=[{'mchid': '1900000109', 'out_trade_no': '20150806125346'}])
    print('code: %s, message: %s' % (code, message))

# 计算签名供调起支付时拼凑参数使用
# 注意事项:注意参数顺序,某个参数为空时不能省略,以空字符串''占位
def sign():
    print(wxpay.sign(['wx888','1414561699','5K8264ILTKCH16CQ2502S....','prepay_id=wx201410272009395522657....']))

# 验证并解密回调消息,把回调接口收到的headers和body传入
def decrypt_callback(headers, body):
    print(wxpay.decrypt_callback(headers, body))

# 智慧商圈积分通知
def points_notify():
    code, message = wxpay.points_notify(
        transaction_id='4200000533202000000000000000',
        openid='otPAN5xxxxxxxxrOEG6lUv_pzacc',
        earn_points=True,
        increased_points=100,
        points_update_time='2020-05-20T13:29:35.120+08:00')
    print('code: %s, message: %s' % (code, message))

# 智慧商圈积分授权查询
def user_authorization():
    code, message = wxpay.user_authorizations(openid='otPAN5xxxxxxxxrOEG6lUv_pzacc')
    print('code: %s, message: %s' % (code, message))
Comments
  • 微信支付回调函数验证签名不正确,求助!

    微信支付回调函数验证签名不正确,求助!

    你好,

    在回调地址notify_url中接受request.header和request.body,并传入wxpay.decrypt_callback函数验证签名和解密返回值,验证签名失败,但解密返回值正确。

    服务器为centos 7,已设置平台证书路径为“\cert”,运行decrypt_callback函数时,系统已下载签名并存放到该文件夹。verify(timestamp, nonce, body, signature, certificate)时可以通过该证书生成公钥文件:<cryptography.hazmat.backends.openssl.rsa._RSAPublicKey object at 0x7f0dcf7b6eb0>

    然后在public_key.verify(signature, message, PKCS1v15(), SHA256())时,验证不过去。以下为拼凑的sign_str,还请帮助看看在哪一步出现了问题,非常感谢!

    例如,验签拼凑字符串为: 1627890132 Fnqw2Aw6k1fIxb8DhPAKogL76BeSnvQ6 {"id": "3e283601-7c3d-5c04-8ebf-225474439c26", "create_time": "2021-08-02T15:42:11+08:00", "resource_type": "encrypt-resource", "event_type": "TRANSACTION.SUCCESS", "summary": "支付成功", "resource": {"original_type": "transaction", "algorithm": "AEAD_AES_256_GCM", "ciphertext": "ECIKoyOZBc9soYj7gVqD1JRzXA+0LSPcbm6lPXqIqB/iLTWk9jR6En9z6vVPHpTDKIySzFb4/A9+fViPQJYMCa8tGqwA2HzMCB52PyRTRQ7nrBLBR7lQyHMZbWDqU35tujTmu4KGuO8nplOV4Q7rm+dXFt5RN7XJwbyufTQmU1FviWfzTwe7sT4ndnf4YhY7V0z7m2AhboQXGxdpSYccHLIGFpZctL4VFE1qJ4ikHdNJNvj6RF/yTElP2ssDVHd4lKckuqZ8u7xa5jmhvxzqkJIAFsVDEHKvM4wUkmgV6B6XIeuXMvxi1JNTW33hTnNWTZphcE467Ge/l2ajJckDNKJTeRv50nY+JLm6K2I7f2kmvxHm9OYpCkHlzXWqieMrPrwQs1KbfTqxYaUYW9vOESRXAAOV7q7YfMCkvfjnyX7KQEKYIsKYHPUnpWpJbBRriAH1oY5DC0SoLmlbaCEvwiaEJg7MFwhFVQYLxwk2DsIjbFC1UUxLIs5tZvKUrWFmbQOUTzmnCv/0qU7KbVZbeaHVEFzZ8d1UG1SK/db+medh65ueEwgko9DIvdCITnXTceS3AwTdre2T", "associated_data": "transaction", "nonce": "123RUOfxtcAL"}}

    opened by carter8225 7
  • 请问“敏感信息加解密”的实现代码在哪里?

    请问“敏感信息加解密”的实现代码在哪里?

    微信支付官方文档中有“敏感信息加解密”的相关要求: https://pay.weixin.qq.com/wiki/doc/apiv3_partner/wechatpay/wechatpay4_3.shtml

    “开发者应当使用微信支付平台证书中的公钥,对上送的敏感信息进行加密。这样只有拥有私钥的微信支付才能对密文进行解密,从而保证了信息的机密性。 另一方面,微信支付使用 商户证书中的公钥对下行的敏感信息进行加密。开发者应使用商户私钥对下行的敏感信息的密文进行解密。”

    大佬,请问wechatpayv3中有相关实现代码吗?找了半天没找到,请恕我愚钝。

    opened by Odyssey166 7
  • wechatpayv3也支持微信支付服务商吧?

    wechatpayv3也支持微信支付服务商吧?

    大佬,再问一个可能比较普遍的问题。wechatpayv3文档上说:”适用对象wechatpayv3支持微信支付直连商户“,然后给出了接口适配的方法。通过阅读微信支付官方文档,我发现直连商户和服务商的签名验签、加密解密过程都是一样的。API本质上貌似也没什么区别。例如,以下是服务商电商收付通的API列表: https://pay.weixin.qq.com/wiki/doc/apiv3_partner/open/pay/chapter3_3_3.shtml

    所以我认为wechatpayv3也支持微信支付服务商,只要开发者自己适配相关接口即可。

    请问我的理解是正确的吗?

    opened by Odyssey166 3
  • 微信支付分退款接口无法使用

    微信支付分退款接口无法使用

    该接口在return refund时掉了一个self参数。因此会报如下错误: File "/usr/local/lib/python3.9/site-packages/wechatpayv3/payscore.py", line 361, in payscore_refund sharedpowerbankdocker-web_api-1 | return refund(out_refund_no=out_refund_no, amount=amount, transaction_id=transaction_id, reason=reason, sharedpowerbankdocker-web_api-1 | TypeError: refund() missing 1 required positional argument: 'self'

    opened by MacGuffinLife 2
  • 【BUG】在本地证书需要更新时,程序会因无法通过证书验证而陷入死循环

    【BUG】在本地证书需要更新时,程序会因无法通过证书验证而陷入死循环

    方法路径:wechatpayv3 > core.py > _verify_signature(self, headers, body)

    方法源码:

        def _verify_signature(self, headers, body):
            signature = headers.get('Wechatpay-Signature')
            timestamp = headers.get('Wechatpay-Timestamp')
            nonce = headers.get('Wechatpay-Nonce')
            serial_no = headers.get('Wechatpay-Serial')
            cert_found = False
            for cert in self._certificates:
                if int('0x' + serial_no, 16) == cert.serial_number:
                    cert_found = True
                    certificate = cert
                    break
            if not cert_found:
                self._update_certificates()
                for cert in self._certificates:
                    if int('0x' + serial_no, 16) == cert.serial_number:
                        cert_found = True
                        certificate = cert
                        break
                if not cert_found:
                    return False
            if not rsa_verify(timestamp, nonce, body, signature, certificate):
                return False
            return True
    

    cert_foundFalse 时,程序将会执行 _update_certificates() 方法,在此更新证书的方法中,self._certificates 中的信息仍然错误,从而导致接下来的验证依旧不能通过,进而再次执行 _update_certificates() 方法,最终产生死循环

    opened by worship76 2
  • 小程序回调方法

    小程序回调方法

    请问一下,为什么我的回调方法接收到的request.data格式不对 { "id": "EV-2018022511223320873", "create_time": "2015-05-20T13:29:35+08:00", "resource_type": "encrypt-resource", "event_type": "TRANSACTION.SUCCESS", "summary": "支付成功", "resource": { "original_type": "transaction", "algorithm": "AEAD_AES_256_GCM", "ciphertext": "", "associated_data": "", "nonce": "" } }

    我得到的是这样的 {"data":[ {"effective_time":"2022-04-15T13:46:12+08:00", "encrypt_certificate": {"algorithm":"AEAD_AES_256_GCM", "associated_data":"certificate", "ciphertext":"MpxtKsvcoF3Jmuofu/L/NjZ+aUqJ4yrQG824VT4At5WHoDyd4x2ydRAJwwy+zuvZ4MsQfGyjjNkO2xAF9G7oN3cnwJAyL0Oo4ZWcrPoMZDLqccaYJaMogun/qz6u8FHP9x5CIBi3HAQzZl+FP9MhpIEuUhj/nMl8yksTWDU9R5MFdw+0CGymglJ6P3kGDIeQACXALRLT6eL0NGQSCQwFAoQpVEwDBVRIjh6beWYOKySP8KLJasL3MH3XthYcS/rvjO0lQxLER2ByZsfBg/yM+3eQuyFJUauqWlY8iPuO8GAYalhomdPWpe2TwAqwce0ZLdKfDOvDxd96TKKGeR5+BD8Ws5+b6y8PYnkcMd+WUyv8BVGl2dHf6tno3QHuqVxm61Km2Ze+6lEKjPXNr7CMX8k1rqeMhlrVxYbUhGWrNXXL+CKOJTNnQgMRO1aU46Kx0N/x9sepKL72RpYbTzcbcRwsZ4WFw+qqd2nO4afusV7HmYsztSvxxcD8fTg19kTEhI3HMWLHf8CCyQ+uRAm7ZiCi/g6WlMT5a2JYMzx4/kKucS1PCHs+3k7OYDocxXDUhVt9YlMJGPdZLMjmQzEt3CP/8zGl4ndJmOuLZsO1xGuJNN5P/h2K+JuZ0Y5toQrR6m9zlWdhmbaxiENVDzaxn9FEyR3Tj1ioRVpFhIBvmyLhZuRr+uHX/9ZcxNqKuP+pVntu+oEnd+aUSZsNV3U+S/vF2d78cFsJMgx1k9dbyYOflmAJB6qhf4MUxumqMXhu6verAs7K9RYy3B/8D+1DLv88gxRSSZVr0iqXYped6EGe0Gfp10oy0OKWAjsXmiIQaX/d4NGnFFfi0HdvaxhFokkh/Nktam0fxl40OZGeyKgqZl/NcfirjtLpRUu3YZV1ASYdbHLe8kqn0HYnMfKUdcw//5AIT9mDTnvP+wHadHicLRQHVzPR2z4IlBGm+Rr6J0yBC9LWzxFstBv/yHq9SmcqiC6C9RVOtrHpqb2HbE4kD0TbpTcofp3KGVsMOEf+hAYob94OEUU74H6tulxI1UiTr6JQzJykxP3M1FnEqb3/JN8aDZPIAwilgE/NjySpRvedkl4apvanNI8gHOK3SYyrD+RvrHrY3LcHjpiR6V5inCXYM3tmPmNiURBoIVLRLzbb84Q11lRJCVmWfE1zU62OCckmlqDJMck58QPI75EEk5sCQbBumuICKwfDfj//uU49KtvcHLVdj3WhmQtz660x2NU80ndB5WBk2AAv/rT3zFd3zGzXeM+jBy/4623dXnDEaSXHQk4BP7FLULhIsQiM/JNP+hbkyHTDq+bbJ3JzQpZtR8aTlP5wZpwWvclDCnisi65JHeEublKe2wIKoiYo9RYsHDzsqy6FlJlSqaJMu6mC6oYsF3ZG21x2Dv+WRIsf3SaPpGLpcOkVJNtT+tdT12z1i//rbLK53DADhTN2h2djPiHkx2KiMlNxocFQXtFcJIR0zmde8UQ54sLg4SMh1An+bJitpNleeCcNZuDJIQCAkpCShztQB9lFdEbeG7bWI28sMYVVOVuSYgqanmEh5CyNteqcqG21A91uMQmmQLG3dJmD9VyTvakBf3R6Qm7rLoXXUJ+yoAVJie6Te12ALLzuyE8pwI8OfvpK+BNLXBS7W3KzENTsIkx/i/IqtgGFzRkQ9guVCwA71JHiuU3+K0KLKXjN4ynLDbk2r0ZIL9m8aBHoguyoIWtFwI76Fz3B4ZwXDX7U9N9VqNGO+UjCljrTZjRQy+FSOh1DJIXKaePEROggGSOjcD3QEE9Q1va2WW7M/uv+yHh8u/V9HnsBnTQrPK09U0BIqy+3ALEhfGgZef6L5kHUY/nWDLcRwtnSq/W0NPf16XjcgQ/29Krq3OXadQ==", "nonce":"0401acb66488"}, "expire_time":"2027-04-14T13:46:12+08:00","serial_no":"474A7CDC898039BEC0F1D6F4A0F7F8C9D8113412"} ] } 麻烦帮忙看一下,非常感谢

    opened by Warzonee 1
  • applyment_submit

    applyment_submit

    path should end with ‘/’, path = '/v3/applyment4sub/applyment/', otherwise will return 404. Also,some field should encrypt too, add logic as follows in applyment_submit function: if params.get('subject_info').get('identity_info'): id_card_info = params.get('subject_info').get('identity_info').get('id_card_info') if id_card_info is not None: id_card_info['id_card_name'] = self._core.encrypt(id_card_info['id_card_name']) id_card_info['id_card_number'] = self._core.encrypt(id_card_info['id_card_number']) cipher_data = True

    opened by realwrtoff 1
Releases(1.2.35)
Owner
chen gang
chen gang
HTTP Calls to Amazon Web Services Rest API for IoT Core Shadow Actions 💻🌐💡

aws-iot-shadow-rest-api HTTP Calls to Amazon Web Services Rest API for IoT Core Shadow Actions 💻 🌐 💡 This simple script implements the following aw

AIIIXIII 3 Jun 06, 2022
Bot to notify when vaccine appointments are available

Vaccine Watch Bot to notify when vaccine appointments are available. Supports checking Hy-Vee, Walgreens, CVS, Walmart, Cosentino's stores (KC), and B

Peter Carnesciali 37 Aug 13, 2022
A melhor maneira de atender seus clientes no Telegram!

Clientes.Chat Sobre o serviço Configuração Banco de Dados Variáveis de Ambiente Docker Python Heroku Contribuição Sobre o serviço A maneira mais organ

Gabriel R F 10 Oct 12, 2022
Dns-Client-Server - Dns Client Server For Python

Dns-client-server DNS Server: supporting all types of queries and replies. Shoul

Nishant Badgujar 1 Feb 15, 2022
The Python version of the official Discord bot for the Astura Studios Discord community server.

About Astura (Python version) is the official Discord bot for the Astura Studios Discord community server developed and maintained by Ascendus and the

Ascendus 1 Apr 21, 2022
Ini Hanya Shortcut Untuk Menambahkan Kunci Tambahan Pada Termux & Membantu Para Nub Yang Decode Script Orang:v

Ini Hanya Shortcut Untuk Menambahkan Kunci Tambahan Pada Termux & Membantu Para Nub Yang Decode Script Orang:v

Lord_Ammar 1 Jan 23, 2022
Telegram bot that let's you flip a coin in a dialog

coin_flip Telegram bot that let's you flip a coin in a dialog Report issue · Request feature About Software development tool that lets you finally dec

Ivan Akostelov 2 Dec 12, 2021
Cryptocurrency Trading Bot - A trading bot to automate cryptocurrency trading strategies using Python, equipped with a basic GUI

Cryptocurrency Trading Bot - A trading bot to automate cryptocurrency trading strategies using Python, equipped with a basic GUI. Used REST and WebSocket API to connect to two of the most popular cry

Francis 8 Sep 15, 2022
This Code is Property of Rehyann Saini. Feel Free to use this Project.

Email-Spammer Rehyann Saini in Collabration With Fe13 Productions This is an easy to use Dev Friendly Email spammer... #Important Things to know..! St

Rehyann Saini 1 Jan 14, 2022
A zero-dependency Python library for getting the Kubernetes token of a AWS EKS cluster

tokeks A zero-dependency Python library for getting the Kubernetes token of a AWS EKS cluster. No AWS CLI, third-party client or library (boto3, botoc

Chris Karageorgiou Kaneen 6 Nov 04, 2022
Sends notifications when Pokemon Center products are in stock

Sends notifications when Pokemon Center products are in stock! If you use this for scalping, I will break your kneecaps

2 Jan 20, 2022
LimitatiBot - A simple telegram bot to establish a conversation with a user without having to use private chats

🤖 LimitatiBot [0.2] LimitatiBot is a simple telegram bot to establish a convers

xMrPente 9 Dec 27, 2022
A Python Library to Make Quote Images

Quote2Image A Python Library to Make Quote Images How To Use? Download The Latest Package From Releases Extract The Zip File And Place Every File In I

Secrets 28 Dec 30, 2022
This Telegram bot allows you to create direct links with pre-filled text to WhatsApp Chats

WhatsApp API Bot Telegram bot to create direct links with pre-filled text for WhatsApp Chats You can check our bot here. The bot is based on the API p

RobotTrick • רובוטריק 17 Aug 20, 2022
Easy to use Google Pub/Sub

Relé makes integration with Google PubSub straightforward and easy. Motivation and Features The Publish-Subscribe pattern and specifically the Google

Mercadona 188 Jan 06, 2023
A Telegram Bot to Extract Various Types Of Archives

IDN Unzip Bot A Telegram Bot to Extract Various Types Of Archives Features Extract various types of archives like rar, zip, tar, 7z, tar.xz etc. Passw

IDNCoderX 8 Jul 25, 2022
GroupMenter : New Telegram Group Manager Bot🔸Fast 🔸Python🔸Pyrogram 🔸

GroupMenter An PowerFull Group Manager Bot. Written In Pytelethon. Info • A modular Telegram Python bot running on python3. • Can be found on telegram

Group Menter 24 Jun 28, 2022
A Discord bot that rewards players in Minecraft for sending messages on Discord

MCRewards-Discord-Bot A Discord bot that rewards players in Minecraft for sending messages on Discord How to setup: Download this git as a .zip, or cl

3 Dec 26, 2021
A Telegram bot to extracting text from images. All languages supported.

OCR Bot A Telegram bot to extracting text from images. All languages supported. Deploy to Heroku Local Deploying Clone the repo git clone https://gith

6 Oct 21, 2022