@@ -19,7 +19,7 @@ weixin-java-tools | |||||
<dependency> | <dependency> | ||||
<groupId>me.chanjar</groupId> | <groupId>me.chanjar</groupId> | ||||
<artifactId>weixin-java-mp</artifactId> | <artifactId>weixin-java-mp</artifactId> | ||||
<version>1.0.5</version> | |||||
<version>1.0.6</version> | |||||
</dependency> | </dependency> | ||||
``` | ``` | ||||
@@ -29,7 +29,7 @@ weixin-java-tools | |||||
<dependency> | <dependency> | ||||
<groupId>me.chanjar</groupId> | <groupId>me.chanjar</groupId> | ||||
<artifactId>weixin-java-cp</artifactId> | <artifactId>weixin-java-cp</artifactId> | ||||
<version>1.0.5</version> | |||||
<version>1.0.6</version> | |||||
</dependency> | </dependency> | ||||
``` | ``` | ||||
@@ -5,7 +5,7 @@ | |||||
<modelVersion>4.0.0</modelVersion> | <modelVersion>4.0.0</modelVersion> | ||||
<groupId>me.chanjar</groupId> | <groupId>me.chanjar</groupId> | ||||
<artifactId>weixin-java-parent</artifactId> | <artifactId>weixin-java-parent</artifactId> | ||||
<version>1.0.5</version> | |||||
<version>1.0.6</version> | |||||
<packaging>pom</packaging> | <packaging>pom</packaging> | ||||
<name>WeiXin Java Tools - Parent</name> | <name>WeiXin Java Tools - Parent</name> | ||||
<description>微信公众号、企业号上级POM</description> | <description>微信公众号、企业号上级POM</description> | ||||
@@ -6,7 +6,7 @@ | |||||
<parent> | <parent> | ||||
<groupId>me.chanjar</groupId> | <groupId>me.chanjar</groupId> | ||||
<artifactId>weixin-java-parent</artifactId> | <artifactId>weixin-java-parent</artifactId> | ||||
<version>1.0.5</version> | |||||
<version>1.0.6</version> | |||||
</parent> | </parent> | ||||
<artifactId>weixin-java-common</artifactId> | <artifactId>weixin-java-common</artifactId> | ||||
@@ -6,7 +6,7 @@ | |||||
<parent> | <parent> | ||||
<groupId>me.chanjar</groupId> | <groupId>me.chanjar</groupId> | ||||
<artifactId>weixin-java-parent</artifactId> | <artifactId>weixin-java-parent</artifactId> | ||||
<version>1.0.5</version> | |||||
<version>1.0.6</version> | |||||
</parent> | </parent> | ||||
<artifactId>weixin-java-cp</artifactId> | <artifactId>weixin-java-cp</artifactId> | ||||
@@ -77,6 +77,9 @@ public class WxCpMessageRouter { | |||||
for (final Rule rule : rules) { | for (final Rule rule : rules) { | ||||
if (rule.test(wxMessage)) { | if (rule.test(wxMessage)) { | ||||
matchRules.add(rule); | matchRules.add(rule); | ||||
if(!rule.reEnter) { | |||||
break; | |||||
} | |||||
} | } | ||||
} | } | ||||
@@ -84,28 +87,17 @@ public class WxCpMessageRouter { | |||||
return null; | return null; | ||||
} | } | ||||
if (matchRules.get(0).async) { | |||||
// 只要第一个是异步的,那就异步执行 | |||||
// 在另一个线程里执行 | |||||
executorService.submit(new Runnable() { | |||||
public void run() { | |||||
for (final Rule rule : matchRules) { | |||||
rule.service(wxMessage); | |||||
if (!rule.reEnter) { | |||||
break; | |||||
} | |||||
} | |||||
} | |||||
}); | |||||
return null; | |||||
} | |||||
WxCpXmlOutMessage res = null; | WxCpXmlOutMessage res = null; | ||||
for (final Rule rule : matchRules) { | for (final Rule rule : matchRules) { | ||||
// 返回最后一个匹配规则的结果 | |||||
res = rule.service(wxMessage); | |||||
if (!rule.reEnter) { | |||||
break; | |||||
// 返回最后一个非异步的rule的执行结果 | |||||
if(rule.async) { | |||||
executorService.submit(new Runnable() { | |||||
public void run() { | |||||
rule.service(wxMessage); | |||||
} | |||||
}); | |||||
} else { | |||||
res = rule.service(wxMessage); | |||||
} | } | ||||
} | } | ||||
return res; | return res; | ||||
@@ -335,7 +335,7 @@ public class WxCpServiceImpl implements WxCpService { | |||||
String url = "https://qyapi.weixin.qq.com/cgi-bin/user/getuserinfo?"; | String url = "https://qyapi.weixin.qq.com/cgi-bin/user/getuserinfo?"; | ||||
url += "access_token=" + wxCpConfigStorage.getAccessToken(); | url += "access_token=" + wxCpConfigStorage.getAccessToken(); | ||||
url += "&code=" + code; | url += "&code=" + code; | ||||
url += "agendid=" + wxCpConfigStorage.getAgentId(); | |||||
url += "&agendid=" + wxCpConfigStorage.getAgentId(); | |||||
try { | try { | ||||
RequestExecutor<String, String> executor = new SimpleGetRequestExecutor(); | RequestExecutor<String, String> executor = new SimpleGetRequestExecutor(); | ||||
@@ -6,7 +6,7 @@ | |||||
<parent> | <parent> | ||||
<groupId>me.chanjar</groupId> | <groupId>me.chanjar</groupId> | ||||
<artifactId>weixin-java-parent</artifactId> | <artifactId>weixin-java-parent</artifactId> | ||||
<version>1.0.5</version> | |||||
<version>1.0.6</version> | |||||
</parent> | </parent> | ||||
<artifactId>weixin-java-mp</artifactId> | <artifactId>weixin-java-mp</artifactId> | ||||
<name>WeiXin Java Tools - MP</name> | <name>WeiXin Java Tools - MP</name> | ||||
@@ -77,6 +77,9 @@ public class WxMpMessageRouter { | |||||
for (final Rule rule : rules) { | for (final Rule rule : rules) { | ||||
if (rule.test(wxMessage)) { | if (rule.test(wxMessage)) { | ||||
matchRules.add(rule); | matchRules.add(rule); | ||||
if(!rule.reEnter) { | |||||
break; | |||||
} | |||||
} | } | ||||
} | } | ||||
@@ -84,28 +87,17 @@ public class WxMpMessageRouter { | |||||
return null; | return null; | ||||
} | } | ||||
if (matchRules.get(0).async) { | |||||
// 只要第一个是异步的,那就异步执行 | |||||
// 在另一个线程里执行 | |||||
executorService.execute(new Runnable() { | |||||
public void run() { | |||||
for (final Rule rule : matchRules) { | |||||
rule.service(wxMessage); | |||||
if (!rule.reEnter) { | |||||
break; | |||||
} | |||||
} | |||||
} | |||||
}); | |||||
return null; | |||||
} | |||||
WxMpXmlOutMessage res = null; | WxMpXmlOutMessage res = null; | ||||
for (final Rule rule : matchRules) { | for (final Rule rule : matchRules) { | ||||
// 返回最后一个匹配规则的结果 | |||||
res = rule.service(wxMessage); | |||||
if (!rule.reEnter) { | |||||
break; | |||||
// 返回最后一个非异步的rule的执行结果 | |||||
if(rule.async) { | |||||
executorService.submit(new Runnable() { | |||||
public void run() { | |||||
rule.service(wxMessage); | |||||
} | |||||
}); | |||||
} else { | |||||
res = rule.service(wxMessage); | |||||
} | } | ||||
} | } | ||||
return res; | return res; | ||||
@@ -315,8 +315,9 @@ public interface WxMpService { | |||||
* </pre> | * </pre> | ||||
* @param templateMessage | * @param templateMessage | ||||
* @throws WxErrorException | * @throws WxErrorException | ||||
* @return msgid | |||||
*/ | */ | ||||
public void templateSend(WxMpTemplateMessage templateMessage) throws WxErrorException; | |||||
public String templateSend(WxMpTemplateMessage templateMessage) throws WxErrorException; | |||||
/** | /** | ||||
* <pre> | * <pre> | ||||
@@ -286,9 +286,11 @@ public class WxMpServiceImpl implements WxMpService { | |||||
return tmpJsonElement.getAsJsonObject().get("short_url").getAsString(); | return tmpJsonElement.getAsJsonObject().get("short_url").getAsString(); | ||||
} | } | ||||
public void templateSend(WxMpTemplateMessage templateMessage) throws WxErrorException { | |||||
public String templateSend(WxMpTemplateMessage templateMessage) throws WxErrorException { | |||||
String url = "https://api.weixin.qq.com/cgi-bin/message/template/send"; | String url = "https://api.weixin.qq.com/cgi-bin/message/template/send"; | ||||
execute(new SimplePostRequestExecutor(), url, templateMessage.toJson()); | |||||
String responseContent = execute(new SimplePostRequestExecutor(), url, templateMessage.toJson()); | |||||
JsonElement tmpJsonElement = Streams.parse(new JsonReader(new StringReader(responseContent))); | |||||
return tmpJsonElement.getAsJsonObject().get("msgid").getAsString(); | |||||
} | } | ||||
public WxMpSemanticQueryResult semanticQuery(WxMpSemanticQuery semanticQuery) throws WxErrorException { | public WxMpSemanticQueryResult semanticQuery(WxMpSemanticQuery semanticQuery) throws WxErrorException { | ||||
@@ -9,7 +9,7 @@ import me.chanjar.weixin.mp.util.json.WxMpGsonBuilder; | |||||
*/ | */ | ||||
public class WxMpMassGroupMessage { | public class WxMpMassGroupMessage { | ||||
private long groupId; | |||||
private Long groupId; | |||||
private String msgtype; | private String msgtype; | ||||
private String content; | private String content; | ||||
private String mediaId; | private String mediaId; | ||||
@@ -58,11 +58,15 @@ public class WxMpMassGroupMessage { | |||||
return WxMpGsonBuilder.INSTANCE.create().toJson(this); | return WxMpGsonBuilder.INSTANCE.create().toJson(this); | ||||
} | } | ||||
public long getGroupId() { | |||||
public Long getGroupId() { | |||||
return groupId; | return groupId; | ||||
} | } | ||||
public void setGroupId(long groupId) { | |||||
/** | |||||
* 如果不设置则就意味着发给所有用户 | |||||
* @param groupId | |||||
*/ | |||||
public void setGroupId(Long groupId) { | |||||
this.groupId = groupId; | this.groupId = groupId; | ||||
} | } | ||||
@@ -381,6 +381,8 @@ public class WxMpXmlMessage { | |||||
public static WxMpXmlMessage fromXml(String xml) { | public static WxMpXmlMessage fromXml(String xml) { | ||||
try { | try { | ||||
// 操蛋的微信,模板消息推送成功的消息是MsgID,其他消息推送过来是MsgId | |||||
xml = xml.replaceAll("<MsgID>", "<MsgId>").replaceAll("</MsgID>", "</MsgId>"); | |||||
return XmlTransformer.fromXml(WxMpXmlMessage.class, xml); | return XmlTransformer.fromXml(WxMpXmlMessage.class, xml); | ||||
} catch (JAXBException e) { | } catch (JAXBException e) { | ||||
throw new RuntimeException(e); | throw new RuntimeException(e); | ||||
@@ -389,8 +391,8 @@ public class WxMpXmlMessage { | |||||
public static WxMpXmlMessage fromXml(InputStream is) { | public static WxMpXmlMessage fromXml(InputStream is) { | ||||
try { | try { | ||||
return XmlTransformer.fromXml(WxMpXmlMessage.class, is); | |||||
} catch (JAXBException e) { | |||||
return fromXml(IOUtils.toString(is, "UTF-8")); | |||||
} catch (IOException e) { | |||||
throw new RuntimeException(e); | throw new RuntimeException(e); | ||||
} | } | ||||
} | } | ||||
@@ -14,7 +14,7 @@ public class WxMpGsonBuilder { | |||||
INSTANCE.disableHtmlEscaping(); | INSTANCE.disableHtmlEscaping(); | ||||
INSTANCE.registerTypeAdapter(WxMpCustomMessage.class, new WxMpCustomMessageGsonAdapter()); | INSTANCE.registerTypeAdapter(WxMpCustomMessage.class, new WxMpCustomMessageGsonAdapter()); | ||||
INSTANCE.registerTypeAdapter(WxMpMassNews.class, new WxMpMassNewsGsonAdapter()); | INSTANCE.registerTypeAdapter(WxMpMassNews.class, new WxMpMassNewsGsonAdapter()); | ||||
INSTANCE.registerTypeAdapter(WxMpMassGroupMessage.class, new WxMpMassMessageGsonAdapter()); | |||||
INSTANCE.registerTypeAdapter(WxMpMassGroupMessage.class, new WxMpMassGroupMessageGsonAdapter()); | |||||
INSTANCE.registerTypeAdapter(WxMpMassOpenIdsMessage.class, new WxMpMassOpenIdsMessageGsonAdapter()); | INSTANCE.registerTypeAdapter(WxMpMassOpenIdsMessage.class, new WxMpMassOpenIdsMessageGsonAdapter()); | ||||
INSTANCE.registerTypeAdapter(WxMpGroup.class, new WxMpGroupGsonAdapter()); | INSTANCE.registerTypeAdapter(WxMpGroup.class, new WxMpGroupGsonAdapter()); | ||||
INSTANCE.registerTypeAdapter(WxMpUser.class, new WxUserGsonAdapter()); | INSTANCE.registerTypeAdapter(WxMpUser.class, new WxUserGsonAdapter()); | ||||
@@ -22,13 +22,18 @@ import java.lang.reflect.Type; | |||||
* @author qianjia | * @author qianjia | ||||
* | * | ||||
*/ | */ | ||||
public class WxMpMassMessageGsonAdapter implements JsonSerializer<WxMpMassGroupMessage> { | |||||
public class WxMpMassGroupMessageGsonAdapter implements JsonSerializer<WxMpMassGroupMessage> { | |||||
public JsonElement serialize(WxMpMassGroupMessage message, Type typeOfSrc, JsonSerializationContext context) { | public JsonElement serialize(WxMpMassGroupMessage message, Type typeOfSrc, JsonSerializationContext context) { | ||||
JsonObject messageJson = new JsonObject(); | JsonObject messageJson = new JsonObject(); | ||||
JsonObject filter = new JsonObject(); | JsonObject filter = new JsonObject(); | ||||
filter.addProperty("group_id", message.getGroupId()); | |||||
if(null == message.getGroupId()) { | |||||
filter.addProperty("is_to_all", true); | |||||
} else { | |||||
filter.addProperty("is_to_all", false); | |||||
filter.addProperty("group_id", message.getGroupId()); | |||||
} | |||||
messageJson.add("filter", filter); | messageJson.add("filter", filter); | ||||
if (WxConsts.MASS_MSG_NEWS.equals(message.getMsgtype())) { | if (WxConsts.MASS_MSG_NEWS.equals(message.getMsgtype())) { |
@@ -87,5 +87,86 @@ public class WxMpXmlMessageTest { | |||||
Assert.assertEquals(wxMessage.getSendLocationInfo().getLabel(), " 广州市海珠区客村艺苑路 106号"); | Assert.assertEquals(wxMessage.getSendLocationInfo().getLabel(), " 广州市海珠区客村艺苑路 106号"); | ||||
Assert.assertEquals(wxMessage.getSendLocationInfo().getPoiname(), "wo de poi"); | Assert.assertEquals(wxMessage.getSendLocationInfo().getPoiname(), "wo de poi"); | ||||
} | } | ||||
public void testFromXml2() { | |||||
String xml = "<xml>" | |||||
+ "<ToUserName><![CDATA[toUser]]></ToUserName>" | |||||
+ "<FromUserName><![CDATA[fromUser]]></FromUserName> " | |||||
+ "<CreateTime>1348831860</CreateTime>" | |||||
+ "<MsgType><![CDATA[text]]></MsgType>" | |||||
+ "<Content><![CDATA[this is a test]]></Content>" | |||||
+ "<MsgID>1234567890123456</MsgID>" | |||||
+ "<PicUrl><![CDATA[this is a url]]></PicUrl>" | |||||
+ "<MediaId><![CDATA[media_id]]></MediaId>" | |||||
+ "<Format><![CDATA[Format]]></Format>" | |||||
+ "<ThumbMediaId><![CDATA[thumb_media_id]]></ThumbMediaId>" | |||||
+ "<Location_X>23.134521</Location_X>" | |||||
+ "<Location_Y>113.358803</Location_Y>" | |||||
+ "<Scale>20</Scale>" | |||||
+ "<Label><![CDATA[位置信息]]></Label>" | |||||
+ "<Description><![CDATA[公众平台官网链接]]></Description>" | |||||
+ "<Url><![CDATA[url]]></Url>" | |||||
+ "<Title><![CDATA[公众平台官网链接]]></Title>" | |||||
+ "<Event><![CDATA[subscribe]]></Event>" | |||||
+ "<EventKey><![CDATA[qrscene_123123]]></EventKey>" | |||||
+ "<Ticket><![CDATA[TICKET]]></Ticket>" | |||||
+ "<Latitude>23.137466</Latitude>" | |||||
+ "<Longitude>113.352425</Longitude>" | |||||
+ "<Precision>119.385040</Precision>" | |||||
+ "<ScanCodeInfo>" | |||||
+ " <ScanType><![CDATA[qrcode]]></ScanType>" | |||||
+ " <ScanResult><![CDATA[1]]></ScanResult>" | |||||
+ "</ScanCodeInfo>" | |||||
+ "<SendPicsInfo>" | |||||
+ " <Count>1</Count>\n" | |||||
+ " <PicList>" | |||||
+ " <item>" | |||||
+ " <PicMd5Sum><![CDATA[1b5f7c23b5bf75682a53e7b6d163e185]]></PicMd5Sum>" | |||||
+ " </item>" | |||||
+ " </PicList>" | |||||
+ "</SendPicsInfo>" | |||||
+ "<SendLocationInfo>" | |||||
+ " <Location_X><![CDATA[23]]></Location_X>\n" | |||||
+ " <Location_Y><![CDATA[113]]></Location_Y>\n" | |||||
+ " <Scale><![CDATA[15]]></Scale>\n" | |||||
+ " <Label><![CDATA[ 广州市海珠区客村艺苑路 106号]]></Label>\n" | |||||
+ " <Poiname><![CDATA[wo de poi]]></Poiname>\n" | |||||
+ "</SendLocationInfo>" | |||||
+ "</xml>"; | |||||
WxMpXmlMessage wxMessage = WxMpXmlMessage.fromXml(xml); | |||||
Assert.assertEquals(wxMessage.getToUserName(), "toUser"); | |||||
Assert.assertEquals(wxMessage.getFromUserName(), "fromUser"); | |||||
Assert.assertEquals(wxMessage.getCreateTime(), new Long(1348831860l)); | |||||
Assert.assertEquals(wxMessage.getMsgType(), WxConsts.XML_MSG_TEXT); | |||||
Assert.assertEquals(wxMessage.getContent(), "this is a test"); | |||||
Assert.assertEquals(wxMessage.getMsgId(), new Long(1234567890123456l)); | |||||
Assert.assertEquals(wxMessage.getPicUrl(), "this is a url"); | |||||
Assert.assertEquals(wxMessage.getMediaId(), "media_id"); | |||||
Assert.assertEquals(wxMessage.getFormat(), "Format"); | |||||
Assert.assertEquals(wxMessage.getThumbMediaId(), "thumb_media_id"); | |||||
Assert.assertEquals(wxMessage.getLocationX(), new Double(23.134521d)); | |||||
Assert.assertEquals(wxMessage.getLocationY(), new Double(113.358803d)); | |||||
Assert.assertEquals(wxMessage.getScale(), new Double(20)); | |||||
Assert.assertEquals(wxMessage.getLabel(), "位置信息"); | |||||
Assert.assertEquals(wxMessage.getDescription(), "公众平台官网链接"); | |||||
Assert.assertEquals(wxMessage.getUrl(), "url"); | |||||
Assert.assertEquals(wxMessage.getTitle(), "公众平台官网链接"); | |||||
Assert.assertEquals(wxMessage.getEvent(), "subscribe"); | |||||
Assert.assertEquals(wxMessage.getEventKey(), "qrscene_123123"); | |||||
Assert.assertEquals(wxMessage.getTicket(), "TICKET"); | |||||
Assert.assertEquals(wxMessage.getLatitude(), new Double(23.137466)); | |||||
Assert.assertEquals(wxMessage.getLongitude(), new Double(113.352425)); | |||||
Assert.assertEquals(wxMessage.getPrecision(), new Double(119.385040)); | |||||
Assert.assertEquals(wxMessage.getScanCodeInfo().getScanType(), "qrcode"); | |||||
Assert.assertEquals(wxMessage.getScanCodeInfo().getScanResult(), "1"); | |||||
Assert.assertEquals(wxMessage.getSendPicsInfo().getCount(), new Long(1l)); | |||||
Assert.assertEquals(wxMessage.getSendPicsInfo().getPicList().get(0).getPicMd5Sum(), "1b5f7c23b5bf75682a53e7b6d163e185"); | |||||
Assert.assertEquals(wxMessage.getSendLocationInfo().getLocationX(), "23"); | |||||
Assert.assertEquals(wxMessage.getSendLocationInfo().getLocationY(), "113"); | |||||
Assert.assertEquals(wxMessage.getSendLocationInfo().getScale(), "15"); | |||||
Assert.assertEquals(wxMessage.getSendLocationInfo().getLabel(), " 广州市海珠区客村艺苑路 106号"); | |||||
Assert.assertEquals(wxMessage.getSendLocationInfo().getPoiname(), "wo de poi"); | |||||
} | |||||
} | } |
@@ -30,7 +30,7 @@ public class WxMpDemoServer { | |||||
ServletHandler servletHandler = new ServletHandler(); | ServletHandler servletHandler = new ServletHandler(); | ||||
server.setHandler(servletHandler); | server.setHandler(servletHandler); | ||||
ServletHolder endpointServletHolder = new ServletHolder(new WxMpEndpointServlt(wxMpConfigStorage, wxMpService, wxMpMessageRouter)); | |||||
ServletHolder endpointServletHolder = new ServletHolder(new WxMpEndpointServlet(wxMpConfigStorage, wxMpService, wxMpMessageRouter)); | |||||
servletHandler.addServletWithMapping(endpointServletHolder, "/*"); | servletHandler.addServletWithMapping(endpointServletHolder, "/*"); | ||||
ServletHolder oauthServletHolder = new ServletHolder(new WxMpOAuth2Servlet(wxMpService)); | ServletHolder oauthServletHolder = new ServletHolder(new WxMpOAuth2Servlet(wxMpService)); | ||||
@@ -22,13 +22,13 @@ import java.util.Map; | |||||
/** | /** | ||||
* @author Daniel Qian | * @author Daniel Qian | ||||
*/ | */ | ||||
public class WxMpEndpointServlt extends HttpServlet { | |||||
public class WxMpEndpointServlet extends HttpServlet { | |||||
protected WxMpConfigStorage wxMpConfigStorage; | protected WxMpConfigStorage wxMpConfigStorage; | ||||
protected WxMpService wxMpService; | protected WxMpService wxMpService; | ||||
protected WxMpMessageRouter wxMpMessageRouter; | protected WxMpMessageRouter wxMpMessageRouter; | ||||
public WxMpEndpointServlt(WxMpConfigStorage wxMpConfigStorage, WxMpService wxMpService, | |||||
public WxMpEndpointServlet(WxMpConfigStorage wxMpConfigStorage, WxMpService wxMpService, | |||||
WxMpMessageRouter wxMpMessageRouter) { | WxMpMessageRouter wxMpMessageRouter) { | ||||
this.wxMpConfigStorage = wxMpConfigStorage; | this.wxMpConfigStorage = wxMpConfigStorage; | ||||
this.wxMpService = wxMpService; | this.wxMpService = wxMpService; |