From 3c2249eae8de732af153d03ab0d5197f9643f392 Mon Sep 17 00:00:00 2001 From: Charming Date: Sun, 29 Apr 2018 21:50:11 +0800 Subject: [PATCH] =?UTF-8?q?#565=20=E5=B0=8F=E7=A8=8B=E5=BA=8F=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0=E6=95=B0=E6=8D=AE=E5=88=86=E6=9E=90=E7=9B=B8=E5=85=B3?= =?UTF-8?q?=20API?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 微信开放平台:1. WxOpenInRedisConfigStorage 支持 JedisPool/JedisSentinelPool 等 Pool 的子类;2. WxOpenInRedisConfigStorage 增加 keyPrefix 以支持可配置的前缀; * 微信开放平台:增加小程序代码模板库管理 * 小程序:增加代码管理相关 API * 小程序:增加修改服务器地址、成员管理 API * 小程序:增加数据分析相关 API --- .../wx/miniapp/api/WxMaAnalysisService.java | 145 ++++++++++++++++ .../wx/miniapp/api/WxMaService.java | 7 + .../api/impl/WxMaAnalysisServiceImpl.java | 126 ++++++++++++++ .../wx/miniapp/api/impl/WxMaServiceImpl.java | 7 + .../miniapp/bean/analysis/WxMaRetainInfo.java | 43 +++++ .../bean/analysis/WxMaSummaryTrend.java | 37 +++++ .../bean/analysis/WxMaUserPortrait.java | 68 ++++++++ .../bean/analysis/WxMaVisitDistribution.java | 83 ++++++++++ .../miniapp/bean/analysis/WxMaVisitPage.java | 55 +++++++ .../miniapp/bean/analysis/WxMaVisitTrend.java | 59 +++++++ .../miniapp/bean/analysis/package-info.java | 7 + .../wx/miniapp/util/json/WxMaGsonBuilder.java | 6 + .../util/json/WxMaRetainInfoGsonAdapter.java | 52 ++++++ .../json/WxMaUserPortraitGsonAdapter.java | 67 ++++++++ .../WxMaVisitDistributionGsonAdapter.java | 67 ++++++++ .../api/impl/WxMaAnalysisServiceImplTest.java | 155 ++++++++++++++++++ .../bean/analysis/WxMaRetainInfoTest.java | 22 +++ .../bean/analysis/WxMaUserPortraitTest.java | 19 +++ .../analysis/WxMaVisitDistributionTest.java | 23 +++ 19 files changed, 1048 insertions(+) create mode 100644 weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/WxMaAnalysisService.java create mode 100644 weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaAnalysisServiceImpl.java create mode 100644 weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/analysis/WxMaRetainInfo.java create mode 100644 weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/analysis/WxMaSummaryTrend.java create mode 100644 weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/analysis/WxMaUserPortrait.java create mode 100644 weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/analysis/WxMaVisitDistribution.java create mode 100644 weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/analysis/WxMaVisitPage.java create mode 100644 weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/analysis/WxMaVisitTrend.java create mode 100644 weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/analysis/package-info.java create mode 100644 weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/util/json/WxMaRetainInfoGsonAdapter.java create mode 100644 weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/util/json/WxMaUserPortraitGsonAdapter.java create mode 100644 weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/util/json/WxMaVisitDistributionGsonAdapter.java create mode 100644 weixin-java-miniapp/src/test/java/cn/binarywang/wx/miniapp/api/impl/WxMaAnalysisServiceImplTest.java create mode 100644 weixin-java-miniapp/src/test/java/cn/binarywang/wx/miniapp/bean/analysis/WxMaRetainInfoTest.java create mode 100644 weixin-java-miniapp/src/test/java/cn/binarywang/wx/miniapp/bean/analysis/WxMaUserPortraitTest.java create mode 100644 weixin-java-miniapp/src/test/java/cn/binarywang/wx/miniapp/bean/analysis/WxMaVisitDistributionTest.java diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/WxMaAnalysisService.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/WxMaAnalysisService.java new file mode 100644 index 00000000..bfa038f1 --- /dev/null +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/WxMaAnalysisService.java @@ -0,0 +1,145 @@ +package cn.binarywang.wx.miniapp.api; + +import cn.binarywang.wx.miniapp.bean.analysis.WxMaRetainInfo; +import cn.binarywang.wx.miniapp.bean.analysis.WxMaSummaryTrend; +import cn.binarywang.wx.miniapp.bean.analysis.WxMaUserPortrait; +import cn.binarywang.wx.miniapp.bean.analysis.WxMaVisitDistribution; +import cn.binarywang.wx.miniapp.bean.analysis.WxMaVisitPage; +import cn.binarywang.wx.miniapp.bean.analysis.WxMaVisitTrend; +import me.chanjar.weixin.common.exception.WxErrorException; + +import java.util.Date; +import java.util.List; + +/** + * 小程序数据分析相关接口 + * 文档:https://mp.weixin.qq.com/debug/wxadoc/dev/api/analysis.html + * + * @author Charming + * @since 2018-04-28 + */ +public interface WxMaAnalysisService { + String GET_DAILY_SUMMARY_TREND_URL = "https://api.weixin.qq.com/datacube/getweanalysisappiddailysummarytrend"; + String GET_DAILY_VISIT_TREND_URL = "https://api.weixin.qq.com/datacube/getweanalysisappiddailyvisittrend"; + String GET_WEEKLY_VISIT_TREND_URL = "https://api.weixin.qq.com/datacube/getweanalysisappidweeklyvisittrend"; + String GET_MONTHLY_VISIT_TREND_URL = "https://api.weixin.qq.com/datacube/getweanalysisappidmonthlyvisittrend"; + String GET_VISIT_DISTRIBUTION_URL = "https://api.weixin.qq.com/datacube/getweanalysisappidvisitdistribution"; + String GET_DAILY_RETAIN_INFO_URL = "https://api.weixin.qq.com/datacube/getweanalysisappiddailyretaininfo"; + String GET_WEEKLY_RETAIN_INFO_URL = "https://api.weixin.qq.com/datacube/getweanalysisappidweeklyretaininfo"; + String GET_MONTHLY_RETAIN_INFO_URL = "https://api.weixin.qq.com/datacube/getweanalysisappidmonthlyretaininfo"; + String GET_VISIT_PAGE_URL = "https://api.weixin.qq.com/datacube/getweanalysisappidvisitpage"; + String GET_USER_PORTRAIT_URL = "https://api.weixin.qq.com/datacube/getweanalysisappiduserportrait"; + + /** + * 查询概况趋势 + * 温馨提示:小程序接口目前只能查询一天的数据,即 beginDate 和 endDate 一样 + * + * @param beginDate 开始日期 + * @param endDate 结束日期,限定查询1天数据,end_date允许设置的最大值为昨日 + * @return 概况趋势 + * @throws WxErrorException 获取失败时抛出,具体错误码请看文档 + */ + List getDailySummaryTrend(Date beginDate, Date endDate) throws WxErrorException; + + /** + * 获取日访问趋势 + * 温馨提示:小程序接口目前只能查询一天的数据,即 beginDate 和 endDate 一样 + * + * @param beginDate 开始日期 + * @param endDate 结束日期,限定查询1天数据,end_date允许设置的最大值为昨日 + * @return 日访问趋势 + * @throws WxErrorException 获取失败时抛出,具体错误码请看文档 + */ + List getDailyVisitTrend(Date beginDate, Date endDate) throws WxErrorException; + + /** + * 获取周访问趋势 + * 限定查询一个自然周的数据,时间必须按照自然周的方式输入: 如:20170306(周一), 20170312(周日) + * + * @param beginDate 开始日期,为周一日期 + * @param endDate 结束日期,为周日日期,限定查询一周数据 + * @return 周访问趋势(每项数据都是一个自然周汇总) + * @throws WxErrorException 获取失败时抛出,具体错误码请看文档 + */ + List getWeeklyVisitTrend(Date beginDate, Date endDate) throws WxErrorException; + + /** + * 获取月访问趋势 + * 限定查询一个自然月的数据,时间必须按照自然月的方式输入: 如:20170201(月初), 20170228(月末) + * + * @param beginDate 开始日期,为自然月第一天 + * @param endDate 结束日期,为自然月最后一天,限定查询一个月数据 + * @return 月访问趋势(每项数据都是一个自然月汇总) + * @throws WxErrorException 获取失败时抛出,具体错误码请看文档 + */ + List getMonthlyVisitTrend(Date beginDate, Date endDate) throws WxErrorException; + + /** + * 获取访问分布 + * (此接口目前只能查询一天的数据,即 beginDate 和 endDate 一样) + * + * @param beginDate 开始日期,为周一日期 + * @param endDate 结束日期,限定查询1天数据,end_date允许设置的最大值为昨日 + * @return 访问分布 + * @throws WxErrorException 获取失败时抛出,具体错误码请看文档 + */ + WxMaVisitDistribution getVisitDistribution(Date beginDate, Date endDate) throws WxErrorException; + + /** + * 日留存 + * (此接口目前只能查询一天的数据,即 beginDate 和 endDate 一样) + * + * @param beginDate 开始日期,为周一日期 + * @param endDate 结束日期,限定查询 1 天数据,endDate 允许设置的最大值为昨日 + * @return 日留存 + * @throws WxErrorException 获取失败时抛出,具体错误码请看文档 + */ + WxMaRetainInfo getDailyRetainInfo(Date beginDate, Date endDate) throws WxErrorException; + + /** + * 周留存 + * 限定查询一个自然周的数据,时间必须按照自然周的方式输入: 如:20170306(周一), 20170312(周日) + * + * @param beginDate 开始日期,为周一日期 + * @param endDate 结束日期,为周日日期,限定查询一周数据 + * @return 周留存 + * @throws WxErrorException 获取失败时抛出,具体错误码请看文档 + */ + WxMaRetainInfo getWeeklyRetainInfo(Date beginDate, Date endDate) throws WxErrorException; + + /** + * 月留存 + * 限定查询一个自然月的数据,时间必须按照自然月的方式输入: 如:20170201(月初), 20170228(月末) + * + * @param beginDate 开始日期,为自然月第一天 + * @param endDate 结束日期,为自然月最后一天,限定查询一个月数据 + * @return 月留存 + * @throws WxErrorException 获取失败时抛出,具体错误码请看文档 + */ + WxMaRetainInfo getMonthlyRetainInfo(Date beginDate, Date endDate) throws WxErrorException; + + /** + * 获取访问页面数据 + * 温馨提示:此接口目前只能查询一天的数据,即 beginDate 和 endDate 一样 + * + * @param beginDate 开始日期 + * @param endDate 结束日期,限定查询1天数据,end_date允许设置的最大值为昨日 + * @return 访问页面数据 + * @throws WxErrorException 获取失败时抛出,具体错误码请看文档 + */ + List getVisitPage(Date beginDate, Date endDate) throws WxErrorException; + + /** + * 获取小程序新增或活跃用户的画像分布数据 + * 时间范围支持昨天、最近7天、最近30天。 + * 其中,新增用户数为时间范围内首次访问小程序的去重用户数, + * 活跃用户数为时间范围内访问过小程序的去重用户数。 + * 画像属性包括用户年龄、性别、省份、城市、终端类型、机型。 + * + * @param beginDate 开始日期 + * @param endDate 结束日期,开始日期与结束日期相差的天数限定为0/6/29,分别表示查询最近1/7/30天数据,end_date允许设置的最大值为昨日 + * @return 小程序新增或活跃用户的画像分布数据 + * @throws WxErrorException 获取失败时抛出,具体错误码请看文档 + */ + WxMaUserPortrait getUserPortrait(Date beginDate, Date endDate) throws WxErrorException; +} diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/WxMaService.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/WxMaService.java index 9ba17f2b..cec42242 100644 --- a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/WxMaService.java +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/WxMaService.java @@ -135,6 +135,13 @@ public interface WxMaService { */ WxMaTemplateService getTemplateService(); + /** + * 数据分析相关查询服务 + * + * @return WxMaAnalysisService + */ + WxMaAnalysisService getAnalysisService(); + /** * 返回代码操作相关的 API * diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaAnalysisServiceImpl.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaAnalysisServiceImpl.java new file mode 100644 index 00000000..a9247fc3 --- /dev/null +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaAnalysisServiceImpl.java @@ -0,0 +1,126 @@ +package cn.binarywang.wx.miniapp.api.impl; + +import cn.binarywang.wx.miniapp.api.WxMaAnalysisService; +import cn.binarywang.wx.miniapp.api.WxMaService; +import cn.binarywang.wx.miniapp.bean.analysis.WxMaRetainInfo; +import cn.binarywang.wx.miniapp.bean.analysis.WxMaSummaryTrend; +import cn.binarywang.wx.miniapp.bean.analysis.WxMaUserPortrait; +import cn.binarywang.wx.miniapp.bean.analysis.WxMaVisitDistribution; +import cn.binarywang.wx.miniapp.bean.analysis.WxMaVisitPage; +import cn.binarywang.wx.miniapp.bean.analysis.WxMaVisitTrend; +import cn.binarywang.wx.miniapp.util.json.WxMaGsonBuilder; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import com.google.gson.reflect.TypeToken; +import me.chanjar.weixin.common.exception.WxErrorException; +import org.apache.commons.lang3.time.DateFormatUtils; + +import java.lang.reflect.Type; +import java.util.Date; +import java.util.List; + +/** + * @author Charming + * @since 2018-04-28 + */ +public class WxMaAnalysisServiceImpl implements WxMaAnalysisService { + private static final JsonParser JSON_PARSER = new JsonParser(); + private WxMaService wxMaService; + + public WxMaAnalysisServiceImpl(WxMaService wxMaService) { + this.wxMaService = wxMaService; + } + + @Override + public List getDailySummaryTrend(Date beginDate, Date endDate) throws WxErrorException { + return getAnalysisResultAsList(GET_DAILY_SUMMARY_TREND_URL, beginDate, endDate, + new TypeToken>() { + }.getType()); + } + + @Override + public List getDailyVisitTrend(Date beginDate, Date endDate) throws WxErrorException { + return getAnalysisResultAsList(GET_DAILY_VISIT_TREND_URL, beginDate, endDate, + new TypeToken>() { + }.getType()); + } + + @Override + public List getWeeklyVisitTrend(Date beginDate, Date endDate) throws WxErrorException { + return getAnalysisResultAsList(GET_WEEKLY_VISIT_TREND_URL, beginDate, endDate, + new TypeToken>() { + }.getType()); + } + + @Override + public List getMonthlyVisitTrend(Date beginDate, Date endDate) throws WxErrorException { + return getAnalysisResultAsList(GET_MONTHLY_VISIT_TREND_URL, beginDate, endDate, + new TypeToken>() { + }.getType()); + } + + @Override + public WxMaVisitDistribution getVisitDistribution(Date beginDate, Date endDate) throws WxErrorException { + String responseContent = this.wxMaService.post(GET_VISIT_DISTRIBUTION_URL, toJson(beginDate, endDate)); + return WxMaVisitDistribution.fromJson(responseContent); + } + + @Override + public WxMaRetainInfo getDailyRetainInfo(Date beginDate, Date endDate) throws WxErrorException { + return getRetainInfo(beginDate, endDate, GET_DAILY_RETAIN_INFO_URL); + } + + @Override + public WxMaRetainInfo getWeeklyRetainInfo(Date beginDate, Date endDate) throws WxErrorException { + return getRetainInfo(beginDate, endDate, GET_WEEKLY_RETAIN_INFO_URL); + } + + @Override + public WxMaRetainInfo getMonthlyRetainInfo(Date beginDate, Date endDate) throws WxErrorException { + return getRetainInfo(beginDate, endDate, GET_MONTHLY_RETAIN_INFO_URL); + } + + @Override + public List getVisitPage(Date beginDate, Date endDate) throws WxErrorException { + return getAnalysisResultAsList(GET_VISIT_PAGE_URL, beginDate, endDate, + new TypeToken>() { + }.getType()); + } + + @Override + public WxMaUserPortrait getUserPortrait(Date beginDate, Date endDate) throws WxErrorException { + String responseContent = this.wxMaService.post(GET_USER_PORTRAIT_URL, toJson(beginDate, endDate)); + return WxMaUserPortrait.fromJson(responseContent); + } + + private WxMaRetainInfo getRetainInfo(Date beginDate, Date endDate, String url) throws WxErrorException { + String responseContent = this.wxMaService.post(url, toJson(beginDate, endDate)); + return WxMaRetainInfo.fromJson(responseContent); + } + + /** + * 获取数据分析结果并返回 List,returnType 类型 + * + * @param url 链接 + * @param returnType 返回的类型 + * @param 返回的类型 + * @return List 类型的数据 + */ + private List getAnalysisResultAsList(String url, Date beginDate, Date endDate, Type returnType) throws WxErrorException { + String responseContent = this.wxMaService.post(url, toJson(beginDate, endDate)); + JsonObject response = JSON_PARSER.parse(responseContent).getAsJsonObject(); + boolean hasList = response.has("list"); + if (hasList) { + return WxMaGsonBuilder.create().fromJson(response.getAsJsonArray("list"), returnType); + } else { + return null; + } + } + + private static String toJson(Date beginDate, Date endDate) { + JsonObject param = new JsonObject(); + param.addProperty("begin_date", DateFormatUtils.format(beginDate, "yyyyMMdd")); + param.addProperty("end_date", DateFormatUtils.format(endDate, "yyyyMMdd")); + return param.toString(); + } +} diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaServiceImpl.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaServiceImpl.java index a4d9d515..014ca1c9 100644 --- a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaServiceImpl.java +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaServiceImpl.java @@ -1,5 +1,6 @@ package cn.binarywang.wx.miniapp.api.impl; +import cn.binarywang.wx.miniapp.api.WxMaAnalysisService; import cn.binarywang.wx.miniapp.api.WxMaCodeService; import cn.binarywang.wx.miniapp.api.WxMaMediaService; import cn.binarywang.wx.miniapp.api.WxMaMsgService; @@ -52,6 +53,7 @@ public class WxMaServiceImpl implements WxMaService, RequestHttpCharming + * @since 2018-04-28 14:41 + */ +@Data +public class WxMaRetainInfo implements Serializable { + private static final long serialVersionUID = 8986403173656848413L; + /** + * 日留存:日期,yyyyMMdd 格式,如 20170313 + * 周留存:时间,如"20170306-20170312" + * 月留存:时间,如"201702" + */ + @SerializedName(value = "refDate", alternate = "ref_date") + private String refDate; + /** + * 新增用户留存 + * - key: + * - 日留存:标识,0开始,0表示当天,1表示1天后,依此类推,key取值分别是:0,1,2,3,4,5,6,7,14,30 + * - 周留存:标识,0开始,0表示当周,1表示1周后,依此类推,key 取值分别是:0,1,2,3,4 + * - 月留存:标识,0开始,0表示当月,1表示1月后,key取值分别是:0,1 + * - value: key对应日期的新增用户数/活跃用户数(key=0时)或留存用户数(k>0时) + */ + private Map visitUvNew; + /** + * 活跃用户留存 + */ + private Map visitUv; + + public static WxMaRetainInfo fromJson(String json) { + return WxMaGsonBuilder.create().fromJson(json, WxMaRetainInfo.class); + } +} diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/analysis/WxMaSummaryTrend.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/analysis/WxMaSummaryTrend.java new file mode 100644 index 00000000..f4ceb0ad --- /dev/null +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/analysis/WxMaSummaryTrend.java @@ -0,0 +1,37 @@ +package cn.binarywang.wx.miniapp.bean.analysis; + +import com.google.gson.annotations.SerializedName; +import lombok.Data; + +import java.io.Serializable; + +/** + * 小程序概况趋势 + * + * @author Charming + * @since 2018-04-28 + */ +@Data +public class WxMaSummaryTrend implements Serializable { + private static final long serialVersionUID = 1379688517709317935L; + /** + * 日期,yyyyMMdd 格式,如 20170313 + */ + @SerializedName(value = "refDate", alternate = "ref_date") + private String refDate; + /** + * 累计用户数 + */ + @SerializedName(value = "visitTotal", alternate = "visit_total") + private Long visitTotal; + /** + * 转发次数 + */ + @SerializedName(value = "sharePv", alternate = "share_pv") + private Long sharePv; + /** + * 转发人数 + */ + @SerializedName(value = "shareUv", alternate = "share_uv") + private Long shareUv; +} diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/analysis/WxMaUserPortrait.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/analysis/WxMaUserPortrait.java new file mode 100644 index 00000000..5e116490 --- /dev/null +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/analysis/WxMaUserPortrait.java @@ -0,0 +1,68 @@ +package cn.binarywang.wx.miniapp.bean.analysis; + +import cn.binarywang.wx.miniapp.util.json.WxMaGsonBuilder; +import lombok.Data; + +import java.io.Serializable; +import java.util.Map; + +/** + * 用户画像 + * + * @author Charming + * @since 2018-04-28 + */ +@Data +public class WxMaUserPortrait implements Serializable { + private static final long serialVersionUID = 5653571047669243178L; + /** + * 时间范围,如: "20170611-20170617" + */ + private String refDate; + /** + * 新用户 + */ + private Item visitUvNew; + /** + * 活跃用户 + */ + private Item visitUv; + + public static WxMaUserPortrait fromJson(String json) { + return WxMaGsonBuilder.create().fromJson(json, WxMaUserPortrait.class); + } + + @Data + public static class Item { + /** + * key: 省份,如北京、广东等 + * value: 活跃用户数或新用户数 + */ + private Map province; + /** + * key: 城市,如北京、广州等 + * value: 活跃用户数或新用户数 + */ + private Map city; + /** + * key: 性别,包括男、女、未知 + * value: 活跃用户数或新用户数 + */ + private Map genders; + /** + * key: 终端类型,包括iPhone, android,其他 + * value: 活跃用户数或新用户数 + */ + private Map platforms; + /** + * key: 机型,如苹果iPhone6, OPPO R9等 + * value: 活跃用户数或新用户数 + */ + private Map devices; + /** + * key: 年龄,包括17岁以下、18-24岁等区间 + * value: 活跃用户数或新用户数 + */ + private Map ages; + } +} diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/analysis/WxMaVisitDistribution.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/analysis/WxMaVisitDistribution.java new file mode 100644 index 00000000..1655eec2 --- /dev/null +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/analysis/WxMaVisitDistribution.java @@ -0,0 +1,83 @@ +package cn.binarywang.wx.miniapp.bean.analysis; + +import cn.binarywang.wx.miniapp.util.json.WxMaGsonBuilder; +import com.google.gson.annotations.SerializedName; +import lombok.Data; + +import java.io.Serializable; +import java.util.Map; + +/** + * 访问分布 + * 访问来源:(index="access_source_session_cnt") + * 1:小程序历史列表 + * 2:搜索 + * 3:会话 + * 4:二维码 + * 5:公众号主页 + * 6:聊天顶部 + * 7:系统桌面 + * 8:小程序主页 + * 9:附近的小程序 + * 10:其他 + * 11:模板消息 + * 12:客服消息 + * 13: 公众号菜单 + * 14: APP分享 + * 15: 支付完成页 + * 16: 长按识别二维码 + * 17: 相册选取二维码 + * 18: 公众号文章 + * 19:钱包 + * 20:卡包 + * 21:小程序内卡券 + * 22:其他小程序 + * 23:其他小程序返回 + * 24:卡券适用门店列表 + * 25:搜索框快捷入口 + * 26:小程序客服消息 + * 27:公众号下发 + * 访问时长:(index="access_staytime_info") + * 1: 0-2s + * 2: 3-5s + * 3: 6-10s + * 4: 11-20s + * 5: 20-30s + * 6: 30-50s + * 7: 50-100s + * 8: > 100s + * 平均访问深度:(index="access_depth_info") + * 1: 1页 + * 2: 2页 + * 3: 3页 + * 4: 4页 + * 5: 5页 + * 6: 6-10页 + * 7: >10页 + * + * @author Charming + * @since 2018-04-28 + */ +@Data +public class WxMaVisitDistribution implements Serializable { + private static final long serialVersionUID = 5404250039495926632L; + /** + * 日期,yyyyMMdd 格式,如 20170313 + */ + @SerializedName(value = "refDate", alternate = "ref_date") + private String refDate; + /** + * key: 分布类型 + * - access_source_session_cnt 访问来源分布 + * - access_staytime_info 访问时长分布 + * - access_depth_info 访问深度的分布 + * value: 场景 ID 下的值 + * - key: 场景 ID + * - value: 场景下的值 + */ + private Map> list; + + public static WxMaVisitDistribution fromJson(String json) { + return WxMaGsonBuilder.create().fromJson(json, WxMaVisitDistribution.class); + } +} diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/analysis/WxMaVisitPage.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/analysis/WxMaVisitPage.java new file mode 100644 index 00000000..705cf6b4 --- /dev/null +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/analysis/WxMaVisitPage.java @@ -0,0 +1,55 @@ +package cn.binarywang.wx.miniapp.bean.analysis; + +import com.google.gson.annotations.SerializedName; +import lombok.Data; + +import java.io.Serializable; + +/** + * @author Charming + * @since 2018-04-28 + */ +@Data +public class WxMaVisitPage implements Serializable { + private static final long serialVersionUID = -7006334774516877372L; + /** + * 页面路径 + */ + @SerializedName(value = "pagePath", alternate = "page_path") + private String pagePath; + /** + * 访问次数 + */ + @SerializedName(value = "pageVisitPv", alternate = "page_visit_pv") + private Long pageVisitPv; + /** + * 访问人数 + */ + @SerializedName(value = "pageVisitUv", alternate = "page_visit_uv") + private Long pageVisitUv; + /** + * 次均停留时长 + */ + @SerializedName(value = "pageStayTimePv", alternate = "page_staytime_pv") + private Float pageStayTimePv; + /** + * 进入页次数 + */ + @SerializedName(value = "entryPagePv", alternate = "entrypage_pv") + private Long entryPagePv; + /** + * 退出页次数 + */ + @SerializedName(value = "exitPagePv", alternate = "exitpage_pv") + private Long exitPagePv; + /** + * 转发次数 + */ + @SerializedName(value = "pageSharePv", alternate = "page_share_pv") + private Long pageSharePv; + /** + * 转发人数 + */ + @SerializedName(value = "pageShareUv", alternate = "page_share_uv") + private Long pageShareUv; +} diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/analysis/WxMaVisitTrend.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/analysis/WxMaVisitTrend.java new file mode 100644 index 00000000..72223ef6 --- /dev/null +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/analysis/WxMaVisitTrend.java @@ -0,0 +1,59 @@ +package cn.binarywang.wx.miniapp.bean.analysis; + +import com.google.gson.annotations.SerializedName; +import lombok.Data; + +import java.io.Serializable; + +/** + * 访问趋势 + * + * @author Charming + * @since 2018-04-28 + */ +@Data +public class WxMaVisitTrend implements Serializable { + private static final long serialVersionUID = 1379688517709317935L; + /** + * 日留存:日期,yyyyMMdd 格式,如 20170313 + * 周留存:时间,如"20170306-20170312" + * 月留存:时间,如"201702" + */ + @SerializedName(value = "refDate", alternate = "ref_date") + private String refDate; + /** + * 打开次数 + */ + @SerializedName(value = "sessionCnt", alternate = "session_cnt") + private Long sessionCnt; + /** + * 访问次数 + */ + @SerializedName(value = "visitPv", alternate = "visit_pv") + private Long visitPv; + /** + * 访问人数 + */ + @SerializedName(value = "visitUv", alternate = "visit_uv") + private Long visitUv; + /** + * 新用户数 + */ + @SerializedName(value = "visitUvNew", alternate = "visit_uv_new") + private Long visitUvNew; + /** + * 人均停留时长 (浮点型,单位:秒) + */ + @SerializedName(value = "stayTimeUv", alternate = "stay_time_uv") + private Float stayTimeUv; + /** + * 人均停留时长 (浮点型,单位:秒) + */ + @SerializedName(value = "stayTimeSession", alternate = "stay_time_session") + private Float stayTimeSession; + /** + * 人均停留时长 (浮点型,单位:秒) + */ + @SerializedName(value = "visitDepth", alternate = "visit_depth") + private Float visitDepth; +} diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/analysis/package-info.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/analysis/package-info.java new file mode 100644 index 00000000..e4e68c78 --- /dev/null +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/analysis/package-info.java @@ -0,0 +1,7 @@ +/** + * 数据分析 + * + * @author Charming + * @since 2018-04-28 + */ +package cn.binarywang.wx.miniapp.bean.analysis; diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/util/json/WxMaGsonBuilder.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/util/json/WxMaGsonBuilder.java index a11e8e6c..21f48d3f 100644 --- a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/util/json/WxMaGsonBuilder.java +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/util/json/WxMaGsonBuilder.java @@ -1,6 +1,9 @@ package cn.binarywang.wx.miniapp.util.json; import cn.binarywang.wx.miniapp.bean.WxMaTemplateMessage; +import cn.binarywang.wx.miniapp.bean.analysis.WxMaRetainInfo; +import cn.binarywang.wx.miniapp.bean.analysis.WxMaUserPortrait; +import cn.binarywang.wx.miniapp.bean.analysis.WxMaVisitDistribution; import cn.binarywang.wx.miniapp.bean.code.WxMaCodeCommitRequest; import cn.binarywang.wx.miniapp.bean.code.WxMaCodeVersionDistribution; import com.google.gson.Gson; @@ -17,6 +20,9 @@ public class WxMaGsonBuilder { INSTANCE.registerTypeAdapter(WxMaTemplateMessage.class, new WxMaTemplateMessageGsonAdapter()); INSTANCE.registerTypeAdapter(WxMaCodeCommitRequest.class, new WxMaCodeCommitRequestGsonAdapter()); INSTANCE.registerTypeAdapter(WxMaCodeVersionDistribution.class, new WxMaCodeVersionDistributionGsonAdapter()); + INSTANCE.registerTypeAdapter(WxMaVisitDistribution.class, new WxMaVisitDistributionGsonAdapter()); + INSTANCE.registerTypeAdapter(WxMaRetainInfo.class, new WxMaRetainInfoGsonAdapter()); + INSTANCE.registerTypeAdapter(WxMaUserPortrait.class, new WxMaUserPortraitGsonAdapter()); } public static Gson create() { diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/util/json/WxMaRetainInfoGsonAdapter.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/util/json/WxMaRetainInfoGsonAdapter.java new file mode 100644 index 00000000..a51972b4 --- /dev/null +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/util/json/WxMaRetainInfoGsonAdapter.java @@ -0,0 +1,52 @@ +package cn.binarywang.wx.miniapp.util.json; + +import cn.binarywang.wx.miniapp.bean.analysis.WxMaRetainInfo; +import com.google.gson.JsonArray; +import com.google.gson.JsonDeserializationContext; +import com.google.gson.JsonDeserializer; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParseException; +import me.chanjar.weixin.common.util.json.GsonHelper; + +import java.lang.reflect.Type; +import java.util.LinkedHashMap; +import java.util.Map; + +/** + * @author Charming + * @since 2018-04-28 + */ +public class WxMaRetainInfoGsonAdapter implements JsonDeserializer { + @Override + public WxMaRetainInfo deserialize(JsonElement json, Type type, JsonDeserializationContext jsonDeserializationContext) throws JsonParseException { + if (json == null) { + return null; + } + + WxMaRetainInfo retainInfo = new WxMaRetainInfo(); + JsonObject object = json.getAsJsonObject(); + String refDate = GsonHelper.getString(object, "ref_date"); + retainInfo.setRefDate(refDate); + retainInfo.setVisitUvNew(getAsMap(object, "visit_uv_new")); + retainInfo.setVisitUv(getAsMap(object, "visit_uv")); + return retainInfo; + } + + private Map getAsMap(JsonObject object, String memberName) { + JsonArray array = object.getAsJsonArray(memberName); + if (array != null && array.size() > 0) { + Map map = new LinkedHashMap<>(array.size()); + for (JsonElement element : array) { + JsonObject elementObject = element.getAsJsonObject(); + Integer key = GsonHelper.getInteger(elementObject, "key"); + if (key != null) { + Integer value = GsonHelper.getInteger(elementObject, "value"); + map.put(key, value); + } + } + return map; + } + return null; + } +} diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/util/json/WxMaUserPortraitGsonAdapter.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/util/json/WxMaUserPortraitGsonAdapter.java new file mode 100644 index 00000000..b8a7c448 --- /dev/null +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/util/json/WxMaUserPortraitGsonAdapter.java @@ -0,0 +1,67 @@ +package cn.binarywang.wx.miniapp.util.json; + +import cn.binarywang.wx.miniapp.bean.analysis.WxMaUserPortrait; +import com.google.gson.JsonArray; +import com.google.gson.JsonDeserializationContext; +import com.google.gson.JsonDeserializer; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParseException; +import me.chanjar.weixin.common.util.json.GsonHelper; +import org.apache.commons.lang3.StringUtils; + +import java.lang.reflect.Type; +import java.util.LinkedHashMap; +import java.util.Map; + +/** + * @author Charming + * @since 2018-04-28 + */ +public class WxMaUserPortraitGsonAdapter implements JsonDeserializer { + @Override + public WxMaUserPortrait deserialize(JsonElement json, Type type, JsonDeserializationContext jsonDeserializationContext) throws JsonParseException { + if (json == null) { + return null; + } + + WxMaUserPortrait portrait = new WxMaUserPortrait(); + JsonObject object = json.getAsJsonObject(); + String refDate = GsonHelper.getString(object, "ref_date"); + portrait.setRefDate(refDate); + portrait.setVisitUvNew(getPortraitItem(object.getAsJsonObject("visit_uv_new"))); + portrait.setVisitUv(getPortraitItem(object.getAsJsonObject("visit_uv"))); + return portrait; + } + + private WxMaUserPortrait.Item getPortraitItem(JsonObject object) { + if (object == null) { + return null; + } + WxMaUserPortrait.Item item = new WxMaUserPortrait.Item(); + item.setProvince(getAsMap(object, "province")); + item.setCity(getAsMap(object, "city")); + item.setGenders(getAsMap(object, "genders")); + item.setPlatforms(getAsMap(object, "platforms")); + item.setDevices(getAsMap(object, "devices")); + item.setAges(getAsMap(object, "ages")); + return item; + } + + private Map getAsMap(JsonObject object, String memberName) { + JsonArray array = object.getAsJsonArray(memberName); + if (array != null && array.size() > 0) { + Map map = new LinkedHashMap<>(array.size()); + for (JsonElement element : array) { + JsonObject elementObject = element.getAsJsonObject(); + String name = GsonHelper.getString(elementObject, "name"); + if (StringUtils.isNotBlank(name)) { + Long value = GsonHelper.getLong(elementObject, "value"); + map.put(name, value); + } + } + return map; + } + return null; + } +} diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/util/json/WxMaVisitDistributionGsonAdapter.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/util/json/WxMaVisitDistributionGsonAdapter.java new file mode 100644 index 00000000..45bdbac0 --- /dev/null +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/util/json/WxMaVisitDistributionGsonAdapter.java @@ -0,0 +1,67 @@ +package cn.binarywang.wx.miniapp.util.json; + +import cn.binarywang.wx.miniapp.bean.analysis.WxMaVisitDistribution; +import com.google.gson.JsonArray; +import com.google.gson.JsonDeserializationContext; +import com.google.gson.JsonDeserializer; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParseException; +import me.chanjar.weixin.common.util.json.GsonHelper; + +import java.lang.reflect.Type; +import java.util.Hashtable; +import java.util.LinkedHashMap; +import java.util.Map; + +/** + * @author Charming + * @since 2018-04-28 + */ +public class WxMaVisitDistributionGsonAdapter implements JsonDeserializer { + @Override + public WxMaVisitDistribution deserialize(JsonElement json, Type type, JsonDeserializationContext jsonDeserializationContext) throws JsonParseException { + if (json == null) { + return null; + } + + WxMaVisitDistribution distribution = new WxMaVisitDistribution(); + JsonObject object = json.getAsJsonObject(); + String refDate = GsonHelper.getString(object, "ref_date"); + distribution.setRefDate(refDate); + + boolean hasList = object.has("list"); + if (!hasList) { + return distribution; + } + + JsonArray listArray = object.getAsJsonArray("list"); + Map> list = new Hashtable<>(listArray.size()); + for (JsonElement indexElement : listArray) { + JsonObject indexObject = indexElement.getAsJsonObject(); + String index = GsonHelper.getString(indexObject, "index"); + if (index == null) { + continue; + } + + Map itemList = new LinkedHashMap<>(); + JsonArray itemArray = indexObject.getAsJsonArray("item_list"); + if (itemArray == null || itemArray.size() <= 0) { + list.put(index, itemList); + continue; + } + + for (JsonElement itemElement : itemArray) { + JsonObject itemObject = itemElement.getAsJsonObject(); + Integer key = GsonHelper.getInteger(itemObject, "key"); + Integer value = GsonHelper.getInteger(itemObject, "value"); + if (key != null) { + itemList.put(key, value); + } + } + list.put(index, itemList); + } + distribution.setList(list); + return distribution; + } +} diff --git a/weixin-java-miniapp/src/test/java/cn/binarywang/wx/miniapp/api/impl/WxMaAnalysisServiceImplTest.java b/weixin-java-miniapp/src/test/java/cn/binarywang/wx/miniapp/api/impl/WxMaAnalysisServiceImplTest.java new file mode 100644 index 00000000..9c1c2f00 --- /dev/null +++ b/weixin-java-miniapp/src/test/java/cn/binarywang/wx/miniapp/api/impl/WxMaAnalysisServiceImplTest.java @@ -0,0 +1,155 @@ +package cn.binarywang.wx.miniapp.api.impl; + +import cn.binarywang.wx.miniapp.api.WxMaAnalysisService; +import cn.binarywang.wx.miniapp.api.WxMaService; +import cn.binarywang.wx.miniapp.bean.analysis.WxMaRetainInfo; +import cn.binarywang.wx.miniapp.bean.analysis.WxMaSummaryTrend; +import cn.binarywang.wx.miniapp.bean.analysis.WxMaUserPortrait; +import cn.binarywang.wx.miniapp.bean.analysis.WxMaVisitDistribution; +import cn.binarywang.wx.miniapp.bean.analysis.WxMaVisitPage; +import cn.binarywang.wx.miniapp.bean.analysis.WxMaVisitTrend; +import cn.binarywang.wx.miniapp.test.ApiTestModule; +import com.google.inject.Inject; +import org.apache.commons.lang3.time.DateFormatUtils; +import org.apache.commons.lang3.time.DateUtils; +import org.testng.annotations.Guice; +import org.testng.annotations.Test; + +import java.util.Calendar; +import java.util.Date; +import java.util.List; + +import static org.testng.Assert.*; + +/** + * @author Charming + * @since 2018-04-28 + */ +@Guice(modules = ApiTestModule.class) +public class WxMaAnalysisServiceImplTest { + @Inject + private WxMaService wxMaService; + + @Test + public void testGetDailySummaryTrend() throws Exception { + final WxMaAnalysisService service = wxMaService.getAnalysisService(); + Date twoDaysAgo = DateUtils.addDays(new Date(), -2); + List trends = service.getDailySummaryTrend(twoDaysAgo, twoDaysAgo); + assertEquals(1, trends.size()); + System.out.println(trends); + } + + @Test + public void testGetDailyVisitTrend() throws Exception { + final WxMaAnalysisService service = wxMaService.getAnalysisService(); + Date twoDaysAgo = DateUtils.addDays(new Date(), -2); + List trends = service.getDailyVisitTrend(twoDaysAgo, twoDaysAgo); + assertEquals(1, trends.size()); + System.out.println(trends); + } + + @Test + public void testGetWeeklyVisitTrend() throws Exception { + Calendar calendar = Calendar.getInstance(); + calendar.set(Calendar.DAY_OF_WEEK, Calendar.SUNDAY); + Date now = new Date(); + Date lastSunday = calendar.getTime(); + if (DateUtils.isSameDay(lastSunday, now)) { + lastSunday = DateUtils.addDays(lastSunday, -7); + } + Date lastMonday = DateUtils.addDays(lastSunday, -6); + + final WxMaAnalysisService service = wxMaService.getAnalysisService(); + List trends = service.getWeeklyVisitTrend(lastMonday, lastSunday); + assertEquals(1, trends.size()); + System.out.println(trends); + } + + @Test + public void testGetMonthlyVisitTrend() throws Exception { + Date now = new Date(); + Date firstDayOfThisMonth = DateUtils.setDays(now, 1); + Date lastDayOfLastMonth = DateUtils.addDays(firstDayOfThisMonth, -1); + Date firstDayOfLastMonth = DateUtils.addMonths(firstDayOfThisMonth, -1); + + final WxMaAnalysisService service = wxMaService.getAnalysisService(); + List trends = service.getMonthlyVisitTrend(firstDayOfLastMonth, lastDayOfLastMonth); + assertEquals(1, trends.size()); + System.out.println(trends); + } + + @Test + public void testGetVisitDistribution() throws Exception { + final WxMaAnalysisService service = wxMaService.getAnalysisService(); + Date twoDaysAgo = DateUtils.addDays(new Date(), -2); + WxMaVisitDistribution distribution = service.getVisitDistribution(twoDaysAgo, twoDaysAgo); + assertNotNull(distribution); + String date = DateFormatUtils.format(twoDaysAgo, "yyyyMMdd"); + assertEquals(date, distribution.getRefDate()); + assertTrue(distribution.getList().containsKey("access_source_session_cnt")); + assertTrue(distribution.getList().containsKey("access_staytime_info")); + assertTrue(distribution.getList().containsKey("access_depth_info")); + System.out.println(distribution); + } + + @Test + public void testGetDailyRetainInfo() throws Exception { + final WxMaAnalysisService service = wxMaService.getAnalysisService(); + Date twoDaysAgo = DateUtils.addDays(new Date(), -2); + WxMaRetainInfo retainInfo = service.getDailyRetainInfo(twoDaysAgo, twoDaysAgo); + assertNotNull(retainInfo); + System.out.println(retainInfo); + } + + @Test + public void testGetWeeklyRetainInfo() throws Exception { + Calendar calendar = Calendar.getInstance(); + calendar.set(Calendar.DAY_OF_WEEK, Calendar.SUNDAY); + Date now = new Date(); + Date lastSunday = calendar.getTime(); + if (DateUtils.isSameDay(lastSunday, now)) { + lastSunday = DateUtils.addDays(lastSunday, -7); + } + Date lastMonday = DateUtils.addDays(lastSunday, -6); + + final WxMaAnalysisService service = wxMaService.getAnalysisService(); + WxMaRetainInfo retainInfo = service.getWeeklyRetainInfo(lastMonday, lastSunday); + assertNotNull(retainInfo); + System.out.println(retainInfo); + } + + @Test + public void testGetMonthlyRetainInfo() throws Exception { + Date now = new Date(); + Date firstDayOfThisMonth = DateUtils.setDays(now, 1); + Date lastDayOfLastMonth = DateUtils.addDays(firstDayOfThisMonth, -1); + Date firstDayOfLastMonth = DateUtils.addMonths(firstDayOfThisMonth, -1); + + final WxMaAnalysisService service = wxMaService.getAnalysisService(); + WxMaRetainInfo retainInfo = service.getMonthlyRetainInfo(firstDayOfLastMonth, lastDayOfLastMonth); + assertNotNull(retainInfo); + System.out.println(retainInfo); + } + + @Test + public void testGetVisitPage() throws Exception { + final WxMaAnalysisService service = wxMaService.getAnalysisService(); + Date twoDaysAgo = DateUtils.addDays(new Date(), -2); + List visitPages = service.getVisitPage(twoDaysAgo, twoDaysAgo); + assertNotNull(visitPages); + System.out.println(visitPages); + System.out.println(visitPages.get(0).getPagePath()); + System.out.println(visitPages.get(0).getPageVisitPv()); + } + + @Test + public void testGetUserPortrait() throws Exception { + Date twoDaysAgo = DateUtils.addDays(new Date(), -2); + Date eightDaysAgo = DateUtils.addDays(new Date(), -8); + + final WxMaAnalysisService service = wxMaService.getAnalysisService(); + WxMaUserPortrait portrait = service.getUserPortrait(eightDaysAgo, twoDaysAgo); + assertNotNull(portrait); + System.out.println(portrait); + } +} diff --git a/weixin-java-miniapp/src/test/java/cn/binarywang/wx/miniapp/bean/analysis/WxMaRetainInfoTest.java b/weixin-java-miniapp/src/test/java/cn/binarywang/wx/miniapp/bean/analysis/WxMaRetainInfoTest.java new file mode 100644 index 00000000..c2fd925e --- /dev/null +++ b/weixin-java-miniapp/src/test/java/cn/binarywang/wx/miniapp/bean/analysis/WxMaRetainInfoTest.java @@ -0,0 +1,22 @@ +package cn.binarywang.wx.miniapp.bean.analysis; + +import org.testng.annotations.Test; + +import static org.testng.Assert.*; + +/** + * @author Charming + * @since 2018-04-28 + */ +public class WxMaRetainInfoTest { + @Test + public void testFromJson() throws Exception { + String json = "{\"ref_date\":\"20170313\",\"visit_uv_new\":[{\"key\":0,\"value\":5464}],\"visit_uv\":[{\"key\":0,\"value\":55500}]}\n"; + WxMaRetainInfo retainInfo = WxMaRetainInfo.fromJson(json); + assertNotNull(retainInfo); + assertEquals("20170313", retainInfo.getRefDate()); + assertTrue(retainInfo.getVisitUv().containsKey(0)); + assertTrue(retainInfo.getVisitUvNew().containsKey(0)); + System.out.println(retainInfo); + } +} diff --git a/weixin-java-miniapp/src/test/java/cn/binarywang/wx/miniapp/bean/analysis/WxMaUserPortraitTest.java b/weixin-java-miniapp/src/test/java/cn/binarywang/wx/miniapp/bean/analysis/WxMaUserPortraitTest.java new file mode 100644 index 00000000..87239bb5 --- /dev/null +++ b/weixin-java-miniapp/src/test/java/cn/binarywang/wx/miniapp/bean/analysis/WxMaUserPortraitTest.java @@ -0,0 +1,19 @@ +package cn.binarywang.wx.miniapp.bean.analysis; + +import org.testng.annotations.Test; + +import static org.testng.Assert.assertNotNull; + +/** + * @author Charming + * @since 2018-04-28 + */ +public class WxMaUserPortraitTest { + @Test + public void testFromJson() throws Exception { + String json = "{\"ref_date\":\"20170611\",\"visit_uv_new\":{\"province\":[{\"id\":31,\"name\":\"广东省\",\"value\":215}],\"city\":[{\"id\":3102,\"name\":\"广州\",\"value\":78}],\"genders\":[{\"id\":1,\"name\":\"男\",\"value\":2146}],\"platforms\":[{\"id\":1,\"name\":\"iPhone\",\"value\":27642}],\"devices\":[{\"name\":\"OPPO R9\",\"value\":61}],\"ages\":[{\"id\":1,\"name\":\"17岁以下\",\"value\":151}]},\"visit_uv\":{\"province\":[{\"id\":31,\"name\":\"广东省\",\"value\":1341}],\"city\":[{\"id\":3102,\"name\":\"广州\",\"value\":234}],\"genders\":[{\"id\":1,\"name\":\"男\",\"value\":14534}],\"platforms\":[{\"id\":1,\"name\":\"iPhone\",\"value\":21750}],\"devices\":[{\"name\":\"OPPO R9\",\"value\":617}],\"ages\":[{\"id\":1,\"name\":\"17岁以下\",\"value\":3156}]}}\n"; + WxMaUserPortrait portrait = WxMaUserPortrait.fromJson(json); + System.out.println(portrait); + assertNotNull(portrait); + } +} diff --git a/weixin-java-miniapp/src/test/java/cn/binarywang/wx/miniapp/bean/analysis/WxMaVisitDistributionTest.java b/weixin-java-miniapp/src/test/java/cn/binarywang/wx/miniapp/bean/analysis/WxMaVisitDistributionTest.java new file mode 100644 index 00000000..2b01b3aa --- /dev/null +++ b/weixin-java-miniapp/src/test/java/cn/binarywang/wx/miniapp/bean/analysis/WxMaVisitDistributionTest.java @@ -0,0 +1,23 @@ +package cn.binarywang.wx.miniapp.bean.analysis; + +import org.testng.annotations.Test; + +import static org.testng.Assert.*; + +/** + * @author Charming + * @since 2018-04-28 + */ +public class WxMaVisitDistributionTest { + @Test + public void testFromJson() throws Exception { + String json = "{\"ref_date\":\"20170313\",\"list\":[{\"index\":\"access_source_session_cnt\",\"item_list\":[{\"key\":10,\"value\":5},{\"key\":8,\"value\":687},{\"key\":7,\"value\":10740},{\"key\":6,\"value\":1961},{\"key\":5,\"value\":677},{\"key\":4,\"value\":653},{\"key\":3,\"value\":1120},{\"key\":2,\"value\":10243},{\"key\":1,\"value\":116578}]},{\"index\":\"access_staytime_info\",\"item_list\":[{\"key\":8,\"value\":16329},{\"key\":7,\"value\":19322},{\"key\":6,\"value\":21832},{\"key\":5,\"value\":19539},{\"key\":4,\"value\":29670},{\"key\":3,\"value\":19667},{\"key\":2,\"value\":11794},{\"key\":1,\"value\":4511}]},{\"index\":\"access_depth_info\",\"item_list\":[{\"key\":5,\"value\":217},{\"key\":4,\"value\":3259},{\"key\":3,\"value\":32445},{\"key\":2,\"value\":63542},{\"key\":1,\"value\":43201}]}]}\n"; + WxMaVisitDistribution distribution = WxMaVisitDistribution.fromJson(json); + assertNotNull(distribution); + assertEquals("20170313", distribution.getRefDate()); + assertTrue(distribution.getList().containsKey("access_source_session_cnt")); + assertTrue(distribution.getList().containsKey("access_staytime_info")); + assertTrue(distribution.getList().containsKey("access_depth_info")); + System.out.println(distribution); + } +}