合并 Develop,发布3.1.0正式版 (#640)

* #519 修复小程序客服消息 URL 被转义的问题

* 优化单元测试提示信息

* 网页授权url增加&connect_redirect=1参数解决两次重定向跳转问题: https://blog.csdn.net/jiangguilong2000/article/details/79416615

* 修复错误的feeToYuan方法名为fenToYuan

* #529 EntPayBankRequest增加默认构造函数

* #529 EntPayBankResult中cmmsAmount的数据类型改为Integer

* #528 WxMpUser类增加三个属性:subscribe_scene、 qr_scene 和qr_scene_str

* 修复代码

* 发布3.0.1.BETA测试版本

* #533 微信刷卡支付请求类增加缺少的三个参数

* #536 企业号模块增加获取企业号应用相关接口

* 定义《企业号应用》的bean

* 增加《获取企业号应用》接口实现

* 增加获取测试企业号应用信息测试类

* #535 修复Tomcat 不能正常关闭的问题,增加线程池shutdown相关的操作

* #541 企业号增加实现管理标签的(获取标签成员)接口 

* 定义《企业号应用》的bean

* 增加《获取企业号应用》接口实现

* 增加获取测试企业号应用信息测试类

* tag service增加获取标签成员方法
http://qydev.weixin.qq.com/wiki/index.php?title=管理标签

* #534 公众号发送模版消息中的小程序path改回pagepath

* 发布3.0.2.BETA测试版本

* #547 开放平台模块 componentAccessToken 增加过期自动刷新

* createOrder方法增加H5支付的支持

* #551 文本卡片消息增加btntext字段

* #550 企业微信删除标签成员接口增加部门列表参数

* 清理无用代码

* #530 微信支付申请退款接口结果类增加单个代金券相关参数 ,并根据官方文档整理其他参数

* #531 小程序WxMaMessage类增加小程序卡片消息相关的几个属性

* #520 企业微信网页授权增加使用user_ticket获取成员详情的接口

* 发布3.0.3.BETA测试版本

* 优化代码

* 完善测试

* #559 微信开放平台:1. WxOpenInRedisConfigStorage 支持 JedisPool/JedisSentinelPool 等 Pool<Jedis> 的子类;2. WxOpenInRedisConfigStorage 增加 keyPrefix 以支持可配置的前缀;

* #560 微信开放平台:增加小程序代码模板库管理 

* 微信开放平台:1. WxOpenInRedisConfigStorage 支持 JedisPool/JedisSentinelPool 等 Pool<Jedis> 的子类;2. WxOpenInRedisConfigStorage 增加 keyPrefix 以支持可配置的前缀;

* 微信开放平台:增加小程序代码模板库管理

* #562 小程序增加代码管理相关 API

* 微信开放平台:1. WxOpenInRedisConfigStorage 支持 JedisPool/JedisSentinelPool 等 Pool<Jedis> 的子类;2. WxOpenInRedisConfigStorage 增加 keyPrefix 以支持可配置的前缀;

* 微信开放平台:增加小程序代码模板库管理

* 小程序:增加代码管理相关 API

* #563 小程序增加修改服务器地址、成员管理 API 

* 微信开放平台:1. WxOpenInRedisConfigStorage 支持 JedisPool/JedisSentinelPool 等 Pool<Jedis> 的子类;2. WxOpenInRedisConfigStorage 增加 keyPrefix 以支持可配置的前缀;

* 微信开放平台:增加小程序代码模板库管理

* 小程序:增加代码管理相关 API

* 小程序:增加修改服务器地址、成员管理 API

* #565 小程序增加数据分析相关 API 

* 微信开放平台:1. WxOpenInRedisConfigStorage 支持 JedisPool/JedisSentinelPool 等 Pool<Jedis> 的子类;2. WxOpenInRedisConfigStorage 增加 keyPrefix 以支持可配置的前缀;

* 微信开放平台:增加小程序代码模板库管理

* 小程序:增加代码管理相关 API

* 小程序:增加修改服务器地址、成员管理 API

* 小程序:增加数据分析相关 API

* #567 微信开放平台增加 HTTP proxy 机制

* 微信开放平台:1. WxOpenInRedisConfigStorage 支持 JedisPool/JedisSentinelPool 等 Pool<Jedis> 的子类;2. WxOpenInRedisConfigStorage 增加 keyPrefix 以支持可配置的前缀;

* 微信开放平台:增加小程序代码模板库管理

* 小程序:增加代码管理相关 API

* 小程序:增加修改服务器地址、成员管理 API

* 小程序:增加数据分析相关 API

* 微信开放平台:增加 HTTP proxy 机制

* #568 修复三方平台多次授权时,RefreshToken 没有刷新的问题

* fix 多次授权时,RefreshToken 没有刷新

* null 判断

* 发布3.0.4.BETA测试版本

* fix code

* #569 微信支付几个查询关闭对账下载相关接口增加重载方法,以方便客户端指定更多参数

* #578 微信开放平台增加 WxMaUserService 的实现

* 微信开放平台:1. WxOpenInRedisConfigStorage 支持 JedisPool/JedisSentinelPool 等 Pool<Jedis> 的子类;2. WxOpenInRedisConfigStorage 增加 keyPrefix 以支持可配置的前缀;

* 微信开放平台:增加小程序代码模板库管理

* 小程序:增加代码管理相关 API

* 小程序:增加修改服务器地址、成员管理 API

* 小程序:增加数据分析相关 API

* 微信开放平台:增加 HTTP proxy 机制

* 微信开放平台:增加 WxMaUserService 的实现

* 修复小程序码的相关方法命名:WxCode->WxaCode, WxCodeLimit -> WxaCodeUnlimit

* #556 日志信息中如果含有secret值的,将其值隐藏掉

* #585 小程序二维码支持is_hyaline参数生成透明背景二维码

* 发布3.0.5.BETA测试版本

* #584 修复企业付款到银行卡接口签名失败的问题

* 简化代码

* #586 微信支付 WxPayConfig增加支持byte数组方式设置证书

* #581 增加微信公众号错误信息枚举类WxMpErrorMsg,并提供方法,方便根据错误代码查询错误信息内容

* #555 修复微信支付服务商模式支付验证签名失败的问题

* #521 微信支付回调通知类WxPayOrderNotifyResult增加version参数

* #583 企业微信新增人员接口新增字段to_invite

* #583 企业微信通讯录管理增加邀请成员接口

* #587 企业微信几个接口增加个人二维码字段

* 修复字符

* 修复单元测试

* 发布3.0.6.BETA测试版本

* 重构WxError相关代码,自动根据代码补充错误中文说明

* 优化微信支付代码

* #584 修复企业付款queryEntPay签名失败问题

* #591 文件上传接口不自动关闭inputStream,由调用方自己控制

* #595 优化WxPayException

* 发布3.0.7.BETA测试版本

* 更新pom

* 优化代码

* #615 公众号客服消息添加 "发送小程序卡片" 类型

* 优化XStreamTransformer

* 微信支付模块jodd-http修改scope

* 发布3.0.8.BETA测试版本

* #623 群发接口增加clientmsgid

* add author for some files

* clean code

* 重构规范RequestExecuter代码

* #532 实现微信AI开放接口的三个接口:语音上传、查询识别结果和微信翻译功能

* 发布3.0.9.BETA测试版本

* #516 增加获取Wi-Fi门店列表接口

* #629 修复WxPayOrderNotifyResult解析xml报错问题

* #639 修复小程序代码模版库管理 access_token key 错误

* 发布3.1.0正式版本
This commit is contained in:
Binary Wang
2018-06-22 23:29:17 +08:00
committed by GitHub
parent 2d84939be0
commit 9d66d582db
304 changed files with 6960 additions and 1452 deletions

View File

@@ -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.error.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;
}

View File

@@ -0,0 +1,140 @@
package cn.binarywang.wx.miniapp.api;
import cn.binarywang.wx.miniapp.bean.code.WxMaCategory;
import cn.binarywang.wx.miniapp.bean.code.WxMaCodeAuditStatus;
import cn.binarywang.wx.miniapp.bean.code.WxMaCodeCommitRequest;
import cn.binarywang.wx.miniapp.bean.code.WxMaCodeSubmitAuditRequest;
import cn.binarywang.wx.miniapp.bean.code.WxMaCodeVersionDistribution;
import me.chanjar.weixin.common.error.WxErrorException;
import java.util.List;
/**
* 小程序代码管理相关 API大部分只能是第三方平台调用
* 文档https://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&t=resource/res_list&verify=1&id=open1489140610_Uavc4&token=&lang=zh_CN
*
* @author <a href="https://github.com/charmingoh">Charming</a>
* @since 2018-04-26 19:43
*/
public interface WxMaCodeService {
/**
* 为授权的小程序帐号上传小程序代码
*/
String COMMIT_URL = "https://api.weixin.qq.com/wxa/commit";
String GET_QRCODE_URL = "https://api.weixin.qq.com/wxa/get_qrcode";
String GET_CATEGORY_URL = "https://api.weixin.qq.com/wxa/get_category";
String GET_PAGE_URL = "https://api.weixin.qq.com/wxa/get_page";
String SUBMIT_AUDIT_URL = "https://api.weixin.qq.com/wxa/submit_audit";
String GET_AUDIT_STATUS_URL = "https://api.weixin.qq.com/wxa/get_auditstatus";
String GET_LATEST_AUDIT_STATUS_URL = "https://api.weixin.qq.com/wxa/get_latest_auditstatus";
String RELEASE_URL = "https://api.weixin.qq.com/wxa/release";
String CHANGE_VISIT_STATUS_URL = "https://api.weixin.qq.com/wxa/change_visitstatus";
String REVERT_CODE_RELEASE_URL = "https://api.weixin.qq.com/wxa/revertcoderelease";
String GET_SUPPORT_VERSION_URL = "https://api.weixin.qq.com/cgi-bin/wxopen/getweappsupportversion";
String SET_SUPPORT_VERSION_URL = "https://api.weixin.qq.com/cgi-bin/wxopen/setweappsupportversion";
String UNDO_CODE_AUDIT_URL = "https://api.weixin.qq.com/wxa/undocodeaudit";
/**
* 为授权的小程序帐号上传小程序代码(仅仅支持第三方开放平台)
*
* @param commitRequest 参数
* @throws WxErrorException 上传失败时抛出,具体错误码请看类注释文档
*/
void commit(WxMaCodeCommitRequest commitRequest) throws WxErrorException;
/**
* 获取体验小程序的体验二维码
*
* @return 二维码 bytes
* @throws WxErrorException 上传失败时抛出,具体错误码请看类注释文档
*/
byte[] getQrCode() throws WxErrorException;
/**
* 获取授权小程序帐号的可选类目
*
* @return List<WxMaCategory>
* @throws WxErrorException 获取失败时返回,具体错误码请看此接口的注释文档
*/
List<WxMaCategory> getCategory() throws WxErrorException;
/**
* 获取小程序的第三方提交代码的页面配置(仅供第三方开发者代小程序调用)
*
* @return page_list 页面配置列表
* @throws WxErrorException 获取失败时返回,具体错误码请看此接口的注释文档
*/
List<String> getPage() throws WxErrorException;
/**
* 将第三方提交的代码包提交审核(仅供第三方开发者代小程序调用)
*
* @param auditRequest 提交审核参数
* @return 审核编号
* @throws WxErrorException 提交失败时返回,具体错误码请看此接口的注释文档
*/
long submitAudit(WxMaCodeSubmitAuditRequest auditRequest) throws WxErrorException;
/**
* 查询某个指定版本的审核状态(仅供第三方代小程序调用)
*
* @param auditId 提交审核时获得的审核id
* @return 审核状态
* @throws WxErrorException 查询失败时返回,具体错误码请看此接口的注释文档
*/
WxMaCodeAuditStatus getAuditStatus(long auditId) throws WxErrorException;
/**
* 查询最新一次提交的审核状态(仅供第三方代小程序调用)
*
* @return 审核状态
* @throws WxErrorException 查询失败时返回,具体错误码请看此接口的注释文档
*/
WxMaCodeAuditStatus getLatestAuditStatus() throws WxErrorException;
/**
* 发布已通过审核的小程序(仅供第三方代小程序调用)
*
* @throws WxErrorException 发布失败时抛出,具体错误码请看此接口的注释文档
*/
void release() throws WxErrorException;
/**
* 修改小程序线上代码的可见状态(仅供第三方代小程序调用)
*
* @param action 设置可访问状态发布后默认可访问close为不可见open为可见
* @throws WxErrorException 发布失败时抛出,具体错误码请看此接口的注释文档
*/
void changeVisitStatus(String action) throws WxErrorException;
/**
* 小程序版本回退(仅供第三方代小程序调用)
*
* @throws WxErrorException 失败时抛出,具体错误码请看此接口的注释文档
*/
void revertCodeRelease() throws WxErrorException;
/**
* 查询当前设置的最低基础库版本及各版本用户占比 (仅供第三方代小程序调用)
*
* @return 小程序版本分布信息
* @throws WxErrorException 失败时抛出,具体错误码请看此接口的注释文档
*/
WxMaCodeVersionDistribution getSupportVersion() throws WxErrorException;
/**
* 设置最低基础库版本(仅供第三方代小程序调用)
*
* @param version 版本
* @throws WxErrorException 失败时抛出,具体错误码请看此接口的注释文档
*/
void setSupportVersion(String version) throws WxErrorException;
/**
* 小程序审核撤回
* 单个帐号每天审核撤回次数最多不超过1次一个月不超过10次
*
* @throws WxErrorException 失败时抛出,具体错误码请看此接口的注释文档
*/
void undoCodeAudit() throws WxErrorException;
}

View File

@@ -1,7 +1,7 @@
package cn.binarywang.wx.miniapp.api;
import me.chanjar.weixin.common.bean.result.WxMediaUploadResult;
import me.chanjar.weixin.common.exception.WxErrorException;
import me.chanjar.weixin.common.error.WxErrorException;
import java.io.File;
import java.io.InputStream;

View File

@@ -2,7 +2,7 @@ package cn.binarywang.wx.miniapp.api;
import cn.binarywang.wx.miniapp.bean.WxMaKefuMessage;
import cn.binarywang.wx.miniapp.bean.WxMaTemplateMessage;
import me.chanjar.weixin.common.exception.WxErrorException;
import me.chanjar.weixin.common.error.WxErrorException;
/**
* <pre>

View File

@@ -1,7 +1,7 @@
package cn.binarywang.wx.miniapp.api;
import cn.binarywang.wx.miniapp.bean.WxMaCodeLineColor;
import me.chanjar.weixin.common.exception.WxErrorException;
import me.chanjar.weixin.common.error.WxErrorException;
import java.io.File;
@@ -9,7 +9,7 @@ import java.io.File;
* <pre>
* 二维码相关操作接口.
*
* 接口AcreateWxCode加上接口CcreateQrcode总共生成的码数量限制为100,000请谨慎调用。
* 接口AcreateWxaCode加上接口CcreateQrcode总共生成的码数量限制为100,000请谨慎调用。
*
* 文档地址https://mp.weixin.qq.com/debug/wxadoc/dev/api/qrcode.html
* </pre>
@@ -40,16 +40,17 @@ public interface WxMaQrcodeService {
/**
* 接口A: 获取小程序码.
*
* @param path 不能为空,最大长度 128 字节
* @param width 默认430 二维码的宽度
* @param autoColor 默认true 自动配置线条颜色,如果颜色依然是黑色,则说明不建议配置主色调
* @param lineColor auth_color 为 false 时生效,使用 rgb 设置颜色 例如 {"r":"xxx","g":"xxx","b":"xxx"}
* @param path 不能为空,最大长度 128 字节
* @param width 默认430 二维码的宽度
* @param autoColor 默认true 自动配置线条颜色,如果颜色依然是黑色,则说明不建议配置主色调
* @param lineColor auth_color 为 false 时生效,使用 rgb 设置颜色 例如 {"r":"xxx","g":"xxx","b":"xxx"}
* @param is_hyaline 是否需要透明底色, is_hyaline 为true时生成透明底色的小程序码
*/
File createWxCode(String path, int width, boolean autoColor, WxMaCodeLineColor lineColor) throws WxErrorException;
File createWxaCode(String path, int width, boolean autoColor, WxMaCodeLineColor lineColor, boolean is_hyaline) throws WxErrorException;
File createWxCode(String path, int width) throws WxErrorException;
File createWxaCode(String path, int width) throws WxErrorException;
File createWxCode(String path) throws WxErrorException;
File createWxaCode(String path) throws WxErrorException;
/**
* 接口B: 获取小程序码(永久有效、数量暂无限制).
@@ -59,14 +60,16 @@ public interface WxMaQrcodeService {
* 使用如下代码可以获取到二维码中的 scene 字段的值。
* 调试阶段可以使用开发工具的条件编译自定义参数 scene=xxxx 进行模拟,开发工具模拟时的 scene 的参数值需要进行 urlencode
* </pre>
*
* @param scene 最大32个可见字符只支持数字大小写英文以及部分特殊字符!#$&'()*+,/:;=?@-._~,其它字符请自行编码为合法字符(因不支持%,中文无法使用 urlencode 处理,请使用其他编码方式)
* @param page 必须是已经发布的小程序页面,例如 "pages/index/index" ,如果不填写这个字段,默认跳主页面
* @param width 默认false 自动配置线条颜色,如果颜色依然是黑色,则说明不建议配置主色调
* @param autoColor 默认true 自动配置线条颜色,如果颜色依然是黑色,则说明不建议配置主色调
* @param lineColor auth_color 为 false 时生效,使用 rgb 设置颜色 例如 {"r":"xxx","g":"xxx","b":"xxx"}
* @param isHyaline 是否需要透明底色, is_hyaline 为true时生成透明底色的小程序码
*/
File createWxCodeLimit(String scene, String page, int width, boolean autoColor, WxMaCodeLineColor lineColor) throws WxErrorException;
File createWxaCodeUnlimit(String scene, String page, int width, boolean autoColor, WxMaCodeLineColor lineColor, boolean isHyaline) throws WxErrorException;
File createWxCodeLimit(String scene, String page) throws WxErrorException;
File createWxaCodeUnlimit(String scene, String page) throws WxErrorException;
}

View File

@@ -2,7 +2,7 @@ package cn.binarywang.wx.miniapp.api;
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import cn.binarywang.wx.miniapp.config.WxMaConfig;
import me.chanjar.weixin.common.exception.WxErrorException;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.common.util.http.MediaUploadRequestExecutor;
import me.chanjar.weixin.common.util.http.RequestExecutor;
import me.chanjar.weixin.common.util.http.RequestHttp;
@@ -135,6 +135,27 @@ public interface WxMaService {
*/
WxMaTemplateService getTemplateService();
/**
* 数据分析相关查询服务
*
* @return WxMaAnalysisService
*/
WxMaAnalysisService getAnalysisService();
/**
* 返回代码操作相关的 API
*
* @return WxMaCodeService
*/
WxMaCodeService getCodeService();
/**
* 小程序修改服务器地址、成员管理 API
*
* @return WxMaSettingService
*/
WxMaSettingService getSettingService();
/**
* 初始化http请求对象.
*/

View File

@@ -0,0 +1,65 @@
package cn.binarywang.wx.miniapp.api;
import cn.binarywang.wx.miniapp.bean.WxMaDomainAction;
import me.chanjar.weixin.common.error.WxErrorException;
/**
* 小程序修改服务器地址、成员管理 API大部分只能是第三方平台调用
*
* @author <a href="https://github.com/charmingoh">Charming</a>
* @since 2018-04-27 15:46
*/
public interface WxMaSettingService {
/**
* 修改服务器地址https://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&t=resource/res_list&verify=1&id=open1489138143_WPbOO&token=&lang=zh_CN
* access_token 为 authorizer_access_token
*/
String MODIFY_DOMAIN_URL = "https://api.weixin.qq.com/wxa/modify_domain";
String SET_WEB_VIEW_DOMAIN_URL = "https://api.weixin.qq.com/wxa/setwebviewdomain";
/**
* 小程序成员管理https://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&t=resource/res_list&verify=1&id=open1489140588_nVUgx&token=&lang=zh_CN
* access_token 为 authorizer_access_token
*/
String BIND_TESTER_URL = "https://api.weixin.qq.com/wxa/bind_tester";
String UNBIND_TESTER_URL = "https://api.weixin.qq.com/wxa/unbind_tester";
/**
* 操作服务器域名
*
* @param domainAction 域名操作参数
* 除了 webViewDomain都是有效的
* @return 以下字段仅在 get 时返回完整字段
* @throws WxErrorException 操作失败时抛出,具体错误码请看文档
*/
WxMaDomainAction modifyDomain(WxMaDomainAction domainAction) throws WxErrorException;
/**
* 设置小程序业务域名(仅供第三方代小程序调用)
* 授权给第三方的小程序,其业务域名只可以为第三方的服务器,
* 当小程序通过第三方发布代码上线后,小程序原先自己配置的业务域名将被删除,
* 只保留第三方平台的域名,所以第三方平台在代替小程序发布代码之前,需要调用接口为小程序添加业务域名。
* 提示:需要先将域名登记到第三方平台的小程序业务域名中,才可以调用接口进行配置。
*
* @param domainAction 域名操作参数
* 只有 action 和 webViewDomain 是有效的
* @return 以下字段仅在 get 时返回完整字段
* @throws WxErrorException 操作失败时抛出,具体错误码请看文档
*/
WxMaDomainAction setWebViewDomain(WxMaDomainAction domainAction) throws WxErrorException;
/**
* 绑定微信用户为小程序体验者
*
* @param wechatId 微信号
* @throws WxErrorException 失败时抛出,具体错误码请看文档
*/
void bindTester(String wechatId) throws WxErrorException;
/**
* 解除绑定小程序的体验者
*
* @param wechatId 微信号
* @throws WxErrorException 失败时抛出,具体错误码请看文档
*/
void unbindTester(String wechatId) throws WxErrorException;
}

View File

@@ -4,7 +4,7 @@ import cn.binarywang.wx.miniapp.bean.template.WxMaTemplateAddResult;
import cn.binarywang.wx.miniapp.bean.template.WxMaTemplateLibraryGetResult;
import cn.binarywang.wx.miniapp.bean.template.WxMaTemplateLibraryListResult;
import cn.binarywang.wx.miniapp.bean.template.WxMaTemplateListResult;
import me.chanjar.weixin.common.exception.WxErrorException;
import me.chanjar.weixin.common.error.WxErrorException;
import java.util.List;

View File

@@ -3,7 +3,7 @@ package cn.binarywang.wx.miniapp.api;
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import cn.binarywang.wx.miniapp.bean.WxMaPhoneNumberInfo;
import cn.binarywang.wx.miniapp.bean.WxMaUserInfo;
import me.chanjar.weixin.common.exception.WxErrorException;
import me.chanjar.weixin.common.error.WxErrorException;
/**
* 用户信息相关操作接口.

View File

@@ -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.error.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);
}
/**
* 获取数据分析结果并返回 ListreturnType 类型
*
* @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();
}
}

View File

@@ -0,0 +1,148 @@
package cn.binarywang.wx.miniapp.api.impl;
import cn.binarywang.wx.miniapp.api.WxMaCodeService;
import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.bean.code.WxMaCategory;
import cn.binarywang.wx.miniapp.bean.code.WxMaCodeAuditStatus;
import cn.binarywang.wx.miniapp.bean.code.WxMaCodeCommitRequest;
import cn.binarywang.wx.miniapp.bean.code.WxMaCodeSubmitAuditRequest;
import cn.binarywang.wx.miniapp.bean.code.WxMaCodeVersionDistribution;
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.error.WxError;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.common.util.http.BaseMediaDownloadRequestExecutor;
import me.chanjar.weixin.common.util.http.RequestExecutor;
import me.chanjar.weixin.common.util.json.GsonHelper;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
/**
* @author <a href="https://github.com/charmingoh">Charming</a>
* @since 2018-04-26 20:00
*/
public class WxMaCodeServiceImpl implements WxMaCodeService {
private static final JsonParser JSON_PARSER = new JsonParser();
private WxMaService wxMaService;
public WxMaCodeServiceImpl(WxMaService wxMaService) {
this.wxMaService = wxMaService;
}
@Override
public void commit(WxMaCodeCommitRequest commitRequest) throws WxErrorException {
this.wxMaService.post(COMMIT_URL, commitRequest.toJson());
}
@Override
public byte[] getQrCode() throws WxErrorException {
String appId = this.wxMaService.getWxMaConfig().getAppid();
Path qrCodeFilePath = null;
try {
RequestExecutor<File, String> executor = BaseMediaDownloadRequestExecutor
.create(this.wxMaService.getRequestHttp(), Files.createTempDirectory("weixin-java-tools-ma-" + appId).toFile());
qrCodeFilePath = this.wxMaService.execute(executor, GET_QRCODE_URL, null).toPath();
return Files.readAllBytes(qrCodeFilePath);
} catch (IOException e) {
throw new WxErrorException(WxError.builder().errorMsg(e.getMessage()).build(), e);
} finally {
if (qrCodeFilePath != null) {
try {
// 及时删除二维码文件,避免积压过多缓存文件
Files.delete(qrCodeFilePath);
} catch (Exception ignored) {
}
}
}
}
@Override
public List<WxMaCategory> getCategory() throws WxErrorException {
String responseContent = this.wxMaService.get(GET_CATEGORY_URL, null);
JsonObject jsonObject = JSON_PARSER.parse(responseContent).getAsJsonObject();
boolean hasCategoryList = jsonObject.has("category_list");
if (hasCategoryList) {
return WxMaGsonBuilder.create().fromJson(jsonObject.getAsJsonArray("category_list"),
new TypeToken<List<WxMaCategory>>() {
}.getType());
} else {
return null;
}
}
@Override
public List<String> getPage() throws WxErrorException {
String responseContent = this.wxMaService.get(GET_PAGE_URL, null);
JsonObject jsonObject = JSON_PARSER.parse(responseContent).getAsJsonObject();
boolean hasPageList = jsonObject.has("page_list");
if (hasPageList) {
return WxMaGsonBuilder.create().fromJson(jsonObject.getAsJsonArray("page_list"),
new TypeToken<List<String>>() {
}.getType());
} else {
return null;
}
}
@Override
public long submitAudit(WxMaCodeSubmitAuditRequest auditRequest) throws WxErrorException {
String responseContent = this.wxMaService.post(SUBMIT_AUDIT_URL, auditRequest.toJson());
JsonObject jsonObject = JSON_PARSER.parse(responseContent).getAsJsonObject();
return GsonHelper.getLong(jsonObject, "auditid");
}
@Override
public WxMaCodeAuditStatus getAuditStatus(long auditId) throws WxErrorException {
JsonObject param = new JsonObject();
param.addProperty("auditid", auditId);
String responseContent = this.wxMaService.post(GET_AUDIT_STATUS_URL, param.toString());
return WxMaCodeAuditStatus.fromJson(responseContent);
}
@Override
public WxMaCodeAuditStatus getLatestAuditStatus() throws WxErrorException {
String responseContent = this.wxMaService.get(GET_LATEST_AUDIT_STATUS_URL, null);
return WxMaCodeAuditStatus.fromJson(responseContent);
}
@Override
public void release() throws WxErrorException {
this.wxMaService.post(RELEASE_URL, "{}");
}
@Override
public void changeVisitStatus(String action) throws WxErrorException {
JsonObject param = new JsonObject();
param.addProperty("action", action);
this.wxMaService.post(CHANGE_VISIT_STATUS_URL, param.toString());
}
@Override
public void revertCodeRelease() throws WxErrorException {
this.wxMaService.get(REVERT_CODE_RELEASE_URL, null);
}
@Override
public WxMaCodeVersionDistribution getSupportVersion() throws WxErrorException {
String responseContent = this.wxMaService.post(GET_SUPPORT_VERSION_URL, "{}");
return WxMaCodeVersionDistribution.fromJson(responseContent);
}
@Override
public void setSupportVersion(String version) throws WxErrorException {
JsonObject param = new JsonObject();
param.addProperty("version", version);
this.wxMaService.post(SET_SUPPORT_VERSION_URL, param.toString());
}
@Override
public void undoCodeAudit() throws WxErrorException {
this.wxMaService.get(UNDO_CODE_AUDIT_URL, null);
}
}

View File

@@ -2,9 +2,9 @@ package cn.binarywang.wx.miniapp.api.impl;
import cn.binarywang.wx.miniapp.api.WxMaMediaService;
import cn.binarywang.wx.miniapp.api.WxMaService;
import me.chanjar.weixin.common.bean.result.WxError;
import me.chanjar.weixin.common.error.WxError;
import me.chanjar.weixin.common.bean.result.WxMediaUploadResult;
import me.chanjar.weixin.common.exception.WxErrorException;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.common.util.fs.FileUtils;
import me.chanjar.weixin.common.util.http.BaseMediaDownloadRequestExecutor;
import me.chanjar.weixin.common.util.http.MediaUploadRequestExecutor;

View File

@@ -7,8 +7,8 @@ import cn.binarywang.wx.miniapp.bean.WxMaTemplateMessage;
import cn.binarywang.wx.miniapp.constant.WxMaConstants;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import me.chanjar.weixin.common.bean.result.WxError;
import me.chanjar.weixin.common.exception.WxErrorException;
import me.chanjar.weixin.common.error.WxError;
import me.chanjar.weixin.common.error.WxErrorException;
/**
* @author <a href="https://github.com/binarywang">Binary Wang</a>

View File

@@ -5,9 +5,9 @@ import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.bean.WxMaCodeLineColor;
import cn.binarywang.wx.miniapp.bean.WxMaQrcode;
import cn.binarywang.wx.miniapp.bean.WxMaWxcode;
import cn.binarywang.wx.miniapp.bean.WxMaWxcodeLimit;
import cn.binarywang.wx.miniapp.bean.WxaCodeUnlimit;
import cn.binarywang.wx.miniapp.util.http.QrCodeRequestExecutor;
import me.chanjar.weixin.common.exception.WxErrorException;
import me.chanjar.weixin.common.error.WxErrorException;
import java.io.File;
@@ -33,42 +33,44 @@ public class WxMaQrcodeServiceImpl implements WxMaQrcodeService {
}
@Override
public File createWxCode(String path, int width, boolean autoColor, WxMaCodeLineColor lineColor) throws WxErrorException {
public File createWxaCode(String path, int width, boolean autoColor, WxMaCodeLineColor lineColor, boolean isHyaline) throws WxErrorException {
WxMaWxcode wxMaWxcode = new WxMaWxcode();
wxMaWxcode.setPath(path);
wxMaWxcode.setWidth(width);
wxMaWxcode.setAutoColor(autoColor);
wxMaWxcode.setLineColor(lineColor);
wxMaWxcode.setHyaline(isHyaline);
return this.wxMaService.execute(new QrCodeRequestExecutor(this.wxMaService.getRequestHttp()),
GET_WXACODE_URL, wxMaWxcode);
}
@Override
public File createWxCode(String path, int width) throws WxErrorException {
return this.createWxCode(path, width, true, null);
public File createWxaCode(String path, int width) throws WxErrorException {
return this.createWxaCode(path, width, true, null, false);
}
@Override
public File createWxCode(String path) throws WxErrorException {
return this.createWxCode(path, 430, true, null);
public File createWxaCode(String path) throws WxErrorException {
return this.createWxaCode(path, 430, true, null, false);
}
@Override
public File createWxCodeLimit(String scene, String page, int width, boolean autoColor, WxMaCodeLineColor lineColor)
public File createWxaCodeUnlimit(String scene, String page, int width, boolean autoColor, WxMaCodeLineColor lineColor, boolean isHyaline)
throws WxErrorException {
WxMaWxcodeLimit wxMaWxcodeLimit = new WxMaWxcodeLimit();
wxMaWxcodeLimit.setScene(scene);
wxMaWxcodeLimit.setPage(page);
wxMaWxcodeLimit.setWidth(width);
wxMaWxcodeLimit.setAutoColor(autoColor);
wxMaWxcodeLimit.setLineColor(lineColor);
WxaCodeUnlimit wxaCodeUnlimit = new WxaCodeUnlimit();
wxaCodeUnlimit.setScene(scene);
wxaCodeUnlimit.setPage(page);
wxaCodeUnlimit.setWidth(width);
wxaCodeUnlimit.setAutoColor(autoColor);
wxaCodeUnlimit.setLineColor(lineColor);
wxaCodeUnlimit.setHyaline(isHyaline);
return this.wxMaService.execute(new QrCodeRequestExecutor(this.wxMaService.getRequestHttp()),
GET_WXACODE_UNLIMIT_URL, wxMaWxcodeLimit);
GET_WXACODE_UNLIMIT_URL, wxaCodeUnlimit);
}
@Override
public File createWxCodeLimit(String scene, String page) throws WxErrorException {
return this.createWxCodeLimit(scene, page, 430, true, null);
public File createWxaCodeUnlimit(String scene, String page) throws WxErrorException {
return this.createWxaCodeUnlimit(scene, page, 430, true, null, false);
}
}

View File

@@ -1,10 +1,29 @@
package cn.binarywang.wx.miniapp.api.impl;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.Lock;
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;
import cn.binarywang.wx.miniapp.api.WxMaQrcodeService;
import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.api.WxMaSettingService;
import cn.binarywang.wx.miniapp.api.WxMaTemplateService;
import cn.binarywang.wx.miniapp.api.WxMaUserService;
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import cn.binarywang.wx.miniapp.config.WxMaConfig;
import com.google.common.base.Joiner;
import me.chanjar.weixin.common.bean.WxAccessToken;
import me.chanjar.weixin.common.error.WxError;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.common.util.DataUtils;
import me.chanjar.weixin.common.util.crypto.SHA1;
import me.chanjar.weixin.common.util.http.HttpType;
import me.chanjar.weixin.common.util.http.RequestExecutor;
import me.chanjar.weixin.common.util.http.RequestHttp;
import me.chanjar.weixin.common.util.http.SimpleGetRequestExecutor;
import me.chanjar.weixin.common.util.http.SimplePostRequestExecutor;
import me.chanjar.weixin.common.util.http.apache.ApacheHttpClientBuilder;
import me.chanjar.weixin.common.util.http.apache.DefaultApacheHttpClientBuilder;
import org.apache.http.HttpHost;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
@@ -14,27 +33,12 @@ import org.apache.http.impl.client.CloseableHttpClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import cn.binarywang.wx.miniapp.api.WxMaMediaService;
import cn.binarywang.wx.miniapp.api.WxMaMsgService;
import cn.binarywang.wx.miniapp.api.WxMaQrcodeService;
import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.api.WxMaTemplateService;
import cn.binarywang.wx.miniapp.api.WxMaUserService;
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import cn.binarywang.wx.miniapp.config.WxMaConfig;
import cn.binarywang.wx.miniapp.constant.WxMaConstants;
import com.google.common.base.Joiner;
import me.chanjar.weixin.common.bean.WxAccessToken;
import me.chanjar.weixin.common.bean.result.WxError;
import me.chanjar.weixin.common.exception.WxErrorException;
import me.chanjar.weixin.common.util.crypto.SHA1;
import me.chanjar.weixin.common.util.http.HttpType;
import me.chanjar.weixin.common.util.http.RequestExecutor;
import me.chanjar.weixin.common.util.http.RequestHttp;
import me.chanjar.weixin.common.util.http.SimpleGetRequestExecutor;
import me.chanjar.weixin.common.util.http.SimplePostRequestExecutor;
import me.chanjar.weixin.common.util.http.apache.ApacheHttpClientBuilder;
import me.chanjar.weixin.common.util.http.apache.DefaultApacheHttpClientBuilder;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.Lock;
import static cn.binarywang.wx.miniapp.constant.WxMaConstants.ErrorCode.*;
/**
* @author <a href="https://github.com/binarywang">Binary Wang</a>
@@ -51,6 +55,9 @@ 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);
private int retrySleepMillis = 1000;
private int maxRetryTimes = 5;
@@ -207,7 +214,9 @@ public class WxMaServiceImpl implements WxMaService, RequestHttp<CloseableHttpCl
throw new RuntimeException("微信服务端异常,超出重试次数");
}
public <T, E> T executeInternal(RequestExecutor<T, E> executor, String uri, E data) throws WxErrorException {
private <T, E> T executeInternal(RequestExecutor<T, E> executor, String uri, E data) throws WxErrorException {
E dataForLog = DataUtils.handleDataWithSecret(data);
if (uri.contains("access_token=")) {
throw new IllegalArgumentException("uri参数中不允许有access_token: " + uri);
}
@@ -217,16 +226,16 @@ public class WxMaServiceImpl implements WxMaService, RequestHttp<CloseableHttpCl
try {
T result = executor.execute(uriWithAccessToken, data);
this.log.debug("\n【请求地址】: {}\n【请求参数】{}\n【响应数据】{}", uriWithAccessToken, data, result);
this.log.debug("\n【请求地址】: {}\n【请求参数】{}\n【响应数据】{}", uriWithAccessToken, dataForLog, result);
return result;
} catch (WxErrorException e) {
WxError error = e.getError();
/*
* 发生以下情况时尝试刷新access_token
*/
if (error.getErrorCode() == WxMaConstants.ErrorCode.ERR_40001
|| error.getErrorCode() == WxMaConstants.ErrorCode.ERR_42001
|| error.getErrorCode() == WxMaConstants.ErrorCode.ERR_40014) {
if (error.getErrorCode() == ERR_40001
|| error.getErrorCode() == ERR_42001
|| error.getErrorCode() == ERR_40014) {
// 强制设置wxMpConfigStorage它的access token过期了这样在下一次请求里就会刷新access token
this.getWxMaConfig().expireAccessToken();
if (this.getWxMaConfig().autoRefreshToken()) {
@@ -235,12 +244,12 @@ public class WxMaServiceImpl implements WxMaService, RequestHttp<CloseableHttpCl
}
if (error.getErrorCode() != 0) {
this.log.error("\n【请求地址】: {}\n【请求参数】{}\n【错误信息】{}", uriWithAccessToken, data, error);
this.log.error("\n【请求地址】: {}\n【请求参数】{}\n【错误信息】{}", uriWithAccessToken, dataForLog, error);
throw new WxErrorException(error, e);
}
return null;
} catch (IOException e) {
this.log.error("\n【请求地址】: {}\n【请求参数】{}\n【异常信息】{}", uriWithAccessToken, data, e.getMessage());
this.log.error("\n【请求地址】: {}\n【请求参数】{}\n【异常信息】{}", uriWithAccessToken, dataForLog, e.getMessage());
throw new RuntimeException(e);
}
}
@@ -290,4 +299,19 @@ public class WxMaServiceImpl implements WxMaService, RequestHttp<CloseableHttpCl
public WxMaTemplateService getTemplateService() {
return this.templateService;
}
@Override
public WxMaAnalysisService getAnalysisService() {
return this.analysisService;
}
@Override
public WxMaCodeService getCodeService() {
return this.codeService;
}
@Override
public WxMaSettingService getSettingService() {
return this.settingService;
}
}

View File

@@ -0,0 +1,48 @@
package cn.binarywang.wx.miniapp.api.impl;
import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.api.WxMaSettingService;
import cn.binarywang.wx.miniapp.bean.WxMaDomainAction;
import cn.binarywang.wx.miniapp.util.json.WxMaGsonBuilder;
import me.chanjar.weixin.common.error.WxErrorException;
import java.util.HashMap;
import java.util.Map;
/**
* @author <a href="https://github.com/charmingoh">Charming</a>
* @since 2018-04-27 15:46
*/
public class WxMaSettingServiceImpl implements WxMaSettingService {
private WxMaService wxMaService;
public WxMaSettingServiceImpl(WxMaService wxMaService) {
this.wxMaService = wxMaService;
}
@Override
public WxMaDomainAction modifyDomain(WxMaDomainAction domainAction) throws WxErrorException {
String responseContent = this.wxMaService.post(MODIFY_DOMAIN_URL, domainAction.toJson());
return WxMaDomainAction.fromJson(responseContent);
}
@Override
public WxMaDomainAction setWebViewDomain(WxMaDomainAction domainAction) throws WxErrorException {
String responseContent = this.wxMaService.post(SET_WEB_VIEW_DOMAIN_URL, domainAction.toJson());
return WxMaDomainAction.fromJson(responseContent);
}
@Override
public void bindTester(String wechatId) throws WxErrorException {
Map<String, Object> param = new HashMap<>(1);
param.put("wechatid", wechatId);
this.wxMaService.post(BIND_TESTER_URL, WxMaGsonBuilder.create().toJson(param));
}
@Override
public void unbindTester(String wechatId) throws WxErrorException {
Map<String, Object> param = new HashMap<>(1);
param.put("wechatid", wechatId);
this.wxMaService.post(UNBIND_TESTER_URL, WxMaGsonBuilder.create().toJson(param));
}
}

View File

@@ -6,8 +6,8 @@ import cn.binarywang.wx.miniapp.bean.template.WxMaTemplateAddResult;
import cn.binarywang.wx.miniapp.bean.template.WxMaTemplateLibraryGetResult;
import cn.binarywang.wx.miniapp.bean.template.WxMaTemplateLibraryListResult;
import cn.binarywang.wx.miniapp.bean.template.WxMaTemplateListResult;
import me.chanjar.weixin.common.bean.result.WxError;
import me.chanjar.weixin.common.exception.WxErrorException;
import me.chanjar.weixin.common.error.WxError;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.common.util.json.WxGsonBuilder;
import java.util.HashMap;

View File

@@ -8,7 +8,7 @@ import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import cn.binarywang.wx.miniapp.bean.WxMaPhoneNumberInfo;
import cn.binarywang.wx.miniapp.bean.WxMaUserInfo;
import cn.binarywang.wx.miniapp.util.crypt.WxMaCryptUtils;
import me.chanjar.weixin.common.exception.WxErrorException;
import me.chanjar.weixin.common.error.WxErrorException;
/**
* @author <a href="https://github.com/binarywang">Binary Wang</a>

View File

@@ -0,0 +1,58 @@
package cn.binarywang.wx.miniapp.bean;
import cn.binarywang.wx.miniapp.util.json.WxMaGsonBuilder;
import com.google.gson.annotations.SerializedName;
import lombok.Builder;
import lombok.Data;
import java.io.Serializable;
import java.util.List;
/**
* 域名相关操作
*
* @author <a href="https://github.com/charmingoh">Charming</a>
* @since 2018-04-27 15:45
*/
@Data
@Builder
public class WxMaDomainAction implements Serializable {
private static final long serialVersionUID = -2898601966852935708L;
/**
* add添加, delete删除, set覆盖, get获取。当参数是get时不需要填四个域名字段
*/
private String action;
/**
* request合法域名当action参数是get时不需要此字段。
*/
@SerializedName("requestdomain")
private List<String> requestDomain;
/**
* socket合法域名当action参数是get时不需要此字段。
*/
@SerializedName("wsrequestdomain")
private List<String> wsRequestDomain;
/**
* uploadFile合法域名当action参数是get时不需要此字段。
*/
@SerializedName("uploaddomain")
private List<String> uploadDomain;
/**
* downloadFile合法域名当action参数是get时不需要此字段。
*/
@SerializedName("downloaddomain")
private List<String> downloadDomain;
/**
* 小程序业务域名当action参数是get时不需要此字段。
*/
@SerializedName("webviewdomain")
private List<String> webViewDomain;
public String toJson() {
return WxMaGsonBuilder.create().toJson(this);
}
public static WxMaDomainAction fromJson(String json) {
return WxMaGsonBuilder.create().fromJson(json, WxMaDomainAction.class);
}
}

View File

@@ -4,7 +4,7 @@ import cn.binarywang.wx.miniapp.builder.ImageMessageBuilder;
import cn.binarywang.wx.miniapp.builder.LinkMessageBuilder;
import cn.binarywang.wx.miniapp.builder.MaPageMessageBuilder;
import cn.binarywang.wx.miniapp.builder.TextMessageBuilder;
import com.google.gson.GsonBuilder;
import cn.binarywang.wx.miniapp.util.json.WxMaGsonBuilder;
import com.google.gson.annotations.SerializedName;
import lombok.AllArgsConstructor;
import lombok.Builder;
@@ -104,7 +104,7 @@ public class WxMaKefuMessage implements Serializable {
}
public String toJson() {
return new GsonBuilder().create().toJson(this);
return WxMaGsonBuilder.create().toJson(this);
}
}

View File

@@ -42,7 +42,6 @@ public class WxMaMessage implements Serializable {
@SerializedName("CreateTime")
@XStreamAlias("CreateTime")
@XStreamConverter(value = XStreamCDataConverter.class)
private Integer createTime;
@SerializedName("MsgType")
@@ -62,7 +61,6 @@ public class WxMaMessage implements Serializable {
@SerializedName("MsgId")
@XStreamAlias("MsgId")
@XStreamConverter(value = XStreamCDataConverter.class)
private Long msgId;
@SerializedName("PicUrl")
@@ -80,6 +78,31 @@ public class WxMaMessage implements Serializable {
@XStreamConverter(value = XStreamCDataConverter.class)
private String event;
@SerializedName("Title")
@XStreamAlias("Title")
@XStreamConverter(value = XStreamCDataConverter.class)
private String title;
@SerializedName("AppId")
@XStreamAlias("AppId")
@XStreamConverter(value = XStreamCDataConverter.class)
private String appId;
@SerializedName("PagePath")
@XStreamAlias("PagePath")
@XStreamConverter(value = XStreamCDataConverter.class)
private String pagePath;
@SerializedName("ThumbUrl")
@XStreamAlias("ThumbUrl")
@XStreamConverter(value = XStreamCDataConverter.class)
private String thumbUrl;
@SerializedName("ThumbMediaId")
@XStreamAlias("ThumbMediaId")
@XStreamConverter(value = XStreamCDataConverter.class)
private String thumbMediaId;
@SerializedName("SessionFrom")
@XStreamAlias("SessionFrom")
@XStreamConverter(value = XStreamCDataConverter.class)

View File

@@ -23,6 +23,9 @@ public class WxMaWxcode extends AbstractWxMaQrcodeWrapper implements Serializabl
@SerializedName("auto_color")
private boolean autoColor = true;
@SerializedName("is_hyaline")
private boolean isHyaline = false;
@SerializedName("line_color")
private WxMaCodeLineColor lineColor = new WxMaCodeLineColor("0", "0", "0");

View File

@@ -15,7 +15,7 @@ import java.io.Serializable;
*/
@Data
@EqualsAndHashCode(callSuper = false)
public class WxMaWxcodeLimit extends AbstractWxMaQrcodeWrapper implements Serializable {
public class WxaCodeUnlimit extends AbstractWxMaQrcodeWrapper implements Serializable {
private static final long serialVersionUID = 4782193774524960401L;
private String scene;
private String page;
@@ -25,11 +25,14 @@ public class WxMaWxcodeLimit extends AbstractWxMaQrcodeWrapper implements Serial
@SerializedName("auto_color")
private boolean autoColor = true;
@SerializedName("is_hyaline")
private boolean isHyaline = false;
@SerializedName("line_color")
private WxMaCodeLineColor lineColor = new WxMaCodeLineColor("0", "0", "0");
public static WxMaWxcodeLimit fromJson(String json) {
return WxMaGsonBuilder.create().fromJson(json, WxMaWxcodeLimit.class);
public static WxaCodeUnlimit fromJson(String json) {
return WxMaGsonBuilder.create().fromJson(json, WxaCodeUnlimit.class);
}
}

View File

@@ -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);
}
}

View File

@@ -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;
}

View File

@@ -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;
}
}

View File

@@ -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);
}
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -0,0 +1,7 @@
/**
* 数据分析
*
* @author <a href="https://github.com/charmingoh">Charming</a>
* @since 2018-04-28
*/
package cn.binarywang.wx.miniapp.bean.analysis;

View File

@@ -0,0 +1,62 @@
package cn.binarywang.wx.miniapp.bean.code;
import com.google.gson.annotations.SerializedName;
import lombok.Builder;
import lombok.Data;
import java.io.Serializable;
/**
* 小程序帐号的可选类目,其中 address / tag / title 是提交审核会用到的
*
* @author <a href="https://github.com/charmingoh">Charming</a>
* @since 2018-04-26 19:44
*/
@Data
@Builder
public class WxMaCategory implements Serializable {
private static final long serialVersionUID = -7663757440028175135L;
/**
* 一级类目名称
*/
@SerializedName("first_class")
private String firstClass;
/**
* 二级类目名称
*/
@SerializedName("second_class")
private String secondClass;
/**
* 三级类目名称
*/
@SerializedName("third_class")
private String thirdClass;
/**
* 一级类目的ID编号
*/
@SerializedName("first_id")
private Long firstId;
/**
* 二级类目的ID编号
*/
@SerializedName("second_id")
private Long secondId;
/**
* 三级类目的ID编号
*/
@SerializedName("third_id")
private Long thirdId;
/**
* 小程序的页面,可通过“获取小程序的第三方提交代码的页面配置”接口获得
*/
private String address;
/**
* 小程序的标签多个标签用空格分隔标签不能多于10个标签长度不超过20
*/
private String tag;
/**
* 小程序页面的标题,标题长度不超过32
*/
private String title;
}

View File

@@ -0,0 +1,37 @@
package cn.binarywang.wx.miniapp.bean.code;
import cn.binarywang.wx.miniapp.util.json.WxMaGsonBuilder;
import com.google.gson.annotations.SerializedName;
import lombok.Builder;
import lombok.Data;
import java.io.Serializable;
/**
* 小程序代码审核状态
*
* @author <a href="https://github.com/charmingoh">Charming</a>
* @since 2018-04-26 19:44:39
*/
@Data
@Builder
public class WxMaCodeAuditStatus implements Serializable {
private static final long serialVersionUID = 4655119308692217268L;
/**
* 审核 ID
*/
@SerializedName(value = "auditId", alternate = {"auditid"})
private Long auditId;
/**
* 审核状态其中0为审核成功1为审核失败2为审核中
*/
private Integer status;
/**
* 当status=1审核被拒绝时返回的拒绝原因
*/
private String reason;
public static WxMaCodeAuditStatus fromJson(String json) {
return WxMaGsonBuilder.create().fromJson(json, WxMaCodeAuditStatus.class);
}
}

View File

@@ -0,0 +1,39 @@
package cn.binarywang.wx.miniapp.bean.code;
import cn.binarywang.wx.miniapp.util.json.WxMaGsonBuilder;
import lombok.Builder;
import lombok.Data;
import java.io.Serializable;
/**
* 微信代码请求上传参数
*
* @author <a href="https://github.com/charmingoh">Charming</a>
* @since 2018-04-26 19:44:47
*/
@Data
@Builder
public class WxMaCodeCommitRequest implements Serializable {
private static final long serialVersionUID = 7495157056049312108L;
/**
* 代码库中的代码模版ID
*/
private Long templateId;
/**
* 第三方自定义的配置
*/
private WxMaCodeExtConfig extConfig;
/**
* 代码版本号,开发者可自定义
*/
private String userVersion;
/**
* 代码描述,开发者可自定义
*/
private String userDesc;
public String toJson() {
return WxMaGsonBuilder.create().toJson(this);
}
}

View File

@@ -0,0 +1,199 @@
package cn.binarywang.wx.miniapp.bean.code;
import lombok.Builder;
import lombok.Data;
import java.io.Serializable;
import java.util.List;
import java.util.Map;
/**
* 上传代码需要用到的第三方自定义的配置
*
* @author <a href="https://github.com/charmingoh">Charming</a>
* @since 2018-04-26 19:44
*/
@Data
@Builder
public class WxMaCodeExtConfig implements Serializable {
private static final long serialVersionUID = -7666911367458178753L;
/**
* 配置 ext.json 是否生效
* 必填:是
*/
private boolean extEnable;
/**
* 配置 extAppid
* 必填:是
*/
private String extAppid;
/**
* 开发自定义的数据字段
* 必填:否
*/
private Object ext;
/**
* 单独设置每个页面的 json
* 必填:否
* key: page 名称,如 pages/logs/logs
* value: page 配置
*/
private Map<String, PageConfig> extPages;
/**
* 是否直接提交到待审核列表
* 必填:否
*/
private Boolean directCommit;
/**
* 设置页面路径(同 app.json 相同的字段,填写会覆盖 app.json
* 必填:否
*/
private List<String> pages;
/**
* 设置默认页面的窗口表现(同 app.json 相同的字段,填写会覆盖 app.json
* 必填:否
*/
private PageConfig window;
/**
* 设置各种网络请求的超时时间(同 app.json 相同的字段,填写会覆盖 app.json
* 必填:否
*/
private NetworkTimeout networkTimeout;
/**
* 设置是否开启 debug 模式(同 app.json 相同的字段,填写会覆盖 app.json
* 必填:否
*/
private Boolean debug;
/**
* page.json 配置,页面配置
* 文档https://mp.weixin.qq.com/debug/wxadoc/dev/framework/config.html
*/
@Data
@Builder
public static class PageConfig {
/**
* 导航栏背景颜色,如"#000000" HexColor
* 默认:#000000
*/
private String navigationBarBackgroundColor;
/**
* 导航栏标题颜色,仅支持 black/white
* 默认white
*/
private String navigationBarTextStyle;
/**
* 导航栏标题文字内容
*/
private String navigationBarTitleText;
/**
* 窗口的背景色 HexColor
* 默认:#ffffff
*/
private String backgroundColor;
/**
* 下拉背景字体、loading 图的样式,仅支持 dark/light
* 默认dark
*/
private String backgroundTextStyle;
/**
* 是否开启下拉刷新,详见页面相关事件处理函数
* 默认false
*/
private String enablePullDownRefresh;
/**
* 设置为 true 则页面整体不能上下滚动;只在 page.json 中有效,无法在 app.json 中设置该项
* 默认false
*/
private Boolean disableScroll;
/**
* 页面上拉触底事件触发时距页面底部距离单位为px
* 默认50
*/
private Integer onReachBottomDistance;
}
/**
* tabBar 配置
*/
@Data
@Builder
public static class TabBar {
/**
* HexColor, tab 上的文字默认颜色
*/
private String color;
/**
* HexColor, tab 上的文字选中时的颜色
*/
private String selectedColor;
/**
* HexColor, tab 的背景色
*/
private String backgroundColor;
/**
* tabbar 上边框的颜色,仅支持 black/white
*/
private String borderStyle;
/**
* tab 的列表最少2个、最多5个 tab
*/
private List<Item> list;
/**
* 可选值 bottom、top
*/
private String position;
/**
* list item
*/
@Data
@Builder
public static class Item {
/**
* 是 页面路径,必须在 pages 中先定义
*/
private String pagePath;
/**
* tab 上按钮文字
*/
private String text;
/**
* 图片路径icon 大小限制为40kb建议尺寸为 81px * 81px当 postion 为 top 时,此参数无效,不支持网络图片
*/
private String iconPath;
/**
* 选中时的图片路径icon 大小限制为40kb建议尺寸为 81px * 81px ,当 postion 为 top 时,此参数无效
*/
private String selectedIconPath;
}
}
/**
* 各种网络请求的超时时间
*/
@Data
@Builder
public static class NetworkTimeout {
/**
* wx.request的超时时间单位毫秒默认为60000
* 必填:否
*/
private Integer request;
/**
* wx.connectSocket的超时时间单位毫秒默认为60000
* 必填:否
*/
private Integer connectSocket;
/**
* wx.uploadFile的超时时间单位毫秒默认为60000
* 必填:否
*/
private Integer uploadFile;
/**
* wx.downloadFile的超时时间单位毫秒默认为60000
* 必填:否
*/
private Integer downloadFile;
}
}

View File

@@ -0,0 +1,30 @@
package cn.binarywang.wx.miniapp.bean.code;
import cn.binarywang.wx.miniapp.util.json.WxMaGsonBuilder;
import com.google.gson.annotations.SerializedName;
import lombok.Builder;
import lombok.Data;
import java.io.Serializable;
import java.util.List;
/**
* 提交审核的请求
*
* @author <a href="https://github.com/charmingoh">Charming</a>
* @since 2018-04-26 19:45
*/
@Data
@Builder
public class WxMaCodeSubmitAuditRequest implements Serializable {
private static final long serialVersionUID = 8854979405505241314L;
/**
* 提交审核项的一个列表至少填写1项至多填写5项
*/
@SerializedName("item_list")
private List<WxMaCategory> itemList;
public String toJson() {
return WxMaGsonBuilder.create().toJson(this);
}
}

View File

@@ -0,0 +1,30 @@
package cn.binarywang.wx.miniapp.bean.code;
import cn.binarywang.wx.miniapp.util.json.WxMaGsonBuilder;
import lombok.Data;
import java.util.Map;
/**
* 小程序代码版本号分布
*
* @author <a href="https://github.com/charmingoh">Charming</a>
* @since 2018-04-26 19:45
*/
@Data
public class WxMaCodeVersionDistribution {
/**
* 当前版本
*/
private String nowVersion;
/**
* 受影响用户占比
* key: version, 版本号
* value: percentage, 受影响比例
*/
private Map<String, Float> uvInfo;
public static WxMaCodeVersionDistribution fromJson(String json) {
return WxMaGsonBuilder.create().fromJson(json, WxMaCodeVersionDistribution.class);
}
}

View File

@@ -0,0 +1,7 @@
/**
* 微信小程序代码管理相关的 bean
*
* @author <a href="https://github.com/charmingoh">Charming</a>
* @since 2018-04-26 19:44
*/
package cn.binarywang.wx.miniapp.bean.code;

View File

@@ -2,7 +2,7 @@ package cn.binarywang.wx.miniapp.message;
import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.bean.WxMaMessage;
import me.chanjar.weixin.common.exception.WxErrorException;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.common.session.WxSessionManager;
import java.util.Map;

View File

@@ -2,7 +2,7 @@ package cn.binarywang.wx.miniapp.message;
import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.bean.WxMaMessage;
import me.chanjar.weixin.common.exception.WxErrorException;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.common.session.WxSessionManager;
import java.util.Map;

View File

@@ -3,7 +3,7 @@ package cn.binarywang.wx.miniapp.message;
import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.bean.WxMaMessage;
import me.chanjar.weixin.common.api.WxErrorExceptionHandler;
import me.chanjar.weixin.common.exception.WxErrorException;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.common.session.WxSessionManager;
import java.util.ArrayList;

View File

@@ -1,8 +1,8 @@
package cn.binarywang.wx.miniapp.util.http;
import cn.binarywang.wx.miniapp.bean.AbstractWxMaQrcodeWrapper;
import me.chanjar.weixin.common.bean.result.WxError;
import me.chanjar.weixin.common.exception.WxErrorException;
import me.chanjar.weixin.common.error.WxError;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.common.util.fs.FileUtils;
import me.chanjar.weixin.common.util.http.RequestExecutor;
import me.chanjar.weixin.common.util.http.RequestHttp;

View File

@@ -0,0 +1,28 @@
package cn.binarywang.wx.miniapp.util.json;
import cn.binarywang.wx.miniapp.bean.code.WxMaCodeCommitRequest;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonSerializationContext;
import com.google.gson.JsonSerializer;
import java.lang.reflect.Type;
/**
* @author <a href="https://github.com/charmingoh">Charming</a>
* @since 2018-04-26 19:47
*/
public class WxMaCodeCommitRequestGsonAdapter implements JsonSerializer<WxMaCodeCommitRequest> {
@Override
public JsonElement serialize(WxMaCodeCommitRequest request, Type typeOfSrc, JsonSerializationContext context) {
JsonObject requestJson = new JsonObject();
requestJson.addProperty("template_id", request.getTemplateId());
requestJson.addProperty("user_version", request.getUserVersion());
requestJson.addProperty("user_desc", request.getUserDesc());
if (request.getExtConfig() != null) {
requestJson.addProperty("ext_json", WxMaGsonBuilder.create().toJson(request.getExtConfig()));
}
return requestJson;
}
}

View File

@@ -0,0 +1,50 @@
package cn.binarywang.wx.miniapp.util.json;
import cn.binarywang.wx.miniapp.bean.code.WxMaCodeVersionDistribution;
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-26 19:47
*/
public class WxMaCodeVersionDistributionGsonAdapter implements JsonDeserializer<WxMaCodeVersionDistribution> {
@Override
public WxMaCodeVersionDistribution deserialize(JsonElement json, Type type, JsonDeserializationContext jsonDeserializationContext) throws JsonParseException {
if (json == null) {
return null;
}
WxMaCodeVersionDistribution distribution = new WxMaCodeVersionDistribution();
JsonObject object = json.getAsJsonObject();
distribution.setNowVersion(GsonHelper.getString(object, "now_version"));
distribution.setUvInfo(getAsMap(object.getAsJsonObject("uv_info"), "items"));
return distribution;
}
private Map<String, Float> getAsMap(JsonObject object, String memberName) {
JsonArray array = object.getAsJsonArray(memberName);
if (array != null && array.size() > 0) {
Map<String, Float> map = new LinkedHashMap<>(array.size());
for (JsonElement element : array) {
JsonObject elementObject = element.getAsJsonObject();
String version = GsonHelper.getString(elementObject, "version");
if (version != null) {
Float percentage = GsonHelper.getFloat(elementObject, "percentage");
map.put(version, percentage);
}
}
return map;
}
return null;
}
}

View File

@@ -1,6 +1,11 @@
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;
import com.google.gson.GsonBuilder;
@@ -13,6 +18,11 @@ public class WxMaGsonBuilder {
static {
INSTANCE.disableHtmlEscaping();
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() {

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -60,7 +60,6 @@ public class XStreamTransformer {
*/
private static void registerClass(Class<?> clz) {
XStream xstream = XStreamInitializer.getInstance();
xstream.setClassLoader(Thread.currentThread().getContextClassLoader());
xstream.processAnnotations(clz);
xstream.processAnnotations(getInnerClasses(clz));

View File

@@ -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);
}
}

View File

@@ -0,0 +1,156 @@
package cn.binarywang.wx.miniapp.api.impl;
import cn.binarywang.wx.miniapp.api.WxMaCodeService;
import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.bean.code.WxMaCategory;
import cn.binarywang.wx.miniapp.bean.code.WxMaCodeAuditStatus;
import cn.binarywang.wx.miniapp.bean.code.WxMaCodeCommitRequest;
import cn.binarywang.wx.miniapp.bean.code.WxMaCodeExtConfig;
import cn.binarywang.wx.miniapp.bean.code.WxMaCodeSubmitAuditRequest;
import cn.binarywang.wx.miniapp.bean.code.WxMaCodeVersionDistribution;
import cn.binarywang.wx.miniapp.config.WxMaConfig;
import cn.binarywang.wx.miniapp.test.ApiTestModule;
import com.google.inject.Inject;
import org.testng.annotations.Guice;
import org.testng.annotations.Test;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.assertTrue;
/**
* @author <a href="https://github.com/charmingoh">Charming</a>
* @since 2018-04-26 20:18
*/
@Test
@Guice(modules = ApiTestModule.class)
public class WxMaCodeServiceImplTest {
@Inject
private WxMaService wxService;
@Inject
private WxMaConfig wxMaConfig;
@Test
public void testGetCategory() throws Exception {
List<WxMaCategory> categories = wxService.getCodeService().getCategory();
System.out.println(String.valueOf(categories));
}
@Test
public void testCommit() throws Exception {
String themeColor = "#0074d9";
String themeFontColor = "#ffffff";
Map<String, Object> ext = new HashMap<>();
ext.put("appName", "xxx");
ext.put("verified", true);
ext.put("navigationBarBackgroundColor", themeColor);
ext.put("navigationBarTextStyle", themeFontColor);
ext.put("companyId", 4128);
ext.put("companyFullName", "xxx有限公司");
WxMaCodeService wxMaCodeService = wxService.getCodeService();
WxMaCodeCommitRequest commitRequest = WxMaCodeCommitRequest
.builder()
.templateId(6L)
.userVersion("v0.1.0")
.userDesc("init")
.extConfig(WxMaCodeExtConfig.builder()
.extAppid(wxMaConfig.getAppid())
.extEnable(true)
.ext(ext)
.window(
WxMaCodeExtConfig.PageConfig
.builder()
.navigationBarBackgroundColor(themeColor)
.navigationBarTextStyle(themeFontColor)
.build()
)
.build())
.build();
wxMaCodeService.commit(commitRequest);
}
@Test
public void testGetQrCode() throws Exception {
byte[] qrCode = wxService.getCodeService().getQrCode();
assertTrue(qrCode.length > 0);
}
@Test
public void testGetPage() throws Exception {
List<String> pageList = wxService.getCodeService().getPage();
System.out.println(String.valueOf(pageList));
}
@Test
public void testSubmitAudit() throws Exception {
WxMaCodeSubmitAuditRequest auditRequest = WxMaCodeSubmitAuditRequest
.builder()
.itemList(Arrays.asList(
WxMaCategory
.builder()
.address("pages/logs/logs")
.tag("工具 效率")
.firstClass("工具")
.firstId(287L)
.secondClass("效率")
.secondId(616L)
.title("日志")
.build()
)).build();
long auditId = wxService.getCodeService().submitAudit(auditRequest);
assertTrue(auditId > 0);
// 421937937
System.out.println(auditId);
}
@Test
public void testGetAuditStatus() throws Exception {
WxMaCodeAuditStatus auditStatus = wxService.getCodeService().getAuditStatus(421937937L);
System.out.println(auditStatus);
assertNotNull(auditStatus);
}
@Test
public void testGetLatestAuditStatus() throws Exception {
WxMaCodeAuditStatus auditStatus = wxService.getCodeService().getLatestAuditStatus();
System.out.println(auditStatus);
assertNotNull(auditStatus);
}
@Test
public void testRelease() throws Exception {
wxService.getCodeService().release();
}
@Test
public void testChangeVisitStatus() throws Exception {
wxService.getCodeService().changeVisitStatus("open");
}
@Test
public void testRevertCodeRelease() throws Exception {
wxService.getCodeService().revertCodeRelease();
}
@Test
public void testGetSupportVersion() throws Exception {
WxMaCodeVersionDistribution distribution = wxService.getCodeService().getSupportVersion();
System.out.println(distribution);
}
@Test
public void testSetSupportVersion() throws Exception {
wxService.getCodeService().setSupportVersion("1.2.0");
}
@Test
public void testUndoCodeAudit() throws Exception {
}
}

View File

@@ -4,7 +4,7 @@ import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.test.ApiTestModule;
import com.google.inject.Inject;
import me.chanjar.weixin.common.bean.result.WxMediaUploadResult;
import me.chanjar.weixin.common.exception.WxErrorException;
import me.chanjar.weixin.common.error.WxErrorException;
import org.testng.annotations.Guice;
import org.testng.annotations.Test;

View File

@@ -7,7 +7,7 @@ import cn.binarywang.wx.miniapp.test.ApiTestModule;
import cn.binarywang.wx.miniapp.test.TestConfig;
import com.google.common.collect.Lists;
import com.google.inject.Inject;
import me.chanjar.weixin.common.exception.WxErrorException;
import me.chanjar.weixin.common.error.WxErrorException;
import org.testng.annotations.*;
import java.text.SimpleDateFormat;

View File

@@ -1,12 +1,12 @@
package cn.binarywang.wx.miniapp.api.impl;
import java.io.File;
import org.testng.annotations.*;
import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.test.ApiTestModule;
import com.google.inject.Inject;
import org.testng.annotations.Guice;
import org.testng.annotations.Test;
import java.io.File;
/**
* @author <a href="https://github.com/binarywang">Binary Wang</a>
@@ -15,7 +15,7 @@ import java.io.File;
@Guice(modules = ApiTestModule.class)
public class WxMaQrcodeServiceImplTest {
@Inject
protected WxMaService wxService;
private WxMaService wxService;
@Test
public void testCreateQrCode() throws Exception {
@@ -24,14 +24,14 @@ public class WxMaQrcodeServiceImplTest {
}
@Test
public void testCreateWxCode() throws Exception {
final File wxCode = this.wxService.getQrcodeService().createWxCode("111", 122);
public void testCreateWxaCode() throws Exception {
final File wxCode = this.wxService.getQrcodeService().createWxaCode("111", 122);
System.out.println(wxCode);
}
@Test
public void testCreateWxCodeLimit() throws Exception {
final File wxCode = this.wxService.getQrcodeService().createWxCodeLimit("111", null);
public void testCreateWxaCodeUnlimit() throws Exception {
final File wxCode = this.wxService.getQrcodeService().createWxaCodeUnlimit("111", null);
System.out.println(wxCode);
}

View File

@@ -4,7 +4,7 @@ import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.config.WxMaConfig;
import cn.binarywang.wx.miniapp.test.ApiTestModule;
import com.google.inject.Inject;
import me.chanjar.weixin.common.exception.WxErrorException;
import me.chanjar.weixin.common.error.WxErrorException;
import org.apache.commons.lang3.StringUtils;
import org.testng.annotations.Guice;
import org.testng.annotations.Test;

View File

@@ -0,0 +1,54 @@
package cn.binarywang.wx.miniapp.api.impl;
import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.bean.WxMaDomainAction;
import cn.binarywang.wx.miniapp.test.ApiTestModule;
import com.google.inject.Inject;
import org.testng.annotations.Guice;
import org.testng.annotations.Test;
import static org.testng.Assert.assertNotNull;
/**
* @author <a href="https://github.com/charmingoh">Charming</a>
* @since 2018-04-27 15:38
*/
@Test
@Guice(modules = ApiTestModule.class)
public class WxMaSettingServiceImplTest {
@Inject
private WxMaService wxService;
@Test
public void testModifyDomain() throws Exception {
WxMaDomainAction domainAction = wxService.getSettingService().modifyDomain(WxMaDomainAction
.builder()
.action("get")
.build());
System.out.println(domainAction);
assertNotNull(domainAction);
domainAction.setAction("set");
WxMaDomainAction result = wxService.getSettingService().modifyDomain(domainAction);
System.out.println(result);
}
@Test
public void testBindTester() throws Exception {
wxService.getSettingService().bindTester("WeChatId");
}
@Test
public void testUnbindTester() throws Exception {
wxService.getSettingService().unbindTester("WeChatId");
}
@Test
public void testSetWebViewDomain() throws Exception {
WxMaDomainAction domainAction = wxService.getSettingService().setWebViewDomain(WxMaDomainAction
.builder()
.action("get")
.build());
System.out.println(domainAction);
}
}

View File

@@ -53,5 +53,17 @@ public class WxMaKefuMessageTest {
"\"miniprogrampage\":{\"title\":\"title\",\"pagepath\":\"pagePath\",\"thumb_media_id\":\"thumbMediaId\"}}");
}
public void testURLEscaped() {
WxMaKefuMessage reply = WxMaKefuMessage.newLinkBuilder()
.toUser("OPENID")
.url("https://mp.weixin.qq.com/s?__biz=MzI0MDA2OTY5NQ==")
.description("description")
.title("title")
.thumbUrl("thumbUrl")
.build();
assertThat(reply.toJson())
.isEqualTo( "{\"touser\":\"OPENID\",\"msgtype\":\"link\"," +
"\"link\":{\"title\":\"title\",\"description\":\"description\",\"url\":\"https://mp.weixin.qq.com/s?__biz=MzI0MDA2OTY5NQ==\",\"thumb_url\":\"thumbUrl\"}}");
}
}

View File

@@ -12,118 +12,39 @@ import static org.testng.Assert.assertEquals;
public class WxMaMessageTest {
public void testFromXml() {
String xml = "<xml>"
+ "<ToUserName><![CDATA[toUser]]></ToUserName>"
+ "<FromUserName><![CDATA[fromUser]]></FromUserName> "
+ "<CreateTime>1348831860</CreateTime>"
+ "<MsgDataFormat><![CDATA[text]]></MsgDataFormat>"
+ "<Content><![CDATA[this is a test]]></Content>"
+ "<MsgId>1234567890123456</MsgId>"
+ "<PicUrl><![CDATA[this is a url]]></PicUrl>"
+ "<MediaId><![CDATA[media_id]]></MediaId>"
+ "<Format><![CDATA[Format]]></Format>"
+ "<ThumbMediaId><![CDATA[thumb_media_id]]></ThumbMediaId>"
+ "<Location_X>23.134521</Location_X>"
+ "<Location_Y>113.358803</Location_Y>"
+ "<Scale>20</Scale>"
+ "<Label><![CDATA[位置信息]]></Label>"
+ "<Description><![CDATA[公众平台官网链接]]></Description>"
+ "<Url><![CDATA[url]]></Url>"
+ "<Title><![CDATA[公众平台官网链接]]></Title>"
+ "<Event><![CDATA[subscribe]]></Event>"
+ "<EventKey><![CDATA[qrscene_123123]]></EventKey>"
+ "<Ticket><![CDATA[TICKET]]></Ticket>"
+ "<Latitude>23.137466</Latitude>"
+ "<Longitude>113.352425</Longitude>"
+ "<Precision>119.385040</Precision>"
+ "<ScanCodeInfo>"
+ " <ScanType><![CDATA[qrcode]]></ScanType>"
+ " <ScanResult><![CDATA[1]]></ScanResult>"
+ "</ScanCodeInfo>"
+ "<SendPicsInfo>"
+ " <Count>1</Count>\n"
+ " <PicList>"
+ " <item>"
+ " <PicMd5Sum><![CDATA[1b5f7c23b5bf75682a53e7b6d163e185]]></PicMd5Sum>"
+ " </item>"
+ " </PicList>"
+ "</SendPicsInfo>"
+ "<SendLocationInfo>"
+ " <Location_X><![CDATA[23]]></Location_X>\n"
+ " <Location_Y><![CDATA[113]]></Location_Y>\n"
+ " <Scale><![CDATA[15]]></Scale>\n"
+ " <Label><![CDATA[ 广州市海珠区客村艺苑路 106号]]></Label>\n"
+ " <Poiname><![CDATA[wo de poi]]></Poiname>\n"
+ "</SendLocationInfo>"
+ "</xml>";
String xml = "<xml>\n" +
" <ToUserName><![CDATA[toUser]]></ToUserName>\n" +
" <FromUserName><![CDATA[fromUser]]></FromUserName>\n" +
" <CreateTime>1482048670</CreateTime>\n" +
" <MsgType><![CDATA[text]]></MsgType>\n" +
" <Content><![CDATA[this is a test]]></Content>\n" +
" <MsgId>1234567890123456</MsgId>\n" +
" <PicUrl><![CDATA[this is a url]]></PicUrl>\n" +
" <MediaId><![CDATA[media_id]]></MediaId>\n" +
" <Title><![CDATA[Title]]></Title>\n" +
" <AppId><![CDATA[AppId]]></AppId>\n" +
" <PagePath><![CDATA[PagePath]]></PagePath>\n" +
" <ThumbUrl><![CDATA[ThumbUrl]]></ThumbUrl>\n" +
" <ThumbMediaId><![CDATA[ThumbMediaId]]></ThumbMediaId>\n" +
" <Event><![CDATA[user_enter_tempsession]]></Event>\n" +
" <SessionFrom><![CDATA[sessionFrom]]></SessionFrom>\n" +
"</xml>";
WxMaMessage wxMessage = WxMaMessage.fromXml(xml);
assertEquals(wxMessage.getToUser(), "toUser");
assertEquals(wxMessage.getFromUser(), "fromUser");
assertEquals(wxMessage.getCreateTime(), new Long(1348831860L));
assertEquals(wxMessage.getCreateTime(),new Integer(1482048670));
assertEquals(wxMessage.getMsgType(), WxConsts.XmlMsgType.TEXT);
assertEquals(wxMessage.getContent(), "this is a test");
assertEquals(wxMessage.getMsgId(), new Long(1234567890123456L));
assertEquals(wxMessage.getPicUrl(), "this is a url");
assertEquals(wxMessage.getMediaId(), "media_id");
assertEquals(wxMessage.getEvent(), "subscribe");
}
public void testFromXml2() {
String xml = "<xml>"
+ "<ToUserName><![CDATA[toUser]]></ToUserName>"
+ "<FromUserName><![CDATA[fromUser]]></FromUserName> "
+ "<CreateTime>1348831860</CreateTime>"
+ "<MsgDataFormat><![CDATA[text]]></MsgDataFormat>"
+ "<Content><![CDATA[this is a test]]></Content>"
+ "<MsgID>1234567890123456</MsgID>"
+ "<PicUrl><![CDATA[this is a url]]></PicUrl>"
+ "<MediaId><![CDATA[media_id]]></MediaId>"
+ "<Format><![CDATA[Format]]></Format>"
+ "<ThumbMediaId><![CDATA[thumb_media_id]]></ThumbMediaId>"
+ "<Location_X>23.134521</Location_X>"
+ "<Location_Y>113.358803</Location_Y>"
+ "<Scale>20</Scale>"
+ "<Label><![CDATA[位置信息]]></Label>"
+ "<Description><![CDATA[公众平台官网链接]]></Description>"
+ "<Url><![CDATA[url]]></Url>"
+ "<Title><![CDATA[公众平台官网链接]]></Title>"
+ "<Event><![CDATA[subscribe]]></Event>"
+ "<EventKey><![CDATA[qrscene_123123]]></EventKey>"
+ "<Ticket><![CDATA[TICKET]]></Ticket>"
+ "<Latitude>23.137466</Latitude>"
+ "<Longitude>113.352425</Longitude>"
+ "<Precision>119.385040</Precision>"
+ "<ScanCodeInfo>"
+ " <ScanType><![CDATA[qrcode]]></ScanType>"
+ " <ScanResult><![CDATA[1]]></ScanResult>"
+ "</ScanCodeInfo>"
+ "<SendPicsInfo>"
+ " <Count>1</Count>\n"
+ " <PicList>"
+ " <item>"
+ " <PicMd5Sum><![CDATA[1b5f7c23b5bf75682a53e7b6d163e185]]></PicMd5Sum>"
+ " </item>"
+ " </PicList>"
+ "</SendPicsInfo>"
+ "<SendLocationInfo>"
+ " <Location_X><![CDATA[23]]></Location_X>\n"
+ " <Location_Y><![CDATA[113]]></Location_Y>\n"
+ " <Scale><![CDATA[15]]></Scale>\n"
+ " <Label><![CDATA[ 广州市海珠区客村艺苑路 106号]]></Label>\n"
+ " <Poiname><![CDATA[wo de poi]]></Poiname>\n"
+ "</SendLocationInfo>"
+ "</xml>";
WxMaMessage wxMessage = WxMaMessage.fromXml(xml);
assertEquals(wxMessage.getToUser(), "toUser");
assertEquals(wxMessage.getFromUser(), "fromUser");
assertEquals(wxMessage.getCreateTime(), new Integer(1348831860));
assertEquals(wxMessage.getMsgType(), WxConsts.XmlMsgType.TEXT);
assertEquals(wxMessage.getContent(), "this is a test");
assertEquals(wxMessage.getMsgId(), new Long(1234567890123456L));
assertEquals(wxMessage.getPicUrl(), "this is a url");
assertEquals(wxMessage.getMediaId(), "media_id");
assertEquals(wxMessage.getEvent(), "subscribe");
assertEquals(wxMessage.getTitle(), "Title");
assertEquals(wxMessage.getPagePath(), "PagePath");
assertEquals(wxMessage.getThumbUrl(), "ThumbUrl");
assertEquals(wxMessage.getThumbMediaId(), "ThumbMediaId");
assertEquals(wxMessage.getAppId(), "AppId");
assertEquals(wxMessage.getEvent(), "user_enter_tempsession");
assertEquals(wxMessage.getSessionFrom(), "sessionFrom");
}
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -0,0 +1,25 @@
package cn.binarywang.wx.miniapp.bean.code;
import org.testng.annotations.Test;
import static org.testng.Assert.assertEquals;
/**
* @author <a href="https://github.com/charmingoh">Charming</a>
* @since 2018-04-26 19:54
*/
public class WxMaCodeCommitRequestTest {
@Test
public void testToJson() {
WxMaCodeCommitRequest commitRequest = WxMaCodeCommitRequest.builder()
.templateId(1L)
.userVersion("v0.1.0")
.userDesc("init")
.extConfig(WxMaCodeExtConfig.builder()
.extAppid("app123")
.extEnable(true)
.build())
.build();
assertEquals(commitRequest.toJson(), "{\"template_id\":1,\"user_version\":\"v0.1.0\",\"user_desc\":\"init\",\"ext_json\":\"{\\\"extEnable\\\":true,\\\"extAppid\\\":\\\"app123\\\"}\"}");
}
}

View File

@@ -0,0 +1,30 @@
package cn.binarywang.wx.miniapp.bean.code;
import org.testng.annotations.Test;
import java.util.Arrays;
/**
* @author <a href="https://github.com/charmingoh">Charming</a>
* @since 2018-04-26 19:55
*/
public class WxMaCodeSubmitAuditRequestTest {
@Test
public void testToJson() {
WxMaCodeSubmitAuditRequest request = WxMaCodeSubmitAuditRequest
.builder()
.itemList(Arrays.asList(
WxMaCategory
.builder()
.address("pages/logs/logs")
.tag("工具 效率")
.firstClass("工具")
.firstId(287L)
.secondClass("效率")
.secondId(616L)
.title("日志")
.build()
)).build();
System.out.println(request.toJson());
}
}

View File

@@ -0,0 +1,15 @@
package cn.binarywang.wx.miniapp.bean.code;
import org.testng.annotations.Test;
/**
* @author <a href="https://github.com/charmingoh">Charming</a>
* @since 2018-04-26 19:58
*/
public class WxMaCodeVersionDistributionTest {
@Test
public void testFromJson() {
String json = "{\"errcode\":0,\"errmsg\":\"ok\",\"now_version\":\"1.2.0\",\"uv_info\":{\"items\":[{\"version\":\"0.0.0\",\"percentage\":0},{\"version\":\"1.0.0\",\"percentage\":0},{\"version\":\"1.0.1\",\"percentage\":0},{\"version\":\"1.1.0\",\"percentage\":0},{\"version\":\"1.1.1\",\"percentage\":0},{\"version\":\"1.2.0\",\"percentage\":0},{\"version\":\"1.2.1\",\"percentage\":0},{\"version\":\"1.2.2\",\"percentage\":0},{\"version\":\"1.2.3\",\"percentage\":0},{\"version\":\"1.2.4\",\"percentage\":0},{\"version\":\"1.2.5\",\"percentage\":0},{\"version\":\"1.2.6\",\"percentage\":0},{\"version\":\"1.3.0\",\"percentage\":0},{\"version\":\"1.4.0\",\"percentage\":0},{\"version\":\"1.4.1\",\"percentage\":0},{\"version\":\"1.4.2\",\"percentage\":0},{\"version\":\"1.4.3\",\"percentage\":0},{\"version\":\"1.4.4\",\"percentage\":0},{\"version\":\"1.5.0\",\"percentage\":0},{\"version\":\"1.5.1\",\"percentage\":0},{\"version\":\"1.5.2\",\"percentage\":0},{\"version\":\"1.5.3\",\"percentage\":0},{\"version\":\"1.5.4\",\"percentage\":0},{\"version\":\"1.5.5\",\"percentage\":0},{\"version\":\"1.5.6\",\"percentage\":0},{\"version\":\"1.5.7\",\"percentage\":0},{\"version\":\"1.5.8\",\"percentage\":0},{\"version\":\"1.6.0\",\"percentage\":0.0132},{\"version\":\"1.6.1\",\"percentage\":0.0132},{\"version\":\"1.6.2\",\"percentage\":0.0132},{\"version\":\"1.6.3\",\"percentage\":0.0132},{\"version\":\"1.6.4\",\"percentage\":0.0132},{\"version\":\"1.6.5\",\"percentage\":0.0132},{\"version\":\"1.6.6\",\"percentage\":0.0132},{\"version\":\"1.6.7\",\"percentage\":0.1711},{\"version\":\"1.6.8\",\"percentage\":0.1711},{\"version\":\"1.7.0\",\"percentage\":0.1842},{\"version\":\"1.7.1\",\"percentage\":0.25},{\"version\":\"1.7.2\",\"percentage\":0.5263},{\"version\":\"1.7.3\",\"percentage\":0.5263},{\"version\":\"1.7.4\",\"percentage\":0.6711}]}}\n";
System.out.println(WxMaCodeVersionDistribution.fromJson(json));
}
}

View File

@@ -12,7 +12,7 @@ import cn.binarywang.wx.miniapp.message.WxMaMessageRouter;
import cn.binarywang.wx.miniapp.test.TestConfig;
import com.google.common.collect.Lists;
import me.chanjar.weixin.common.bean.result.WxMediaUploadResult;
import me.chanjar.weixin.common.exception.WxErrorException;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.common.session.WxSessionManager;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.servlet.ServletHandler;

View File

@@ -1,22 +1,30 @@
package cn.binarywang.wx.miniapp.test;
import java.io.IOException;
import java.io.InputStream;
import java.util.concurrent.locks.ReentrantLock;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.config.WxMaConfig;
import com.google.inject.Binder;
import com.google.inject.Module;
import java.io.IOException;
import java.io.InputStream;
import java.util.concurrent.locks.ReentrantLock;
/**
* @author <a href="https://github.com/binarywang">Binary Wang</a>
*/
public class ApiTestModule implements Module {
private final Logger log = LoggerFactory.getLogger(this.getClass());
private static final String TEST_CONFIG_XML = "test-config.xml";
@Override
public void configure(Binder binder) {
try (InputStream inputStream = ClassLoader.getSystemResourceAsStream("test-config.xml")) {
try (InputStream inputStream = ClassLoader.getSystemResourceAsStream(TEST_CONFIG_XML)) {
if (inputStream == null) {
throw new RuntimeException("测试配置文件【" + TEST_CONFIG_XML + "】未找到请参照test-config-sample.xml文件生成");
}
TestConfig config = TestConfig.fromXml(inputStream);
config.setAccessTokenLock(new ReentrantLock());
@@ -26,7 +34,7 @@ public class ApiTestModule implements Module {
binder.bind(WxMaService.class).toInstance(wxService);
binder.bind(WxMaConfig.class).toInstance(config);
} catch (IOException e) {
e.printStackTrace();
this.log.error(e.getMessage(), e);
}
}