# -*- coding: utf-8 -*- # !/usr/bin/env python from __future__ import unicode_literals import logging from apilib.systypes import IterConstant from library.jdopen import JDOpenErrorCode from library.jdopen.exceptions import JdOpenException 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__(accessKey, secretKey, timeout, auto_retry) self.agentNum = agentNum 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: """ url = '/v3/order/pay/create' data = { 'version': 'V4.0', 'agentNum': str(self.agentNum), 'customerNum': str(self.customerNum), # 'shopNum': str(self.shopNum), 'authId': str(authId), 'bankType': str(bankType), 'requestNum': str(requestNum), 'amount': str(amount), 'callbackUrl': str(callbackUrl), 'payModel': 'ONCE' } if self.shopNum: data.update({ 'shopNum': str(self.shopNum) }) if ledgerRule: data.update({ 'subOrderType': str(SubOrderType.LEDGER), 'ledgerRule': ledgerRule }) else: data.update({ 'subOrderType': str(SubOrderType.NORMAL) }) data.update(kwargs) if extraInfo: data.update({ 'extraInfo': extraInfo }) return self.post(url=url, data=data) def api_trade_query(self, out_trade_no=None, trade_no=None): assert out_trade_no or trade_no, 'out_trade_no and trade_no must not be empty at the same time' url = '/v3/order/query' data = { 'agentNum': self.agentNum, 'customerNum': self.customerNum, 'shopNum': self.shopNum, 'requestNum': out_trade_no, 'orderNum': trade_no } if out_trade_no: data.update({'requestNum': out_trade_no}) else: data.update({'orderNum': trade_no}) return self.post(url=url, data=data) def api_trade_refund(self, outTradeNo, outRefundNo, amount, **kwargs): """ 退款 :param outTradeNo: :param outRefundNo: :param amount: :param kwargs: :return: """ url = '/v3/order/refund/part' data = { 'version': 'V4.0', 'agentNum': self.agentNum, 'customerNum': self.customerNum, 'shopNum': self.shopNum, 'requestNum': outTradeNo, 'refundRequestNum': outRefundNo, 'refundPartAmount': amount } ledgerInfoList = kwargs.pop('ledgerInfoList', None) if ledgerInfoList: data.update({'ledgerInfoList': ledgerInfoList}) data.update(kwargs) return self.post(url=url, data=data) def api_refund_query(self, requestNum=None, orderNum=None): """ 查询退款订单 :param requestNum: 原商户订单号 :param orderNum: 原订单编号 :return: """ assert not (requestNum and orderNum), u'不能同时提供商户订单号和京东订单号' url = '/v3/order/refund/query' data = { 'agentNum': self.agentNum, 'customerNum': self.customerNum, 'shopNum': self.shopNum } if requestNum: data.update({ 'requestNum': requestNum }) elif orderNum: data.update({ 'orderNum': orderNum }) else: raise JdOpenException( errCode=JDOpenErrorCode.MY_INVALID_PARAMETER, errMsg=u'缺少订单号参数') return self.post(url=url, data=data) def add_wechat_auth_pay_dir(self, auth_pay_dir): """ 追加商户微信支付目录 :param auth_pay_dir: :return: """ url = '/api/addAuthPayDirsDevConfig' data = { 'customerNum': self.customerNum, 'authPayDir': auth_pay_dir } return self.post(url=url, data=data) def query_wechat_auth_pay_dir(self, batch_num): """ 查询商户微信支付目录 :param batch_num: :return: """ url = '/api/queryAddAuthPayDirsDevConfigByBatchNum' data = { 'customerNum': self.customerNum, 'batchNum': batch_num } return self.post(url=url, data=data) def api_close_order(self, requestNum): url = '/v1/agent/order/close' data = { 'agentNum': self.agentNum, 'customerNum': self.customerNum, 'requestNum': requestNum } return self.post(url=url, data=data) def api_cancel_order(self, requestNum): url = '/v2/agent/order/cancel' data = { 'agentNum': self.agentNum, 'customerNum': self.customerNum, 'requestNum': requestNum } return self.post(url=url, data=data) def download_bill(self, bill_date): url = '/v1/agent/checkaccountfile/download' data = { 'agentNum': self.agentNum, 'customerNum': self.customerNum, 'date': bill_date } result = self.post(url = url, data = data) return result['data']['downloadUrl']