Esempio n. 1
0
    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
Esempio n. 2
0
    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
Esempio n. 3
0
    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
Esempio n. 4
0
    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
Esempio n. 5
0
    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