🆕 #2356 【公众号】新增草稿箱和发布相关的接口

This commit is contained in:
dragon 2021-10-23 23:23:18 +08:00 committed by GitHub
parent 8c787d1638
commit 5755c293df
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
20 changed files with 1330 additions and 3 deletions

View File

@ -0,0 +1,127 @@
package me.chanjar.weixin.mp.api;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.mp.bean.draft.WxMpAddDraft;
import me.chanjar.weixin.mp.bean.draft.WxMpDraftInfo;
import me.chanjar.weixin.mp.bean.draft.WxMpDraftList;
import me.chanjar.weixin.mp.bean.draft.WxMpUpdateDraft;
/**
* 微信 草稿箱 接口.
*
* @author dragon
* @date 2021-10-22
*/
public interface WxMpDraftService {
/**
* 新建草稿 - 只有默认必填参数
* <pre>
* 请求地址POST https://api.weixin.qq.com/cgi-bin/draft/add?access_token=ACCESS_TOKEN
* 文档地址https://developers.weixin.qq.com/doc/offiaccount/Draft_Box/Add_draft.html
* </pre>
*
* @param title 标题
* @param content 图文消息的具体内容支持HTML标签必须少于2万字符小于1M且此处会去除JS,涉及图片url必须来源 "上传图文消息内的图片获取URL"接口获取外部图片url将被过滤
* @param thumbMediaId 图文消息的封面图片素材id必须是永久MediaID
* @throws WxErrorException .
*/
String addDraft(String title, String content, String thumbMediaId) throws WxErrorException;
/**
* 新建草稿 - 完整参数
* <pre>
* 请求地址POST https://api.weixin.qq.com/cgi-bin/draft/add?access_token=ACCESS_TOKEN
* 文档地址https://developers.weixin.qq.com/doc/offiaccount/Draft_Box/Add_draft.html
* </pre>
*
* @param addDraft 新建草稿信息
* @throws WxErrorException .
*/
String addDraft(WxMpAddDraft addDraft) throws WxErrorException;
/**
* 修改草稿 - 完整参数
* 正常情况下调用成功时errcode将为0错误时微信会返回错误码等信息请根据错误码查询错误信息
* <pre>
* 请求地址 POST https://api.weixin.qq.com/cgi-bin/draft/update?access_token=ACCESS_TOKEN
* 文档地址https://developers.weixin.qq.com/doc/offiaccount/Draft_Box/Update_draft.html
* </pre>
*
* @param updateDraftInfo 修改草稿信息
* @throws WxErrorException .
*/
Boolean updateDraft(WxMpUpdateDraft updateDraftInfo) throws WxErrorException;
/**
* 获取草稿信息
*
* <pre>
* 请求地址POST https://api.weixin.qq.com/cgi-bin/draft/get?access_token=ACCESS_TOKEN
* 文档地址https://developers.weixin.qq.com/doc/offiaccount/Draft_Box/Get_draft.html
* </pre>
*
* @param mediaId 要获取的草稿的media_id
* @return 草稿信息
* @throws WxErrorException .
*/
WxMpDraftInfo getDraft(String mediaId) throws WxErrorException;
/**
* 删除草稿
* 正常情况下调用成功时errcode将为0错误时微信会返回错误码等信息请根据错误码查询错误信息
* 多次删除同一篇草稿也返回 0.
* <pre>
* 请求地址POST https://api.weixin.qq.com/cgi-bin/draft/delete?access_token=ACCESS_TOKEN
* 文档地址https://developers.weixin.qq.com/doc/offiaccount/Draft_Box/Delete_draft.html
* </pre>
*
* @param mediaId 要删除的草稿的media_id
* @throws WxErrorException .
*/
Boolean delDraft(String mediaId) throws WxErrorException;
/**
* 获取草稿列表
*
* <pre>
* 请求地址POST https://api.weixin.qq.com/cgi-bin/draft/batchget?access_token=ACCESS_TOKEN
* 文档地址https://developers.weixin.qq.com/doc/offiaccount/Draft_Box/Get_draft_list.html
* </pre>
*
* @param offset 分页页数从0开始 从全部素材的该偏移位置开始返回0表示从第一个素材返回
* @param count 每页数量 返回素材的数量取值在1到20之间
* @param noContent 1 表示不返回 content 字段0 表示正常返回默认为 0
* @return 草稿信息列表
* @throws WxErrorException .
*/
WxMpDraftList listDraft(int offset, int count, int noContent) throws WxErrorException;
/**
* 获取草稿列表
* <pre>
* 请求地址POST https://api.weixin.qq.com/cgi-bin/draft/batchget?access_token=ACCESS_TOKEN
* 文档地址https://developers.weixin.qq.com/doc/offiaccount/Draft_Box/Get_draft_list.html
* </pre>
*
* @param offset 分页页数从0开始 从全部素材的该偏移位置开始返回0表示从第一个素材返回
* @param count 每页数量 返回素材的数量取值在1到20之间
* @return
* @throws WxErrorException
*/
WxMpDraftList listDraft(int offset, int count) throws WxErrorException;
/**
* 获取草稿数量
* 开发者可以根据本接口来获取草稿的总数此接口只统计数量不返回草稿的具体内容
* <pre>
* 请求地址POST https://api.weixin.qq.com/cgi-bin/draft/count?access_token=ACCESS_TOKEN
* 文档地址https://developers.weixin.qq.com/doc/offiaccount/Draft_Box/Count_drafts.html
* </pre>
*
* @return 草稿的总数
* @throws WxErrorException .
*/
Long countDraft() throws WxErrorException;
}

View File

@ -0,0 +1,113 @@
package me.chanjar.weixin.mp.api;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.mp.bean.freepublish.WxMpFreePublishInfo;
import me.chanjar.weixin.mp.bean.freepublish.WxMpFreePublishList;
import me.chanjar.weixin.mp.bean.freepublish.WxMpFreePublishStatus;
/**
* 微信 发布能力 接口.
*
* @author dragon
* @date 2021-10-23
*/
public interface WxMpFreePublishService {
/**
* 发布接口 - 只有默认必填参数
* 开发者需要先将图文素材以草稿的形式保存草稿箱/新建草稿如需从已保存的草稿中选择草稿箱/获取草稿列表选择要发布的草稿 media_id 进行发布
* <pre>
* 请求地址POST https://api.weixin.qq.com/cgi-bin/freepublish/submit?access_token=ACCESS_TOKEN
* 文档地址https://developers.weixin.qq.com/doc/offiaccount/Publish/Publish.html
* </pre>
*
* @param mediaId 要发布的草稿的media_id
* @throws WxErrorException .
*/
String submit(String mediaId) throws WxErrorException;
/**
* 发布状态轮询接口
* 开发者可以尝试通过下面的发布状态轮询接口获知发布情况
* <pre>
* 请求地址POST https://api.weixin.qq.com/cgi-bin/freepublish/get?access_token=ACCESS_TOKEN
* 文档地址https://developers.weixin.qq.com/doc/offiaccount/Publish/Get_status.html
* </pre>
*
* @param publishId 发布任务id
* @throws WxErrorException .
*/
WxMpFreePublishStatus getPushStatus(String publishId) throws WxErrorException;
/**
* 删除发布
* 发布成功之后随时可以通过该接口删除此操作不可逆请谨慎操作
* <pre>
* 请求地址POST https://api.weixin.qq.com/cgi-bin/freepublish/delete?access_token=ACCESS_TOKEN
* 文档地址https://developers.weixin.qq.com/doc/offiaccount/Publish/Delete_posts.html
* </pre>
*
* @param articleId 成功发布时返回的 article_id
* @param index 要删除的文章在图文消息中的位置第一篇编号为1该字段不填或填0会删除全部文章
* @throws WxErrorException .
*/
Boolean deletePush(String articleId, Integer index) throws WxErrorException;
/**
* 删除发布 - 此条发布的所有内容不指定文章编号
* 发布成功之后随时可以通过该接口删除此操作不可逆请谨慎操作
* <pre>
* 请求地址POST https://api.weixin.qq.com/cgi-bin/freepublish/delete?access_token=ACCESS_TOKEN
* 文档地址https://developers.weixin.qq.com/doc/offiaccount/Publish/Delete_posts.html
* </pre>
*
* @param articleId 成功发布时返回的 article_id
* @throws WxErrorException .
*/
Boolean deletePushAllArticle(String articleId) throws WxErrorException;
/**
* 通过 article_id 获取已发布文章
* 开发者可以通过 article_id 获取已发布的图文信息
* <pre>
* 请求地址POST https://api.weixin.qq.com/cgi-bin/freepublish/getarticle?access_token=ACCESS_TOKEN
* 文档地址https://developers.weixin.qq.com/doc/offiaccount/Publish/Get_article_from_id.html
* </pre>
*
* @param articleId 要获取的草稿的article_id
* @return 已发布文章信息
* @throws WxErrorException .
*/
WxMpFreePublishInfo getArticleFromId(String articleId) throws WxErrorException;
/**
* 获取成功发布列表 - 支持选择是否返回图文消息的具体内容
*
* <pre>
* 请求地址POST https://api.weixin.qq.com/cgi-bin/draft/batchget?access_token=ACCESS_TOKEN
* 文档地址https://developers.weixin.qq.com/doc/offiaccount/Publish/Get_publication_records.html
* </pre>
*
* @param offset 分页页数从0开始 从全部素材的该偏移位置开始返回0表示从第一个素材返回
* @param count 每页数量 返回素材的数量取值在1到20之间
* @param noContent 1 表示不返回 content 字段0 表示正常返回默认为 0
* @return 草稿信息列表
* @throws WxErrorException .
*/
WxMpFreePublishList getPublicationRecords(int offset, int count, int noContent) throws WxErrorException;
/**
* 获取成功发布列表 - 默认返回 图文消息的具体内容
* <pre>
* 请求地址POST https://api.weixin.qq.com/cgi-bin/draft/batchget?access_token=ACCESS_TOKEN
* 文档地址https://developers.weixin.qq.com/doc/offiaccount/Publish/Get_publication_records.html
* </pre>
*
* @param offset 分页页数从0开始 从全部素材的该偏移位置开始返回0表示从第一个素材返回
* @param count 每页数量 返回素材的数量取值在1到20之间
* @return
* @throws WxErrorException
*/
WxMpFreePublishList getPublicationRecords(int offset, int count) throws WxErrorException;
}

View File

@ -567,6 +567,20 @@ public interface WxMpService extends WxService {
*/
WxMpReimburseInvoiceService getReimburseInvoiceService();
/**
* 返回草稿箱相关接口
*
* @return WxMpDraftService
*/
WxMpDraftService getDraftService();
/**
* 返回发布能力接口
*
* @return WxMpFreePublishService
*/
WxMpFreePublishService getFreePublishService();
/**
* .
*
@ -818,4 +832,18 @@ public interface WxMpService extends WxService {
* @param merchantInvoiceService the merchant invoice service
*/
void setMerchantInvoiceService(WxMpMerchantInvoiceService merchantInvoiceService);
/**
* Sets draft service.
*
* @param draftService the draft service
*/
void setDraftService(WxMpDraftService draftService);
/**
* Sets free publish service.
*
* @param freePublishService the free publish service
*/
void setFreePublishService(WxMpFreePublishService freePublishService);
}

View File

@ -25,7 +25,11 @@ import me.chanjar.weixin.common.session.WxSessionManager;
import me.chanjar.weixin.common.util.DataUtils;
import me.chanjar.weixin.common.util.RandomUtils;
import me.chanjar.weixin.common.util.crypto.SHA1;
import me.chanjar.weixin.common.util.http.*;
import me.chanjar.weixin.common.util.http.RequestExecutor;
import me.chanjar.weixin.common.util.http.RequestHttp;
import me.chanjar.weixin.common.util.http.SimpleGetRequestExecutor;
import me.chanjar.weixin.common.util.http.SimplePostRequestExecutor;
import me.chanjar.weixin.common.util.http.URIUtil;
import me.chanjar.weixin.common.util.json.GsonParser;
import me.chanjar.weixin.common.util.json.WxGsonBuilder;
import me.chanjar.weixin.mp.api.*;
@ -42,7 +46,16 @@ import java.io.IOException;
import java.util.Map;
import java.util.concurrent.locks.Lock;
import static me.chanjar.weixin.mp.enums.WxMpApiUrl.Other.*;
import static me.chanjar.weixin.mp.enums.WxMpApiUrl.Other.CLEAR_QUOTA_URL;
import static me.chanjar.weixin.mp.enums.WxMpApiUrl.Other.FETCH_SHORTEN_URL;
import static me.chanjar.weixin.mp.enums.WxMpApiUrl.Other.GEN_SHORTEN_URL;
import static me.chanjar.weixin.mp.enums.WxMpApiUrl.Other.GET_CALLBACK_IP_URL;
import static me.chanjar.weixin.mp.enums.WxMpApiUrl.Other.GET_CURRENT_AUTOREPLY_INFO_URL;
import static me.chanjar.weixin.mp.enums.WxMpApiUrl.Other.GET_TICKET_URL;
import static me.chanjar.weixin.mp.enums.WxMpApiUrl.Other.NETCHECK_URL;
import static me.chanjar.weixin.mp.enums.WxMpApiUrl.Other.QRCONNECT_URL;
import static me.chanjar.weixin.mp.enums.WxMpApiUrl.Other.SEMANTIC_SEMPROXY_SEARCH_URL;
import static me.chanjar.weixin.mp.enums.WxMpApiUrl.Other.SHORTURL_API_URL;
/**
* 基础实现类.
@ -146,6 +159,14 @@ public abstract class BaseWxMpServiceImpl<H, P> implements WxMpService, RequestH
@Setter
private WxMpReimburseInvoiceService reimburseInvoiceService = new WxMpReimburseInvoiceServiceImpl(this);
@Getter
@Setter
private WxMpDraftService draftService = new WxMpDraftServiceImpl(this);
@Getter
@Setter
private WxMpFreePublishService freePublishService = new WxMpFreePublishServiceImpl(this);
private Map<String, WxMpConfigStorage> configStorageMap;
private int retrySleepMillis = 1000;

View File

@ -0,0 +1,84 @@
package me.chanjar.weixin.mp.api.impl;
import lombok.AllArgsConstructor;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.common.util.json.GsonHelper;
import me.chanjar.weixin.common.util.json.GsonParser;
import me.chanjar.weixin.mp.api.WxMpDraftService;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.bean.draft.WxMpAddDraft;
import me.chanjar.weixin.mp.bean.draft.WxMpDraftArticles;
import me.chanjar.weixin.mp.bean.draft.WxMpDraftInfo;
import me.chanjar.weixin.mp.bean.draft.WxMpDraftList;
import me.chanjar.weixin.mp.bean.draft.WxMpUpdateDraft;
import me.chanjar.weixin.mp.enums.WxMpApiUrl;
import java.util.ArrayList;
import java.util.List;
/**
* 草稿箱能力-service实现类.
*
* @author dragon
* @date 2021-10-22
*/
@AllArgsConstructor
public class WxMpDraftServiceImpl implements WxMpDraftService {
private static final String MEDIA_ID = "media_id";
private static final String ERRCODE_SUCCESS = "0";
private static final String ERRCODE = "errcode";
private final WxMpService mpService;
@Override
public String addDraft(String title, String content, String thumbMediaId) throws WxErrorException {
List<WxMpDraftArticles> draftArticleList = new ArrayList<>();
WxMpDraftArticles draftArticle = WxMpDraftArticles.builder()
.title(title).content(content).thumbMediaId(thumbMediaId).build();
WxMpAddDraft addDraft = WxMpAddDraft.builder().articles(draftArticleList).build();
draftArticleList.add(draftArticle);
return addDraft(addDraft);
}
@Override
public String addDraft(WxMpAddDraft addDraft) throws WxErrorException {
String json = this.mpService.post(WxMpApiUrl.Draft.ADD_DRAFT, addDraft);
return GsonParser.parse(json).get(MEDIA_ID).toString();
}
@Override
public Boolean updateDraft(WxMpUpdateDraft updateDraftInfo) throws WxErrorException {
String json = this.mpService.post(WxMpApiUrl.Draft.UPDATE_DRAFT, updateDraftInfo);
return GsonParser.parse(json).get(ERRCODE).toString().equals(ERRCODE_SUCCESS);
}
@Override
public WxMpDraftInfo getDraft(String mediaId) throws WxErrorException {
return WxMpDraftInfo.fromJson(this.mpService.post(WxMpApiUrl.Draft.GET_DRAFT,
GsonHelper.buildJsonObject(MEDIA_ID, mediaId)));
}
@Override
public Boolean delDraft(String mediaId) throws WxErrorException {
String json = this.mpService.post(WxMpApiUrl.Draft.DEL_DRAFT,
GsonHelper.buildJsonObject(MEDIA_ID, mediaId));
return GsonParser.parse(json).get(ERRCODE).toString().equals(ERRCODE_SUCCESS);
}
@Override
public WxMpDraftList listDraft(int offset, int count, int noContent) throws WxErrorException {
return WxMpDraftList.fromJson(this.mpService.post(WxMpApiUrl.Draft.LIST_DRAFT,
GsonHelper.buildJsonObject("offset", offset, "count", count, "no_content", noContent)));
}
@Override
public WxMpDraftList listDraft(int offset, int count) throws WxErrorException {
return listDraft(offset, count, 0);
}
@Override
public Long countDraft() throws WxErrorException {
String json = this.mpService.get(WxMpApiUrl.Draft.COUNT_DRAFT, null);
return Long.valueOf(GsonParser.parse(json).get("total_count").toString());
}
}

View File

@ -0,0 +1,72 @@
package me.chanjar.weixin.mp.api.impl;
import lombok.AllArgsConstructor;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.common.util.json.GsonHelper;
import me.chanjar.weixin.common.util.json.GsonParser;
import me.chanjar.weixin.mp.api.WxMpFreePublishService;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.bean.freepublish.WxMpFreePublishInfo;
import me.chanjar.weixin.mp.bean.freepublish.WxMpFreePublishList;
import me.chanjar.weixin.mp.bean.freepublish.WxMpFreePublishStatus;
import me.chanjar.weixin.mp.enums.WxMpApiUrl;
/**
* 发布能力-service实现类.
*
* @author dragon
* @date 2021-10-23
*/
@AllArgsConstructor
public class WxMpFreePublishServiceImpl implements WxMpFreePublishService {
private static final String MEDIA_ID = "media_id";
private static final String PUBLISH_ID = "publish_id";
private static final String ARTICLE_ID = "article_id";
private static final String ERRCODE_SUCCESS = "0";
private static final String ERRCODE = "errcode";
private final WxMpService mpService;
@Override
public String submit(String mediaId) throws WxErrorException {
String json = this.mpService.post(WxMpApiUrl.FreePublish.SUBMIT,
GsonHelper.buildJsonObject(MEDIA_ID, mediaId));
return GsonParser.parse(json).get(PUBLISH_ID).toString();
}
@Override
public WxMpFreePublishStatus getPushStatus(String publishId) throws WxErrorException {
return WxMpFreePublishStatus.fromJson(this.mpService.post(WxMpApiUrl.FreePublish.GET_PUSH_STATUS,
GsonHelper.buildJsonObject(PUBLISH_ID, publishId)));
}
@Override
public Boolean deletePush(String articleId, Integer index) throws WxErrorException {
String json = this.mpService.post(WxMpApiUrl.FreePublish.DEL_PUSH,
GsonHelper.buildJsonObject(ARTICLE_ID, articleId, "index", index));
return GsonParser.parse(json).get(ERRCODE).toString().equals(ERRCODE_SUCCESS);
}
@Override
public Boolean deletePushAllArticle(String articleId) throws WxErrorException {
// index字段不填或填0会删除全部文章
return deletePush(articleId, 0);
}
@Override
public WxMpFreePublishInfo getArticleFromId(String articleId) throws WxErrorException {
return WxMpFreePublishInfo.fromJson(this.mpService.post(WxMpApiUrl.FreePublish.GET_ARTICLE,
GsonHelper.buildJsonObject(ARTICLE_ID, articleId)));
}
@Override
public WxMpFreePublishList getPublicationRecords(int offset, int count, int noContent) throws WxErrorException {
return WxMpFreePublishList.fromJson(this.mpService.post(WxMpApiUrl.FreePublish.BATCH_GET,
GsonHelper.buildJsonObject("offset", offset, "count", count, "no_content", noContent)));
}
@Override
public WxMpFreePublishList getPublicationRecords(int offset, int count) throws WxErrorException {
return getPublicationRecords(offset, count, 0);
}
}

View File

@ -0,0 +1,44 @@
package me.chanjar.weixin.mp.bean.draft;
import com.google.gson.annotations.SerializedName;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
import me.chanjar.weixin.common.bean.ToJson;
import me.chanjar.weixin.common.util.json.WxGsonBuilder;
import java.io.Serializable;
import java.util.List;
/**
* 草稿箱能力-新建草稿.
*
* @author dragon
* @date 2021-10-22
*/
@Data
@Builder
@Accessors(chain = true)
@NoArgsConstructor
@AllArgsConstructor
public class WxMpAddDraft implements ToJson, Serializable {
private static final long serialVersionUID = 2481699972367293721L;
/**
* 图文素材列表
*/
@SerializedName("articles")
private List<WxMpDraftArticles> articles;
public static WxMpAddDraft fromJson(String json) {
return WxGsonBuilder.create().fromJson(json, WxMpAddDraft.class);
}
@Override
public String toJson() {
return WxGsonBuilder.create().toJson(this);
}
}

View File

@ -0,0 +1,81 @@
package me.chanjar.weixin.mp.bean.draft;
import com.google.gson.annotations.SerializedName;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
import me.chanjar.weixin.common.bean.ToJson;
import me.chanjar.weixin.common.util.json.WxGsonBuilder;
import java.io.Serializable;
/**
* 草稿箱能力-图文素材文章实体.
*
* @author dragon
* @date 2021-10-22
*/
@Data
@Builder
@Accessors(chain = true)
@NoArgsConstructor
@AllArgsConstructor
public class WxMpDraftArticles implements ToJson, Serializable {
/**
* 标题
*/
@SerializedName("title")
private String title;
/**
* 作者
*/
@SerializedName("author")
private String author;
/**
* 图文消息的摘要仅有单图文消息才有摘要多图文此处为空如果本字段为没有填写则默认抓取正文前54个字
*/
@SerializedName("digest")
private String digest;
/**
* 图文消息的具体内容支持HTML标签必须少于2万字符小于1M且此处会去除JS,涉及图片url必须来源 "上传图文消息内的图片获取URL"接口获取外部图片url将被过滤
*/
@SerializedName("content")
private String content;
/**
* 图文消息的原文地址即点击阅读原文后的URL
*/
@SerializedName("content_source_url")
private String contentSourceUrl;
/**
* 图文消息的封面图片素材id必须是永久MediaID
*/
@SerializedName("thumb_media_id")
private String thumbMediaId;
/**
* 是否显示封面0为false即不显示1为true即显示(默认)
*/
@SerializedName("show_cover_pic")
private Integer showCoverPic;
/**
* 是否打开评论0不打开(默认)1打开
*/
@SerializedName("need_open_comment")
private Integer needOpenComment;
/**
* 是否粉丝才可评论0所有人可评论(默认)1粉丝才可评论
*/
@SerializedName("only_fans_can_comment")
private Integer onlyFansCanComment;
public static WxMpDraftArticles fromJson(String json) {
return WxGsonBuilder.create().fromJson(json, WxMpDraftArticles.class);
}
@Override
public String toJson() {
return WxGsonBuilder.create().toJson(this);
}
}

View File

@ -0,0 +1,44 @@
package me.chanjar.weixin.mp.bean.draft;
import com.google.gson.annotations.SerializedName;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
import me.chanjar.weixin.common.bean.ToJson;
import me.chanjar.weixin.common.util.json.WxGsonBuilder;
import java.io.Serializable;
import java.util.List;
/**
* 草稿箱能力-获取草稿详情.
*
* @author dragon
* @date 2021-10-22
*/
@Data
@Builder
@Accessors(chain = true)
@NoArgsConstructor
@AllArgsConstructor
public class WxMpDraftInfo implements ToJson, Serializable {
private static final long serialVersionUID = 6111694033486314392L;
/**
* 文章列表
*/
@SerializedName("news_item")
private List<WxMpDraftArticles> newsItem;
public static WxMpDraftInfo fromJson(String json) {
return WxGsonBuilder.create().fromJson(json, WxMpDraftInfo.class);
}
@Override
public String toJson() {
return WxGsonBuilder.create().toJson(this);
}
}

View File

@ -0,0 +1,33 @@
package me.chanjar.weixin.mp.bean.draft;
import com.google.gson.annotations.SerializedName;
import lombok.Data;
import me.chanjar.weixin.common.util.json.WxGsonBuilder;
import java.io.Serializable;
/**
* 一条草稿
*
* @author dragon
* @date 2021-10-22
*/
@Data
public class WxMpDraftItem implements Serializable {
private static final long serialVersionUID = 214696458030935146L;
/**
* 图文消息的id
*/
@SerializedName("media_id")
private String mediaId;
/**
* 图文消息的具体内容支持HTML标签必须少于2万字符小于1M且此处会去除JS
*/
@SerializedName("content")
private WxMpDraftInfo content;
public static WxMpDraftItem fromJson(String json) {
return WxGsonBuilder.create().fromJson(json, WxMpDraftItem.class);
}
}

View File

@ -0,0 +1,41 @@
package me.chanjar.weixin.mp.bean.draft;
import com.google.gson.annotations.SerializedName;
import lombok.Data;
import me.chanjar.weixin.common.util.json.WxGsonBuilder;
import java.io.Serializable;
import java.util.List;
/**
* 草稿箱能力-获取草稿列表.
*
* @author dragon
* @date 2021-10-22
*/
@Data
public class WxMpDraftList implements Serializable {
private static final long serialVersionUID = 7216822694952035295L;
/**
* 草稿素材的总数
*/
@SerializedName("total_count")
private Integer totalCount;
/**
* 本次调用获取的素材的数量
*/
@SerializedName("item_count")
private Integer itemCount;
/**
* 所有草稿列表
*/
@SerializedName("item")
private List<WxMpDraftItem> items;
public static WxMpDraftList fromJson(String json) {
return WxGsonBuilder.create().fromJson(json, WxMpDraftList.class);
}
}

View File

@ -0,0 +1,55 @@
package me.chanjar.weixin.mp.bean.draft;
import com.google.gson.annotations.SerializedName;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
import me.chanjar.weixin.common.bean.ToJson;
import me.chanjar.weixin.common.util.json.WxGsonBuilder;
import java.io.Serializable;
/**
* 草稿箱能力-修改草稿.
*
* @author dragon
* @date 2021-10-22
*/
@Data
@Builder
@Accessors(chain = true)
@NoArgsConstructor
@AllArgsConstructor
public class WxMpUpdateDraft implements ToJson, Serializable {
private static final long serialVersionUID = -8564521168423899915L;
/**
* 要修改的图文消息的id
*/
@SerializedName("media_id")
private String mediaId;
/**
* 要更新的文章在图文消息中的位置多图文消息时此字段才有意义第一篇为0
*/
@SerializedName("index")
private Integer index;
/**
* 图文素材列表
*/
@SerializedName("articles")
private WxMpDraftArticles articles;
public static WxMpUpdateDraft fromJson(String json) {
return WxGsonBuilder.create().fromJson(json, WxMpUpdateDraft.class);
}
@Override
public String toJson() {
return WxGsonBuilder.create().toJson(this);
}
}

View File

@ -0,0 +1,85 @@
package me.chanjar.weixin.mp.bean.freepublish;
import com.google.gson.annotations.SerializedName;
import lombok.Data;
import lombok.NoArgsConstructor;
import me.chanjar.weixin.common.util.json.WxGsonBuilder;
import java.io.Serializable;
/**
* 一条发布的图文记录
*
* @author dragon
* @date 2021-10-23
*/
@NoArgsConstructor
@Data
public class WxMpFreePublishArticles implements Serializable {
private static final long serialVersionUID = -6435229818150835883L;
/**
* 标题
*/
@SerializedName("title")
private String title;
/**
* 作者
*/
@SerializedName("author")
private String author;
/**
* 图文消息的摘要仅有单图文消息才有摘要多图文此处为空
*/
@SerializedName("digest")
private String digest;
/**
* 图文消息的具体内容支持HTML标签必须少于2万字符小于1M且此处会去除JS
*/
@SerializedName("content")
private String content;
/**
* 图文消息的原文地址即点击阅读原文后的URL
*/
@SerializedName("content_source_url")
private String contentSourceUrl;
/**
* 图文消息的封面图片素材id一定是永久MediaID
*/
@SerializedName("thumb_media_id")
private String thumbMediaId;
/**
* 是否显示封面0为false即不显示1为true即显示(默认)
*/
@SerializedName("show_cover_pic")
private Integer showCoverPic;
/**
* 是否打开评论0不打开(默认)1打开
*/
@SerializedName("need_open_comment")
private Integer needOpenComment;
/**
* 是否粉丝才可评论0所有人可评论(默认)1粉丝才可评论
*/
@SerializedName("only_fans_can_comment")
private Integer onlyFansCanComment;
/*
* ===== 上面的参数就是草稿箱的内容的字段为了后续扩展单独写一份====
*/
/**
* 草稿的临时链接
*/
@SerializedName("url")
private String url;
/**
* 该图文是否被删除
*/
@SerializedName("is_deleted")
private Boolean isDeleted;
public static WxMpFreePublishArticles fromJson(String json) {
return WxGsonBuilder.create().fromJson(json, WxMpFreePublishArticles.class);
}
}

View File

@ -0,0 +1,44 @@
package me.chanjar.weixin.mp.bean.freepublish;
import com.google.gson.annotations.SerializedName;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
import me.chanjar.weixin.common.bean.ToJson;
import me.chanjar.weixin.common.util.json.WxGsonBuilder;
import java.io.Serializable;
import java.util.List;
/**
* 发布能力-通过 article_id 获取已发布文章.
*
* @author dragon
* @date 2021-10-23
*/
@Data
@Builder
@Accessors(chain = true)
@NoArgsConstructor
@AllArgsConstructor
public class WxMpFreePublishInfo implements ToJson, Serializable {
private static final long serialVersionUID = 3331288672996730705L;
/**
* 文章列表
*/
@SerializedName("news_item")
private List<WxMpFreePublishArticles> newsItem;
public static WxMpFreePublishInfo fromJson(String json) {
return WxGsonBuilder.create().fromJson(json, WxMpFreePublishInfo.class);
}
@Override
public String toJson() {
return WxGsonBuilder.create().toJson(this);
}
}

View File

@ -0,0 +1,35 @@
package me.chanjar.weixin.mp.bean.freepublish;
import com.google.gson.annotations.SerializedName;
import lombok.Data;
import lombok.NoArgsConstructor;
import me.chanjar.weixin.common.util.json.WxGsonBuilder;
import java.io.Serializable;
/**
* 发布列表的一条记录
*
* @author dragon
* @date 2021-10-23
*/
@NoArgsConstructor
@Data
public class WxMpFreePublishItem implements Serializable {
private static final long serialVersionUID = -6435229818150835883L;
/**
* 成功发布的图文消息id
*/
@SerializedName("article_id")
private String articleId;
/**
* 图文消息的具体内容支持HTML标签必须少于2万字符小于1M且此处会去除JS
*/
@SerializedName("content")
private WxMpFreePublishInfo content;
public static WxMpFreePublishItem fromJson(String json) {
return WxGsonBuilder.create().fromJson(json, WxMpFreePublishItem.class);
}
}

View File

@ -0,0 +1,41 @@
package me.chanjar.weixin.mp.bean.freepublish;
import com.google.gson.annotations.SerializedName;
import lombok.Data;
import me.chanjar.weixin.common.util.json.WxGsonBuilder;
import java.io.Serializable;
import java.util.List;
/**
* 发布能力-获取成功发布列表.
*
* @author dragon
* @date 2021-10-22
*/
@Data
public class WxMpFreePublishList implements Serializable {
private static final long serialVersionUID = 764054773431665250L;
/**
* 成功发布素材的总数
*/
@SerializedName("total_count")
private Integer totalCount;
/**
* 本次调用获取的素材的数量
*/
@SerializedName("item_count")
private Integer itemCount;
/**
* 所有成功发布列表
*/
@SerializedName("item")
private List<WxMpFreePublishItem> items;
public static WxMpFreePublishList fromJson(String json) {
return WxGsonBuilder.create().fromJson(json, WxMpFreePublishList.class);
}
}

View File

@ -0,0 +1,56 @@
package me.chanjar.weixin.mp.bean.freepublish;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
import me.chanjar.weixin.common.bean.ToJson;
import me.chanjar.weixin.common.util.json.WxGsonBuilder;
import java.io.Serializable;
import java.util.List;
/**
* 发布能力-发布状态轮询接口通过publishId返回 article_id(删除发布时需要用到).
*
* @author dragon
* @date 2021-10-23
*/
@Data
@Builder
@Accessors(chain = true)
@NoArgsConstructor
@AllArgsConstructor
public class WxMpFreePublishStatus implements ToJson, Serializable {
private static final long serialVersionUID = -7526369389476785732L;
private String publish_id;
private Integer publish_status;
private String article_id;
private ArticleDetail article_detail;
private List<Integer> fail_idx;
public static WxMpFreePublishStatus fromJson(String json) {
return WxGsonBuilder.create().fromJson(json, WxMpFreePublishStatus.class);
}
@Override
public String toJson() {
return WxGsonBuilder.create().toJson(this);
}
@NoArgsConstructor
@Data
public static class ArticleDetail {
private Integer count;
private List<Item> item;
@NoArgsConstructor
@Data
public static class Item {
private Integer idx;
private String article_url;
}
}
}

View File

@ -5,7 +5,10 @@ import lombok.Getter;
import me.chanjar.weixin.mp.config.WxMpConfigStorage;
import me.chanjar.weixin.mp.config.WxMpHostConfig;
import static me.chanjar.weixin.mp.config.WxMpHostConfig.*;
import static me.chanjar.weixin.mp.config.WxMpHostConfig.API_DEFAULT_HOST_URL;
import static me.chanjar.weixin.mp.config.WxMpHostConfig.MP_DEFAULT_HOST_URL;
import static me.chanjar.weixin.mp.config.WxMpHostConfig.OPEN_DEFAULT_HOST_URL;
import static me.chanjar.weixin.mp.config.WxMpHostConfig.buildUrl;
/**
* <pre>
@ -1374,6 +1377,90 @@ public interface WxMpApiUrl {
;
private final String prefix;
private final String path;
}
/**
* 草稿箱 能力:
* 新建草稿
* 获取草稿
* 删除草稿
* 修改草稿
* 获取草稿总数
* 获取草稿列表
* MP端开关仅内测期间使用- 上线后废弃没实现可以自己去公众号后台开启草稿箱
*/
@AllArgsConstructor
@Getter
enum Draft implements WxMpApiUrl {
/**
* 新建草稿
*/
ADD_DRAFT(API_DEFAULT_HOST_URL, "/cgi-bin/draft/add"),
/**
* 修改草稿
*/
UPDATE_DRAFT(API_DEFAULT_HOST_URL, "/cgi-bin/draft/update"),
/**
* 获取草稿
*/
GET_DRAFT(API_DEFAULT_HOST_URL, "/cgi-bin/draft/get"),
/**
* 删除草稿
*/
DEL_DRAFT(API_DEFAULT_HOST_URL, "/cgi-bin/draft/delete"),
/**
* 获取草稿列表
*/
LIST_DRAFT(API_DEFAULT_HOST_URL, "/cgi-bin/draft/batchget"),
/**
* 获取草稿总数
*/
COUNT_DRAFT(API_DEFAULT_HOST_URL, "/cgi-bin/draft/count");
private final String prefix;
private final String path;
}
/**
* 发布能力:
* 发布接口
* 发布状态轮询接口
* 事件推送发布结果 -- 是回调没实现
* 删除发布
* 通过 article_id 获取已发布文章
* 获取成功发布列表
*/
@AllArgsConstructor
@Getter
enum FreePublish implements WxMpApiUrl {
/**
* 发布接口
*/
SUBMIT(API_DEFAULT_HOST_URL, "/cgi-bin/freepublish/submit"),
/**
* 通过 article_id 获取已发布文章
*/
GET_ARTICLE(API_DEFAULT_HOST_URL, "/cgi-bin/freepublish/getarticle"),
/**
* 发布状态轮询接口
*/
GET_PUSH_STATUS(API_DEFAULT_HOST_URL, "/cgi-bin/freepublish/get"),
/**
* 删除发布
*/
DEL_PUSH(API_DEFAULT_HOST_URL, "/cgi-bin/freepublish/delete"),
/**
* 获取成功发布列表
*/
BATCH_GET(API_DEFAULT_HOST_URL, "/cgi-bin/freepublish/batchget")
;
private final String prefix;
private final String path;

View File

@ -0,0 +1,127 @@
package me.chanjar.weixin.mp.api.impl;
import com.google.inject.Inject;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.api.test.ApiTestModule;
import me.chanjar.weixin.mp.bean.draft.WxMpAddDraft;
import me.chanjar.weixin.mp.bean.draft.WxMpDraftArticles;
import me.chanjar.weixin.mp.bean.draft.WxMpDraftInfo;
import me.chanjar.weixin.mp.bean.draft.WxMpDraftList;
import me.chanjar.weixin.mp.bean.draft.WxMpUpdateDraft;
import org.testng.annotations.Guice;
import org.testng.annotations.Test;
import java.util.ArrayList;
import java.util.List;
import static org.assertj.core.api.Assertions.assertThat;
/**
* 草稿箱单元测试.
*
* @author dragon
* @date 2021-10-22
*/
@Guice(modules = ApiTestModule.class)
public class WxMpDraftServiceImplTest {
/**
* 1.先上传一个永久图片素材me.chanjar.weixin.mp.api.impl.WxMpMaterialServiceImplTest.testUploadMaterial
* 2.后续图文需要设置一个永久素材id
*/
final String thumbMediaId = "zUUtT8ZYeXzZ4slFbtnAkh7Yd-f45DbFoF9ERzVC6s4";
/**
* 新增草稿后返回的id后续查询修改删除获取等需要使用
*/
final String mediaId = "zUUtT8ZYeXzZ4slFbtnAkpgGKyqnTsjtUvMdVBRWJVk";
@Inject
protected WxMpService wxService;
@Test
public void testAddDraft() throws WxErrorException {
// {"mediaId":"zUUtT8ZYeXzZ4slFbtnAkh7Yd-f45DbFoF9ERzVC6s4","url":"http://mmbiz.qpic.cn/mmbiz_jpg/fLtyChQRfH84IyicNUbGt3l3IlHxJRibSFz7Tky0ibmzKykzVbo9tZGYhXQGJ2npFtDPbvPhKYxBz6JxkYIibTmUicQ/0?wx_fmt=jpeg"}
this.wxService.getDraftService().addDraft("标题", "图文消息的具体内容", thumbMediaId);
// 响应数据{"media_id":"zUUtT8ZYeXzZ4slFbtnAks-nZeGiPQmwvhShTh72CqM","item":[]}
}
@Test
public void testAddGuide_another() throws WxErrorException {
List<WxMpDraftArticles> draftArticleList = new ArrayList<>();
WxMpDraftArticles draftArticle = WxMpDraftArticles.builder()
.title("新建草稿-对象形式")
.author("dragon")
.digest("图文消息的摘要,仅有单图文消息才有摘要,多图文此处为空")
.content("图文消息的具体内容支持HTML标签必须少于2万字符小于1M且此处会去除JS")
.contentSourceUrl("https://github.com/Wechat-Group/WxJava")
.thumbMediaId(thumbMediaId)
// 显示封面打开评论所有人可评论
.showCoverPic(1).needOpenComment(1).onlyFansCanComment(0)
.build();
draftArticleList.add(draftArticle);
WxMpAddDraft addDraft = WxMpAddDraft.builder().articles(draftArticleList).build();
String mediaId = this.wxService.getDraftService().addDraft(addDraft);
// 响应数据{"media_id":"zUUtT8ZYeXzZ4slFbtnAkpgGKyqnTsjtUvMdVBRWJVk","item":[]}
assertThat(mediaId).isNotNull();
}
@Test
public void testGetDraft() throws WxErrorException {
final WxMpDraftInfo draftInfo = this.wxService.getDraftService().getDraft(mediaId);
assertThat(draftInfo).isNotNull();
// 响应数据{"news_item":[{"title":"标题","author":"","digest":"图文消息的具体内容","content":"图文消息的具体内容","content_source_url":"","thumb_media_id":"zUUtT8ZYeXzZ4slFbtnAkh7Yd-f45DbFoF9ERzVC6s4","show_cover_pic":1,"url":"http:\/\/mp.weixin.qq.com\/s?__biz=Mzk0OTI5MzM1OQ==&mid=100000006&idx=1&sn=89903965ae5ebd6014903c7c5ca34daa&chksm=435bd946742c5050d18da32289904db5ede8bbd157d181438231a1762b85030419b3c0ed4c00#rd","thumb_url":"http:\/\/mmbiz.qpic.cn\/mmbiz_jpg\/fLtyChQRfH84IyicNUbGt3l3IlHxJRibSFz7Tky0ibmzKykzVbo9tZGYhXQGJ2npFtDPbvPhKYxBz6JxkYIibTmUicQ\/0?wx_fmt=jpeg","need_open_comment":0,"only_fans_can_comment":0}],"create_time":1634886802,"update_time":1634886802}
}
@Test
public void testUpdateDraft() throws WxErrorException {
WxMpDraftArticles draftArticles = WxMpDraftArticles.builder()
.title("新标题").content("新图文消息的具体内容").thumbMediaId(thumbMediaId).build();
WxMpUpdateDraft updateDraft = WxMpUpdateDraft.builder()
.mediaId(mediaId)
.index(0)
.articles(draftArticles)
.build();
Boolean updateDraftResult = this.wxService.getDraftService().updateDraft(updateDraft);
// assertThat(updateDraftResult).isTrue();
assertThat(updateDraftResult).isTrue();
}
@Test
public void testDelDraft() throws WxErrorException {
Boolean delDraftResult = this.wxService.getDraftService().delDraft(mediaId);
// 响应数据{"errcode":0,"errmsg":"ok"}
assertThat(delDraftResult).isTrue();
}
@Test
public void testListDraft() throws WxErrorException {
WxMpDraftList draftList = this.wxService.getDraftService().listDraft(0, 10);
/*
响应数据{"item":[{"media_id":"zUUtT8ZYeXzZ4slFbtnAks-nZeGiPQmwvhShTh72CqM",
"content":{
"news_item":
[
{"title":"标题","author":"","digest":"图文消息的具体内容","content":"图文消息的具体内容",
"content_source_url":"","thumb_media_id":"zUUtT8ZYeXzZ4slFbtnAkh7Yd-f45DbFoF9ERzVC6s4",
"show_cover_pic":1,"url":"http:\/\/mp.weixin.qq.com\/s?__biz=Mzk0OTI5MzM1?wx_fmt=jpeg",
"need_open_comment":0,"only_fans_can_comment":0}],
"create_time":1634886802,"update_time":1634886802},"update_time":1634886802}
]
,"total_count":1,"item_count":1}
*/
assertThat(draftList).isNotNull();
}
@Test
public void testCountDraft() throws WxErrorException {
Long countDraft = this.wxService.getDraftService().countDraft();
// 响应数据{"total_count":1}
assertThat(countDraft).isNotNull();
}
}

View File

@ -0,0 +1,109 @@
package me.chanjar.weixin.mp.api.impl;
import com.google.inject.Inject;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.api.test.ApiTestModule;
import me.chanjar.weixin.mp.bean.freepublish.WxMpFreePublishInfo;
import me.chanjar.weixin.mp.bean.freepublish.WxMpFreePublishList;
import me.chanjar.weixin.mp.bean.freepublish.WxMpFreePublishStatus;
import org.testng.annotations.Guice;
import org.testng.annotations.Test;
import static org.assertj.core.api.Assertions.assertThat;
/**
* 发布能力-单元测试.
*
* @author dragon
* @date 2021-10-23
*/
@Guice(modules = ApiTestModule.class)
public class WxMpFreePublishServiceImplTest {
/**
* 新增草稿后返回的id发布需要使用
*/
final String mediaId = "HKVdzjkDfooMqBqJtvSs2EEeRAJaM33gJgkii_JDOHg";
/**
* 发布后的id后续查询等需要使用
*/
final String publishId = "2650177669";
/**
* 图文的 article_id后续查询图文详情删除发布内容 需要使用
* 要根据 publishId 来获取 article_id
*
* @see this.testGetPushStatus
*/
final String articleId = "zjMKVd1g66BkEkpetwml4ElbDdniE8JeI2Ec324Sjqg";
@Inject
protected WxMpService wxService;
@Test
public void testSubmit() throws WxErrorException {
String submit = this.wxService.getFreePublishService().submit(mediaId);
assertThat(submit).isNotBlank();
// 响应数据{"errcode":0,"errmsg":"ok","publish_id":2650177668}
}
@Test
public void testGetPushStatus() throws WxErrorException {
WxMpFreePublishStatus pushStatus = this.wxService.getFreePublishService().getPushStatus(publishId);
assertThat(pushStatus).isNotNull();
// 响应数据{"publish_id":2650177668,"publish_status":0,"article_id":"zjMKVd1g66BkEkpetwml4J-4gNf4I1nsh-B-r_inemw",
// "article_detail":{"count":1,"item":
// [{"idx":1,"article_url":
// "https://mp.weixin.qq.com/s?__biz=MzAwMTE2MzA1xxxxxxxxxx"
// }]},"fail_idx":[]}
// article_url -> 已发布内容可被自定义菜单自动回复话题引用也可用于公开传播
}
@Test
public void testGetArticleFromId() throws WxErrorException {
WxMpFreePublishInfo articleFromId = this.wxService.getFreePublishService().getArticleFromId(articleId);
assertThat(articleFromId).isNotNull();
/* 响应数据{"news_item":[{"title":"欢迎你加入啊~ 这是我的第一条文字消息草稿","author":"","digest":"","content":"欢迎你加入啊~ 这是我的第一条文字消息草稿",
"content_source_url":"","thumb_media_id":"","show_cover_pic":0,"url":"http:\/\/mp.weixin.qq
.com\/s?__biz=MzAwMTE2MzA1Mg==&mid=2650177668","thumb_url":"","need_open_comment":1,"only_fans_can_comment":1,"is_deleted":false}],
"create_time":1634961670,"update_time":1634961672}
*/
}
@Test
public void testDelPush() throws WxErrorException {
Boolean deletePush = this.wxService.getFreePublishService().deletePush(articleId, 0);
// 响应数据{"errcode":0,"errmsg":"ok"}
assertThat(deletePush).isTrue();
}
@Test
public void testDeletePushAllArticle() throws WxErrorException {
Boolean deletePush = this.wxService.getFreePublishService().deletePushAllArticle(articleId);
// 响应数据{"errcode":0,"errmsg":"ok"}
assertThat(deletePush).isTrue();
}
@Test
public void testGetPublicationRecords() throws WxErrorException {
WxMpFreePublishList publicationRecords = this.wxService.getFreePublishService().getPublicationRecords(0, 10, 0);
/*
响应数据
{"item":[{"article_id":"zjMKVd1g66BkEkpetwml4BOSzatuEYNY3TFhCc0kSIE","content":{"news_item":[
{"title":"新建草稿-对象形式","author":"dragon","digest":"图文消息的摘要,仅有单图文消息才有摘要,多图文此处为空",
"content":"图文消息的具体内容支持HTML标签必须少于2万字符小于1M且此处会去除JS",
"content_source_url":"https:\/\/github.com\/Wechat-Group\/WxJava","thumb_media_id":"HKVdzjkDfooMqBqJtvSs2Ajz2v6L_vtGhyyr_mqKcPU",
"show_cover_pic":1,"url":"http:\/\/mp.weixin.qq.com\/s?__biz=MzAwMTE2MzA1Mg==&mid=26501776710e5adb91#rd",
"thumb_url":"http:\/\/mmbiz.qpic.cn\/mmbiz_jpg\/0QSAUfroWrUmxHthQ\/0?wx_fmt=jpeg",
"need_open_comment":1,"only_fans_can_comment":0,"is_deleted":false}],
"create_time":1634976306,"update_time":1634976318}}
]
,"total_count":1,"item_count":1}
*/
assertThat(publicationRecords).isNotNull();
}
}