新手指南
成为开发者
-
G7S用户,直接通过G7S账号授权登录
-
非G7S用户,进行开发者账号申请,审核通过后使用开放平台账号登录
- 开发者账号申请
在开发者账号申请页面[链接]完成相关信息填写,并提交。 - 资质认证
在我们确定了开发者的身份以后,会将审核结果发送到所申请的邮箱,如果审核通过,邮件会附上您的账号和密码。
第一次登录,及时修改密码后便可以进入操作界面。
数据申请
-
进入产品中心,在产品中心查看需要使用的接口或者相关的推送数据,点击立即申请并提交审核。然后进入控制台便可以查看到审核的状态,审核通过后AccessID和Secret也将在控制台展示。
-
您可通过AccessID和Secret获取您想要的数据,具体使用方法请详见开发指南的对应模块。
-
AccessID和Secret它们的作用是计算验证签名,请妥善保管,不要泄露。
开发指南
RestAPI
开发准备
确保已经在产品中心-Rest API下完成了所需API的申请并取得相应的AccessId/SecretKey
SDK下载及文档
为方便开发者调试和接入开放平台产品 API,这里为您介绍开发工具包,让您快速获取SDK 并开始调用。
适用范围 | 语言 | 下载 |
---|---|---|
openAPI | C#/ java / php / python | open-sdk |
下面以java的sdk举例进行联调说明:
- 首先将SDK工程导入到IDE中,用导入maven工程的方式进行即可。
-
依赖环境
- JDK版本1.8及以上
- maven版本3.3.9及以上
-
MyEclipse导入后的工程结构:
-
Intellj IDEA导入后的工程结构:
-
程序入口可参照<openapi-sdk-demo-java\src\test\java\com\chinawayltd\altair\demo>目录下的Demo.java文件:
-
配置参数说明:
//APP KEY(申请接入码后给出的AccessID)
private final static String ACCESS_ID = "02co9r";
// APP密钥(申请接入码后给出的SecretKey)
private final static String SECRET_KEY = "EZRUPGx1PY99WSYE1GO7eEoXaOAniP14";
/** API域名(服务访问的地址)
* demo环境为:demo.dsp.chinawayltd.com/altair/rest
* 生产环境为:openapi.huoyunren.com
*/
private final static String BaseURL = "demo.dsp.chinawayltd.com/altair/rest";
//请求path(openAPI文档中给出的业务接口的路径)
String path = "/v1/base/truck/history_location";
根据openAPI业务接口的请求类型的不同,如Get和Post,这个在具体的接口文档中有,其接口参数传递方式也有所区别。
- Get请求是将参数组装到map中,然后设置到request对象中,详情可参考Demo.java中的代码:
//GET请求的query
Map<String, String> querys = new HashMap<>();
querys.put("plate_num", "部A11110");
querys.put("from", "2017-11-25 00:00:00");
querys.put("to", "2017-11-30 00:00:00");
request.setQueries(querys);
- Post请求需要将请求的参数序列化成Json字符串,然后传递给业务接口。详情可参考Demo.java中的postJson方法:
public void postJson() throws Exception {
//请求path(openAPI文档中给出的业务接口的路径)
String path = "/v1/base/current/full_currents";
//Body内容(请求参数)
String body = "{\n" +
"\"carnum\": \"川A12345\",\n" +
"\"longitude\": \"104.07134\",\n" +
"\"latitude\": \"30.54013\"\n" +
"}";
System.out.println(body);
Map<String, String> headers = new HashMap<String, String>();
headers.put(HttpHeader.HTTP_HEADER_CONTENT_MD5, MessageDigestUtil.base64AndMD5(body));
//(POST/PUT请求必选)请求Body内容格式
headers.put(HttpHeader.HTTP_HEADER_CONTENT_TYPE, ContentType.CONTENT_TYPE_JSON);
// headers.put("d-header1", "header1Value");
// headers.put("X-G7-Ca-a-header1", "header1Value");
// headers.put("X-G7-Ca-b-header2", "header2Value");
headers.put(HttpHeader.HTTP_HEADER_G7_TIMESTAMP, "" + System.currentTimeMillis());
Request request = new Request(Method.POST_JSON, HttpSchema.HTTP + BaseURL, path, ACCESS_ID, SECRET_KEY, Constants.DEFAULT_TIMEOUT);
request.setHeaders(headers);
request.setJsonStrBody(body);
//调用服务端
Response response = Client.execute(request);
LOG.info(response.getBody());
}
常见问题(FAQ)
- 咨询问题必看:若检查到最后仍无法解决问题时,进行咨询的时候,请将请求的 ACCESS_ID 、SECRET_KEY、PATH以及请求响应返回的结果JSON字符串用文本格式发出,请勿截图。可咨询张双建 [email protected] 或陈坤云 [email protected]
程序报请求超时或读写超时?
- 首先请检查下BaseURL是否填写正确,DEMO环境的为demo.dsp.chinawayltd.com/altair/rest,生产环境的为:openapi.huoyunren.com
- 在所在服务器或主机上PING一下BaseURL中的host,看能否PING通,PING不通的话请找网管处理。
- 若能PING通,请检查下程序中设置的HTTP请求的读写超时的相关配置,尝试配置超时时间多一点(如:10秒钟)看看
- 经过以上操作还不行,可咨询 张双建 [email protected] 或 陈坤云 [email protected]
接口响应信息报 no permission, api can't access
- 先检查下程序中的ACCESS_ID和SECRET_KEY是否填写正确。
- 检查调用业务接口的PATH是否填写正确。
- 经过以上操作还不行,可咨询张双建 [email protected] 或 陈坤云 [email protected]
接口响应信息报auth failed:signature error
- 请严格参考demo程序中的代码进行签名操作,阅览用户包中OpenAPI系统认证机制文档
接口响应信息报wrong timestamp
- 先确认所在服务器或主机时间是否是当前标准的北京时间
- timestamp时间格式应为毫秒长整型
- timestamp参数的值应放置在请求头的X-G7-OpenAPI-Timestamp参数中
HTTP推送服务
服务接入
概述、使用场景及限制
G7提供的HTTP推送服务,是一种将车辆设备数据实时发送给数据使用方的服务。当设备上传数据后,推送服务会第一时间感知,在将数据整理打包后,通过HTTP链路发送到订阅事件数据的客户,客户接收数据后可根据自身业务自行处理数据。
HTTP推送服务适用于发生频率较低的事件,比如进出区域、停留、超速等事件。对于一些发生频率较高的事件,比如定位,推荐使用MQTT推送服务。接收限制:HTTP推送服务与客户数据接收服务是紧耦合关联的,推送服务的吞吐量严重依赖接收服务的响应速度,一旦接收服务响应速度过慢,就有可能造成推送服务的线程堆积,消耗大量资源无法释放,最严重的情况使推送服务崩溃。所以,接收服务在接收到数据后,必须以最快的速度接收并返回接收结果。数据的业务逻辑处理请放入线程池,或者放入kafka中间件后再处理。如果接收服务响应速度过慢导致大量推送超时,或者接收服务不可用,为保护推送服务,当单一事件失败超过20000条时,相关推送服务会自动关闭。关闭后可联系管理员重新开启。
服务接入流程
-
申请:见对应数据申请,每个HTTP事件都需要单独申请。
-
提供推送数据接收服务的HTTP回调地址,推送服务将根据这个地址发送数据,此时请保证接收服务已开发完成并上线。
推送接收与开发
开发准备
-
确保已经在产品中心-推送下完成了所需推送数据的申请并取得相应的AccessId/SecretKey
-
确保提供了推送数据接收服务的HTTP回调地址,推送数据接收服务是一种web应用程序,须提供一个回调地址,由推送服务将事件数据通过回调地址发送到接收服务。
接收服务的HTTP请求规范
接收服务的HTTP请求须满足如下格式:
method: POST
content-type: application/json; charset=UTF-8
接收服务HTTP请求的header包含如下信息:
Authorization: g7ac {Timestamp} {AccessId}:{Signature}
字段名 | 描述 |
---|---|
Timestamp | 时间戳(ms) |
AccessId | 由用户申请 |
Signature | 签名字符串,具体算法见章节3 |
推送服务推送的事件数据放置在接收服务HTTP请求的body中,具体格式请参考《推送事件》
签名算法
Signature = Base64(HMAC_SHA1({SecretKey}, UTF_8_Encoding_Of(StringToSign)));
StringToSign = HTTP-Verb + "\n" + content_MD5 + "\n" + Content-Type + "\n" + Timestamp + "\n" + {回调uri}
StringToSign相关字段
字段 | 描述 |
---|---|
HTTP-Verb | HTTP请求的方法,如__GET/POST__ |
content_MD5 | 对HTTP请求的body做MD5, 然后结果转成__小写__ |
Content-Type | 这里固定成application/json; charset=UTF-8 |
回调uri | 资源路径(注意:不是URL) |
Signature相关字段
字段 | 描述 |
---|---|
SecretKey | 由用户申请和AccessId配对的secret |
签名算法示例
参数:
HTTP-Verb = POST
//content即Http请求body部分,返回的事件数据以json的方式存在
content = {"code":null,"msg":null,"event":"rangeEvent","pushTime":1509075000048,"data":{"code":"00893","carnum":"闽ADF518",
"driverName":"","driverno":"","eventid":895172472687300608,"gpsno":"90016335","imei":"107015090016335","intTruckId":null,
"latitude":45.311760757237025,"longitude":130.97304330793787,"media":0,"nextId":0,"oid":"38B4BF2984F17FC77198E3556F5ECE3D48",
"orgcode":"2007XM","pointName":"467A鸡西分部","time":1502260718000,"type":2}}
//对content进行md5计算后的结果
content_MD5 = 315ecbaf920e7b98f62cc65fc4bda933
Content-Type = application/json; charset=UTF-8
Timestamp = 1509075000048
回调地址 = http://localhost:9516/zuul/push/test
回调uri = /zuul/push/test
//AccessId和SecretKey由G7分配,是对G7对数据访问权限的控制方式,请妥善保管,不要泄漏给第三方
AccessId = SR2DUNk
SecretKey = 7abc2fe88c955e067a1a5e913bbac741048ac76a
计算过程:
//StringToSign = HTTP-Verb + "\n" + content_MD5 + "\n" + Content-Type + "\n" + Timestamp + "\n" + {回调uri}
StringToSign = POST\n315ecbaf920e7b98f62cc65fc4bda933\napplication/json; charset=UTF-8\n1509075000048\n/zuul/push/test
//Signature = Base64(HMAC_SHA1({SecretKey}, UTF_8_Encoding_Of(StringToSign)))
Signature = cFj2cHeLMdxNCUoX/8cIvBWngYw=
//Authorization: g7ac {Timestamp} {AccessId}:{Signature}
Authorization=g7ac 1509075000048 SR2DUNk:cFj2cHeLMdxNCUoX/8cIvBWngYw=
结果:
//计算完成后放入http的head中
Authorization: g7ac 1509075000048 SR2DUNk:cFj2cHeLMdxNCUoX/8cIvBWngYw=
接收服务HTTP请求返回结果格式
返回类型:content-type: application/json; charset=UTF-8
返回值格式:
{
"code": 0,
"msg" : "ok"
}
字段 | 描述 |
---|---|
code | 0表示成功,其他数字表示失败 |
msg | 成功或失败的描述 |
注
:如果推送失败,则会在两小时内重试3次
MQTT推送服务
服务接入需知
概述、使用场景及限制
G7提供的MQTT推送服务,是一种将车辆设备数据实时发送给数据使用方的服务。 当设备上传数据后,推送服务会第一时间感知,在将数据整理打包后,发送至MQTT服务器,客户数据接收服务从MQTT服务器获取数据,然后客户根据自身业务自行处理数据。
MQTT推送服务使用MQTT服务器将推送服务和接收服务解耦,为高并发高可用提供保障,并支持数据的短暂缓存,适用于各种发生频率的事件。G7优先推荐使用MQTT推送服务。
MQTT协议及服务器
测试服务器地址:tcp://123.56.0.101:1993
正式服务器地址:tcp://openapi.huoyunren.com:1883
以上两个服务器都是需要用户验证的,且只能接收规定topic的数据。如果需要开发用MQTT服务器,可以使用EMQ提供的服务集群q.emqtt.com:1883 ,该集群没有任何限制。
- 第一次登陆时,MQTT服务器建立客户端clientId对应的session,在客户端订阅topic后,服务器发送当前topic的最新一条数据给客户端(发送最新一条的机制由MQTT协议规定)
- session的主要作用是管理topic的访问情况,一个clientId对应一个session。如果客户端关闭时选择不清除session,那么下次以相同clientId登陆后,服务器将从上次访问的位置发送数据;否则,清除了session,服务器发送topic的最新一条数据给客户端
- G7的MQTT服务器session过期时间为3天,过期后客户端重新连接服务器,将从最新一条数据开始访问,未消费的历史数据在session过期时被服务器自动清理。如要获取超过3天的数据,请使用开放平台访问历史数据的相关API
- 更多解释请查看MQTT规范http://mqtt.org/ 。
服务接入流程
- 申请:见数据申请,每个MQTT事件都需要单独申请。
- 每种订阅事件都对应一个clientId和topic,应用保存后系统生成,接收服务连接MQTT服务器时使用。
接收服务中会使用accessId和secret,它们的作用是连接MQTT服务器时的权限验证,请妥善保管,不要泄露
推送接收与开发
开发准备
-
确保已经在产品中心-推送下完成了所需推送数据的申请并取得相应的AccessId/SecretKey,AccessId/SecretKey对应于连接MQTT服务器时要求的user/password,在接收程序中会使用到。
-
平台将为每一种事件订阅生成一个topic和clientId,在接收服务中会使用到。支持的事件和事件的数据结构请查看《推送事件》
接收服务开发
推送数据接收程序是一种包含MQTT客户端的应用程序,对开发语言没有限制,只要支持MQTT协议即可。 目前接受程序只能订阅MQTT服务器数据,不能向MQTT服务器发送数据。 下面使用java的开源MQTT客户端paho对数据接收程序进行说明(代码中的accessId/secretKey/clientId/topic均为虚构)
引入paho依赖
<dependency>
<groupId>org.eclipse.paho</groupId>
<artifactId>org.eclipse.paho.client.mqttv3</artifactId>
<version>1.2.0</version>
</dependency>
建立MQTT连接
建立连接的时候需使用AccessId、secret、topic、clientId均为系统分配,其中AccessId对应客户端的user,secret对应客户端的password。
String user = "u8vngl";//user为accessId
String password = "xxxxxx";//password为secretKey
String topic = "u8vngl/rangeEvent";
int qos = 1;//qos2消耗较大,请使用1或0
String broker = "tcp://123.56.0.101:1993";//mqtt服务器地址
String clientId = "200061/u8vngl/rangeEvent";
//qos为1或2时,mqttclient使用
MemoryPersistence persistence = new MemoryPersistence();
try {
MqttClient client = new MqttClient(broker, clientId, persistence);
MqttConnectOptions connOpts = new MqttConnectOptions();
connOpts.setUserName(user);
connOpts.setPassword(password.toCharArray());
//cleanSession为false时,下次以相同clientId登录将可以获取存储的所有消息
//如果为true,将获取到retained标记的最后一条消息
connOpts.setCleanSession(false);
connOpts.setAutomaticReconnect(true);//设置自动重连
client.setCallback(new MqttCallback());//获取订阅消息
client.connect(connOpts);
client.subscribe(topic, qos);//订阅topic
} catch(MqttException me) {
me.printStackTrace();
}
获取订阅消息
paho的消息获取通过实现MqttCallback接口,MqttCallback接口通过messageArrived方法获取消息
@Override
public void messageArrived(String topic, MqttMessage message) throws Exception {
//messge的处理请放入其他线程中,在该方法中消耗时间过多将影响qos为1或2的响应,使服务器认为未成功投递消息
System.out.println("topic:" + topic + " msg:" + message);
}