123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387 |
- # -*- coding: utf-8 -*-
- # !/usr/bin/env python
- from __future__ import unicode_literals
- import logging
- from library import random_string
- from apilib.systypes import IterConstant
- from library.jdopen import JDOpenErrorCode
- from library.jdbase.exceptions import JDException, JDRequestException
- from library.jdopen.client import JdOpenBaseClient
- logger = logging.getLogger(__name__)
- __all__ = ('JDOpenPay')
- class SubOrderType(IterConstant):
- NORMAL = 'NORMAL'
- LEDGER = 'LEDGER'
- class JDOpenPay(JdOpenBaseClient):
- API_BASE_URL = 'https://openapi.duolabao.com'
- def __init__(self, agentNum, accessKey, secretKey, customerNum, shopNum, timeout = None, auto_retry = True):
- super(JDOpenPay, self).__init__(agentNum, accessKey, secretKey, timeout, auto_retry)
- self.customerNum = customerNum
- self.shopNum = shopNum
- def create_pay_url(self, out_trade_no, total_fee, notify_url, extraInfo = None, **kwargs):
- """
- 创建主扫链接
- :param out_trade_no:
- :param total_fee:
- :param notify_url:
- :param extraInfo:
- :param kwargs: 接受tableNum, machineNum参数
- :return:
- """
- url = '/v3/order/payurl/create'
- data = {
- 'agentNum': self.agentNum,
- 'customerNum': self.customerNum,
- 'shopNum': self.shopNum,
- 'requestNum': out_trade_no,
- 'amount': total_fee,
- 'callbackUrl': notify_url,
- 'source': 'API',
- 'payModel': 'ONCE'
- }
- if extraInfo:
- data.update({
- 'extraInfo': extraInfo
- })
- data.update(kwargs)
- result = self.post(url = url, data = data)
- return result['data']['url']
- def unified_order(self, authId, bankType, requestNum, amount, callbackUrl, subject, ledgerRule = None,
- extraInfo = None, **kwargs):
- """
- :param authId:
- :param bankType:
- :param requestNum:
- :param amount:
- :param callbackUrl:
- :param subject:
- :param ledgerRule:
- :param extraInfo:
- :param kwargs: 接受ledgerRule
- {
- "ledgerType":"FIXED", -- 分账类型 固定金额:FIXED 比例:RATE 目前只支持固定金额分账
- "ledgerFeeAssume":"RECEIVER", 收款方承担:RECEIVER 分账方承担:LEDGER 默认为RECEIVER,目前仅支持收款方承担手续费
- "list":[ -- 分账list必须全部包括收款方和分账方,分账金额保留两位小数,且分账金额相加需等于订单金额
- {
- "customerNum":"10001115199597283447316",
- "amount":"0.01"
- },
- {
- "customerNum":"10001114504252653551690",
- "amount":"0.01"
- }
- ]
- }
- :return:
- """
- def processor(self, result):
- if 'success' not in result or not result['success'] or result['code'] != 'success':
- raise JDException(
- errCode = result.get('code'),
- errMsg = result.get("msg"),
- client = self)
- else:
- return result
- url = '/api/createPayWithCheck'
- data = {
- 'version': 'V4.0',
- 'agentNum': str(self.agentNum),
- 'customerNum': str(self.customerNum),
- # 'shopNum': str(self.shopNum),
- 'authCode': str(authId),
- 'bankType': str(bankType),
- 'requestNum': str(requestNum),
- 'orderAmount': str(amount),
- 'callbackUrl': str(callbackUrl),
- 'payModel': 'ONCE',
- 'orderType': 'SALES',
- 'payType': 'ACTIVE',
- 'bussinessType': 'QRCODE_TRAD',
- 'source': 'API',
- 'paySource': str(bankType)
- }
- if self.shopNum:
- data.update({
- 'shopNum': str(self.shopNum)
- })
- if ledgerRule:
- data.update({
- 'subOrderType': str(SubOrderType.LEDGER),
- 'LedgerRequest': ledgerRule
- })
- else:
- data.update({
- 'subOrderType': str(SubOrderType.NORMAL)
- })
- data.update(kwargs)
- if extraInfo:
- data.update({
- 'extraInfo': extraInfo
- })
- return self.post(url = url, data = data, processor = processor)
- def api_trade_query(self, out_trade_no = None):
- def processor(self, result):
- if 'success' not in result or not result['success']:
- raise JDException(
- errCode = result.get('code'),
- errMsg = result.get("msg"),
- client = self)
- if 'queryOrderInfoRes' not in result:
- raise JDException(
- errCode = 'QUERY_ORDER_FAILURE',
- errMsg = u'查询订单信息失败',
- client = self)
- if not result['queryOrderInfoRes']['success']:
- raise JDException(
- errCode = result['queryOrderInfoRes']['code'],
- errMsg = result['queryOrderInfoRes']['msg'],
- client = self)
- return result
- url = '/api/queryOrderPayDetail'
- data = {
- 'customerNum': self.customerNum,
- }
- if out_trade_no:
- data.update({'requestNum': out_trade_no})
- else:
- raise JDException(
- errCode = JDOpenErrorCode.MY_INVALID_PARAMETER, errMsg = u'缺少requestNum参数')
- return self.post(url = url, data = data, processor = processor)
- def api_trade_refund(self, outTradeNo, outRefundNo, amount, **kwargs):
- """
- 退款
- :param outTradeNo:
- :param outRefundNo:
- :param amount:
- :param kwargs:
- :return:
- """
- def processor(self, result):
- if 'result' not in result or not result['result'] or result['resultCode'] != 'success':
- raise JDRequestException(
- errCode = result.get('resultCode'),
- errMsg = result.get("message"),
- client = self)
- else:
- return result
- url = '/api/refundByRequestNum'
- data = {
- 'requestVersion': 'V4.0',
- 'agentNum': self.agentNum,
- 'customerNum': self.customerNum,
- # 'shopNum': self.shopNum,
- 'requestNum': outTradeNo,
- 'refundRequestNum': outRefundNo,
- 'refundPartAmount': amount
- }
- if self.shopNum:
- data.update({
- 'shopNum': self.shopNum
- })
- ledgerInfoList = kwargs.pop('ledgerInfoList', None)
- if ledgerInfoList:
- data.update({'list': ledgerInfoList})
- data.update(kwargs)
- return self.post(url = url, data = data, processor = processor)
- def api_refund_query(self, out_refund_no):
- """
- 查询退款订单
- :param out_refund_no: 退款单号
- :return:
- """
- def processor(self, result):
- if 'success' not in result or not result['success'] or result['code'] != 'success':
- raise JDRequestException(
- errCode = result.get('code'),
- errMsg = result.get("msg"),
- client = self)
- else:
- return result
- url = '/api/queryRefundOrderByRequestNum'
- data = {
- 'agentNum': self.agentNum,
- 'customerNum': self.customerNum,
- # 'shopNum': self.shopNum
- }
- if self.shopNum:
- data.update({
- 'shopNum': self.shopNum
- })
- if out_refund_no:
- data.update({
- 'requestNum': out_refund_no
- })
- else:
- raise JDException(
- errCode = JDOpenErrorCode.MY_INVALID_PARAMETER, errMsg = u'缺少退款订单号参数')
- nonce_str = random_string(32)
- if self.shopNum:
- _str = 'agentnum={}&customernum={}&nonce_str={}&requestnum={}&shopnum={}&key=xrtbvjJk213W'.format(
- self.agentNum, self.customerNum, nonce_str, out_refund_no, self.shopNum)
- else:
- _str = 'agentnum={}&customernum={}&nonce_str={}&requestnum={}&key=xrtbvjJk213W'.format(
- self.agentNum, self.customerNum, nonce_str, out_refund_no)
- import hashlib
- sign = hashlib.md5(_str.encode('utf-8')).hexdigest().upper()
- data.update({
- 'nonce_str': nonce_str,
- 'sign': sign
- })
- return self.post(url = url, data = data, processor = processor)
- def add_wechat_auth_pay_dir(self, auth_pay_dir):
- """
- 追加商户微信支付目录
- :param auth_pay_dir:
- :return:
- """
- def processor(self, result):
- if 'success' not in result or not result['success'] or result['code'] != 'success':
- raise JDException(
- errCode = result.get('code'),
- errMsg = result.get("message"),
- client = self)
- else:
- return result
- url = '/api/addAuthPayDirsDevConfig'
- data = {
- 'customerNum': self.customerNum,
- 'authPayDir': auth_pay_dir
- }
- return self.post(url = url, data = data, processor = processor)
- def query_wechat_auth_pay_dir(self, batch_num):
- """
- 查询商户微信支付目录
- :param batch_num:
- :return:
- """
- def processor(self, result):
- if 'success' not in result or not result['success'] or result['code'] != 'success':
- raise JDException(
- errCode = result.get('code'),
- errMsg = result.get("message"),
- client = self)
- else:
- return result
- url = '/api/queryAddAuthPayDirsDevConfigByBatchNum'
- data = {
- 'customerNum': self.customerNum,
- 'batchNum': batch_num
- }
- return self.post(url = url, data = data, processor = processor)
- def api_close_order(self, requestNum):
- def processor(self, result):
- if 'success' not in result or not result['success'] or result['code'] != 'success':
- raise JDException(
- errCode = result.get('code'),
- errMsg = result.get("msg"),
- client = self)
- else:
- return result
- url = '/api/close'
- data = {
- 'agentNum': self.agentNum,
- 'customerNum': self.customerNum,
- 'requestNum': requestNum
- }
- return self.post(url = url, data = data, processor = processor)
- def api_cancel_order(self, requestNum):
- def processor(self, result):
- if 'success' not in result or not result['success'] or result['code'] != 'success':
- raise JDException(
- errCode = result.get('code'),
- errMsg = result.get("msg"),
- client = self)
- else:
- return result
- url = '/api/cancel'
- data = {
- 'agentNum': self.agentNum,
- 'customerNum': self.customerNum,
- 'requestNum': requestNum
- }
- return self.post(url = url, data = data, processor = processor)
- def download_bill(self, bill_date):
- url = '/v1/agent/checkaccountfile/download'
- data = {
- 'agentNum': self.agentNum,
- 'customerNum': self.customerNum,
- 'billType': 'QRBILL',
- 'date': bill_date
- }
- result = self.post(url = url, data = data)
- return result['data']['downloadUrl']
|