@@ -3,19 +3,8 @@ package me.chanjar.weixin.mp.api; | |||
import me.chanjar.weixin.common.bean.WxJsapiSignature; | |||
import me.chanjar.weixin.common.exception.WxErrorException; | |||
import me.chanjar.weixin.common.util.http.RequestExecutor; | |||
import me.chanjar.weixin.mp.bean.WxMpIndustry; | |||
import me.chanjar.weixin.mp.bean.WxMpMassTagMessage; | |||
import me.chanjar.weixin.mp.bean.WxMpMassNews; | |||
import me.chanjar.weixin.mp.bean.WxMpMassOpenIdsMessage; | |||
import me.chanjar.weixin.mp.bean.WxMpMassPreviewMessage; | |||
import me.chanjar.weixin.mp.bean.WxMpMassVideo; | |||
import me.chanjar.weixin.mp.bean.WxMpSemanticQuery; | |||
import me.chanjar.weixin.mp.bean.WxMpTemplateMessage; | |||
import me.chanjar.weixin.mp.bean.result.WxMpMassSendResult; | |||
import me.chanjar.weixin.mp.bean.result.WxMpMassUploadResult; | |||
import me.chanjar.weixin.mp.bean.result.WxMpOAuth2AccessToken; | |||
import me.chanjar.weixin.mp.bean.result.WxMpSemanticQueryResult; | |||
import me.chanjar.weixin.mp.bean.result.WxMpUser; | |||
import me.chanjar.weixin.mp.bean.*; | |||
import me.chanjar.weixin.mp.bean.result.*; | |||
/** | |||
* 微信API的Service | |||
@@ -133,16 +122,6 @@ public interface WxMpService { | |||
*/ | |||
String shortUrl(String long_url) throws WxErrorException; | |||
/** | |||
* <pre> | |||
* 发送模板消息 | |||
* 详情请见: http://mp.weixin.qq.com/wiki/index.php?title=模板消息接口 | |||
* </pre> | |||
* | |||
* @return msgid | |||
*/ | |||
String templateSend(WxMpTemplateMessage templateMessage) throws WxErrorException; | |||
/** | |||
* <pre> | |||
* 语义查询接口 | |||
@@ -266,27 +245,6 @@ public interface WxMpService { | |||
*/ | |||
WxMpMassSendResult massMessagePreview(WxMpMassPreviewMessage wxMpMassPreviewMessage) throws Exception; | |||
/** | |||
* <pre> | |||
* 设置所属行业 | |||
* 官方文档中暂未告知响应内容 | |||
* 详情请见:http://mp.weixin.qq.com/wiki/5/6dde9eaa909f83354e0094dc3ad99e05.html#.E8.AE.BE.E7.BD.AE.E6.89.80.E5.B1.9E.E8.A1.8C.E4.B8.9A | |||
* </pre> | |||
* | |||
* @return JsonObject | |||
*/ | |||
String setIndustry(WxMpIndustry wxMpIndustry) throws WxErrorException; | |||
/*** | |||
* <pre> | |||
* 获取设置的行业信息 | |||
* 详情请见:http://mp.weixin.qq.com/wiki/5/6dde9eaa909f83354e0094dc3ad99e05.html#.E8.AE.BE.E7.BD.AE.E6.89.80.E5.B1.9E.E8.A1.8C.E4.B8.9A | |||
* </pre> | |||
* | |||
* @return wxMpIndustry | |||
*/ | |||
WxMpIndustry getIndustry() throws WxErrorException; | |||
/** | |||
* 获取WxMpConfigStorage 对象 | |||
* | |||
@@ -370,4 +328,11 @@ public interface WxMpService { | |||
* @return WxMpStoreService | |||
*/ | |||
WxMpStoreService getStoreService(); | |||
/** | |||
* 返回模板消息相关接口方法的实现类对象,以方便调用其各种接口 | |||
* | |||
* @return WxMpTemplateMsgService | |||
*/ | |||
WxMpTemplateMsgService getTemplateMsgService(); | |||
} |
@@ -0,0 +1,49 @@ | |||
package me.chanjar.weixin.mp.api; | |||
import me.chanjar.weixin.common.exception.WxErrorException; | |||
import me.chanjar.weixin.mp.bean.WxMpIndustry; | |||
import me.chanjar.weixin.mp.bean.WxMpTemplateMessage; | |||
/** | |||
* <pre> | |||
* 模板消息接口 | |||
* http://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1433751277&token=&lang=zh_CN | |||
* Created by Binary Wang on 2016-10-14. | |||
* @author miller.lin | |||
* @author <a href="https://github.com/binarywang">binarywang(Binary Wang)</a> | |||
* </pre> | |||
*/ | |||
public interface WxMpTemplateMsgService { | |||
/** | |||
* <pre> | |||
* 设置所属行业 | |||
* 官方文档中暂未告知响应内容 | |||
* 详情请见:http://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1433751277&token=&lang=zh_CN | |||
* </pre> | |||
* | |||
* @return 是否成功 | |||
*/ | |||
boolean setIndustry(WxMpIndustry wxMpIndustry) throws WxErrorException; | |||
/*** | |||
* <pre> | |||
* 获取设置的行业信息 | |||
* 详情请见:http://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1433751277&token=&lang=zh_CN | |||
* </pre> | |||
* | |||
* @return wxMpIndustry | |||
*/ | |||
WxMpIndustry getIndustry() throws WxErrorException; | |||
/** | |||
* <pre> | |||
* 发送模板消息 | |||
* 详情请见: http://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1433751277&token=&lang=zh_CN | |||
* </pre> | |||
* | |||
* @return 消息Id | |||
*/ | |||
String sendTemplateMsg(WxMpTemplateMessage templateMessage) throws WxErrorException; | |||
} |
@@ -69,6 +69,8 @@ public class WxMpServiceImpl implements WxMpService { | |||
private WxMpUserBlacklistService blackListService = new WxMpUserBlacklistServiceImpl(this); | |||
private WxMpTemplateMsgService templateMsgService = new WxMpTemplateMsgServiceImpl(this); | |||
private CloseableHttpClient httpClient; | |||
private HttpHost httpProxy; | |||
@@ -221,35 +223,6 @@ public class WxMpServiceImpl implements WxMpService { | |||
return tmpJsonElement.getAsJsonObject().get("short_url").getAsString(); | |||
} | |||
@Override | |||
public String templateSend(WxMpTemplateMessage templateMessage) throws WxErrorException { | |||
String url = "https://api.weixin.qq.com/cgi-bin/message/template/send"; | |||
String responseContent = this.post(url, templateMessage.toJson()); | |||
final JsonObject jsonObject = JSON_PARSER.parse(responseContent).getAsJsonObject(); | |||
if (jsonObject.get("errcode").getAsInt() == 0){ | |||
return jsonObject.get("msgid").getAsString(); | |||
} | |||
throw new WxErrorException(WxError.fromJson(responseContent)); | |||
} | |||
@Override | |||
public String setIndustry(WxMpIndustry wxMpIndustry) throws WxErrorException { | |||
if (null == wxMpIndustry.getPrimaryIndustry() || null == wxMpIndustry.getPrimaryIndustry().getId() | |||
|| null == wxMpIndustry.getSecondIndustry() || null == wxMpIndustry.getSecondIndustry().getId()) { | |||
throw new IllegalArgumentException("industry id is empty"); | |||
} | |||
String url = "https://api.weixin.qq.com/cgi-bin/template/api_set_industry"; | |||
return this.post(url, wxMpIndustry.toJson()); | |||
} | |||
@Override | |||
public WxMpIndustry getIndustry() throws WxErrorException { | |||
String url = "https://api.weixin.qq.com/cgi-bin/template/get_industry"; | |||
String responseContent = this.get(url, null); | |||
return WxMpIndustry.fromJson(responseContent); | |||
} | |||
@Override | |||
public WxMpSemanticQueryResult semanticQuery(WxMpSemanticQuery semanticQuery) throws WxErrorException { | |||
String url = "https://api.weixin.qq.com/semantic/semproxy/search"; | |||
@@ -562,4 +535,9 @@ public class WxMpServiceImpl implements WxMpService { | |||
return this.storeService; | |||
} | |||
@Override | |||
public WxMpTemplateMsgService getTemplateMsgService() { | |||
return this.templateMsgService; | |||
} | |||
} |
@@ -0,0 +1,58 @@ | |||
package me.chanjar.weixin.mp.api.impl; | |||
import com.google.gson.JsonObject; | |||
import com.google.gson.JsonParser; | |||
import me.chanjar.weixin.common.bean.result.WxError; | |||
import me.chanjar.weixin.common.exception.WxErrorException; | |||
import me.chanjar.weixin.mp.api.WxMpService; | |||
import me.chanjar.weixin.mp.api.WxMpTemplateMsgService; | |||
import me.chanjar.weixin.mp.bean.WxMpIndustry; | |||
import me.chanjar.weixin.mp.bean.WxMpTemplateMessage; | |||
/** | |||
* <pre> | |||
* Created by Binary Wang on 2016-10-14. | |||
* @author <a href="https://github.com/binarywang">binarywang(Binary Wang)</a> | |||
* </pre> | |||
*/ | |||
public class WxMpTemplateMsgServiceImpl implements WxMpTemplateMsgService { | |||
public static final String API_URL_PREFIX = "https://api.weixin.qq.com/cgi-bin/template"; | |||
private static final JsonParser JSON_PARSER = new JsonParser(); | |||
private WxMpService wxMpService; | |||
public WxMpTemplateMsgServiceImpl(WxMpService wxMpService) { | |||
this.wxMpService = wxMpService; | |||
} | |||
@Override | |||
public String sendTemplateMsg(WxMpTemplateMessage templateMessage) throws WxErrorException { | |||
String url = "https://api.weixin.qq.com/cgi-bin/message/template/send"; | |||
String responseContent = this.wxMpService.post(url, templateMessage.toJson()); | |||
final JsonObject jsonObject = JSON_PARSER.parse(responseContent).getAsJsonObject(); | |||
if (jsonObject.get("errcode").getAsInt() == 0) { | |||
return jsonObject.get("msgid").getAsString(); | |||
} | |||
throw new WxErrorException(WxError.fromJson(responseContent)); | |||
} | |||
@Override | |||
public boolean setIndustry(WxMpIndustry wxMpIndustry) throws WxErrorException { | |||
if (null == wxMpIndustry.getPrimaryIndustry() || null == wxMpIndustry.getPrimaryIndustry().getId() | |||
|| null == wxMpIndustry.getSecondIndustry() || null == wxMpIndustry.getSecondIndustry().getId()) { | |||
throw new IllegalArgumentException("行业Id不能为空,请核实"); | |||
} | |||
String url = API_URL_PREFIX + "/api_set_industry"; | |||
this.wxMpService.post(url, wxMpIndustry.toJson()); | |||
return true; | |||
} | |||
@Override | |||
public WxMpIndustry getIndustry() throws WxErrorException { | |||
String url = API_URL_PREFIX + "/get_industry"; | |||
String responseContent = this.wxMpService.get(url, null); | |||
return WxMpIndustry.fromJson(responseContent); | |||
} | |||
} |
@@ -1,38 +0,0 @@ | |||
package me.chanjar.weixin.mp.bean; | |||
import java.io.Serializable; | |||
/** | |||
* @author miller | |||
* 官方文档中,创建和获取的数据结构不一样。所以采用冗余字段的方式,实现相应的接口 | |||
*/ | |||
public class Industry implements Serializable { | |||
private static final long serialVersionUID = -1707184885588012142L; | |||
private String id; | |||
private String firstClass; | |||
private String secondClass; | |||
public String getId() { | |||
return this.id; | |||
} | |||
public void setId(String id) { | |||
this.id = id; | |||
} | |||
public String getFirstClass() { | |||
return this.firstClass; | |||
} | |||
public void setFirstClass(String firstClass) { | |||
this.firstClass = firstClass; | |||
} | |||
public String getSecondClass() { | |||
return this.secondClass; | |||
} | |||
public void setSecondClass(String secondClass) { | |||
this.secondClass = secondClass; | |||
} | |||
} |
@@ -2,6 +2,8 @@ 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; | |||
@@ -9,31 +11,97 @@ import java.io.Serializable; | |||
* @author miller | |||
*/ | |||
public class WxMpIndustry implements Serializable { | |||
private static final long serialVersionUID = -7700398224795914722L; | |||
private Industry primaryIndustry; | |||
private Industry secondIndustry; | |||
private static final long serialVersionUID = -7700398224795914722L; | |||
private Industry primaryIndustry; | |||
private Industry secondIndustry; | |||
public static WxMpIndustry fromJson(String json) { | |||
return WxMpGsonBuilder.create().fromJson(json, WxMpIndustry.class); | |||
public WxMpIndustry() { | |||
} | |||
public WxMpIndustry(Industry primaryIndustry, Industry secondIndustry) { | |||
this.primaryIndustry = primaryIndustry; | |||
this.secondIndustry = secondIndustry; | |||
} | |||
/** | |||
* @author miller | |||
* 官方文档中,创建和获取的数据结构不一样。所以采用冗余字段的方式,实现相应的接口 | |||
*/ | |||
public static class Industry implements Serializable { | |||
private static final long serialVersionUID = -1707184885588012142L; | |||
private String id; | |||
private String firstClass; | |||
private String secondClass; | |||
public Industry() { | |||
} | |||
public Industry(String id) { | |||
this.id = id; | |||
} | |||
public Industry(String id, String firstClass, String secondClass) { | |||
this.id = id; | |||
this.firstClass = firstClass; | |||
this.secondClass = secondClass; | |||
} | |||
@Override | |||
public String toString() { | |||
return ToStringBuilder.reflectionToString(this, ToStringStyle.MULTI_LINE_STYLE); | |||
} | |||
public String toJson() { | |||
return WxMpGsonBuilder.create().toJson(this); | |||
public String getId() { | |||
return this.id; | |||
} | |||
public Industry getPrimaryIndustry() { | |||
return this.primaryIndustry; | |||
public void setId(String id) { | |||
this.id = id; | |||
} | |||
public void setPrimaryIndustry(Industry primaryIndustry) { | |||
this.primaryIndustry = primaryIndustry; | |||
public String getFirstClass() { | |||
return this.firstClass; | |||
} | |||
public Industry getSecondIndustry() { | |||
return this.secondIndustry; | |||
public void setFirstClass(String firstClass) { | |||
this.firstClass = firstClass; | |||
} | |||
public void setSecondIndustry(Industry secondIndustry) { | |||
this.secondIndustry = secondIndustry; | |||
public String getSecondClass() { | |||
return this.secondClass; | |||
} | |||
public void setSecondClass(String secondClass) { | |||
this.secondClass = secondClass; | |||
} | |||
} | |||
@Override | |||
public String toString() { | |||
return ToStringBuilder.reflectionToString(this, ToStringStyle.MULTI_LINE_STYLE); | |||
} | |||
public static WxMpIndustry fromJson(String json) { | |||
return WxMpGsonBuilder.create().fromJson(json, WxMpIndustry.class); | |||
} | |||
public String toJson() { | |||
return WxMpGsonBuilder.create().toJson(this); | |||
} | |||
public Industry getPrimaryIndustry() { | |||
return this.primaryIndustry; | |||
} | |||
public void setPrimaryIndustry(Industry primaryIndustry) { | |||
this.primaryIndustry = primaryIndustry; | |||
} | |||
public Industry getSecondIndustry() { | |||
return this.secondIndustry; | |||
} | |||
public void setSecondIndustry(Industry secondIndustry) { | |||
this.secondIndustry = secondIndustry; | |||
} | |||
} |
@@ -1,19 +1,11 @@ | |||
package me.chanjar.weixin.mp.util.json; | |||
import java.lang.reflect.Type; | |||
import com.google.gson.JsonDeserializationContext; | |||
import com.google.gson.JsonDeserializer; | |||
import com.google.gson.JsonElement; | |||
import com.google.gson.JsonObject; | |||
import com.google.gson.JsonParseException; | |||
import com.google.gson.JsonSerializationContext; | |||
import com.google.gson.JsonSerializer; | |||
import com.google.gson.*; | |||
import me.chanjar.weixin.common.util.json.GsonHelper; | |||
import me.chanjar.weixin.mp.bean.Industry; | |||
import me.chanjar.weixin.mp.bean.WxMpIndustry; | |||
import java.lang.reflect.Type; | |||
/** | |||
* @author miller | |||
*/ | |||
@@ -42,8 +34,8 @@ public class WxMpIndustryGsonAdapter | |||
return wxMpIndustry; | |||
} | |||
private static Industry convertFromJson(JsonObject json) { | |||
Industry industry = new Industry(); | |||
private static WxMpIndustry.Industry convertFromJson(JsonObject json) { | |||
WxMpIndustry.Industry industry = new WxMpIndustry.Industry(); | |||
industry.setFirstClass(GsonHelper.getString(json, "first_class")); | |||
industry.setSecondClass(GsonHelper.getString(json, "second_class")); | |||
return industry; | |||
@@ -1,20 +1,12 @@ | |||
package me.chanjar.weixin.mp.api.impl; | |||
import java.text.SimpleDateFormat; | |||
import java.util.Date; | |||
import org.testng.Assert; | |||
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.WxMpTemplateData; | |||
import me.chanjar.weixin.mp.bean.WxMpTemplateMessage; | |||
import org.testng.Assert; | |||
import org.testng.annotations.Guice; | |||
import org.testng.annotations.Test; | |||
@Test | |||
@Guice(modules = ApiTestModule.class) | |||
@@ -88,20 +80,6 @@ public class WxMpServiceImplTest { | |||
Assert.fail("Not yet implemented"); | |||
} | |||
@Test(invocationCount = 100, threadPoolSize = 30) | |||
public void testTemplateSend() throws WxErrorException { | |||
SimpleDateFormat dateFormat = new SimpleDateFormat( | |||
"yyyy-MM-dd HH:mm:ss.SSS"); | |||
WxXmlMpInMemoryConfigStorage configStorage = (WxXmlMpInMemoryConfigStorage) this.wxService | |||
.getWxMpConfigStorage(); | |||
WxMpTemplateMessage templateMessage = WxMpTemplateMessage.builder() | |||
.toUser(configStorage.getOpenid()) | |||
.templateId(configStorage.getTemplateId()).build(); | |||
templateMessage.addWxMpTemplateData( | |||
new WxMpTemplateData("first", dateFormat.format(new Date()))); | |||
this.wxService.templateSend(templateMessage); | |||
} | |||
@Test | |||
public void testSetIndustry() { | |||
Assert.fail("Not yet implemented"); | |||
@@ -0,0 +1,59 @@ | |||
package me.chanjar.weixin.mp.api.impl; | |||
import com.google.inject.Inject; | |||
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.WxMpIndustry; | |||
import me.chanjar.weixin.mp.bean.WxMpTemplateData; | |||
import me.chanjar.weixin.mp.bean.WxMpTemplateMessage; | |||
import org.testng.Assert; | |||
import org.testng.annotations.Guice; | |||
import org.testng.annotations.Test; | |||
import java.text.SimpleDateFormat; | |||
import java.util.Date; | |||
/** | |||
* <pre> | |||
* Created by Binary Wang on 2016-10-14. | |||
* @author <a href="https://github.com/binarywang">binarywang(Binary Wang)</a> | |||
* </pre> | |||
*/ | |||
@Guice(modules = ApiTestModule.class) | |||
public class WxMpTemplateMsgServiceImplTest { | |||
@Inject | |||
protected WxMpServiceImpl wxService; | |||
@Test(invocationCount = 10, threadPoolSize = 10) | |||
public void testSendTemplateMsg() throws WxErrorException { | |||
SimpleDateFormat dateFormat = new SimpleDateFormat( | |||
"yyyy-MM-dd HH:mm:ss.SSS"); | |||
WxXmlMpInMemoryConfigStorage configStorage = (WxXmlMpInMemoryConfigStorage) this.wxService | |||
.getWxMpConfigStorage(); | |||
WxMpTemplateMessage templateMessage = WxMpTemplateMessage.builder() | |||
.toUser(configStorage.getOpenid()) | |||
.templateId(configStorage.getTemplateId()).build(); | |||
templateMessage.addWxMpTemplateData( | |||
new WxMpTemplateData("first", dateFormat.format(new Date()))); | |||
String msgId = this.wxService.getTemplateMsgService().sendTemplateMsg(templateMessage); | |||
Assert.assertNotNull(msgId); | |||
System.out.println(msgId); | |||
} | |||
@Test | |||
public void testGetIndustry() throws Exception { | |||
final WxMpIndustry industry = this.wxService.getTemplateMsgService().getIndustry(); | |||
Assert.assertNotNull(industry); | |||
System.out.println(industry); | |||
} | |||
@Test | |||
public void testSetIndustry() throws Exception { | |||
WxMpIndustry industry = new WxMpIndustry(new WxMpIndustry.Industry("1"), | |||
new WxMpIndustry.Industry("04")); | |||
boolean result = this.wxService.getTemplateMsgService().setIndustry(industry); | |||
Assert.assertTrue(result); | |||
} | |||
} |