龙空技术网

企业微信机器人webhook消息通知

Clover幸运之星 277

前言:

当前朋友们对“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开发企业号红包