Esempio n. 1
0
    def query_single_trade(trade_no=None, transaction_id=None, sign_type='MD5', time_out=6):
        """
        单笔订单交易查询。已经拿到支付宝交易号时请使用支付宝交易号查 询,如未拿到则使用订单号查询
        :param trade_no: 订单号
        :param transaction_id: 支付宝交易号
        :param time_out:
        :return:
        """
        # 检测必填参数
        data = {
            'partner': AliPayConfig.PID,
            '_input_charset': AliPayConfig.INPUT_CHARSET,
            'service': 'single_trade_query',
        }
        if transaction_id:
            data['trade_no'] = transaction_id
        elif trade_no:
            data['out_trade_no'] = trade_no
        else:
            raise ValueError(u'trade_no、ali_trade_no必须有一个')

        data['sign'] = makeSign(data, sign_type)   # 签名
        data['sign_type'] = sign_type
        req_body = '&'.join('{}={}'.format(k,v) for k,v in data.items())

        h = httplib2.Http(".cache", timeout=time_out)
        resp, content = h.request(AliPayApi.__ALI_PAY_URL, "POST", body=req_body,
                                  headers={'content-type': 'application/x-www-form-urlencoded'})

        result = AliPayApi.make_dict_from_resp(resp, content)

        if not checkSign(result):
            raise AliPayException(AliPayException.ERROR_SIGN, u'query_single_trade返回值签名错误')

        return result
Esempio n. 2
0
    def get_notify_data_and_verify(self, resp_data):
        """
        接收从支付宝支付后台发送过来的数据并验证签名
        :return: 支付宝支付后台返回的数据
        """

        # 接收从支付宝后台传来的数据
        if checkSign(resp_data) != 0:
            logging.error('from ali pay notification: sign error: ' + str(resp_data))
            raise AliPayException(AliPayException.ERROR_SIGN, u'签名错误')
        notify_id = resp_data.get('notify_id')
        if not notify_id or not AliPayApi.verify_notification(notify_id):
            logging.error('from ali pay notification: notify_id error: ' + str(resp_data))
            raise AliPayException(AliPayException.FAILED_NOTIFY_ID, u'notify_id无效')
        return resp_data
Esempio n. 3
0
    def query_and_set_order(cls, trade):
        if trade.transaction_id:
            resp_data = AliPayApi.query_single_trade({'transaction_id': trade.transaction_id})
        else:
            resp_data = AliPayApi.query_single_trade({'out_trade_no': trade.trade_no})
        if resp_data['is_success'] == 'T':

            if checkSign(resp_data) != 0:
                logging.error('from ali pay single order query: sign error: ' + trade.trade_no)
                logging.error(resp_data)
                return None

            trade.transaction_id = resp_data['trade_no']
            trade.gmt_create = resp_data['gmt_create']
            if 'gmt_payment' in resp_data:
                trade.gmt_payment = resp_data['gmt_payment']
            if 'gmt_last_modified_time' in resp_data:
                trade.gmt_last_modified_time = resp_data['gmt_last_modified_time']
            if 'time_out' in resp_data:
                trade.time_out = resp_data['time_out']
            if 'gmt_close' in resp_data:
                trade.gmt_close = resp_data['gmt_close']
            if 'time_out_type' in resp_data:
                trade.time_out_type = resp_data['time_out_type']

            if 'bank_seq_no' in resp_data:
                trade.bank_seq_no = resp_data['bank_seq_no']

            trade.ali_result_code = resp_data['result_code']
            trade.ali_err_code = resp_data.get('error', '')
            trade.ali_trade_status = resp_data.get('trade_status', '')
            if trade.ali_trade_status == 'TRADE_SUCCESS':   # 支付成功
                trade.order_status = 3
            with transaction.atomic():  # 支付成功
                if trade.order_status in (3,9) and trade.is_order_over is False:
                    trade.ali_response = resp_data
                    trade.is_order_over = True
                    trade.save(force_update=True)
                    # 通知订单支付成功
                    product_order = ProductOrder.objects.select_for_update().get(order_no=trade.order_no)
                    # product_order.status = 2
                    # product_order.pay_type = 2
                    notify_order_pay_success(product_order)
                else:
                    trade.save(force_update=True)
            return trade
        else:
            return None
Esempio n. 4
0
    def query_trade(gmt_start_time=None, gmt_end_time=None, page_size=5000, time_out=6, **kwargs):
        """
        账目明细分页查询
        :param gmt_start_time: 账务查询开始时间,格式为 yyyy-MM-dd HH:mm:ss.
            开始时间不能大于当前时间 和查询结束时间,并且与账 务查询结束时间的间隔不能 大于 1 天。 开始时间最早为当前时间前 3 年。
            当查询条件含有账务流水号、支付宝交易号、商户订单号、充值网银流水号中任意一个时,本参数可空,否则不可空。
            查询结果数据包含该时间点数据。
        :param gmt_end_time: 账务查询结束时间,格式为 yyyy-MM-dd HH:mm:ss.
            当查询条件含有账务流水 号、支付宝交易号、商户订 单号、充值网银流水号中任 意一个时,本参数可空,否则不可空。
            查询结果数据不包含该时间点数据。
        :prarm trans_code: 交易类型代码。多个交易类型代码之间以半角逗号“,”分隔。
                            3011 转账(含红包、集分宝等)
                            3012 收费
                            4003 充值
                            5004 提现
                            5103 退票
                            6001 在线支付
        :param page_size:每页记录数。 小于等于5000的正整数.
        :param time_out:
        :param kwargs: logon_id:交易收款账户.查询的收款账户,需要联系 支付宝绑定与商户 PID 的对 应关系。 若为空,表示查 PID 所属交易.
                        iw_account_log_id:账务流水号.
                        transaction_id:业务流水号.业务流水号字段对于交易数 据为交易号,对于转账、充值、提现等资金操作,此处为业务流水号。
                        merchant_out_order_no:商户订单号 .
                        deposit_bank_no:充值网银流水号.
                        查询优先级如下:账务流水号>业务流水号>商户订单号>充值网银流水号。当存在优先级高的参数时,优先级 低的参数无效。

        :return:
        """

        #正常返回的情况下,需要签名的参数是节点account_log_list、has_next_page、 page_no、page_size。
        # 参数 has_next_page、page_no、page_size 的值分 别是各个节点的值,参数 account_log_list 的值则是包含节点本身在内所有数据
        # accountLogList节点XML片段解析时需要expand empty element,如<memo/> 展开为<memo></memo>。
        # <response>
        #     <account_page_query_result>
        #         <account_log_list>
        #             <AccountQueryAccountLogVO>…..</AccountQueryAccountLogVO>
        #         </account_log_list>
        #         <has_next_page>F</has_next_page>
        #         <page_no>1</page_no>
        #         <page_size>5000</page_size>
        #     </account_page_query_result>
        # </response>
        # account_log_list :<account_log_list><Account QueryAccountLogVO>...</A ccountQueryAccountLogVO ></account_log_list>
        # has_next_page: F
        # page_no: 1
        # page_size: 5000

        data = {
            'partner': AliPayConfig.PID,
            '_input_charset': AliPayConfig.INPUT_CHARSET,
            'service': 'account.page.query',
        }
        k = {'logon_id', 'iw_account_log_id', 'transaction_id', 'merchant_out_order_no', 'deposit_bank_no',}
        if not k.intersection(kwargs.keys()) and (not gmt_end_time or not gmt_start_time):
            raise ValueError(u'缺少必要的查询参数')

        for ele in k.intersection(kwargs.keys()):
            if ele == 'transaction_id':
                data['trade_no'] = kwargs[ele]
            else:
                data[ele] = kwargs[ele]

        if gmt_start_time and gmt_end_time:
            data['gmt_start_time'] = gmt_start_time
            data['gmt_end_time'] = gmt_end_time

        page_no = 1
        while True:
            data['page_no'] = page_no
            data['sign'] = makeSign(data)   # 签名
            data['sign_type'] = AliPayConfig.SIGN_TYPE
            req_body = '&'.join('{}={}'.format(k,v) for k,v in data.items())

            h = httplib2.Http(".cache", timeout=time_out)
            resp, content = h.request(AliPayApi.__ALI_PAY_URL, "POST", body=req_body,
                                      headers={'content-type': 'application/x-www-form-urlencoded'})

            # 验证签名
            sign_m = {}
            start = content.find('<account_log_list>')
            end = content.find('</account_log_list>')
            if start!= -1 and end != -1:
                end += len('</account_log_list>')
                sign_m['account_log_list'] = content[start: end]

            result = AliPayApi.make_dict_from_resp(resp, content, xml_handler=QueryOrderXMLHandler)
            for ele in ['has_next_page', 'page_no', 'page_size', 'sign', 'sign_type']:
                sign_m[ele] = result.get(ele, '')

            if not checkSign(sign_m):
                raise AliPayException(AliPayException.ERROR_SIGN, u'query_single_trade返回值签名错误')

            yield result.get('bills', [])

            if result['has_next_page'] != 'T':
                break

            page_no = int(result['page_no'])