@chenpbh
2019-03-27T12:03:19.000000Z
字数 18026
阅读 477
开放接口
| 版本 | 日期 | 人员 | 变更内容 |
|---|---|---|---|
| 1.0 | 2019-02-27 | 陈鹏 | 版本初定义 |
所有数据接口均采用HTTP(S)协议,每个接口的URL均采用以下格式:
http(s)://[地址]/接口名称
- 地址:接口服务所属域名或ip
- 接口名称:所调用接口的名称,具体接口名称见各业务接口描述文档
1、统一采用Http Post请求,采用JSON方式;
2、传输过程中应包含请求头和消息体;
3、接口请求时,要求将TOKEN存放到请求头中,供双方验证。
4、消息体转换为JSON字符串进行传输
| 属性 | 值 | 描述 |
|---|---|---|
| Content-type | application/json;charset=UTF-8 |
json传输 |
| Authorization | bearer token | bearer预留,可以任意填,其中token为上面提供的字符串,bearer和token之间留空格。示例:bearer adc347c5667aeeafaf34556c |
| 参数 | 是否必填 | 类型 | 说明 |
|---|---|---|---|
| requestMsg | true | String | 请求内容体,详细描述见 数据加解密 |
| timestamp | true | long | 时间戳,毫秒数 System.currentTimeMillis() |
| sign | true | String | 签名值,详细描述见 签名规范 |
| 参数 | 是否必填 | 类型 | 说明 |
|---|---|---|---|
| code | true | int | 响应码,详细描述见 响应码定义 |
| msg | true | String | 响应提示 |
| data | true | String | 查询结果 |
平台加解密支持RSA和AES加密方案,只能二选一。每个用户交互前需要申请分配 消息密钥、认证标识、签名密钥。
- AES密钥(AES_KEY): 用于所有接口中业务数据加密
- 认证标识(TOKEN): 用于身份认证
- 签名密钥(SIGN_SECRET): 用于数据签名,防止数据被截取篡改
其中TOKEN需要在请求中传递,其他两项妥善保管不允许在请求中传递
- RSA公钥(RAS_PUBLIC_SECRET): 调用方用来加解密数据
- RSA私钥(RAS_PRIVATE_SECRET): 接口平台方用来加解密数据
- 认证标识(TOKEN): 用于身份认证
- 签名密钥(SIGN_SECRET): 用于数据签名,防止数据被截取篡改
其中TOKEN需要在请求中传递,其他两项妥善保管不允许在请求中传递
密钥具备随机产生特性,弱密钥会被剔除,所有密钥均由接口管理平台生成。
密钥分发由安全方式进行,通过线下分发,邮件等方式。
- 调用方对业务数据利用消息密钥(AES_KEY)进行加密;
- 接口平台利用消息密钥(AES_KEY)对消息体中的业务数据解密,校验参数合法性等后续业务处理,具体加解密方法和示例见 AES加解密
签名采用HMAC-MD5算法,利用MD5作为散列函数,通过签名密钥(SIGN_SECRET)对整个消息主体进行签名。
具体签名方法和示例见 签名规范
签名采用HMAC-MD5算法,签名流程:
- 在密钥key后面添加0来创建一个长为B(64字节)的字符串(str);
- 将上一步生成的字符串(str) 与ipad(0x36)做异或运算,形成结果字符串(istr)
- 将数据流data附加到第二步的结果字符串(istr)的末尾
- 做md5运算于第三步生成的数据流(istr)
- 将第一步生成的字符串(str) 与opad(0x5c)做异或运算,形成结果字符串(ostr)
- 再将第四步的结果(istr) 附加到第五步的结果字符串(ostr)的末尾
- 做md5运算于第6步生成的数据流(ostr),最终输出结果(out)
- requestMsg 和 timestamp 参数名和参数值拼接成一个字符串A
- 用字符串A和签名密钥(SIGN_SECRET)调用签名算法,生成签名值,签名算法见 签名算法
示例:
// 业务参数加密后数据"requestMsg":"xo6+oObvQ071Qw0U9pZn/+QOJsQYcX4YJGKH+Q1j/gdpKaDseLWzM3mOsT9LdYWKgB/8DcZSynck2s5Xi504fGWxpOM1Cvd8Ne7T6/2r0eU="// 时间戳"timestamp"=1508983789981// 拼接后String input = "requestMsgxo6+oObvQ071Qw0U9pZn/+QOJsQYcX4YJGKH+Q1j/gdpKaDseLWzM3mOsT9LdYWKgB/8DcZSynck2s5Xi504fGWxpOM1Cvd8Ne7T6/2r0eU=timestamp1508983789981"// 假设SIGN_SECRET为 "test" 调用签名算法HmacUtil.byteArrayToHexString(HmacUtil.encryptHMAC(input.getBytes(), "test"))// 签名结果为abc48a4267d64921a55c30b33abd18c1
private static final String KEY_MAC = "HmacMD5";/*** HMAC加密** @param data 数据* @param key 秘钥* @return 签名结果*/public static byte[] encryptHMAC(byte[] data, String key) throws Exception {SecretKey secretKey = new SecretKeySpec(key.getBytes(), KEY_MAC);Mac mac = Mac.getInstance(secretKey.getAlgorithm());mac.init(secretKey);return mac.doFinal(data);}/*** byte数组转换为HexString*/public static String byteArrayToHexString(byte[] bytes) {StringBuilder sb = new StringBuilder(bytes.length * 2);for (byte aByte : bytes) {int v = aByte & 0xff;if (v < 16) {sb.append('0');}sb.append(Integer.toHexString(v));}return sb.toString();}public static void main(String[] args) throws Exception {String inputStr = "{\"somek\":\"somev\"}";byte[] inputData = inputStr.getBytes();String key = "somekey";System.out.println(HmacUtil.byteArrayToHexString(HmacUtil.encryptHMAC(inputData, key)));}
外部系统调用此接口,可进行对车联网系统的单位联系人进行新增或修改操作,支持多单位联系人
/open/v1/unitContactors/add
请求数据区的类型为List<UnitContactor>,UnitContactor单位联系人定义如下
| 参数 | 是否必填 | 数据类型 | 说明 |
|---|---|---|---|
| name | 是 | String | 联系人姓名 |
| unitName | 是 | String | 所属单位, 需要在提前录入同步 |
| jobPost | 否 | String | 岗位 |
| jobNumber | 否 | String | 工号 |
| sex | 是 | int | 性别 1:男 2:女 |
| telPhone | 是 | String | 手机号码,手机号码作为唯一标识 |
| 否 | String | 电子邮箱 | |
| cardType | 否 | int | 证件类型 1:居民身份证 2:士官证 3 学生证 4 驾驶证 5 护照 6 港澳通行证 |
| cardNo | 否 | String | 证件号码 |
| cardAddress | 否 | String | 证件地址 |
| frontCardImg | 否 | String | 证件正面照片,Base64编码 |
| backCardImg | 否 | String | 证件背面照片,Base64编码 |
| faceCardImg | 否 | String | 手持证件照,Base64编码 |
响应数据区data类型为List<RespDetail>,RespDetail对象定义如下
| 参数 | 是否必填 | 数据类型 | 说明 |
|---|---|---|---|
| status | 是 | int | 状态 1:成功 0:失败 |
| errorMessage | 否 | String | 错误信息 |
外部系统调用此接口,可进行对车联网系统的个人车主信息进行新增或修改操作,支持多个人车主信息
/open/v1/vehOwners/add
请求数据区的类型为List<VehOwners>,VehOwners个人车主定义如下
| 参数 | 是否必填 | 数据类型 | 说明 |
|---|---|---|---|
| name | 是 | String | 联系人姓名 |
| sex | 是 | int | 性别 1:男 2:女 |
| telPhone | 是 | String | 手机号码,手机号码作为唯一标识 |
| 否 | String | 电子邮箱 | |
| cardType | 否 | int | 证件类型 1:居民身份证 2:士官证 3 学生证 4 驾驶证 5 护照 6 港澳通行证 |
| cardNo | 否 | String | 证件号码 |
| cardAddress | 否 | String | 证件地址 |
| frontCardImg | 否 | String | 证件正面照片,Base64编码 |
| backCardImg | 否 | String | 证件背面照片,Base64编码 |
| faceCardImg | 否 | String | 手持证件照,Base64编码 |
外部系统调用此接口,可进行对车联网系统的单位厂商信息进行新增或修改操作,支持多单位厂商信息
/open/v1/units/add
请求数据区的类型为List<Unit>,Unit单位厂商信息定义如下
| 参数 | 是否必填 | 数据类型 | 说明 |
|---|---|---|---|
| name | 是 | string | 单位名称 |
| nickName | 否 | string | 单位简称 |
| unitType | 是 | int | 单位类型 1:汽车厂商 2:经销商 3:购车单位 4:运营单位 5:供应商 ^政府部门 7:合作服务网点/4S店;支持多个,用逗号分隔 |
| parentUnitName | 否 | String | 上级单位名称,先于此步录入车联网系统 |
| parentUnitName | 否 | String | 上级单位名称,先于此步录入车联网系统 |
| address | 是 | string | 单位地址 |
| phone | 否 | String | 座机号 |
| bussinessLines | 否 | String | 业务种类 |
| brands | 否 | String | 产品或服务品牌名称,多个用逗号隔开 |
| organizationCode | 否 | String | 统一社会信用代码 |
| contactorName | 是 | String | 联系人姓名 |
| contactorPhone | 是 | String | 联系人手机号 |
| contactorAddress | 是 | String | 联系人地址 |
| licenceImg | 否 | String | 营业执照扫描照 |
| certImg | 否 | String | 授权书扫描照 |
响应数据区data类型为List<RespDetail>,RespDetail对象定义如下
| 参数 | 是否必填 | 数据类型 | 说明 |
|---|---|---|---|
| status | 是 | int | 状态 1:成功 0:失败 |
| errorMessage | 否 | String | 错误信息 |
外部系统调用此接口,可进行对车联网系统的车型配置进行新增或修改操作,支持多车型配置
/open/v1/vehModel/add
请求数据区的类型为List<VehModel>,VehModel车型配置定义如下
| 参数 | 是否必填 | 数据类型 | 说明 |
|---|---|---|---|
| name | 是 | string | 车型名称 |
| noticeName | 是 | string | 车型公告型号,需要提前在系统录入公告型号 |
| configName | 是 | string | 配置名称 |
| ruleType | 是 | int | 协议类型 1:国标 |
| detectionMechanismName | 否 | string | 检测机构名称 |
| vehReportNumber | 否 | string | 车型符合性报告编号 |
| chassisModel | 否 | string | 底盘型号 |
| chassisUnitName | 否 | string | 底盘生产企业,得提前录入系统 |
| vehWeight | 否 | double | 车重(kg) |
| curbWeight | 否 | double | 整备质量(kg) |
| vehLang | 否 | double | 车长(mm) |
| vehWide | 否 | double | 车宽(mm) |
| vehHigh | 否 | double | 车高(mm) |
响应数据区data类型为List<RespDetail>,RespDetail对象定义如下
| 参数 | 是否必填 | 数据类型 | 说明 |
|---|---|---|---|
| status | 是 | int | 状态 1:成功 0:失败 |
| errorMessage | 否 | String | 错误信息 |
外部系统调用此接口,可进行对车联网系统的SIM卡进行新增或修改操作,支持多SIM卡
/open/v1/sims/add
请求数据区的类型为List<Sim>,Sim定义如下
| 参数 | 是否必填 | 数据类型 | 说明 |
|---|---|---|---|
| iccid | 是 | string | iccid号,唯一 |
| msisdn | 否 | string | 移动用户号 |
| carrier_type | 是 | int | 运营商类型 1:联通 2:移动 3:电信 |
响应数据区data类型为List<RespDetail>,RespDetail对象定义如下
| 参数 | 是否必填 | 数据类型 | 说明 |
|---|---|---|---|
| status | 是 | int | 状态 1:成功 0:失败 |
| errorMessage | 否 | String | 错误信息 |
外部系统调用此接口,可进行对车联网系统的终端型号进行新增或修改操作,支持多终端型号
/open/v1/termModels/add
请求数据区的类型为List<TermModel>,TermModel定义如下
| 参数 | 是否必填 | 数据类型 | 说明 |
|---|---|---|---|
| name | 是 | string | 型号名称,唯一 |
| termCategory | 是 | int | 终端种类 1:车机 2:TBOX 3:OBD 4:智能后视镜 5:其他 |
| brandName | 否 | string | 品牌名称 |
| workingVoltage | 否 | double | 工作电压 |
| firmwareVersion | 否 | string | 硬件版本号 |
| powerWaste | 否 | string | 功耗 |
| unitName | 否 | string | 终端生产厂商, 需提前录入系统 |
| sleepElectricCurrent | 否 | double(mA) | 休眠电流 |
| builtInBatteryCapacity | 否 | double | 内置电池容量(Ah) |
响应数据区data类型为List<RespDetail>,RespDetail对象定义如下
| 参数 | 是否必填 | 数据类型 | 说明 |
|---|---|---|---|
| status | 是 | int | 状态 1:成功 0:失败 |
| errorMessage | 否 | String | 错误信息 |
外部系统调用此接口,可进行对车联网系统的 终端个体进行新增或修改操作,支持多终端个体
/open/v1/termUnits/add
请求数据区的类型为List<TermUnit>,TermUnit定义如下
| 参数 | 是否必填 | 数据类型 | 说明 |
|---|---|---|---|
| name | 是 | string | 型号名称,唯一 |
| termCategory | 是 | int | 终端种类 1:车机 2:TBOX 3:OBD 4:智能后视镜 5:其他 |
| brandName | 否 | string | 品牌名称 |
| workingVoltage | 否 | double | 工作电压 |
| firmwareVersion | 否 | string | 硬件版本号 |
| powerWaste | 否 | string | 功耗 |
| unitName | 否 | string | 终端生产厂商, 需提前录入系统 |
| sleepElectricCurrent | 否 | double(mA) | 休眠电流 |
| builtInBatteryCapacity | 否 | double | 内置电池容量(Ah) |
响应数据区data类型为List<RespDetail>,RespDetail对象定义如下
| 参数 | 是否必填 | 数据类型 | 说明 |
|---|---|---|---|
| status | 是 | int | 状态 1:成功 0:失败 |
| errorMessage | 否 | String | 错误信息 |
外部系统调用此接口,可进行对车联网系统的车辆基础信息进行新增或修改操作,支持多车辆
/open/v1/vehicleBaseInfo/add
请求数据区的类型为List<VehicleBaseInfo>,VehicleBaseInfo定义如下
| 参数 | 是否必填 | 数据类型 | 说明 |
|---|---|---|---|
| vin | 是 | string | 车架号 |
| interNo | 是 | string | 内部编号 |
| vehModelName | 是 | string | 车辆型号,要提前录入系统 |
| color | 否 | string | 车辆颜色,红、白、绿等 |
| nickColor | 否 | string | 颜色昵称/td> |
| termUnitNo | 否 | string | 终端编号,要提前录入系统 |
| engeryDeviceNos | 否 | string | 可充电储能编码,多个用逗号隔开。需要提前录入系统 |
| drvieDeviceNos | 否 | string | 驱动装置编码,多个用逗号隔开。需要提前录入系统 |
| elecDeviceNos | 否 | string | 发电装置编码,多个用逗号隔开。需要提前录入系统 |
| manuUnitName | 是 | string | 车辆生产企业,需要提前录入系统 |
| produceBatch | 否 | string | 生产批次 |
| qualityYears | 否 | int | 整车质保期(年) |
| vehCertificateNumber | 否 | int | 车辆合格证编号 |
| produceDate | 否 | int | 车辆生产日期,格式yy-MM-dd |
| factoryDate | 否 | int | 车辆出厂日期,格式yy-MM-dd |
响应数据区data类型为List<RespDetail>,RespDetail对象定义如下
| 参数 | 是否必填 | 数据类型 | 说明 |
|---|---|---|---|
| status | 是 | int | 状态 1:成功 0:失败 |
| errorMessage | 否 | String | 错误信息 |
外部系统调用此接口,可进行对车联网系统的车辆基础信息进行新增或修改操作,支持多车辆
/open/v1/vehicleSellInfo/add
请求数据区的类型为List<vehicleSellInfo>,vehicleSellInfo定义如下
| 参数 | 是否必填 | 数据类型 | 说明 |
|---|---|---|---|
| vin | 是 | string | 车架号 |
| sellDate | 否 | int | 车辆销售日期,格式yy-MM-dd |
| sellPrice | 是 | double | 销售价格(万元) |
| sellForField | 是 | int | 购车领域 1:私人领域 2:公共领域 |
| priVehOwnerPhone | 否 | string | 车主手机号码,私人领域车辆必填此项 |
| pubUnitName | 否 | string | 购车单位名称,需提前录入系统,公共领域车辆必填此项 |
| sell4sUnitName | 是 | string | 经销商单位名称,需提前录入系统 |
| sellerPhone | 是 | string | 销售人员手机号码(对应单位联系人),需要提前录入系统 |
| secureDate | 否 | string | 投保日期,格式yy-MM-dd |
| firstCheckDate | 否 | string | 首次年检日期,格式yy-MM-dd |
| invoiceNo | 否 | string | 发票号 |
| invoiceDate | 否 | string | 发票开具日期,格式yy-MM-dd |
| invoiceImg | 否 | string | 发票图片,Base64编码 |
| licenseNo | 否 | string | 车辆行驶证号/td> |
| licenseRegDate | 否 | string | 车辆行驶证注册日期,格式yy-MM-dd |
| licenseGrantDate | 否 | string | 车辆行驶证发放日期,格式yy-MM-dd |
| licenseImg | 否 | string | 行驶证图片,Base64编码 |
响应数据区data类型为List<RespDetail>,RespDetail对象定义如下
| 参数 | 是否必填 | 数据类型 | 说明 |
|---|---|---|---|
| status | 是 | int | 状态 1:成功 0:失败 |
| errorMessage | 否 | String | 错误信息 |
外部系统调用此接口,可进行对车联网系统的车辆运营信息进行新增或修改操作,支持多车辆
/open/v1/vehicleOperInfo/add
请求数据区的类型为List<vehicleOperInfo>,vehicleOperInfo定义如下
| 参数 | 是否必填 | 数据类型 | 说明 |
|---|---|---|---|
| vin | 是 | string | 车架号 |
| licensePlate | 是 | string | 车牌号 |
| licenseType | 是 | int | 车牌类型,参见车牌类型字典定义 |
| licenseCityName | 是 | string | 上牌城市名称 |
| vehUseFor | 是 | int | 车辆用途,参见车辆用途字典定义 |
| vehUseType | 是 | int | 车辆运营性质,参见车辆运营性质字典定义 |
| vehOwnerPhone | 是 | string | 个人车主手机号码,需提前录入系统 |
| operUnitName | 是 | string | 运营单位名称,需提前录入系统 |
| operInterNo | 否 | string | 运营单位内部编号 |
| operAreaName | 否 | string | 运营区域名称 |
| operTime | 否 | string | 投运日期 |
| operSupportOwnerPhone | 否 | string | 售后负责人手机号码,需要提前录入系统 |
| operSaveCityName | 否 | string | 存放城市名称 |
| operSaveAddress | 否 | string | 详细存放地址 |
| operPoleCityName | 否 | string | 充电桩城市名称 |
| operPoleAddress | 否 | string | 充电桩地址 |
响应数据区data类型为List<RespDetail>,RespDetail对象定义如下
| 参数 | 是否必填 | 数据类型 | 说明 |
|---|---|---|---|
| status | 是 | int | 状态 1:成功 0:失败 |
| errorMessage | 否 | String | 错误信息 |
外部系统调用此接口,可进行对车联网系统的车辆补贴信息进行新增或修改操作,支持多车辆
/open/v1/vehicleSubsidyInfo/add
请求数据区的类型为List<vehicleSubsidyInfo>,vehicleSubsidyInfo定义如下
| 参数 | 是否必填 | 数据类型 | 说明 |
|---|---|---|---|
| vin | 是 | string | 车架号 |
| subsidyApplyStatus | 是 | int | 申报状态,参见字典定义 |
| susidyApplyCount | 是 | int | 申报次数 |
响应数据区data类型为List<RespDetail>,RespDetail对象定义如下
| 参数 | 是否必填 | 数据类型 | 说明 |
|---|---|---|---|
| status | 是 | int | 状态 1:成功 0:失败 |
| errorMessage | 否 |
| 值 | 描述 |
|---|---|
| 0 | 请求正确 |
| 1001 | token不合法或无权限 |
| 1002 | 参数缺失 |
| 1003 | 令牌为空 |
| 1004 | 该账号处于无效状态 |
| 1005 | 该账号已过期 |
| 1006 | 您无当前接口的访问权限 |
| 1011 | 该账号当天访问次数已达到限制 |
| 1012 | 该账号每分钟访问次数已达到限制 |
| 1013 | 您当前接口当天的访问次数已达到限制 |
| 1014 | 您当前接口每分钟访问次数已达到限制 |
| 1021 | 请求已过期,请确认时间戳正常 |
| 1022 | 签名验证失败 |
/*** 加密* @param content 待加密内容* @return*/public static String encrypt(String content) {try {if (StringUtil.isEmpty(content))return "";String password = AES_KEY;KeyGenerator kgen = KeyGenerator.getInstance("AES");SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG");secureRandom.setSeed(password.getBytes());kgen.init(128, secureRandom);SecretKey secretKey = kgen.generateKey();byte[] enCodeFormat = secretKey.getEncoded();SecretKeySpec key = new SecretKeySpec(enCodeFormat, "AES");Cipher cipher = Cipher.getInstance("AES");// 创建密码器byte[] byteContent = content.getBytes("utf-8");cipher.init(Cipher.ENCRYPT_MODE, key);// 初始化byte[] result = cipher.doFinal(byteContent);String str = Base64.encode(result);return str; // 加密} catch (NoSuchAlgorithmException e) {// e.printStackTrace();} catch (NoSuchPaddingException e) {// e.printStackTrace();} catch (InvalidKeyException e) {// e.printStackTrace();} catch (UnsupportedEncodingException e) {// e.printStackTrace();} catch (IllegalBlockSizeException e) {// e.printStackTrace();} catch (BadPaddingException e) {// e.printStackTrace();}return null;}/*** 解密* @param str 待解密内容* @return*/public static String decrypt(String str) {try {String password = AES_KEY;byte[] content = Base64.decode(str);KeyGenerator kgen = KeyGenerator.getInstance("AES");SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG");secureRandom.setSeed(password.getBytes());kgen.init(128, secureRandom);SecretKey secretKey = kgen.generateKey();byte[] enCodeFormat = secretKey.getEncoded();SecretKeySpec key = new SecretKeySpec(enCodeFormat, "AES");Cipher cipher = Cipher.getInstance("AES");// 创建密码器cipher.init(Cipher.DECRYPT_MODE, key);// 初始化byte[] result = cipher.doFinal(content);return new String(result); // 加密} catch (NoSuchAlgorithmException e) {// e.printStackTrace();} catch (NoSuchPaddingException e) {// e.printStackTrace();} catch (InvalidKeyException e) {// e.printStackTrace();} catch (IllegalBlockSizeException e) {// e.printStackTrace();} catch (BadPaddingException e) {// e.printStackTrace();}catch (Exception e){// e.printStackTrace();}return "";}
public class RSAUtil {/*** 加密算法RSA*/public static final String KEY_ALGORITHM = "RSA";/*** 签名算法*/public static final String SIGNATURE_ALGORITHM = "MD5withRSA";/*** RSA最大加密明文大小*/private static final int MAX_ENCRYPT_BLOCK = 117;/*** RSA最大解密密文大小*/private static final int MAX_DECRYPT_BLOCK = 128;/*** 公钥加密* @param msg 源数据* @param publicKey 公钥(BASE64编码)* @return* @throws Exception*/public static String encryptByPublicKey(String msg, String publicKey) throws Exception {byte[] data = msg.getBytes("UTF-8");byte[] keyBytes = Base64.decode(publicKey);X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);Key publicK = keyFactory.generatePublic(x509KeySpec);// 对数据加密Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());cipher.init(Cipher.ENCRYPT_MODE, publicK);int inputLen = data.length;ByteArrayOutputStream out = new ByteArrayOutputStream();int offSet = 0;byte[] cache;int i = 0;// 对数据分段加密while (inputLen - offSet > 0) {if (inputLen - offSet > MAX_ENCRYPT_BLOCK) {cache = cipher.doFinal(data, offSet, MAX_ENCRYPT_BLOCK);} else {cache = cipher.doFinal(data, offSet, inputLen - offSet);}out.write(cache, 0, cache.length);i++;offSet = i * MAX_ENCRYPT_BLOCK;}byte[] encryptedData = out.toByteArray();out.close();String retStr = Base64.encodeToString(encryptedData);return retStr;}/*** 私钥解密* @param encryptedMsg 已加密数据* @param privateKey 私钥(BASE64编码)* @return* @throws Exception*/public static String decryptByPrivateKey(String encryptedMsg, String privateKey)throws Exception {byte[] keyBytes = Base64.decode(privateKey);PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);Key privateK = keyFactory.generatePrivate(pkcs8KeySpec);Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());cipher.init(Cipher.DECRYPT_MODE, privateK);byte[] encryptedData = Base64.decode(encryptedMsg);int inputLen = encryptedData.length;ByteArrayOutputStream out = new ByteArrayOutputStream();int offSet = 0;byte[] cache;int i = 0;// 对数据分段解密while (inputLen - offSet > 0) {if (inputLen - offSet > MAX_DECRYPT_BLOCK) {cache = cipher.doFinal(encryptedData, offSet, MAX_DECRYPT_BLOCK);} else {cache = cipher.doFinal(encryptedData, offSet, inputLen - offSet);}out.write(cache, 0, cache.length);i++;offSet = i * MAX_DECRYPT_BLOCK;}byte[] decryptedData = out.toByteArray();out.close();return new String(decryptedData);}/*** 私钥加密* @param msg 源数据* @param privateKey 私钥(BASE64编码)* @return* @throws Exception*/public static String encryptByPrivateKey(String msg, String privateKey)throws Exception {byte[] data = msg.getBytes("UTF-8");byte[] keyBytes = Base64.decode(privateKey);PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);Key privateK = keyFactory.generatePrivate(pkcs8KeySpec);Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());cipher.init(Cipher.ENCRYPT_MODE, privateK);int inputLen = data.length;ByteArrayOutputStream out = new ByteArrayOutputStream();int offSet = 0;byte[] cache;int i = 0;// 对数据分段加密while (inputLen - offSet > 0) {if (inputLen - offSet > MAX_ENCRYPT_BLOCK) {cache = cipher.doFinal(data, offSet, MAX_ENCRYPT_BLOCK);} else {cache = cipher.doFinal(data, offSet, inputLen - offSet);}out.write(cache, 0, cache.length);i++;offSet = i * MAX_ENCRYPT_BLOCK;}byte[] encryptedData = out.toByteArray();out.close();String retStr = Base64.encodeToString(encryptedData);return retStr;}/*** 公钥解密* @param encryptedMsg 已加密数据* @param publicKey 公钥(BASE64编码)* @return* @throws Exception*/public static String decryptByPublicKey(String encryptedMsg, String publicKey)throws Exception {byte[] keyBytes = Base64.decode(publicKey);X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);Key publicK = keyFactory.generatePublic(x509KeySpec);Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());cipher.init(Cipher.DECRYPT_MODE, publicK);byte[] encryptedData = Base64.decode(encryptedMsg);int inputLen = encryptedData.length;ByteArrayOutputStream out = new ByteArrayOutputStream();int offSet = 0;byte[] cache;int i = 0;// 对数据分段解密while (inputLen - offSet > 0) {if (inputLen - offSet > MAX_DECRYPT_BLOCK) {cache = cipher.doFinal(encryptedData, offSet, MAX_DECRYPT_BLOCK);} else {cache = cipher.doFinal(encryptedData, offSet, inputLen - offSet);}out.write(cache, 0, cache.length);i++;offSet = i * MAX_DECRYPT_BLOCK;}byte[] decryptedData = out.toByteArray();out.close();return new String(decryptedData);}}
| 编号 | 数据项名称 | 描述 |
|---|---|---|
| 1001 | 注册时间 | |
| 1002 | 注册流水号 | |
| 1003 | 车牌号 | |
| 1004 | 车载终端编号 | |
| 1005 | 车辆动力类型 | |
| 1006 | 动力蓄电池包总数 | |
| 1007 | 动力蓄电池代码列表 | |
| 1008 | 发动机编码 | |
| 1009 | 燃油种类 | |
| 1010 | 最大输出功率 | |
| 1011 | 最大输出转矩 | |
| 1012 | 注册预留 | |
| 1020 | 终端登入/登出流水号 | |
| 1021 | ICCID | |
| 1022 | 可充电储能子系统数 | |
| 1023 | 可充电储能系统编码长度 | |
| 1024 | 可充电储能系统编码 | |
| 1025 | 终端登入/登出时间 | |
| 1026 | 平台登入/登出时间 | |
| 1027 | 平台登入/登出流水号 | |
| 1028 | 平台用户名 | |
| 1029 | 平台密码 | |
| 1031 | 终端登出时间 | |
| 1033 | 终端登出流水号 | |
| 2000 | 实时数据时间 | |
| 2001 | 单体蓄电池总数 | |
| 2002 | 动力蓄电池包总数 | |
| 2003 | 单体蓄电池电压值 | |
| 2004 | 动力蓄电池预留 | |
| 2005 | 动力蓄电池包总数 | |
| 2101 | 动力蓄电池包温度探针总数 | |
| 2102 | 动力蓄电池包总数 | |
| 2103 | 温度值 | |
| 2110 | 燃料电池电压 | |
| 2111 | 燃料电池电流 | |
| 2112 | 燃料消耗率 | |
| 2113 | 燃料电池温度探针总数 | |
| 2114 | 探针温度值 | |
| 2115 | 氢系统中最高温度 | |
| 2116 | 氢系统中最高温度探针代号 | |
| 2117 | 氢气最高浓度 | |
| 2118 | 氢气最高浓度传感器代号 | |
| 2119 | 氢气最高压力 | |
| 2120 | 氢气最高压力传感器代号 | |
| 2121 | 高压DC/DC状态 | |
| 2201 | 车速 | |
| 2202 | 里程 | |
| 2203 | 档位 | |
| 2204 | 制动状态 | |
| 2205 | 驱动状态 | |
| 2206 | 预留 | |
| 2207 | 预留 | |
| 2208 | 加速踏板行程值 | |
| 2209 | 制动踏板行程值 | |
| 2211 | 整车数据预留 | |
| 2212 | 实时数据信息类型预留 | |
| 2213 | 运行模式 | |
| 2214 | DC-DC状态 | |
| 2301 | 充放电状态 | |
| 2302 | 电机控制器温度 | |
| 2303 | 电机转速 | |
| 2304 | 电机温度 | |
| 2305 | 电机电压 | |
| 2306 | 电机母线电流 | |
| 2307 | 驱动电机个数 | |
| 2308 | 驱动电机总成信息列表 | |
| 2309 | 驱动电机序号 | |
| 2310 | 驱动电机状态 | |
| 2311 | 驱动电机转矩 | |
| 2401 | 发动机状态 | |
| 2402 | ECU温度 | |
| 2403 | 车辆电池电压 | |
| 2404 | 发动机温度 | |
| 2405 | 进气歧管气压 | |
| 2406 | 进气温度 | |
| 2407 | 废气排出温度 | |
| 2408 | 燃料喷射压力 | |
| 2409 | 燃料喷射量 | |
| 2410 | 点火提前角 | |
| 2411 | 曲轴转速 | |
| 2412 | 油门开度 | |
| 2413 | 燃料消耗率 | |
| 2501 | 定位状态 | |
| 2502 | 经度 | |
| 2503 | 纬度 | |
| 2506 | 定位数据预留 | |
| 2601 | 最高电压动力蓄电池包序号 | |
| 2602 | 最高电压单体蓄电池序号 | |
| 2603 | 电池单体电压最高值 | |
| 2604 | 最低电压动力蓄电池包序号 | |
| 2605 | 最低电压单体蓄电池序号 | |
| 2606 | 电池单体电压最低值 | |
| 2607 | 最高温度动力蓄电池包序号 | |
| 2608 | 最高温度探针序号 | |
| 2609 | 最高温度值 | |
| 2610 | 最低温度动力蓄电池包序号 | |
| 2611 | 最低温度探针序号 | |
| 2612 | 最低温度值 | |
| 2613 | 总电压 | |
| 2614 | 总电流 | |
| 2615 | SOC | |
| 2617 | 正极对地电阻 | |
| 2618 | 极值数据预留 | |
| 2701 | 自定义数据长度 | |
| 2702 | 自定义数据 | |
| 2802 | 动力蓄电池其他故障总数n | |
| 2803 | 动力蓄电池其他故障代码列表 | |
| 2804 | 电机故障总数N | |
| 2805 | 电机故障代码列表 | |
| 2806 | 发动机故障总数N1 | |
| 2807 | 发动机故障列表(2308) | |
| 2808 | 其他故障总数M | |
| 2809 | 其他故障代码列表 | |
| 2901 | 温度差异报警 | |
| 2902 | 电池极柱高温报警 | |
| 2903 | 动力蓄电池包过压报警 | |
| 2904 | 动力蓄电池包欠压报警 | |
| 2905 | SOC低报警 | |
| 2906 | 单体蓄电池过压报警 | |
| 2907 | 单体蓄电池欠压报警 | |
| 2908 | SOC太低报警 | |
| 2909 | SOC过高报警 | |
| 2910 | 动力蓄电池包不匹配报警 | |
| 2911 | 动力蓄电池一致性差报警 | |
| 2912 | 绝缘故障 | |
| 2920 | 最高报警等级 | |
| 2921 | 可充电储能装置故障总数N1 | |
| 2922 | 可充电储能装置故障代码列表 | |
| 2923 | 发动机故障总数N3 | |
| 2924 | 发动机故障列表(2924) | |
| 3101 | 信息采集时间 | |
| 3102 | 通电状态 | |
| 3103 | 电源正常 | |
| 3104 | 通信传输状态 | |
| 3105 | 其他异常 | |
| 3106 | 车载终端预留 | |
| 3201 | 车辆状态 | |
| 3202 | 状态标志 | |
| 3301 | 系统预留1 | |
| 3302 | 系统预留2 | |
| 3303 | 系统预留3 | |
| 3401 | 终端参数查询 | |
| 3402 | 终端参数设置 | |
| 3403 | 终端控制命令 | |
| 3801 | 通用报警状态 |