Exemplo n.º 1
0
    def upload_wugan(trans_order_no, park_code, plate_no, plate_color_code, plate_type_code, entrance_time,
                     park_record_time, exit_time, device_no, deduct_amount):
        entrance_time = CommonUtil.timestamp_format(entrance_time, format='%Y%m%d%H%M%S')
        exit_time = CommonUtil.timestamp_format(exit_time, format='%Y%m%d%H%M%S')
        data_dict = {
            "method": "whitePay",
            "params": {
                "trans_order_no": trans_order_no,
                "park_code": park_code,
                "plate_no": plate_no,
                "plate_color_code": plate_color_code,
                "plate_type_code": plate_type_code,
                "entrance_time": entrance_time,
                "park_record_time": park_record_time,
                "exit_time": exit_time,
                "device_no": device_no,
                "deduct_amount": deduct_amount
            }
        }

        data_json = json.dumps(data_dict, ensure_ascii=False)
        logger.info('无感支付上传: {}'.format(data_json))
        sign = XlapiSignature.to_sign_with_private_key(data_json, private_key=ThirdEtcApi.PRIVATE_KEY)
        upload_body = dict(appid=ThirdEtcApi.APPID,
                           data=data_json,
                           sign=sign.decode(encoding='utf8'))
        res = http_session.post(ThirdEtcApi.ETC_UPLOAD_URL,
                                data=upload_body)  # ('http://58.59.49.122:8810/api/gateway/etc', data=upload_body) #
        res_json = res.json()
        code, message = res_json['code'], res_json['message']
        logger.info('无感支付上传: code: {}, message: {}'.format(code, message))
        return code, message
Exemplo n.º 2
0
def etc_toll_by_thread(body: OBUModel):
    time.sleep(2)
    # TODO 进行到此步骤,表示etc扣费成功,调用强哥接口
    payTime = CommonUtil.timestamp_format(int(time.time()), format='%Y-%m-%d %H:%M:%S')
    etc_deduct_notify_data = {
        "flag": True,
        "data": {
            "parkCode": body.park_code,
            "outTradeNo": body.trans_order_no,
            "derateFee": body.discount_amount,
            "payFee": body.deduct_amount,
            "payTime": payTime
        }
    }
    logger.info('etc扣费下发请求:')
    logger.info(json.dumps(etc_deduct_notify_data, ensure_ascii=False))
    etc_deduct_notify_url = 'http://z250h48353.zicp.vip:80/park/etcPayDetail'
    try:
        res = http_session.post(etc_deduct_notify_url, json=etc_deduct_notify_data)
        logger.info(res.json())
        result = res.json()['result']
        if result == 'success':
            return True
    except:
        logger.error(traceback.format_exc())
    return False
Exemplo n.º 3
0
 def upload_vehicle_plate_no(park_code, plate_no, plate_color):
     """
     上传车辆信息
     @param vehicle_info_json:
     @return:
     """
     params = dict(park_code=park_code,
                   plate_no=plate_no,
                   plate_color_code=str(int(plate_color, 16)),
                   record_time=CommonUtil.timestamp_format(
                       int(time.time()), format='%Y%m%d%H%M%S'))
     vehicle_info_dict = dict(method='passThrough', params=params)
     vehicle_info_json = json.dumps(vehicle_info_dict, ensure_ascii=False)
     # # 如果上传成功upload_flag=1, 上传失败upload_flag=0, 默认上传失败
     upload_flag = 0
     # 业务编码报文
     # 将data 值base64 后,使用SHA256WithRSA 计算签名
     sign = XlapiSignature.to_sign_with_private_key(
         vehicle_info_json, private_key=ThirdEtcApi.PRIVATE_KEY)
     upload_body = dict(appid=ThirdEtcApi.APPID,
                        data=vehicle_info_json,
                        sign=sign.decode(encoding='utf8'))
     logger.info('上传车辆信息: {}'.format(vehicle_info_json))
     try:
         res = http_session.post(ThirdEtcApi.ETC_UPLOAD_URL,
                                 data=upload_body)
         if res.json()['code'] == '000000':
             upload_flag = 1
         logger.info(res.json())
     except:
         logger.error(traceback.format_exc())
     upload_fail_count = 0 if upload_flag else 1
     return upload_flag, upload_fail_count
Exemplo n.º 4
0
 def upload_vehicle_plate_no(park_code, plate_no, plate_color):
     """
     上传车辆信息
     @param vehicle_info_json:
     @return:
     """
     params = dict(park_code=park_code,
                   plate_no=plate_no,
                   plate_color_code=str(int(plate_color, 16)),
                   record_time=CommonUtil.timestamp_format(
                       int(time.time()), format='%Y%m%d%H%M%S'))
     vehicle_info_dict = dict(method='passThrough', params=params)
     vehicle_info_json = json.dumps(vehicle_info_dict, ensure_ascii=False)
     # # 如果上传成功upload_flag=1, 上传失败upload_flag=0, 默认上传失败
     upload_flag = 0
     # 业务编码报文
     # 将data 值base64 后,使用SHA256WithRSA 计算签名
     sign = XlapiSignature.to_sign_with_private_key(
         vehicle_info_json, private_key=ThirdEtcApi.PRIVATE_KEY)
     upload_body = dict(appid=ThirdEtcApi.APPID,
                        data=vehicle_info_json,
                        sign=sign.decode(encoding='utf8'))
     logger.info('上传车辆信息: {}'.format(vehicle_info_json))
     try:
         res = http_session.post(ThirdEtcApi.ETC_UPLOAD_URL,
                                 data=upload_body)
         if res.json()['code'] == '000000':
             upload_flag = 1
         logger.info(res.json())
     except:
         logger.error(traceback.format_exc())
     upload_fail_count = 0 if upload_flag else 1
     if not upload_flag:
         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=VehicleInfoOrm(
                          id=CommonUtil.random_str(32).lower(),
                          vehicle_info=vehicle_info_json,
                          upload_flag=upload_flag,
                          upload_fail_count=upload_fail_count))
         db_session.close()
         db_engine.dispose()
     return upload_flag, upload_fail_count
Exemplo n.º 5
0
 def combine_c0(lane_mode='13',
                bst_interval=10,
                tx_power=10,
                pll_channel_id='01',
                trans_mode='01',
                flag_id='371102'):
     """
     初始化指令c0指令
     """
     cmd_type = 'c0'
     seconds = hex(int(time.time()))[2:]
     data_time = CommonUtil.timestamp_format(int(time.time()))
     bst_interval = '0' + hex(bst_interval)[2:] if len(
         hex(bst_interval)[2:]) == 1 else hex(bst_interval)[
             2:]  # 路测单元自动发送bst的间隔,单位ms,默认10ms
     tx_power = '0' + hex(tx_power)[2:] if len(
         hex(tx_power)[2:]) == 1 else hex(tx_power)[2:]  # 天线功率
     reserved = '0000'
     data = ''.join([
         cmd_type, seconds, data_time, lane_mode, bst_interval, tx_power,
         pll_channel_id, trans_mode, flag_id, reserved
     ])
     command = CommandSendSet.combine_common_command(data)
     return command
Exemplo n.º 6
0
 def notify_taigan(body: ETCRequestInfoOrm):
     logger.info('无感支付通知抬杆。。。。。。。。。。。')
     payTime = CommonUtil.timestamp_format(int(time.time()), format='%Y-%m-%d %H:%M:%S')
     res_etc_deduct_notify_flag = ThirdEtcApi.etc_deduct_notify(body.park_code, body.trans_order_no,
                                                                body.discount_amount, body.deduct_amount, payTime)
Exemplo n.º 7
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
Exemplo n.º 8
0
 def fee_deduction(self, obu_body: OBUModel):
     """
     etc扣费, 正常扣费指令流程, 耗时大约700ms  c0->b0->b2->c1->b3->c1->b4->c6->b5,其中
     c0: 发送初始化指令  --> init_rsu()中已经初始化
     b0: 接收设备状态信息帧  --> nit_rsu()中已经初始化
     b2: 接收电子标签信息帧
     c1: 发送继续交易指令
     b3: 接收设备车辆信息帧
     c1: 发送继续交易指令
     b4: 接收速通卡信息帧
     c6: 发送消费交易指令,出口消费写过站
     b5: 接收交易信息帧,表示此次交易成功结束
     :return:
     """
     current_time = time.time()
     logger.info(
         '==========================================开始扣费=========================================='
     )
     logger.info('订单号:{}, 车牌号:{}, 车牌颜色:{}'.format(
         obu_body.trans_order_no, obu_body.plate_no,
         obu_body.plate_color_code))
     logger.info('最新obu检查时间差:{}'.format(current_time -
                                        self.detect_obu_time_latest))
     self.monitor_rsu_status_on = False  # 关闭心跳检测
     # self.etc_charge_flag=True表示交易成功,self.etc_charge_flag=False表示交易失败
     self.etc_charge_flag = False
     obuid = None
     error_result = dict(flag=False, data=None, error_msg="error")
     # 设置超时时间
     while True:
         # 接收数据
         # msg_bytes = self.socket_client.recv(1024)
         try:
             msg_bytes = self.recv_msg()
         except:
             logger.error('搜索obu超时')
             self.monitor_rsu_status_on = True  # 打开心跳检测
             error_result['error_msg'] = '没有搜索到obu'
             return error_result
         logger.info('收到obu返回的数据,睡眠 {} s'.format(
             CommonConf.OBU_COMMAND_WAIT_TIME))
         # 指令转义
         msg_str = msg_bytes.hex().replace('fe01',
                                           'ff').replace('fe00',
                                                         'fe')  # 字节转十六进制
         logger.info('接收数据: {}'.format(repr(msg_str)))
         # 等待几毫秒
         time.sleep(CommonConf.OBU_COMMAND_WAIT_TIME)
         # b2 电子标签信息帧
         if msg_str[6:8] == 'b2':
             if msg_str[8:16] == 'ffffffff':  # 'ffffffff' 表示心跳
                 logger.info('心跳')
             elif msg_str[68:72] == '2001':
                 info_b2 = self.command_recv_set.parse_b2(msg_str)  # 解析b2指令
                 # 过期日期
                 data_of_expire = self.command_recv_set.info_b2[
                     'DataOfExpire']
                 # 当前日期
                 data_of_now = CommonUtil.timestamp_format(
                     int(time.time()), '%Y%m%d')
                 if data_of_now > data_of_expire:
                     error_result['error_msg'] = '过期日期:{}'.format(
                         data_of_expire)
                     return error_result
                 # 电子标签mac地址
                 obuid = info_b2['OBUID']
                 # 获取c1指令
                 c1 = CommandSendSet.combine_c1(
                     obuid, obu_div_factor=self.rsu_conf['obu_div_factor'])
                 logger.info('b2后发送c1指令:%s' % (c1))
                 self.socket_client.send(bytes.fromhex(c1))
             else:
                 error_result['error_msg'] = 'obu卡有问题,obu状态码: {}'.format(
                     msg_str[68:72])
                 return error_result
         # b3 车辆信息帧
         elif msg_str[6:8] == 'b3':
             if msg_str[16:18] == '00':  # obu信息帧状态执行码,取值00正常
                 self.command_recv_set.parse_b3(msg_str)  # 解析b3指令
                 # TODO 车牌号,车颜色 需要校验, 不匹配需要返回
                 plate_no = self.command_recv_set.info_b3[
                     'VehicleLicencePlateNumber']
                 try:
                     plate_no = CommonUtil.parse_plate_code(
                         plate_no).replace('测A', '鲁L')
                 except:
                     logger.error(traceback.format_exc())
                     logger.error('车牌号解析错误:{}'.format(repr(plate_no)))
                 # 车牌颜色
                 obu_plate_color = str(
                     int(
                         self.command_recv_set.
                         info_b3['VehicleLicencePlateColor'], 16))  # obu车颜色
                 if (obu_body.plate_no != plate_no) or (
                         obu_body.plate_color_code != obu_plate_color):
                     error_msg = "车牌号或车颜色不匹配: 监控获取的车牌号:%s, 车颜色:%s; obu获取的车牌号:%s,车颜色:%s" % (
                         obu_body.plate_no, obu_body.plate_color_code,
                         plate_no, obu_plate_color)
                     logger.error(error_msg)
                     error_result['error_msg'] = error_msg
                     return error_result
                 if obuid is None:  # 如果没有获取到obuid,继续
                     logger.error(
                         'obuid is none =====================+++++++++++++++++++'
                     )
                     continue
                 # 再次获取c1指令并发送
                 c1 = CommandSendSet.combine_c1(
                     obuid, obu_div_factor=self.rsu_conf['obu_div_factor'])
                 logger.info('b3后发送c1指令:%s' % (c1, ))
                 self.socket_client.send(bytes.fromhex(c1))
             else:  # 状态执行码不正常,发送c2指令,终止交易
                 c2 = CommandSendSet.combine_c2(obuid, stop_type='01')
                 # logger.info('发送c2指令,终止交易:  %s' % (c2,))
                 self.socket_client.send(bytes.fromhex(c2))
                 error_result['error_msg'] = '终止交易'
                 return error_result
         # b4 速通卡信息帧
         elif msg_str[6:8] == 'b4':
             if msg_str[16:18] == '00':  # 状态执行码,00说明后续速通卡信息合法有效
                 logger.info('接收b4指令: {}'.format(msg_str))
                 self.command_recv_set.parse_b4(msg_str)  # 解析b4指令
                 logger.info('b4解析后:{}'.format(
                     json.dumps(self.command_recv_set.info_b4,
                                ensure_ascii=False)))
                 # 获取并发送c6消费交易指令
                 if CommonConf.ETC_CONF_DICT['debug'] == 'true':
                     deduct_amount = CommonUtil.etcfee_to_hex(0.01)
                 else:
                     deduct_amount = CommonUtil.etcfee_to_hex(
                         obu_body.deduct_amount)  # 扣款额,高字节在前
                 purchase_time = CommonUtil.timestamp_format(
                     int(time.time()))
                 station = msg_str[132:212]  # 过站信息,40个字节
                 c6 = CommandSendSet.combine_c6(
                     obuid,
                     card_div_factor=self.rsu_conf['obu_div_factor'],
                     reserved='00000000',
                     deduct_amount=deduct_amount,
                     purchase_time=purchase_time,
                     station=station)
                 logger.info('b4后发送c6指令,消费交易,出口消费写过站: {}, 其中扣除费用{}'.format(
                     c6, obu_body.deduct_amount))
                 self.socket_client.send(bytes.fromhex(c6))
             else:
                 error_result['error_msg'] = 'b4指令有问题'
                 return error_result
         # b5 交易信息帧,表示此次交易成功结束
         elif msg_str[6:8] == 'b5':
             if msg_str[16:18] == '00':  # 状态执行码,00说明正常
                 self.command_recv_set.parse_b5(msg_str)  # 解析b5指令
                 #  获取并发送c1继续交易指令
                 c1 = CommandSendSet.combine_c1(
                     obuid, obu_div_factor=self.rsu_conf['obu_div_factor'])
                 logger.info('b5后发送c1指令:%s, 电子标签mac地址 obuid = %s' %
                             (c1, obuid))
                 self.socket_client.send(bytes.fromhex(c1))
                 self.etc_charge_flag = True
                 self.monitor_rsu_status_on = True  # 打开心跳检测
                 return self.command_recv_set
             else:
                 error_result['error_msg'] = 'b5指令有问题'
                 return error_result
         elif not msg_str:
             logger.error('接收到的指令为空')
             self.monitor_rsu_status_on = True  # 打开心跳检测
             return self.command_recv_set
         else:
             logger.error('未能解析的指令:%s' % (msg_str))
             continue
Exemplo n.º 9
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
Exemplo n.º 10
0
    def fee_deduction(self, obu_body: ETCRequestInfoOrm):
        """
        交易指令流程: b2 -> c1 -> b4 -> c6 -> b5 ->c1
        """
        logger.info(
            '==========================================开始扣费=========================================='
        )
        logger.info('订单号:{}, 车牌号:{}, 车牌颜色:{}'.format(
            obu_body.trans_order_no, obu_body.plate_no,
            obu_body.plate_color_code))
        # self.etc_charge_flag=True表示交易成功,self.etc_charge_flag=False表示交易失败
        self.etc_charge_flag = False
        result = dict(flag=False, data=None, error_msg=None)
        # 设置超时时间
        while True:
            # 接收数据
            try:
                msg_str = self.recv_msg().hex()
            except:
                logger.error('搜索obu超时')
                result['error_msg'] = '没有搜索到obu'
                return result
            logger.info('接收数据: {}'.format(repr(msg_str)))
            # b1 心跳
            if msg_str[16:18] == 'b1':
                # logger.info('接收b1心跳数据:{}'.format(msg_str))
                if msg_str[18:20] == '00':
                    self.rsu_heartbeat_time = datetime.datetime.now()
                else:
                    logger.error('天线心跳出现问题')
                    result['error_msg'] = '天线心跳出现问题'
                    return result
            # 车载单元信息帧
            elif msg_str[16:18] == 'b2':
                if msg_str[26:28] == '00':  # 执行状态代码,取值为“00H”时有后续数据
                    info_b2 = self.command_recv_set.parse_b2(msg_str)  # 解析b2指令
                    obuid = info_b2['OBUID']
                    # todo 待定
                    obu_div_factor = info_b2['IssuerIdentifier']
                    # 发送c1指令
                    c1 = CommandSendSet.combine_c1(obuid, obu_div_factor)
                    logger.info('发送c1指令:{}'.format(c1))
                    self.socket_client.send(bytes.fromhex(c1))
                    continue
                else:
                    logger.error('车载单元信息帧出错')
                    result['error_msg'] = '车载单元信息帧出错'
            # 用户信息帧
            elif msg_str[16:18] == 'b4':
                if msg_str[26:28] == '00':  # 执行状态代码,取值为“00H”时有后续数据
                    info_b4 = self.command_recv_set.parse_b4(msg_str)  # 解析b4指令
                    consume_money = CommonUtil.etcfee_to_hex(
                        obu_body.deduct_amount)
                    purchase_time = CommonUtil.timestamp_format(
                        int(time.time()))
                    station = info_b4['LastStation']
                    plate_no = CommonUtil.parse_plate_code(
                        info_b4['VehicleInfo'][:24])
                    # 车牌颜色
                    obu_plate_color = str(
                        int(
                            self.command_recv_set.info_b4['VehicleInfo']
                            [24:26], 16))  # obu车颜色
                    if (obu_body.plate_no != plate_no):
                        error_msg = '车牌号不匹配,监控获取的车牌号:{},obu获取的车牌号:{}'.format(
                            obu_body.plate_no, plate_no)

                        result['error_msg'] = error_msg
                        return result
                    elif int(
                            obu_body.plate_color_code) != int(obu_plate_color):
                        error_msg = "车牌号或车颜色不匹配: 监控获取的车牌号:%s, 车颜色:%s; obu获取的车牌号:%s,车颜色:%s" % (
                            obu_body.plate_no, obu_body.plate_color_code,
                            plate_no, obu_plate_color)
                        logger.error(error_msg)
                        # todo 颜色不对,继续扣费
                    # 针对红门轮训模式
                    if CommonUtil.deduct_stop(obu_body.create_time):
                        error_msg = '时间超时,终止etc交易'
                        logger.info(error_msg)
                        result['error_msg'] = error_msg
                        return result
                    # 发送c6消费交易指令
                    c6 = CommandSendSet.combine_c6(obuid, obu_div_factor,
                                                   consume_money,
                                                   purchase_time, station)
                    logger.info('发送c6指令:{}'.format(c6))
                    self.socket_client.send(bytes.fromhex(c6))
                    continue
                else:
                    logger.error('用户信息帧出错')
                    result['error_msg'] = '用户信息帧出错'
            # 交易信息帧
            elif msg_str[16:18] == 'b5':
                b5 = self.command_recv_set.parse_b5(msg_str)
                logger.info(json.dumps(b5, ensure_ascii=False))
                if msg_str[26:28] == '00':  # 执行状态代码,取值为“00H”时有后续数据
                    logger.info('发送c1指令:{}'.format(c1))
                    self.socket_client.send(bytes.fromhex(c1))
                    self.etc_charge_flag = True
                    result['flag'] = True
                    result['data'] = self.command_recv_set
                    return result
                else:
                    logger.error('交易信息帧出错')
                    result['error_msg'] = '交易信息帧出错'
            else:
                logger.error('未能解析的指令')
Exemplo n.º 11
0
    def fee_deduction(self, obu_body: ETCRequestInfoOrm):
        """
        etc扣费, 正常扣费指令流程, 耗时大约700ms  c0->b0->b2->c1->b3->c1->b4->c6->b5,其中
        c0: 发送初始化指令  --> init_rsu()中已经初始化
        b0: 接收设备状态信息帧  --> nit_rsu()中已经初始化
        b2: 接收电子标签信息帧
        c1: 发送继续交易指令
        b3: 接收设备车辆信息帧
        c1: 发送继续交易指令
        b4: 接收速通卡信息帧
        c6: 发送消费交易指令,出口消费写过站
        b5: 接收交易信息帧,表示此次交易成功结束
        :return:
        """
        current_time = time.time()
        logger.info(
            '==========================================开始扣费=========================================='
        )
        logger.info('订单号:{}, 车牌号:{}, 车牌颜色:{}'.format(
            obu_body.trans_order_no, obu_body.plate_no,
            obu_body.plate_color_code))
        logger.info('最新obu检查时间差:{}'.format(current_time -
                                           self.detect_obu_time_latest))
        # self.etc_charge_flag=True表示交易成功,self.etc_charge_flag=False表示交易失败
        self.etc_charge_flag = False
        obuid = None
        result = dict(flag=False, data=None, error_msg="error")

        while True:
            # 接收数据
            try:
                msg_bytes = self.recv_msg()
            except:
                logger.error('搜索obu超时')
                result['error_msg'] = '没有搜索到obu'
                return result
            # 指令转义
            msg_str = msg_bytes.hex().replace('fe01',
                                              'ff').replace('fe00',
                                                            'fe')  # 字节转十六进制
            if msg_str[8:10] == 'b2':
                logger.info('接收b2心跳数据:{}'.format(msg_str))
                if msg_str[10:12] == '00':
                    self.rsu_heartbeat_time = datetime.datetime.now()
                else:
                    logger.error('天线心跳出现问题')
                    return result

            elif msg_str[8:10] == 'b4':
                info_b4 = self.command_recv_set.parse_b4(b4=msg_str)
                logger.info('接收b4: {}'.format(info_b4))
                obuid = info_b4['ObuID']
                # TODO 测试卡,正式环境要检测obu_status
                obu_status = info_b4['OBUStatus']
                # if obu_status == '01':
                #     result['error_msg'] = 'obu非法拆卸!!!'
                #     return result
                black_list_status = info_b4['BlackListStatus']
                if black_list_status == '01':
                    result['error_msg'] = '属于黑名单车辆!!!'
                    return result
                # 当前日期
                data_of_now = CommonUtil.timestamp_format(
                    int(time.time()), '%Y%m%d')
                if data_of_now > info_b4['DataOfExpire']:
                    result['error_msg'] = '过期日期:{}'.format(
                        info_b4['DataOfExpire'])
                    return result

                plate_no = info_b4['VehicleLicencePlateNumber']
                try:
                    plate_no = CommonUtil.parse_plate_code(plate_no).replace(
                        '测A', '鲁L')
                except:
                    logger.error(traceback.format_exc())
                    result['error_msg'] = '车牌号解析错误:{}'.format(repr(plate_no))
                    return result

                plate_color = str(int(info_b4['VehicleLicencePlateColor'], 16))
                if (plate_no != obu_body.plate_no) or (
                        plate_color != obu_body.plate_color_code):
                    error_msg = "车牌号或车颜色不匹配: 监控获取的车牌号:%s, 车颜色:%s; obu获取的车牌号:%s,车颜色:%s" % (
                        obu_body.plate_no, obu_body.plate_color_code, plate_no,
                        plate_color)
                    logger.error(error_msg)
                    result['error_msg'] = error_msg
                    return result
                consume_money = CommonUtil.etcfee_to_hex(
                    obu_body.deduct_amount)  # 扣费金额
                purchase_time = CommonUtil.timestamp_format(
                    int(time.time()), format='%Y%m%d%H%M%S')
                station_info = info_b4['StationInfo']
                entry_time = CommonUtil.timestamp_format(int(time.time()) -
                                                         100,
                                                         format='%Y%m%d%H%M%S')
                c6 = CommandSendSet.combine_c6(obuid=obuid,
                                               consume_money=consume_money,
                                               purchase_time=purchase_time,
                                               station_info=station_info,
                                               entry_time=entry_time)
                logger.info('b4后发送c6指令:{}'.format(c6))
                self.socket_client.send(bytes.fromhex(c6))
            elif msg_str[8:10] == 'b5':
                self.command_recv_set.parse_b5(b5=msg_str)
                logger.info('c6后接收b5指令:{}'.format(msg_str))
                if self.command_recv_set.info_b5['ErrorCode'] == '01':
                    logger.error('读取obu卡超时。。。。。。。。。。。。')
                    # logger.info('b5后发送c6指令:{}'.format(c6))
                    # self.socket_client.send(bytes.fromhex(c6))
                    continue
                c1 = CommandSendSet.combine_c1(obuid)
                logger.info('b5后发送c1指令:{}'.format(c1))
                self.socket_client.send(bytes.fromhex(c1))

                self.etc_charge_flag = True
                self.monitor_rsu_status_on = True  # 打开心跳检测
                result['flag'] = True
                result['data'] = self.command_recv_set
                result['error_msg'] = None
                return result
            else:
                logger.info('未能解析到的指令:{}'.format(msg_str))
                time.sleep(1)