* 微信开放平台:1. WxOpenInRedisConfigStorage 支持 JedisPool/JedisSentinelPool 等 Pool<Jedis> 的子类;2. WxOpenInRedisConfigStorage 增加 keyPrefix 以支持可配置的前缀; * 微信开放平台:增加小程序代码模板库管理 * 小程序:增加代码管理相关 API * 小程序:增加修改服务器地址、成员管理 API * 小程序:增加数据分析相关 APImaster
| @@ -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 <a href="https://github.com/charmingoh">Charming</a> | |||
| * @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<WxMaSummaryTrend> getDailySummaryTrend(Date beginDate, Date endDate) throws WxErrorException; | |||
| /** | |||
| * 获取日访问趋势 | |||
| * 温馨提示:小程序接口目前只能查询一天的数据,即 beginDate 和 endDate 一样 | |||
| * | |||
| * @param beginDate 开始日期 | |||
| * @param endDate 结束日期,限定查询1天数据,end_date允许设置的最大值为昨日 | |||
| * @return 日访问趋势 | |||
| * @throws WxErrorException 获取失败时抛出,具体错误码请看文档 | |||
| */ | |||
| List<WxMaVisitTrend> getDailyVisitTrend(Date beginDate, Date endDate) throws WxErrorException; | |||
| /** | |||
| * 获取周访问趋势 | |||
| * 限定查询一个自然周的数据,时间必须按照自然周的方式输入: 如:20170306(周一), 20170312(周日) | |||
| * | |||
| * @param beginDate 开始日期,为周一日期 | |||
| * @param endDate 结束日期,为周日日期,限定查询一周数据 | |||
| * @return 周访问趋势(每项数据都是一个自然周汇总) | |||
| * @throws WxErrorException 获取失败时抛出,具体错误码请看文档 | |||
| */ | |||
| List<WxMaVisitTrend> getWeeklyVisitTrend(Date beginDate, Date endDate) throws WxErrorException; | |||
| /** | |||
| * 获取月访问趋势 | |||
| * 限定查询一个自然月的数据,时间必须按照自然月的方式输入: 如:20170201(月初), 20170228(月末) | |||
| * | |||
| * @param beginDate 开始日期,为自然月第一天 | |||
| * @param endDate 结束日期,为自然月最后一天,限定查询一个月数据 | |||
| * @return 月访问趋势(每项数据都是一个自然月汇总) | |||
| * @throws WxErrorException 获取失败时抛出,具体错误码请看文档 | |||
| */ | |||
| List<WxMaVisitTrend> 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<WxMaVisitPage> 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; | |||
| } | |||
| @@ -135,6 +135,13 @@ public interface WxMaService { | |||
| */ | |||
| WxMaTemplateService getTemplateService(); | |||
| /** | |||
| * 数据分析相关查询服务 | |||
| * | |||
| * @return WxMaAnalysisService | |||
| */ | |||
| WxMaAnalysisService getAnalysisService(); | |||
| /** | |||
| * 返回代码操作相关的 API | |||
| * | |||
| @@ -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 <a href="https://github.com/charmingoh">Charming</a> | |||
| * @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<WxMaSummaryTrend> getDailySummaryTrend(Date beginDate, Date endDate) throws WxErrorException { | |||
| return getAnalysisResultAsList(GET_DAILY_SUMMARY_TREND_URL, beginDate, endDate, | |||
| new TypeToken<List<WxMaSummaryTrend>>() { | |||
| }.getType()); | |||
| } | |||
| @Override | |||
| public List<WxMaVisitTrend> getDailyVisitTrend(Date beginDate, Date endDate) throws WxErrorException { | |||
| return getAnalysisResultAsList(GET_DAILY_VISIT_TREND_URL, beginDate, endDate, | |||
| new TypeToken<List<WxMaVisitTrend>>() { | |||
| }.getType()); | |||
| } | |||
| @Override | |||
| public List<WxMaVisitTrend> getWeeklyVisitTrend(Date beginDate, Date endDate) throws WxErrorException { | |||
| return getAnalysisResultAsList(GET_WEEKLY_VISIT_TREND_URL, beginDate, endDate, | |||
| new TypeToken<List<WxMaVisitTrend>>() { | |||
| }.getType()); | |||
| } | |||
| @Override | |||
| public List<WxMaVisitTrend> getMonthlyVisitTrend(Date beginDate, Date endDate) throws WxErrorException { | |||
| return getAnalysisResultAsList(GET_MONTHLY_VISIT_TREND_URL, beginDate, endDate, | |||
| new TypeToken<List<WxMaVisitTrend>>() { | |||
| }.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<WxMaVisitPage> getVisitPage(Date beginDate, Date endDate) throws WxErrorException { | |||
| return getAnalysisResultAsList(GET_VISIT_PAGE_URL, beginDate, endDate, | |||
| new TypeToken<List<WxMaVisitPage>>() { | |||
| }.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 <T> 返回的类型 | |||
| * @return List 类型的数据 | |||
| */ | |||
| private <T> List<T> 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(); | |||
| } | |||
| } | |||
| @@ -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, RequestHttp<CloseableHttpCl | |||
| private WxMaUserService userService = new WxMaUserServiceImpl(this); | |||
| private WxMaQrcodeService qrCodeService = new WxMaQrcodeServiceImpl(this); | |||
| private WxMaTemplateService templateService = new WxMaTemplateServiceImpl(this); | |||
| private WxMaAnalysisService analysisService = new WxMaAnalysisServiceImpl(this); | |||
| private WxMaCodeService codeService = new WxMaCodeServiceImpl(this); | |||
| private WxMaSettingService settingService = new WxMaSettingServiceImpl(this); | |||
| @@ -294,6 +296,11 @@ public class WxMaServiceImpl implements WxMaService, RequestHttp<CloseableHttpCl | |||
| return this.templateService; | |||
| } | |||
| @Override | |||
| public WxMaAnalysisService getAnalysisService() { | |||
| return this.analysisService; | |||
| } | |||
| @Override | |||
| public WxMaCodeService getCodeService() { | |||
| return this.codeService; | |||
| @@ -0,0 +1,43 @@ | |||
| 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; | |||
| /** | |||
| * 访问留存 | |||
| * | |||
| * @author <a href="https://github.com/charmingoh">Charming</a> | |||
| * @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<Integer, Integer> visitUvNew; | |||
| /** | |||
| * 活跃用户留存 | |||
| */ | |||
| private Map<Integer, Integer> visitUv; | |||
| public static WxMaRetainInfo fromJson(String json) { | |||
| return WxMaGsonBuilder.create().fromJson(json, WxMaRetainInfo.class); | |||
| } | |||
| } | |||
| @@ -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 <a href="https://github.com/charmingoh">Charming</a> | |||
| * @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; | |||
| } | |||
| @@ -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 <a href="https://github.com/charmingoh">Charming</a> | |||
| * @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<String, Long> province; | |||
| /** | |||
| * key: 城市,如北京、广州等 | |||
| * value: 活跃用户数或新用户数 | |||
| */ | |||
| private Map<String, Long> city; | |||
| /** | |||
| * key: 性别,包括男、女、未知 | |||
| * value: 活跃用户数或新用户数 | |||
| */ | |||
| private Map<String, Long> genders; | |||
| /** | |||
| * key: 终端类型,包括iPhone, android,其他 | |||
| * value: 活跃用户数或新用户数 | |||
| */ | |||
| private Map<String, Long> platforms; | |||
| /** | |||
| * key: 机型,如苹果iPhone6, OPPO R9等 | |||
| * value: 活跃用户数或新用户数 | |||
| */ | |||
| private Map<String, Long> devices; | |||
| /** | |||
| * key: 年龄,包括17岁以下、18-24岁等区间 | |||
| * value: 活跃用户数或新用户数 | |||
| */ | |||
| private Map<String, Long> ages; | |||
| } | |||
| } | |||
| @@ -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 <a href="https://github.com/charmingoh">Charming</a> | |||
| * @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<String, Map<Integer, Integer>> list; | |||
| public static WxMaVisitDistribution fromJson(String json) { | |||
| return WxMaGsonBuilder.create().fromJson(json, WxMaVisitDistribution.class); | |||
| } | |||
| } | |||
| @@ -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 <a href="https://github.com/charmingoh">Charming</a> | |||
| * @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; | |||
| } | |||
| @@ -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 <a href="https://github.com/charmingoh">Charming</a> | |||
| * @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; | |||
| } | |||
| @@ -0,0 +1,7 @@ | |||
| /** | |||
| * 数据分析 | |||
| * | |||
| * @author <a href="https://github.com/charmingoh">Charming</a> | |||
| * @since 2018-04-28 | |||
| */ | |||
| package cn.binarywang.wx.miniapp.bean.analysis; | |||
| @@ -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() { | |||
| @@ -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 <a href="https://github.com/charmingoh">Charming</a> | |||
| * @since 2018-04-28 | |||
| */ | |||
| public class WxMaRetainInfoGsonAdapter implements JsonDeserializer<WxMaRetainInfo> { | |||
| @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<Integer, Integer> getAsMap(JsonObject object, String memberName) { | |||
| JsonArray array = object.getAsJsonArray(memberName); | |||
| if (array != null && array.size() > 0) { | |||
| Map<Integer, Integer> 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; | |||
| } | |||
| } | |||
| @@ -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 <a href="https://github.com/charmingoh">Charming</a> | |||
| * @since 2018-04-28 | |||
| */ | |||
| public class WxMaUserPortraitGsonAdapter implements JsonDeserializer<WxMaUserPortrait> { | |||
| @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<String, Long> getAsMap(JsonObject object, String memberName) { | |||
| JsonArray array = object.getAsJsonArray(memberName); | |||
| if (array != null && array.size() > 0) { | |||
| Map<String, Long> 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; | |||
| } | |||
| } | |||
| @@ -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 <a href="https://github.com/charmingoh">Charming</a> | |||
| * @since 2018-04-28 | |||
| */ | |||
| public class WxMaVisitDistributionGsonAdapter implements JsonDeserializer<WxMaVisitDistribution> { | |||
| @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<String, Map<Integer, Integer>> list = new Hashtable<>(listArray.size()); | |||
| for (JsonElement indexElement : listArray) { | |||
| JsonObject indexObject = indexElement.getAsJsonObject(); | |||
| String index = GsonHelper.getString(indexObject, "index"); | |||
| if (index == null) { | |||
| continue; | |||
| } | |||
| Map<Integer, Integer> 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; | |||
| } | |||
| } | |||
| @@ -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 <a href="https://github.com/charmingoh">Charming</a> | |||
| * @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<WxMaSummaryTrend> 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<WxMaVisitTrend> 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<WxMaVisitTrend> 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<WxMaVisitTrend> 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<WxMaVisitPage> 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); | |||
| } | |||
| } | |||
| @@ -0,0 +1,22 @@ | |||
| package cn.binarywang.wx.miniapp.bean.analysis; | |||
| import org.testng.annotations.Test; | |||
| import static org.testng.Assert.*; | |||
| /** | |||
| * @author <a href="https://github.com/charmingoh">Charming</a> | |||
| * @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); | |||
| } | |||
| } | |||
| @@ -0,0 +1,19 @@ | |||
| package cn.binarywang.wx.miniapp.bean.analysis; | |||
| import org.testng.annotations.Test; | |||
| import static org.testng.Assert.assertNotNull; | |||
| /** | |||
| * @author <a href="https://github.com/charmingoh">Charming</a> | |||
| * @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); | |||
| } | |||
| } | |||
| @@ -0,0 +1,23 @@ | |||
| package cn.binarywang.wx.miniapp.bean.analysis; | |||
| import org.testng.annotations.Test; | |||
| import static org.testng.Assert.*; | |||
| /** | |||
| * @author <a href="https://github.com/charmingoh">Charming</a> | |||
| * @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); | |||
| } | |||
| } | |||