transfer.py 4.5 KB

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