1
|
|
|
# -*- coding: utf-8 -*- |
2
|
10 |
|
from __future__ import absolute_import, unicode_literals |
3
|
10 |
|
import random |
4
|
10 |
|
from datetime import datetime |
5
|
|
|
|
6
|
10 |
|
from wechatpy.pay.utils import get_external_ip, rsa_encrypt |
7
|
10 |
|
from wechatpy.pay.base import BaseWeChatPayAPI |
8
|
|
|
|
9
|
|
|
|
10
|
10 |
|
class WeChatTransfer(BaseWeChatPayAPI): |
11
|
|
|
|
12
|
10 |
|
def transfer(self, user_id, amount, desc, client_ip=None, |
13
|
|
|
check_name='OPTION_CHECK', real_name=None, |
14
|
|
|
out_trade_no=None, device_info=None): |
15
|
|
|
""" |
16
|
|
|
企业付款接口 |
17
|
|
|
|
18
|
|
|
:param user_id: 接受收红包的用户在公众号下的 openid |
19
|
|
|
:param amount: 付款金额,单位分 |
20
|
|
|
:param desc: 付款说明 |
21
|
|
|
:param client_ip: 可选,调用接口机器的 IP 地址 |
22
|
|
|
:param check_name: 可选,校验用户姓名选项, |
23
|
|
|
NO_CHECK:不校验真实姓名, |
24
|
|
|
FORCE_CHECK:强校验真实姓名(未实名认证的用户会校验失败,无法转账), |
25
|
|
|
OPTION_CHECK:针对已实名认证的用户才校验真实姓名(未实名认证用户不校验,可以转账成功), |
26
|
|
|
默认为 OPTION_CHECK |
27
|
|
|
:param real_name: 可选,收款用户真实姓名, |
28
|
|
|
如果check_name设置为FORCE_CHECK或OPTION_CHECK,则必填用户真实姓名 |
29
|
|
|
:param out_trade_no: 可选,商户订单号,需保持唯一性,默认自动生成 |
30
|
|
|
:param device_info: 可选,微信支付分配的终端设备号 |
31
|
|
|
:return: 返回的结果信息 |
32
|
|
|
""" |
33
|
|
|
if not out_trade_no: |
34
|
|
|
now = datetime.now() |
35
|
|
|
out_trade_no = '{0}{1}{2}'.format( |
36
|
|
|
self.mch_id, |
37
|
|
|
now.strftime('%Y%m%d%H%M%S'), |
38
|
|
|
random.randint(1000, 10000) |
39
|
|
|
) |
40
|
|
|
data = { |
41
|
|
|
'mch_appid': self.appid, |
42
|
|
|
'mchid': self.mch_id, |
43
|
|
|
'device_info': device_info, |
44
|
|
|
'partner_trade_no': out_trade_no, |
45
|
|
|
'openid': user_id, |
46
|
|
|
'check_name': check_name, |
47
|
|
|
're_user_name': real_name, |
48
|
|
|
'amount': amount, |
49
|
|
|
'desc': desc, |
50
|
|
|
'spbill_create_ip': client_ip or get_external_ip(), |
51
|
|
|
} |
52
|
|
|
return self._post('mmpaymkttransfers/promotion/transfers', data=data) |
53
|
|
|
|
54
|
10 |
|
def query(self, out_trade_no): |
55
|
|
|
""" |
56
|
|
|
企业付款查询接口 |
57
|
|
|
|
58
|
|
|
:param out_trade_no: 商户调用企业付款API时使用的商户订单号 |
59
|
|
|
:return: 返回的结果数据 |
60
|
|
|
""" |
61
|
|
|
data = { |
62
|
|
|
'appid': self.appid, |
63
|
|
|
'partner_trade_no': out_trade_no, |
64
|
|
|
} |
65
|
|
|
return self._post('mmpaymkttransfers/gettransferinfo', data=data) |
66
|
|
|
|
67
|
10 |
|
def transfer_bankcard(self, true_name, bank_card_no, bank_code, amount, desc=None, out_trade_no=None): |
68
|
|
|
""" |
69
|
|
|
企业付款到银行卡接口 |
70
|
|
|
|
71
|
|
|
:param true_name: 开户人名称 |
72
|
|
|
:param bank_card_no: 银行卡号 |
73
|
|
|
:param bank_code: 银行编号 |
74
|
|
|
:param amount: 付款金额,单位分 |
75
|
|
|
:param desc: 付款说明 |
76
|
|
|
:param out_trade_no: 可选,商户订单号,需保持唯一性,默认自动生成 |
77
|
|
|
:return: 返回的结果信息 |
78
|
|
|
""" |
79
|
|
|
if not out_trade_no: |
80
|
|
|
now = datetime.now() |
81
|
|
|
out_trade_no = '{0}{1}{2}'.format( |
82
|
|
|
self.mch_id, |
83
|
|
|
now.strftime('%Y%m%d%H%M%S'), |
84
|
|
|
random.randint(1000, 10000) |
85
|
|
|
) |
86
|
|
|
data = { |
87
|
|
|
'mch_id': self.mch_id, |
88
|
|
|
'partner_trade_no': out_trade_no, |
89
|
|
|
'amount': amount, |
90
|
|
|
'desc': desc, |
91
|
|
|
'enc_bank_no': self._rsa_encrypt(bank_card_no), |
92
|
|
|
'enc_true_name': self._rsa_encrypt(true_name), |
93
|
|
|
'bank_code': bank_code, |
94
|
|
|
} |
95
|
|
|
return self._post('mmpaysptrans/pay_bank', data=data) |
96
|
|
|
|
97
|
10 |
|
def query_bankcard(self, out_trade_no): |
98
|
|
|
""" |
99
|
|
|
企业付款查询接口 |
100
|
|
|
|
101
|
|
|
:param out_trade_no: 商户调用企业付款API时使用的商户订单号 |
102
|
|
|
:return: 返回的结果数据 |
103
|
|
|
""" |
104
|
|
|
data = { |
105
|
|
|
'mch_id': self.mch_id, |
106
|
|
|
'partner_trade_no': out_trade_no, |
107
|
|
|
} |
108
|
|
|
return self._post('mmpaysptrans/query_bank', data=data) |
109
|
|
|
|
110
|
10 |
|
def get_rsa_public_key(self): |
111
|
|
|
data = { |
112
|
|
|
'mch_id': self.mch_id, |
113
|
|
|
'sign_type': 'MD5', |
114
|
|
|
} |
115
|
|
|
return self._post('https://fraud.mch.weixin.qq.com/risk/getpublickey', data=data) |
116
|
|
|
|
117
|
10 |
|
def _rsa_encrypt(self, data): |
118
|
|
|
if not getattr(self, '_rsa_public_key', None): |
119
|
|
|
self._rsa_public_key = self.get_rsa_public_key()['pub_key'] |
120
|
|
|
return rsa_encrypt(data, self._rsa_public_key) |
121
|
|
|
|