| @@ -0,0 +1,26 @@ | |||||
| package chanjarster.weixin.api; | |||||
| import chanjarster.weixin.bean.WxAccessToken; | |||||
| /** | |||||
| * 微信配置的工具类 | |||||
| * @author chanjarster | |||||
| * | |||||
| */ | |||||
| public interface WxConfigProvider { | |||||
| public void updateAccessToken(WxAccessToken accessToken); | |||||
| public void updateAccessToken(String accessToken, int expiresIn); | |||||
| public String getAccessToken(); | |||||
| public String getAppId(); | |||||
| public String getSecret(); | |||||
| public String getToken(); | |||||
| public int getExpiresIn(); | |||||
| } | |||||
| @@ -1,6 +1,6 @@ | |||||
| package chanjarster.weixin.service; | |||||
| package chanjarster.weixin.api; | |||||
| public class WxMsgType { | |||||
| public class WxConsts { | |||||
| public static final String TEXT = "text"; | public static final String TEXT = "text"; | ||||
| public static final String IMAGE = "image"; | public static final String IMAGE = "image"; | ||||
| @@ -0,0 +1,47 @@ | |||||
| package chanjarster.weixin.api; | |||||
| import chanjarster.weixin.bean.WxAccessToken; | |||||
| /** | |||||
| * 基于内存的微信配置provider | |||||
| * @author chanjarster | |||||
| * | |||||
| */ | |||||
| public class WxMemoryConfigProvider implements WxConfigProvider { | |||||
| protected String appId; | |||||
| protected String secret; | |||||
| protected String token; | |||||
| protected String accessToken; | |||||
| protected int expiresIn; | |||||
| public void updateAccessToken(WxAccessToken accessToken) { | |||||
| updateAccessToken(accessToken.getAccess_token(), accessToken.getExpires_in()); | |||||
| } | |||||
| public void updateAccessToken(String accessToken, int expiresIn) { | |||||
| this.accessToken = accessToken; | |||||
| this.expiresIn = expiresIn; | |||||
| } | |||||
| public String getAccessToken() { | |||||
| return this.accessToken; | |||||
| } | |||||
| public String getAppId() { | |||||
| return this.appId; | |||||
| } | |||||
| public String getSecret() { | |||||
| return this.secret; | |||||
| } | |||||
| public String getToken() { | |||||
| return this.token; | |||||
| } | |||||
| public int getExpiresIn() { | |||||
| return this.expiresIn; | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,16 @@ | |||||
| package chanjarster.weixin.api; | |||||
| import java.util.Map; | |||||
| import chanjarster.weixin.bean.WxXmlMessage; | |||||
| /** | |||||
| * 处理微信推送消息的处理器 | |||||
| * @author chanjarster | |||||
| * | |||||
| */ | |||||
| public interface WxMessageHandler { | |||||
| public void handle(WxXmlMessage wxMessage, Map<String, Object> context); | |||||
| } | |||||
| @@ -1,8 +1,8 @@ | |||||
| package chanjarster.weixin.service; | |||||
| package chanjarster.weixin.api; | |||||
| import java.util.Map; | import java.util.Map; | ||||
| import chanjarster.weixin.out.WxUserMessage; | |||||
| import chanjarster.weixin.bean.WxXmlMessage; | |||||
| /** | /** | ||||
| @@ -17,6 +17,6 @@ public interface WxMessageInterceptor { | |||||
| * @param wxMessage | * @param wxMessage | ||||
| * @return true代表OK,false代表不OK | * @return true代表OK,false代表不OK | ||||
| */ | */ | ||||
| public boolean intercept(WxUserMessage wxMessage, Map<String, Object> context); | |||||
| public boolean intercept(WxXmlMessage wxMessage, Map<String, Object> context); | |||||
| } | } | ||||
| @@ -1,11 +1,11 @@ | |||||
| package chanjarster.weixin.service; | |||||
| package chanjarster.weixin.api; | |||||
| import java.util.ArrayList; | import java.util.ArrayList; | ||||
| import java.util.HashMap; | import java.util.HashMap; | ||||
| import java.util.List; | import java.util.List; | ||||
| import java.util.Map; | import java.util.Map; | ||||
| import chanjarster.weixin.out.WxUserMessage; | |||||
| import chanjarster.weixin.bean.WxXmlMessage; | |||||
| /** | /** | ||||
| * 微信消息路由器,通过代码化的配置,把来自微信的消息交给某个的handler处理 | * 微信消息路由器,通过代码化的配置,把来自微信的消息交给某个的handler处理 | ||||
| @@ -28,7 +28,7 @@ public class WxMessageRouter { | |||||
| * 处理微信消息 | * 处理微信消息 | ||||
| * @param wxMessage | * @param wxMessage | ||||
| */ | */ | ||||
| public void route(WxUserMessage wxMessage) { | |||||
| public void route(WxXmlMessage wxMessage) { | |||||
| for (Rule rule : rules) { | for (Rule rule : rules) { | ||||
| boolean doNext = rule.service(wxMessage); | boolean doNext = rule.service(wxMessage); | ||||
| if (!doNext) { | if (!doNext) { | ||||
| @@ -148,7 +148,7 @@ public class WxMessageRouter { | |||||
| return this.routerBuilder; | return this.routerBuilder; | ||||
| } | } | ||||
| protected boolean test(WxUserMessage wxMessage) { | |||||
| protected boolean test(WxXmlMessage wxMessage) { | |||||
| return | return | ||||
| (this.msgType == null || this.msgType.equals(wxMessage.getMsgType())) | (this.msgType == null || this.msgType.equals(wxMessage.getMsgType())) | ||||
| && | && | ||||
| @@ -165,7 +165,7 @@ public class WxMessageRouter { | |||||
| * @param wxMessage | * @param wxMessage | ||||
| * @return true 代表继续执行别的router,false 代表停止执行别的router | * @return true 代表继续执行别的router,false 代表停止执行别的router | ||||
| */ | */ | ||||
| protected boolean service(WxUserMessage wxMessage) { | |||||
| protected boolean service(WxXmlMessage wxMessage) { | |||||
| // 如果不匹配本规则,那么接着执行后面的Rule | // 如果不匹配本规则,那么接着执行后面的Rule | ||||
| if (!test(wxMessage)) { | if (!test(wxMessage)) { | ||||
| return true; | return true; | ||||
| @@ -0,0 +1,54 @@ | |||||
| package chanjarster.weixin.api; | |||||
| import chanjarster.weixin.bean.WxCustomMessage; | |||||
| import chanjarster.weixin.bean.WxMenu; | |||||
| import chanjarster.weixin.exception.WxErrorException; | |||||
| /** | |||||
| * 微信API的Service | |||||
| */ | |||||
| public interface WxService { | |||||
| /** | |||||
| * 刷新access_token,这个方法是线程安全的 | |||||
| * 且在高并发情况下只会刷新一次,而不是刷新多次 | |||||
| * 在非必要情况下不要主动调用此方法 | |||||
| * 本service的所有方法都会在access_token过期的情况下调用此方法 | |||||
| * | |||||
| * 详情请见: http://mp.weixin.qq.com/wiki/index.php?title=获取access_token | |||||
| * @throws WxErrorException | |||||
| */ | |||||
| public void refreshAccessToken() throws WxErrorException; | |||||
| /** | |||||
| * 发送客服消息 | |||||
| * @param message | |||||
| * @return | |||||
| * @throws WxErrorException | |||||
| */ | |||||
| public String sendCustomMessage(WxCustomMessage message) throws WxErrorException; | |||||
| /** | |||||
| * 创建菜单 | |||||
| * @param menu | |||||
| * @return | |||||
| * @throws WxErrorException | |||||
| */ | |||||
| public String createMenu(WxMenu menu) throws WxErrorException; | |||||
| /** | |||||
| * 删除菜单 | |||||
| * @return | |||||
| * @throws WxErrorException | |||||
| */ | |||||
| public String deleteMenu() throws WxErrorException; | |||||
| /** | |||||
| * 获得菜单 | |||||
| * @return | |||||
| * @throws WxErrorException | |||||
| */ | |||||
| public WxMenu getMenu() throws WxErrorException; | |||||
| public void setWxConfigProvider(WxConfigProvider wxConfigProvider); | |||||
| } | |||||
| @@ -1,4 +1,4 @@ | |||||
| package chanjarster.weixin.service; | |||||
| package chanjarster.weixin.api; | |||||
| import java.io.IOException; | import java.io.IOException; | ||||
| import java.nio.charset.Charset; | import java.nio.charset.Charset; | ||||
| @@ -14,11 +14,11 @@ import org.apache.http.impl.client.BasicResponseHandler; | |||||
| import org.apache.http.impl.client.CloseableHttpClient; | import org.apache.http.impl.client.CloseableHttpClient; | ||||
| import org.apache.http.impl.client.HttpClients; | import org.apache.http.impl.client.HttpClients; | ||||
| import chanjarster.weixin.bean.WxAccessToken; | |||||
| import chanjarster.weixin.bean.WxCustomMessage; | |||||
| import chanjarster.weixin.bean.WxError; | |||||
| import chanjarster.weixin.bean.WxMenu; | |||||
| import chanjarster.weixin.exception.WxErrorException; | import chanjarster.weixin.exception.WxErrorException; | ||||
| import chanjarster.weixin.in.WxAccessToken; | |||||
| import chanjarster.weixin.in.WxError; | |||||
| import chanjarster.weixin.out.WxCustomMessage; | |||||
| import chanjarster.weixin.out.WxMenu; | |||||
| public class WxServiceImpl implements WxService { | public class WxServiceImpl implements WxService { | ||||
| @@ -35,12 +35,6 @@ public class WxServiceImpl implements WxService { | |||||
| protected WxConfigProvider wxConfigProvider; | protected WxConfigProvider wxConfigProvider; | ||||
| /** | |||||
| * 获得access_token | |||||
| * 详情请见: http://mp.weixin.qq.com/wiki/index.php?title=获取access_token | |||||
| * @return | |||||
| * @throws WxErrorException | |||||
| */ | |||||
| public void refreshAccessToken() throws WxErrorException { | public void refreshAccessToken() throws WxErrorException { | ||||
| if (!GLOBAL_ACCESS_TOKEN_REFRESH_FLAG.getAndSet(true)) { | if (!GLOBAL_ACCESS_TOKEN_REFRESH_FLAG.getAndSet(true)) { | ||||
| try { | try { | ||||
| @@ -1,4 +1,4 @@ | |||||
| package chanjarster.weixin.in; | |||||
| package chanjarster.weixin.bean; | |||||
| import chanjarster.weixin.util.WxGsonBuilder; | import chanjarster.weixin.util.WxGsonBuilder; | ||||
| @@ -1,4 +1,4 @@ | |||||
| package chanjarster.weixin.out; | |||||
| package chanjarster.weixin.bean; | |||||
| import java.util.ArrayList; | import java.util.ArrayList; | ||||
| import java.util.List; | import java.util.List; | ||||
| @@ -6,7 +6,7 @@ import java.util.List; | |||||
| import chanjarster.weixin.util.WxGsonBuilder; | import chanjarster.weixin.util.WxGsonBuilder; | ||||
| /** | /** | ||||
| * 回复给用户的客服消息 | |||||
| * 客服消息 | |||||
| * @author chanjarster | * @author chanjarster | ||||
| * | * | ||||
| */ | */ | ||||
| @@ -1,4 +1,4 @@ | |||||
| package chanjarster.weixin.in; | |||||
| package chanjarster.weixin.bean; | |||||
| import chanjarster.weixin.util.WxGsonBuilder; | import chanjarster.weixin.util.WxGsonBuilder; | ||||
| @@ -1,8 +1,12 @@ | |||||
| package chanjarster.weixin.out; | |||||
| package chanjarster.weixin.bean; | |||||
| import java.io.InputStream; | |||||
| import java.io.InputStreamReader; | |||||
| import java.util.ArrayList; | import java.util.ArrayList; | ||||
| import java.util.List; | import java.util.List; | ||||
| import chanjarster.weixin.util.WxGsonBuilder; | |||||
| /** | /** | ||||
| * 公众号菜单 | * 公众号菜单 | ||||
| * @author chanjarster | * @author chanjarster | ||||
| @@ -20,6 +24,18 @@ public class WxMenu { | |||||
| this.button = button; | this.button = button; | ||||
| } | } | ||||
| public String toJson() { | |||||
| return WxGsonBuilder.create().toJson(this); | |||||
| } | |||||
| public static WxMenu fromJson(String json) { | |||||
| return WxGsonBuilder.create().fromJson(json, WxMenu.class); | |||||
| } | |||||
| public static WxMenu fromJson(InputStream is) { | |||||
| return WxGsonBuilder.create().fromJson(new InputStreamReader(is), WxMenu.class); | |||||
| } | |||||
| public static class WxMenuButton { | public static class WxMenuButton { | ||||
| protected String type; | protected String type; | ||||
| @@ -1,10 +1,11 @@ | |||||
| package chanjarster.weixin.out; | |||||
| package chanjarster.weixin.bean; | |||||
| import java.io.InputStream; | |||||
| import javax.xml.bind.JAXBException; | import javax.xml.bind.JAXBException; | ||||
| import javax.xml.bind.annotation.XmlAccessType; | import javax.xml.bind.annotation.XmlAccessType; | ||||
| import javax.xml.bind.annotation.XmlAccessorType; | import javax.xml.bind.annotation.XmlAccessorType; | ||||
| import javax.xml.bind.annotation.XmlElement; | import javax.xml.bind.annotation.XmlElement; | ||||
| import javax.xml.bind.annotation.XmlRegistry; | |||||
| import javax.xml.bind.annotation.XmlRootElement; | import javax.xml.bind.annotation.XmlRootElement; | ||||
| import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; | import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; | ||||
| @@ -13,7 +14,7 @@ import chanjarster.weixin.util.XmlTransformer; | |||||
| /** | /** | ||||
| * <pre> | * <pre> | ||||
| * 微信推送过来的消息,同时也是同步回复给用户的消息 | |||||
| * 微信推送过来的消息,也是同步回复给用户的消息,xml格式 | |||||
| * 相关字段的解释看微信开发者文档: | * 相关字段的解释看微信开发者文档: | ||||
| * http://mp.weixin.qq.com/wiki/index.php?title=接收普通消息 | * http://mp.weixin.qq.com/wiki/index.php?title=接收普通消息 | ||||
| * http://mp.weixin.qq.com/wiki/index.php?title=接收事件推送 | * http://mp.weixin.qq.com/wiki/index.php?title=接收事件推送 | ||||
| @@ -24,7 +25,7 @@ import chanjarster.weixin.util.XmlTransformer; | |||||
| */ | */ | ||||
| @XmlRootElement(name = "xml") | @XmlRootElement(name = "xml") | ||||
| @XmlAccessorType(XmlAccessType.FIELD) | @XmlAccessorType(XmlAccessType.FIELD) | ||||
| public class WxUserMessage { | |||||
| public class WxXmlMessage { | |||||
| /////////////////////// | /////////////////////// | ||||
| // 以下都是微信推送过来的消息的xml的element所对应的属性 | // 以下都是微信推送过来的消息的xml的element所对应的属性 | ||||
| @@ -288,21 +289,31 @@ public class WxUserMessage { | |||||
| public String toXml() { | public String toXml() { | ||||
| try { | try { | ||||
| return XmlTransformer.toXml(WxUserMessage.class, this); | |||||
| return XmlTransformer.toXml(WxXmlMessage.class, this); | |||||
| } catch (JAXBException e) { | } catch (JAXBException e) { | ||||
| e.printStackTrace(); | e.printStackTrace(); | ||||
| } | } | ||||
| return ""; | return ""; | ||||
| } | } | ||||
| public static WxUserMessage fromXml(String xml) { | |||||
| public static WxXmlMessage fromXml(String xml) { | |||||
| try { | try { | ||||
| return XmlTransformer.fromXml(WxUserMessage.class, xml); | |||||
| return XmlTransformer.fromXml(WxXmlMessage.class, xml); | |||||
| } catch (JAXBException e) { | } catch (JAXBException e) { | ||||
| e.printStackTrace(); | e.printStackTrace(); | ||||
| } | } | ||||
| return null; | return null; | ||||
| } | } | ||||
| public static WxXmlMessage fromXml(InputStream is) { | |||||
| try { | |||||
| return XmlTransformer.fromXml(WxXmlMessage.class, is); | |||||
| } catch (JAXBException e) { | |||||
| e.printStackTrace(); | |||||
| } | |||||
| return null; | |||||
| } | |||||
| @Override | @Override | ||||
| public int hashCode() { | public int hashCode() { | ||||
| final int prime = 31; | final int prime = 31; | ||||
| @@ -338,7 +349,7 @@ public class WxUserMessage { | |||||
| if (this == obj) return true; | if (this == obj) return true; | ||||
| if (obj == null) return false; | if (obj == null) return false; | ||||
| if (getClass() != obj.getClass()) return false; | if (getClass() != obj.getClass()) return false; | ||||
| WxUserMessage other = (WxUserMessage) obj; | |||||
| WxXmlMessage other = (WxXmlMessage) obj; | |||||
| if (Content == null) { | if (Content == null) { | ||||
| if (other.Content != null) return false; | if (other.Content != null) return false; | ||||
| } else if (!Content.equals(other.Content)) return false; | } else if (!Content.equals(other.Content)) return false; | ||||
| @@ -1,6 +1,6 @@ | |||||
| package chanjarster.weixin.exception; | package chanjarster.weixin.exception; | ||||
| import chanjarster.weixin.in.WxError; | |||||
| import chanjarster.weixin.bean.WxError; | |||||
| public class WxErrorException extends Exception { | public class WxErrorException extends Exception { | ||||
| @@ -1,15 +0,0 @@ | |||||
| package chanjarster.weixin.service; | |||||
| public interface WxConfigProvider { | |||||
| public void updateAccessToken(String accessToken, Integer expiresIn); | |||||
| public String getAccessToken(); | |||||
| public String getAppId(); | |||||
| public String getSecret(); | |||||
| public String getToken(); | |||||
| } | |||||
| @@ -1,16 +0,0 @@ | |||||
| package chanjarster.weixin.service; | |||||
| import java.util.Map; | |||||
| import chanjarster.weixin.out.WxUserMessage; | |||||
| /** | |||||
| * 处理微信推送消息的处理器 | |||||
| * @author chanjarster | |||||
| * | |||||
| */ | |||||
| public interface WxMessageHandler { | |||||
| public void handle(WxUserMessage wxMessage, Map<String, Object> context); | |||||
| } | |||||
| @@ -1,23 +0,0 @@ | |||||
| package chanjarster.weixin.service; | |||||
| import chanjarster.weixin.exception.WxErrorException; | |||||
| import chanjarster.weixin.out.WxCustomMessage; | |||||
| import chanjarster.weixin.out.WxMenu; | |||||
| /** | |||||
| * 微信相关的常量 | |||||
| */ | |||||
| public interface WxService { | |||||
| public void refreshAccessToken() throws WxErrorException; | |||||
| public String sendCustomMessage(WxCustomMessage message) throws WxErrorException; | |||||
| public String createMenu(WxMenu menu) throws WxErrorException; | |||||
| public String deleteMenu() throws WxErrorException; | |||||
| public WxMenu getMenu() throws WxErrorException; | |||||
| public void setWxConfigProvider(WxConfigProvider wxConfigProvider); | |||||
| } | |||||
| @@ -0,0 +1,115 @@ | |||||
| /* | |||||
| * KINGSTAR MEDIA SOLUTIONS Co.,LTD. Copyright c 2005-2013. All rights reserved. | |||||
| * | |||||
| * This source code is the property of KINGSTAR MEDIA SOLUTIONS LTD. It is intended | |||||
| * only for the use of KINGSTAR MEDIA application development. Reengineering, reproduction | |||||
| * arose from modification of the original source, or other redistribution of this source | |||||
| * is not permitted without written permission of the KINGSTAR MEDIA SOLUTIONS LTD. | |||||
| */ | |||||
| package chanjarster.weixin.util; | |||||
| import com.google.gson.JsonElement; | |||||
| import com.google.gson.JsonObject; | |||||
| public class GsonHelper { | |||||
| public static boolean isNull(JsonElement element) { | |||||
| return element == null || element.isJsonNull(); | |||||
| } | |||||
| public static boolean isNotNull(JsonElement element) { | |||||
| return !isNull(element); | |||||
| } | |||||
| public static Long getLong(JsonObject json, String property) { | |||||
| return getAsLong(json.get(property)); | |||||
| } | |||||
| public static long getPrimitiveLong(JsonObject json, String property) { | |||||
| return getAsPrimitiveLong(json.get(property)); | |||||
| } | |||||
| public static Integer getInteger(JsonObject json, String property) { | |||||
| return getAsInteger(json.get(property)); | |||||
| } | |||||
| public static int getPrimitiveInteger(JsonObject json, String property) { | |||||
| return getAsPrimitiveInt(json.get(property)); | |||||
| } | |||||
| public static Double getDouble(JsonObject json, String property) { | |||||
| return getAsDouble(json.get(property)); | |||||
| } | |||||
| public static double getPrimitiveDouble(JsonObject json, String property) { | |||||
| return getAsPrimitiveDouble(json.get(property)); | |||||
| } | |||||
| public static Float getFloat(JsonObject json, String property) { | |||||
| return getAsFloat(json.get(property)); | |||||
| } | |||||
| public static float getPrimitiveFloat(JsonObject json, String property) { | |||||
| return getAsPrimitiveFloat(json.get(property)); | |||||
| } | |||||
| public static Boolean getBoolean(JsonObject json, String property) { | |||||
| return getAsBoolean(json.get(property)); | |||||
| } | |||||
| public static String getString(JsonObject json, String property) { | |||||
| return getAsString(json.get(property)); | |||||
| } | |||||
| public static String getAsString(JsonElement element) { | |||||
| return isNull(element) ? null : element.getAsString(); | |||||
| } | |||||
| public static Long getAsLong(JsonElement element) { | |||||
| return isNull(element) ? null : element.getAsLong(); | |||||
| } | |||||
| public static long getAsPrimitiveLong(JsonElement element) { | |||||
| Long r = getAsLong(element); | |||||
| return r == null ? 0l : r; | |||||
| } | |||||
| public static Integer getAsInteger(JsonElement element) { | |||||
| return isNull(element) ? null : element.getAsInt(); | |||||
| } | |||||
| public static int getAsPrimitiveInt(JsonElement element) { | |||||
| Integer r = getAsInteger(element); | |||||
| return r == null ? 0 : r; | |||||
| } | |||||
| public static Boolean getAsBoolean(JsonElement element) { | |||||
| return isNull(element) ? null : element.getAsBoolean(); | |||||
| } | |||||
| public static boolean getAsPrimitiveBool(JsonElement element) { | |||||
| Boolean r = getAsBoolean(element); | |||||
| return r == null ? false : r.booleanValue(); | |||||
| } | |||||
| public static Double getAsDouble(JsonElement element) { | |||||
| return isNull(element) ? null : element.getAsDouble(); | |||||
| } | |||||
| public static double getAsPrimitiveDouble(JsonElement element) { | |||||
| Double r = getAsDouble(element); | |||||
| return r == null ? 0d : r; | |||||
| } | |||||
| public static Float getAsFloat(JsonElement element) { | |||||
| return isNull(element) ? null : element.getAsFloat(); | |||||
| } | |||||
| public static float getAsPrimitiveFloat(JsonElement element) { | |||||
| Float r = getAsFloat(element); | |||||
| return r == null ? 0f : r; | |||||
| } | |||||
| } | |||||
| @@ -10,9 +10,9 @@ package chanjarster.weixin.util; | |||||
| import java.lang.reflect.Type; | import java.lang.reflect.Type; | ||||
| import chanjarster.weixin.out.WxCustomMessage; | |||||
| import chanjarster.weixin.out.WxCustomMessage.WxArticle; | |||||
| import chanjarster.weixin.service.WxMsgType; | |||||
| import chanjarster.weixin.api.WxConsts; | |||||
| import chanjarster.weixin.bean.WxCustomMessage; | |||||
| import chanjarster.weixin.bean.WxCustomMessage.WxArticle; | |||||
| import com.google.gson.JsonArray; | import com.google.gson.JsonArray; | ||||
| import com.google.gson.JsonElement; | import com.google.gson.JsonElement; | ||||
| @@ -32,25 +32,25 @@ public class WxCustomMessageGsonAdapter implements JsonSerializer<WxCustomMessag | |||||
| messageJson.addProperty("touser", message.getTouser()); | messageJson.addProperty("touser", message.getTouser()); | ||||
| messageJson.addProperty("msgtype", message.getMsgtype()); | messageJson.addProperty("msgtype", message.getMsgtype()); | ||||
| if (WxMsgType.TEXT.equals(message.getMsgtype())) { | |||||
| if (WxConsts.TEXT.equals(message.getMsgtype())) { | |||||
| JsonObject text = new JsonObject(); | JsonObject text = new JsonObject(); | ||||
| text.addProperty("content", message.getContent()); | text.addProperty("content", message.getContent()); | ||||
| messageJson.add("text", text); | messageJson.add("text", text); | ||||
| } | } | ||||
| if (WxMsgType.IMAGE.equals(message.getMsgtype())) { | |||||
| if (WxConsts.IMAGE.equals(message.getMsgtype())) { | |||||
| JsonObject image = new JsonObject(); | JsonObject image = new JsonObject(); | ||||
| image.addProperty("media_id", message.getMedia_id()); | image.addProperty("media_id", message.getMedia_id()); | ||||
| messageJson.add("image", image); | messageJson.add("image", image); | ||||
| } | } | ||||
| if (WxMsgType.VOICE.equals(message.getMsgtype())) { | |||||
| if (WxConsts.VOICE.equals(message.getMsgtype())) { | |||||
| JsonObject voice = new JsonObject(); | JsonObject voice = new JsonObject(); | ||||
| voice.addProperty("media_id", message.getMedia_id()); | voice.addProperty("media_id", message.getMedia_id()); | ||||
| messageJson.add("voice", voice); | messageJson.add("voice", voice); | ||||
| } | } | ||||
| if (WxMsgType.VIDEO.equals(message.getMsgtype())) { | |||||
| if (WxConsts.VIDEO.equals(message.getMsgtype())) { | |||||
| JsonObject video = new JsonObject(); | JsonObject video = new JsonObject(); | ||||
| video.addProperty("media_id", message.getMedia_id()); | video.addProperty("media_id", message.getMedia_id()); | ||||
| video.addProperty("thumb_media_id", message.getThumb_media_id()); | video.addProperty("thumb_media_id", message.getThumb_media_id()); | ||||
| @@ -59,7 +59,7 @@ public class WxCustomMessageGsonAdapter implements JsonSerializer<WxCustomMessag | |||||
| messageJson.add("video", video); | messageJson.add("video", video); | ||||
| } | } | ||||
| if (WxMsgType.MUSIC.equals(message.getMsgtype())) { | |||||
| if (WxConsts.MUSIC.equals(message.getMsgtype())) { | |||||
| JsonObject music = new JsonObject(); | JsonObject music = new JsonObject(); | ||||
| music.addProperty("title", message.getTitle()); | music.addProperty("title", message.getTitle()); | ||||
| music.addProperty("description", message.getDescription()); | music.addProperty("description", message.getDescription()); | ||||
| @@ -69,7 +69,7 @@ public class WxCustomMessageGsonAdapter implements JsonSerializer<WxCustomMessag | |||||
| messageJson.add("music", music); | messageJson.add("music", music); | ||||
| } | } | ||||
| if (WxMsgType.NEWS.equals(message.getMsgtype())) { | |||||
| if (WxConsts.NEWS.equals(message.getMsgtype())) { | |||||
| JsonArray articleJsonArray = new JsonArray(); | JsonArray articleJsonArray = new JsonArray(); | ||||
| for (WxArticle article : message.getArticles()) { | for (WxArticle article : message.getArticles()) { | ||||
| JsonObject articleJson = new JsonObject(); | JsonObject articleJson = new JsonObject(); | ||||
| @@ -1,6 +1,7 @@ | |||||
| package chanjarster.weixin.util; | package chanjarster.weixin.util; | ||||
| import chanjarster.weixin.out.WxCustomMessage; | |||||
| import chanjarster.weixin.bean.WxCustomMessage; | |||||
| import chanjarster.weixin.bean.WxMenu; | |||||
| import com.google.gson.Gson; | import com.google.gson.Gson; | ||||
| import com.google.gson.GsonBuilder; | import com.google.gson.GsonBuilder; | ||||
| @@ -12,6 +13,7 @@ public class WxGsonBuilder { | |||||
| static { | static { | ||||
| INSTANCE.disableHtmlEscaping(); | INSTANCE.disableHtmlEscaping(); | ||||
| INSTANCE.registerTypeAdapter(WxCustomMessage.class, new WxCustomMessageGsonAdapter()); | INSTANCE.registerTypeAdapter(WxCustomMessage.class, new WxCustomMessageGsonAdapter()); | ||||
| INSTANCE.registerTypeAdapter(WxMenu.class, new WxMenuGsonAdapter()); | |||||
| } | } | ||||
| public static Gson create() { | public static Gson create() { | ||||
| @@ -10,12 +10,15 @@ package chanjarster.weixin.util; | |||||
| import java.lang.reflect.Type; | import java.lang.reflect.Type; | ||||
| import chanjarster.weixin.out.WxMenu; | |||||
| import chanjarster.weixin.out.WxMenu.WxMenuButton; | |||||
| import chanjarster.weixin.bean.WxMenu; | |||||
| import chanjarster.weixin.bean.WxMenu.WxMenuButton; | |||||
| import com.google.gson.JsonArray; | import com.google.gson.JsonArray; | ||||
| import com.google.gson.JsonDeserializationContext; | |||||
| import com.google.gson.JsonDeserializer; | |||||
| import com.google.gson.JsonElement; | import com.google.gson.JsonElement; | ||||
| import com.google.gson.JsonObject; | import com.google.gson.JsonObject; | ||||
| import com.google.gson.JsonParseException; | |||||
| import com.google.gson.JsonSerializationContext; | import com.google.gson.JsonSerializationContext; | ||||
| import com.google.gson.JsonSerializer; | import com.google.gson.JsonSerializer; | ||||
| @@ -24,14 +27,14 @@ import com.google.gson.JsonSerializer; | |||||
| * @author qianjia | * @author qianjia | ||||
| * | * | ||||
| */ | */ | ||||
| public class WxMenuGsonAdapter implements JsonSerializer<WxMenu> { | |||||
| public class WxMenuGsonAdapter implements JsonSerializer<WxMenu>, JsonDeserializer<WxMenu> { | |||||
| public JsonElement serialize(WxMenu menu, Type typeOfSrc, JsonSerializationContext context) { | public JsonElement serialize(WxMenu menu, Type typeOfSrc, JsonSerializationContext context) { | ||||
| JsonObject json = new JsonObject(); | JsonObject json = new JsonObject(); | ||||
| JsonArray buttonArray = new JsonArray(); | JsonArray buttonArray = new JsonArray(); | ||||
| for (WxMenuButton button : menu.getButton()) { | for (WxMenuButton button : menu.getButton()) { | ||||
| JsonObject buttonJson = serialize(button); | |||||
| JsonObject buttonJson = convertToJson(button); | |||||
| buttonArray.add(buttonJson); | buttonArray.add(buttonJson); | ||||
| } | } | ||||
| json.add("button", buttonArray); | json.add("button", buttonArray); | ||||
| @@ -39,17 +42,48 @@ public class WxMenuGsonAdapter implements JsonSerializer<WxMenu> { | |||||
| return json; | return json; | ||||
| } | } | ||||
| protected JsonObject serialize(WxMenuButton button) { | |||||
| protected JsonObject convertToJson(WxMenuButton button) { | |||||
| JsonObject buttonJson = new JsonObject(); | JsonObject buttonJson = new JsonObject(); | ||||
| buttonJson.addProperty("type", button.getType()); | |||||
| buttonJson.addProperty("name", button.getName()); | buttonJson.addProperty("name", button.getName()); | ||||
| // TODO 其他字段 | |||||
| if (button.getSub_button() == null || button.getSub_button().size() == 0) { | |||||
| buttonJson.addProperty("key", button.getKey()); | |||||
| buttonJson.addProperty("url", button.getUrl()); | |||||
| if (button.getSub_button() != null && button.getSub_button().size() > 0) { | |||||
| JsonArray buttonArray = new JsonArray(); | JsonArray buttonArray = new JsonArray(); | ||||
| for (WxMenuButton sub_button : button.getSub_button()) { | for (WxMenuButton sub_button : button.getSub_button()) { | ||||
| buttonArray.add(serialize(sub_button)); | |||||
| buttonArray.add(convertToJson(sub_button)); | |||||
| } | } | ||||
| buttonJson.add("sub_button", buttonArray); | buttonJson.add("sub_button", buttonArray); | ||||
| } | } | ||||
| return buttonJson; | return buttonJson; | ||||
| } | } | ||||
| } | |||||
| public WxMenu deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { | |||||
| WxMenu menu = new WxMenu(); | |||||
| JsonArray buttonsJson = json.getAsJsonObject().get("button").getAsJsonArray(); | |||||
| for (int i = 0; i < buttonsJson.size(); i++) { | |||||
| JsonObject buttonJson = buttonsJson.get(i).getAsJsonObject(); | |||||
| WxMenuButton button = convertFromJson(buttonJson); | |||||
| menu.getButton().add(button); | |||||
| if (buttonJson.get("sub_button") == null || buttonJson.get("sub_button").isJsonNull()) { | |||||
| continue; | |||||
| } | |||||
| JsonArray sub_buttonsJson = buttonJson.get("sub_button").getAsJsonArray(); | |||||
| for (int j = 0; j < sub_buttonsJson.size(); j++) { | |||||
| JsonObject sub_buttonJson = sub_buttonsJson.get(j).getAsJsonObject(); | |||||
| button.getSub_button().add(convertFromJson(sub_buttonJson)); | |||||
| } | |||||
| } | |||||
| return menu; | |||||
| } | |||||
| protected WxMenuButton convertFromJson(JsonObject json) { | |||||
| WxMenuButton button = new WxMenuButton(); | |||||
| button.setName(GsonHelper.getString(json, "name")); | |||||
| button.setKey(GsonHelper.getString(json, "key")); | |||||
| button.setUrl(GsonHelper.getString(json, "url")); | |||||
| button.setType(GsonHelper.getString(json, "type")); | |||||
| return button; | |||||
| } | |||||
| } | |||||
| @@ -1,4 +1,4 @@ | |||||
| package chanjarster.weixin.service; | |||||
| package chanjarster.weixin.api; | |||||
| // TODO | // TODO | ||||
| public class WxMessageRouterTest { | public class WxMessageRouterTest { | ||||
| @@ -1,4 +1,4 @@ | |||||
| package chanjarster.weixin.service; | |||||
| package chanjarster.weixin.api; | |||||
| import java.io.InputStream; | import java.io.InputStream; | ||||
| @@ -12,14 +12,18 @@ import org.testng.Assert; | |||||
| import org.testng.annotations.DataProvider; | import org.testng.annotations.DataProvider; | ||||
| import org.testng.annotations.Test; | import org.testng.annotations.Test; | ||||
| import chanjarster.weixin.api.WxConsts; | |||||
| import chanjarster.weixin.api.WxMemoryConfigProvider; | |||||
| import chanjarster.weixin.api.WxService; | |||||
| import chanjarster.weixin.api.WxServiceImpl; | |||||
| import chanjarster.weixin.bean.WxCustomMessage; | |||||
| import chanjarster.weixin.exception.WxErrorException; | import chanjarster.weixin.exception.WxErrorException; | ||||
| import chanjarster.weixin.out.WxCustomMessage; | |||||
| import chanjarster.weixin.util.XmlTransformer; | import chanjarster.weixin.util.XmlTransformer; | ||||
| public class WxServiceTest { | public class WxServiceTest { | ||||
| @Test(dataProvider = "configs") | @Test(dataProvider = "configs") | ||||
| public void testRefreshAccessToken(WxConfigProvider config) throws WxErrorException { | |||||
| public void testRefreshAccessToken(WxTestConfigProvider config) throws WxErrorException { | |||||
| String before = config.getAccessToken(); | String before = config.getAccessToken(); | ||||
| WxService wxService = new WxServiceImpl(); | WxService wxService = new WxServiceImpl(); | ||||
| @@ -33,12 +37,12 @@ public class WxServiceTest { | |||||
| } | } | ||||
| @Test(dataProvider = "configs") | @Test(dataProvider = "configs") | ||||
| public void sendCustomMessage(SimpleWxConfigProvider config) throws WxErrorException { | |||||
| public void sendCustomMessage(WxTestConfigProvider config) throws WxErrorException { | |||||
| WxService wxService = new WxServiceImpl(); | WxService wxService = new WxServiceImpl(); | ||||
| wxService.setWxConfigProvider(config); | wxService.setWxConfigProvider(config); | ||||
| WxCustomMessage message = new WxCustomMessage(); | WxCustomMessage message = new WxCustomMessage(); | ||||
| message.setMsgtype(WxMsgType.TEXT); | |||||
| message.setMsgtype(WxConsts.TEXT); | |||||
| message.setTouser(config.getOpenId()); | message.setTouser(config.getOpenId()); | ||||
| message.setContent("欢迎使用教务系统微信公众号\n下面\n<a href=\"http://192.168.1.249:9180/eams-rc/login.action\">Hello World</a>"); | message.setContent("欢迎使用教务系统微信公众号\n下面\n<a href=\"http://192.168.1.249:9180/eams-rc/login.action\">Hello World</a>"); | ||||
| @@ -56,7 +60,7 @@ public class WxServiceTest { | |||||
| */ | */ | ||||
| // 没有access_token | // 没有access_token | ||||
| InputStream is1 = ClassLoader.getSystemResourceAsStream("test-config.xml"); | InputStream is1 = ClassLoader.getSystemResourceAsStream("test-config.xml"); | ||||
| SimpleWxConfigProvider config1 = XmlTransformer.fromXml(SimpleWxConfigProvider.class, is1); | |||||
| WxTestConfigProvider config1 = XmlTransformer.fromXml(WxTestConfigProvider.class, is1); | |||||
| return new Object[][] { | return new Object[][] { | ||||
| new Object[] { | new Object[] { | ||||
| config1 | config1 | ||||
| @@ -66,47 +70,10 @@ public class WxServiceTest { | |||||
| @XmlRootElement(name = "xml") | @XmlRootElement(name = "xml") | ||||
| @XmlAccessorType(XmlAccessType.FIELD) | @XmlAccessorType(XmlAccessType.FIELD) | ||||
| public static class SimpleWxConfigProvider implements WxConfigProvider { | |||||
| private String appId; | |||||
| private String secret; | |||||
| private String accessToken = ""; | |||||
| private Integer expiresIn; | |||||
| private String token; | |||||
| private String openId; | |||||
| public void updateAccessToken(String accessToken, Integer expiresIn) { | |||||
| this.accessToken = accessToken; | |||||
| this.expiresIn = expiresIn; | |||||
| } | |||||
| public String getAccessToken() { | |||||
| return accessToken; | |||||
| } | |||||
| public String getAppId() { | |||||
| return appId; | |||||
| } | |||||
| public String getSecret() { | |||||
| return secret; | |||||
| } | |||||
| public String getToken() { | |||||
| return token; | |||||
| } | |||||
| public void setAppId(String appId) { | |||||
| this.appId = appId; | |||||
| } | |||||
| public void setSecret(String secret) { | |||||
| this.secret = secret; | |||||
| } | |||||
| public void setToken(String token) { | |||||
| this.token = token; | |||||
| } | |||||
| public Integer getExpiresIn() { | |||||
| return expiresIn; | |||||
| } | |||||
| public void setExpiresIn(Integer expiresIn) { | |||||
| this.expiresIn = expiresIn; | |||||
| } | |||||
| public void setAccessToken(String accessToken) { | |||||
| this.accessToken = accessToken; | |||||
| } | |||||
| public static class WxTestConfigProvider extends WxMemoryConfigProvider { | |||||
| protected String openId; | |||||
| public String getOpenId() { | public String getOpenId() { | ||||
| return openId; | return openId; | ||||
| } | } | ||||
| @@ -0,0 +1,18 @@ | |||||
| package chanjarster.weixin.bean; | |||||
| import org.testng.Assert; | |||||
| import org.testng.annotations.Test; | |||||
| @Test | |||||
| public class WxAccessTokenTest { | |||||
| public void testFromJson() { | |||||
| String json = "{\"access_token\":\"ACCESS_TOKEN\",\"expires_in\":7200}"; | |||||
| WxAccessToken wxError = WxAccessToken.fromJson(json); | |||||
| Assert.assertEquals(wxError.getAccess_token(), "ACCESS_TOKEN"); | |||||
| Assert.assertTrue(wxError.getExpires_in() == 7200); | |||||
| } | |||||
| } | |||||
| @@ -1,18 +1,19 @@ | |||||
| package chanjarster.weixin.out; | |||||
| package chanjarster.weixin.bean; | |||||
| import org.testng.Assert; | import org.testng.Assert; | ||||
| import org.testng.annotations.Test; | import org.testng.annotations.Test; | ||||
| import chanjarster.weixin.out.WxCustomMessage; | |||||
| import chanjarster.weixin.out.WxCustomMessage.WxArticle; | |||||
| import chanjarster.weixin.service.WxMsgType; | |||||
| import chanjarster.weixin.api.WxConsts; | |||||
| import chanjarster.weixin.bean.WxCustomMessage; | |||||
| import chanjarster.weixin.bean.WxCustomMessage.WxArticle; | |||||
| @Test | @Test | ||||
| public class WxCustomMessageTest { | public class WxCustomMessageTest { | ||||
| public void testTextReply() { | public void testTextReply() { | ||||
| WxCustomMessage reply = new WxCustomMessage(); | WxCustomMessage reply = new WxCustomMessage(); | ||||
| reply.setTouser("OPENID"); | reply.setTouser("OPENID"); | ||||
| reply.setMsgtype(WxMsgType.TEXT); | |||||
| reply.setMsgtype(WxConsts.TEXT); | |||||
| reply.setContent("sfsfdsdf"); | reply.setContent("sfsfdsdf"); | ||||
| Assert.assertEquals(reply.toJson(), "{\"touser\":\"OPENID\",\"msgtype\":\"text\",\"text\":{\"content\":\"sfsfdsdf\"}}"); | Assert.assertEquals(reply.toJson(), "{\"touser\":\"OPENID\",\"msgtype\":\"text\",\"text\":{\"content\":\"sfsfdsdf\"}}"); | ||||
| } | } | ||||
| @@ -20,7 +21,7 @@ public class WxCustomMessageTest { | |||||
| public void testImageReply() { | public void testImageReply() { | ||||
| WxCustomMessage reply = new WxCustomMessage(); | WxCustomMessage reply = new WxCustomMessage(); | ||||
| reply.setTouser("OPENID"); | reply.setTouser("OPENID"); | ||||
| reply.setMsgtype(WxMsgType.IMAGE); | |||||
| reply.setMsgtype(WxConsts.IMAGE); | |||||
| reply.setMedia_id("MEDIA_ID"); | reply.setMedia_id("MEDIA_ID"); | ||||
| Assert.assertEquals(reply.toJson(), "{\"touser\":\"OPENID\",\"msgtype\":\"image\",\"image\":{\"media_id\":\"MEDIA_ID\"}}"); | Assert.assertEquals(reply.toJson(), "{\"touser\":\"OPENID\",\"msgtype\":\"image\",\"image\":{\"media_id\":\"MEDIA_ID\"}}"); | ||||
| } | } | ||||
| @@ -28,7 +29,7 @@ public class WxCustomMessageTest { | |||||
| public void testVoiceReply() { | public void testVoiceReply() { | ||||
| WxCustomMessage reply = new WxCustomMessage(); | WxCustomMessage reply = new WxCustomMessage(); | ||||
| reply.setTouser("OPENID"); | reply.setTouser("OPENID"); | ||||
| reply.setMsgtype(WxMsgType.VOICE); | |||||
| reply.setMsgtype(WxConsts.VOICE); | |||||
| reply.setMedia_id("MEDIA_ID"); | reply.setMedia_id("MEDIA_ID"); | ||||
| Assert.assertEquals(reply.toJson(), "{\"touser\":\"OPENID\",\"msgtype\":\"voice\",\"voice\":{\"media_id\":\"MEDIA_ID\"}}"); | Assert.assertEquals(reply.toJson(), "{\"touser\":\"OPENID\",\"msgtype\":\"voice\",\"voice\":{\"media_id\":\"MEDIA_ID\"}}"); | ||||
| } | } | ||||
| @@ -36,7 +37,7 @@ public class WxCustomMessageTest { | |||||
| public void testVideoReply() { | public void testVideoReply() { | ||||
| WxCustomMessage reply = new WxCustomMessage(); | WxCustomMessage reply = new WxCustomMessage(); | ||||
| reply.setTouser("OPENID"); | reply.setTouser("OPENID"); | ||||
| reply.setMsgtype(WxMsgType.VIDEO); | |||||
| reply.setMsgtype(WxConsts.VIDEO); | |||||
| reply.setMedia_id("MEDIA_ID"); | reply.setMedia_id("MEDIA_ID"); | ||||
| reply.setThumb_media_id("MEDIA_ID"); | reply.setThumb_media_id("MEDIA_ID"); | ||||
| reply.setTitle("TITLE"); | reply.setTitle("TITLE"); | ||||
| @@ -47,7 +48,7 @@ public class WxCustomMessageTest { | |||||
| public void testMusicReply() { | public void testMusicReply() { | ||||
| WxCustomMessage reply = new WxCustomMessage(); | WxCustomMessage reply = new WxCustomMessage(); | ||||
| reply.setTouser("OPENID"); | reply.setTouser("OPENID"); | ||||
| reply.setMsgtype(WxMsgType.MUSIC); | |||||
| reply.setMsgtype(WxConsts.MUSIC); | |||||
| reply.setThumb_media_id("MEDIA_ID"); | reply.setThumb_media_id("MEDIA_ID"); | ||||
| reply.setDescription("DESCRIPTION"); | reply.setDescription("DESCRIPTION"); | ||||
| reply.setTitle("TITLE"); | reply.setTitle("TITLE"); | ||||
| @@ -59,7 +60,7 @@ public class WxCustomMessageTest { | |||||
| public void testNewsReply() { | public void testNewsReply() { | ||||
| WxCustomMessage reply = new WxCustomMessage(); | WxCustomMessage reply = new WxCustomMessage(); | ||||
| reply.setTouser("OPENID"); | reply.setTouser("OPENID"); | ||||
| reply.setMsgtype(WxMsgType.NEWS); | |||||
| reply.setMsgtype(WxConsts.NEWS); | |||||
| WxArticle article1 = new WxArticle(); | WxArticle article1 = new WxArticle(); | ||||
| article1.setUrl("URL"); | article1.setUrl("URL"); | ||||
| @@ -1,9 +1,9 @@ | |||||
| package chanjarster.weixin.in; | |||||
| package chanjarster.weixin.bean; | |||||
| import org.testng.Assert; | import org.testng.Assert; | ||||
| import org.testng.annotations.Test; | import org.testng.annotations.Test; | ||||
| import chanjarster.weixin.in.WxError; | |||||
| import chanjarster.weixin.bean.WxError; | |||||
| @Test | @Test | ||||
| public class WxErrorTest { | public class WxErrorTest { | ||||
| @@ -0,0 +1,104 @@ | |||||
| package chanjarster.weixin.bean; | |||||
| import org.apache.http.util.Asserts; | |||||
| import org.testng.Assert; | |||||
| import org.testng.annotations.DataProvider; | |||||
| import org.testng.annotations.Test; | |||||
| import chanjarster.weixin.bean.WxMenu.WxMenuButton; | |||||
| @Test | |||||
| public class WxMenuTest { | |||||
| @Test(dataProvider="json") | |||||
| public void testFromJson(String json) { | |||||
| WxMenu menu = WxMenu.fromJson(json); | |||||
| Assert.assertEquals(menu.getButton().size(), 3); | |||||
| } | |||||
| @Test(dataProvider="json") | |||||
| public void testToJson(String json) { | |||||
| WxMenu menu = new WxMenu(); | |||||
| WxMenuButton button1 = new WxMenuButton(); | |||||
| button1.setType("click"); | |||||
| button1.setName("今日歌曲"); | |||||
| button1.setKey("V1001_TODAY_MUSIC"); | |||||
| WxMenuButton button2 = new WxMenuButton(); | |||||
| button2.setType("click"); | |||||
| button2.setName("歌手简介"); | |||||
| button2.setKey("V1001_TODAY_SINGER"); | |||||
| WxMenuButton button3 = new WxMenuButton(); | |||||
| button3.setName("菜单"); | |||||
| menu.getButton().add(button1); | |||||
| menu.getButton().add(button2); | |||||
| menu.getButton().add(button3); | |||||
| WxMenuButton button31 = new WxMenuButton(); | |||||
| button31.setType("view"); | |||||
| button31.setName("搜索"); | |||||
| button31.setUrl("http://www.soso.com/"); | |||||
| WxMenuButton button32 = new WxMenuButton(); | |||||
| button32.setType("view"); | |||||
| button32.setName("视频"); | |||||
| button32.setUrl("http://v.qq.com/"); | |||||
| WxMenuButton button33 = new WxMenuButton(); | |||||
| button33.setType("click"); | |||||
| button33.setName("赞一下我们"); | |||||
| button33.setKey("V1001_GOOD"); | |||||
| button3.getSub_button().add(button31); | |||||
| button3.getSub_button().add(button32); | |||||
| button3.getSub_button().add(button33); | |||||
| System.out.println(menu.toJson()); | |||||
| Assert.assertEquals(menu.toJson(), json); | |||||
| } | |||||
| @DataProvider(name="json") | |||||
| public Object[][] getMenuJson() { | |||||
| String json = | |||||
| "{" | |||||
| +"\"button\":[" | |||||
| +"{" | |||||
| +"\"type\":\"click\"," | |||||
| +"\"name\":\"今日歌曲\"," | |||||
| +"\"key\":\"V1001_TODAY_MUSIC\"" | |||||
| +"}," | |||||
| +"{" | |||||
| +"\"type\":\"click\"," | |||||
| +"\"name\":\"歌手简介\"," | |||||
| +"\"key\":\"V1001_TODAY_SINGER\"" | |||||
| +"}," | |||||
| +"{" | |||||
| +"\"name\":\"菜单\"," | |||||
| +"\"sub_button\":[" | |||||
| +"{" | |||||
| +"\"type\":\"view\"," | |||||
| +"\"name\":\"搜索\"," | |||||
| +"\"url\":\"http://www.soso.com/\"" | |||||
| +"}," | |||||
| +"{" | |||||
| +"\"type\":\"view\"," | |||||
| +"\"name\":\"视频\"," | |||||
| +"\"url\":\"http://v.qq.com/\"" | |||||
| +"}," | |||||
| +"{" | |||||
| +"\"type\":\"click\"," | |||||
| +"\"name\":\"赞一下我们\"," | |||||
| +"\"key\":\"V1001_GOOD\"" | |||||
| +"}" | |||||
| +"]" | |||||
| +"}" | |||||
| +"]" | |||||
| +"}"; | |||||
| return new Object[][] { | |||||
| new Object[] { json } | |||||
| }; | |||||
| } | |||||
| } | |||||
| @@ -1,13 +1,13 @@ | |||||
| package chanjarster.weixin.out; | |||||
| package chanjarster.weixin.bean; | |||||
| import org.testng.Assert; | import org.testng.Assert; | ||||
| import org.testng.annotations.Test; | import org.testng.annotations.Test; | ||||
| import chanjarster.weixin.out.WxUserMessage; | |||||
| import chanjarster.weixin.service.WxMsgType; | |||||
| import chanjarster.weixin.api.WxConsts; | |||||
| import chanjarster.weixin.bean.WxXmlMessage; | |||||
| @Test | @Test | ||||
| public class WxUserMessageTest { | |||||
| public class WxXmlMessageTest { | |||||
| public void testFromXml() { | public void testFromXml() { | ||||
| @@ -36,11 +36,11 @@ public class WxUserMessageTest { | |||||
| + "<Longitude>113.352425</Longitude>" | + "<Longitude>113.352425</Longitude>" | ||||
| + "<Precision>119.385040</Precision>" | + "<Precision>119.385040</Precision>" | ||||
| + "</xml>"; | + "</xml>"; | ||||
| WxUserMessage wxMessage = WxUserMessage.fromXml(xml); | |||||
| WxXmlMessage wxMessage = WxXmlMessage.fromXml(xml); | |||||
| Assert.assertEquals(wxMessage.getToUserName(), "toUser"); | Assert.assertEquals(wxMessage.getToUserName(), "toUser"); | ||||
| Assert.assertEquals(wxMessage.getFromUserName(), "fromUser"); | Assert.assertEquals(wxMessage.getFromUserName(), "fromUser"); | ||||
| Assert.assertEquals(wxMessage.getCreateTime(), new Long(1348831860l)); | Assert.assertEquals(wxMessage.getCreateTime(), new Long(1348831860l)); | ||||
| Assert.assertEquals(wxMessage.getMsgType(), WxMsgType.TEXT); | |||||
| Assert.assertEquals(wxMessage.getMsgType(), WxConsts.TEXT); | |||||
| Assert.assertEquals(wxMessage.getContent(), "this is a test"); | Assert.assertEquals(wxMessage.getContent(), "this is a test"); | ||||
| Assert.assertEquals(wxMessage.getMsgId(), new Long(1234567890123456l)); | Assert.assertEquals(wxMessage.getMsgId(), new Long(1234567890123456l)); | ||||
| Assert.assertEquals(wxMessage.getPicUrl(), "this is a url"); | Assert.assertEquals(wxMessage.getPicUrl(), "this is a url"); | ||||
| @@ -63,11 +63,11 @@ public class WxUserMessageTest { | |||||
| } | } | ||||
| public void testToXml() { | public void testToXml() { | ||||
| WxUserMessage wxMessage = new WxUserMessage(); | |||||
| WxXmlMessage wxMessage = new WxXmlMessage(); | |||||
| wxMessage.setToUserName("toUser"); | wxMessage.setToUserName("toUser"); | ||||
| wxMessage.setFromUserName("fromUser"); | wxMessage.setFromUserName("fromUser"); | ||||
| wxMessage.setCreateTime(new Long(1348831860l)); | wxMessage.setCreateTime(new Long(1348831860l)); | ||||
| wxMessage.setMsgType(WxMsgType.TEXT); | |||||
| wxMessage.setMsgType(WxConsts.TEXT); | |||||
| wxMessage.setContent("this is a test"); | wxMessage.setContent("this is a test"); | ||||
| wxMessage.setMsgId(new Long(1234567890123456l)); | wxMessage.setMsgId(new Long(1234567890123456l)); | ||||
| wxMessage.setPicUrl("this is a url"); | wxMessage.setPicUrl("this is a url"); | ||||