diff --git a/README.md b/README.md index 9f02645..5fe436b 100644 --- a/README.md +++ b/README.md @@ -44,7 +44,7 @@ pip install wechatpayv3 根据[Q&A](docs/Q&A.md)第一条判断当前账户所使用的模式(微信支付平台证书模式 或 微信支付平台公钥模式)。 -参考微信官方文档准备好商户证书私钥、商户证书序列号、APIv3密钥, 如果使用微信支付公钥模式,还需要准备好微信支付平台公钥和微信支付公钥ID,这些参数配置方法请参考官方文档。 +参考微信官方文档准备好商户证书私钥、商户证书序列号、APIv3密钥, 如果使用微信支付平台公钥模式,还需要准备好微信支付平台公钥和微信支付公钥ID,这些参数配置方法请参考官方文档。 - **商户 API 证书私钥:PRIVATE_KEY**。商户申请商户 API 证书时,会生成商户私钥,并保存在本地证书文件夹的文件 apiclient_key.pem 中。 > :warning: 不要把私钥文件暴露在公共场合,如上传到 Github,写在客户端代码等。 @@ -53,8 +53,8 @@ pip install wechatpayv3 在2024年09月后申请开通的微信支付可能[无法使用接口下载平台证书](docs/Q&A.md#下载平台证书时解析失败),这种情况下,需要从微信支付后台的“API安全”菜单中下载/复制以下两项,使用公钥模式初始化WechatPay。 -- **微信支付公钥:PUBLIC_KEY**,微信支付后台“API安全-微信支付公钥”菜单中下载的微信支付公钥。 -- **微信支付公钥ID:PUBLIC_KEY_ID**,微信支付后台“API安全-微信支付公钥”菜单中复制的微信支付公钥ID,形如:PUB_KEY_ID_1234567890...。 +- **微信支付平台公钥:PUBLIC_KEY**,微信支付后台“API安全-微信支付公钥”菜单中下载的微信支付公钥。 +- **微信支付平台公钥ID:PUBLIC_KEY_ID**,微信支付后台“API安全-微信支付公钥”菜单中复制的微信支付公钥ID,形如:PUB_KEY_ID_1234567890...。 ### 一个最小的后端 diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index e4a1270..981d13e 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +## [1.3.7] - 2025-01-15 + +### Added + +- 支持新版商家转账功能 + ## [1.3.6] - 2024-12-23 ### Fixed diff --git a/docs/apis.md b/docs/apis.md index 0965bab..51f20f1 100644 --- a/docs/apis.md +++ b/docs/apis.md @@ -109,6 +109,11 @@ | 资金应用 | 商家转账到零钱 | 查询转账电子回单| transfer_query_bill_receipt | 是| 否| | 资金应用 | 商家转账到零钱 | 转账明细电子回单受理| transfer_detail_receipt | 是| 否| | 资金应用 | 商家转账到零钱 | 查询转账明细电子回单受理结果| transfer_query_receipt | 是| 否| +| 资金应用 | 商家转账 | 发起转账 | mch_transfer_bills | 是 | 否 +| 资金应用 | 商家转账 | 撤销转账 | mch_transfer_bills_cancel | 是 | 否 +| 资金应用 | 商家转账 | 查询转账单 | mch_transfer_bills_query | 是 | 否 +| 资金应用 | 商家转账 | 申请电子回单 | mch_transfer_elecsign | 是 | 否 +| 资金应用 | 商家转账 | 查询电子回单 | mch_transfer_elecsign_query | 是 | 否 | 资金应用 | 分账 | 请求分账 | profitsharing_order | 是| 是| | 资金应用 | 分账 | 查询分账结果| profitsharing_order_query | 是| 是| | 资金应用 | 分账 | 请求分账回退| profitsharing_return| 是| 是| diff --git a/setup.py b/setup.py index 00562a4..36a255a 100644 --- a/setup.py +++ b/setup.py @@ -6,7 +6,7 @@ setup( name="wechatpayv3", - version="1.3.6", + version="1.3.7", author="minibear", description="微信支付 API v3 Python SDK(python sdk for wechatpay v3)", long_description=long_description, diff --git a/wechatpayv3/__init__.py b/wechatpayv3/__init__.py index 7d92f8c..46ebbd3 100644 --- a/wechatpayv3/__init__.py +++ b/wechatpayv3/__init__.py @@ -195,3 +195,6 @@ def decrypt(self, ciphtext): transfer_query_out_batch_no, transfer_query_out_detail_no, transfer_query_receipt) + from .mchtransfer import (mch_transfer_bills, mch_transfer_bills_cancel, + mch_transfer_bills_query, mch_transfer_elecsign, + mch_transfer_elecsign_query) diff --git a/wechatpayv3/mchtransfer.py b/wechatpayv3/mchtransfer.py new file mode 100644 index 0000000..a3364b1 --- /dev/null +++ b/wechatpayv3/mchtransfer.py @@ -0,0 +1,104 @@ +# -*- coding: utf-8 -*- + +from .type import RequestType + +def mch_transfer_bills(self, out_bill_no, transfer_scene_id, openid, transfer_amount, transfer_remark, user_name=None, user_recv_perception=None, transfer_scene_report_infos=[], appid=None, notify_url=None): + """发起转账 + :param out_bill_no: 商户单号,商户系统内部的商家单号,要求此参数只能由数字、大小写字母组成,在商户系统内部唯一,示例值:'plfk2020042013' + :param transfer_scene_id: 转账场景ID,示例值:'1001' + :param openid: 收款用户OpenID,商户AppID下,某用户的OpenID,示例值:'o-MYE42l80oelYMDE34nYD456Xoy' + :param transfer_amount: 转账金额,单位为“分”,示例值: 1000 + :param transfer_remark: 转账备注,用户收款时可见该备注信息,最多允许32个字符,示例值:'2020年4月报销' + :param user_name: 收款用户姓名,转账金额 >= 2,000元时,该笔明细必须填写。若商户传入收款用户姓名,微信支付会校验收款用户与输入姓名是否一致,并提供电子回单,示例值:'张三' + :param user_recv_perception: 用户收款时感知到的收款原因,将根据转账场景自动展示默认内容。如有其他展示需求,可在本字段传入。示例值: '现金奖励' + :param transfer_scene_report_infos: 转账场景报备信息,示例值: [{'info_type':'奖励说明', 'info_content':'注册会员抽奖'}] + :param appid: 应用ID,可不填,默认传入初始化时的appid,示例值:'wx1234567890abcdef' + :param notify_url: 通知地址,异步接收微信支付结果通知的回调地址,示例值:'https://www.weixin.qq.com/wxpay/pay.php' + """ + params={} + if out_bill_no: + params.update({'out_bill_no':out_bill_no}) + else: + raise Exception('out_batch_no is not assigned') + if transfer_scene_id: + params.update({'transfer_scene_id':transfer_scene_id}) + else: + raise Exception('transfer_scene_id is not assigned') + if openid: + params.update({'openid':openid}) + else: + raise Exception('openid is not assigned') + if transfer_amount: + params.update({'transfer_amount':transfer_amount}) + else: + raise Exception('transfer_amount is not assigned') + if transfer_remark: + params.update({'transfer_remark':transfer_remark}) + else: + raise Exception('transfer_remark is not assigned') + cipher_data = False + if user_name: + params.update({'user_name':self._core.encrypt(user_name)}) + cipher_data = True + if transfer_amount >= 200000 and not user_name: + raise Exception('user_name is not assigned') + if user_recv_perception: + params.update({'user_recv_perception':user_recv_perception}) + if transfer_scene_report_infos: + params.update({'transfer_scene_report_infos':transfer_scene_report_infos}) + params.update({'appid': appid or self._appid}) + params.update({'notify_url': notify_url or self._notify_url}) + path = '/v3/fund-app/mch-transfer/transfer-bills' + return self._core.request(path, method=RequestType.POST, data=params, cipher_data=cipher_data) + +def mch_transfer_bills_cancel(self, out_bill_no): + """撤销转账 + :param out_bill_no: 商户单号,商户系统内部的商家单号,要求此参数只能由数字、大小写字母组成,在商户系统内部唯一,示例值:'plfk2020042013' + """ + if out_bill_no: + path = f'/v3/fund-app/mch-transfer/transfer-bills/out-bill-no/{out_bill_no}/cancel' + else: + raise Exception('out_bill_no is not assigned') + return self._core.request(path) + +def mch_transfer_bills_query(self, out_bill_no=None, transfer_bill_no=None): + """查询转账单 + :param out_bill_no: 商户单号,商户系统内部的商家单号,要求此参数只能由数字、大小写字母组成,在商户系统内部唯一,示例值:'plfk2020042013' + :param transfer_bill_no: 微信转账单号,微信商家转账系统返回的唯一标识,示例值: '1330000071100999991182020050700019480001' + """ + if not (out_bill_no or transfer_bill_no): + raise Exception('out_bill_no or transfer_bill_no is not assigned') + if out_bill_no: + path = f'/v3/fund-app/mch-transfer/transfer-bills/out-bill-no/{out_bill_no}' + else: + path = f'/v3/fund-app/mch-transfer/transfer-bills/transfer-bill-no/{transfer_bill_no}' + return self._core.request(path) + +def mch_transfer_elecsign(self, out_bill_no=None, transfer_bill_no=None): + """申请电子回单 + :param out_bill_no: 商户单号,商户系统内部的商家单号,要求此参数只能由数字、大小写字母组成,在商户系统内部唯一,示例值:'plfk2020042013' + :param transfer_bill_no: 微信转账单号,微信商家转账系统返回的唯一标识,示例值: '1330000071100999991182020050700019480001' + """ + if not (out_bill_no or transfer_bill_no): + raise Exception('out_bill_no or transfer_bill_no is not assigned') + params = {} + if out_bill_no: + params.update({'out_bill_no':out_bill_no}) + path = '/v3/fund-app/mch-transfer/elecsign/out-bill-no' + else: + params.update({'transfer_bill_no':transfer_bill_no}) + path = '/v3/fund-app/mch-transfer/elecsign/transfer-bill-no' + return self._core.request(path, method=RequestType.POST, data=params) + +def mch_transfer_elecsign_query(self, out_bill_no=None, transfer_bill_no=None): + """查询电子回单 + :param out_bill_no: 商户单号,商户系统内部的商家单号,要求此参数只能由数字、大小写字母组成,在商户系统内部唯一,示例值:'plfk2020042013' + :param transfer_bill_no: 微信转账单号,微信商家转账系统返回的唯一标识,示例值: '1330000071100999991182020050700019480001' + """ + if not (out_bill_no or transfer_bill_no): + raise Exception('out_bill_no or transfer_bill_no is not assigned') + if out_bill_no: + path = f'/v3/fund-app/mch-transfer/elecsign/out-bill-no/{out_bill_no}' + else: + path = f'/v3/fund-app/mch-transfer/elecsign/transfer-bill-no/{transfer_bill_no}' + return self._core.request(path)