pay.py 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
  1. # -*- coding: utf-8 -*-
  2. # !/usr/bin/env python
  3. from __future__ import unicode_literals
  4. import logging
  5. from apilib.systypes import IterConstant
  6. from library.jdopen import JDOpenErrorCode
  7. from library.jdopen.exceptions import JdOpenException
  8. from library.jdopen.client import JdOpenBaseClient
  9. logger = logging.getLogger(__name__)
  10. __all__ = ('JDOpenPay')
  11. class SubOrderType(IterConstant):
  12. NORMAL = 'NORMAL'
  13. LEDGER = 'LEDGER'
  14. class JDOpenPay(JdOpenBaseClient):
  15. API_BASE_URL = 'https://openapi.duolabao.com'
  16. def __init__(self, agentNum, accessKey, secretKey, customerNum, shopNum, timeout=None, auto_retry=True):
  17. super(JDOpenPay, self).__init__(accessKey, secretKey, timeout, auto_retry)
  18. self.agentNum = agentNum
  19. self.customerNum = customerNum
  20. self.shopNum = shopNum
  21. def create_pay_url(self, out_trade_no, total_fee, notify_url, extraInfo=None, **kwargs):
  22. """
  23. 创建主扫链接
  24. :param out_trade_no:
  25. :param total_fee:
  26. :param notify_url:
  27. :param extraInfo:
  28. :param kwargs: 接受tableNum, machineNum参数
  29. :return:
  30. """
  31. url = '/v3/order/payurl/create'
  32. data = {
  33. 'agentNum': self.agentNum,
  34. 'customerNum': self.customerNum,
  35. 'shopNum': self.shopNum,
  36. 'requestNum': out_trade_no,
  37. 'amount': total_fee,
  38. 'callbackUrl': notify_url,
  39. 'source': 'API',
  40. 'payModel': 'ONCE'
  41. }
  42. if extraInfo:
  43. data.update({
  44. 'extraInfo': extraInfo
  45. })
  46. data.update(kwargs)
  47. result = self.post(url=url, data=data)
  48. return result['data']['url']
  49. def unified_order(self, authId, bankType, requestNum, amount, callbackUrl, subject, ledgerRule=None,
  50. extraInfo=None, **kwargs):
  51. """
  52. :param authId:
  53. :param bankType:
  54. :param requestNum:
  55. :param amount:
  56. :param callbackUrl:
  57. :param subject:
  58. :param ledgerRule:
  59. :param extraInfo:
  60. :param kwargs: 接受ledgerRule
  61. {
  62. "ledgerType":"FIXED", -- 分账类型 固定金额:FIXED 比例:RATE 目前只支持固定金额分账
  63. "ledgerFeeAssume":"RECEIVER", 收款方承担:RECEIVER 分账方承担:LEDGER 默认为RECEIVER,目前仅支持收款方承担手续费
  64. "list":[ -- 分账list必须全部包括收款方和分账方,分账金额保留两位小数,且分账金额相加需等于订单金额
  65. {
  66. "customerNum":"10001115199597283447316",
  67. "amount":"0.01"
  68. },
  69. {
  70. "customerNum":"10001114504252653551690",
  71. "amount":"0.01"
  72. }
  73. ]
  74. }
  75. :return:
  76. """
  77. url = '/v3/order/pay/create'
  78. data = {
  79. 'version': 'V4.0',
  80. 'agentNum': str(self.agentNum),
  81. 'customerNum': str(self.customerNum),
  82. # 'shopNum': str(self.shopNum),
  83. 'authId': str(authId),
  84. 'bankType': str(bankType),
  85. 'requestNum': str(requestNum),
  86. 'amount': str(amount),
  87. 'callbackUrl': str(callbackUrl),
  88. 'payModel': 'ONCE'
  89. }
  90. if self.shopNum:
  91. data.update({
  92. 'shopNum': str(self.shopNum)
  93. })
  94. if ledgerRule:
  95. data.update({
  96. 'subOrderType': str(SubOrderType.LEDGER),
  97. 'ledgerRule': ledgerRule
  98. })
  99. else:
  100. data.update({
  101. 'subOrderType': str(SubOrderType.NORMAL)
  102. })
  103. data.update(kwargs)
  104. if extraInfo:
  105. data.update({
  106. 'extraInfo': extraInfo
  107. })
  108. return self.post(url=url, data=data)
  109. def api_trade_query(self, out_trade_no=None, trade_no=None):
  110. assert out_trade_no or trade_no, 'out_trade_no and trade_no must not be empty at the same time'
  111. url = '/v3/order/query'
  112. data = {
  113. 'agentNum': self.agentNum,
  114. 'customerNum': self.customerNum,
  115. 'shopNum': self.shopNum,
  116. 'requestNum': out_trade_no,
  117. 'orderNum': trade_no
  118. }
  119. if out_trade_no:
  120. data.update({'requestNum': out_trade_no})
  121. else:
  122. data.update({'orderNum': trade_no})
  123. return self.post(url=url, data=data)
  124. def api_trade_refund(self, outTradeNo, outRefundNo, amount, **kwargs):
  125. """
  126. 退款
  127. :param outTradeNo:
  128. :param outRefundNo:
  129. :param amount:
  130. :param kwargs:
  131. :return:
  132. """
  133. url = '/v3/order/refund/part'
  134. data = {
  135. 'version': 'V4.0',
  136. 'agentNum': self.agentNum,
  137. 'customerNum': self.customerNum,
  138. 'shopNum': self.shopNum,
  139. 'requestNum': outTradeNo,
  140. 'refundRequestNum': outRefundNo,
  141. 'refundPartAmount': amount
  142. }
  143. ledgerInfoList = kwargs.pop('ledgerInfoList', None)
  144. if ledgerInfoList:
  145. data.update({'ledgerInfoList': ledgerInfoList})
  146. data.update(kwargs)
  147. return self.post(url=url, data=data)
  148. def api_refund_query(self, requestNum=None, orderNum=None):
  149. """
  150. 查询退款订单
  151. :param requestNum: 原商户订单号
  152. :param orderNum: 原订单编号
  153. :return:
  154. """
  155. assert not (requestNum and orderNum), u'不能同时提供商户订单号和京东订单号'
  156. url = '/v3/order/refund/query'
  157. data = {
  158. 'agentNum': self.agentNum,
  159. 'customerNum': self.customerNum,
  160. 'shopNum': self.shopNum
  161. }
  162. if requestNum:
  163. data.update({
  164. 'requestNum': requestNum
  165. })
  166. elif orderNum:
  167. data.update({
  168. 'orderNum': orderNum
  169. })
  170. else:
  171. raise JdOpenException(
  172. errCode=JDOpenErrorCode.MY_INVALID_PARAMETER, errMsg=u'缺少订单号参数')
  173. return self.post(url=url, data=data)
  174. def add_wechat_auth_pay_dir(self, auth_pay_dir):
  175. """
  176. 追加商户微信支付目录
  177. :param auth_pay_dir:
  178. :return:
  179. """
  180. url = '/api/addAuthPayDirsDevConfig'
  181. data = {
  182. 'customerNum': self.customerNum,
  183. 'authPayDir': auth_pay_dir
  184. }
  185. return self.post(url=url, data=data)
  186. def query_wechat_auth_pay_dir(self, batch_num):
  187. """
  188. 查询商户微信支付目录
  189. :param batch_num:
  190. :return:
  191. """
  192. url = '/api/queryAddAuthPayDirsDevConfigByBatchNum'
  193. data = {
  194. 'customerNum': self.customerNum,
  195. 'batchNum': batch_num
  196. }
  197. return self.post(url=url, data=data)
  198. def api_close_order(self, requestNum):
  199. url = '/v1/agent/order/close'
  200. data = {
  201. 'agentNum': self.agentNum,
  202. 'customerNum': self.customerNum,
  203. 'requestNum': requestNum
  204. }
  205. return self.post(url=url, data=data)
  206. def api_cancel_order(self, requestNum):
  207. url = '/v2/agent/order/cancel'
  208. data = {
  209. 'agentNum': self.agentNum,
  210. 'customerNum': self.customerNum,
  211. 'requestNum': requestNum
  212. }
  213. return self.post(url=url, data=data)
  214. def download_bill(self, bill_date):
  215. url = '/v1/agent/checkaccountfile/download'
  216. data = {
  217. 'agentNum': self.agentNum,
  218. 'customerNum': self.customerNum,
  219. 'date': bill_date
  220. }
  221. result = self.post(url = url, data = data)
  222. return result['data']['downloadUrl']