@chenpbh
2019-03-27T12:03:19.000000Z
字数 18026
阅读 412
开放接口
版本 | 日期 | 人员 | 变更内容 |
---|---|---|---|
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 | 通用报警状态 |