Skip to content

Commit 08e2107

Browse files
authored
🎨 #3571【公众号】草稿箱相关接口支持图片文章类型
1 parent f71ac21 commit 08e2107

File tree

6 files changed

+291
-6
lines changed

6 files changed

+291
-6
lines changed

weixin-java-common/src/main/java/me/chanjar/weixin/common/api/WxConsts.java

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -431,7 +431,7 @@ public static class EventType {
431431
*/
432432
public static final String WEAPP_AUDIT_FAIL = "weapp_audit_fail";
433433

434-
434+
435435
/**
436436
* 小程序审核事件:审核延后
437437
*/
@@ -622,4 +622,19 @@ public static class AppIdType {
622622
*/
623623
public static final String MINI_TYPE = "mini";
624624
}
625+
626+
/**
627+
* 新建文章类型
628+
*/
629+
@UtilityClass
630+
public static class ArticleType {
631+
/**
632+
* 图文消息
633+
*/
634+
public static final String NEWS = "news";
635+
/**
636+
* 图片消息
637+
*/
638+
public static final String NEWS_PIC = "newspic";
639+
}
625640
}

weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/draft/WxMpDraftArticles.java

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,13 @@
2323
@NoArgsConstructor
2424
@AllArgsConstructor
2525
public class WxMpDraftArticles implements ToJson, Serializable {
26+
/**
27+
* 文章类型,分别有图文消息(news)、图片消息(newspic),不填默认为图文消息(news)
28+
*
29+
* @see me.chanjar.weixin.common.api.WxConsts.ArticleType
30+
*/
31+
@SerializedName("article_type")
32+
private String articleType;
2633
/**
2734
* 标题
2835
*/
@@ -78,18 +85,31 @@ public class WxMpDraftArticles implements ToJson, Serializable {
7885
*/
7986
@SerializedName("thumb_url")
8087
private String thumbUrl;
81-
8288
/**
8389
* 封面裁剪为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。
8490
*/
8591
@SerializedName("pic_crop_235_1")
8692
private String picCrop2351;
87-
8893
/**
8994
* 封面裁剪为1:1规格的坐标字段,裁剪原理同pic_crop_235_1,裁剪后的图片必须符合规格要求。
9095
*/
9196
@SerializedName("pic_crop_1_1")
9297
private String picCrop11;
98+
/**
99+
* 图片消息里的图片相关信息,图片数量最多为20张,首张图片即为封面图
100+
*/
101+
@SerializedName("image_info")
102+
private WxMpDraftImageInfo imageInfo;
103+
/**
104+
* 封面图裁剪信息
105+
*/
106+
@SerializedName("cover_info")
107+
private WxMpDraftCoverInfo coverInfo;
108+
/**
109+
* 商品相关信息
110+
*/
111+
@SerializedName("product_info")
112+
private WxMpDraftProductInfo productInfo;
93113

94114
public static WxMpDraftArticles fromJson(String json) {
95115
return WxGsonBuilder.create().fromJson(json, WxMpDraftArticles.class);
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
package me.chanjar.weixin.mp.bean.draft;
2+
3+
import com.google.gson.annotations.SerializedName;
4+
import lombok.AllArgsConstructor;
5+
import lombok.Builder;
6+
import lombok.Data;
7+
import lombok.NoArgsConstructor;
8+
import lombok.experimental.Accessors;
9+
import me.chanjar.weixin.common.util.json.WxGsonBuilder;
10+
11+
import java.io.Serializable;
12+
import java.util.List;
13+
14+
/**
15+
* 草稿箱能力-图片消息里的封面裁剪信息
16+
*
17+
* @author 阿杆
18+
* created on 2025/5/23
19+
*/
20+
@Data
21+
@Builder
22+
@Accessors(chain = true)
23+
@NoArgsConstructor
24+
@AllArgsConstructor
25+
public class WxMpDraftCoverInfo implements Serializable {
26+
27+
private static final long serialVersionUID = -1676442833397632638L;
28+
29+
/**
30+
* 封面裁剪信息,裁剪比例ratio支持:“1_1”,“16_9”,“2.35_1”。
31+
* 以图片左上角(0,0),右下角(1,1)建立平面坐标系,经过裁剪后的图片,其左上角所在的坐标填入x1,y1参数,右下角所在的坐标填入x2,y2参数
32+
*/
33+
@SerializedName("crop_percent_list")
34+
private List<CropPercent> cropPercentList;
35+
36+
public static WxMpDraftCoverInfo fromJson(String json) {
37+
return WxGsonBuilder.create().fromJson(json, WxMpDraftCoverInfo.class);
38+
}
39+
40+
@Data
41+
@Builder
42+
@NoArgsConstructor
43+
@AllArgsConstructor
44+
public static class CropPercent implements Serializable {
45+
private static final long serialVersionUID = 8495528870408737871L;
46+
private String ratio;
47+
private String x1;
48+
private String y1;
49+
private String x2;
50+
private String y2;
51+
}
52+
53+
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
package me.chanjar.weixin.mp.bean.draft;
2+
3+
import com.google.gson.annotations.SerializedName;
4+
import lombok.AllArgsConstructor;
5+
import lombok.Builder;
6+
import lombok.Data;
7+
import lombok.NoArgsConstructor;
8+
import lombok.experimental.Accessors;
9+
import me.chanjar.weixin.common.util.json.WxGsonBuilder;
10+
11+
import java.io.Serializable;
12+
import java.util.List;
13+
14+
/**
15+
* 草稿箱能力-图片消息里的图片相关信息
16+
*
17+
* @author 阿杆
18+
* created on 2025/5/23
19+
*/
20+
@Data
21+
@Builder
22+
@Accessors(chain = true)
23+
@NoArgsConstructor
24+
@AllArgsConstructor
25+
public class WxMpDraftImageInfo implements Serializable {
26+
27+
private static final long serialVersionUID = -1997245511033770476L;
28+
29+
/**
30+
* 图片列表
31+
*/
32+
@SerializedName("image_list")
33+
private List<ImageItem> imageList;
34+
35+
public static WxMpDraftImageInfo fromJson(String json) {
36+
return WxGsonBuilder.create().fromJson(json, WxMpDraftImageInfo.class);
37+
}
38+
39+
@Data
40+
@NoArgsConstructor
41+
@AllArgsConstructor
42+
public static class ImageItem implements Serializable {
43+
private static final long serialVersionUID = 4180558781166966752L;
44+
/**
45+
* 图片消息里的图片素材id(必须是永久MediaID)
46+
*/
47+
@SerializedName("image_media_id")
48+
private String imageMediaId;
49+
}
50+
51+
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
package me.chanjar.weixin.mp.bean.draft;
2+
3+
import com.google.gson.annotations.SerializedName;
4+
import lombok.AllArgsConstructor;
5+
import lombok.Builder;
6+
import lombok.Data;
7+
import lombok.NoArgsConstructor;
8+
import lombok.experimental.Accessors;
9+
import me.chanjar.weixin.common.util.json.WxGsonBuilder;
10+
11+
import java.io.Serializable;
12+
13+
/**
14+
* 草稿箱能力-商品相关信息
15+
*
16+
* @author 阿杆
17+
* created on 2025/5/23
18+
*/
19+
@Data
20+
@Builder
21+
@Accessors(chain = true)
22+
@NoArgsConstructor
23+
@AllArgsConstructor
24+
public class WxMpDraftProductInfo implements Serializable {
25+
private static final long serialVersionUID = 8637785998127610863L;
26+
27+
/**
28+
* 文末插入商品相关信息
29+
*/
30+
@SerializedName("footer_product_info")
31+
private FooterProductInfo footerProductInfo;
32+
33+
public static WxMpDraftProductInfo fromJson(String json) {
34+
return WxGsonBuilder.create().fromJson(json, WxMpDraftProductInfo.class);
35+
}
36+
37+
@Data
38+
@NoArgsConstructor
39+
@AllArgsConstructor
40+
public static class FooterProductInfo {
41+
/**
42+
* 商品key
43+
*/
44+
@SerializedName("product_key")
45+
private String productKey;
46+
}
47+
48+
}

weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpDraftServiceImplTest.java

Lines changed: 101 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package me.chanjar.weixin.mp.api.impl;
22

33
import com.google.inject.Inject;
4+
import me.chanjar.weixin.common.api.WxConsts;
45
import me.chanjar.weixin.common.error.WxErrorException;
56
import me.chanjar.weixin.mp.api.WxMpService;
67
import me.chanjar.weixin.mp.api.test.ApiTestModule;
@@ -23,15 +24,15 @@
2324
public class WxMpDraftServiceImplTest {
2425

2526
/**
26-
* 1.先上传一个永久图片素材:me.chanjar.weixin.mp.api.impl.WxMpMaterialServiceImplTest.testUploadMaterial
27+
* 1.先上传一个永久图片素材:{@link me.chanjar.weixin.mp.api.impl.WxMpMaterialServiceImplTest#testUploadMaterial}
2728
* 2.后续图文需要设置一个永久素材id
2829
*/
29-
final String thumbMediaId = "zUUtT8ZYeXzZ4slFbtnAkh7Yd-f45DbFoF9ERzVC6s4";
30+
final String thumbMediaId = "-V3dxNv-eyJlImuJjWrmaTPt76BS6jHrL6-cGBlFPaXxAuv0qeJYV2p6Ezirr0zS";
3031

3132
/**
3233
* 新增草稿后返回的id,后续查询、修改、删除,获取等需要使用
3334
*/
34-
final String mediaId = "zUUtT8ZYeXzZ4slFbtnAkpgGKyqnTsjtUvMdVBRWJVk";
35+
final String mediaId = "-V3dxNv-eyJlImuJjWrmaZLwMkTKfDEhzq5NURU02H-k1qHMJ0lh9p0UU46w3rbd";
3536

3637
@Inject
3738
protected WxMpService wxService;
@@ -114,6 +115,7 @@ public void testListDraft() throws WxErrorException {
114115
,"total_count":1,"item_count":1}
115116
116117
*/
118+
System.out.println(draftList);
117119
assertThat(draftList).isNotNull();
118120
}
119121

@@ -124,5 +126,101 @@ public void testCountDraft() throws WxErrorException {
124126
assertThat(countDraft).isNotNull();
125127
}
126128

129+
//-----以下是图片类型草稿测试
130+
131+
/**
132+
* 先上传一个永久图片素材:{@link me.chanjar.weixin.mp.api.impl.WxMpMaterialServiceImplTest#testUploadMaterial}
133+
* 这里的图片,使用的是 mm.jpeg
134+
*/
135+
@Test
136+
public void testAddDraftPic() throws WxErrorException {
137+
List<WxMpDraftArticles> draftArticleList = new ArrayList<>();
138+
ArrayList<WxMpDraftImageInfo.ImageItem> imageItems = new ArrayList<>();
139+
imageItems.add(new WxMpDraftImageInfo.ImageItem(thumbMediaId));
140+
141+
ArrayList<WxMpDraftCoverInfo.CropPercent> cropPercents = new ArrayList<>();
142+
cropPercents.add(new WxMpDraftCoverInfo.CropPercent("1_1", "0.1", "0", "1", "0.9"));
143+
144+
WxMpDraftArticles draftArticle = WxMpDraftArticles.builder()
145+
.articleType(WxConsts.ArticleType.NEWS_PIC)
146+
.title("新建图片草稿")
147+
.content("图片消息的具体内容")
148+
// 打开评论、所有人可评论
149+
.needOpenComment(1).onlyFansCanComment(0)
150+
.imageInfo(WxMpDraftImageInfo.builder().imageList(imageItems).build())
151+
.coverInfo(WxMpDraftCoverInfo.builder().cropPercentList(cropPercents).build())
152+
.productInfo(WxMpDraftProductInfo.builder().footerProductInfo(new WxMpDraftProductInfo.FooterProductInfo("")).build())
153+
.build();
154+
draftArticleList.add(draftArticle);
155+
156+
WxMpAddDraft addDraft = WxMpAddDraft.builder().articles(draftArticleList).build();
157+
String mediaId = this.wxService.getDraftService().addDraft(addDraft);
158+
System.out.println(mediaId);
159+
assertThat(mediaId).isNotNull();
160+
}
161+
162+
@Test
163+
public void testGetDraftPic() throws WxErrorException {
164+
final WxMpDraftInfo draftInfo = this.wxService.getDraftService().getDraft(mediaId);
165+
assertThat(draftInfo).isNotNull();
166+
System.out.println(draftInfo.toJson());
167+
// 【响应数据】:{
168+
// "news_item": [
169+
// {
170+
// "article_type": "newspic",
171+
// "title": "新建图片草稿",
172+
// "content": "图片消息的具体内容",
173+
// "thumb_media_id": "-V3dxNv-eyJlImuJjWrmaTPt76BS6jHrL6-cGBlFPaXxAuv0qeJYV2p6Ezirr0zS",
174+
// "need_open_comment": 1,
175+
// "only_fans_can_comment": 0,
176+
// "url": "http://mp.weixin.qq.com/s?__biz=MzkyNTg4NDM1NA==&tempkey=MTMyM18rUktkOHFIQm5Kd3U5Rk1yS2NRYWtyZWUyNDNwS2MxZTZ3VXBKTkVScExpUFdGYzN2X0IzOEl1NGxEMGFpYld6NmdvbE9UUzlyYUdiVklvWTQ2YlRzSkkzQlpWMEZpcG9JRWp5LWZCVVNoWURodUlfWnE4VWZVQnlPd2VaUkg5SGREYUd3TW1wQkhlbTFuenBvRzFIbUxhMEJVbEo0Z3oyd2tnSGJBfn4%3D&chksm=423e8b9e75490288e8388c9ee91d6dad462bbce654742edd316622ab2b2fcfc593a4db58577b#rd",
177+
// "thumb_url": "http://mmbiz.qpic.cn/sz_mmbiz_jpg/s7FE7rYN42QgPuJeXX9MfNuJBiaoalrWv8fj4AEqnK0WBM3KzqS0DsqHIW4epA3cx1PGjpco87BTssgQibvSNBIQ/0?wx_fmt=jpeg",
178+
// "image_info": {
179+
// "image_list": [
180+
// {
181+
// "image_media_id": "-V3dxNv-eyJlImuJjWrmaTPt76BS6jHrL6-cGBlFPaXxAuv0qeJYV2p6Ezirr0zS"
182+
// }
183+
// ]
184+
// }
185+
// }
186+
// ]
187+
// }
188+
}
189+
190+
@Test
191+
public void testUpdateDraftPic() throws WxErrorException {
192+
ArrayList<WxMpDraftImageInfo.ImageItem> imageItems = new ArrayList<>();
193+
imageItems.add(new WxMpDraftImageInfo.ImageItem(thumbMediaId));
194+
ArrayList<WxMpDraftCoverInfo.CropPercent> cropPercents = new ArrayList<>();
195+
cropPercents.add(new WxMpDraftCoverInfo.CropPercent("1_1", "0.3", "0", "1", "0.7"));
196+
197+
WxMpDraftArticles draftArticle = WxMpDraftArticles.builder()
198+
.articleType(WxConsts.ArticleType.NEWS_PIC)
199+
.title("修改图片草稿")
200+
.content("修改后的图片消息的具体内容")
201+
// 打开评论、所有人可评论
202+
.needOpenComment(1).onlyFansCanComment(0)
203+
.imageInfo(WxMpDraftImageInfo.builder().imageList(imageItems).build())
204+
.coverInfo(WxMpDraftCoverInfo.builder().cropPercentList(cropPercents).build())
205+
.productInfo(WxMpDraftProductInfo.builder().footerProductInfo(new WxMpDraftProductInfo.FooterProductInfo("")).build())
206+
.build();
207+
208+
WxMpUpdateDraft updateDraft = WxMpUpdateDraft.builder()
209+
.mediaId(mediaId)
210+
.index(0)
211+
.articles(draftArticle)
212+
.build();
213+
Boolean updateDraftResult = this.wxService.getDraftService().updateDraft(updateDraft);
214+
assertThat(updateDraftResult).isTrue();
215+
}
216+
217+
@Test
218+
public void testDelDraftPic() throws WxErrorException {
219+
Boolean delDraftResult = this.wxService.getDraftService().delDraft(mediaId);
220+
System.out.println(delDraftResult);
221+
// 【响应数据】:{"errcode":0,"errmsg":"ok"}
222+
assertThat(delDraftResult).isTrue();
223+
}
224+
127225
}
128226

0 commit comments

Comments
 (0)