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
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
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
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'])