@@ -23,14 +23,15 @@ public class WxConsts { | |||
/////////////////////// | |||
// 主动发送消息(即客服消息)的消息类型 | |||
/////////////////////// | |||
public static final String CUSTOM_MSG_TEXT = "text"; | |||
public static final String CUSTOM_MSG_IMAGE = "image"; | |||
public static final String CUSTOM_MSG_VOICE = "voice"; | |||
public static final String CUSTOM_MSG_VIDEO = "video"; | |||
public static final String CUSTOM_MSG_MUSIC = "music"; | |||
public static final String CUSTOM_MSG_NEWS = "news"; | |||
public static final String CUSTOM_MSG_FILE = "file"; | |||
public static final String CUSTOM_MSG_WXCARD = "wxcard"; | |||
public static final String CUSTOM_MSG_TEXT = "text";//文本消息 | |||
public static final String CUSTOM_MSG_IMAGE = "image";//图片消息 | |||
public static final String CUSTOM_MSG_VOICE = "voice";//语音消息 | |||
public static final String CUSTOM_MSG_VIDEO = "video";//视频消息 | |||
public static final String CUSTOM_MSG_MUSIC = "music";//音乐消息 | |||
public static final String CUSTOM_MSG_NEWS = "news";//图文消息(点击跳转到外链) | |||
public static final String CUSTOM_MSG_MPNEWS = "mpnews";//图文消息(点击跳转到图文消息页面) | |||
public static final String CUSTOM_MSG_FILE = "file";//发送文件(CP专用) | |||
public static final String CUSTOM_MSG_WXCARD = "wxcard";//卡券消息 | |||
public static final String CUSTOM_MSG_TRANSFER_CUSTOMER_SERVICE = "transfer_customer_service"; | |||
public static final String CUSTOM_MSG_SAFE_NO = "0"; | |||
public static final String CUSTOM_MSG_SAFE_YES = "1"; | |||
@@ -193,7 +194,7 @@ public class WxConsts { | |||
* 弹出授权页面,可通过openid拿到昵称、性别、所在地。并且,即使在未关注的情况下,只要用户授权,也能获取其信息 | |||
*/ | |||
public static final String OAUTH2_SCOPE_USER_INFO = "snsapi_userinfo"; | |||
/** | |||
* 网页应用登录授权作用域 snsapi_login | |||
*/ | |||
@@ -1,17 +1,16 @@ | |||
package me.chanjar.weixin.mp.bean; | |||
import me.chanjar.weixin.mp.util.json.WxMpGsonBuilder; | |||
import org.apache.commons.lang3.builder.ToStringBuilder; | |||
import org.apache.commons.lang3.builder.ToStringStyle; | |||
import java.io.Serializable; | |||
import java.util.ArrayList; | |||
import java.util.List; | |||
public class WxMpMaterialNews implements Serializable { | |||
/** | |||
* | |||
*/ | |||
private static final long serialVersionUID = -3283203652013494976L; | |||
private List<WxMpMaterialNewsArticle> articles = new ArrayList<>(); | |||
public List<WxMpMaterialNewsArticle> getArticles() { | |||
@@ -81,7 +80,6 @@ public class WxMpMaterialNews implements Serializable { | |||
/** | |||
* 点击图文消息跳转链接 | |||
* @return | |||
*/ | |||
private String url; | |||
@@ -159,14 +157,12 @@ public class WxMpMaterialNews implements Serializable { | |||
@Override | |||
public String toString() { | |||
return "WxMpMassNewsArticle [" + "thumbMediaId=" + this.thumbMediaId + "thumbUrl=" + this.thumbUrl + ", author=" + this.author + ", title=" + this.title + | |||
", contentSourceUrl=" + this.contentSourceUrl + ", content=" + this.content + ", digest=" + this.digest + | |||
", showCoverPic=" + this.showCoverPic +", url=" + this.url + "]"; | |||
return ToStringBuilder.reflectionToString(this, ToStringStyle.MULTI_LINE_STYLE); | |||
} | |||
} | |||
@Override | |||
public String toString() { | |||
return "WxMpMaterialNews [" + "articles=" + this.articles + "]"; | |||
return ToStringBuilder.reflectionToString(this, ToStringStyle.MULTI_LINE_STYLE); | |||
} | |||
} |
@@ -0,0 +1,33 @@ | |||
package me.chanjar.weixin.mp.bean.custombuilder; | |||
import me.chanjar.weixin.common.api.WxConsts; | |||
import me.chanjar.weixin.mp.bean.kefu.WxMpKefuMessage; | |||
/** | |||
* 图文消息builder | |||
* <pre> | |||
* 用法: | |||
* WxMpKefuMessage m = WxMpKefuMessage.NEWS().mediaId("xxxxx").toUser(...).build(); | |||
* </pre> | |||
* @author Binary Wang | |||
* | |||
*/ | |||
public final class MpNewsBuilder extends BaseBuilder<MpNewsBuilder> { | |||
private String mediaId; | |||
public MpNewsBuilder() { | |||
this.msgType = WxConsts.CUSTOM_MSG_MPNEWS; | |||
} | |||
public MpNewsBuilder mediaId(String mediaId) { | |||
this.mediaId = mediaId; | |||
return this; | |||
} | |||
@Override | |||
public WxMpKefuMessage build() { | |||
WxMpKefuMessage m = super.build(); | |||
m.setMpNewsMediaId(this.mediaId); | |||
return m; | |||
} | |||
} |
@@ -1,16 +1,23 @@ | |||
package me.chanjar.weixin.mp.bean.kefu; | |||
import me.chanjar.weixin.mp.bean.custombuilder.*; | |||
import me.chanjar.weixin.mp.util.json.WxMpGsonBuilder; | |||
import java.io.Serializable; | |||
import java.util.ArrayList; | |||
import java.util.List; | |||
import me.chanjar.weixin.mp.bean.custombuilder.ImageBuilder; | |||
import me.chanjar.weixin.mp.bean.custombuilder.MpNewsBuilder; | |||
import me.chanjar.weixin.mp.bean.custombuilder.MusicBuilder; | |||
import me.chanjar.weixin.mp.bean.custombuilder.NewsBuilder; | |||
import me.chanjar.weixin.mp.bean.custombuilder.TextBuilder; | |||
import me.chanjar.weixin.mp.bean.custombuilder.VideoBuilder; | |||
import me.chanjar.weixin.mp.bean.custombuilder.VoiceBuilder; | |||
import me.chanjar.weixin.mp.bean.custombuilder.WxCardBuilder; | |||
import me.chanjar.weixin.mp.util.json.WxMpGsonBuilder; | |||
/** | |||
* 客服消息 | |||
* @author chanjarster | |||
* | |||
* @author chanjarster | |||
*/ | |||
public class WxMpKefuMessage implements Serializable { | |||
private static final long serialVersionUID = -9196732086954365246L; | |||
@@ -26,18 +33,85 @@ public class WxMpKefuMessage implements Serializable { | |||
private String hqMusicUrl; | |||
private String kfAccount; | |||
private String cardId; | |||
private String mpNewsMediaId; | |||
private List<WxArticle> articles = new ArrayList<>(); | |||
/** | |||
* 获得文本消息builder | |||
*/ | |||
public static TextBuilder TEXT() { | |||
return new TextBuilder(); | |||
} | |||
/** | |||
* 获得图片消息builder | |||
*/ | |||
public static ImageBuilder IMAGE() { | |||
return new ImageBuilder(); | |||
} | |||
/** | |||
* 获得语音消息builder | |||
*/ | |||
public static VoiceBuilder VOICE() { | |||
return new VoiceBuilder(); | |||
} | |||
/** | |||
* 获得视频消息builder | |||
*/ | |||
public static VideoBuilder VIDEO() { | |||
return new VideoBuilder(); | |||
} | |||
/** | |||
* 获得音乐消息builder | |||
*/ | |||
public static MusicBuilder MUSIC() { | |||
return new MusicBuilder(); | |||
} | |||
/** | |||
* 获得图文消息(点击跳转到外链)builder | |||
*/ | |||
public static NewsBuilder NEWS() { | |||
return new NewsBuilder(); | |||
} | |||
/** | |||
* 获得图文消息(点击跳转到图文消息页面)builder | |||
*/ | |||
public static MpNewsBuilder MPNEWS() { | |||
return new MpNewsBuilder(); | |||
} | |||
/** | |||
* 获得卡券消息builder | |||
*/ | |||
public static WxCardBuilder WXCARD() { | |||
return new WxCardBuilder(); | |||
} | |||
public String getToUser() { | |||
return this.toUser; | |||
} | |||
public void setToUser(String toUser) { | |||
this.toUser = toUser; | |||
} | |||
public String getMsgType() { | |||
return this.msgType; | |||
} | |||
public String getMpNewsMediaId() { | |||
return this.mpNewsMediaId; | |||
} | |||
public void setMpNewsMediaId(String mpNewsMediaId) { | |||
this.mpNewsMediaId = mpNewsMediaId; | |||
} | |||
/** | |||
* <pre> | |||
* 请使用 | |||
@@ -47,52 +121,68 @@ public class WxMpKefuMessage implements Serializable { | |||
* {@link me.chanjar.weixin.common.api.WxConsts#CUSTOM_MSG_MUSIC} | |||
* {@link me.chanjar.weixin.common.api.WxConsts#CUSTOM_MSG_VIDEO} | |||
* {@link me.chanjar.weixin.common.api.WxConsts#CUSTOM_MSG_NEWS} | |||
* {@link me.chanjar.weixin.common.api.WxConsts#CUSTOM_MSG_MPNEWS} | |||
* {@link me.chanjar.weixin.common.api.WxConsts#CUSTOM_MSG_WXCARD} | |||
* </pre> | |||
* | |||
* @param msgType | |||
*/ | |||
public void setMsgType(String msgType) { | |||
this.msgType = msgType; | |||
} | |||
public String getContent() { | |||
return this.content; | |||
} | |||
public void setContent(String content) { | |||
this.content = content; | |||
} | |||
public String getMediaId() { | |||
return this.mediaId; | |||
} | |||
public void setMediaId(String mediaId) { | |||
this.mediaId = mediaId; | |||
} | |||
public String getThumbMediaId() { | |||
return this.thumbMediaId; | |||
} | |||
public void setThumbMediaId(String thumbMediaId) { | |||
this.thumbMediaId = thumbMediaId; | |||
} | |||
public String getTitle() { | |||
return this.title; | |||
} | |||
public void setTitle(String title) { | |||
this.title = title; | |||
} | |||
public String getDescription() { | |||
return this.description; | |||
} | |||
public void setDescription(String description) { | |||
this.description = description; | |||
} | |||
public String getMusicUrl() { | |||
return this.musicUrl; | |||
} | |||
public void setMusicUrl(String musicUrl) { | |||
this.musicUrl = musicUrl; | |||
} | |||
public String getHqMusicUrl() { | |||
return this.hqMusicUrl; | |||
} | |||
public void setHqMusicUrl(String hqMusicUrl) { | |||
this.hqMusicUrl = hqMusicUrl; | |||
} | |||
@@ -108,6 +198,7 @@ public class WxMpKefuMessage implements Serializable { | |||
public List<WxArticle> getArticles() { | |||
return this.articles; | |||
} | |||
public void setArticles(List<WxArticle> articles) { | |||
this.articles = articles; | |||
} | |||
@@ -116,8 +207,15 @@ public class WxMpKefuMessage implements Serializable { | |||
return WxMpGsonBuilder.INSTANCE.create().toJson(this); | |||
} | |||
public static class WxArticle { | |||
public String getKfAccount() { | |||
return this.kfAccount; | |||
} | |||
public void setKfAccount(String kfAccount) { | |||
this.kfAccount = kfAccount; | |||
} | |||
public static class WxArticle { | |||
private String title; | |||
private String description; | |||
private String url; | |||
@@ -126,85 +224,34 @@ public class WxMpKefuMessage implements Serializable { | |||
public String getTitle() { | |||
return this.title; | |||
} | |||
public void setTitle(String title) { | |||
this.title = title; | |||
} | |||
public String getDescription() { | |||
return this.description; | |||
} | |||
public void setDescription(String description) { | |||
this.description = description; | |||
} | |||
public String getUrl() { | |||
return this.url; | |||
} | |||
public void setUrl(String url) { | |||
this.url = url; | |||
} | |||
public String getPicUrl() { | |||
return this.picUrl; | |||
} | |||
public void setPicUrl(String picUrl) { | |||
this.picUrl = picUrl; | |||
} | |||
} | |||
/** | |||
* 获得文本消息builder | |||
*/ | |||
public static TextBuilder TEXT() { | |||
return new TextBuilder(); | |||
} | |||
/** | |||
* 获得图片消息builder | |||
*/ | |||
public static ImageBuilder IMAGE() { | |||
return new ImageBuilder(); | |||
} | |||
/** | |||
* 获得语音消息builder | |||
*/ | |||
public static VoiceBuilder VOICE() { | |||
return new VoiceBuilder(); | |||
} | |||
/** | |||
* 获得视频消息builder | |||
*/ | |||
public static VideoBuilder VIDEO() { | |||
return new VideoBuilder(); | |||
} | |||
/** | |||
* 获得音乐消息builder | |||
*/ | |||
public static MusicBuilder MUSIC() { | |||
return new MusicBuilder(); | |||
} | |||
/** | |||
* 获得图文消息builder | |||
*/ | |||
public static NewsBuilder NEWS() { | |||
return new NewsBuilder(); | |||
} | |||
/** | |||
* 获得卡券消息builder | |||
*/ | |||
public static WxCardBuilder WXCARD() { | |||
return new WxCardBuilder(); | |||
} | |||
public String getKfAccount() { | |||
return this.kfAccount; | |||
} | |||
public void setKfAccount(String kfAccount) { | |||
this.kfAccount = kfAccount; | |||
} | |||
} |
@@ -75,6 +75,12 @@ public class WxMpKefuMessageGsonAdapter implements JsonSerializer<WxMpKefuMessag | |||
messageJson.add("news", newsJsonObject); | |||
} | |||
if (WxConsts.CUSTOM_MSG_MPNEWS.equals(message.getMsgType())) { | |||
JsonObject json = new JsonObject(); | |||
json.addProperty("media_id", message.getMpNewsMediaId()); | |||
messageJson.add("mpnews", json); | |||
} | |||
if (WxConsts.CUSTOM_MSG_WXCARD.equals(message.getMsgType())) { | |||
JsonObject wxcard = new JsonObject(); | |||
wxcard.addProperty("card_id", message.getCardId()); | |||
@@ -1,29 +1,21 @@ | |||
package me.chanjar.weixin.mp.api.impl; | |||
import java.io.File; | |||
import java.util.Date; | |||
import com.google.inject.Inject; | |||
import me.chanjar.weixin.common.api.WxConsts; | |||
import me.chanjar.weixin.common.exception.WxErrorException; | |||
import me.chanjar.weixin.mp.api.ApiTestModule; | |||
import me.chanjar.weixin.mp.api.WxXmlMpInMemoryConfigStorage; | |||
import me.chanjar.weixin.mp.bean.kefu.WxMpKefuMessage; | |||
import me.chanjar.weixin.mp.bean.kefu.request.WxMpKfAccountRequest; | |||
import me.chanjar.weixin.mp.bean.kefu.result.*; | |||
import org.joda.time.DateTime; | |||
import org.testng.Assert; | |||
import org.testng.annotations.DataProvider; | |||
import org.testng.annotations.Guice; | |||
import org.testng.annotations.Test; | |||
import com.google.inject.Inject; | |||
import me.chanjar.weixin.common.api.WxConsts; | |||
import me.chanjar.weixin.common.exception.WxErrorException; | |||
import me.chanjar.weixin.mp.api.ApiTestModule; | |||
import me.chanjar.weixin.mp.api.WxXmlMpInMemoryConfigStorage; | |||
import me.chanjar.weixin.mp.bean.kefu.request.WxMpKfAccountRequest; | |||
import me.chanjar.weixin.mp.bean.kefu.result.WxMpKfInfo; | |||
import me.chanjar.weixin.mp.bean.kefu.result.WxMpKfList; | |||
import me.chanjar.weixin.mp.bean.kefu.result.WxMpKfMsgList; | |||
import me.chanjar.weixin.mp.bean.kefu.result.WxMpKfOnlineList; | |||
import me.chanjar.weixin.mp.bean.kefu.result.WxMpKfSessionGetResult; | |||
import me.chanjar.weixin.mp.bean.kefu.result.WxMpKfSessionList; | |||
import me.chanjar.weixin.mp.bean.kefu.result.WxMpKfSessionWaitCaseList; | |||
import java.io.File; | |||
import java.util.Date; | |||
/** | |||
* 测试客服相关接口 | |||
@@ -37,7 +29,18 @@ public class WxMpKefuServiceImplTest { | |||
@Inject | |||
protected WxMpServiceImpl wxService; | |||
public void testSendCustomMessage() throws WxErrorException { | |||
public void testSendKefuMpNewsMessage() throws WxErrorException { | |||
WxXmlMpInMemoryConfigStorage configStorage = (WxXmlMpInMemoryConfigStorage) this.wxService | |||
.getWxMpConfigStorage(); | |||
WxMpKefuMessage message = new WxMpKefuMessage(); | |||
message.setMsgType(WxConsts.CUSTOM_MSG_MPNEWS); | |||
message.setToUser(configStorage.getOpenid()); | |||
message.setMpNewsMediaId("52R6dL2FxDpM9N1rCY3sYBqHwq-L7K_lz1sPI71idMg"); | |||
this.wxService.getKefuService().sendKefuMessage(message); | |||
} | |||
public void testSendKefuMessage() throws WxErrorException { | |||
WxXmlMpInMemoryConfigStorage configStorage = (WxXmlMpInMemoryConfigStorage) this.wxService | |||
.getWxMpConfigStorage(); | |||
WxMpKefuMessage message = new WxMpKefuMessage(); | |||
@@ -49,7 +52,7 @@ public class WxMpKefuServiceImplTest { | |||
this.wxService.getKefuService().sendKefuMessage(message); | |||
} | |||
public void testSendCustomMessageWithKfAccount() throws WxErrorException { | |||
public void testSendKefuMessageWithKfAccount() throws WxErrorException { | |||
WxXmlMpInMemoryConfigStorage configStorage = (WxXmlMpInMemoryConfigStorage) this.wxService | |||
.getWxMpConfigStorage(); | |||
WxMpKefuMessage message = new WxMpKefuMessage(); | |||
@@ -98,41 +98,40 @@ public class WxMpMaterialServiceImplTest { | |||
@Test(dependsOnMethods = {"testUploadMaterial"}) | |||
public void testAddNews() throws WxErrorException { | |||
// 单图文消息 | |||
WxMpMaterialNews wxMpMaterialNewsSingle = new WxMpMaterialNews(); | |||
WxMpMaterialNews.WxMpMaterialNewsArticle mpMaterialNewsArticleSingle = new WxMpMaterialNews.WxMpMaterialNewsArticle(); | |||
mpMaterialNewsArticleSingle.setAuthor("author"); | |||
mpMaterialNewsArticleSingle.setThumbMediaId(this.thumbMediaId); | |||
mpMaterialNewsArticleSingle.setTitle("single title"); | |||
mpMaterialNewsArticleSingle.setContent("single content"); | |||
mpMaterialNewsArticleSingle.setContentSourceUrl("content url"); | |||
mpMaterialNewsArticleSingle.setShowCoverPic(true); | |||
mpMaterialNewsArticleSingle.setDigest("single news"); | |||
wxMpMaterialNewsSingle.addArticle(mpMaterialNewsArticleSingle); | |||
WxMpMaterialNews.WxMpMaterialNewsArticle article = new WxMpMaterialNews.WxMpMaterialNewsArticle(); | |||
article.setAuthor("author"); | |||
article.setThumbMediaId(this.thumbMediaId); | |||
article.setTitle("single title"); | |||
article.setContent("single content"); | |||
article.setContentSourceUrl("content url"); | |||
article.setShowCoverPic(true); | |||
article.setDigest("single news"); | |||
wxMpMaterialNewsSingle.addArticle(article); | |||
// 多图文消息 | |||
WxMpMaterialNews wxMpMaterialNewsMultiple = new WxMpMaterialNews(); | |||
WxMpMaterialNews.WxMpMaterialNewsArticle wxMpMaterialNewsArticleMultiple1 = new WxMpMaterialNews.WxMpMaterialNewsArticle(); | |||
wxMpMaterialNewsArticleMultiple1.setAuthor("author1"); | |||
wxMpMaterialNewsArticleMultiple1.setThumbMediaId(this.thumbMediaId); | |||
wxMpMaterialNewsArticleMultiple1.setTitle("multi title1"); | |||
wxMpMaterialNewsArticleMultiple1.setContent("content 1"); | |||
wxMpMaterialNewsArticleMultiple1.setContentSourceUrl("content url"); | |||
wxMpMaterialNewsArticleMultiple1.setShowCoverPic(true); | |||
wxMpMaterialNewsArticleMultiple1.setDigest(""); | |||
WxMpMaterialNews.WxMpMaterialNewsArticle wxMpMaterialNewsArticleMultiple2 = new WxMpMaterialNews.WxMpMaterialNewsArticle(); | |||
wxMpMaterialNewsArticleMultiple2.setAuthor("author2"); | |||
wxMpMaterialNewsArticleMultiple2.setThumbMediaId(this.thumbMediaId); | |||
wxMpMaterialNewsArticleMultiple2.setTitle("multi title2"); | |||
wxMpMaterialNewsArticleMultiple2.setContent("content 2"); | |||
wxMpMaterialNewsArticleMultiple2.setContentSourceUrl("content url"); | |||
wxMpMaterialNewsArticleMultiple2.setShowCoverPic(true); | |||
wxMpMaterialNewsArticleMultiple2.setDigest(""); | |||
wxMpMaterialNewsMultiple.addArticle(wxMpMaterialNewsArticleMultiple1); | |||
wxMpMaterialNewsMultiple.addArticle(wxMpMaterialNewsArticleMultiple2); | |||
WxMpMaterialNews.WxMpMaterialNewsArticle article1 = new WxMpMaterialNews.WxMpMaterialNewsArticle(); | |||
article1.setAuthor("author1"); | |||
article1.setThumbMediaId(this.thumbMediaId); | |||
article1.setTitle("multi title1"); | |||
article1.setContent("content 1"); | |||
article1.setContentSourceUrl("content url"); | |||
article1.setShowCoverPic(true); | |||
article1.setDigest(""); | |||
WxMpMaterialNews.WxMpMaterialNewsArticle article2 = new WxMpMaterialNews.WxMpMaterialNewsArticle(); | |||
article2.setAuthor("author2"); | |||
article2.setThumbMediaId(this.thumbMediaId); | |||
article2.setTitle("multi title2"); | |||
article2.setContent("content 2"); | |||
article2.setContentSourceUrl("content url"); | |||
article2.setShowCoverPic(true); | |||
article2.setDigest(""); | |||
wxMpMaterialNewsMultiple.addArticle(article1); | |||
wxMpMaterialNewsMultiple.addArticle(article2); | |||
WxMpMaterialUploadResult resSingle = this.wxService.getMaterialService().materialNewsUpload(wxMpMaterialNewsSingle); | |||
this.singleNewsMediaId = resSingle.getMediaId(); | |||
@@ -268,6 +267,7 @@ public class WxMpMaterialServiceImplTest { | |||
// 以下为media接口的测试 | |||
private List<String> mediaIdsToDownload = new ArrayList<>(); | |||
@Test(dataProvider="mediaFiles") | |||
public void testUploadMedia(String mediaType, String fileType, String fileName) throws WxErrorException, IOException { | |||
try(InputStream inputStream = ClassLoader.getSystemResourceAsStream(fileName)){ | |||