全部产品
存储与CDN 数据库 安全 应用服务 数加·人工智能 数加·大数据基础服务 互联网中间件 视频服务 开发者工具 解决方案 物联网
推荐引擎

API说明 V3.0

更新时间:2017-11-21 11:32:48

API V3.0

API V3.0接口适用于推荐引擎新版控制台,如果使用旧版控制台,请参考API说明 V2.0

参数说明

API请求Host

​ 公网地址:https://dtplus-cn-shanghai.data.aliyuncs.com

​ 私网地址:https://dtplus-lan-cn-shanghai.data.aliyuncs.com

dplus_org_code:数加分配给用户的组织Code

注意:使用算法任务API 数据预处理任务API 效果计算任务API 这三个方法时, 需要增加 header:x-dataplus-timeout=60000

* 请参见数加鉴权规范

1、推荐API

接口说明:获取在线推荐结果

API用户授权类型:数加API鉴权

请参见 数加鉴权规范

地址:${host}/${dplus_org_code}/re/doRec

method: GET

query参数:

参数 类型 是否必填 实例 默认值 描述
bizCode string “biz” null 业务code
scnCode string “scn” null 场景code
userId string “u1” null 用户id
itemId string “i1” null 物品id
category string “16” null 物品所属类目:表示限制推荐的物品均属于此传入类目
class string “热点,阿里云,推荐” null 物品分类筛选:多个分类间用逗号分隔,表示限制推荐的物品需要满足所有传入的分类属性
recnum int 10 10 一次请求最多获取多少条推荐结果,默认为10
start int 0 0 从第几条结果开始取,默认为0

输入样例(不包括数加身份验证的headers,下同):

  1. curl -X GET "${host}/${dplus_org_code}/re/doRec?bizCode=b1&scnCode=s1&userId=123"

返回结果:

参数 类型 实例 描述
trace_id string “277f255555a1e4ff124bdacc528b815d” 系统自动分配的唯一标识单次推荐请求的Id
rec JSONArray {} 推荐列表,已排序
abtag string “p1” ABtest标签,即在线流程Code

返回示例:

  1. {
  2. "code":"SUCCESS",
  3. "data":{
  4. "trace_id":"t1",
  5. "rec":[["i1","0.9"],["i2","0.8"]],
  6. "abtag":"p1"
  7. }
  8. "message":null
  9. }

2、数据预处理任务API

接口说明:启动数据预处理任务

API用户授权类型: 数加API鉴权

请参见 数加鉴权规范

地址:${host}/${dplus_org_code}/re/etl

method: POST

body参数:

参数 类型 是否必填 实例 默认值 描述
bizCode string “biz” null 业务code
ds string “20150101” null 业务时间,格式yyyymmdd

输入样例:

  1. curl -X POST -d "{'bizCode':'b1','ds':'20160101'}" "${host}/${dplus_org_code}/re/etl"

返回结果:

参数 类型 实例 描述
taskId number 123 系统自动分配,可用于轮询任务状态

返回示例:

  1. {
  2. "code":"SUCCESS",
  3. "data":{
  4. "taskId":123
  5. }
  6. "message":null
  7. }

3、离线算法任务API

接口说明:启动指定biz(业务)或者scn(场景)下所有”线上环境“中已配置的算法流程。当存在多个已配置的算法流程时,每个算法流程启动的离线算法任务对应一个taskId,返回结果中的taskIds中会包含多个taskId。

API用户授权类型: 数加API鉴权

请参见 数加鉴权规范

地址:${host}/${dplus_org_code}/re/tasks

method: POST

body参数:

参数 类型 是否必填 实例 默认值 描述
ds string “20150101” null 业务时间,格式yyyymmdd
bizCode string “biz” null 业务code
scnCode string “scn” null 场景code,不传入表示启动bizCode下所有场景的离线算法任务
containImport boolean true true 是否启动算法任务的之前先启动数据预处理

输入样例:

  1. curl -X POST -d "{'bizCode':'b1','ds':'20160101'}" "${host}/${dplus_org_code}/re/tasks"

返回结果:

参数 类型 实例 描述
taskIds object [1,3,4] 返回taskId列表,可用于轮询任务状态

返回示例:

  1. {
  2. "code":"SUCCESS",
  3. "data":{
  4. "taskIds":[1,2,3]
  5. }
  6. "message":null
  7. }

错误码:

  1. HTTP标准错误码

4、效果计算任务API

接口说明:启动指定biz(业务)下的效果计算

API用户授权类型: 数加API鉴权

请参见 数加鉴权规范

地址:${host}/${dplus_org_code}/re/index

method: POST

body参数:

参数 类型 是否必填 实例 默认值 描述
bizCode string “biz” null 业务code
ds string “20150101” null 业务时间,格式yyyymmdd

输入样例:

  1. curl -X POST -d "{'bizCode':'b1','ds':'20160101'}" "${host}/${dplus_org_code}/re/index"

返回结果:

参数 类型 实例 描述
taskId number 123 系统自动分配,可用于轮询任务状态

返回示例:

  1. {
  2. "code":"SUCCESS",
  3. "data":{
  4. "taskId":1
  5. }
  6. "message":null
  7. }

5、查询任务状态API

接口说明:查询离线任务的运行状态

API用户授权类型:数加API鉴权

请参见 数加鉴权规范

地址:${host}/${dplus_org_code}/re/status

method: GET

query参数:

参数 类型 是否必填 实例 默认值 描述
taskId string 按taskId查询时必填 “123” null 作业id
bizCode string 按bizCode查询时必填 “biz” null 业务code
ds string 按bizCode查询时必填 “20150101” null 业务时间,格式yyyymmdd
scnCode string “scn” null 场景code
taskType int 1 null 作业类型 0:线上生产算法流程 1: 数据预处理 2:效果流程 3:测试算法流程

输入样例:

按taskId查询

  1. curl -X GET "${host}/${dplus_org_code}/re/status?taskId=123"

返回结果:

参数 类型 实例 描述
taskStatus string “SUCCESS” 三种状态 “SUCCESS”:成功,“FAILURE”:失败,“RUNNING”:正在运行

返回示例:

  1. {
  2. "code":"SUCCESS",
  3. "data":{
  4. "taskStatus":"RUNNING"
  5. }
  6. "message":null
  7. }

按bizCode查询

需要传入bizCode和ds,选填scnCode和taskType做条件筛选,表示按ds查询bizCode下的任务Id及状态。

  1. curl -X GET "${host}/${dplus_org_code}/re/status?bizCode=xxx&ds=20160315"

返回结果:

参数 类型 实例 描述
taskStatus array [{taskId:1,taskStatus:”SUCCESS”}] 三种状态 “SUCCESS”:成功,“FAILURE”:失败,“RUNNING”:正在运行

返回示例:

  1. {
  2. "code":"SUCCESS",
  3. "data":[{
  4. taskId:1,
  5. taskStatus:"SUCCESS"
  6. }],
  7. "message":null
  8. }

6、日志API

接口说明:

实时日志上传,需要使用GZIP对数据进行压缩成字节数组后进行上传。行为日志的规范请参见 日志埋点规范

Token获取方式:进入产品控制台 => 选中一个业务 => 左侧导航栏选中“线上” => 右侧导航栏选中“API调试” => “选择API接口”下拉框选择“日志API” => 下方的“请求地址”框内查看。

本接口调用方法请参考下文中的代码样例。

如您使用日志API,在新建或编辑已有业务时,必须在“配置业务数据”部分,勾选“使用日志API上传日志”。勾选了使用日志API后,推荐引擎将不再需要您自行ETL上传行为表数据到MaxCompute(原ODPS)中。如同时存在离线上传和日志API上传两种方式,推荐引擎将在数据预处理环节对数据进行合并。

地址:

  1. ${host}/${dplus_org_code}/re/uploadlog?businessName=recommend&customerName=${customerName}&token=${token}

Method: POST

URL参数:

参数 类型 是否必填 实例 默认值 描述
businessName string “recommend” 没有默认值 日志服务的业务名,推荐引擎固定为”recommend”
customerName string “log_test” 没有默认值 客户在推荐引擎中的业务code
token string “xxxx” 没有默认值 推荐引擎分配给客户的日志token

注意: 这三个参数必须拼接在URL后面

Body数据:

  • Body数据是使用GZIP对多条行为日志组成的JSONArray字符串压缩后的字节数组。
  • JSONAarry字符串:里面是多条日志,建议积累一段时间上传(要么隔一分钟上传一次,要么一次累计约2000~3000条上传)。一次数据限制在5M内(压缩前),必须进行GZIP压缩,并需要设置POST请求头的Content-Encoding为gzip。
  • JSONArray每个元素是一条行为日志, 每一条是必须是字符串类型(如果是JSONObject类型则需要序列化为字符串,如JSON.stringify),日志规范参见 日志埋点规范中的[行为类]。

注意

  • 调用API的时候需要加上HASH签名进行鉴权,参见:https://help.aliyun.com/document_detail/30245.html

  • POST请求头的Content-Encoding需要设置为gzip,否则服务器会拒收。

  • 上传的时候需要积累一定量再进行上传,要么累计一分钟,要么累计2000-3000条。

JAVA样例:

  1. import java.io.BufferedReader;
  2. import java.io.ByteArrayOutputStream;
  3. import java.io.DataOutputStream;
  4. import java.io.IOException;
  5. import java.io.InputStreamReader;
  6. import java.net.MalformedURLException;
  7. import java.net.URL;
  8. import java.security.MessageDigest;
  9. import java.text.SimpleDateFormat;
  10. import java.util.Date;
  11. import java.util.LinkedList;
  12. import java.util.List;
  13. import java.util.Locale;
  14. import java.util.zip.GZIPOutputStream;
  15. import javax.crypto.Mac;
  16. import javax.crypto.spec.SecretKeySpec;
  17. import javax.net.ssl.HttpsURLConnection;
  18. import org.json.JSONArray;
  19. import org.json.JSONObject;
  20. import sun.misc.BASE64Encoder;
  21. public class UploadLogExample {
  22. // 用户需要修改
  23. private static String biz_code = "${biz_code}";
  24. private static String token = "${token}";
  25. private static String url_prefix = "${host}/${dplus_org_code}/re/uploadlog?businessName=recommend";
  26. // 用户需要修改, 用户的access_key_id与access_key_secret
  27. private static String access_key_id = "";
  28. private static String access_key_secret = "";
  29. public static void main(String[] args) throws IOException {
  30. // 用户的logs数组,要求每条日志必须是字符串类型
  31. List<String> logs = new LinkedList<String>();
  32. // 用户添加日志,要么积累一分钟的量, 要么积累到2000~3000条
  33. logs.add("{\"user_id\":\"0\", \"item_id\":0, \"action\":\"view\",\"bhv_datetime\": \"2016-05-26 00:00:00\"}");
  34. if (logs == null || logs.size() == 0) {
  35. return;
  36. }
  37. // 积累的多条日志JSONArray数组
  38. JSONArray content = new JSONArray();
  39. // 用户向content中填写多条日志(要么积累一分钟的量, 要么积累到2000~3000条)
  40. for (String log : logs) {
  41. content.put(log);
  42. }
  43. // 上传日志
  44. sendPostHTTPS(content, access_key_id, access_key_secret);
  45. }
  46. /**
  47. * 使用HTTPS对多条日志进行GZIP压缩并上传
  48. *
  49. * @param content 日志JSONArray数组(要么积累一分钟的量, 要么积累到2000~3000条)
  50. * @param ak_id
  51. * @param ak_secret
  52. * @throws IOException
  53. */
  54. public static void sendPostHTTPS(JSONArray content, String ak_id, String ak_secret) throws IOException {
  55. if (content != null && content.length() > 0) {
  56. HttpsURLConnection conn = null;
  57. try {
  58. BufferedReader in = null;
  59. URL upload_url = new URL(url_prefix + "&customerName=" + biz_code + "&token=" + token);
  60. StringBuilder result = new StringBuilder();
  61. /*
  62. * http header 参数 必须设置
  63. */
  64. String method = "POST";
  65. String accept = "application/json";
  66. String content_type = "application/json";
  67. String path = upload_url.getFile();
  68. String date = toGMTString(new Date());
  69. String content_encoding = "gzip";
  70. // 1. 对日志JSONArray进行FGZIP压缩
  71. byte[] body = compressToByte(content);
  72. // 2. 对body做MD5+BASE64加密
  73. String body_md5 = MD5Base64(body);
  74. String string_to_sign = method + "\n" + accept + "\n" + body_md5 + "\n" + content_type + "\n" + date + "\n" + path;
  75. // 3.计算 HMAC-SHA1
  76. String signature = HMACSha1(string_to_sign, ak_secret);
  77. // 4.得到 authorization header
  78. String auth_header = "Dataplus " + ak_id + ":" + signature;
  79. // 发起连接
  80. conn = (HttpsURLConnection) upload_url.openConnection();
  81. // 设置超时, 建议1分钟, 可以更大一点
  82. conn.setConnectTimeout(60000);
  83. conn.setReadTimeout(60000);
  84. // 设置请求方法
  85. conn.setRequestMethod("POST");
  86. // 设置通用的请求属性
  87. conn.setRequestProperty("accept", accept);
  88. conn.setRequestProperty("content-type", content_type);
  89. conn.setRequestProperty("date", date);
  90. conn.setRequestProperty("Authorization", auth_header);
  91. // 必须要设置为GZIP,否则服务器会不接受
  92. conn.setRequestProperty("Content-Encoding", content_encoding);
  93. // 发送POST请求必须设置如下两行
  94. conn.setDoOutput(true);
  95. conn.setDoInput(true);
  96. // 设置是非缓存
  97. conn.setUseCaches(false);
  98. // 传输body流 必须GZIP加密后字节数组
  99. DataOutputStream data_stream = new DataOutputStream(conn.getOutputStream());
  100. data_stream.write(body);
  101. data_stream.flush();
  102. data_stream.close();
  103. if (conn.getResponseCode() != 200) {
  104. System.err.println("日志API连接失败!");
  105. } else {
  106. // 返回jsonobject
  107. in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
  108. String line = null;
  109. while ((line = in.readLine()) != null) {
  110. result.append(line);
  111. }
  112. if (result.length() > 0) {
  113. JSONObject rsp_json = new JSONObject(result.toString());
  114. int success = rsp_json.getInt("success");
  115. if (success == 1) {
  116. System.out.println("数据上传成功");
  117. } else {
  118. System.out.println("数据上传失败, 出错信息: " + rsp_json.getString("errMsg"));
  119. }
  120. }
  121. }
  122. } catch (MalformedURLException e) {
  123. e.printStackTrace();
  124. } catch (IOException e) {
  125. e.printStackTrace();
  126. } finally {
  127. if (conn != null) {
  128. conn.disconnect();
  129. }
  130. }
  131. }
  132. }
  133. /*
  134. * 计算MD5+BASE64
  135. */
  136. public static String MD5Base64(byte[] utfBytes) {
  137. if (utfBytes == null)
  138. return null;
  139. String encodeStr = "";
  140. MessageDigest mdTemp;
  141. try {
  142. mdTemp = MessageDigest.getInstance("MD5");
  143. mdTemp.update(utfBytes);
  144. byte[] md5Bytes = mdTemp.digest();
  145. BASE64Encoder b64Encoder = new BASE64Encoder();
  146. encodeStr = b64Encoder.encode(md5Bytes);
  147. } catch (Exception e) {
  148. throw new Error("Failed to generate MD5 : " + e.getMessage());
  149. }
  150. return encodeStr;
  151. }
  152. /*
  153. * 计算 HMAC-SHA1
  154. */
  155. public static String HMACSha1(String data, String key) {
  156. String result;
  157. try {
  158. SecretKeySpec signingKey = new SecretKeySpec(key.getBytes(), "HmacSHA1");
  159. Mac mac = Mac.getInstance("HmacSHA1");
  160. mac.init(signingKey);
  161. byte[] rawHmac = mac.doFinal(data.getBytes());
  162. result = (new BASE64Encoder()).encode(rawHmac);
  163. } catch (Exception e) {
  164. throw new Error("Failed to generate HMAC : " + e.getMessage());
  165. }
  166. return result;
  167. }
  168. /*
  169. * 等同于javaScript中的 new Date().toUTCString();
  170. */
  171. public static String toGMTString(Date date) {
  172. SimpleDateFormat df = new SimpleDateFormat("E, dd MMM yyyy HH:mm:ss z", Locale.UK);
  173. df.setTimeZone(new java.util.SimpleTimeZone(0, "GMT"));
  174. return df.format(date);
  175. }
  176. /*
  177. * 字符串压缩为字节数组
  178. */
  179. public static byte[] compressToByte(JSONArray content) {
  180. try {
  181. int len1 = content.toString().getBytes("utf-8").length;
  182. System.out.println("压缩前数据大小(B): " + len1);
  183. ByteArrayOutputStream out = new ByteArrayOutputStream();
  184. GZIPOutputStream gzip = new GZIPOutputStream(out);
  185. gzip.write(content.toString().getBytes("utf-8"));
  186. gzip.finish();
  187. gzip.flush();
  188. gzip.close();
  189. byte[] data = out.toByteArray();
  190. int len2 = data.length;
  191. System.out.println("压缩后数据大小(B): " + len2);
  192. System.out.println("压缩率: " + len2 * 1.0 / len1);
  193. return data;
  194. } catch (Exception e) {
  195. e.printStackTrace();
  196. return null;
  197. }
  198. }
  199. }

NodeJS样例

  1. var request = require('request');
  2. var url = require('url');
  3. var crypto = require('crypto');
  4. var zlib = require('zlib');
  5. // 参数, 客户需要自己填写
  6. var url_prefix = "${host}/${dplus_org_code}/re/uploadlog?businessName=recommend";
  7. var biz_code = "bizCode";
  8. var token = "token";
  9. var access_key_id = 'accessId';
  10. var access_key_secret = 'accessKey';
  11. /**
  12. 注意事项:
  13. 首先, 需要注意,每条日志必须是String格式,如果是JSONObject则需要预先JSON.stringify转为字符串
  14. 然后, 将每条日志put到JSONArray中, 需要积累一段时间(如一分钟)或者一定量的日志再上传(2000~3000条)
  15. 接着, 将JSONArray转换为String, 并使用gzip进行压缩, 将压缩后的数据作为body上传
  16. 最后, 使用数加鉴权中的相关字段进行签名
  17. 其中, 请求头中的Content-Encoding不参与签名,但是必须设置为gzip
  18. **/
  19. var log = '{"user_id":"xxx","item_id":0,"action":"view","bhv_datetime":"2016-05-26 00:00:00"}';
  20. // 多条日志put到JSONArray中, 这里造10条数据
  21. var logs = [];
  22. for(var i = 0; i < 10; ++i) {
  23. var content = typeof(log) === 'object' ? JSON.stringify(log) : log.toString();
  24. logs.push(content);
  25. }
  26. // JSONArray 转换成String
  27. logs = JSON.stringify(logs);
  28. // send post函数
  29. sendPostHttps = function(logs, ak_id, ak_key) {
  30. var log_upload_url = url_prefix + '&customerName=' + biz_code + '&token=' + token;
  31. var path = url.parse(log_upload_url).path;
  32. // 请求选项, 这些字段必须填写
  33. var options = {
  34. url: log_upload_url,
  35. method: "POST",
  36. body: '',
  37. headers: {
  38. 'accept': "application/json",
  39. 'content-type': "application/json",
  40. 'Content-Encoding': "gzip", // 上传的数据是gzip压缩的, 不参与签名
  41. 'date': new Date().toUTCString(),
  42. 'Authorization': ''
  43. }
  44. };
  45. // step 1 使用gzip进行压缩
  46. zlib.gzip(logs, function(err, buffer) {
  47. if (!err) {
  48. // 使用压缩后的数据填充请求body
  49. options.body = buffer;
  50. console.log("step1 Gzip body", buffer);
  51. // step2: 组stringToSign [StringToSign = #{method}\\n#{accept}\\n#{md5(body)}\\n#{contentType}\\n#{date}\\n#{action}]
  52. var bodymd5 = md5(buffer);
  53. var string_to_sign = options.method + "\n" + options.headers.accept + "\n" + bodymd5 + "\n" + options.headers['content-type'] + "\n" + options.headers.date + "\n" + path;
  54. console.log("step2 Sign string:", string_to_sign);
  55. // step3: 加密 [Signature = Base64( HMAC-SHA1( AccessSecret, UTF-8-Encoding-Of(StringToSign)))]
  56. var signature = sha1(string_to_sign, ak_key);
  57. console.log("step3 Signature:", signature);
  58. // step4: 组authorization header [Authorization = Dataplus AccessKeyId + ":" + Signature]
  59. var auth_header = "Dataplus " + ak_id + ":" + signature;
  60. console.log("step4 Authorization Header:", auth_header);
  61. options.headers.Authorization = auth_header;
  62. // step5: send request
  63. request(options, callback);
  64. }
  65. });
  66. };
  67. callback = function(error, response, body) {
  68. if (error) {
  69. console.log("error", error);
  70. } else {
  71. console.log("step5 response body:", response.statusCode, body);
  72. }
  73. }
  74. // 计算MD5+BASE64
  75. md5 = function(buffer) {
  76. var hash = crypto.createHash('md5');
  77. hash.update(buffer);
  78. return hash.digest('base64');
  79. };
  80. // 计算 HMAC-SHA1
  81. sha1 = function(string_to_sign, secret) {
  82. var signature;
  83. return signature = crypto.createHmac('sha1', secret).update(string_to_sign).digest().toString('base64');
  84. };
  85. // 最后调用函数发送请求
  86. sendPostHttps(logs, access_key_id, access_key_secret);

PHP样例:

  1. <?php
  2. function unparse_url($parsed_url) {
  3. $scheme = isset($parsed_url['scheme']) ? $parsed_url['scheme'] . '://' : '';
  4. $host = isset($parsed_url['host']) ? $parsed_url['host'] : '';
  5. $port = isset($parsed_url['port']) ? ':' . $parsed_url['port'] : '';
  6. $user = isset($parsed_url['user']) ? $parsed_url['user'] : '';
  7. $pass = isset($parsed_url['pass']) ? ':' . $parsed_url['pass'] : '';
  8. $pass = ($user || $pass) ? "$pass@" : '';
  9. $path = isset($parsed_url['path']) ? $parsed_url['path'] : '';
  10. $query = isset($parsed_url['query']) ? '?' . $parsed_url['query'] : '';
  11. $fragment = isset($parsed_url['fragment']) ? '#' . $parsed_url['fragment'] : '';
  12. return "$scheme$user$pass$host$port$path$query$fragment";
  13. }
  14. function callDplus($opt, $accessId, $accessSecret) {
  15. $header = array(
  16. 'Accept'=> "application/json",
  17. 'Content-Type' => "application/json",
  18. 'Content-Encoding' => "gzip",
  19. 'Date' => gmdate("D, d M Y H:i:s \G\M\T"),
  20. 'Authorization' => '',
  21. );
  22. $url = parse_url($opt['url']);
  23. parse_str($url['query'], $query);
  24. if ($opt['query']) {
  25. $query = array_merge($query, $opt['query']);
  26. }
  27. $url['query'] = http_build_query($query);
  28. $body = gzencode(json_encode($opt['data']));
  29. if (empty($body)) {
  30. $bodymd5 = $body;
  31. } else {
  32. $bodymd5 = base64_encode(md5($body, true));
  33. }
  34. $path = $url['path'];
  35. if (!empty($query)) {
  36. $path = $path . '?' . $url['query'];
  37. }
  38. $stringToSign = $opt['method'] . "\n" . $header['Accept'] . "\n" . $bodymd5 . "\n". $header['Content-Type'] . "\n" . $header['Date'] . "\n" . $path;
  39. $signature = base64_encode(hash_hmac("sha1", $stringToSign, $accessSecret, true));
  40. $header['Authorization'] = "Dataplus "."$accessId".":"."$signature";
  41. $header = array_map(
  42. function($key, $val){
  43. return $key.":".$val;
  44. },
  45. array_keys($header),
  46. $header
  47. );
  48. $curl_opt = array(
  49. CURLOPT_URL => unparse_url($url),
  50. CURLOPT_RETURNTRANSFER => 1,
  51. CURLOPT_HTTPHEADER => $header
  52. );
  53. if ($opt['method'] == 'POST') {
  54. $curl_opt[CURLOPT_POST] = true;
  55. $curl_opt[CURLOPT_POSTFIELDS] = $body;
  56. } else {
  57. $curl_opt[CURLOPT_HTTPGET] = true;
  58. }
  59. $request = curl_init();
  60. curl_setopt_array($request, $curl_opt);
  61. $res = curl_exec($request);
  62. curl_close($request);
  63. return $res;
  64. }
  65. /**
  66. * ====================================
  67. * config here
  68. * ====================================
  69. */
  70. // 公网请求地址
  71. $dplusHost = "https://dtplus-cn-shanghai.data.aliyuncs.com";
  72. // 私网请求地址
  73. // $dplusHost = "https://dtplus-lan-cn-shanghai.data.aliyuncs.com";
  74. $dplusOrgCode = '';
  75. $bizCode = '';
  76. $token = '';
  77. $accessId = "";
  78. $accessSecret = "";
  79. /**
  80. * ====================================
  81. * config end
  82. * ====================================
  83. */
  84. $api="${dplusHost}/${dplusOrgCode}/re/uploadlog?businessName=recommend&customerName=${bizCode}&token=${token}";
  85. /**
  86. * prepare log
  87. */
  88. $logs = array(
  89. json_encode(array("action" => "login", "user_id" => "0", "tags" =>"{'age':'1','gender':'1'}")),
  90. json_encode(array("action" => "item", "item_id" => "1", "category" =>"1")),
  91. json_encode(array("action" => "click", "user_id" => "0", "item_id" =>"0")),
  92. );
  93. /**
  94. * upload log
  95. */
  96. $opt = array(
  97. url => $api,
  98. method => 'POST',
  99. /** queryString param */
  100. query => array(
  101. businessName => 'recommend',
  102. customerName => $bizCode,
  103. token => $token
  104. ),
  105. /* post body data */
  106. data => $logs
  107. );
  108. $res = callDplus($opt, $accessId, $accessSecret);
  109. print_r($res);
  110. ?>

返回示例:

  1. {
  2. "success":1,
  3. "errMsg":""
  4. }
本文导读目录