企业微信推送应用消息-图片(news)/图文(npmnews)/卡片/文字


前言

最近在做一些企业微信应用推送消息的一些东西,总结一下。

一、HTTP发送get、post方法

插件:基于OkHttp发送请求。

1.引入依赖库


2.get、post方法

package io.yunke.common.utils;

import com.alibaba.fastjson.JSON;
import okhttp3.*;

import java.util.Map;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicReference;

public class HTTP {

    private static final MediaType JSONTYPE
            = MediaType.get("application/json; charset=utf-8");

    public static <T> T post(String url, Object obj, Class<T> clazz) {
        RequestBody body = RequestBody.create(JSONTYPE, JSON.toJSONString(obj));
        Request request = new Request.Builder()
                .url(url)
                .post(body)
                .build();
        try (Response response = new OkHttpClient().newCall(request).execute()) {
            return JSON.parseObject(Objects.requireNonNull(response.body()).string(), clazz);
        } catch (Exception e) {
            return null;
        }
    }

    public static <T> T get(String url, Map<String, String> param, Class<T> clazz) {
        // 处理问号传值
        AtomicReference<String> _url = new AtomicReference<>("");
        if (param.keySet().size() != 0) {
            _url.set(url + "?");
            param.forEach((k, v) -> {
                String u = _url.get();
                u += (k + "=" + v + "&");
                _url.set(u);
            });
        } else {
            _url.set(url);
        }
        Request request = new Request.Builder()
                .url(_url.get())
                .get()
                .build();
        try (Response response = new OkHttpClient().newCall(request).execute()) {
            return JSON.parseObject(Objects.requireNonNull(response.body()).string(), clazz);
        } catch (Exception e) {
            return null;
        }
    }
}

二、构造发送json与企业微信返回类

1. 构造json对象

字段意思,有详细的解释;
企业微信发送应用消息-图片发送
在这里插入图片描述

// 企业微信标准发送格式
{
   "touser" : "UserID1|UserID2|UserID3",
   "toparty" : "PartyID1 | PartyID2",
   "totag" : "TagID1 | TagID2",
   "msgtype" : "news",
   "agentid" : 1,
   "news" : {
       "articles" : [
           {
               "title" : "中秋节礼品领取",
               "description" : "今年中秋节公司有豪礼相送",
               "url" : "URL",
               "picurl" : "http://res.mail.qq.com/node/ww/wwopenmng/images/independent/doc/test_pic_msg1.png", 
			   "appid": "wx123123123123123",
        	   "pagepath": "pages/index?userid=zhangsan&orderid=123123123",
           }
                ]
   },
   "enable_id_trans": 0,
   "enable_duplicate_check": 0,
   "duplicate_check_interval": 1800
}

构造实体类(示例):

package io.yunke.modules.wechat.entity;

import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.annotations.ApiModelProperty;
import io.yunke.modules.wechat.vo.PictureNewsVo;
import lombok.Data;

import java.io.Serializable;

@Data
@TableName("picture_news_push")
public class PictureNewsPushEntity implements Serializable {

    @TableId
    private Long id;
    /**
     * 格式:"UserID1"或"UserID1|UserID2|UserID3"
     */
    @ApiModelProperty(value = "推送给谁")
    private String touser;

    /**
     * 格式:"PartyID1"或"PartyID1 | PartyID2"
     */
    @ApiModelProperty(value = "部门")
    private String toparty;
    /**
     * 标签ID列表
     */
    @ApiModelProperty(value = "标签")
    private String totag;
    /**
     * 消息类型
     */
    @ApiModelProperty(value = "消息类型")
    private String msgtype;
    /**
     * 企业应用的id,整型。
     */
    @ApiModelProperty(value = "企业应用的id,整型。")
    private String agentid;

    /**
     * 表示是否开启id转译,0表示否,1表示是,默认0
     */
    @ApiModelProperty(value = "表示是否开启id转译,0表示否,1表示是,默认0")
    private Integer enable_id_trans;
    /**
     * 表示是否开启重复消息检查,0表示否,1表示是,默认0
     */
    @ApiModelProperty(value = "表示是否开启重复消息检查,0表示否,1表示是,默认0")
    private Integer enable_duplicate_check;

    @TableField(exist = false)
    private PictureNewsVo news;
}

内容实体类(示例):

@Data
@TableName("picture_content")
public class PictureWordContentEntity {
    /*
               {
               "title": "Title",
               "thumb_media_id": "MEDIA_ID",
               "author": "Author",
               "content_source_url": "URL",
               "content": "Content",
               "digest": "Digest description"
            }
     */
    @ApiModelProperty(value = "标题")
    private String title;
    @ApiModelProperty(value = "上传临时文件返回的media_id")
    private String thumb_media_id;
    @ApiModelProperty(value = "作者")
    private String author;
    @ApiModelProperty(value = "跳转的url")
    private String content_source_url;
    @ApiModelProperty(value = "内容")
    private String content;
    @ApiModelProperty(value = "企业应用的id")
    private String digest;
}

中间表实体类(示例):

@Data
public class PictureNewsVo implements Serializable {
    private List<PictureNewsContentEntity> articles;
}

构造返回数据结果(示例):

/**
 * @notes: 企业微信返回数据
 */
@Data
public class WeChatResultVo {
    /**
     * {
     *   "errcode" : 0,
     *   "errmsg" : "ok",
     *   "invaliduser" : "userid1|userid2",
     *   "invalidparty" : "partyid1|partyid2",
     *   "invalidtag": "tagid1|tagid2",
     *   "msgid": "xxxx",
     *   "response_code": "xyzxyz"
     * }
     */

    private Integer errcode;
    private String errmsg;

    private String invaliduser;
    private String invalidparty;
    private String invalidtag;
    private String msgid;
    private String response_code;
}

2.获取token

token存在redis中缓存,启动获取token(示例):

import io.yunke.common.constant.WeChatConstant;
import io.yunke.common.utils.HTTP;
import org.apache.commons.lang.StringUtils;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * @notes: 企业微信调用接口
 */
@Slf4j
@Component
public class Oauth {

    @Autowired
    StringRedisTemplate redisTemplate;

    @Value("${tencent.weixin.qiye.corpid}")
    private String corpid;

    @Value("${tencent.weixin.qiye.corpsecret}")
    private String corpsecret;

    private static String sCorpid;
    private static String sCorpsecret;

    public static String accessToken;

    private Map generateAccessToken() {
        Map parMap = new HashMap<>();
        parMap.put("corpid", sCorpid);
        parMap.put("corpsecret", sCorpsecret);
        Map map = HTTP.get(WeChatConstant.GETTOKEN_URL, parMap, Map.class);
        return map;
    }

    @PostConstruct
    public void getCorpidAndCorpsecret() {
        sCorpid = this.corpid;
        sCorpsecret = this.corpsecret;
    }

    /**
     * 每1个小时58分钟获取一次tokne
     * @return
     */
    @PostConstruct
    @Scheduled(cron = "0 0/58 0/1 * * ? ")
    public String getToken() {
        log.info("开始查询token");
        String token = redisTemplate.opsForValue().get("TOKEN");
        if (StringUtils.isNotEmpty(token)) return token;
        log.info("远程查询token");
        Map map = generateAccessToken();
        int error = (int) map.get(WeChatConstant.ERRORCODE);
        if (error == 0) {
            accessToken = map.get(WeChatConstant.ACCESS_TOKEN).toString();
            log.info("正则表达式:{}", accessToken);
            redisTemplate.opsForValue().set("TOKEN", accessToken, 2, TimeUnit.HOURS);
            return accessToken;
        } else {
            log.error("获取验证码错误!");
            return null;
        }
    }
}

该处使用的url网络请求的数据。

三、发送请求

post请求。


    @Override
    public void pushPicture(PictureNewsPushEntity pictureNewsPush) {
        String token = oauth.getToken();
        // 企业微信推送
        String itemUrl = new StringBuffer(WeChatConstant.MESSAGE_SEND).append("?").append(WeChatConstant.ACCESS_TOKEN).append("=").append(token).toString();
        log.info("wx send: {} ", JSON.toJSONString(pictureNewsPush));
        WeChatResultVo res = HTTP.post(itemUrl, pictureNewsPush, WeChatResultVo.class);
        log.info("wx send resp: {}", JSON.toJSONString(res));
    }

测试代码

import com.alibaba.fastjson.JSON;
import io.yunke.common.constant.WeChatConstant;
import io.yunke.common.utils.HTTP;
import io.yunke.common.utils.RedisUtils;
import io.yunke.modules.sys.entity.SysUserEntity;
import io.yunke.modules.wechat.Utils.MessageTemplate;
import io.yunke.modules.wechat.entity.*;
import io.yunke.modules.wechat.oauth.Oauth;
import io.yunke.modules.wechat.vo.PictureMpnewsVo;
import io.yunke.modules.wechat.vo.PictureNewsVo;
import io.yunke.modules.wechat.vo.WeChatResultVo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.builder.ToStringBuilder;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.core.io.FileSystemResource;
import org.springframework.http.ContentDisposition;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.util.UriComponentsBuilder;

import java.io.IOException;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

@Slf4j
@RunWith(SpringRunner.class)
@SpringBootTest
public class RedisTest {
    @Autowired
    private RedisUtils redisUtils;

    @Autowired
    Oauth oauth;

    @Value("${tencent.weixin.qiye.agentid}")
    private String agentid;

    @Test
    public void contextLoads() {
        SysUserEntity user = new SysUserEntity();
        user.setEmail("qqq@qq.com");
        redisUtils.set("user", user);

        System.out.println(ToStringBuilder.reflectionToString(redisUtils.get("user", SysUserEntity.class)));
    }

	/**
	 * 文本消息推送
	 */
	@Test
    public void text() {
        String token = oauth.getToken();
        TextEntity textEntity = new TextEntity();
        textEntity.setTouser("yfl");
        textEntity.setMsgtype("text");
        textEntity.setAgentid(agentid);

        TextTextEntity textTextEntity = new TextTextEntity();
        MessageTemplate messageTemplate = new MessageTemplate();
        String text = messageTemplate.text("http://work.weixin.qq.com");
        textTextEntity.setContent(text);
        textEntity.setText(textTextEntity);
        Object json = JSON.toJSON(textEntity);
        String itemUrl = new StringBuffer(WeChatConstant.MESSAGE_SEND).append("?").append(WeChatConstant.ACCESS_TOKEN).append("=").append(token).toString();
        log.info("wx send: {} ", JSON.toJSONString(textEntity));
        WeChatResultVo resMap = HTTP.post(itemUrl, textEntity, WeChatResultVo.class);
        log.info("wx send resp: {}", JSON.toJSONString(resMap));
    }

	/**
	 * 图文消息推送
	 */
	@Test
    public void pictureWordPushWehChcat() {
        String token = oauth.getToken();
        PictureMpnPushEntity picture = new PictureMpnPushEntity();
        picture.setTouser("yfl");
        picture.setMsgtype("mpnews");
        picture.setAgentid(agentid);


        PictureWordContentEntity picContent = new PictureWordContentEntity();
        picContent.setAuthor("yfl");
        picContent.setContent("新年快乐!");
        picContent.setContent_source_url("https://cdn.com/report/#/annualSummary?userId=yfl");
        // 下面有获取值得方法
        picContent.setThumb_media_id("3uBAmXHrMhhIb7_TJwJkMCSFW8f3sCnQHzafRyI_Pt_gkebZhENXvfI0XJOG0xj");
        picContent.setTitle("2022新年快乐!");
        List<PictureWordContentEntity> picContents = new ArrayList<>();
        picContents.add(picContent);

        PictureMpnewsVo pictureMpnewsVo = new PictureMpnewsVo();
        pictureMpnewsVo.setArticles(picContents);
        picture.setMpnews(pictureMpnewsVo);

        String itemUrl = new StringBuffer(WeChatConstant.MESSAGE_SEND).append("?").append(WeChatConstant.ACCESS_TOKEN).append("=").append(token).toString();
        log.info("wx send: {} ", JSON.toJSONString(picture));
        Map resMap = HTTP.post(itemUrl, picture, Map.class);
        log.info("wx send resp: {}", JSON.toJSONString(resMap));
    }

	/**
	 * 图片消息推送
	 */
	@Test
	public void picturePushWehChcat() {
		String token = oauth.getToken();
		PictureNewsPushEntity picture = new PictureNewsPushEntity();
		picture.setTouser("yfl");
		picture.setMsgtype("news");// 消息类型
		picture.setAgentid(agentid);


		PictureNewsContentEntity picContent = new PictureNewsContentEntity();
		picContent.setUrl("https://cdn.com/report/#/annuSummary?userId=yfl");
		picContent.setPicurl("https://project-stage.obs.cn-east-2.myhuaweicloud.com/workCamp/2022/01/26/14861633939047362_yunke.png");
		picContent.setTitle("2022新年快乐!");
		List<PictureNewsContentEntity> picContents = new ArrayList<>();
		picContents.add(picContent);

		PictureNewsVo pictureMpnewsVo = new PictureNewsVo();
		pictureMpnewsVo.setArticles(picContents);
		picture.setNews(pictureMpnewsVo);

		String itemUrl = new StringBuffer(WeChatConstant.MESSAGE_SEND).append("?").append(WeChatConstant.ACCESS_TOKEN).append("=").append(token).toString();
		log.info("wx send: {} ", JSON.toJSONString(picture));
		Map resMap = HTTP.post(itemUrl, picture, Map.class);
		log.info("wx send resp: {}", JSON.toJSONString(resMap));
	}

    /**
     * @return 企业微信上传临时文件
     * @throws IOException
     * 主要是获取 media_id
     */
    @Test
    public void uploadimg() throws IOException {
        String token = oauth.getToken();
        RestTemplate restTemplate = new RestTemplate();
        URI uri = UriComponentsBuilder.fromHttpUrl("https://qyapi.weixin.qq.com/cgi-bin/media/upload")
                .queryParam("access_token", token)
                .queryParam("type", "image")
                .build().toUri();

        FileSystemResource fileSystemResource = new FileSystemResource("C:\\Users\\86188\\Pictures\\yunke\\yunke.png");

        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.MULTIPART_FORM_DATA);

        /*Content-Disposition: form-data; name="media";filename="wework.txt"; filelength=6*/
        ContentDisposition build = ContentDisposition.builder("form-data").filename(fileSystemResource.getFilename()).build();
        headers.setContentDisposition(build);
        MultiValueMap<String, Object> params = new LinkedMultiValueMap<>();
        params.add("media", fileSystemResource);

        HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<>(params, headers);

        String s = restTemplate.postForObject(uri, requestEntity, String.class);
        log.info("上传文件返回值:{}", s);
    }


}


总结

提示:post发送请求jsonObject:
实体类直接转为jsonObject

 JSON.toJSONString(obj)
  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值