Skip to content

Commit f76b4db

Browse files
committed
新增商家客服服务入口与请求执行
1 parent a651123 commit f76b4db

7 files changed

Lines changed: 199 additions & 0 deletions

File tree

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
package me.chanjar.weixin.channel.api;
2+
3+
import me.chanjar.weixin.channel.bean.kf.WxChannelKfSendMsgParam;
4+
import me.chanjar.weixin.channel.bean.kf.WxChannelKfSendMsgResponse;
5+
import me.chanjar.weixin.common.error.WxErrorException;
6+
7+
/** 视频号小店商家客服服务。 */
8+
public interface WxChannelKfService {
9+
10+
/**
11+
* 上传多媒体资源。
12+
*
13+
* @param openId 用户 open_id
14+
* @param msgType 文件类型,仅支持 video、file、image
15+
* @param file 文件字节内容
16+
* @return COS 地址
17+
* @throws WxErrorException 微信异常
18+
*/
19+
String uploadMedia(String openId, String msgType, byte[] file) throws WxErrorException;
20+
21+
/**
22+
* 上传多媒体资源。
23+
*
24+
* @param openId 用户 open_id
25+
* @param msgType 文件类型,仅支持 video、file、image
26+
* @param fileName 文件名
27+
* @param file 文件字节内容
28+
* @return COS 地址
29+
* @throws WxErrorException 微信异常
30+
*/
31+
String uploadMedia(String openId, String msgType, String fileName, byte[] file) throws WxErrorException;
32+
33+
/**
34+
* 发送客服消息。
35+
*
36+
* @param param 请求参数
37+
* @return 发送结果
38+
* @throws WxErrorException 微信异常
39+
*/
40+
WxChannelKfSendMsgResponse sendMessage(WxChannelKfSendMsgParam param) throws WxErrorException;
41+
}

weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/WxChannelService.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,13 @@
77
*/
88
public interface WxChannelService extends BaseWxChannelService {
99

10+
/**
11+
* 商家客服服务。
12+
*
13+
* @return 商家客服服务
14+
*/
15+
WxChannelKfService getKfService();
16+
1017
/**
1118
* 基础接口服务
1219
*

weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/impl/BaseWxChannelServiceImpl.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ public abstract class BaseWxChannelServiceImpl<H, P> implements WxChannelService
6464
private WxChannelQicService qicService = null;
6565
private WxTalentService talentService = null;
6666
private WxChannelFavoriteService favoriteService = null;
67+
private WxChannelKfService kfService = null;
6768

6869
protected WxChannelConfig config;
6970
private int retrySleepMillis = 1000;
@@ -509,4 +510,12 @@ public synchronized WxChannelFavoriteService getFavoriteService() {
509510
return favoriteService;
510511
}
511512

513+
@Override
514+
public synchronized WxChannelKfService getKfService() {
515+
if (kfService == null) {
516+
kfService = new WxChannelKfServiceImpl(this);
517+
}
518+
return kfService;
519+
}
520+
512521
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
package me.chanjar.weixin.channel.api.impl;
2+
3+
import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.Kf.COS_UPLOAD_URL;
4+
import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.Kf.SEND_MSG_URL;
5+
6+
import me.chanjar.weixin.channel.api.WxChannelKfService;
7+
import me.chanjar.weixin.channel.bean.kf.WxChannelKfCosUploadResponse;
8+
import me.chanjar.weixin.channel.bean.kf.WxChannelKfSendMsgParam;
9+
import me.chanjar.weixin.channel.bean.kf.WxChannelKfSendMsgResponse;
10+
import me.chanjar.weixin.channel.util.ResponseUtils;
11+
import me.chanjar.weixin.common.bean.CommonUploadParam;
12+
import me.chanjar.weixin.common.error.WxErrorException;
13+
14+
/** 视频号小店商家客服服务实现。 */
15+
public class WxChannelKfServiceImpl implements WxChannelKfService {
16+
17+
private final BaseWxChannelServiceImpl<?, ?> channelService;
18+
19+
public WxChannelKfServiceImpl(BaseWxChannelServiceImpl<?, ?> channelService) {
20+
this.channelService = channelService;
21+
}
22+
23+
@Override
24+
public String uploadMedia(String openId, String msgType, byte[] file) throws WxErrorException {
25+
return uploadMedia(openId, msgType, null, file);
26+
}
27+
28+
@Override
29+
public String uploadMedia(String openId, String msgType, String fileName, byte[] file) throws WxErrorException {
30+
CommonUploadParam uploadParam = CommonUploadParam.fromBytes("file", fileName, file)
31+
.addFormField("open_id", openId)
32+
.addFormField("msg_type", msgType);
33+
String responseJson = channelService.upload(COS_UPLOAD_URL, uploadParam);
34+
return ResponseUtils.decode(responseJson, WxChannelKfCosUploadResponse.class).getCosUrl();
35+
}
36+
37+
@Override
38+
public WxChannelKfSendMsgResponse sendMessage(WxChannelKfSendMsgParam param) throws WxErrorException {
39+
String responseJson = channelService.post(SEND_MSG_URL, param);
40+
return ResponseUtils.decode(responseJson, WxChannelKfSendMsgResponse.class);
41+
}
42+
}

weixin-java-channel/src/main/java/me/chanjar/weixin/channel/constant/WxChannelApiUrlConstants.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,15 @@ public interface Favorite {
4949
String GET_FAVORITE_COUNT = "https://api.weixin.qq.com/channels/ec/favorites/count/get";
5050
}
5151

52+
/** 商家客服相关接口 */
53+
public interface Kf {
54+
55+
/** 上传客服素材 */
56+
String COS_UPLOAD_URL = "https://api.weixin.qq.com/channels/ec/commkf/cosupload";
57+
/** 发送客服消息 */
58+
String SEND_MSG_URL = "https://api.weixin.qq.com/channels/ec/commkf/sendmsg";
59+
}
60+
5261
/** 商品类目相关接口 */
5362
public interface Category {
5463

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
package me.chanjar.weixin.channel.api.impl;
2+
3+
import static org.testng.Assert.assertEquals;
4+
import static org.testng.Assert.assertNotNull;
5+
import static org.testng.Assert.assertSame;
6+
7+
import me.chanjar.weixin.channel.bean.kf.WxChannelKfSendMsgParam;
8+
import me.chanjar.weixin.channel.bean.kf.WxChannelKfSendMsgResponse;
9+
import me.chanjar.weixin.channel.util.JsonUtils;
10+
import me.chanjar.weixin.common.bean.CommonUploadParam;
11+
import me.chanjar.weixin.common.error.WxErrorException;
12+
import org.testng.annotations.Test;
13+
14+
/** 商家客服服务离线测试。 */
15+
public class WxChannelKfServiceImplTest {
16+
17+
@Test
18+
public void shouldUploadMediaWithDocumentedUrlAndMultipartFields() throws WxErrorException {
19+
RecordingChannelService channelService = new RecordingChannelService();
20+
channelService.uploadResult = "{\"errcode\":0,\"errmsg\":\"ok\",\"cos_url\":\"https://cos.example.com/image.png\"}";
21+
22+
String cosUrl = new WxChannelKfServiceImpl(channelService)
23+
.uploadMedia("open-id", "image", "image.png", new byte[]{1, 2, 3});
24+
25+
assertEquals(channelService.uploadUrl, "https://api.weixin.qq.com/channels/ec/commkf/cosupload");
26+
assertNotNull(channelService.uploadParam);
27+
assertEquals(channelService.uploadParam.getName(), "file");
28+
assertEquals(channelService.uploadParam.getData().getFileName(), "image.png");
29+
assertEquals(channelService.uploadParam.getData().readAllBytes(), new byte[]{1, 2, 3});
30+
assertEquals(channelService.uploadParam.getFormFields().get("open_id"), "open-id");
31+
assertEquals(channelService.uploadParam.getFormFields().get("msg_type"), "image");
32+
assertEquals(cosUrl, "https://cos.example.com/image.png");
33+
}
34+
35+
@Test
36+
public void shouldSendJsonMessageAndDecodeResponse() throws WxErrorException {
37+
RecordingChannelService channelService = new RecordingChannelService();
38+
channelService.postResult = "{\"errcode\":0,\"errmsg\":\"ok\",\"msg_id\":\"message-id\"}";
39+
WxChannelKfSendMsgParam param = new WxChannelKfSendMsgParam();
40+
param.setRequestId("request-id");
41+
param.setOpenId("open-id");
42+
param.setMsgType("text");
43+
WxChannelKfSendMsgParam.Text text = new WxChannelKfSendMsgParam.Text();
44+
text.setContent("hello");
45+
param.setText(text);
46+
47+
WxChannelKfSendMsgResponse response = new WxChannelKfServiceImpl(channelService).sendMessage(param);
48+
49+
assertEquals(channelService.postUrl, "https://api.weixin.qq.com/channels/ec/commkf/sendmsg");
50+
assertEquals(channelService.postJson,
51+
"{\"request_id\":\"request-id\",\"open_id\":\"open-id\",\"msg_type\":\"text\",\"text\":{\"content\":\"hello\"}}");
52+
assertEquals(response.getMsgId(), "message-id");
53+
assertEquals(response.getErrCode(), 0);
54+
}
55+
56+
@Test
57+
public void shouldCacheKfServiceEntryPoint() {
58+
WxChannelServiceImpl channelService = new WxChannelServiceImpl();
59+
60+
assertSame(channelService.getKfService(), channelService.getKfService());
61+
}
62+
63+
private static class RecordingChannelService extends WxChannelServiceImpl {
64+
65+
private String uploadResult;
66+
private String postResult;
67+
private String uploadUrl;
68+
private CommonUploadParam uploadParam;
69+
private String postUrl;
70+
private String postJson;
71+
72+
@Override
73+
public String upload(String url, CommonUploadParam param) {
74+
this.uploadUrl = url;
75+
this.uploadParam = param;
76+
return uploadResult;
77+
}
78+
79+
@Override
80+
public String post(String url, Object obj) {
81+
this.postUrl = url;
82+
this.postJson = JsonUtils.encode(obj);
83+
return postResult;
84+
}
85+
}
86+
}

weixin-java-channel/src/test/resources/testng.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,9 @@
1616
<class name="me.chanjar.weixin.channel.util.ResponseUtilsTest"/>
1717
</classes>
1818
</test>
19+
<test name="Kf_Service_Test">
20+
<classes>
21+
<class name="me.chanjar.weixin.channel.api.impl.WxChannelKfServiceImplTest"/>
22+
</classes>
23+
</test>
1924
</suite>

0 commit comments

Comments
 (0)