🎨 #3571【公众号】草稿箱相关接口支持图片文章类型

This commit is contained in:
阿杆 2025-05-28 15:59:08 +08:00 committed by GitHub
parent f71ac2185c
commit 08e2107667
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 291 additions and 6 deletions

View File

@ -431,7 +431,7 @@ public class WxConsts {
*/
public static final String WEAPP_AUDIT_FAIL = "weapp_audit_fail";
/**
* 小程序审核事件审核延后
*/
@ -622,4 +622,19 @@ public class WxConsts {
*/
public static final String MINI_TYPE = "mini";
}
/**
* 新建文章类型
*/
@UtilityClass
public static class ArticleType {
/**
* 图文消息
*/
public static final String NEWS = "news";
/**
* 图片消息
*/
public static final String NEWS_PIC = "newspic";
}
}

View File

@ -23,6 +23,13 @@ import java.io.Serializable;
@NoArgsConstructor
@AllArgsConstructor
public class WxMpDraftArticles implements ToJson, Serializable {
/**
* 文章类型分别有图文消息news图片消息newspic不填默认为图文消息news
*
* @see me.chanjar.weixin.common.api.WxConsts.ArticleType
*/
@SerializedName("article_type")
private String articleType;
/**
* 标题
*/
@ -78,18 +85,31 @@ public class WxMpDraftArticles implements ToJson, Serializable {
*/
@SerializedName("thumb_url")
private String thumbUrl;
/**
* 封面裁剪为2.35:1规格的坐标字段以原始图片thumb_media_id左上角0,0右下角1,1建立平面坐标系经过裁剪后的图片其左上角所在的坐标即为X1,Y1,右下角所在的坐标则为X2,Y2用分隔符_拼接为X1_Y1_X2_Y2每个坐标值的精度为不超过小数点后6位数字示例见下图图中(X1,Y1) 等于0.1945,0,(X2,Y2)等于1,0.5236所以请求参数值为0.1945_0_1_0.5236
*/
@SerializedName("pic_crop_235_1")
private String picCrop2351;
/**
* 封面裁剪为1:1规格的坐标字段裁剪原理同pic_crop_235_1裁剪后的图片必须符合规格要求
*/
@SerializedName("pic_crop_1_1")
private String picCrop11;
/**
* 图片消息里的图片相关信息图片数量最多为20张首张图片即为封面图
*/
@SerializedName("image_info")
private WxMpDraftImageInfo imageInfo;
/**
* 封面图裁剪信息
*/
@SerializedName("cover_info")
private WxMpDraftCoverInfo coverInfo;
/**
* 商品相关信息
*/
@SerializedName("product_info")
private WxMpDraftProductInfo productInfo;
public static WxMpDraftArticles fromJson(String json) {
return WxGsonBuilder.create().fromJson(json, WxMpDraftArticles.class);

View File

@ -0,0 +1,53 @@
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.util.json.WxGsonBuilder;
import java.io.Serializable;
import java.util.List;
/**
* 草稿箱能力-图片消息里的封面裁剪信息
*
* @author 阿杆
* created on 2025/5/23
*/
@Data
@Builder
@Accessors(chain = true)
@NoArgsConstructor
@AllArgsConstructor
public class WxMpDraftCoverInfo implements Serializable {
private static final long serialVersionUID = -1676442833397632638L;
/**
* 封面裁剪信息裁剪比例ratio支持1_116_9,2.35_1
* 以图片左上角0,0右下角1,1建立平面坐标系经过裁剪后的图片其左上角所在的坐标填入x1y1参数右下角所在的坐标填入x2y2参数
*/
@SerializedName("crop_percent_list")
private List<CropPercent> cropPercentList;
public static WxMpDraftCoverInfo fromJson(String json) {
return WxGsonBuilder.create().fromJson(json, WxMpDraftCoverInfo.class);
}
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public static class CropPercent implements Serializable {
private static final long serialVersionUID = 8495528870408737871L;
private String ratio;
private String x1;
private String y1;
private String x2;
private String y2;
}
}

View File

@ -0,0 +1,51 @@
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.util.json.WxGsonBuilder;
import java.io.Serializable;
import java.util.List;
/**
* 草稿箱能力-图片消息里的图片相关信息
*
* @author 阿杆
* created on 2025/5/23
*/
@Data
@Builder
@Accessors(chain = true)
@NoArgsConstructor
@AllArgsConstructor
public class WxMpDraftImageInfo implements Serializable {
private static final long serialVersionUID = -1997245511033770476L;
/**
* 图片列表
*/
@SerializedName("image_list")
private List<ImageItem> imageList;
public static WxMpDraftImageInfo fromJson(String json) {
return WxGsonBuilder.create().fromJson(json, WxMpDraftImageInfo.class);
}
@Data
@NoArgsConstructor
@AllArgsConstructor
public static class ImageItem implements Serializable {
private static final long serialVersionUID = 4180558781166966752L;
/**
* 图片消息里的图片素材id必须是永久MediaID
*/
@SerializedName("image_media_id")
private String imageMediaId;
}
}

View File

@ -0,0 +1,48 @@
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.util.json.WxGsonBuilder;
import java.io.Serializable;
/**
* 草稿箱能力-商品相关信息
*
* @author 阿杆
* created on 2025/5/23
*/
@Data
@Builder
@Accessors(chain = true)
@NoArgsConstructor
@AllArgsConstructor
public class WxMpDraftProductInfo implements Serializable {
private static final long serialVersionUID = 8637785998127610863L;
/**
* 文末插入商品相关信息
*/
@SerializedName("footer_product_info")
private FooterProductInfo footerProductInfo;
public static WxMpDraftProductInfo fromJson(String json) {
return WxGsonBuilder.create().fromJson(json, WxMpDraftProductInfo.class);
}
@Data
@NoArgsConstructor
@AllArgsConstructor
public static class FooterProductInfo {
/**
* 商品key
*/
@SerializedName("product_key")
private String productKey;
}
}

View File

@ -1,6 +1,7 @@
package me.chanjar.weixin.mp.api.impl;
import com.google.inject.Inject;
import me.chanjar.weixin.common.api.WxConsts;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.api.test.ApiTestModule;
@ -23,15 +24,15 @@ import static org.assertj.core.api.Assertions.assertThat;
public class WxMpDraftServiceImplTest {
/**
* 1.先上传一个永久图片素材me.chanjar.weixin.mp.api.impl.WxMpMaterialServiceImplTest.testUploadMaterial
* 1.先上传一个永久图片素材{@link me.chanjar.weixin.mp.api.impl.WxMpMaterialServiceImplTest#testUploadMaterial}
* 2.后续图文需要设置一个永久素材id
*/
final String thumbMediaId = "zUUtT8ZYeXzZ4slFbtnAkh7Yd-f45DbFoF9ERzVC6s4";
final String thumbMediaId = "-V3dxNv-eyJlImuJjWrmaTPt76BS6jHrL6-cGBlFPaXxAuv0qeJYV2p6Ezirr0zS";
/**
* 新增草稿后返回的id后续查询修改删除获取等需要使用
*/
final String mediaId = "zUUtT8ZYeXzZ4slFbtnAkpgGKyqnTsjtUvMdVBRWJVk";
final String mediaId = "-V3dxNv-eyJlImuJjWrmaZLwMkTKfDEhzq5NURU02H-k1qHMJ0lh9p0UU46w3rbd";
@Inject
protected WxMpService wxService;
@ -114,6 +115,7 @@ public class WxMpDraftServiceImplTest {
,"total_count":1,"item_count":1}
*/
System.out.println(draftList);
assertThat(draftList).isNotNull();
}
@ -124,5 +126,101 @@ public class WxMpDraftServiceImplTest {
assertThat(countDraft).isNotNull();
}
//-----以下是图片类型草稿测试
/**
* 先上传一个永久图片素材{@link me.chanjar.weixin.mp.api.impl.WxMpMaterialServiceImplTest#testUploadMaterial}
* 这里的图片使用的是 mm.jpeg
*/
@Test
public void testAddDraftPic() throws WxErrorException {
List<WxMpDraftArticles> draftArticleList = new ArrayList<>();
ArrayList<WxMpDraftImageInfo.ImageItem> imageItems = new ArrayList<>();
imageItems.add(new WxMpDraftImageInfo.ImageItem(thumbMediaId));
ArrayList<WxMpDraftCoverInfo.CropPercent> cropPercents = new ArrayList<>();
cropPercents.add(new WxMpDraftCoverInfo.CropPercent("1_1", "0.1", "0", "1", "0.9"));
WxMpDraftArticles draftArticle = WxMpDraftArticles.builder()
.articleType(WxConsts.ArticleType.NEWS_PIC)
.title("新建图片草稿")
.content("图片消息的具体内容")
// 打开评论所有人可评论
.needOpenComment(1).onlyFansCanComment(0)
.imageInfo(WxMpDraftImageInfo.builder().imageList(imageItems).build())
.coverInfo(WxMpDraftCoverInfo.builder().cropPercentList(cropPercents).build())
.productInfo(WxMpDraftProductInfo.builder().footerProductInfo(new WxMpDraftProductInfo.FooterProductInfo("")).build())
.build();
draftArticleList.add(draftArticle);
WxMpAddDraft addDraft = WxMpAddDraft.builder().articles(draftArticleList).build();
String mediaId = this.wxService.getDraftService().addDraft(addDraft);
System.out.println(mediaId);
assertThat(mediaId).isNotNull();
}
@Test
public void testGetDraftPic() throws WxErrorException {
final WxMpDraftInfo draftInfo = this.wxService.getDraftService().getDraft(mediaId);
assertThat(draftInfo).isNotNull();
System.out.println(draftInfo.toJson());
// 响应数据{
// "news_item": [
// {
// "article_type": "newspic",
// "title": "新建图片草稿",
// "content": "图片消息的具体内容",
// "thumb_media_id": "-V3dxNv-eyJlImuJjWrmaTPt76BS6jHrL6-cGBlFPaXxAuv0qeJYV2p6Ezirr0zS",
// "need_open_comment": 1,
// "only_fans_can_comment": 0,
// "url": "http://mp.weixin.qq.com/s?__biz=MzkyNTg4NDM1NA==&tempkey=MTMyM18rUktkOHFIQm5Kd3U5Rk1yS2NRYWtyZWUyNDNwS2MxZTZ3VXBKTkVScExpUFdGYzN2X0IzOEl1NGxEMGFpYld6NmdvbE9UUzlyYUdiVklvWTQ2YlRzSkkzQlpWMEZpcG9JRWp5LWZCVVNoWURodUlfWnE4VWZVQnlPd2VaUkg5SGREYUd3TW1wQkhlbTFuenBvRzFIbUxhMEJVbEo0Z3oyd2tnSGJBfn4%3D&chksm=423e8b9e75490288e8388c9ee91d6dad462bbce654742edd316622ab2b2fcfc593a4db58577b#rd",
// "thumb_url": "http://mmbiz.qpic.cn/sz_mmbiz_jpg/s7FE7rYN42QgPuJeXX9MfNuJBiaoalrWv8fj4AEqnK0WBM3KzqS0DsqHIW4epA3cx1PGjpco87BTssgQibvSNBIQ/0?wx_fmt=jpeg",
// "image_info": {
// "image_list": [
// {
// "image_media_id": "-V3dxNv-eyJlImuJjWrmaTPt76BS6jHrL6-cGBlFPaXxAuv0qeJYV2p6Ezirr0zS"
// }
// ]
// }
// }
// ]
// }
}
@Test
public void testUpdateDraftPic() throws WxErrorException {
ArrayList<WxMpDraftImageInfo.ImageItem> imageItems = new ArrayList<>();
imageItems.add(new WxMpDraftImageInfo.ImageItem(thumbMediaId));
ArrayList<WxMpDraftCoverInfo.CropPercent> cropPercents = new ArrayList<>();
cropPercents.add(new WxMpDraftCoverInfo.CropPercent("1_1", "0.3", "0", "1", "0.7"));
WxMpDraftArticles draftArticle = WxMpDraftArticles.builder()
.articleType(WxConsts.ArticleType.NEWS_PIC)
.title("修改图片草稿")
.content("修改后的图片消息的具体内容")
// 打开评论所有人可评论
.needOpenComment(1).onlyFansCanComment(0)
.imageInfo(WxMpDraftImageInfo.builder().imageList(imageItems).build())
.coverInfo(WxMpDraftCoverInfo.builder().cropPercentList(cropPercents).build())
.productInfo(WxMpDraftProductInfo.builder().footerProductInfo(new WxMpDraftProductInfo.FooterProductInfo("")).build())
.build();
WxMpUpdateDraft updateDraft = WxMpUpdateDraft.builder()
.mediaId(mediaId)
.index(0)
.articles(draftArticle)
.build();
Boolean updateDraftResult = this.wxService.getDraftService().updateDraft(updateDraft);
assertThat(updateDraftResult).isTrue();
}
@Test
public void testDelDraftPic() throws WxErrorException {
Boolean delDraftResult = this.wxService.getDraftService().delDraft(mediaId);
System.out.println(delDraftResult);
// 响应数据{"errcode":0,"errmsg":"ok"}
assertThat(delDraftResult).isTrue();
}
}