合并 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,28 @@
package me.chanjar.weixin.cp.api;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.cp.bean.WxCpAgent;
/**
* <pre>
* 管理企业号应用
* Created by huansinho on 2018/4/13.
* </pre>
*
* @author <a href="https://github.com/huansinho">huansinho</a>
*/
public interface WxCpAgentService {
/**
* <pre>
* 获取企业号应用信息
* 该API用于获取企业号某个应用的基本信息包括头像、昵称、帐号类型、认证类型、可见范围等信息
* 详情请见: http://qydev.weixin.qq.com/wiki/index.php?title=获取企业号应用
* </pre>
*
* @param agentId 企业应用的id
* @return 部门id
*/
WxCpAgent get(Integer agentId) throws WxErrorException;
}

View File

@@ -1,6 +1,6 @@
package me.chanjar.weixin.cp.api;
import me.chanjar.weixin.common.exception.WxErrorException;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.cp.bean.WxCpDepart;
import java.util.List;

View File

@@ -1,12 +1,12 @@
package me.chanjar.weixin.cp.api;
import me.chanjar.weixin.common.bean.result.WxMediaUploadResult;
import me.chanjar.weixin.common.exception.WxErrorException;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import me.chanjar.weixin.common.bean.result.WxMediaUploadResult;
import me.chanjar.weixin.common.error.WxErrorException;
/**
* <pre>
* 媒体管理接口
@@ -30,7 +30,7 @@ public interface WxCpMediaService {
*
* @param mediaType 媒体类型, 请看{@link me.chanjar.weixin.common.api.WxConsts}
* @param fileType 文件类型,请看{@link me.chanjar.weixin.common.api.WxConsts}
* @param inputStream 输入流
* @param inputStream 输入流,需要调用方控制关闭该输入流
*/
WxMediaUploadResult upload(String mediaType, String fileType, InputStream inputStream)
throws WxErrorException, IOException;

View File

@@ -1,7 +1,7 @@
package me.chanjar.weixin.cp.api;
import me.chanjar.weixin.common.bean.menu.WxMenu;
import me.chanjar.weixin.common.exception.WxErrorException;
import me.chanjar.weixin.common.error.WxErrorException;
/**
* <pre>

View File

@@ -1,6 +1,7 @@
package me.chanjar.weixin.cp.api;
import me.chanjar.weixin.common.exception.WxErrorException;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.cp.bean.WxCpUserDetail;
/**
* <pre>
@@ -64,4 +65,19 @@ public interface WxCpOAuth2Service {
*/
String[] getUserInfo(Integer agentId, String code) throws WxErrorException;
/**
* <pre>
* 使用user_ticket获取成员详情.
*
* 文档地址https://work.weixin.qq.com/api/doc#10028/%E4%BD%BF%E7%94%A8user_ticket%E8%8E%B7%E5%8F%96%E6%88%90%E5%91%98%E8%AF%A6%E6%83%85
* 请求方式POSTHTTPS
* 请求地址https://qyapi.weixin.qq.com/cgi-bin/user/getuserdetail?access_token=ACCESS_TOKEN
*
* 权限说明:
* 需要有对应应用的使用权限,且成员必须在授权应用的可见范围内。
* </pre>
*
* @param userTicket 成员票据
*/
WxCpUserDetail getUserDetail(String userTicket) throws WxErrorException;
}

View File

@@ -1,9 +1,7 @@
package me.chanjar.weixin.cp.api;
import me.chanjar.weixin.common.bean.WxJsapiSignature;
import me.chanjar.weixin.common.bean.menu.WxMenu;
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.WxSession;
import me.chanjar.weixin.common.session.WxSessionManager;
import me.chanjar.weixin.common.util.http.MediaUploadRequestExecutor;
@@ -12,11 +10,6 @@ import me.chanjar.weixin.common.util.http.RequestHttp;
import me.chanjar.weixin.cp.bean.*;
import me.chanjar.weixin.cp.config.WxCpConfigStorage;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
/**
* 微信API的Service
* @author chanjaster
@@ -249,6 +242,8 @@ public interface WxCpService {
*/
WxCpUserService getUserService();
WxCpAgentService getAgentService();
/**
* http请求对象
*/

View File

@@ -1,15 +1,16 @@
package me.chanjar.weixin.cp.api;
import me.chanjar.weixin.common.exception.WxErrorException;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.cp.bean.WxCpTag;
import me.chanjar.weixin.cp.bean.WxCpTagAddOrRemoveUsersResult;
import me.chanjar.weixin.cp.bean.WxCpTagGetResult;
import me.chanjar.weixin.cp.bean.WxCpUser;
import java.util.List;
/**
* <pre>
* 标签管理接口
* 标签管理接口.
* Created by BinaryWang on 2017/6/24.
* </pre>
*
@@ -17,14 +18,14 @@ import java.util.List;
*/
public interface WxCpTagService {
/**
* 创建标签
* 创建标签.
*
* @param tagName 标签名
*/
String create(String tagName) throws WxErrorException;
/**
* 更新标签
* 更新标签.
*
* @param tagId 标签id
* @param tagName 标签名
@@ -32,35 +33,49 @@ public interface WxCpTagService {
void update(String tagId, String tagName) throws WxErrorException;
/**
* 删除标签
* 删除标签.
*
* @param tagId 标签id
*/
void delete(String tagId) throws WxErrorException;
/**
* 获得标签列表
* 获得标签列表.
*/
List<WxCpTag> listAll() throws WxErrorException;
/**
* 获取标签成员
* 获取标签成员.
*
* @param tagId 标签ID
*/
List<WxCpUser> listUsersByTagId(String tagId) throws WxErrorException;
/**
* 增加标签成员
* @param tagId 标签id
* @param userIds 用户ID 列表
* 增加标签成员.
*
* @param tagId 标签id
* @param userIds 用户ID 列表
* @param partyIds 企业部门ID列表
*/
WxCpTagAddOrRemoveUsersResult addUsers2Tag(String tagId, List<String> userIds, List<String> partyIds) throws WxErrorException;
/**
* 移除标签成员
* @param tagId 标签id
* @param userIds 用户id列表
* 移除标签成员.
*
* @param tagId 标签id
* @param userIds 用户id列表
* @param partyIds 企业部门ID列表
*/
WxCpTagAddOrRemoveUsersResult removeUsersFromTag(String tagId, List<String> userIds) throws WxErrorException;
WxCpTagAddOrRemoveUsersResult removeUsersFromTag(String tagId, List<String> userIds, List<String> partyIds) throws WxErrorException;
/**
* 获取标签成员.
* 对应: http://qydev.weixin.qq.com/wiki/index.php?title=管理标签 中的get接口
*
* @param tagId 标签id
*/
WxCpTagGetResult get(String tagId) throws WxErrorException;
}

View File

@@ -1,6 +1,7 @@
package me.chanjar.weixin.cp.api;
import me.chanjar.weixin.common.exception.WxErrorException;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.cp.bean.WxCpInviteResult;
import me.chanjar.weixin.cp.bean.WxCpUser;
import java.util.List;
@@ -84,18 +85,18 @@ public interface WxCpUserService {
/**
* <pre>
* 邀请成员关注
* http://qydev.weixin.qq.com/wiki/index.php?title=管理成员#.E9.82.80.E8.AF.B7.E6.88.90.E5.91.98.E5.85.B3.E6.B3.A8
* 邀请成员
* 企业可通过接口批量邀请成员使用企业微信,邀请后将通过短信或邮件下发通知。
* 请求方式POSTHTTPS
* 请求地址: https://qyapi.weixin.qq.com/cgi-bin/batch/invite?access_token=ACCESS_TOKEN
* 文档地址https://work.weixin.qq.com/api/doc#12543
* </pre>
*
* @param userId 用户的userid
* @param inviteTips 推送到微信上的提示语只有认证号可以使用。当使用微信推送时该字段默认为“请关注XXX企业号”邮件邀请时该字段无效
* @return 1:微信邀请 2.邮件邀请
* @deprecated api obsoleted. 邀请关注的功能微信企业号已经下线了,
* 详细请参考该链接点击查看 https://qy.weixin.qq.com/cgi-bin/homepagenotify?action=get&id=46
* @param userIds 成员ID列表, 最多支持1000个。
* @param partyIds 部门ID列表最多支持100个
* @param tagIds 标签ID列表最多支持100个。
*/
@Deprecated
int invite(String userId, String inviteTips) throws WxErrorException;
WxCpInviteResult invite(List<String> userIds, List<String> partyIds, List<String> tagIds) throws WxErrorException;
/**
* <pre>

View File

@@ -0,0 +1,37 @@
package me.chanjar.weixin.cp.api.impl;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.cp.api.WxCpAgentService;
import me.chanjar.weixin.cp.api.WxCpService;
import me.chanjar.weixin.cp.bean.WxCpAgent;
/**
* <pre>
* 管理企业号应用
* Created by huansinho on 2018/4/13.
* </pre>
*
* @author <a href="https://github.com/huansinho">huansinho</a>
*/
public class WxCpAgentServiceImpl implements WxCpAgentService {
private WxCpService mainService;
public WxCpAgentServiceImpl(WxCpService mainService) {
this.mainService = mainService;
}
@Override
public WxCpAgent get(Integer agentId) throws WxErrorException {
String url = "https://qyapi.weixin.qq.com/cgi-bin/agent/get";
if (agentId != null) {
url += "?agentid=" + agentId;
} else {
throw new IllegalArgumentException("缺少agentid参数");
}
String responseContent = this.mainService.get(url, null);
return WxCpAgent.fromJson(responseContent);
}
}

View File

@@ -3,7 +3,7 @@ package me.chanjar.weixin.cp.api.impl;
import com.google.gson.JsonElement;
import com.google.gson.JsonParser;
import com.google.gson.reflect.TypeToken;
import me.chanjar.weixin.common.exception.WxErrorException;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.common.util.json.GsonHelper;
import me.chanjar.weixin.cp.api.WxCpDepartmentService;
import me.chanjar.weixin.cp.api.WxCpService;

View File

@@ -1,7 +1,7 @@
package me.chanjar.weixin.cp.api.impl;
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

@@ -1,7 +1,7 @@
package me.chanjar.weixin.cp.api.impl;
import me.chanjar.weixin.common.bean.menu.WxMenu;
import me.chanjar.weixin.common.exception.WxErrorException;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.cp.api.WxCpMenuService;
import me.chanjar.weixin.cp.api.WxCpService;
import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder;

View File

@@ -1,13 +1,15 @@
package me.chanjar.weixin.cp.api.impl;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import me.chanjar.weixin.common.exception.WxErrorException;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.common.util.http.URIUtil;
import me.chanjar.weixin.common.util.json.GsonHelper;
import me.chanjar.weixin.cp.api.WxCpOAuth2Service;
import me.chanjar.weixin.cp.api.WxCpService;
import me.chanjar.weixin.cp.bean.WxCpUserDetail;
/**
* <pre>
@@ -52,9 +54,8 @@ public class WxCpOAuth2ServiceImpl implements WxCpOAuth2Service {
@Override
public String[] getUserInfo(Integer agentId, String code) throws WxErrorException {
String url = "https://qyapi.weixin.qq.com/cgi-bin/user/getuserinfo?"
+ "code=" + code
+ "&agentid=" + agentId;
String url = String.format("https://qyapi.weixin.qq.com/cgi-bin/user/getuserinfo?code=%s&agentid=%d",
code, agentId);
String responseText = this.mainService.get(url, null);
JsonElement je = new JsonParser().parse(responseText);
JsonObject jo = je.getAsJsonObject();
@@ -63,4 +64,12 @@ public class WxCpOAuth2ServiceImpl implements WxCpOAuth2Service {
GsonHelper.getString(jo, "OpenId")};
}
@Override
public WxCpUserDetail getUserDetail(String userTicket) throws WxErrorException {
String url = "https://qyapi.weixin.qq.com/cgi-bin/user/getuserdetail";
JsonObject param = new JsonObject();
param.addProperty("user_ticket", userTicket);
String responseText = this.mainService.post(url, param.toString());
return new GsonBuilder().create().fromJson(responseText, WxCpUserDetail.class);
}
}

View File

@@ -5,13 +5,12 @@ import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import me.chanjar.weixin.common.bean.WxJsapiSignature;
import me.chanjar.weixin.common.bean.menu.WxMenu;
import me.chanjar.weixin.common.bean.result.WxError;
import me.chanjar.weixin.common.bean.result.WxMediaUploadResult;
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.session.StandardSessionManager;
import me.chanjar.weixin.common.session.WxSession;
import me.chanjar.weixin.common.session.WxSessionManager;
import me.chanjar.weixin.common.util.DataUtils;
import me.chanjar.weixin.common.util.RandomUtils;
import me.chanjar.weixin.common.util.crypto.SHA1;
import me.chanjar.weixin.common.util.http.RequestExecutor;
@@ -21,14 +20,11 @@ import me.chanjar.weixin.common.util.http.SimplePostRequestExecutor;
import me.chanjar.weixin.cp.api.*;
import me.chanjar.weixin.cp.bean.*;
import me.chanjar.weixin.cp.config.WxCpConfigStorage;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
public abstract class WxCpServiceAbstractImpl<H, P> implements WxCpService, RequestHttp<H, P> {
protected final Logger log = LoggerFactory.getLogger(this.getClass());
@@ -39,6 +35,7 @@ public abstract class WxCpServiceAbstractImpl<H, P> implements WxCpService, Requ
private WxCpMenuService menuService = new WxCpMenuServiceImpl(this);
private WxCpOAuth2Service oauth2Service = new WxCpOAuth2ServiceImpl(this);
private WxCpTagService tagService = new WxCpTagServiceImpl(this);
private WxCpAgentService agentService = new WxCpAgentServiceImpl(this);
/**
* 全局的是否正在刷新access token的锁
@@ -200,6 +197,8 @@ public abstract class WxCpServiceAbstractImpl<H, P> implements WxCpService, Requ
}
protected <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);
}
@@ -209,7 +208,7 @@ public abstract class WxCpServiceAbstractImpl<H, P> implements WxCpService, Requ
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();
@@ -226,12 +225,12 @@ public abstract class WxCpServiceAbstractImpl<H, P> implements WxCpService, Requ
}
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);
}
}
@@ -368,4 +367,13 @@ public abstract class WxCpServiceAbstractImpl<H, P> implements WxCpService, Requ
public void setTagService(WxCpTagService tagService) {
this.tagService = tagService;
}
@Override
public WxCpAgentService getAgentService() {
return agentService;
}
public void setAgentService(WxCpAgentService agentService) {
this.agentService = agentService;
}
}

View File

@@ -1,9 +1,10 @@
package me.chanjar.weixin.cp.api.impl;
import me.chanjar.weixin.common.WxType;
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.error.WxError;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.common.util.http.HttpType;
import me.chanjar.weixin.common.util.http.apache.ApacheHttpClientBuilder;
import me.chanjar.weixin.common.util.http.apache.DefaultApacheHttpClientBuilder;
@@ -58,7 +59,7 @@ public class WxCpServiceApacheHttpClientImpl extends WxCpServiceAbstractImpl<Clo
} finally {
httpGet.releaseConnection();
}
WxError error = WxError.fromJson(resultContent);
WxError error = WxError.fromJson(resultContent, WxType.CP);
if (error.getErrorCode() != 0) {
throw new WxErrorException(error);
}

View File

@@ -1,9 +1,10 @@
package me.chanjar.weixin.cp.api.impl;
import jodd.http.*;
import me.chanjar.weixin.common.WxType;
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.error.WxError;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.common.util.http.HttpType;
import me.chanjar.weixin.cp.config.WxCpConfigStorage;
@@ -44,7 +45,7 @@ public class WxCpServiceJoddHttpImpl extends WxCpServiceAbstractImpl<HttpConnect
HttpResponse response = request.send();
String resultContent = response.bodyText();
WxError error = WxError.fromJson(resultContent);
WxError error = WxError.fromJson(resultContent, WxType.CP);
if (error.getErrorCode() != 0) {
throw new WxErrorException(error);
}

View File

@@ -1,8 +1,9 @@
package me.chanjar.weixin.cp.api.impl;
import me.chanjar.weixin.common.WxType;
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.error.WxError;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.common.util.http.HttpType;
import me.chanjar.weixin.common.util.http.okhttp.OkHttpProxyInfo;
import me.chanjar.weixin.cp.config.WxCpConfigStorage;
@@ -51,7 +52,7 @@ public class WxCpServiceOkHttpImpl extends WxCpServiceAbstractImpl<OkHttpClient,
this.log.error(e.getMessage(), e);
}
WxError error = WxError.fromJson(resultContent);
WxError error = WxError.fromJson(resultContent, WxType.CP);
if (error.getErrorCode() != 0) {
throw new WxErrorException(error);
}

View File

@@ -2,11 +2,12 @@ package me.chanjar.weixin.cp.api.impl;
import com.google.gson.*;
import com.google.gson.reflect.TypeToken;
import me.chanjar.weixin.common.exception.WxErrorException;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.cp.api.WxCpService;
import me.chanjar.weixin.cp.api.WxCpTagService;
import me.chanjar.weixin.cp.bean.WxCpTag;
import me.chanjar.weixin.cp.bean.WxCpTagAddOrRemoveUsersResult;
import me.chanjar.weixin.cp.bean.WxCpTagGetResult;
import me.chanjar.weixin.cp.bean.WxCpUser;
import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder;
@@ -82,6 +83,22 @@ public class WxCpTagServiceImpl implements WxCpTagService {
String url = "https://qyapi.weixin.qq.com/cgi-bin/tag/addtagusers";
JsonObject jsonObject = new JsonObject();
jsonObject.addProperty("tagid", tagId);
this.addUserIdsAndPartyIdsToJson(userIds, partyIds, jsonObject);
return WxCpTagAddOrRemoveUsersResult.fromJson(this.mainService.post(url, jsonObject.toString()));
}
@Override
public WxCpTagAddOrRemoveUsersResult removeUsersFromTag(String tagId, List<String> userIds, List<String> partyIds) throws WxErrorException {
String url = "https://qyapi.weixin.qq.com/cgi-bin/tag/deltagusers";
JsonObject jsonObject = new JsonObject();
jsonObject.addProperty("tagid", tagId);
this.addUserIdsAndPartyIdsToJson(userIds, partyIds, jsonObject);
return WxCpTagAddOrRemoveUsersResult.fromJson(this.mainService.post(url, jsonObject.toString()));
}
private void addUserIdsAndPartyIdsToJson(List<String> userIds, List<String> partyIds, JsonObject jsonObject) {
if (userIds != null) {
JsonArray jsonArray = new JsonArray();
for (String userId : userIds) {
@@ -89,6 +106,7 @@ public class WxCpTagServiceImpl implements WxCpTagService {
}
jsonObject.add("userlist", jsonArray);
}
if (partyIds != null) {
JsonArray jsonArray = new JsonArray();
for (String userId : partyIds) {
@@ -96,21 +114,19 @@ public class WxCpTagServiceImpl implements WxCpTagService {
}
jsonObject.add("partylist", jsonArray);
}
return WxCpTagAddOrRemoveUsersResult.fromJson(this.mainService.post(url, jsonObject.toString()));
}
@Override
public WxCpTagAddOrRemoveUsersResult removeUsersFromTag(String tagId, List<String> userIds) throws WxErrorException {
String url = "https://qyapi.weixin.qq.com/cgi-bin/tag/deltagusers";
JsonObject jsonObject = new JsonObject();
jsonObject.addProperty("tagid", tagId);
JsonArray jsonArray = new JsonArray();
for (String userId : userIds) {
jsonArray.add(new JsonPrimitive(userId));
public WxCpTagGetResult get(String tagId) throws WxErrorException {
String url = "https://qyapi.weixin.qq.com/cgi-bin/tag/get";
if (tagId != null) {
url += "?tagId=" + tagId;
} else {
throw new IllegalArgumentException("缺少tagId参数");
}
jsonObject.add("userlist", jsonArray);
return WxCpTagAddOrRemoveUsersResult.fromJson(this.mainService.post(url, jsonObject.toString()));
String responseContent = this.mainService.get(url, null);
return WxCpTagGetResult.fromJson(responseContent);
}
}

View File

@@ -3,12 +3,12 @@ package me.chanjar.weixin.cp.api.impl;
import com.google.common.collect.Maps;
import com.google.gson.*;
import com.google.gson.reflect.TypeToken;
import me.chanjar.weixin.common.exception.WxErrorException;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.cp.api.WxCpService;
import me.chanjar.weixin.cp.api.WxCpUserService;
import me.chanjar.weixin.cp.bean.WxCpInviteResult;
import me.chanjar.weixin.cp.bean.WxCpUser;
import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder;
import org.apache.commons.lang3.StringUtils;
import java.util.List;
import java.util.Map;
@@ -116,17 +116,34 @@ public class WxCpUserServiceImpl implements WxCpUserService {
}
@Override
@Deprecated
public int invite(String userId, String inviteTips) throws WxErrorException {
String url = "https://qyapi.weixin.qq.com/cgi-bin/invite/send";
public WxCpInviteResult invite(List<String> userIds, List<String> partyIds, List<String> tagIds) throws WxErrorException {
String url = "https://qyapi.weixin.qq.com/cgi-bin/batch/invite";
JsonObject jsonObject = new JsonObject();
jsonObject.addProperty("userid", userId);
if (StringUtils.isNotEmpty(inviteTips)) {
jsonObject.addProperty("invite_tips", inviteTips);
if (userIds != null) {
JsonArray jsonArray = new JsonArray();
for (String userId : userIds) {
jsonArray.add(new JsonPrimitive(userId));
}
jsonObject.add("user", jsonArray);
}
String responseContent = this.mainService.post(url, jsonObject.toString());
JsonElement tmpJsonElement = new JsonParser().parse(responseContent);
return tmpJsonElement.getAsJsonObject().get("type").getAsInt();
if (partyIds != null) {
JsonArray jsonArray = new JsonArray();
for (String userId : partyIds) {
jsonArray.add(new JsonPrimitive(userId));
}
jsonObject.add("party", jsonArray);
}
if (tagIds != null) {
JsonArray jsonArray = new JsonArray();
for (String tagId : tagIds) {
jsonArray.add(new JsonPrimitive(tagId));
}
jsonObject.add("tag", jsonArray);
}
return WxCpInviteResult.fromJson(this.mainService.post(url, jsonObject.toString()));
}
@Override

View File

@@ -0,0 +1,47 @@
package me.chanjar.weixin.cp.bean;
/**
* <pre>
* 性别枚举
* Created by BinaryWang on 2018/4/22.
* </pre>
*
* @author <a href="https://github.com/binarywang">Binary Wang</a>
*/
public enum Gender {
/**
* 男
*/
MALE("", "1"),
/**
* 女
*/
FEMALE("", "2");
private String genderName;
private String code;
Gender(String genderName, String code) {
this.genderName = genderName;
this.code = code;
}
public String getGenderName() {
return this.genderName;
}
public String getCode() {
return this.code;
}
public static Gender fromCode(String code) {
if ("1".equals(code)) {
return Gender.MALE;
}
if ("2".equals(code)) {
return Gender.FEMALE;
}
return null;
}
}

View File

@@ -0,0 +1,96 @@
package me.chanjar.weixin.cp.bean;
import com.google.gson.annotations.SerializedName;
import lombok.Data;
import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder;
import java.io.Serializable;
import java.util.List;
/**
* <pre>
* 企业号应用信息.
* Created by huansinho on 2018/4/13.
* </pre>
*
* @author <a href="https://github.com/huansinho">huansinho</a>
*/
@Data
public class WxCpAgent implements Serializable {
@SerializedName("errcode")
private Integer errcode;
@SerializedName("errmsg")
private String errmsg;
@SerializedName("agentid")
private Integer agentid;
@SerializedName("name")
private String name;
@SerializedName("square_logo_url")
private String squareLogoUrl;
@SerializedName("description")
private String description;
@SerializedName("allow_userinfos")
private Users allowUserinfos;
@SerializedName("allow_partys")
private Partys allowPartys;
@SerializedName("allow_tags")
private Tags allowTags;
@SerializedName("close")
private Integer close;
@SerializedName("redirect_domain")
private String redirectDomain;
@SerializedName("report_location_flag")
private Integer reportLocationFlag;
@SerializedName("isreportenter")
private Integer isreportenter;
@SerializedName("home_url")
private String homeUrl;
public static WxCpAgent fromJson(String json) {
return WxCpGsonBuilder.create().fromJson(json, WxCpAgent.class);
}
public String toJson() {
return WxCpGsonBuilder.create().toJson(this);
}
@Data
public static class Users implements Serializable {
@SerializedName("user")
private List<User> user;
}
@Data
public class User implements Serializable {
@SerializedName("userid")
private String userid;
}
@Data
public class Partys {
@SerializedName("partyid")
private List<Integer> partyids = null;
}
@Data
public class Tags {
@SerializedName("tagid")
private List<Integer> tagids = null;
}
}

View File

@@ -0,0 +1,60 @@
package me.chanjar.weixin.cp.bean;
import com.google.common.base.Splitter;
import com.google.gson.annotations.SerializedName;
import lombok.Data;
import me.chanjar.weixin.common.util.ToStringUtils;
import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder;
import org.apache.commons.lang3.StringUtils;
import java.io.Serializable;
import java.util.Collections;
import java.util.List;
/**
* 邀请成员的结果对象类.
* Created by Binary Wang on 2018-5-13.
*
* @author <a href="https://github.com/binarywang">Binary Wang</a>
*/
@Data
public class WxCpInviteResult implements Serializable {
private static final long serialVersionUID = 1420065684270213578L;
@Override
public String toString() {
return ToStringUtils.toSimpleString(this);
}
public static WxCpInviteResult fromJson(String json) {
return WxCpGsonBuilder.INSTANCE.create().fromJson(json, WxCpInviteResult.class);
}
@SerializedName("errcode")
private Integer errCode;
@SerializedName("errmsg")
private String errMsg;
@SerializedName("invaliduser")
private String invalidUsers;
@SerializedName("invalidparty")
private String[] invalidParties;
@SerializedName("invalidtag")
private String[] invalidTags;
public List<String> getInvalidUserList() {
return this.content2List(this.invalidUsers);
}
private List<String> content2List(String content) {
if (StringUtils.isBlank(content)) {
return Collections.emptyList();
}
return Splitter.on("|").splitToList(content);
}
}

View File

@@ -34,6 +34,7 @@ public class WxCpMessage implements Serializable {
private String hqMusicUrl;
private String safe;
private String url;
private String btnTxt;
private List<NewArticle> articles = new ArrayList<>();
private List<MpnewsArticle> mpnewsArticles = new ArrayList<>();

View File

@@ -0,0 +1,57 @@
package me.chanjar.weixin.cp.bean;
import com.google.gson.annotations.SerializedName;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder;
import java.io.Serializable;
import java.util.List;
/**
* <pre>
* 管理企业号应用-测试
* Created by huansinho on 2018/4/16.
* </pre>
*
* @author <a href="https://github.com/huansinho">huansinho</a>
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class WxCpTagGetResult implements Serializable {
@SerializedName("errcode")
private Integer errcode;
@SerializedName("errmsg")
private String errmsg;
/**
* 用户列表
*/
@SerializedName("userlist")
private List<WxCpUser> userlist;
/**
* 部门列表
*/
@SerializedName("partylist")
private List<Integer> partylist;
/**
* 标签名称
*/
@SerializedName("tagname")
private String tagname;
public static WxCpTagGetResult fromJson(String json) {
return WxCpGsonBuilder.create().fromJson(json, WxCpTagGetResult.class);
}
public String toJson() {
return WxCpGsonBuilder.create().toJson(this);
}
}

View File

@@ -15,44 +15,6 @@ import java.util.List;
*/
@Data
public class WxCpUser implements Serializable {
public enum Gender {
/**
* 男
*/
MALE("", "1"),
/**
* 女
*/
FEMALE("", "2");
private String genderName;
private String code;
Gender(String genderName, String code) {
this.genderName = genderName;
this.code = code;
}
public String getGenderName() {
return this.genderName;
}
public String getCode() {
return this.code;
}
public static Gender fromCode(String code) {
if ("1".equals(code)) {
return Gender.MALE;
}
if ("2".equals(code)) {
return Gender.FEMALE;
}
return null;
}
}
private static final long serialVersionUID = -5696099236344075582L;
private String userId;
private String name;
@@ -69,6 +31,8 @@ public class WxCpUser implements Serializable {
private Integer hideMobile;
private String englishName;
private String telephone;
private String qrCode;
private Boolean toInvite;
public void addExtAttr(String name, String value) {
this.extAttrs.add(new Attr(name, value));

View File

@@ -0,0 +1,24 @@
package me.chanjar.weixin.cp.bean;
import com.google.gson.annotations.SerializedName;
import lombok.Data;
/**
* <pre>
* 使用user_ticket获取成员详情接口返回类.
* Created by BinaryWang on 2018/4/22.
* </pre>
*
* @author <a href="https://github.com/binarywang">Binary Wang</a>
*/
@Data
public class WxCpUserDetail {
@SerializedName("userid")
private String userId;
private String name;
private String mobile;
private String gender;
private String email;
@SerializedName("qrCode")
private String qrCode;
}

View File

@@ -3,6 +3,7 @@ package me.chanjar.weixin.cp.bean;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import com.thoughtworks.xstream.annotations.XStreamConverter;
import lombok.Data;
import lombok.EqualsAndHashCode;
import me.chanjar.weixin.common.api.WxConsts;
import me.chanjar.weixin.common.util.xml.XStreamCDataConverter;
@@ -11,6 +12,7 @@ import java.util.List;
@XStreamAlias("xml")
@Data
@EqualsAndHashCode(callSuper = true)
public class WxCpXmlOutNewsMessage extends WxCpXmlOutMessage {
private static final long serialVersionUID = -5796178637883178826L;

View File

@@ -16,6 +16,7 @@ public class TextCardBuilder extends BaseBuilder<TextCardBuilder> {
private String title;
private String description;
private String url;
private String btnTxt;
public TextCardBuilder() {
this.msgType = WxConsts.KefuMsgType.TEXTCARD;
@@ -36,12 +37,18 @@ public class TextCardBuilder extends BaseBuilder<TextCardBuilder> {
return this;
}
public TextCardBuilder btnTxt(String btnTxt) {
this.btnTxt = btnTxt;
return this;
}
@Override
public WxCpMessage build() {
WxCpMessage m = super.build();
m.setTitle(this.title);
m.setDescription(this.description);
m.setUrl(this.url);
m.setBtnTxt(this.btnTxt);
return m;
}
}

View File

@@ -1,6 +1,6 @@
package me.chanjar.weixin.cp.message;
import me.chanjar.weixin.common.exception.WxErrorException;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.common.session.WxSessionManager;
import me.chanjar.weixin.cp.api.WxCpService;
import me.chanjar.weixin.cp.bean.WxCpXmlMessage;

View File

@@ -1,6 +1,6 @@
package me.chanjar.weixin.cp.message;
import me.chanjar.weixin.common.exception.WxErrorException;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.common.session.WxSessionManager;
import me.chanjar.weixin.cp.api.WxCpService;
import me.chanjar.weixin.cp.bean.WxCpXmlMessage;

View File

@@ -1,7 +1,7 @@
package me.chanjar.weixin.cp.message;
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 me.chanjar.weixin.cp.api.WxCpService;
import me.chanjar.weixin.cp.bean.WxCpXmlMessage;

View File

@@ -3,7 +3,7 @@ package me.chanjar.weixin.cp.util.json;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import me.chanjar.weixin.common.bean.menu.WxMenu;
import me.chanjar.weixin.common.bean.result.WxError;
import me.chanjar.weixin.common.error.WxError;
import me.chanjar.weixin.common.util.json.WxErrorAdapter;
import me.chanjar.weixin.cp.bean.WxCpDepart;
import me.chanjar.weixin.cp.bean.WxCpMessage;

View File

@@ -48,6 +48,7 @@ public class WxCpMessageGsonAdapter implements JsonSerializer<WxCpMessage> {
text.addProperty("title", message.getTitle());
text.addProperty("description", message.getDescription());
text.addProperty("url", message.getUrl());
text.addProperty("btntxt", message.getBtnTxt());
messageJson.add("textcard", text);
}

View File

@@ -10,6 +10,7 @@ package me.chanjar.weixin.cp.util.json;
import com.google.gson.*;
import me.chanjar.weixin.common.util.json.GsonHelper;
import me.chanjar.weixin.cp.bean.Gender;
import me.chanjar.weixin.cp.bean.WxCpUser;
import java.lang.reflect.Type;
@@ -39,7 +40,7 @@ public class WxCpUserGsonAdapter implements JsonDeserializer<WxCpUser>, JsonSeri
user.setName(GsonHelper.getString(o, "name"));
user.setPosition(GsonHelper.getString(o, "position"));
user.setMobile(GsonHelper.getString(o, "mobile"));
user.setGender(WxCpUser.Gender.fromCode(GsonHelper.getString(o, "gender")));
user.setGender(Gender.fromCode(GsonHelper.getString(o, "gender")));
user.setEmail(GsonHelper.getString(o, "email"));
user.setAvatar(GsonHelper.getString(o, "avatar"));
user.setStatus(GsonHelper.getInteger(o, "status"));
@@ -48,6 +49,8 @@ public class WxCpUserGsonAdapter implements JsonDeserializer<WxCpUser>, JsonSeri
user.setHideMobile(GsonHelper.getInteger(o, "hide_mobile"));
user.setEnglishName(GsonHelper.getString(o, "english_name"));
user.setTelephone(GsonHelper.getString(o, "telephone"));
user.setQrCode(GsonHelper.getString(o, "qr_code"));
user.setToInvite(GsonHelper.getBoolean(o, "to_invite"));
if (GsonHelper.isNotNull(o.get("extattr"))) {
JsonArray attrJsonElements = o.get("extattr").getAsJsonObject().get("attrs").getAsJsonArray();
@@ -111,6 +114,13 @@ public class WxCpUserGsonAdapter implements JsonDeserializer<WxCpUser>, JsonSeri
if (user.getTelephone() != null) {
o.addProperty("telephone", user.getTelephone());
}
if (user.getQrCode() != null) {
o.addProperty("qr_code", user.getQrCode());
}
if (user.getToInvite() != null) {
o.addProperty("to_invite", user.getToInvite());
}
if (user.getExtAttrs().size() > 0) {
JsonArray attrsJsonArray = new JsonArray();
for (WxCpUser.Attr attr : user.getExtAttrs()) {

View File

@@ -63,7 +63,6 @@ public class XStreamTransformer {
private static XStream configWxCpXmlMessage() {
XStream xstream = XStreamInitializer.getInstance();
xstream.setClassLoader(Thread.currentThread().getContextClassLoader());
xstream.processAnnotations(WxCpXmlMessage.class);
xstream.processAnnotations(WxCpXmlMessage.ScanCodeInfo.class);
@@ -75,7 +74,6 @@ public class XStreamTransformer {
private static XStream configWxCpXmlOutImageMessage() {
XStream xstream = XStreamInitializer.getInstance();
xstream.setClassLoader(Thread.currentThread().getContextClassLoader());
xstream.processAnnotations(WxCpXmlOutMessage.class);
xstream.processAnnotations(WxCpXmlOutImageMessage.class);
@@ -84,7 +82,6 @@ public class XStreamTransformer {
private static XStream configWxCpXmlOutNewsMessage() {
XStream xstream = XStreamInitializer.getInstance();
xstream.setClassLoader(Thread.currentThread().getContextClassLoader());
xstream.processAnnotations(WxCpXmlOutMessage.class);
xstream.processAnnotations(WxCpXmlOutNewsMessage.class);
@@ -94,7 +91,6 @@ public class XStreamTransformer {
private static XStream configWxCpXmlOutTextMessage() {
XStream xstream = XStreamInitializer.getInstance();
xstream.setClassLoader(Thread.currentThread().getContextClassLoader());
xstream.processAnnotations(WxCpXmlOutMessage.class);
xstream.processAnnotations(WxCpXmlOutTextMessage.class);
@@ -103,7 +99,6 @@ public class XStreamTransformer {
private static XStream configWxCpXmlOutVideoMessage() {
XStream xstream = XStreamInitializer.getInstance();
xstream.setClassLoader(Thread.currentThread().getContextClassLoader());
xstream.processAnnotations(WxCpXmlOutMessage.class);
xstream.processAnnotations(WxCpXmlOutVideoMessage.class);
@@ -113,7 +108,6 @@ public class XStreamTransformer {
private static XStream configWxCpXmlOutVoiceMessage() {
XStream xstream = XStreamInitializer.getInstance();
xstream.setClassLoader(Thread.currentThread().getContextClassLoader());
xstream.processAnnotations(WxCpXmlOutMessage.class);
xstream.processAnnotations(WxCpXmlOutVoiceMessage.class);

View File

@@ -1,20 +1,24 @@
package me.chanjar.weixin.cp.api;
import java.io.IOException;
import java.io.InputStream;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.inject.Binder;
import com.google.inject.Module;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import me.chanjar.weixin.common.util.xml.XStreamInitializer;
import me.chanjar.weixin.cp.api.impl.WxCpServiceImpl;
import me.chanjar.weixin.cp.config.WxCpConfigStorage;
import me.chanjar.weixin.cp.config.WxCpInMemoryConfigStorage;
import java.io.IOException;
import java.io.InputStream;
public class ApiTestModule implements Module {
private final Logger log = LoggerFactory.getLogger(this.getClass());
private static final String TEST_CONFIG_XML = "test-config.xml";
public static <T> T fromXml(Class<T> clazz, InputStream is) {
private static <T> T fromXml(Class<T> clazz, InputStream is) {
XStream xstream = XStreamInitializer.getInstance();
xstream.alias("xml", clazz);
xstream.processAnnotations(clazz);
@@ -23,17 +27,19 @@ public class ApiTestModule implements Module {
@Override
public void configure(Binder binder) {
try (InputStream is1 = ClassLoader
.getSystemResourceAsStream("test-config.xml")) {
WxXmlCpInMemoryConfigStorage config = fromXml(
WxXmlCpInMemoryConfigStorage.class, is1);
try (InputStream inputStream = ClassLoader.getSystemResourceAsStream(TEST_CONFIG_XML)) {
if (inputStream == null) {
throw new RuntimeException("测试配置文件【" + TEST_CONFIG_XML + "】未找到请参照test-config-sample.xml文件生成");
}
WxXmlCpInMemoryConfigStorage config = fromXml(WxXmlCpInMemoryConfigStorage.class, inputStream);
WxCpService wxService = new WxCpServiceImpl();
wxService.setWxCpConfigStorage(config);
binder.bind(WxCpService.class).toInstance(wxService);
binder.bind(WxXmlCpInMemoryConfigStorage.class).toInstance(config);
} catch (IOException e) {
e.printStackTrace();
this.log.error(e.getMessage(), e);
}
}

View File

@@ -1,7 +1,7 @@
package me.chanjar.weixin.cp.api;
import com.google.inject.Inject;
import me.chanjar.weixin.common.exception.WxErrorException;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.cp.api.impl.WxCpServiceImpl;
import me.chanjar.weixin.cp.config.WxCpConfigStorage;
import org.apache.commons.lang3.StringUtils;

View File

@@ -1,7 +1,7 @@
package me.chanjar.weixin.cp.api;
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.http.RequestExecutor;
import me.chanjar.weixin.cp.api.impl.WxCpServiceImpl;
import org.testng.annotations.DataProvider;

View File

@@ -2,7 +2,7 @@ package me.chanjar.weixin.cp.api;
import com.google.inject.Inject;
import me.chanjar.weixin.common.api.WxConsts;
import me.chanjar.weixin.common.exception.WxErrorException;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.cp.bean.WxCpMessage;
import me.chanjar.weixin.cp.bean.WxCpMessageSendResult;
import org.testng.annotations.*;

View File

@@ -0,0 +1,52 @@
package me.chanjar.weixin.cp.api.impl;
import com.google.inject.Inject;
import me.chanjar.weixin.common.api.WxConsts;
import me.chanjar.weixin.common.bean.menu.WxMenu;
import me.chanjar.weixin.common.bean.menu.WxMenuButton;
import me.chanjar.weixin.cp.api.ApiTestModule;
import me.chanjar.weixin.cp.api.WxCpAgentService;
import me.chanjar.weixin.cp.api.WxCpService;
import me.chanjar.weixin.cp.bean.WxCpAgent;
import me.chanjar.weixin.cp.config.WxCpInMemoryConfigStorage;
import org.mockito.Mock;
import org.testng.Assert;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Guice;
import org.testng.annotations.Test;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull;
import static org.mockito.Mockito.*;
/**
* <pre>
* 管理企业号应用-测试
* Created by huansinho on 2018/4/13.
* </pre>
*
* @author <a href="https://github.com/huansinho">huansinho</a>
*/
public class WxCpAgentServiceImplTest {
protected WxCpService wxService = mock(WxCpService.class);
@Test
public void testGet() throws Exception {
String returnJson = "{\"errcode\": 0,\"errmsg\": \"ok\",\"agentid\": 9,\"name\": \"测试应用\",\"square_logo_url\": \"http://wx.qlogo.cn/mmhead/alksjf;lasdjf;lasjfuodiuj3rj2o34j/0\",\"description\": \"这是一个企业号应用\",\"allow_userinfos\": {\"user\": [{\"userid\": \"0009854\"}, {\"userid\": \"1723\"}, {\"userid\": \"5625\"}]},\"allow_partys\": {\"partyid\": [42762742]},\"allow_tags\": {\"tagid\": [23, 22, 35, 19, 32, 125, 133, 46, 150, 38, 183, 9, 7]},\"close\": 0,\"redirect_domain\": \"weixin.com.cn\",\"report_location_flag\": 0,\"isreportenter\": 0,\"home_url\": \"\"}";
when(wxService.get("https://qyapi.weixin.qq.com/cgi-bin/agent/get?agentid=9", null)).thenReturn(returnJson);
when(wxService.getAgentService()).thenReturn(new WxCpAgentServiceImpl(wxService));
WxCpAgentService wxAgentService = this.wxService.getAgentService();
WxCpAgent wxCpAgent = wxAgentService.get(9);
Assert.assertEquals(9, wxCpAgent.getAgentid().intValue());
Assert.assertEquals(new Integer[]{42762742}, wxCpAgent.getAllowPartys().getPartyids().toArray());
Assert.assertEquals(new Integer[]{23, 22, 35, 19, 32, 125, 133, 46, 150, 38, 183, 9, 7}, wxCpAgent.getAllowTags().getTagids().toArray());
}
}

View File

@@ -56,7 +56,7 @@ public class WxCpDepartmentServiceImplTest {
}
}
@Test(dependsOnMethods = {"testListAll", "testCreate"})
@Test(dependsOnMethods = {"testList", "testCreate"})
public void testUpdate() throws Exception {
System.out.println("=================更新部门");
this.depart.setName("子部门改名" + System.currentTimeMillis());

View File

@@ -3,7 +3,7 @@ package me.chanjar.weixin.cp.api.impl;
import com.google.inject.Inject;
import me.chanjar.weixin.common.api.WxConsts;
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.cp.api.ApiTestModule;
import me.chanjar.weixin.cp.api.TestConstants;
import me.chanjar.weixin.cp.api.WxCpService;

View File

@@ -0,0 +1,33 @@
package me.chanjar.weixin.cp.api.impl;
import com.google.inject.Inject;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.cp.api.ApiTestModule;
import me.chanjar.weixin.cp.api.WxCpService;
import me.chanjar.weixin.cp.bean.WxCpUserDetail;
import org.testng.annotations.Guice;
import org.testng.annotations.Test;
/**
* <pre>
* Created by BinaryWang on 2018/4/22.
* </pre>
*
* @author <a href="https://github.com/binarywang">Binary Wang</a>
*/
@Guice(modules = ApiTestModule.class)
public class WxCpOAuth2ServiceImplTest {
@Inject
private WxCpService wxService;
@Test
public void testGetUserDetail() throws WxErrorException {
WxCpUserDetail userDetail = this.wxService.getOauth2Service().getUserDetail("b");
System.out.println(userDetail);
}
@Test
public void testGetUserInfo() throws WxErrorException {
this.wxService.getOauth2Service().getUserInfo("abc");
}
}

View File

@@ -2,16 +2,23 @@ package me.chanjar.weixin.cp.api.impl;
import com.google.common.base.Splitter;
import com.google.inject.Inject;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.cp.api.ApiTestModule;
import me.chanjar.weixin.cp.api.WxCpService;
import me.chanjar.weixin.cp.api.WxCpTagService;
import me.chanjar.weixin.cp.bean.WxCpTag;
import me.chanjar.weixin.cp.bean.WxCpTagAddOrRemoveUsersResult;
import me.chanjar.weixin.cp.bean.WxCpTagGetResult;
import me.chanjar.weixin.cp.bean.WxCpUser;
import org.testng.annotations.*;
import org.testng.annotations.Guice;
import org.testng.annotations.Test;
import java.util.List;
import static org.testng.Assert.*;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotEquals;
/**
* <pre>
@@ -63,7 +70,7 @@ public class WxCpTagServiceImplTest {
@Test(dependsOnMethods = {"testListUsersByTagId", "testAddUsers2Tag", "testListAll", "testUpdate", "testCreate"})
public void testRemoveUsersFromTag() throws Exception {
List<String> userIds = Splitter.on("|").splitToList(this.configStorage.getUserId());
WxCpTagAddOrRemoveUsersResult result = this.wxService.getTagService().removeUsersFromTag(this.tagId, userIds);
WxCpTagAddOrRemoveUsersResult result = this.wxService.getTagService().removeUsersFromTag(this.tagId, userIds, null);
assertEquals(result.getErrCode(), Integer.valueOf(0));
}
@@ -72,4 +79,24 @@ public class WxCpTagServiceImplTest {
this.wxService.getTagService().delete(this.tagId);
}
@Test
public void testGet() throws WxErrorException {
String apiResultJson = "{\"errcode\": 0,\"errmsg\": \"ok\",\"userlist\": [{\"userid\": \"0124035\",\"name\": \"王五\"},{\"userid\": \"0114035\",\"name\": \"梦雪\"}],\"partylist\": [9576,9567,9566],\"tagname\": \"测试标签-001\"}";
WxCpService wxService = mock(WxCpService.class);
when(wxService.get("https://qyapi.weixin.qq.com/cgi-bin/tag/get?tagId=150", null)).thenReturn(apiResultJson);
when(wxService.getTagService()).thenReturn(new WxCpTagServiceImpl(wxService));
WxCpTagService wxCpTagService = wxService.getTagService();
WxCpTagGetResult wxCpTagGetResult = wxCpTagService.get(String.valueOf(150));
assertEquals(0, wxCpTagGetResult.getErrcode().intValue());
assertEquals(2, wxCpTagGetResult.getUserlist().size());
assertEquals(3, wxCpTagGetResult.getPartylist().size());
assertEquals("测试标签-001", wxCpTagGetResult.getTagname());
}
}

View File

@@ -1,8 +1,11 @@
package me.chanjar.weixin.cp.api.impl;
import com.google.common.collect.Lists;
import com.google.inject.Inject;
import me.chanjar.weixin.cp.api.ApiTestModule;
import me.chanjar.weixin.cp.api.WxCpService;
import me.chanjar.weixin.cp.bean.Gender;
import me.chanjar.weixin.cp.bean.WxCpInviteResult;
import me.chanjar.weixin.cp.bean.WxCpUser;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
@@ -40,7 +43,7 @@ public class WxCpUserServiceImplTest {
user.setName("Some Woman");
user.setDepartIds(new Integer[]{2});
user.setEmail("none@none.com");
user.setGender(WxCpUser.Gender.FEMALE);
user.setGender(Gender.FEMALE);
user.setMobile("13560084979");
user.setPosition("woman");
user.setTelephone("3300393");
@@ -87,9 +90,9 @@ public class WxCpUserServiceImplTest {
}
@Test
@Deprecated
public void testInvite() throws Exception {
int result = this.wxCpService.getUserService().invite(userId, "");
WxCpInviteResult result = this.wxCpService.getUserService().invite(
Lists.newArrayList(userId), null,null);
System.out.println(result);
}

View File

@@ -0,0 +1,25 @@
package me.chanjar.weixin.cp.bean;
import org.testng.Assert;
import org.testng.annotations.Test;
/**
* Created by huansinho on 2018/4/13.
*/
@Test
public class WxCpAgentTest {
public void testDeserialize() {
String json = "{\"errcode\": 0,\"errmsg\": \"ok\",\"agentid\": 9,\"name\": \"测试应用\",\"square_logo_url\": \"http://wx.qlogo.cn/mmhead/alksjf;lasdjf;lasjfuodiuj3rj2o34j/0\",\"description\": \"这是一个企业号应用\",\"allow_userinfos\": {\"user\": [{\"userid\": \"0009854\"}, {\"userid\": \"1723\"}, {\"userid\": \"5625\"}]},\"allow_partys\": {\"partyid\": [42762742]},\"allow_tags\": {\"tagid\": [23, 22, 35, 19, 32, 125, 133, 46, 150, 38, 183, 9, 7]},\"close\": 0,\"redirect_domain\": \"weixin.com.cn\",\"report_location_flag\": 0,\"isreportenter\": 0,\"home_url\": \"\"}";
WxCpAgent wxCpAgent = WxCpAgent.fromJson(json);
Assert.assertEquals(9, wxCpAgent.getAgentid().intValue());
Assert.assertEquals(new Integer[]{42762742}, wxCpAgent.getAllowPartys().getPartyids().toArray());
Assert.assertEquals(new Integer[]{23, 22, 35, 19, 32, 125, 133, 46, 150, 38, 183, 9, 7}, wxCpAgent.getAllowTags().getTagids().toArray());
}
}

View File

@@ -2,39 +2,47 @@ package me.chanjar.weixin.cp.bean;
import me.chanjar.weixin.cp.bean.article.MpnewsArticle;
import me.chanjar.weixin.cp.bean.article.NewArticle;
import org.testng.annotations.*;
import org.testng.annotations.Test;
import static org.testng.Assert.*;
import static org.assertj.core.api.Assertions.assertThat;
import static org.testng.Assert.assertEquals;
@Test
public class WxCpMessageTest {
public void testTextBuild() {
WxCpMessage reply = WxCpMessage.TEXT().toUser("OPENID").content("sfsfdsdf").build();
assertEquals(reply.toJson(), "{\"touser\":\"OPENID\",\"msgtype\":\"text\",\"text\":{\"content\":\"sfsfdsdf\"},\"safe\":\"0\"}");
assertThat(reply.toJson())
.isEqualTo("{\"touser\":\"OPENID\",\"msgtype\":\"text\",\"text\":{\"content\":\"sfsfdsdf\"},\"safe\":\"0\"}");
}
public void testTextCardBuild() {
WxCpMessage reply = WxCpMessage.TEXTCARD().toUser("OPENID")
.title("领奖通知")
.description( "<div class=\"gray\">2016年9月26日</div> <div class=\"normal\">恭喜你抽中iPhone 7一台领奖码xxxx</div><div class=\"highlight\">请于2016年10月10日前联系行政同事领取</div>")
.url("http://www.qq.com").build();
assertEquals(reply.toJson(), "{\"touser\":\"OPENID\",\"msgtype\":\"textcard\",\"textcard\":{\"title\":\"领奖通知\",\"description\":\"<div class=\\\"gray\\\">2016年9月26日</div> <div class=\\\"normal\\\">恭喜你抽中iPhone 7一台领奖码xxxx</div><div class=\\\"highlight\\\">请于2016年10月10日前联系行政同事领取</div>\",\"url\":\"http://www.qq.com\"},\"safe\":\"0\"}");
.description("<div class=\"gray\">2016年9月26日</div> <div class=\"normal\">恭喜你抽中iPhone 7一台领奖码xxxx</div><div class=\"highlight\">请于2016年10月10日前联系行政同事领取</div>")
.url("http://www.qq.com")
.btnTxt("更多")
.build();
assertThat(reply.toJson())
.isEqualTo("{\"touser\":\"OPENID\",\"msgtype\":\"textcard\",\"textcard\":{\"title\":\"领奖通知\",\"description\":\"<div class=\\\"gray\\\">2016年9月26日</div> <div class=\\\"normal\\\">恭喜你抽中iPhone 7一台领奖码xxxx</div><div class=\\\"highlight\\\">请于2016年10月10日前联系行政同事领取</div>\",\"url\":\"http://www.qq.com\",\"btntxt\":\"更多\"},\"safe\":\"0\"}");
}
public void testImageBuild() {
WxCpMessage reply = WxCpMessage.IMAGE().toUser("OPENID").mediaId("MEDIA_ID").build();
assertEquals(reply.toJson(), "{\"touser\":\"OPENID\",\"msgtype\":\"image\",\"image\":{\"media_id\":\"MEDIA_ID\"},\"safe\":\"0\"}");
assertThat(reply.toJson())
.isEqualTo("{\"touser\":\"OPENID\",\"msgtype\":\"image\",\"image\":{\"media_id\":\"MEDIA_ID\"},\"safe\":\"0\"}");
}
public void testVoiceBuild() {
WxCpMessage reply = WxCpMessage.VOICE().toUser("OPENID").mediaId("MEDIA_ID").build();
assertEquals(reply.toJson(), "{\"touser\":\"OPENID\",\"msgtype\":\"voice\",\"voice\":{\"media_id\":\"MEDIA_ID\"},\"safe\":\"0\"}");
assertThat(reply.toJson())
.isEqualTo("{\"touser\":\"OPENID\",\"msgtype\":\"voice\",\"voice\":{\"media_id\":\"MEDIA_ID\"},\"safe\":\"0\"}");
}
public void testVideoBuild() {
WxCpMessage reply = WxCpMessage.VIDEO().toUser("OPENID").title("TITLE").mediaId("MEDIA_ID").thumbMediaId("MEDIA_ID").description("DESCRIPTION").build();
assertEquals(reply.toJson(), "{\"touser\":\"OPENID\",\"msgtype\":\"video\",\"safe\":\"0\",\"video\":{\"media_id\":\"MEDIA_ID\",\"thumb_media_id\":\"MEDIA_ID\",\"title\":\"TITLE\",\"description\":\"DESCRIPTION\"}}");
assertThat(reply.toJson())
.isEqualTo("{\"touser\":\"OPENID\",\"msgtype\":\"video\",\"safe\":\"0\",\"video\":{\"media_id\":\"MEDIA_ID\",\"thumb_media_id\":\"MEDIA_ID\",\"title\":\"TITLE\",\"description\":\"DESCRIPTION\"}}");
}
public void testNewsBuild() {
@@ -52,7 +60,8 @@ public class WxCpMessageTest {
WxCpMessage reply = WxCpMessage.NEWS().toUser("OPENID").addArticle(article1).addArticle(article2).build();
assertEquals(reply.toJson(), "{\"touser\":\"OPENID\",\"msgtype\":\"news\",\"safe\":\"0\",\"news\":{\"articles\":[{\"title\":\"Happy Day\",\"description\":\"Is Really A Happy Day\",\"url\":\"URL\",\"picurl\":\"PIC_URL\"},{\"title\":\"Happy Day\",\"description\":\"Is Really A Happy Day\",\"url\":\"URL\",\"picurl\":\"PIC_URL\"}]}}");
assertThat(reply.toJson())
.isEqualTo( "{\"touser\":\"OPENID\",\"msgtype\":\"news\",\"safe\":\"0\",\"news\":{\"articles\":[{\"title\":\"Happy Day\",\"description\":\"Is Really A Happy Day\",\"url\":\"URL\",\"picurl\":\"PIC_URL\"},{\"title\":\"Happy Day\",\"description\":\"Is Really A Happy Day\",\"url\":\"URL\",\"picurl\":\"PIC_URL\"}]}}");
}
public void testMpnewsBuild_with_articles() {
@@ -78,14 +87,15 @@ public class WxCpMessageTest {
WxCpMessage reply = WxCpMessage.MPNEWS().toUser("OPENID").addArticle(article1, article2).build();
assertEquals(reply.toJson(), "{\"touser\":\"OPENID\",\"msgtype\":\"mpnews\",\"safe\":\"0\",\"mpnews\":{\"articles\":[{\"title\":\"Happy Day\",\"thumb_media_id\":\"thumb\",\"author\":\"aaaaaa\",\"content_source_url\":\"nice url\",\"content\":\"hahaha\",\"digest\":\"digest\",\"show_cover_pic\":\"heihei\"},{\"title\":\"Happy Day\",\"thumb_media_id\":\"thumb\",\"author\":\"aaaaaa\",\"content_source_url\":\"nice url\",\"content\":\"hahaha\",\"digest\":\"digest\",\"show_cover_pic\":\"heihei\"}]}}");
assertThat(reply.toJson())
.isEqualTo( "{\"touser\":\"OPENID\",\"msgtype\":\"mpnews\",\"safe\":\"0\",\"mpnews\":{\"articles\":[{\"title\":\"Happy Day\",\"thumb_media_id\":\"thumb\",\"author\":\"aaaaaa\",\"content_source_url\":\"nice url\",\"content\":\"hahaha\",\"digest\":\"digest\",\"show_cover_pic\":\"heihei\"},{\"title\":\"Happy Day\",\"thumb_media_id\":\"thumb\",\"author\":\"aaaaaa\",\"content_source_url\":\"nice url\",\"content\":\"hahaha\",\"digest\":\"digest\",\"show_cover_pic\":\"heihei\"}]}}");
}
public void testMpnewsBuild_with_media_id() {
WxCpMessage reply = WxCpMessage.MPNEWS().toUser("OPENID").mediaId("mmm").build();
assertEquals(reply.toJson(),
"{\"touser\":\"OPENID\",\"msgtype\":\"mpnews\",\"safe\":\"0\",\"mpnews\":{\"media_id\":\"mmm\"}}");
assertThat(reply.toJson())
.isEqualTo("{\"touser\":\"OPENID\",\"msgtype\":\"mpnews\",\"safe\":\"0\",\"mpnews\":{\"media_id\":\"mmm\"}}");
}
}

View File

@@ -1,6 +1,6 @@
package me.chanjar.weixin.cp.demo;
import me.chanjar.weixin.common.exception.WxErrorException;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.cp.api.WxCpService;
import javax.servlet.http.HttpServlet;