前言:
当前朋友们对“net开发企业号红包”都比较关注,咱们都需要知道一些“net开发企业号红包”的相关知识。那么小编在网摘上网罗了一些对于“net开发企业号红包””的相关知识,希望兄弟们能喜欢,小伙伴们一起来学习一下吧!一,机器人消息通知概述
在一些服务掉线以及错误日志通知的时候,我们可能会使用短信,群,电话等通知,为了配合项目可以稳定的运行,需要将一些错误等信息可以及时的做出通知,这个时候就需要使用到群机器人进行通知。
二,企业微信群机器人思路实现1,在企业微信中新建一个群2,在设置里面添加机器人3,拿到webhook地址三,机器人配置说明在终端某个群组添加机器人之后,创建者可以在机器人详情页看的该机器人特有的webhookurl。开发者可以按以下说明a向这个地址发起HTTP POST 请求,即可实现给该群组发送消息。下面举个简单的例子.
假设webhook是:
特别特别要注意:一定要保护好机器人的webhook地址,避免泄漏!不要分享到github、博客等可被公开查阅的地方,否则坏人就可以用你的机器人来发垃圾消息了。
以下是用curl工具往群组推送文本消息的示例(注意要将url替换成你的机器人webhook地址,content必须是utf8编码):
curl '; \ -H 'Content-Type: application/json' \ -d ' { "msgtype": "text", "text": { "content": "hello world" } }'当前自定义机器人支持文本(text)、markdown(markdown)、图片(image)、图文(news)四种消息类型。机器人的text/markdown类型消息支持在content中使用<@userid>扩展语法来@群成员3.1 消息类型及数据格式3.1.1 文本类型
{ "msgtype": "text", "text": { "content": "广州今日天气:29度,大部分多云,降雨概率:60%", "mentioned_list":["wangqing","@all"], "mentioned_mobile_list":["13800001111","@all"] }}
参数
是否必填
说明
msgtype
是
消息类型,此时固定为text
content
是
文本内容,最长不超过2048个字节,必须是utf8编码
mentioned_list
否
userid的列表,提醒群中的指定成员(@某个成员),@all表示提醒所有人,如果开发者获取不到userid,可以使用mentioned_mobile_list
mentioned_mobile_list
否
手机号列表,提醒手机号对应的群成员(@某个成员),@all表示提醒所有人
3.1.2 markdown类型
{ "msgtype": "markdown", "markdown": { "content": "实时新增用户反馈<font color=\"warning\">132例</font>,请相关同事注意。\n >类型:<font color=\"comment\">用户反馈</font> >普通用户反馈:<font color=\"comment\">117例</font> >VIP用户反馈:<font color=\"comment\">15例</font>" }}
参数
是否必填
说明
msgtype
是
消息类型,此时固定为markdown
content
是
markdown内容,最长不超过4096个字节,必须是utf8编码
目前支持的markdown语法是如下的子集:
标题 (支持1至6级标题,注意#与文字中间要有空格)
# 标题一## 标题二### 标题三#### 标题四##### 标题五###### 标题六加粗
**bold**链接
[这是一个链接]()行内代码段(暂不支持跨行)
`code`引用
> 引用文字字体颜色(只支持3种内置颜色)
<font color="info">绿色</font><font color="comment">灰色</font><font color="warning">橙红色</font>图片类型
{ "msgtype": "image", "image": { "base64": "DATA", "md5": "MD5" }}
参数
是否必填
说明
msgtype
是
消息类型,此时固定为image
base64
是
图片内容的base64编码
md5
是
图片内容(base64编码前)的md5值
注:图片(base64编码前)最大不能超过2M,支持JPG,PNG格式
3.1.3图文类型
{ "msgtype": "news", "news": { "articles" : [ { "title" : "中秋节礼品领取", "description" : "今年中秋节公司有豪礼相送", "url" : ";, "picurl" : "; } ] }}
参数
是否必填
说明
msgtype
是
消息类型,此时固定为news
articles
是
图文消息,一个图文消息支持1到8条图文
title
是
标题,不超过128个字节,超过会自动截断
description
否
描述,不超过512个字节,超过会自动截断
url
是
点击后跳转的链接。
picurl
否
图文消息的图片链接,支持JPG、PNG格式,较好的效果为大图 1068*455,小图150*150。
3.1.4文件类型
{ "msgtype": "file", "file": { "media_id": "3a8asd892asd8asd" }}
参数
是否必填
说明
msgtype
是
消息类型,此时固定为file
media_id
是
文件id,通过下文的文件上传接口获取
3.1.5 模版卡片类型文本通知模版卡片
{ "msgtype":"template_card", "template_card":{ "card_type":"text_notice", "source":{ "icon_url":";, "desc":"企业微信", "desc_color":0 }, "main_title":{ "title":"欢迎使用企业微信", "desc":"您的好友正在邀请您加入企业微信" }, "emphasis_content":{ "title":"100", "desc":"数据含义" }, "quote_area":{ "type":1, "url":";, "appid":"APPID", "pagepath":"PAGEPATH", "title":"引用文本标题", "quote_text":"Jack:企业微信真的很好用~\nBalian:超级好的一款软件!" }, "sub_title_text":"下载企业微信还能抢红包!", "horizontal_content_list":[ { "keyname":"邀请人", "value":"张三" }, { "keyname":"企微官网", "value":"点击访问", "type":1, "url":"; }, { "keyname":"企微下载", "value":"企业微信.apk", "type":2, "media_id":"MEDIAID" } ], "jump_list":[ { "type":1, "url":";, "title":"企业微信官网" }, { "type":2, "appid":"APPID", "pagepath":"PAGEPATH", "title":"跳转小程序" } ], "card_action":{ "type":1, "url":";, "appid":"APPID", "pagepath":"PAGEPATH" } }}
请求参数
参数
类型
必须
说明
msgtype
String
是
消息类型,此时的消息类型固定为template_card
template_card
Object
是
具体的模版卡片参数
template_card的参数说明
参数
类型
必须
说明
card_type
String
是
模版卡片的模版类型,文本通知模版卡片的类型为text_notice
source
Object
否
卡片来源样式信息,不需要来源样式可不填写
source.icon_url
String
否
来源图片的url
source.desc
String
否
来源图片的描述,建议不超过13个字
source.desc_color
Int
否
来源文字的颜色,目前支持:0(默认) 灰色,1 黑色,2 红色,3 绿色
main_title
Object
是
模版卡片的主要内容,包括一级标题和标题辅助信息
main_title.title
String
否
一级标题,建议不超过26个字。模版卡片主要内容的一级标题main_title.title和二级普通文本sub_title_text必须有一项填写
main_title.desc
String
否
标题辅助信息,建议不超过30个字
emphasis_content
Object
否
关键数据样式
emphasis_content.title
String
否
关键数据样式的数据内容,建议不超过10个字
emphasis_content.desc
String
否
关键数据样式的数据描述内容,建议不超过15个字
quote_area
Object
否
引用文献样式,建议不与关键数据共用
quote_area.type
Int
否
引用文献样式区域点击事件,0或不填代表没有点击事件,1 代表跳转url,2 代表跳转小程序
quote_area.url
String
否
点击跳转的url,quote_area.type是1时必填
quote_area.appid
String
否
点击跳转的小程序的appid,quote_area.type是2时必填
quote_area.pagepath
String
否
点击跳转的小程序的pagepath,quote_area.type是2时选填
quote_area.title
String
否
引用文献样式的标题
quote_area.quote_text
String
否
引用文献样式的引用文案
sub_title_text
String
否
二级普通文本,建议不超过112个字。模版卡片主要内容的一级标题main_title.title和二级普通文本sub_title_text必须有一项填写
horizontal_content_list
Object[]
否
二级标题+文本列表,该字段可为空数组,但有数据的话需确认对应字段是否必填,列表长度不超过6
horizontal_content_list.type
Int
否
链接类型,0或不填代表是普通文本,1 代表跳转url,2 代表下载附件,3 代表@员工
horizontal_content_list.keyname
String
是
二级标题,建议不超过5个字
horizontal_content_list.value
String
否
二级文本,如果horizontal_content_list.type是2,该字段代表文件名称(要包含文件类型),建议不超过26个字
horizontal_content_list.url
String
否
链接跳转的url,horizontal_content_list.type是1时必填
horizontal_content_list.media_id
String
否
附件的media_id
,horizontal_content_list.type是2时必填
horizontal_content_list.userid
String
否
被@的成员的userid,horizontal_content_list.type是3时必填
jump_list
Object[]
否
跳转指引样式的列表,该字段可为空数组,但有数据的话需确认对应字段是否必填,列表长度不超过3
jump_list.type
Int
否
跳转链接类型,0或不填代表不是链接,1 代表跳转url,2 代表跳转小程序
jump_list.title
String
是
跳转链接样式的文案内容,建议不超过13个字
jump_list.url
String
否
跳转链接的url,jump_list.type是1时必填
jump_list.appid
String
否
跳转链接的小程序的appid,jump_list.type是2时必填
jump_list.pagepath
String
否
跳转链接的小程序的pagepath,jump_list.type是2时选填
card_action
Object
是
整体卡片的点击跳转事件,text_notice模版卡片中该字段为必填项
card_action.type
Int
是
卡片跳转类型,1 代表跳转url,2 代表打开小程序。text_notice模版卡片中该字段取值范围为[1,2]
card_action.url
String
否
跳转事件的url,card_action.type是1时必填
card_action.appid
String
否
跳转事件的小程序的appid,card_action.type是2时必填
card_action.pagepath
String
否
跳转事件的小程序的pagepath,card_action.type是2时选填
图文展示模版卡片
{ "msgtype":"template_card", "template_card":{ "card_type":"news_notice", "source":{ "icon_url":";, "desc":"企业微信", "desc_color":0 }, "main_title":{ "title":"欢迎使用企业微信", "desc":"您的好友正在邀请您加入企业微信" }, "card_image":{ "url":";, "aspect_ratio":2.25 }, "image_text_area":{ "type":1, "url":";, "title":"欢迎使用企业微信", "desc":"您的好友正在邀请您加入企业微信", "image_url":"; }, "quote_area":{ "type":1, "url":";, "appid":"APPID", "pagepath":"PAGEPATH", "title":"引用文本标题", "quote_text":"Jack:企业微信真的很好用~\nBalian:超级好的一款软件!" }, "vertical_content_list":[ { "title":"惊喜红包等你来拿", "desc":"下载企业微信还能抢红包!" } ], "horizontal_content_list":[ { "keyname":"邀请人", "value":"张三" }, { "keyname":"企微官网", "value":"点击访问", "type":1, "url":"; }, { "keyname":"企微下载", "value":"企业微信.apk", "type":2, "media_id":"MEDIAID" } ], "jump_list":[ { "type":1, "url":";, "title":"企业微信官网" }, { "type":2, "appid":"APPID", "pagepath":"PAGEPATH", "title":"跳转小程序" } ], "card_action":{ "type":1, "url":";, "appid":"APPID", "pagepath":"PAGEPATH" } }}
请求参数
参数
类型
必须
说明
msgtype
String
是
模版卡片的消息类型为template_card
template_card
Object
是
具体的模版卡片参数
template_card的参数说明
参数
类型
必须
说明
card_type
String
是
模版卡片的模版类型,图文展示模版卡片的类型为news_notice
source
Object
否
卡片来源样式信息,不需要来源样式可不填写
source.icon_url
String
否
来源图片的url
source.desc
String
否
来源图片的描述,建议不超过13个字
source.desc_color
Int
否
来源文字的颜色,目前支持:0(默认) 灰色,1 黑色,2 红色,3 绿色
main_title
Object
是
模版卡片的主要内容,包括一级标题和标题辅助信息
main_title.title
String
是
一级标题,建议不超过26个字
main_title.desc
String
否
标题辅助信息,建议不超过30个字
card_image
Object
是
图片样式
card_image.url
String
是
图片的url
card_image.aspect_ratio
Float
否
图片的宽高比,宽高比要小于2.25,大于1.3,不填该参数默认1.3
image_text_area
Object
否
左图右文样式
image_text_area.type
Int
否
左图右文样式区域点击事件,0或不填代表没有点击事件,1 代表跳转url,2 代表跳转小程序
image_text_area.url
String
否
点击跳转的url,image_text_area.type是1时必填
image_text_area.appid
String
否
点击跳转的小程序的appid,必须是与当前应用关联的小程序,image_text_area.type是2时必填
image_text_area.pagepath
String
否
点击跳转的小程序的pagepath,image_text_area.type是2时选填
image_text_area.title
String
否
左图右文样式的标题
image_text_area.desc
String
否
左图右文样式的描述
image_text_area.image_url
String
是
左图右文样式的图片url
quote_area
Object
否
引用文献样式,建议不与关键数据共用
quote_area.type
Int
否
引用文献样式区域点击事件,0或不填代表没有点击事件,1 代表跳转url,2 代表跳转小程序
quote_area.url
String
否
点击跳转的url,quote_area.type是1时必填
quote_area.appid
String
否
点击跳转的小程序的appid,quote_area.type是2时必填
quote_area.pagepath
String
否
点击跳转的小程序的pagepath,quote_area.type是2时选填
quote_area.title
String
否
引用文献样式的标题
quote_area.quote_text
String
否
引用文献样式的引用文案
vertical_content_list
Object[]
否
卡片二级垂直内容,该字段可为空数组,但有数据的话需确认对应字段是否必填,列表长度不超过4
vertical_content_list.title
String
是
卡片二级标题,建议不超过26个字
vertical_content_list.desc
String
否
二级普通文本,建议不超过112个字
horizontal_content_list
Object[]
否
二级标题+文本列表,该字段可为空数组,但有数据的话需确认对应字段是否必填,列表长度不超过6
horizontal_content_list.type
Int
否
模版卡片的二级标题信息内容支持的类型,1是url,2是文件附件
horizontal_content_list.keyname
String
是
二级标题,建议不超过5个字
horizontal_content_list.value
String
否
二级文本,如果horizontal_content_list.type是2,该字段代表文件名称(要包含文件类型),建议不超过26个字
horizontal_content_list.url
String
否
链接跳转的url,horizontal_content_list.type是1时必填
horizontal_content_list.media_id
String
否
附件的media_id
,horizontal_content_list.type是2时必填
jump_list
Object[]
否
跳转指引样式的列表,该字段可为空数组,但有数据的话需确认对应字段是否必填,列表长度不超过3
jump_list.type
Int
否
跳转链接类型,0或不填代表不是链接,1 代表跳转url,2 代表跳转小程序
jump_list.title
String
是
跳转链接样式的文案内容,建议不超过13个字
jump_list.url
String
否
跳转链接的url,jump_list.type是1时必填
jump_list.appid
String
否
跳转链接的小程序的appid,jump_list.type是2时必填
jump_list.pagepath
String
否
跳转链接的小程序的pagepath,jump_list.type是2时选填
card_action
Object
是
整体卡片的点击跳转事件,news_notice模版卡片中该字段为必填项
card_action.type
Int
是
卡片跳转类型,1 代表跳转url,2 代表打开小程序。news_notice模版卡片中该字段取值范围为[1,2]
card_action.url
String
否
跳转事件的url,card_action.type是1时必填
card_action.appid
String
否
跳转事件的小程序的appid,card_action.type是2时必填
card_action.pagepath
String
否
跳转事件的小程序的pagepath,card_action.type是2时选填
3.2 消息发送频率限制
每个机器人发送的消息不能超过20条/分钟。
3.3 文件上传接口
素材上传得到media_id,该media_id仅三天内有效
media_id只能是对应上传文件的机器人可以使用
请求方式:POST(HTTPS)
请求地址:
使用multipart/form-data POST上传文件, 文件标识名为”media”
参数说明:
参数
必须
说明
key
是
调用接口凭证, 机器人webhookurl中的key参数
type
是
固定传file
POST的请求包中,form-data中媒体文件标识,应包含有 filename、filelength、content-type等信息
filename标识文件展示的名称。比如,使用该media_id发消息时,展示的文件名由该字段控制
请求示例:
POST HTTP/1.1Content-Type: multipart/form-data; boundary=-------------------------acebdf13572468Content-Length: 220---------------------------acebdf13572468Content-Disposition: form-data; name="media";filename="wework.txt"; filelength=6Content-Type: application/octet-streammytext---------------------------acebdf13572468--
返回数据:
{ "errcode": 0, "errmsg": "ok", "type": "file", "media_id": "1G6nrLmr5EC3MMb_-zK1dDdzmd0p7cNliYu9V5w7o8K0", "created_at": "1380000000"}
参数说明:
参数
说明
type
媒体文件类型,分别有图片(image)、语音(voice)、视频(video),普通文件(file)
media_id
媒体文件上传后获取的唯一标识,3天内有效
created_at
媒体文件上传时间戳
上传的文件限制:
要求文件大小在5B~20M之间四,JAVA代码实现
MessageSenderAutoConfiguration
@Slf4j@Configuration@AutoConfigureOrder(value = Ordered.HIGHEST_PRECEDENCE)public class MessageSenderAutoConfiguration { @Bean @ConditionalOnMissingBean(search = SearchStrategy.CURRENT) public MessageSenderProperties getProperties() { return new MessageSenderProperties(); } @Bean public WebhookMessageService getMessageSenderService() { MessageSenderProperties properties = getProperties(); if (ObjectUtils.isEmpty(properties.getWechat_webhooks())) { log.error("加载webhook—api默认配置失败"); } return new WebhookMessageServiceImpl(properties); }}
MessageSenderProperties
@Data@ConfigurationProperties(prefix = "spring.message")public class MessageSenderProperties { /** * message开关 */ private boolean enable = true; /** * wechat-webhookList */ private List<String> wechat_webhooks;}
Article
@Data@Accessors(chain = true)public class Article { private String title; private String description; private String url; private String picUrl;}
WorkWebhookMessage
@Data@Accessors(chain = true)public class WorkWebhookMessage { private String webhook; private String msgtype; private Text text; private Markdown markdown; private Image image; private News news; @Data @Accessors(chain = true) public static class Text { private String content; private List<String> mentioned_list; } @Data @Accessors(chain = true) public static class Markdown { private String content; } @Data @Accessors(chain = true) public static class Image { private String base64; private String md5; } @Data @Accessors(chain = true) public static class News { private List<Article> articles; } /** * @type 发送网络图片或者本地图片都可以 * @desc */ public static WorkWebhookMessage buildImageMessage(String imagePath) { File file; try { WorkWebhookMessage message = new WorkWebhookMessage(); message.setMsgtype("image"); WorkWebhookMessage.Image image = new WorkWebhookMessage.Image(); if (imagePath.startsWith("http")) { file = Fileutils.downloadFile(imagePath, "image", IDUtils.genRandom("image-", 15)); image.setBase64(ImageToBase64.ImageToBase64(file)); image.setMd5(MD5Utils.getFileMD5String(file)); message.setImage(image); Fileutils.keepTop(file, 1); } else { file = new File(imagePath); image.setBase64(ImageToBase64.ImageToBase64(file)); image.setMd5(MD5Utils.getFileMD5String(file)); message.setImage(image); } return message; } catch (Exception e) { e.printStackTrace(); return null; } } /** * @type 构建markdown消息 * @desc */ public static WorkWebhookMessage buildMarkDownMessage(MarkdownBuffer content) { WorkWebhookMessage message = new WorkWebhookMessage(); message.setMsgtype("markdown"); WorkWebhookMessage.Markdown markdown = new WorkWebhookMessage.Markdown(); markdown.setContent(content.toString()); message.setMarkdown(markdown); return message; } /** * @type 批量构建图文卡片链接消息 * @desc */ public static WorkWebhookMessage buildNewsMessage(List<Article> articles) { WorkWebhookMessage message = new WorkWebhookMessage(); message.setMsgtype("news"); WorkWebhookMessage.News news = new WorkWebhookMessage.News(); news.setArticles(articles); message.setNews(news); return message; } /** * @type 构建图文卡片链接消息 * @desc */ public static WorkWebhookMessage buildNewsMessage(Article article) { WorkWebhookMessage message = new WorkWebhookMessage(); message.setMsgtype("news"); WorkWebhookMessage.News news = new WorkWebhookMessage.News(); List<Article> list = new ArrayList(); list.add(article); news.setArticles(list); message.setNews(news); return message; } /** * @type 构建普通文本消息 * @desc */ public static WorkWebhookMessage buildText(String content) { return buildText(content, false); } /** * @type 构建普通文本消息(@ALL 指定webhookapi) * @desc */ public static WorkWebhookMessage buildText(String content, boolean atAll) { WorkWebhookMessage message = new WorkWebhookMessage(); message.setMsgtype("text"); WorkWebhookMessage.Text text = new WorkWebhookMessage.Text(); text.setContent(content); List<String> mentioned_list = text.getMentioned_list(); if (atAll) { if (mentioned_list == null) { mentioned_list = new ArrayList<>(); } mentioned_list.add("@all"); text.setMentioned_list(mentioned_list); } message.setText(text); return message; }}
WebhookMessageService
public interface WebhookMessageService { /** * @type 发送企业微信消息--系统配置发送者 * @desc */ boolean send(WorkWebhookMessage workWebhookMessage); /** * @type 发送企业微信消息--自定义发送者 * @desc */ boolean send(WorkWebhookMessage workWebhookMessage, String webhook);}
WebhookMessageServiceImpl
@Slf4jpublic class WebhookMessageServiceImpl implements WebhookMessageService { private List<String> wechat_webhooks; public WebhookMessageServiceImpl(MessageSenderProperties messagesenderProperties) { this.wechat_webhooks = messagesenderProperties.getWechat_webhooks(); if (wechat_webhooks == null || wechat_webhooks.size() == 0) { log.error("没有配置webhook"); } } @Override public boolean send(WorkWebhookMessage weWorkWebhookMessage) { return send(weWorkWebhookMessage, wechat_webhooks.get(0)); } @Override public boolean send(WorkWebhookMessage weWorkWebhookMessage, String webhook) { if (StringUtils.isEmpty(webhook)) { return true; } Map<String, String> headerParams = new HashMap<>(); headerParams.put("Content-Type", "application/json"); headerParams.put("charset", "utf-8"); String responseStr = HttpClientUtil.doPostJson(webhook, headerParams, JSON.toJSONString(weWorkWebhookMessage)); if (JSON.parseObject(responseStr).getString("errmsg").equals("ok")) { log.warn("webHookSendMessage failed:{}",responseStr); return true; } else { return false; } }}
Base64Utils
public class Base64Utils { public static Key DEFAULT_KEY = null; public static final String DEFAULT_SECRET_KEY1 = "?:P)(OL><KI*&UJMNHY^%TGBVFR$#EDCXSW@!QAZ"; public static final String DEFAULT_SECRET_KEY2 = "1qaz2wsx3edc4rfv5tgb6yhn7ujm8ik,9ol.0p;/"; public static final String DEFAULT_SECRET_KEY3 = "!QAZ@WSX#EDC$RFV%TGB^YHN&UJM*IK<(OL>)P:?"; public static final String DEFAULT_SECRET_KEY4 = "1qaz@WSX3edc$RFV5tgb^YHN7ujm*IK<9ol.)P:?"; public static final String DEFAULT_SECRET_KEY5 = "!QAZ2wsx#EDC4rfv%TGB6yhn&UJM8ik,(OL>0p;/"; public static final String DEFAULT_SECRET_KEY6 = "1qaz2wsx3edc4rfv5tgb^YHN&UJM*IK<(OL>)P:?"; public static final String DEFAULT_SECRET_KEY = DEFAULT_SECRET_KEY1; public static final String DES = "DES"; public static final Base32 base32 = new Base32(); static { DEFAULT_KEY = obtainKey(DEFAULT_SECRET_KEY); } /** * 获得key **/ public static Key obtainKey(String key) { if (key == null) { return DEFAULT_KEY; } try { KeyGenerator keyGenerator = KeyGenerator.getInstance(DES); //替换开始 SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG"); secureRandom.setSeed(key.getBytes()); keyGenerator.init(secureRandom); return keyGenerator.generateKey(); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } return null; } /** * 加密<br> * String明文输入,String密文输出 */ public static String encode(String str) { return encode64(null, str); } /** * 加密<br> * String明文输入,String密文输出 */ public static String encode64(String key, String str) { return Base64.encodeBase64URLSafeString(obtainEncode(key, str.getBytes())); } /** * 加密<br> * String明文输入,String密文输出 */ public static String encode32(String key, String str) { return base32.encodeAsString(obtainEncode(key, str.getBytes())).replaceAll("=", ""); } /** * 加密<br> * String明文输入,String密文输出 */ public static String encode16(String key, String str) { return Hex.encodeHexString(obtainEncode(key, str.getBytes())); } /** * 解密<br> * 以String密文输入,String明文输出 */ public static String decode(String str) { return decode64(null, str); } /** * 解密<br> * 以String密文输入,String明文输出 */ public static String decode64(String key, String str) { return new String(obtainDecode(key, Base64.decodeBase64(str))); } /** * 解密<br> * 以String密文输入,String明文输出 */ public static String decode32(String key, String str) { return new String(obtainDecode(key, base32.decode(str))); } /** * 解密<br> * 以String密文输入,String明文输出 */ public static String decode16(String key, String str) { try { return new String(obtainDecode(key, Hex.decodeHex(str.toCharArray()))); } catch (DecoderException e) { e.printStackTrace(); } return null; } /** * 加密<br> * 以byte[]明文输入,byte[]密文输出 */ private static byte[] obtainEncode(String key, byte[] str) { byte[] byteFina = null; Cipher cipher; try { Key key1 = obtainKey(key); cipher = Cipher.getInstance(DES); cipher.init(Cipher.ENCRYPT_MODE, key1); byteFina = cipher.doFinal(str); } catch (Exception e) { e.printStackTrace(); } finally { cipher = null; } return byteFina; } /** * 解密<br> * 以byte[]密文输入,以byte[]明文输出 */ private static byte[] obtainDecode(String key, byte[] str) { Cipher cipher; byte[] byteFina = null; try { Key key1 = obtainKey(key); cipher = Cipher.getInstance(DES); cipher.init(Cipher.DECRYPT_MODE, key1); byteFina = cipher.doFinal(str); } catch (Exception e) { e.printStackTrace(); } finally { cipher = null; } return byteFina; }}
Fileutils
/** * Java原生的API可用于发送HTTP请求,即java.net.URL、java.net.URLConnection,这些API很好用、很常用, * 但不够简便; * <p> * 1.通过统一资源定位器(java.net.URL)获取连接器(java.net.URLConnection) 2.设置请求的参数 3.发送请求 * 4.以输入流的形式获取返回内容 5.关闭输入流 */public class Fileutils { private static Logger logger = Logger.getLogger(Fileutils.class.getName()); /** * 下载网络文件 */ public static File downloadFile(String urlPath, String folderName, String fileName) throws Exception { File folder = new File(folderName); if (!folder.exists()) { folder.mkdir(); } File file = new File(folder + File.separator + fileName); BufferedInputStream bin = null; OutputStream out = null; try { // 统一资源 URL url = new URL(urlPath); // 连接类的父类,抽象类 URLConnection urlConnection = url.openConnection(); // http的连接类 HttpURLConnection httpURLConnection = (HttpURLConnection) urlConnection; // 设定请求的方法,默认是GET httpURLConnection.setRequestMethod("GET"); // 设置字符编码 httpURLConnection.setRequestProperty("Charset", "UTF-8"); // 打开到此 URL 引用的资源的通信链接(如果尚未建立这样的连接)。 httpURLConnection.connect(); // 文件大小 int fileLength = httpURLConnection.getContentLength(); // 文件名 String filePathUrl = httpURLConnection.getURL().getFile(); String fileFullName = filePathUrl.substring(filePathUrl.lastIndexOf(File.separatorChar) + 1); fileFullName = fileFullName.substring(fileFullName.lastIndexOf("/") + 1); url.openConnection(); bin = new BufferedInputStream(httpURLConnection.getInputStream()); out = new FileOutputStream(file); int size = 0; int len = 0; byte[] buf = new byte[1024]; while ((size = bin.read(buf)) != -1) { len += size; out.write(buf, 0, size); } return file; } catch (Exception e) { throw new RuntimeException(e.toString() + "文件下载异常,请检查下载链接$$" + urlPath); } finally { if (bin != null) { bin.close(); } if (out != null) { out.close(); } } } /** * 方法描述:保持最大的文件数量 * 返回类型: * 修改内容:(若修改了请注明修改人,修改时间,修改内容) */ public static void keepTop(File file, int max) { File[] files = file.getParentFile().listFiles(); if (files.length > max) { List<File> list = new ArrayList<>(); for (int i = 0; i < files.length; i++) { list.add(files[i]); } AtomicInteger removeCounter = new AtomicInteger(files.length - max); list.stream().sorted(Comparator.comparingLong(File::lastModified)).forEach(ele -> { if (removeCounter.get() > 0) { ele.delete(); } removeCounter.getAndDecrement(); }); } }}
HttpClientUtil
@SuppressWarnings("all")public class HttpClientUtil { public static String doGet(String url, Map<String, String> param, String username, String password) { // 创建Httpclient对象 CloseableHttpClient httpclient = HttpClients.createDefault(); String resultString = ""; CloseableHttpResponse response = null; try { // 创建uri URIBuilder builder = new URIBuilder(url); if (param != null) { for (String key : param.keySet()) { builder.addParameter(key, param.get(key)); } } URI uri = builder.build(); // 创建http GET请求 HttpGet httpGet = new HttpGet(uri); httpGet.addHeader("Authorization", "Basic " + Base64.getUrlEncoder().encodeToString((username + ":" + password).getBytes())); // 执行请求 response = httpclient.execute(httpGet); // 判断返回状态是否为200 if (response.getStatusLine().getStatusCode() == 200) { resultString = EntityUtils.toString(response.getEntity(), "UTF-8"); // UTF-8 } } catch (Exception e) { e.printStackTrace(); } finally { try { if (response != null) { response.close(); } httpclient.close(); } catch (IOException e) { e.printStackTrace(); } } return resultString; } public static String doGet(String url, String username, String password) { return doGet(url, null, username, password); } public static String doPost(String url, Map<String, String> param) { return doPost(url, param, null); } private final static CloseableHttpClient getBasicHttpClient(String username, String password) { // 创建HttpClientBuilder HttpClientBuilder httpClientBuilder = HttpClientBuilder.create(); // 设置BasicAuth CredentialsProvider provider = new BasicCredentialsProvider(); // Create the authentication scope AuthScope scope = new AuthScope(AuthScope.ANY_HOST, AuthScope.ANY_PORT, AuthScope.ANY_REALM); // Create credential pair,在此处填写用户名和密码 UsernamePasswordCredentials credentials = new UsernamePasswordCredentials(username, password); // Inject the credentials provider.setCredentials(scope, credentials); // Set the default credentials provider httpClientBuilder.setDefaultCredentialsProvider(provider); // HttpClient CloseableHttpClient closeableHttpClient = httpClientBuilder.build(); return closeableHttpClient; } public static String doPost(String url, Map<String, String> param, Map<String, String> header) { // 创建Httpclient对象 CloseableHttpClient httpClient = getBasicHttpClient("huanglei", "111111"); CloseableHttpResponse response = null; String resultString = ""; try { // 创建Http Post请求 HttpPost httpPost = new HttpPost(url); // 创建header头信息 if (header != null) { for (Map.Entry<String, String> entry : header.entrySet()) { httpPost.addHeader(entry.getKey(), entry.getValue()); } } // 创建参数列表 if (param != null) { List<NameValuePair> paramList = new ArrayList<>(); for (String key : param.keySet()) { paramList.add(new BasicNameValuePair(key, param.get(key))); } // 模拟表单 UrlEncodedFormEntity entity = new UrlEncodedFormEntity(paramList, "utf-8"); httpPost.setEntity(entity); } // 执行http请求 response = httpClient.execute(httpPost); resultString = EntityUtils.toString(response.getEntity(), "utf-8"); } catch (Exception e) { e.printStackTrace(); } finally { try { response.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } return resultString; } public static String doPost(String url) { return doPost(url, null); } public static String doPostJson(String url, String json) { // 创建Httpclient对象 CloseableHttpClient httpClient = HttpClients.createDefault(); CloseableHttpResponse response = null; String resultString = ""; try { // 创建Http Post请求 HttpPost httpPost = new HttpPost(url); // 添加header httpPost = (HttpPost) addHeaders(httpPost, null); // 创建请求内容 StringEntity entity = new StringEntity(json, ContentType.APPLICATION_JSON); httpPost.setEntity(entity); // 执行http请求 response = httpClient.execute(httpPost); resultString = EntityUtils.toString(response.getEntity(), "utf-8"); } catch (Exception e) { e.printStackTrace(); } finally { try { response.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } return resultString; } public static String doPostJson(String url, Map<String, String> headers, String json) { // 创建Httpclient对象 CloseableHttpClient httpClient = HttpClients.createDefault(); CloseableHttpResponse response = null; String resultString = ""; try { // 创建Http Post请求 HttpPost httpPost = new HttpPost(url); // 添加header httpPost = (HttpPost) addHeaders(httpPost, headers); // 创建请求内容 StringEntity entity = new StringEntity(json, ContentType.APPLICATION_JSON); httpPost.setEntity(entity); // 执行http请求 response = httpClient.execute(httpPost); resultString = EntityUtils.toString(response.getEntity(), "utf-8"); } catch (Exception e) { e.printStackTrace(); } finally { try { response.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } return resultString; } private static HttpRequestBase addHeaders(HttpRequestBase httpRequest, Map<String, String> headers) { // 设置请求头信息,鉴权// httpRequest.setHeader("Authorization", "Bearer da3efcbf-0845-4fe3-8aba-ee040be542c0"); httpRequest.addHeader("Authorization", "1231321321313132132"); for (Map.Entry<String, String> entry : headers.entrySet()) { httpRequest.addHeader(entry.getKey(), entry.getValue()); } // 设置配置请求参数 RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(35000)// 连接主机服务超时时间 .setConnectionRequestTimeout(35000)// 请求超时时间 .setSocketTimeout(60000)// 数据读取超时时间 .build(); // 为httpGet实例设置配置 httpRequest.setConfig(requestConfig); return httpRequest; } public static void main(String[] args) { }}
IDUtils
public class IDUtils { /** * 图片名生成 */ public static String genImageName() { //取当前时间的长整形值包含毫秒 long millis = System.currentTimeMillis(); //long millis = System.nanoTime(); //加上三位随机数 Random random = new Random(); int end3 = random.nextInt(999); //如果不足三位前面补0 String str = millis + String.format("%03d", end3); return str; } /** * 商品id生成 */ public static String genRandom() { //取当前时间的长整形值包含毫秒 long millis = System.currentTimeMillis(); //long millis = System.nanoTime(); //加上两位随机数 Random random = new Random(); int end2 = random.nextInt(99); //如果不足两位前面补0 String str = millis + String.format("%02d", end2); long id = new Long(str); String timeId = Long.toString(id); return timeId; } /** * 生成UUID工具类 */ public static String getUUID() { String uuid = UUID.randomUUID().toString().replace("-", ""); return uuid; } // 生成时间+随机数的id public static String genRandom(String pre, Integer needLength) { SimpleDateFormat format = new SimpleDateFormat("yyyyMMddHHmm"); String part2 = format.format(new Date()); int originLength = pre.length() + part2.length(); if (needLength == null || needLength <= originLength) { needLength = pre.length() + part2.length(); } StringBuffer part3 = new StringBuffer(); Random random = new Random(); for (int i = 0; i < needLength - originLength; i++) { int rand = random.nextInt(10); part3.append(rand); } return pre + "" + part2 + "" + part3; } // 生成20位随机id public static Long genRandomId() { long timeMillis = System.currentTimeMillis(); Random random = new Random(); StringBuffer buffer = new StringBuffer(); for (int i = 0; i < 6; i++) { buffer.append(random.nextInt(10)); } String id = timeMillis + buffer.toString(); return Long.valueOf(id); } // 生成时间+随机数的id public static String genRandom(String pre, int needLength) { if (needLength <= pre.length()) { needLength = pre.length(); } StringBuffer part3 = new StringBuffer(); Random random = new Random(); for (int i = 0; i < needLength - pre.length(); i++) { int rand = random.nextInt(10); part3.append(rand); } return pre + "" + part3; } public static void main(String[] args) { } public static String genSMSCode() { String value = ""; Random random = new Random(); int gen = random.nextInt(2); String charOrNum = gen % 2 == 0 ? "char" : "num"; if ("char".equals(charOrNum)) { //字符 int temp = random.nextInt(2) % 2 == 0 ? 65 : 97; int ascii = random.nextInt(26); value += (char) (ascii + temp); } else if ("num".equals(charOrNum)) { //是数字 value += String.valueOf(random.nextInt(10)); } return value; } public static String genSMSCode_num() { String value = ""; Random random = new Random(); while (true) { value += String.valueOf(random.nextInt(10)); if (value.length() == 6) { break; } } return value; } public static String genOssKey(String originalFilename) { String suffix = originalFilename.substring(originalFilename.lastIndexOf(".")); return getUUID() + suffix; }}
ImageToBase64
public class ImageToBase64 { private static String strNetImageToBase64; /** * 网络图片转换Base64的方法 * * @param netImagePath */ public static String NetImageToBase64(String netImagePath) { final ByteArrayOutputStream data = new ByteArrayOutputStream(); try { // 创建URL URL url = new URL(netImagePath); final byte[] by = new byte[1024]; // 创建链接 final HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setRequestMethod("GET"); conn.setConnectTimeout(5000); new Thread(new Runnable() { @Override public void run() { try { InputStream is = conn.getInputStream(); // 将内容读取内存中 int len = -1; while ((len = is.read(by)) != -1) { data.write(by, 0, len); } // 对字节数组Base64编码 Base64.Encoder encoder = Base64.getEncoder(); strNetImageToBase64 = encoder.encodeToString(data.toByteArray()); // 关闭流 is.close(); } catch (IOException e) { e.printStackTrace(); } } }).start(); } catch (IOException e) { e.printStackTrace(); } return strNetImageToBase64; } /** * 本地图片转换Base64的方法 * * @param imgPath */ public static String ImageToBase64(String imgPath) { return ImageToBase64(new File(imgPath)); } /** * 本地图片转换Base64的方法 * */ public static String ImageToBase64(File imageFile) { byte[] data = null; // 读取图片字节数组 try { InputStream in = new FileInputStream(imageFile); data = new byte[in.available()]; in.read(data); in.close(); } catch (IOException e) { e.printStackTrace(); } // 对字节数组Base64编码 Base64.Encoder encoder = Base64.getEncoder(); // 返回Base64编码过的字节数组字符串 return encoder.encodeToString(Objects.requireNonNull(data)); }}
MarkdownBuffer
public class MarkdownBuffer { private static final String NEXT_LINE = "\n"; private StringBuffer buffer = new StringBuffer(); public MarkdownBuffer h6(String text) { buffer.append("###### " + text); return this; } public MarkdownBuffer h5(String text) { buffer.append("##### " + text); return this; } public MarkdownBuffer h4(String text) { buffer.append("#### " + text); return this; } public MarkdownBuffer h3(String text) { buffer.append("### " + text); return this; } public MarkdownBuffer h2(String text) { buffer.append("## " + text); return this; } public MarkdownBuffer h1(String h1Text) { buffer.append("# " + h1Text); return this; } public MarkdownBuffer code(String code) { buffer.append("`" + code + "`"); return this; } public MarkdownBuffer link(String link, String url) { buffer.append("[" + link + "](" + url + ")"); return this; } public MarkdownBuffer text(String text) { buffer.append(text); return this; } public MarkdownBuffer quote(String text) { buffer.append("> " + text); return this; } public MarkdownBuffer orange(String orangeText) { buffer.append("<font color=\"warning\">" + orangeText + "</font>"); return this; } public MarkdownBuffer green(String greenText) { buffer.append("<font color=\"info\">" + greenText + "</font>"); return this; } public MarkdownBuffer gray(String grayText) { buffer.append("<font color=\"comment\">" + grayText + "</font>"); return this; } public MarkdownBuffer bold(String boldText) { buffer.append("**" + boldText + "**"); return this; } public MarkdownBuffer nextLine() { buffer.append(NEXT_LINE); return this; } public MarkdownBuffer quoteEnd() { buffer.append(NEXT_LINE).append(NEXT_LINE); return this; } @Override public String toString() { return this.buffer.toString(); }}
MD5Utils
public class MD5Utils { /** * 默认的密码字符串组合,用来将字节转换成 16 进制表示的字符,apache校验下载的文件的正确性用的就是默认的这个组合 */ protected static char hexDigits[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; protected static MessageDigest messagedigest = null; static { try { messagedigest = MessageDigest.getInstance("MD5"); } catch (NoSuchAlgorithmException nsaex) { System.err.println(MD5Utils.class.getName() + "初始化失败,MessageDigest不支持MD5Util。"); nsaex.printStackTrace(); } } /** * 生成字符串的md5校验值 * * @param s * @return */ public static String getMD5String(String s) { return getMD5String(s.getBytes()); } /** * 判断字符串的md5校验码是否与一个已知的md5码相匹配 * * @param password * 要校验的字符串 * @param md5PwdStr * 已知的md5校验码 * @return */ public static boolean checkPassword(String password, String md5PwdStr) { String s = getMD5String(password); return s.equals(md5PwdStr); } /** * 生成文件的md5校验值 * * @param file * @return * @throws IOException */ public static String getFileMD5String(File file) throws IOException { InputStream fis; fis = new FileInputStream(file); byte[] buffer = new byte[1024]; int numRead = 0; while ((numRead = fis.read(buffer)) > 0) { messagedigest.update(buffer, 0, numRead); } fis.close(); return bufferToHex(messagedigest.digest()); } /** * JDK1.4中不支持以MappedByteBuffer类型为参数update方法,并且网上有讨论要慎用MappedByteBuffer, * 原因是当使用 FileChannel.map 方法时,MappedByteBuffer 已经在系统内占用了一个句柄, 而使用 * FileChannel.close 方法是无法释放这个句柄的,且FileChannel有没有提供类似 unmap 的方法, * 因此会出现无法删除文件的情况。 * * 不推荐使用 * * @param file * @return * @throws IOException */ public static String getFileMD5String_old(File file) throws IOException { FileInputStream in = new FileInputStream(file); FileChannel ch = in.getChannel(); MappedByteBuffer byteBuffer = ch.map(FileChannel.MapMode.READ_ONLY, 0, file.length()); messagedigest.update(byteBuffer); in.close(); return bufferToHex(messagedigest.digest()); } public static String getMD5String(byte[] bytes) { messagedigest.update(bytes); return bufferToHex(messagedigest.digest()); } private static String bufferToHex(byte bytes[]) { return bufferToHex(bytes, 0, bytes.length); } private static String bufferToHex(byte bytes[], int m, int n) { StringBuffer stringbuffer = new StringBuffer(2 * n); int k = m + n; for (int l = m; l < k; l++) { appendHexPair(bytes[l], stringbuffer); } return stringbuffer.toString(); } private static void appendHexPair(byte bt, StringBuffer stringbuffer) { char c0 = hexDigits[(bt & 0xf0) >> 4];// 取字节中高 4 位的数字转换, >>> // 为逻辑右移,将符号位一起右移,此处未发现两种符号有何不同 char c1 = hexDigits[bt & 0xf];// 取字节中低 4 位的数字转换 stringbuffer.append(c0); stringbuffer.append(c1); } public static void main(String[] args) throws IOException { long begin = System.currentTimeMillis(); File file = new File("D:/BaiduNetdiskDownload/01_SpringBoot全套视频教程2018年3月份录制2.0.x版本/01-SpringBoot简介.avi"); if(!file.exists()){ System.out.println("不存在"); } String md5 = getFileMD5String(file); String md5_a = getMD5String("a"); long end = System.currentTimeMillis(); System.out.println("md5:" + md5 + " time:" + ((end - begin) / 1000) + "s"); System.out.println(file.getPath()); } public static String getNetFileMD5String(String imagePath) { try { // 创建URL URL url = new URL(imagePath); final byte[] by = new byte[1024]; // 创建链接 final HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setRequestMethod("GET"); conn.setConnectTimeout(5000); InputStream is = conn.getInputStream(); File temp = File.createTempFile("temp", ".img"); FileOutputStream outputStream = new FileOutputStream(temp); int len = -1; while ((len = is.read(by)) != -1) { outputStream.write(by, 0, len); } // 关闭流 is.close(); outputStream.close(); String md5String = getFileMD5String(temp); temp.delete(); return md5String; } catch (IOException e) { e.printStackTrace(); return null; } }}
TextBuffer
public class TextBuffer { private static final String NEXT_LINE = "\n"; private StringBuffer buffer = new StringBuffer(); public TextBuffer nextLine() { buffer.append( NEXT_LINE); return this; } public TextBuffer append(String text) { buffer.append(text); return this; } @Override public String toString() { return this.buffer.toString(); }}
标签: #net开发企业号红包