企业微信推送应用应用消息的记录
企业微信官方文档 :https://developer.work.weixin.qq.com/document/path/90664
本文写于2022/11/10号,官网文档中有些字段可能会进行更新,实体类的创建根据官方文档为准,本文仅提供参考
如果想要使用企业微信相关的api功能,我们需要先获取企业微信相关应用的token
请求方式: GET(HTTPS)
请求地址: https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid=ID&corpsecret=SECRET
参数说明:
参数 | 必须 | 说明 |
---|---|---|
corpid | 是 | 企业ID |
corpsecret | 是 | 应用的凭证密钥,注意应用需要是启用状态, |
注意:获取的token有应用和应用区分,A应用的token只能用于A应用,B应用的token只能用于B应用,corpsecret是区分应用的一种途径,每个应用的corpsecret是不同的,且同一个应用的token在两个小时内重复获取,获取的token不会改变,并且token的访问次数是有限制的
1、案例准备
1>定义一个异常类
public class EnterpriseWeChatException extends RuntimeException {
public EnterpriseWeChatException(String msg) {
super(msg);
}
public EnterpriseWeChatException() {
super();
}
}
2>定义一个guavaCache的缓存类
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>22.0</version>
</dependency>
/**
* 企业微信应用token缓存
*
* @Author liuxk
* @date: 2022/10/31
*/
public class EnterpriseWeChatAgentTokenGuavaCache {
/**
* 缓存过期时间为 2 小时
*/
public static Cache<Integer, String> cache = CacheBuilder.newBuilder().expireAfterAccess(2, TimeUnit.HOURS).build();
/**
* 添加缓存数据
*
* @param key
* @param value
*/
public static void put(Integer key, String value) {
cache.put(key, value);
}
/**
* 获取缓存数据
*
* @param key
* @return
*/
public static String get(Integer key) {
return cache.getIfPresent(key);
}
}
3>定义一个常量类
/**
* 微信公众平台常量类
* <p>
* User: liuxk
* Date: 2022/10/27
*/
public class EnterpriseWeChatConstant {
/**
* 企业id
*/
public static final String CORPID = "填写自己的企业id";
/**
* 应用的凭证密钥
* 注意:应用需要是启用状态
*/
// 一开始进行设计开发时,使用的想法时直接在常量类中将每个应用的密钥设置到常量中,后来感觉不可取,就把密钥设置到数据库中,使用的时候从数据库中进行获取
public static final String CORPSECRET = "填写自己的企业应用密钥";
/**
* 获取访问权限码(access_token)URL GET请求
*/
public static final String ACCESS_TOKEN_URL = "https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid=%s&corpsecret=%s";
/**
* 发送消息URL POST请求
*/
public static final String CREATE_SESSION_URL = "https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token=";
/**
* 获取企业微信用户userid POST请求
*/
public static final String GET_USER_ID = "https://qyapi.weixin.qq.com/cgi-bin/user/getuserid?access_token=";
}
4> 数据库准备
(也可以不使用数据库,用什么方法见仁见智)
--更改相关字段为你所需要的
CREATE TABLE `table_name` (
`id` int NOT NULL AUTO_INCREMENT COMMENT '企业微信应用表id',
`appName` varchar(20) NOT NULL COMMENT '企业微信下应用名称',
`agentId` int NOT NULL COMMENT '企业微信下应用id',
`appSecret` varchar(255) NOT NULL COMMENT '企业微信下应用的私钥',
`createTime` datetime NOT NULL COMMENT '创建时间',
`updateTime` datetime DEFAULT NULL COMMENT '修改时间',
`deleted` int unsigned NOT NULL DEFAULT '0' COMMENT '逻辑删除',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='企业微信下应用的相关信息';
5>定义mapper
public interface EnterpriseWeChatAppMapper {
EnterpriseWeChatAppDto queryByAgentId(Integer agentId);
List<EnterpriseWeChatAppDto> list();
}
相关的mapper.xml自行书写
6>发送网络请求使用restTemplate
定义一个restTemplate配置类
@Configuration
public class RestTemplateConfig {
@Bean
RestTemplate restTemplate() {
return new RestTemplate();
}
}
7>定义获取token的返回值的对象
@Getter
@Setter
public class EnterpriseAccessTokenDto {
/**
* 出错返回码,为0表示成功,非0表示调用失败
*/
private Integer errcode;
/**
* 返回码提示语
*/
private String errmsg;
/**
* 获取到的凭证,最长为512字节
*/
private String access_token;
/**
* 凭证的有效时间(秒)
*/
private String expires_in;
}
8>定义一个字典
(本案例中不定义也可以)
public enum EnterpriseWeixinErrorCodeDict {
// 存放的为微信的一些常用的错误码
Not_OK(-1,"系统繁忙"),
Ok(0, "请求成功");
public final int code;
public final String name;
EnterpriseWeixinErrorCodeDict(int code, String name) {
this.code = code;
this.name = name;
}
}
9>定义一个类用于接受推送消息返回结果
@Getter
@Setter
public class EnterpriseAppMessageDto {
/**
* 返回码
*/
private Integer errcode;
/**
* 对返回码的文本描述内容
*/
private String errmsg;
/**
* 不合法的userid,不区分大小写,统一转为小写
*/
private String invaliduser;
/**
* 不合法的partyid
*/
private String invalidparty;
/**
* 不合法的标签id
*/
private String invalidtag;
/**
* 没有基础接口许可(包含已过期)的userid
*/
private String unlicenseduser;
/**
* 消息id,用于撤回应用消息
*/
private String msgid;
/**
* 仅消息类型为“按钮交互型”,“投票选择型”和“多项选择型”的模板卡片消息返回,应用可使用response_code调用更新模版卡片消息接口,72小时内有效,且只能使用一次
*/
private String response_code;
}
2、获取token
因为知道
1、每个应用的token都不同且不通用
2、token在两个小时内获取到的是一样的
3、固定时间内获取token的次数是固定的
为了解决这些问题,要考虑把token放在缓存中(redis缓存,guavaCache等多种缓存,本案例使用guavaCache进行缓存)
先按照步骤3 定义一个接口及其实现类,将获取token的方法写在其实现类中
public String getAccessToken(Integer agentId) {
// 获取缓存中的token,有则返回token,没有则获取token
String token = EnterpriseWeChatAgentTokenGuavaCache.get(agentId);
if (StringUtils.isNotEmpty(token)) {
return token;
}
// 从数据库中获取到的相关信息
EnterpriseWeChatAppDto enterpriseWeChatAppDto = enterpriseWeChatAppMapper.queryByAgentId(agentId);
if (enterpriseWeChatAppDto == null) {
throw new EnterpriseWeChatException("获取应用密钥失败,请检查应用id是否正确");
}
String appSecret = enterpriseWeChatAppDto.getAppSecret();
// 拼接获取token 的url
// 常量类中的属性
String getTokenUrl = String.format(EnterpriseWeChatConstant.ACCESS_TOKEN_URL,
EnterpriseWeChatConstant.CORPID,
appSecret);
// 通过url发送请求,获取返回的对象
ResponseEntity<EnterpriseAccessTokenDto> entity =
restTemplate.getForEntity(getTokenUrl, EnterpriseAccessTokenDto.class);
if (entity.getStatusCode() != HttpStatus.OK) {
throw new EnterpriseWeChatException("获取token请求发送失败,错误信息:" + entity);
}
EnterpriseAccessTokenDto body = entity.getBody();
// 如果没有定义字典,也可以直接使用 0 代替 EnterpriseWeixinErrorCodeDict.Ok.code
if (body.getErrcode() != EnterpriseWeixinErrorCodeDict.Ok.code) {
throw new EnterpriseWeChatException("获取token失败,错误码:" + body.getErrcode() + "错误信息:" + body.getErrmsg());
}
// 获取到了token之后存档在guavaCache缓存中
EnterpriseWeChatAgentTokenGuavaCache.put(agentId, body.getAccess_token());
return body.getAccess_token();
}
3、发送文字消息
定义一个参数实体类
实体类内容要和企业微信官网文档中的对应
@Getter
@Setter
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class EnterpriseWeChatTextMessageParam {
// touser、toparty、totag不能同时为空
/**
* 指定接收消息的成员,成员ID列表(多个接收者用‘|’分隔,最多支持1000个)。特殊情况:指定为"@all",则向该企业应用的全部成员发送
*/
private String touser;
/**
* 指定接收消息的部门,部门ID列表,多个接收者用‘|’分隔,最多支持100个。当touser为"@all"时忽略本参数
*/
private String toparty;
/**
* 指定接收消息的标签,标签ID列表,多个接收者用‘|’分隔,最多支持100个。 当touser为"@all"时忽略本参数
*/
private String totag;
/**
* 消息类型
*/
private String msgtype;
/**
* 企业应用的id
*/
private Integer agentid;
/**
* 消息内容
*/
private EnterpriseWeChatTextMessage text;
/**
* 表示是否是保密消息,0表示可对外分享,1表示不能分享且内容显示水印,默认为0
*/
private Integer safe = 0;
/**
* 表示是否开启id转译,0表示否,1表示是,默认0。仅第三方应用需要用到,企业自建应用可以忽略。
*/
private Integer enable_id_trans = 0 ;
/**
* 表示是否开启重复消息检查,0表示否,1表示是,默认0
*/
private Integer enable_duplicate_check = 0 ;
/**
* 表示是否重复消息检查的时间间隔,默认1800s,最大不超过4小时
*/
private Integer duplicate_check_interval = 1800;
}
定义一个接口
@Service
public interface EnterpriseWeChatService {
/**
* 应用消息-文字消息
*
* @param appTextMessage
* @return
*/
Result sendTextMessage(EnterpriseWeChatTextMessageParam appTextMessage);
}
接口实现类
(获取token的方法写在此处)
@Slf4j
@Service
public class EnterpriseWeChatServiceImpl implements EnterpriseWeChatService {
@Autowired
private RestTemplate restTemplate;
@Autowired
private EnterpriseWeChatAppMapper enterpriseWeChatAppMapper;
@Override
public Result sendTextMessage(EnterpriseWeChatTextMessageParam appTextMessage) {
log.info("应用文本消息参数: {} ", appTextMessage.toString());
EnterpriseAppMessageDto enterpriseAppMessageDto =
sendMessage(appTextMessage.getAgentid(), appTextMessage);
log.info("应用文本消息响应:{}", enterpriseAppMessageDto.toString());
return Result.success();
}
/**
* 发送微信消息
*
* @param agentId 企业应用id
* @param request 请求体参数对象
* @return 推送应用消息返回值
*/
public EnterpriseAppMessageDto sendMessage(Integer agentId, Object request) {
String token = getAccessToken(agentId);
//请求链接
String action = EnterpriseWeChatConstant.CREATE_SESSION_URL + token;
ResponseEntity<EnterpriseAppMessageDto> responseEntity =
restTemplate.postForEntity(action, request, EnterpriseAppMessageDto.class);
if (responseEntity.getStatusCode() != HttpStatus.OK) {
throw new EnterpriseWeChatException("应用消息请求发送失败{}" + request);
}
EnterpriseAppMessageDto body = responseEntity.getBody();
if (body.getErrcode() != EnterpriseWeixinErrorCodeDict.Ok.code) {
throw new EnterpriseWeChatException("发送应用消息失败,错误码:" + body.getErrcode() + "错误信息:" + body.getErrmsg());
}
return body;
}
}
4、发送文字消息
定义参数实体类
/**
* 企业微信应用消息推送图文消息
* (两种图文消息,此实体类对应msgtype = ”mpnews“)
*/
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
public class EnterpriseWeChatPictureNewsPushParam {
/**
* 否
* 成员ID列表(消息接收者,多个接收者用‘|’分隔,最多支持1000个)。特殊情况:指定为@all,则向关注该企业应用的全部成员发送
*/
private String touser;
/**
* 否
* 部门ID列表,多个接收者用‘|’分隔,最多支持100个。当touser为@all时忽略本参数
*/
private String toparty;
/**
* 否
* 标签ID列表,多个接收者用‘|’分隔,最多支持100个。当touser为@all时忽略本参数
*/
private String totag;
/**
* 是
* 消息类型,此时固定为:mpnews
*/
private String msgtype;
/**
* 是
* 企业应用的id,整型。企业内部开发,可在应用的设置页面查看;第三方服务商,可通过接口 获取企业授权信息 获取该参数值
*/
private Integer agentid;
/**
* 消息主体
*/
private EnterpriseWeChatPictureNewsParam mpnews;
/**
* 否
* 表示是否是保密消息,0表示可对外分享,1表示不能分享且内容显示水印,2表示仅限在企业内分享,默认为0;注意仅mpnews类型的消息支持safe值为2,其他消息类型不支持
*/
private Integer safe;
/**
* 否
* 表示是否开启id转译,0表示否,1表示是,默认0
*/
private Integer enable_id_trans;
/**
* 否
* 表示是否开启重复消息检查,0表示否,1表示是,默认0
*/
private Integer enable_duplicate_check;
/**
* 否
* 表示是否重复消息检查的时间间隔,默认1800s,最大不超过4小时
*/
private Integer duplicate_check_interval;
}
@Getter
@Setter
public class EnterpriseWeChatPictureNewsParam {
/**
* 图文消息-消息主体内容
*/
private List<EnterPriseWeChatPictureWordContentParam> articles;
}
@Getter
@Setter
public class EnterPriseWeChatPictureWordContentParam {
/**
* 是否必填 :是
* 标题
*/
private String title;
/**
* 是
* 图文消息缩略图的media_id, 可以通过素材管理接口获得。此处thumb_media_id即上传接口返回的media_id
*/
private String thumb_media_id;
/**
* 否
* 图文消息的作者,不超过64个字节
*/
private String author;
/**
* 否
* 图文消息点击“阅读原文”之后的页面链接
*/
private String content_source_url;
/**
* 是
* 图文消息的内容,支持html标签,不超过666 K个字节(支持id转译)
*/
private String content;
/**
* 否
* 图文消息的描述,不超过512个字节,超过会自动截断(支持id转译)
*/
private String digest;
}
定义三个实体类而不是定义一个,原因是为了符合微信官方文档的消息体格式
{
"touser" : "UserID1|UserID2|UserID3",
"toparty" : "PartyID1 | PartyID2",
"totag": "TagID1 | TagID2",
"msgtype" : "mpnews",
"agentid" : 1,
"mpnews" : {
"articles":[
{
"title": "Title",
"thumb_media_id": "MEDIA_ID",
"author": "Author",
"content_source_url": "URL",
"content": "Content",
"digest": "Digest description"
}
]
},
"safe":0,
"enable_id_trans": 0,
"enable_duplicate_check": 0,
"duplicate_check_interval": 1800
}
在接口中添加方法
/**
* 应用消息-图文消息
*
* @param picture
* @return
*/
Result sendImageTextMessage(EnterpriseWeChatPictureNewsPushParam picture);
接口实现类中也增加相应的方法
@Override
public Result sendImageTextMessage(EnterpriseWeChatPictureNewsPushParam picture) {
log.info("图文消息参数: {} ", picture.toString());
EnterpriseAppMessageDto enterpriseAppMessageDto = sendMessage(picture.getAgentid(), picture);
log.info("图文消息响应: {}", enterpriseAppMessageDto.toString());
return Result.success();
}
5、发送卡片信息
定义参数实体类
@Getter
@Setter
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class EnterpriseWeChatCardMessageParam {
/**
* 是否必填:否
* 成员ID列表(消息接收者,多个接收者用‘|’分隔,最多支持1000个)。特殊情况:指定为@all,则向关注该企业应用的全部成员发送
*/
private String touser;
/**
* 是否必填:否
* 部门ID列表,多个接收者用‘|’分隔,最多支持100个。当touser为@all时忽略本参数
*/
private String toparty;
/**
* 是否必填:否
* 标签ID列表,多个接收者用‘|’分隔,最多支持100个。当touser为@all时忽略本参数
*/
private String totag;
/**
* 是否必填:是
* 消息类型,此时固定为:template_card
*/
private String msgtype = "template_card";
/**
* 是否必填:是
* 企业应用的id,整型。企业内部开发,可在应用的设置页面查看;第三方服务商,可通过接口 获取企业授权信息 获取该参数值
*/
private Integer agentid;
/**
* 是否必填:是
* 模板卡片类型,文本通知型卡片填写 "text_notice"
*/
private String card_type;
/**
* 是否必填:否
* 卡片来源样式信息,不需要来源样式可不填写
*/
private EnterpriseWeChatCardSourceparam source;
/**
* 是否必填:否
* 卡片右上角更多操作按钮
*/
private EnterpriseWeChatCardActionMenuParam action_menu;
/**
* 是否必填:
* 一级标题,建议不超过36个字,文本通知型卡片本字段非必填
* 但不可以本字段和sub_title_text都不填
*/
private EnterpriseWeChatCardMainTitleParam main_title;
/**
* 是否必填:否
* 引用文献样式
*/
private EnterpriseWeChatCardQuoteAreaParam quote_area;
/**
* 是否必填:否
* 关键数据样式
*/
private EnterpriseWeChatCardEmphasisContentParam emphasis_content;
/**
* 是否必填:否
* 二级普通文本,建议不超过160个字,(支持id转译)
*/
private String sub_title_text;
/**
* 是否必填:否
* 二级标题+文本列表,该字段可为空数组,但有数据的话需确认对应字段是否必填,列表长度不超过6
*/
private List<EnterpriseWeChatCardHorizontalContentListParam> horizontal_content_list;
/**
* 是否必填:否
* 跳转指引样式的列表,该字段可为空数组,但有数据的话需确认对应字段是否必填,列表长度不超过3
*/
private List<EnterpriseWeChatCardJumpListParam> jump_list;
/**
* 是否必填:是
* 整体卡片的点击跳转事件,text_notice必填本字段
*/
private EnterpriseWeChatCardCardActionParam card_action;
/**
* 是否必填:否
* 任务id,同一个应用任务id不能重复,只能由数字、字母和“_-@”组成,最长128字节,填了action_menu字段的话本字段必填
*/
private String task_id;
/**
* 是否必填:否
* 表示是否开启id转译,0表示否,1表示是,默认0
*/
private Integer enable_id_trans = 0;
/**
* 是否必填:否
* 表示是否开启重复消息检查,0表示否,1表示是,默认0
*/
private Integer enable_duplicate_check = 0;
/**
* 是否必填:否
* 表示是否重复消息检查的时间间隔,默认1800s,最大不超过4小时
*/
private Integer duplicate_check_interval = 1800;
}
@Getter
@Setter
public class EnterpriseWeChatCardSourceparam {
/**
* 是否必填:否
* 来源图片的url,来源图片的尺寸建议为72*72
*/
private String icon_url;
/**
* 是否必填:否
* 来源图片的描述,建议不超过20个字,(支持id转译)
*/
private String desc ;
/**
* 是否必填:否
* 来源文字的颜色,目前支持:0(默认) 灰色,1 黑色,2 红色,3 绿色
*/
private Integer desc_color;
}
@Getter
@Setter
public class EnterpriseWeChatCardActionMenuParam {
/**
* 是否必填: 否
* 更多操作界面的描述
*/
private String desc;
/**
* 是否必填:是
* 操作列表,列表长度取值范围为 [1, 3]
*/
private EnterpriseWeChatCardActionListParam action_list;
}
@Getter
@Setter
public class EnterpriseWeChatCardMainTitleParam {
/**
* 是否必填:否
* 一级标题,建议不超过36个字,文本通知型卡片本字段非必填,但不可本字段和sub_title_text都不填,(支持id转译)
*/
private String title;
/**
* 是否必填:否
* 标题辅助信息,建议不超过44个字,(支持id转译)
*/
private String desc;
}
@Getter
@Setter
public class EnterpriseWeChatCardQuoteAreaParam {
/**
* 是否必填:否
* 引用文献样式区域点击事件,0或不填代表没有点击事件,1 代表跳转url,2 代表跳转小程序
*/
private Integer type;
/**
* 是否必填:否
* 点击跳转的url, type是1时必填
*/
private String url;
/**
* 是否必填:否
* 点击跳转的小程序的appid,必须是与当前应用关联的小程序, type是2时必填
*/
private String appid;
/**
* 是否必填:否
* 点击跳转的小程序的pagepath, type是2时选填
*/
private String pagepath;
/**
* 是否必填:否
* 引用文献样式的标题
*/
private String title;
/**
* 是否必填:否
* 引用文献样式的引用文案
*/
private String quote_text;
}
@Getter
@Setter
public class EnterpriseWeChatCardEmphasisContentParam {
/**
* 是否必填:否
* 关键数据样式的数据内容,建议不超过14个字
*/
private String title;
/**
* 是否必填:否
* 关键数据样式的数据描述内容,建议不超过22个字
*/
private String desc;
}
@Getter
@Setter
public class EnterpriseWeChatCardHorizontalContentListParam {
/**
* 是否必填:否
* 链接类型,0或不填代表不是链接,1 代表跳转url,2 代表下载附件,3 代表点击跳转成员详情
*/
private Integer type;
/**
* 是否必填:是
* 二级标题,建议不超过5个字
*/
private String keyname;
/**
* 根据type的值判断是否必填
* 二级文本,如果 type是2,该字段代表文件名称(要包含文件类型),建议不超过30个字,(支持id转译)
*/
private String value;
/**
* 根据type的值判断是否必填
* 链接跳转的url, type是1时必填
*/
private String url;
/**
* 根据type的值判断是否必填
* 附件的media_id, type是2时必填
*/
private String media_id;
/**
* 根据type的值判断是否必填
* 成员详情的userid, type是3时必填
*/
private String userid;
}
@Getter
@Setter
public class EnterpriseWeChatCardJumpListParam {
/**
* 是否必填:否
* 跳转链接类型,0或不填代表不是链接,1代表跳转url,2代表跳转小程序
*/
private Integer type;
/**
* 根据type的值判断是否必填
* 跳转链接样式的文案内容,建议不超过18个字
*/
private String title;
/**
* 根据type的值判断是否必填
* 跳转链接的url, type是1时必填
*/
private String url;
/**
* 根据type的值判断是否必填
* 跳转链接的小程序的appid,必须是与当前应用关联的小程序, type是2时必填
*/
private String appid;
/**
* 是根据type的值判断是否必填
* 跳转链接的小程序的pagepath, type是2时选填
*/
private String pagepath;
}
@Getter
@Setter
public class EnterpriseWeChatCardCardActionParam {
/**
* 是否必填:是
* 跳转事件类型,1代表跳转url,2代表打开小程序。text_notice卡片模版中该字段取值范围为[1,2]
*/
private Integer type;
/**
* 根据type的值判断是否必填
* 跳转事件的url, type是1时必填
*/
private String url;
/**
* 根据type的值判断是否必填
* 跳转事件的小程序的appid,必须是与当前应用关联的小程序, type是2时必填
*/
private String appid;
/**
* 根据type的值判断是否必填
* 跳转事件的小程序的pagepath, type是2时选填
*/
private String pagepath;
}
接口中新增方法
/**
* 应用消息-卡片消息
*
* @param cardMessage
* @return
*/
Result sendCardMessage(EnterpriseWeChatCardMessageParam cardMessage);
接口实现类中也增加相应的方法
@Override
public Result sendCardMessage(EnterpriseWeChatCardMessageParam cardMessage) {
log.info("卡片消息参数: {} ", cardMessage.toString());
EnterpriseAppMessageDto enterpriseAppMessageDto = sendMessage(cardMessage.getAgentid(), cardMessage);
log.info("卡片消息响应: {}", enterpriseAppMessageDto.toString());
return Result.success();
}
Result 实体包装类 (上文返回值),
public class Result<E> implements Serializable {
/**
* 请求响应状态,参考字典ResultStatus
* @mock 200
*/
private Integer status;
/**
* 消息提示
* @mock 请求成功
*/
private String msg;
/**
* 返回结果
*/
private E data;
public Result(Integer status, String msg, E data) {
this.status = status;
this.msg = msg;
this.data = data;
}
public Result() {
}
public E getData() {
return data;
}
public void setData(E data) {
this.data = data;
}
public Integer getStatus() {
return status;
}
public void setStatus(Integer status) {
this.status = status;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
/**
* 请求结果成功
*/
public boolean succeeded() {
return status == ResultStatus.Success.code;
}
/**
* 请求结果失败
*/
public boolean failed() {
return status != ResultStatus.Success.code;
}
/**
* 业务处理成功
*/
public static <T> Result<T> success(String msg) {
return success(msg, null);
}
public static <T> Result<T> success() {
return success(null, null);
}
public static <T> Result<T> success(T data) {
return success(null, data);
}
public static <T> Result<T> success(String msg, T data) {
return new Result(ResultStatus.Success.code, msg, data);
}
/**
* 业务处理失败
*/
public static <T> Result<T> failure(String msg) {
return failure(msg, null);
}
public static <T> Result<T> failure(String msg, T data) {
return new Result(ResultStatus.Failure.code, msg, data);
}
public static <T> Result<T> failure(ResultStatus statusCode) {
return new Result(statusCode.code, statusCode.name, null);
}
/**
* 系统异常
*/
public static <T> Result<T> error(String msg) {
return new Result(ResultStatus.Internal_Server_Error.code, msg, null);
}
// /**
// * 系统异常,计划删除的方法
// */
// @Deprecated
// public static <T> Result<T> error(String msg, Throwable throwable) {
// return new Result(ResultStatus.Internal_Server_Error.code, msg, null);
// }
public static <T> Result<T> set(ResultStatus status) {
return set(status, status.name, null);
}
public static <T> Result<T> set(ResultStatus status, String msg) {
return set(status, msg, null);
}
public static <T> Result<T> set(ResultStatus status, String msg, T data) {
return new Result(status.code, msg, data);
}
public static <T> Result<T> valueOf(Result resp) {
return new Result(resp.getStatus(), resp.getMsg(), null);
}
public static <T> Result page(T data) {
return new Result(ResultStatus.Success.code, null, new Page<>(data));
}
@Override
public String toString() {
return "Result{" +
"status=" + status +
", msg='" + msg + '\'' +
", data=" + data +
'}';
}
}
Http内部接口交互状态码
public enum ResultStatus {
/**
* 业务处理成功,付款与退款结果表示处理完成
*/
Success(200, "业务处理成功"),
Accepted(202, "业务处理成功,等待服务器通知处理"),
/**
* 提示message消息内容
*/
Failure(400, "业务处理失败"),
/**
* 用户身份验证不通过,拉起登录窗口
*/
Unauthorized(401, "会话过期请重新登录"),
Forbidden(403, "无权限访问"),
Not_Found(404, "无效指令,或接口不存在"),
Method_Not_Allowed(405, "请求方法不支持"),
Precondition_Failed(412, "前提条件失败"),
Payload_Too_Large(413, "请求方法不支持"),
Upgrade_Required(426, "需要升级版本"),
Precondition_Required(428, "需要条件验证"),
/**
* 显示系统异常占位图
*/
Internal_Server_Error(500, "服务器内部异常");
public final int code;
public final String name;
ResultStatus(int code, String name) {
this.code = code;
this.name = name;
}
public short shortCode() {
return (short) code;
}
}