最近因为工作的需要,对接了国内四大厂商应用商店的API,获取广告投放数据,针对四大厂商的OpenAPI实现方案进行分析。帮忙我们设计一个优雅的openapi。
请求示例
POST /api/oauth2/v1/token
Host: connect-api.cloud.huawei.com
Content-Type: application/json
{
"grant_type":"client_credentials",
"client_id":"26********20",
"client_secret":"************************"
}
响应示例
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
{
"access_token": "eyJhbGciOiJIUzU****************",
"expires_in": 172800
}
调用示例
public static String getToken(String domain, String clientId, String clientSecret) {
String token = null;
try {
HttpPost post = new HttpPost(domain + "/oauth2/v1/token");
JSONObject keyString = new JSONObject();
keyString.put("client_id", "18893***83957248");
keyString.put("client_secret", "B15B497B44E080EBE2C4DE4E74930***52409516B2A1A5C8F0FCD2C579A8EB14");
keyString.put("grant_type", "client_credentials");
StringEntity entity = new StringEntity(keyString.toString(), Charset.forName("UTF-8"));
entity.setContentEncoding("UTF-8");
entity.setContentType("application/json");
post.setEntity(entity);
CloseableHttpClient httpClient = HttpClients.createDefault();
HttpResponse response = httpClient.execute(post);
int statusCode = response.getStatusLine().getStatusCode();
if (statusCode == HttpStatus.SC_OK) {
BufferedReader br =
new BufferedReader(new InputStreamReader(response.getEntity().getContent(), Consts.UTF_8));
String result = br.readLine();
JSONObject object = JSON.parseObject(result);
token = object.getString("access_token");
}
post.releaseConnection();
httpClient.close();
} catch (Exception e) {
}
return token;
}
请求示例
POST https://connect-api.cloud.huawei.com/api/marketing-api/v1/report/ad/subtask
Content-type: application/json
Authorization: Bearer ***
client_id:***
{
"startDate":"2021-09-14",
"endDate":"2021-09-14",
"groupby": [
"statDate",
"taskId",
"subTaskId"
],
"filtering": {
"taskIds": [
"101153900"
],
"subTaskIds": [
"1437676090851860480"
]
}
}
响应示例
{
"code": 20770001,
"msg": "",
"total": 1,
"datas": [{
"statDate": "2021-09-14",
"taskId": 101153900,
"subTaskId": "1437676090851860480",
"cost": 180,
"show": 0,
"exposure": 120,
"click": 50,
"clickRate": 0.42,
"download": 31,
"downloadRate": 0.26,
"downloadAverageCost": 5.8,
"conversions": [
{
"conversionBehaviorId": "123",
"conversionCount": 6,
"conversionRate": 0.3,
"conversionAvgPrice": 6.6
}
]
}]
}
调用示例
Curl
curl -X POST https://connect-api.cloud.huawei.com/api/marketing-api/v1/report/ad/subtask -H "Authorization:Bearer ***" -H "client_id:***" -H "Content-type: application/json"-d '{"startDate":"2021-04-06","endDate":"2021-04-20"}'
该实现方案是目前最流行的实现方案,目前阿里,腾讯,百度都使用该方案来作为API的对接方案。
如何安装运行
com.heytap.ads.omni
omni-api-sdk
1.0.2
OPPO Omni API SDK
如何使用
SDK数组参数调用的方法名与API接口一一对应,如v3/ad/get接口就对应OmniAds.getInstance().ads().v3AdGet()方法。
/**
* 根据配置类型获取配置项
*/
public class V3CommunalConfigGetList {
//定义omniAds
public OmniAds omniAds;
//注意:owner_id是Long类型,传入的参数结尾要加“L”
private final static Long OWNER_ID = 分配到的owner_id;
//API授权接入方唯一身份标识;
private final static String API_ID = 分配的apiId;
//开通API授权后获得的私钥,在开通授权邮件中会与app_id一块提供;
private final static String API_KEY = 分配的apiKey;
//重要提示:返回类型暂定ResultDto
缺点:通过SDK接入看起来简单,但是如果处理不好,就会引起不可遇见的依赖冲突问题,有时甚至需要修改SDK中的源码来适配当前工程,得不偿失。例如我引入这个“omni-api-sdk”依赖之后,它给我引入了很多乱七八糟的依赖包进来,如下所示:
+- com.heytap.ads.omni:omni-api-sdk:jar:1.0.2:compile
| +- com.squareup.okhttp:okhttp:jar:2.7.5:compile
| +- io.gsonfire:gson-fire:jar:1.8.0:compile
| +- com.google.inject:guice:jar:4.0:compile
| | +- javax.inject:javax.inject:jar:1:compile
| | - aopalliance:aopalliance:jar:1.0:compile
| +- org.threeten:threetenbp:jar:1.3.5:compile
| +- com.squareup.okhttp:logging-interceptor:jar:2.7.5:compile
| +- org.hibernate.validator:hibernate-validator:jar:6.2.3.Final:compile
| | +- jakarta.validation:jakarta.validation-api:jar:2.0.2:compile
| | +- org.jboss.logging:jboss-logging:jar:3.4.3.Final:compile
| | - com.fasterxml:classmate:jar:1.5.1:compile
| +- com.github.fge:json-schema-validator:jar:2.2.3:compile
| | +- com.github.fge:json-schema-core:jar:1.2.1:compile
| | | +- com.github.fge:uri-template:jar:0.9:compile
| | | | - com.github.fge:msg-simple:jar:1.1:compile
| | | | - com.github.fge:btf:jar:1.2:compile
| | | +- com.github.fge:jackson-coreutils:jar:1.6:compile
| | | - org.mozilla:rhino:jar:1.7R4:compile
| | +- com.googlecode.libphonenumber:libphonenumber:jar:6.0:compile
| | +- javax.mail:mailapi:jar:1.4.3:compile
| | | - javax.activation:activation:jar:1.1:compile
| | +- com.google.code.findbugs:jsr305:jar:2.0.1:compile
| | - net.sf.jopt-simple:jopt-simple:jar:4.6:compile
| +- org.apache.tomcat.embed:tomcat-embed-core:jar:9.0.62:compile
| | - org.apache.tomcat:tomcat-annotations-api:jar:9.0.62:compile
| +- com.alibaba:dubbo:jar:2.5.3:compile
| | +- org.springframework:spring:jar:2.5.6.SEC03:compile
| | - org.jboss.netty:netty:jar:3.2.5.Final:compile
| +- cn.hutool:hutool-all:jar:4.0.2:compile
| +- io.swagger:swagger-annotations:jar:1.5.20:compile
| - com.baomidou:mybatis-plus-annotation:jar:3.5.1:compile
这样导致我的项目出现了jar包冲突的问题,我就不得不去查找到底是那个jar引起的冲突,然后再去一个一个的排除,排除配置如下:
com.heytap.ads.omni
omni-api-sdk
1.0.2
org.springframework
spring
com.alibaba
dubbo
org.apache.tomcat.embed
tomcat-embed-core
io.swagger
swagger-annotations
com.baomidou
mybatis-plus-annotation
个人总结:SDK的实现如果实现得好,可以大大节省我们的对接时间,同时SDK设计时需要注意对那个与对接功能不相关的代码,需要从SDK中剔除出去,不相关的依赖不要引进了,以免导致各种冲突的问题。
vivo MarketingAPI采用OAuth2.0进行授权认证,目前支持授权码模式(authorization code).在您开始使用MarketingAPI推广前,您需要引导客户至少完成一次OAuth2.0认证操作,以获得调用接口必须的access_token。进行OAuth2.0认证需要完成以下步骤:
1、 引导客户进入OAuth2.0授权页面;
授权页面的地址为 https://open-ad.vivo.com.cn/OAuth?clientId={您的client_id}&state={开发者标识}&redirectUri={您的redirectUri}
注意: redirectUri(回调地址)域名需与申请应用时填写的redirectUri域名一致;state必填(内容不限)例如:授权的营销平台账户名称或账户ID。
2、 客户登录营销平台广告主账号或二代账号;
3、客户登录并确认授权后,vivo商业开放平台向您的应用程序返回一个授权码(Authorization Code),code的有效期是10分钟;
注意:广告主或二代点击同意授权后,vivo商业开放平台会请求redirectUri地址,并携带 state参数和 code参数。
4、应用程序调用接口用授权码(Authorization Code)获得 access_token,同时获得一个用于刷新 access_token 的 refresh_token;
5、在 access_token 过期后,使用 refresh_token 获得新的 access_token(可选);
OkHttpClient client = new OkHttpClient().newBuilder()
.build();
MediaType mediaType = MediaType.parse("application/json");
RequestBody body = RequestBody.create(mediaType, "{"startDate":"20200601","endDate":"20200801","pageIndex":1,"pageSize":100,"summaryType":"SUMMARY","level":"CREATIVE"}");
Request request = new Request.Builder()
.url("https://marketing-api.vivo.com.cn/openapi/v1/adstatement/summary/query?access_token=202c6e7b154ff55da04b20c7c316cf5f33e12642a3f1abee9c82ec4749d3fa73×tamp=1598359942000&nonce=1598359942&advertiser_id=6a556980efd4b57e6c8c")
.method("POST", body)
.addHeader("Content-Type", "application/json")
.build();
Response response = client.newCall(request).execute();
该方案适用于客户端的对接实现,但是针对服务器的对接,个人觉得不合适。
缺点:
1)首次获取token必须要人工介入,通过用户登录系统点击授权,才能获取到授权码,再用授权码去换取token,这种方式虽然安全,但是中途需要人工介入。
2)再次获取token,针对服务器自动对接无需人工介入的情况,我们需要持久化refresh_token,定时去刷新token防止token过期。所以总得来说,授权码模式不太适用了服务器API对接,不但实现起来麻烦,安全性也由于refresh_token的存在而大打折扣。
api.e.mi.com + <接口路径> + <接口入参> + signId + sign
sign = MD5(paramStr)
parmStr = sort_by_key 【 接口入参(key1value1key2value2) + ( signId_key + signId_value ) 】 + secretKey_value
sort_by_key 参数按照英文字母升序排序,signId 需要加入排序。
某客户A(账户ID:321)开通OpenAPI权限并绑定邮箱,获取密钥后系统发放的邮件内容为:
signId: 12345678
secretKey: 00000000
获取A客户2018年8月5号通过viewSum升序排列的计划列表请求应该为:
http://api.e.mi.com/campaign/list?customerId=321&edate=2018-08-05&orderby=viewSum&sdate=2018-08-05&signId=12345678&sortMode=1&sign=8054b81bdb0454a99846e04f34bf0de5 |
POST接口参与生成sign的只有url中的参数,requestBody 中参数不参与生成签名.
编辑A客户的创意(创意ID:67812)修改 RTA Token的POST请求应该为:
http://api.e.mi.com/campaign/list?customerId=321&creativeId=67812&signId=12345678&sign=aeb8db9ea50a30f55b8f0fd1cb9f7d4b
小米的实现方案是通过申请到的signId 和 secretKey对请求参数进行MD5加密,然后在服务器验签,确保请求的合法,这也是比较多公司喜欢用的一种实现方案。
缺点:
虽然在方案上无可挑剔,但是这个sign怎么计算出来的呢?缺少代码实现,这种通用的sign计算方法如果可以将实现代码贴出来给我们参考,那么可以大大节省我们每个对接公司的时间。
针对以上四大厂商的对接方案,你们更喜欢那个对接方案呢?认为那个对接方案更加优秀呢?欢迎发表一下个人见解。
页面更新:2024-02-25
本站资料均由网友自行发布提供,仅用于学习交流。如有版权问题,请与我联系,QQ:4156828
© CopyRight 2020-2024 All Rights Reserved. Powered By 71396.com 闽ICP备11008920号-4
闽公网安备35020302034903号