同步文章至微信公众号并推送到用户

目录

 

相关文档

业务流程

代码实现

引入依赖

yml参数

微信相关接口调用封装

嵌入业务


相关文档

公众号获取access_token

https://developers.weixin.qq.com/doc/offiaccount/Basic_Information/Get_access_token.html

新增永久素材(包括新增其它永久素材和新增永久图文素材等接口)

https://developers.weixin.qq.com/doc/offiaccount/Asset_Management/Adding_Permanent_Assets.html

群发接口

https://developers.weixin.qq.com/doc/offiaccount/Message_Management/Batch_Sends_and_Originality_Checks.html

业务流程

  1. 准备参数:1文章内容(可以是纯文本或者带html),2封面图片
  2. 将图片上传至”新增其它永久素材“接口获取该图片的media_id(该图片会上传至公众号的图片素材库,可在公众号后台查询)
  3. 将封面图片的media_id和文章内容(注意如果内容带html需要注意<>等符号是否被转义,否则会出现html不被解析的情况)等参数调用新增永久图文素材接口获取图文素材的media_id()(该文章会上传至公众号的图文素材库,可在公众号后台查询)
  4. 将图文素材库的media_id调用群发接口推送给用户(可选随送给所有用户或者指定标签用户)(每月推送次数有限)

代码实现

引入依赖


        
            com.arronlong
            httpclientutil
            1.0.4
        

yml参数

wechat:
  appid: wx2c4d9cfa5767575f
  secret: 9396f2ba7cdab92bad13c5ad69c76f88
#  获取token的url
  access_token_url: https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential
#  保存永久图文素材url
  save_permanent_image_text_material: https://api.weixin.qq.com/cgi-bin/material/add_news?access_token=
#  保存永久其它素材url
  save_permanent_other_material: https://api.weixin.qq.com/cgi-bin/material/add_material?access_token=
#  群发素材到用户url
  tag_send_material_url: https://api.weixin.qq.com/cgi-bin/message/mass/sendall?access_token=
#  生成图文素材的阅读原文地址
  content_source_url: http://www.gacycu.cn/

微信相关接口调用封装

package com.snow.management.plug.wechat;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.arronlong.httpclientutil.HttpClientUtil;
import com.arronlong.httpclientutil.common.HttpConfig;
import com.arronlong.httpclientutil.exception.HttpProcessException;
import com.snow.management.util.EhCacheUtil;
import org.springframework.core.io.FileSystemResource;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;

import java.util.*;

/**
 * 微信公众号相关
 * @ClassName Wechat
 * @Author snow
 * @Date 2020/10/19 14:38
 */
public class Wechat {

    private String appId = "";

    private String secret = "";

    private String tokenUrl = "";

    public Wechat(String appId, String secret, String tokenUrl) {
        this.appId = appId;
        this.secret = secret;
        this.tokenUrl = tokenUrl;
    }

    /**
     * 获取token
     */
    public String getAccessToken() throws HttpProcessException {
        String result = HttpClientUtil.get(HttpConfig.custom().url(tokenUrl + "&appid=" + appId + "&secret=" + secret));
        JSONObject resultObj = JSON.parseObject(result);
        if (!resultObj.containsKey("access_token")) {
            throw new RuntimeException(result);
        }
        String token = resultObj.getString("access_token");
        EhCacheUtil.getInstance().put(EhCacheUtil.LOGIN_CACHE, "access_token", token);
        EhCacheUtil.getInstance().put(EhCacheUtil.LOGIN_CACHE, "access_token_time", System.currentTimeMillis());
        return token;
    }

    /**
     * 判断token是否有效
     * @return  有效返回token
     */
    private String validToken() {
        String token = (String) EhCacheUtil.getInstance().get(EhCacheUtil.LOGIN_CACHE, "access_token");
        if (token == null) {
            return "";
        }
        long validTime = (long) EhCacheUtil.getInstance().get(EhCacheUtil.LOGIN_CACHE, "access_token_time");
        if (validTime + 7000000 >= System.currentTimeMillis()) {
            return token;
        }
        return "";
    }

    /**
     * 新增永久图文素材
     * @param imageTextMaterialUrl  新增素材的url
     * @param title                 标题
     * @param thumbMediaId          封面图片的media_id
     * @param digest                摘要
     * @param showCoverPic          是否显示封面
     * @param content               内容
     * @param contentSourceUrl      阅读原文地址
     * @return                      图文素材的media_id
     */
    public String savePermanentImageTextMaterial(String imageTextMaterialUrl, String title, String thumbMediaId, String digest
            , int showCoverPic, String content, String contentSourceUrl) throws HttpProcessException {
        String token = validToken();
        if (token.isEmpty()) {
            token = getAccessToken();
        }
        Map article = new LinkedHashMap<>(5);
        // 标题
        article.put("title", title);
        // 图文消息的封面图片素材id(必须是永久mediaID)
        article.put("thumb_media_id", thumbMediaId);
        // 图文消息的摘要,仅有单图文消息才有摘要,多图文此处为空。如果本字段为没有填写,则默认抓取正文前64个字。
        article.put("digest", digest);
        // 是否显示封面,0为false,即不显示,1为true,即显示
        article.put("show_cover_pic", showCoverPic);
        // 图文消息的具体内容,支持HTML标签,必须少于2万字符,小于1M,且此处会去除JS,涉及图片url必须来源 "上传图文消息内的图片获取URL"接口获取。
        // 外部图片url将被过滤。
        article.put("content", content);
        // 图文消息的原文地址,即点击“阅读原文”后的URL
        article.put("content_source_url", contentSourceUrl);
        List> list = new ArrayList<>();
        list.add(article);
        Map param = new HashMap<>(1);
        param.put("articles", list);
        System.out.println(param);
        HttpConfig config = HttpConfig.custom().url(imageTextMaterialUrl + token).encoding("utf-8").json(JSONObject.toJSONString(param));
        String resultStr = HttpClientUtil.post(config);
        JSONObject result = JSONObject.parseObject(resultStr);
        if (!result.containsKey("media_id")) {
            throw new RuntimeException(resultStr);
        }
        System.out.println("图文素材media_id:" + result.getString("media_id"));
        return result.getString("media_id");
    }

    /**
     * 新增永久其它素材
     * @param imageOtherUrl     上传地址
     * @param type              媒体文件类型,分别有图片(image)、语音(voice)、视频(video)和缩略图(thumb)
     * @param filePath          要上传的文件地址
     * @return                  素材的mediaId
     * @throws HttpProcessException
     */
    public String savePermanentOtherMaterial(String imageOtherUrl, String type, String filePath) throws HttpProcessException {
        String token = validToken();
        if (token.isEmpty()) {
            token = getAccessToken();
        }
        MultiValueMap data = new LinkedMultiValueMap<>();
        //设置上传文件
        FileSystemResource fileSystemResource = new FileSystemResource(filePath);
        data.add("media", fileSystemResource);
        //上传文件,设置请求头
        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.setContentType(MediaType.MULTIPART_FORM_DATA);
        httpHeaders.setContentLength(fileSystemResource.getFile().length());
        HttpEntity> requestEntity = new HttpEntity<>(data,
                httpHeaders);
        RestTemplate restTemplate = new RestTemplate();
        String resultString = restTemplate.postForObject(imageOtherUrl + token + "&type=" + type, requestEntity, String.class);
        JSONObject result = JSONObject.parseObject(resultString);
        if (!result.containsKey("media_id")) {
            throw new RuntimeException(resultString);
        }
        System.out.println("其它素材media_id:" + result.getString("media_id"));
        return result.getString("media_id");
    }

    /**
     * 根据标签进行群发【订阅号与服务号认证后均可用】
     * @param url       推送接口
     * @param mediaId   图文素材id
     * @throws HttpProcessException
     */
    public String sendImageTextMessage(String url, String mediaId) throws HttpProcessException {
        String token = validToken();
        if (token.isEmpty()) {
            token = getAccessToken();
        }
        JSONObject filter = new JSONObject();
        // 用于设定是否向全部用户发送,值为true或false,选择true该消息群发给所有用户,选择false可根据tag_id发送给指定群组的用户
        filter.put("is_to_all", true);
        // 群发到的标签的tag_id,参见用户管理中用户分组接口,若is_to_all值为true,可不填写tag_id
//        filter.put("tag_id", 2);
        JSONObject mpnews = new JSONObject();
        // 用于群发的消息的media_id
        mpnews.put("media_id", mediaId);
        JSONObject param = new JSONObject();
        // 用于设定图文消息的接收者
        param.put("filter", filter);
        // 用于设定即将发送的图文消息
        param.put("mpnews", mpnews);
        // 群发的消息类型,图文消息为mpnews,文本消息为text,语音为voice,音乐为music,图片为image,视频为video,卡券为wxcard
        param.put("msgtype", "mpnews");
        // 图文消息被判定为转载时,是否继续群发。 1为继续群发(转载),0为停止群发。 该参数默认为0。
        param.put("send_ignore_reprint", 0);
        HttpConfig config = HttpConfig.custom().url(url + token).encoding("utf-8").json(JSONObject.toJSONString(param));
        String resultStr = HttpClientUtil.post(config);
        JSONObject result = JSONObject.parseObject(resultStr);
        Integer code = result.getInteger("errcode");
        if (code == 0) {
            return "";
        } else if (code == 45065) {
            return "文章已推送";
        }
        throw new RuntimeException(resultStr);
    }
}

嵌入业务

/**
     * 发送文章到公众号
     * @param id    文章id
     */
    private JSONObject shareWechat(String id) throws HttpProcessException {
        if (DataOperateUtil.isNull(appid, secret, tokenUrl, imageTextMaterialUrl, otherMaterialUrl, tagSendMaterialUrl)) {
            return fail("缺少参数配置");
        }
        QueryWrapper
queryWrapper = new QueryWrapper<>(); queryWrapper.eq("id", id); queryWrapper.select("id", "title", "introduction", "type", "cover", "content", "media_id"); Article article = articleService.getOne(queryWrapper); if (article == null) { return fail("文章不存在"); } if (article.getType() != 1) { return fail("仅支持自行编辑的图文文章"); } if (DataOperateUtil.isNull(article.getCover())) { return fail("请上传封面用以公众号推送图文信息"); } Wechat wechat = new Wechat(appid, secret, tokenUrl); String materialMediaId = ""; // 判断文章是否已经上传到公众号素材库 if (DataOperateUtil.isNull(article.getMediaId())) { String coverMediaId = wechat.savePermanentOtherMaterial(otherMaterialUrl, "image", fileUploadPath + article.getCover()); materialMediaId = wechat.savePermanentImageTextMaterial(imageTextMaterialUrl, article.getTitle(), coverMediaId, article.getIntroduction(), 1, article.getContent(), contentSourceUrl); // 保存素材id到库,防止多次上传到公众号素材库 article.setMediaId(materialMediaId); articleService.updateById(article); } else { materialMediaId = article.getMediaId(); } String sendResult = wechat.sendImageTextMessage(tagSendMaterialUrl, materialMediaId); if (sendResult.isEmpty()) { return successNotData(); } return fail(sendResult); }

 

你可能感兴趣的:(springboot,微信,Java,java,微信公众号)