def toll(body: ETCRequestInfoOrm, rsu_client: RsuSocket, db_session) -> dict: """ etc收费 :param db_session: :param body: 接收到的数据 :param rsu_client: socket客户端 :return: """ body.flag = 1 handle_data_result = None # 默认扣费失败 result = dict(flag=False, errorCode='01', errorMessage='etc扣费失败', data=None) diff_time = 0 if not CommonConf.ETC_DEDUCT_FLAG: return result try: # etc开始扣费,并解析天线返回的数据 msg = rsu_client.fee_deduction(body) # 如果扣费失败,同时无感支付开启,并且是白名单,开启无感支付 if (msg['flag'] is False) and (CommonConf.ETC_CONF_DICT['wugan'] == 'true') and (body.is_white == 1): device_no = CommonConf.ETC_CONF_DICT['dev_code'] deduct_amount = CommonUtil.yuan_to_fen(body.deduct_amount) park_code = CommonConf.ETC_CONF_DICT['etc'][0]['park_code'] code, message = WuGan.upload_wugan(body.trans_order_no, park_code, body.plate_no, body.plate_color_code, body.plate_type_code, body.entrance_time, body.park_record_time, body.exit_time, device_no, deduct_amount) if code == '000000': WuGan.notify_taigan(body) result['flag'] = True result['errorMessage'] = None else: result['errorCode'] = code result['errorMessage'] = message elif msg['flag'] is False: result['errorMessage'] = msg['error_msg'] logger.info('...................扣费失败........................') body.deduct_status = EtcDeductStatus.FAIL else: # 表示交易成功 # etc扣费成功后做进一步数据解析 handle_data_result = rsu_client.handle_data(body) result['flag'] = handle_data_result['flag'] result['errorMessage'] = handle_data_result['error_msg'] if handle_data_result['flag']: logger.info('...................扣费成功........................') body.deduct_status = EtcDeductStatus.SUCCESS else: logger.info('...................扣费失败........................') body.deduct_status = EtcDeductStatus.FAIL body.update_time = datetime.now() # 计算update_time与create_time的时间差 diff_time = (body.update_time - body.create_time).seconds except: logger.error(traceback.format_exc()) result = dict(flag=False, errorCode='01', errorMessage='入库失败', data=None) return result # 记入日志 logger.info(json.dumps(result, ensure_ascii=False)) # 数据修改好后提交 DBClient.db_sesson_commit(db_session) if handle_data_result and handle_data_result['flag'] and handle_data_result['data']: data = dict(method='etcPayUpload', params=handle_data_result['data'], ) logger.info('etc交易成功') logger.info(json.dumps(data, ensure_ascii=False)) # 如果etc_deduct_notify_url为空,同时diff_time超时,则放弃上传etc数据 if (not CommonConf.ETC_CONF_DICT['thirdApi']['etc_deduct_notify_url']) and (diff_time >= CommonConf.ETC_CONF_DICT['hongmen_wait_time']): logger.info('etc扣费成功时间与etc扣费请求时间的时间差超时,放弃上传') return result # 通知抬杆, 上传etc数据,并将etc数据存入本地 try: body_dict = dict(park_code=body.park_code, trans_order_no=body.trans_order_no, discount_amount=body.discount_amount, deduct_amount=body.deduct_amount) t = Thread(target=EtcToll.etc_upload_and_addto_db, args=(handle_data_result, body_dict)) t.setDaemon(False) t.start() except: logger.error(traceback.format_exc()) db_session.close() return result
def toll(body: ETCRequestInfoOrm, rsu_client: RsuSocket) -> dict: """ etc收费 :param body: 接收到的数据 :param rsu_client: socket客户端 :return: """ # 默认扣费失败 result = dict(flag=False, errorCode='01', errorMessage='etc扣费失败', data=None) if not CommonConf.ETC_DEDUCT_FLAG: return result try: # etc开始扣费,并解析天线返回的数据 msg = rsu_client.fee_deduction(body) # 如果扣费失败,同时无感支付开启,并且是白名单,开启无感支付 if (msg['flag'] is False) and (CommonConf.ETC_CONF_DICT['wugan'] == 'true') and (body.is_white == 1): device_no = CommonConf.ETC_CONF_DICT['dev_code'] deduct_amount = CommonUtil.yuan_to_fen(body.deduct_amount) park_code = CommonConf.ETC_CONF_DICT['etc'][0]['park_code'] code, message = WuGan.upload_wugan( body.trans_order_no, park_code, body.plate_no, body.plate_color_code, body.plate_type_code, body.entrance_time, body.park_record_time, body.exit_time, device_no, deduct_amount) if code == '000000': WuGan.notify_taigan(body) result['flag'] = True result['errorMessage'] = None else: result['errorCode'] = code result['errorMessage'] = message elif msg['flag'] is False: result['errorMessage'] = msg['error_msg'] else: # 表示交易成功 # etc扣费成功后做进一步数据解析 handle_data_result = rsu_client.handle_data(body) result['flag'] = handle_data_result['flag'] result['errorMessage'] = handle_data_result['error_msg'] params = handle_data_result['data'] # handle_data_result['flag']=False一般是存在黑名单 if handle_data_result['flag'] and handle_data_result['data']: # 交易时间格式转换 pay_time = CommonUtil.timeformat_convert( timestr1=params['exit_time'], format1='%Y%m%d%H%M%S', format2='%Y-%m-%d %H:%M:%S') result['data'] = dict(parkCode=params['park_code'], orderNo=params['trans_order_no'], outTradeNo=params['trans_order_no'], payFee=params['deduct_amount'] / 100, derateFee=params['discount_amount'], payTime=pay_time) # result['data'] = '交易成功' data = dict( method='etcPayUpload', params=params, ) logger.info('etc交易成功') logger.info(json.dumps(data, ensure_ascii=False)) except: logger.error(traceback.format_exc()) # 记入日志 logger.info(json.dumps(result, ensure_ascii=False)) return result
def handle_data(self, body: ETCRequestInfoOrm): """ 处理self.command_recv_set,也就是收到的天线的信息 :param body: 接收到的数据 :return: """ # 结果存储 result = dict(flag=False, data=None, error_msg=None) deduct_amount = body.deduct_amount # 入场时间戳格式化 yyyyMMddHHmmss entrance_time = CommonUtil.timestamp_format(body.entrance_time, format='%Y%m%d%H%M%S') # 交易时间格式化(yyyyMMddHHmmss) # exit_time = CommonUtil.timestamp_format(body.exit_time, format='%Y%m%d%H%M%S') exit_time = CommonUtil.timestamp_format(body.exit_time, format='%Y%m%d%H%M%S') exit_time_stamp = CommonUtil.str_to_timestamp(timestr=exit_time, format='%Y%m%d%H%M%S') # 计算停车时长 park_record_time = CommonUtil.time_difference(body.entrance_time, exit_time_stamp) # 交易后余额 balance = '123' # 交易前余额 1999918332 单位分 trans_before_balance = '123' # 卡片发行信息 issuer_info = '0000000000000000000000000000000000000000000000000' # ETC 卡片类型(22:储值卡;23:记账卡), 位于issuer_info的16,17位, 16进制形式,需要转为10进制 card_type = '23' # PSAM 卡编号 psam_id = '000000000000000' # card_sn 物理卡号 card_sn = '0000000000000509' # TODO 待确认 logger.info('ETC 卡片类型(22:储值卡;23:记账卡): {}'.format(card_type)) params = dict(algorithm_type="1", # TODO 金额位数待确定 balance=CommonUtil.hex_to_etcfee(balance, unit='fen'), # 交易后余额 # TODO 待确认 card_net_no=issuer_info[20:24], # 网络编号 card_rnd=CommonUtil.random_str(8), # 卡内随机数 card_serial_no='0129', # 卡内交易序号 card_sn=card_sn, # self.command_recv_set.info_b4['CardID'], # "1030230218354952",ETC 支付时与卡物理号一致;非 ETC 时上传车牌号 card_type=card_type, # "23", # ETC 卡片类型(22:储值卡;23:记账卡) charging_type="0", # 扣费方式(0:天线 1:刷卡器) deduct_amount=CommonUtil.yuan_to_fen(deduct_amount), # 扣款金额 device_no=self.rsu_conf['device_no'], # 设备号 device_type=self.rsu_conf['device_type'], # 设备类型(0:天线;1:刷卡器;9:其它) discount_amount=CommonUtil.yuan_to_fen(body.discount_amount), # 折扣金额 entrance_time=entrance_time, # 入场时间 yyyyMMddHHmmss exit_time=exit_time, # 交易时间(yyyyMMddHHmmss) issuer_identifier='B9E3B6AB44010001', # 发行商代码 obu_id='02F7D593', # OBU 序号编码 park_code=self.rsu_conf['park_code'], # 车场编号 park_record_time=park_record_time, # 停车时长,时间精确到秒, 6小时50分钟 plate_color_code=body.plate_color_code, # 车牌颜色编码 0:蓝色、1:黄色、2:黑色、3:白色、4:渐变绿色、5:黄绿双拼、6:绿色、7:蓝白渐变 plate_no=body.plate_no, # 车牌号码 "皖LX4652", plate_type_code=body.plate_type_code, # 车辆类型编码 0:小车 1:大车 2:超大车 psam_id=psam_id, # PSAM 卡编号 "37010101000000295460" psam_serial_no='00000129', # PSAM 流水号 "00005BA2", receivable_total_amount=CommonUtil.yuan_to_fen(body.receivable_total_amount), # 应收金额 serial_number='86030002200479e1', # 合同序列号"340119126C6AFEDE" tac=CommonUtil.random_str(8), # 交易认证码 terminal_id='000000000509', # 终端编号 trans_before_balance=CommonUtil.hex_to_etcfee(trans_before_balance, unit='fen'), # 交易前余额 1999918332 单位分 trans_order_no=body.trans_order_no, # 交易订单号 "6711683258167489287" trans_type='09', # 交易类型(06:传统;09:复合) vehicle_type='0' # 收费车型 ) result['flag'] = True result['data'] = params return result
def handle_data(self, body: OBUModel): """ 处理self.command_recv_set,也就是收到的天线的信息 :param body: 接收到的数据 :return: """ # 结果存储 result = dict(flag=False, data=None, error_msg=None) # TODO 待待删打印信息 # self.command_recv_set.print_obu_info() # 判断card_net和card_sn 物理卡号是否存在于黑名单中 card_sn_in_blacklist_flag, error_msg = self.card_sn_in_blacklist() # 物理卡号存在于黑名单中直接返回 if card_sn_in_blacklist_flag: result['error_msg'] = error_msg return result # 入场时间戳格式化 yyyyMMddHHmmss entrance_time = CommonUtil.timestamp_format(body.entrance_time, format='%Y%m%d%H%M%S') # 交易时间格式化(yyyyMMddHHmmss) # exit_time = CommonUtil.timestamp_format(body.exit_time, format='%Y%m%d%H%M%S') exit_time = self.command_recv_set.info_b5['TransTime'] exit_time_stamp = CommonUtil.str_to_timestamp(timestr=exit_time, format='%Y%m%d%H%M%S') # 计算停车时长 park_record_time = CommonUtil.time_difference(body.entrance_time, exit_time_stamp) # 交易后余额 balance = self.command_recv_set.info_b5['CardBalance'] # 交易前余额 1999918332 单位分 trans_before_balance = self.command_recv_set.info_b4['CardRestMoney'] if CommonConf.ETC_CONF_DICT['debug'] == 'true': deduct_amount = 0.01 else: deduct_amount = body.deduct_amount # 卡片发行信息 issuer_info = self.command_recv_set.info_b4['IssuerInfo'] # ETC 卡片类型(22:储值卡;23:记账卡), 位于issuer_info的16,17位, 16进制形式,需要转为10进制 card_type = str(int(issuer_info[16:18], 16)) # PSAM 卡编号 psam_id = issuer_info[20:40] # card_sn 物理卡号 card_sn = psam_id[4:] # TODO 待确认 logger.info('ETC 卡片类型(22:储值卡;23:记账卡): {}'.format(card_type)) params = dict( algorithm_type="1", # TODO 金额位数待确定 balance=CommonUtil.hex_to_etcfee(balance, unit='fen'), # 交易后余额 # TODO 待确认 card_net_no=issuer_info[20:24], # 网络编号 card_rnd=CommonUtil.random_str(8), # 卡内随机数 card_serial_no=self.command_recv_set. info_b5['ICCPaySerial'], # 卡内交易序号 card_sn=card_sn, # self.command_recv_set.info_b4['CardID'], # "1030230218354952",ETC 支付时与卡物理号一致;非 ETC 时上传车牌号 card_type=card_type, # "23", # ETC 卡片类型(22:储值卡;23:记账卡) charging_type="0", # 扣费方式(0:天线 1:刷卡器) deduct_amount=CommonUtil.yuan_to_fen(deduct_amount), # 扣款金额 device_no=self.rsu_conf['device_no'], # 设备号 device_type=self.rsu_conf['device_type'], # 设备类型(0:天线;1:刷卡器;9:其它) discount_amount=CommonUtil.yuan_to_fen( body.discount_amount), # 折扣金额 entrance_time=entrance_time, # 入场时间 yyyyMMddHHmmss exit_time=exit_time, # 交易时间(yyyyMMddHHmmss) issuer_identifier=self.command_recv_set. info_b2['IssuerIdentifier'].upper(), # 发行商代码 obu_id=self.command_recv_set.info_b2['OBUID'].upper(), # OBU 序号编码 park_code=self.rsu_conf['park_code'], # 车场编号 park_record_time=park_record_time, # 停车时长,时间精确到秒, 6小时50分钟 plate_color_code=body. plate_color_code, # 车牌颜色编码 0:蓝色、1:黄色、2:黑色、3:白色、4:渐变绿色、5:黄绿双拼、6:绿色、7:蓝白渐变 plate_no=body.plate_no, # 车牌号码 "皖LX4652", plate_type_code=body.plate_type_code, # 车辆类型编码 0:小车 1:大车 2:超大车 psam_id=psam_id, # PSAM 卡编号 "37010101000000295460" psam_serial_no=self.command_recv_set. info_b5['PSAMTransSerial'], # PSAM 流水号 "00005BA2", receivable_total_amount=CommonUtil.yuan_to_fen( body.receivable_total_amount), # 应收金额 serial_number=self.command_recv_set. info_b2['SerialNumber'], # 合同序列号"340119126C6AFEDE" tac=self.command_recv_set.info_b5['TAC'], # 交易认证码 terminal_id=self.command_recv_set.info_b5['PSAMNo'], # 终端编号 trans_before_balance=CommonUtil.hex_to_etcfee(trans_before_balance, unit='fen'), # 交易前余额 1999918332 单位分 trans_order_no=body.trans_order_no, # 交易订单号 "6711683258167489287" trans_type=self.command_recv_set. info_b5['TransType'], # 交易类型(06:传统;09:复合) vehicle_type=str(int( self.command_recv_set.info_b3['VehicleClass'])) # 收费车型 ) etc_deduct_info_dict = {"method": "etcPayUpload", "params": params} # 业务编码报文json格式 etc_deduct_info_json = json.dumps(etc_deduct_info_dict, ensure_ascii=False) # TODO 进行到此步骤,表示etc扣费成功,调用强哥接口 payTime = CommonUtil.timeformat_convert(exit_time, format1='%Y%m%d%H%M%S', format2='%Y-%m-%d %H:%M:%S') res_etc_deduct_notify_flag = ThirdEtcApi.etc_deduct_notify( self.rsu_conf['park_code'], body.trans_order_no, body.discount_amount, body.deduct_amount, payTime) if res_etc_deduct_notify_flag: # 接收到强哥返回值后,上传etc扣费数据 upload_flag, upload_fail_count = ThirdEtcApi.etc_deduct_upload( etc_deduct_info_json) db_engine, db_session = create_db_session( sqlite_dir=CommonConf.SQLITE_DIR, sqlite_database='etc_deduct.sqlite') # etc_deduct_info_json入库 DBClient.add(db_session=db_session, orm=ETCFeeDeductInfoOrm( id=CommonUtil.random_str(32).lower(), trans_order_no=body.trans_order_no, etc_info=etc_deduct_info_json, upload_flag=upload_flag, upload_fail_count=upload_fail_count)) db_session.close() db_engine.dispose() # 清除收集到的b2,b3, b4, b5 self.command_recv_set.clear_info_b2345() result['flag'] = True result['data'] = params return result
def handle_data(self, body: VehicleOweOrm): """ 处理self.command_recv_set,也就是收到的天线的信息 :param body: 接收到的数据 :return: """ # 结果存储 result = dict(flag=False, data=None, error_msg=None) # TODO 待待删打印信息 # self.command_recv_set.print_obu_info() # TODO 判断card_net和card_sn 物理卡号是否存在于黑名单中 # card_sn_in_blacklist_flag, error_msg = self.card_sn_in_blacklist() # # 物理卡号存在于黑名单中直接返回 # if card_sn_in_blacklist_flag: # result['error_msg'] = error_msg # return result # 入场时间戳格式化 yyyyMMddHHmmss entrance_time = body.entrance_time # 出场时间 exit_time = body.exit_time # 交易时间格式化(yyyyMMddHHmmss) trans_time = self.command_recv_set.info_b5['TransTime'] # 计算停车时长 park_record_time = body.park_record_time # 交易后余额 balance = self.command_recv_set.info_b5['CardRestMoney'] # 交易前余额 1999918332 单位分 trans_before_balance = self.command_recv_set.info_b4['CardRestMoney'] if CommonConf.ETC_CONF_DICT['debug'] == 'true': deduct_amount = 0.01 else: deduct_amount = body.deduct_amount card_net_no = self.command_recv_set.info_b4['CardNetNo'] # 网络编号 # ETC 卡片类型 16 储值卡 17 记账卡,转换成十进制分别对应22,23 card_type = str(int(self.command_recv_set.info_b4['CardType'], 16)) # PSAM 卡编号 10字节 try: psam_id = self.command_recv_set.info_ba['PsamSN'] except: print(self.command_recv_set.info_ba) # card_sn 物理卡号 8字节 card_sn = psam_id[4:] # TODO 待确认 logger.info('ETC 卡片类型(22:储值卡;23:记账卡): {}'.format(card_type)) params = dict( algorithm_type="1", # TODO 金额位数待确定 balance=CommonUtil.hex_to_etcfee(balance, unit='fen'), # 交易后余额 # TODO 待确认 card_net_no=card_net_no, # 网络编号 card_rnd=CommonUtil.random_str(8), # 卡内随机数 card_serial_no=self.command_recv_set. info_b5['ETCTradNo'], # 卡内交易序号 card_sn=card_sn, # self.command_recv_set.info_b4['CardID'], # "1030230218354952",ETC 支付时与卡物理号一致;非 ETC 时上传车牌号 card_type=card_type, # "23", # ETC 卡片类型(22:储值卡;23:记账卡) charging_type="0", # 扣费方式(0:天线 1:刷卡器) deduct_amount=CommonUtil.yuan_to_fen(deduct_amount), # 扣款金额 device_no=self.rsu_conf['device_no'], # 设备号 device_type=self.rsu_conf['device_type'], # 设备类型(0:天线;1:刷卡器;9:其它) # TODO 折扣金额 discount_amount=CommonUtil.yuan_to_fen(body.discount_amount), entrance_time=entrance_time, # 入场时间 yyyyMMddHHmmss exit_time=exit_time, # 交易时间(yyyyMMddHHmmss) issuer_identifier=self.command_recv_set. info_b4['IssuerIdentifier'].upper(), # 发行商代码 obu_id=self.command_recv_set.info_b4['ObuID'].upper(), # OBU 序号编码 park_code=self.rsu_conf['park_code'], # 车场编号 park_record_time=park_record_time, # 停车时长,时间精确到秒, 6小时50分钟 plate_color_code=body. plate_color, # 车牌颜色编码 0:蓝色、1:黄色、2:黑色、3:白色、4:渐变绿色、5:黄绿双拼、6:绿色、7:蓝白渐变 plate_no=body.plate_no, # 车牌号码 "皖LX4652", # TODO 车辆类型编码 0:小车 1:大车 2:超大车 plate_type_code=body.plate_type_code, psam_id=psam_id, # PSAM 卡编号 "37010101000000295460" psam_serial_no=self.command_recv_set. info_b5['PSAMTransSerial'], # PSAM 流水号 "00005BA2", # TODO 应收金额 receivable_total_amount=CommonUtil.yuan_to_fen( body.receivable_total_amount), serial_number=self.command_recv_set. info_b4['ApplySerial'], # 合同序列号"340119126C6AFEDE" tac=self.command_recv_set.info_b5['TAC'], # 交易认证码 terminal_id=self.command_recv_set. info_b5['PsamTerminalID'], # 终端编号 trans_before_balance=CommonUtil.hex_to_etcfee( trans_before_balance, unit='fen'), # 交易前余额 1999918332 单位分 # TODO 交易订单号 "6711683258167489287" trans_order_no=CommonUtil.random_str(16), # body.trans_order_no, trans_time=trans_time, # 交易时间 # TODO 待确认 trans_type='09', # 交易类型(06:传统;09:复合) vehicle_type=str( int(self.command_recv_set.info_b4['VehicleClass'], 16)) # 收费车型 ) etc_deduct_info_dict = {"method": "etcPayUpload", "params": params} etc_deduct_info_json = json.dumps(etc_deduct_info_dict, ensure_ascii=False) logger.info(etc_deduct_info_json) # TODO 上传etc扣费数据 upload_flag, upload_fail_count = ThirdEtcApi.etc_deduct_upload( etc_deduct_info_json) db_engine, db_session = create_db_session( sqlite_dir=CommonConf.SQLITE_DIR, sqlite_database='etc_deduct.sqlite') # etc_deduct_info_json入库 DBClient.add(db_session=db_session, orm=ETCFeeDeductInfoOrm( id=CommonUtil.random_str(32).lower(), etc_info=etc_deduct_info_json, upload_flag=upload_flag, upload_fail_count=upload_fail_count)) db_session.close() db_engine.dispose() # 清除收集到的b2,b3, b4, b5 self.command_recv_set.clear_info_b2345() result['flag'] = True result['data'] = params return result