├── src ├── test │ ├── resources │ │ ├── .gitignore │ │ ├── sql │ │ │ └── import-data.sql │ │ ├── media │ │ │ └── cat.jpg │ │ ├── log4j.properties │ │ ├── application.development.properties │ │ └── applicationContext-test-weixinmp.xml │ └── java │ │ └── org │ │ └── hamster │ │ └── weixinmp │ │ └── test │ │ ├── base │ │ ├── AbstractServiceTest.java │ │ └── AbstractWxServiceTest.java │ │ ├── service │ │ ├── WxQrServiceTest.java │ │ ├── WxUserServiceTest.java │ │ ├── WxGroupServceTest.java │ │ ├── WxMediaServiceTest.java │ │ ├── WxMenuServiceTest.java │ │ └── WxServiceTest.java │ │ ├── controller │ │ └── WxControllerManualTest.java │ │ └── xml │ │ └── WxXMLUtilTest.java └── main │ ├── java │ └── org │ │ └── hamster │ │ └── weixinmp │ │ ├── model │ │ ├── qr │ │ │ ├── WxQrSceneJson.java │ │ │ ├── WxQrActionInfoJson.java │ │ │ └── WxQrCreateJson.java │ │ ├── user │ │ │ ├── WxOpenIdListJson.java │ │ │ └── WxUserGetJson.java │ │ ├── menu │ │ │ ├── WxMenuGetJson.java │ │ │ └── WxMenuCreateJson.java │ │ ├── send │ │ │ ├── item │ │ │ │ ├── SendItemTextJson.java │ │ │ │ ├── SendItemImageJson.java │ │ │ │ ├── SendItemVoiceJson.java │ │ │ │ ├── SendItemVideoJson.java │ │ │ │ ├── SendItemArticleJson.java │ │ │ │ ├── SendItemMusicJson.java │ │ │ │ └── wrapper │ │ │ │ │ └── WxSendItemArticleWrapper.java │ │ │ ├── SendTextJson.java │ │ │ ├── SendVideoJson.java │ │ │ ├── SendVoiceJson.java │ │ │ ├── SendImageJson.java │ │ │ ├── SendMusicJson.java │ │ │ └── SendItemPicDescJson.java │ │ ├── WxRespCode.java │ │ └── WxAccessTokenJson.java │ │ ├── constant │ │ ├── WxMenuBtnType.java │ │ ├── WxMsgRespType.java │ │ ├── WxMsgEventType.java │ │ ├── WxMsgType.java │ │ ├── WxMediaType.java │ │ ├── WxMenuBtnTypeEnum.java │ │ ├── WxMsgTypeEnum.java │ │ ├── WxMsgRespTypeEnum.java │ │ ├── WxMsgEventTypeEnum.java │ │ └── WxMediaTypeEnum.java │ │ ├── dao │ │ ├── repository │ │ │ ├── msg │ │ │ │ ├── WxMsgVoiceDao.java │ │ │ │ ├── WxBaseMsgDao.java │ │ │ │ ├── WxMsgLocDao.java │ │ │ │ ├── WxMsgLinkDao.java │ │ │ │ ├── WxMsgTextDao.java │ │ │ │ ├── WxMsgEventDao.java │ │ │ │ ├── WxMsgImageDao.java │ │ │ │ └── WxMsgVideoDao.java │ │ │ ├── resp │ │ │ │ ├── WxRespVideoDao.java │ │ │ │ ├── WxRespTextDao.java │ │ │ │ ├── WxRespImageDao.java │ │ │ │ ├── WxRespMusicDao.java │ │ │ │ ├── WxRespPicDescDao.java │ │ │ │ └── WxRespVoiceDao.java │ │ │ ├── auth │ │ │ │ ├── WxAuthDao.java │ │ │ │ └── WxAuthReqDao.java │ │ │ ├── user │ │ │ │ ├── WxUserDao.java │ │ │ │ └── WxGroupDao.java │ │ │ ├── menu │ │ │ │ └── WxMenuBtnDao.java │ │ │ └── item │ │ │ │ ├── WxItemImageDao.java │ │ │ │ ├── WxItemMusicDao.java │ │ │ │ ├── WxItemThumbDao.java │ │ │ │ ├── WxItemVideoDao.java │ │ │ │ ├── WxItemVoiceDao.java │ │ │ │ └── WxItemPicDescDao.java │ │ └── entity │ │ │ ├── base │ │ │ ├── WxBaseItemMediaEntity.java │ │ │ ├── WxBaseEntity.java │ │ │ ├── WxBaseRespEntity.java │ │ │ └── WxBaseMsgEntity.java │ │ │ ├── resp │ │ │ ├── WxRespTextEntity.java │ │ │ ├── WxRespImageEntity.java │ │ │ ├── WxRespVideoEntity.java │ │ │ ├── WxRespVoiceEntity.java │ │ │ ├── WxRespPicDescEntity.java │ │ │ └── WxRespMusicEntity.java │ │ │ ├── item │ │ │ ├── WxItemThumbEntity.java │ │ │ ├── WxItemImageEntity.java │ │ │ ├── WxItemVoiceEntity.java │ │ │ ├── WxItemPicDescEntity.java │ │ │ ├── WxItemVideoEntity.java │ │ │ └── WxItemMusicEntity.java │ │ │ ├── auth │ │ │ ├── WxAuthReq.java │ │ │ └── WxAuth.java │ │ │ ├── msg │ │ │ ├── WxMsgTextEntity.java │ │ │ ├── WxMsgVoiceEntity.java │ │ │ ├── WxMsgVideoEntity.java │ │ │ ├── WxMsgImageEntity.java │ │ │ ├── WxMsgLinkEntity.java │ │ │ ├── WxMsgLocEntity.java │ │ │ └── WxMsgEventEntity.java │ │ │ ├── user │ │ │ ├── WxGroupEntity.java │ │ │ └── WxUserEntity.java │ │ │ ├── qr │ │ │ └── WxQrEntity.java │ │ │ └── menu │ │ │ └── WxMenuBtnEntity.java │ │ ├── service │ │ ├── handler │ │ │ └── WxMessageHandlerIfc.java │ │ ├── WxUserService.java │ │ ├── WxQrService.java │ │ ├── WxMenuService.java │ │ ├── WxAuthService.java │ │ ├── WxMediaService.java │ │ ├── WxMessageService.java │ │ ├── WxUserGroupService.java │ │ └── WxStorageService.java │ │ ├── exception │ │ └── WxException.java │ │ ├── controller │ │ ├── util │ │ │ ├── WxJsonUtil.java │ │ │ └── WxXmlUtil.java │ │ └── WxController.java │ │ ├── gson │ │ └── WxMenuBtnSerializer.java │ │ ├── config │ │ └── WxConfig.java │ │ └── util │ │ └── WxUtil.java │ └── resources │ ├── applicationContext-weixinmp.xml │ └── wx.properties ├── .gitignore ├── README.md ├── pom.xml └── LICENSE /src/test/resources/.gitignore: -------------------------------------------------------------------------------- 1 | /tmp 2 | -------------------------------------------------------------------------------- /src/test/resources/sql/import-data.sql: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | .project 3 | .settings/ 4 | .classpath 5 | /logs 6 | -------------------------------------------------------------------------------- /src/test/resources/media/cat.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grossopa/weixin-mp-java/HEAD/src/test/resources/media/cat.jpg -------------------------------------------------------------------------------- /src/main/java/org/hamster/weixinmp/model/qr/WxQrSceneJson.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package org.hamster.weixinmp.model.qr; 5 | 6 | import lombok.Data; 7 | 8 | /** 9 | * @author grossopaforever@gmail.com 10 | * @version Jan 4, 2014 11 | * 12 | */ 13 | @Data 14 | public class WxQrSceneJson { 15 | 16 | private Long scene_id; 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/org/hamster/weixinmp/model/qr/WxQrActionInfoJson.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package org.hamster.weixinmp.model.qr; 5 | 6 | import lombok.Data; 7 | 8 | /** 9 | * @author grossopaforever@gmail.com 10 | * @version Jan 4, 2014 11 | * 12 | */ 13 | @Data 14 | public class WxQrActionInfoJson { 15 | private WxQrSceneJson scene; 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/org/hamster/weixinmp/constant/WxMenuBtnType.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package org.hamster.weixinmp.constant; 5 | 6 | /** 7 | * @author grossopaforever@gmail.com 8 | * @version Jan 5, 2014 9 | * 10 | */ 11 | public class WxMenuBtnType { 12 | public static final String VIEW = "view"; 13 | public static final String CLICK = "click"; 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/org/hamster/weixinmp/model/user/WxOpenIdListJson.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package org.hamster.weixinmp.model.user; 5 | 6 | import java.util.List; 7 | 8 | import lombok.Data; 9 | 10 | /** 11 | * @author grossopaforever@gmail.com 12 | * @version Jan 4, 2014 13 | * 14 | */ 15 | @Data 16 | public class WxOpenIdListJson { 17 | private List openid; 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/org/hamster/weixinmp/model/menu/WxMenuGetJson.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package org.hamster.weixinmp.model.menu; 5 | 6 | import lombok.AllArgsConstructor; 7 | import lombok.Data; 8 | 9 | /** 10 | * @author grossopaforever@gmail.com 11 | * @version Jan 4, 2014 12 | * 13 | */ 14 | @Data 15 | @AllArgsConstructor 16 | public class WxMenuGetJson { 17 | private WxMenuCreateJson menu; 18 | 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/org/hamster/weixinmp/model/qr/WxQrCreateJson.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package org.hamster.weixinmp.model.qr; 5 | 6 | import lombok.Data; 7 | 8 | /** 9 | * @author grossopaforever@gmail.com 10 | * @version Jan 4, 2014 11 | * 12 | */ 13 | @Data 14 | public class WxQrCreateJson { 15 | private String action_name; 16 | private Long expire_seconds; 17 | private WxQrActionInfoJson action_info; 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/org/hamster/weixinmp/model/send/item/SendItemTextJson.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package org.hamster.weixinmp.model.send.item; 5 | 6 | import lombok.AllArgsConstructor; 7 | import lombok.Data; 8 | import lombok.NoArgsConstructor; 9 | 10 | /** 11 | * @author grossopaforever@gmail.com 12 | * @version Dec 30, 2013 13 | * 14 | */ 15 | @Data 16 | @NoArgsConstructor 17 | @AllArgsConstructor 18 | public class SendItemTextJson { 19 | private String text; 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/org/hamster/weixinmp/model/WxRespCode.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package org.hamster.weixinmp.model; 5 | 6 | import lombok.AllArgsConstructor; 7 | import lombok.Data; 8 | import lombok.NoArgsConstructor; 9 | 10 | /** 11 | * @author grossopaforever@gmail.com 12 | * @version Aug 4, 2013 13 | * 14 | */ 15 | @Data 16 | @NoArgsConstructor 17 | @AllArgsConstructor 18 | public class WxRespCode { 19 | private Integer errcode; 20 | private String errmsg; 21 | 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/org/hamster/weixinmp/model/send/item/SendItemImageJson.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package org.hamster.weixinmp.model.send.item; 5 | 6 | import lombok.AllArgsConstructor; 7 | import lombok.Data; 8 | import lombok.NoArgsConstructor; 9 | 10 | /** 11 | * @author grossopaforever@gmail.com 12 | * @version Dec 30, 2013 13 | * 14 | */ 15 | @Data 16 | @NoArgsConstructor 17 | @AllArgsConstructor 18 | public class SendItemImageJson { 19 | private String mediaId; 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/org/hamster/weixinmp/model/send/item/SendItemVoiceJson.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package org.hamster.weixinmp.model.send.item; 5 | 6 | import lombok.AllArgsConstructor; 7 | import lombok.Data; 8 | import lombok.NoArgsConstructor; 9 | 10 | /** 11 | * @author grossopaforever@gmail.com 12 | * @version Dec 30, 2013 13 | * 14 | */ 15 | @Data 16 | @NoArgsConstructor 17 | @AllArgsConstructor 18 | public class SendItemVoiceJson { 19 | private String mediaId; 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/org/hamster/weixinmp/dao/repository/msg/WxMsgVoiceDao.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package org.hamster.weixinmp.dao.repository.msg; 5 | 6 | import org.hamster.weixinmp.dao.entity.msg.WxMsgVoiceEntity; 7 | import org.springframework.data.repository.PagingAndSortingRepository; 8 | 9 | /** 10 | * @author grossopaforever@gmail.com 11 | * @version Jan 5, 2014 12 | * 13 | */ 14 | public interface WxMsgVoiceDao extends PagingAndSortingRepository { 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/org/hamster/weixinmp/dao/repository/resp/WxRespVideoDao.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package org.hamster.weixinmp.dao.repository.resp; 5 | 6 | import org.hamster.weixinmp.dao.entity.resp.WxRespVideoEntity; 7 | import org.springframework.data.repository.PagingAndSortingRepository; 8 | 9 | 10 | /** 11 | * @author grossopaforever@gmail.com 12 | * @version Jul 28, 2013 13 | * 14 | */ 15 | public interface WxRespVideoDao extends PagingAndSortingRepository { 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/org/hamster/weixinmp/dao/repository/resp/WxRespTextDao.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package org.hamster.weixinmp.dao.repository.resp; 5 | 6 | import org.hamster.weixinmp.dao.entity.resp.WxRespTextEntity; 7 | import org.springframework.data.repository.PagingAndSortingRepository; 8 | 9 | 10 | /** 11 | * @author grossopaforever@gmail.com 12 | * @version Jul 28, 2013 13 | * 14 | */ 15 | public interface WxRespTextDao extends PagingAndSortingRepository { 16 | 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/org/hamster/weixinmp/dao/repository/resp/WxRespImageDao.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package org.hamster.weixinmp.dao.repository.resp; 5 | 6 | import org.hamster.weixinmp.dao.entity.resp.WxRespImageEntity; 7 | import org.springframework.data.repository.PagingAndSortingRepository; 8 | 9 | 10 | /** 11 | * @author grossopaforever@gmail.com 12 | * @version Jul 28, 2013 13 | * 14 | */ 15 | public interface WxRespImageDao extends PagingAndSortingRepository { 16 | 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/org/hamster/weixinmp/dao/repository/resp/WxRespMusicDao.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package org.hamster.weixinmp.dao.repository.resp; 5 | 6 | import org.hamster.weixinmp.dao.entity.resp.WxRespMusicEntity; 7 | import org.springframework.data.repository.PagingAndSortingRepository; 8 | 9 | 10 | /** 11 | * @author grossopaforever@gmail.com 12 | * @version Jul 28, 2013 13 | * 14 | */ 15 | public interface WxRespMusicDao extends PagingAndSortingRepository { 16 | 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/org/hamster/weixinmp/dao/repository/resp/WxRespPicDescDao.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package org.hamster.weixinmp.dao.repository.resp; 5 | 6 | import org.hamster.weixinmp.dao.entity.resp.WxRespPicDescEntity; 7 | import org.springframework.data.repository.PagingAndSortingRepository; 8 | 9 | 10 | /** 11 | * @author grossopaforever@gmail.com 12 | * @version Jul 28, 2013 13 | * 14 | */ 15 | public interface WxRespPicDescDao extends PagingAndSortingRepository { 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/org/hamster/weixinmp/model/WxAccessTokenJson.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package org.hamster.weixinmp.model; 5 | 6 | import lombok.AllArgsConstructor; 7 | import lombok.Data; 8 | import lombok.NoArgsConstructor; 9 | 10 | /** 11 | * @author grossopaforever@gmail.com 12 | * @version Aug 4, 2013 13 | * 14 | */ 15 | @Data 16 | @NoArgsConstructor 17 | @AllArgsConstructor 18 | public class WxAccessTokenJson { 19 | 20 | private String access_token; 21 | private String expires_in; 22 | 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/org/hamster/weixinmp/model/user/WxUserGetJson.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package org.hamster.weixinmp.model.user; 5 | 6 | import lombok.Data; 7 | 8 | /** 9 | * {"total":2,"count":2,"data":{"openid":["","OPENID1","OPENID2"]},"next_openid":"NEXT_OPENID"} 10 | * 11 | * @author grossopaforever@gmail.com 12 | * @version Jan 4, 2014 13 | * 14 | */ 15 | @Data 16 | public class WxUserGetJson { 17 | private Long total; 18 | private Long count; 19 | WxOpenIdListJson data; 20 | private String next_openid; 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/org/hamster/weixinmp/model/menu/WxMenuCreateJson.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package org.hamster.weixinmp.model.menu; 5 | 6 | import java.util.List; 7 | 8 | import lombok.AllArgsConstructor; 9 | import lombok.Data; 10 | 11 | import org.hamster.weixinmp.dao.entity.menu.WxMenuBtnEntity; 12 | 13 | /** 14 | * @author grossopaforever@gmail.com 15 | * @version Aug 4, 2013 16 | * 17 | */ 18 | @Data 19 | @AllArgsConstructor 20 | public class WxMenuCreateJson { 21 | 22 | private List button; 23 | 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/org/hamster/weixinmp/dao/repository/auth/WxAuthDao.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package org.hamster.weixinmp.dao.repository.auth; 5 | 6 | import org.hamster.weixinmp.dao.entity.auth.WxAuth; 7 | import org.springframework.data.repository.PagingAndSortingRepository; 8 | import org.springframework.stereotype.Repository; 9 | 10 | /** 11 | * @author grossopaforever@gmail.com 12 | * @version Aug 4, 2013 13 | * 14 | */ 15 | @Repository 16 | public interface WxAuthDao extends PagingAndSortingRepository { 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/org/hamster/weixinmp/model/send/item/SendItemVideoJson.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package org.hamster.weixinmp.model.send.item; 5 | 6 | import lombok.AllArgsConstructor; 7 | import lombok.Data; 8 | import lombok.NoArgsConstructor; 9 | 10 | /** 11 | * @author grossopaforever@gmail.com 12 | * @version Dec 30, 2013 13 | * 14 | */ 15 | @Data 16 | @NoArgsConstructor 17 | @AllArgsConstructor 18 | public class SendItemVideoJson { 19 | private String mediaId; 20 | private String title; 21 | private String description; 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/org/hamster/weixinmp/constant/WxMsgRespType.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package org.hamster.weixinmp.constant; 5 | 6 | /** 7 | * @author grossopaforever@gmail.com 8 | * @version Jan 5, 2014 9 | * 10 | */ 11 | public class WxMsgRespType { 12 | public static final String TEXT = "text"; 13 | public static final String IMAGE = "image"; 14 | public static final String VOICE = "voice"; 15 | public static final String VIDEO = "video"; 16 | public static final String MUSIC = "music"; 17 | public static final String NEWS = "news"; 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/org/hamster/weixinmp/constant/WxMsgEventType.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package org.hamster.weixinmp.constant; 5 | 6 | /** 7 | * @author grossopaforever@gmail.com 8 | * @version Dec 30, 2013 9 | * 10 | */ 11 | public class WxMsgEventType { 12 | public static final String SUBSCRIBE = "subscribe"; 13 | public static final String UNSUBSCRIBE = "unsubscribe"; 14 | public static final String SCAN = "scan"; 15 | public static final String LOCATION = "LOCATION"; // wtf?? 16 | public static final String CLICK = "CLICK"; // wtf?? 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/org/hamster/weixinmp/dao/repository/auth/WxAuthReqDao.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package org.hamster.weixinmp.dao.repository.auth; 5 | 6 | import org.hamster.weixinmp.dao.entity.auth.WxAuthReq; 7 | import org.springframework.data.repository.PagingAndSortingRepository; 8 | import org.springframework.stereotype.Repository; 9 | 10 | 11 | /** 12 | * @author grossopaforever@gmail.com 13 | * @version Jul 28, 2013 14 | * 15 | */ 16 | @Repository 17 | public interface WxAuthReqDao extends PagingAndSortingRepository { 18 | 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/org/hamster/weixinmp/dao/repository/user/WxUserDao.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package org.hamster.weixinmp.dao.repository.user; 5 | 6 | import org.hamster.weixinmp.dao.entity.user.WxUserEntity; 7 | import org.springframework.data.repository.PagingAndSortingRepository; 8 | import org.springframework.stereotype.Repository; 9 | 10 | 11 | /** 12 | * @author grossopaforever@gmail.com 13 | * @version Jul 28, 2013 14 | * 15 | * 16 | */ 17 | @Repository 18 | public interface WxUserDao extends PagingAndSortingRepository { 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/org/hamster/weixinmp/dao/repository/menu/WxMenuBtnDao.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package org.hamster.weixinmp.dao.repository.menu; 5 | 6 | import org.hamster.weixinmp.dao.entity.menu.WxMenuBtnEntity; 7 | import org.springframework.data.repository.PagingAndSortingRepository; 8 | import org.springframework.stereotype.Repository; 9 | 10 | /** 11 | * @author grossopaforever@gmail.com 12 | * @version Aug 4, 2013 13 | * 14 | */ 15 | @Repository 16 | public interface WxMenuBtnDao extends PagingAndSortingRepository { 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/org/hamster/weixinmp/dao/repository/msg/WxBaseMsgDao.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package org.hamster.weixinmp.dao.repository.msg; 5 | 6 | import org.hamster.weixinmp.dao.entity.base.WxBaseMsgEntity; 7 | import org.springframework.data.repository.PagingAndSortingRepository; 8 | import org.springframework.stereotype.Repository; 9 | 10 | /** 11 | * @author grossopaforever@gmail.com 12 | * @version Dec 30, 2013 13 | * 14 | */ 15 | @Repository 16 | public interface WxBaseMsgDao extends PagingAndSortingRepository { 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/org/hamster/weixinmp/dao/repository/msg/WxMsgLocDao.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package org.hamster.weixinmp.dao.repository.msg; 5 | 6 | import org.hamster.weixinmp.dao.entity.msg.WxMsgLocEntity; 7 | import org.springframework.data.repository.PagingAndSortingRepository; 8 | import org.springframework.stereotype.Repository; 9 | 10 | 11 | /** 12 | * @author grossopaforever@gmail.com 13 | * @version Jul 28, 2013 14 | * 15 | */ 16 | @Repository 17 | public interface WxMsgLocDao extends PagingAndSortingRepository { 18 | 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/org/hamster/weixinmp/dao/repository/user/WxGroupDao.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package org.hamster.weixinmp.dao.repository.user; 5 | 6 | import org.hamster.weixinmp.dao.entity.user.WxGroupEntity; 7 | import org.springframework.data.repository.PagingAndSortingRepository; 8 | import org.springframework.stereotype.Repository; 9 | 10 | 11 | /** 12 | * @author grossopaforever@gmail.com 13 | * @version Jul 28, 2013 14 | * 15 | * 16 | */ 17 | @Repository 18 | public interface WxGroupDao extends PagingAndSortingRepository { 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/org/hamster/weixinmp/dao/repository/msg/WxMsgLinkDao.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package org.hamster.weixinmp.dao.repository.msg; 5 | 6 | import org.hamster.weixinmp.dao.entity.msg.WxMsgLinkEntity; 7 | import org.springframework.data.repository.PagingAndSortingRepository; 8 | import org.springframework.stereotype.Repository; 9 | 10 | 11 | /** 12 | * @author grossopaforever@gmail.com 13 | * @version Jul 28, 2013 14 | * 15 | */ 16 | @Repository 17 | public interface WxMsgLinkDao extends PagingAndSortingRepository { 18 | 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/org/hamster/weixinmp/dao/repository/msg/WxMsgTextDao.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package org.hamster.weixinmp.dao.repository.msg; 5 | 6 | import org.hamster.weixinmp.dao.entity.msg.WxMsgTextEntity; 7 | import org.springframework.data.repository.PagingAndSortingRepository; 8 | import org.springframework.stereotype.Repository; 9 | 10 | 11 | /** 12 | * @author grossopaforever@gmail.com 13 | * @version Jul 28, 2013 14 | * 15 | */ 16 | @Repository 17 | public interface WxMsgTextDao extends PagingAndSortingRepository { 18 | 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/org/hamster/weixinmp/model/send/item/SendItemArticleJson.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package org.hamster.weixinmp.model.send.item; 5 | 6 | import lombok.AllArgsConstructor; 7 | import lombok.Data; 8 | import lombok.NoArgsConstructor; 9 | 10 | /** 11 | * @author grossopaforever@gmail.com 12 | * @version Dec 30, 2013 13 | * 14 | */ 15 | @Data 16 | @NoArgsConstructor 17 | @AllArgsConstructor 18 | public class SendItemArticleJson { 19 | private String title; 20 | private String description; 21 | private String url; 22 | private String picurl; 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/org/hamster/weixinmp/dao/entity/base/WxBaseItemMediaEntity.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package org.hamster.weixinmp.dao.entity.base; 5 | 6 | import javax.persistence.MappedSuperclass; 7 | 8 | import lombok.Data; 9 | import lombok.EqualsAndHashCode; 10 | import lombok.ToString; 11 | 12 | /** 13 | * @author grossopaforever@gmail.com 14 | * @version Dec 29, 2013 15 | * 16 | */ 17 | 18 | @MappedSuperclass 19 | @Data 20 | @ToString(callSuper = true) 21 | @EqualsAndHashCode(callSuper = true) 22 | public class WxBaseItemMediaEntity extends WxBaseEntity { 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/org/hamster/weixinmp/dao/repository/msg/WxMsgEventDao.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package org.hamster.weixinmp.dao.repository.msg; 5 | 6 | import org.hamster.weixinmp.dao.entity.msg.WxMsgEventEntity; 7 | import org.springframework.data.repository.PagingAndSortingRepository; 8 | import org.springframework.stereotype.Repository; 9 | 10 | 11 | /** 12 | * @author grossopaforever@gmail.com 13 | * @version Jul 28, 2013 14 | * 15 | */ 16 | @Repository 17 | public interface WxMsgEventDao extends PagingAndSortingRepository { 18 | 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/org/hamster/weixinmp/dao/repository/msg/WxMsgImageDao.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package org.hamster.weixinmp.dao.repository.msg; 5 | 6 | import org.hamster.weixinmp.dao.entity.msg.WxMsgImageEntity; 7 | import org.springframework.data.repository.PagingAndSortingRepository; 8 | import org.springframework.stereotype.Repository; 9 | 10 | 11 | /** 12 | * @author grossopaforever@gmail.com 13 | * @version Jul 28, 2013 14 | * 15 | */ 16 | @Repository 17 | public interface WxMsgImageDao extends PagingAndSortingRepository { 18 | 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/org/hamster/weixinmp/dao/repository/msg/WxMsgVideoDao.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package org.hamster.weixinmp.dao.repository.msg; 5 | 6 | import org.hamster.weixinmp.dao.entity.msg.WxMsgVideoEntity; 7 | import org.springframework.data.repository.PagingAndSortingRepository; 8 | import org.springframework.stereotype.Repository; 9 | 10 | 11 | /** 12 | * @author grossopaforever@gmail.com 13 | * @version Jul 28, 2013 14 | * 15 | */ 16 | @Repository 17 | public interface WxMsgVideoDao extends PagingAndSortingRepository { 18 | 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/org/hamster/weixinmp/dao/repository/resp/WxRespVoiceDao.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package org.hamster.weixinmp.dao.repository.resp; 5 | 6 | import org.hamster.weixinmp.dao.entity.resp.WxRespVoiceEntity; 7 | import org.springframework.data.repository.PagingAndSortingRepository; 8 | import org.springframework.stereotype.Repository; 9 | 10 | 11 | /** 12 | * @author grossopaforever@gmail.com 13 | * @version Jul 28, 2013 14 | * 15 | */ 16 | @Repository 17 | public interface WxRespVoiceDao extends PagingAndSortingRepository { 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/org/hamster/weixinmp/dao/repository/item/WxItemImageDao.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package org.hamster.weixinmp.dao.repository.item; 5 | 6 | import org.hamster.weixinmp.dao.entity.item.WxItemImageEntity; 7 | import org.springframework.data.repository.PagingAndSortingRepository; 8 | import org.springframework.stereotype.Repository; 9 | 10 | /** 11 | * @author grossopaforever@gmail.com 12 | * @version Jan 5, 2014 13 | * 14 | */ 15 | @Repository 16 | public interface WxItemImageDao extends 17 | PagingAndSortingRepository { 18 | 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/org/hamster/weixinmp/dao/repository/item/WxItemMusicDao.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package org.hamster.weixinmp.dao.repository.item; 5 | 6 | import org.hamster.weixinmp.dao.entity.item.WxItemMusicEntity; 7 | import org.springframework.data.repository.PagingAndSortingRepository; 8 | import org.springframework.stereotype.Repository; 9 | 10 | 11 | /** 12 | * @author grossopaforever@gmail.com 13 | * @version Jul 28, 2013 14 | * 15 | */ 16 | @Repository 17 | public interface WxItemMusicDao extends PagingAndSortingRepository { 18 | 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/org/hamster/weixinmp/dao/repository/item/WxItemThumbDao.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package org.hamster.weixinmp.dao.repository.item; 5 | 6 | import org.hamster.weixinmp.dao.entity.item.WxItemThumbEntity; 7 | import org.springframework.data.repository.PagingAndSortingRepository; 8 | import org.springframework.stereotype.Repository; 9 | 10 | /** 11 | * @author grossopaforever@gmail.com 12 | * @version Jan 5, 2014 13 | * 14 | */ 15 | @Repository 16 | public interface WxItemThumbDao extends 17 | PagingAndSortingRepository { 18 | 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/org/hamster/weixinmp/dao/repository/item/WxItemVideoDao.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package org.hamster.weixinmp.dao.repository.item; 5 | 6 | import org.hamster.weixinmp.dao.entity.item.WxItemVideoEntity; 7 | import org.springframework.data.repository.PagingAndSortingRepository; 8 | import org.springframework.stereotype.Repository; 9 | 10 | /** 11 | * @author grossopaforever@gmail.com 12 | * @version Jan 5, 2014 13 | * 14 | */ 15 | @Repository 16 | public interface WxItemVideoDao extends 17 | PagingAndSortingRepository { 18 | 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/org/hamster/weixinmp/dao/repository/item/WxItemVoiceDao.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package org.hamster.weixinmp.dao.repository.item; 5 | 6 | import org.hamster.weixinmp.dao.entity.item.WxItemVoiceEntity; 7 | import org.springframework.data.repository.PagingAndSortingRepository; 8 | import org.springframework.stereotype.Repository; 9 | 10 | /** 11 | * @author grossopaforever@gmail.com 12 | * @version Jan 5, 2014 13 | * 14 | */ 15 | @Repository 16 | public interface WxItemVoiceDao extends 17 | PagingAndSortingRepository { 18 | 19 | } 20 | -------------------------------------------------------------------------------- /src/test/java/org/hamster/weixinmp/test/base/AbstractServiceTest.java: -------------------------------------------------------------------------------- 1 | package org.hamster.weixinmp.test.base; 2 | 3 | import org.springframework.test.context.ContextConfiguration; 4 | import org.springframework.test.context.junit4.AbstractJUnit4SpringContextTests; 5 | 6 | /** 7 | * @author grossopaforever@gmail.com 8 | * @version Mar 8, 2013 3:51:14 PM Change set 9 | */ 10 | @ContextConfiguration(locations = { "file:src/test/resources/applicationContext-test-weixinmp.xml"}) 11 | public abstract class AbstractServiceTest extends AbstractJUnit4SpringContextTests { 12 | 13 | 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/org/hamster/weixinmp/model/send/SendTextJson.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package org.hamster.weixinmp.model.send; 5 | 6 | import lombok.AllArgsConstructor; 7 | import lombok.Data; 8 | import lombok.NoArgsConstructor; 9 | 10 | import org.hamster.weixinmp.model.send.item.SendItemTextJson; 11 | 12 | /** 13 | * @author grossopaforever@gmail.com 14 | * @version Dec 30, 2013 15 | * 16 | */ 17 | @Data 18 | @NoArgsConstructor 19 | @AllArgsConstructor 20 | public class SendTextJson { 21 | private String touser; 22 | private String msgtype; 23 | private SendItemTextJson content; 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/org/hamster/weixinmp/model/send/SendVideoJson.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package org.hamster.weixinmp.model.send; 5 | 6 | import org.hamster.weixinmp.model.send.item.SendItemVoiceJson; 7 | 8 | import lombok.AllArgsConstructor; 9 | import lombok.Data; 10 | import lombok.NoArgsConstructor; 11 | 12 | /** 13 | * @author grossopaforever@gmail.com 14 | * @version Dec 30, 2013 15 | * 16 | */ 17 | @Data 18 | @NoArgsConstructor 19 | @AllArgsConstructor 20 | public class SendVideoJson { 21 | private String touser; 22 | private String msgtype; 23 | private SendItemVoiceJson voice; 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/org/hamster/weixinmp/model/send/SendVoiceJson.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package org.hamster.weixinmp.model.send; 5 | 6 | import lombok.AllArgsConstructor; 7 | import lombok.Data; 8 | import lombok.NoArgsConstructor; 9 | 10 | import org.hamster.weixinmp.model.send.item.SendItemVideoJson; 11 | 12 | /** 13 | * @author grossopaforever@gmail.com 14 | * @version Dec 30, 2013 15 | * 16 | */ 17 | @Data 18 | @NoArgsConstructor 19 | @AllArgsConstructor 20 | public class SendVoiceJson { 21 | private String touser; 22 | private String msgtype; 23 | private SendItemVideoJson video; 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/org/hamster/weixinmp/constant/WxMsgType.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package org.hamster.weixinmp.constant; 5 | 6 | /** 7 | * @author grossopaforever@gmail.com 8 | * @version Dec 30, 2013 9 | * 10 | */ 11 | public class WxMsgType { 12 | public static final String TEXT = "text"; 13 | public static final String IMAGE = "image"; 14 | public static final String LOCATION = "location"; 15 | public static final String LINK = "link"; 16 | public static final String EVENT = "event"; 17 | public static final String VIDEO = "video"; 18 | public static final String VOICE = "voice"; 19 | 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/org/hamster/weixinmp/model/send/SendImageJson.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package org.hamster.weixinmp.model.send; 5 | 6 | import org.hamster.weixinmp.model.send.item.SendItemImageJson; 7 | 8 | import lombok.AllArgsConstructor; 9 | import lombok.Data; 10 | import lombok.NoArgsConstructor; 11 | 12 | /** 13 | * @author grossopaforever@gmail.com 14 | * @version Dec 30, 2013 15 | * 16 | */ 17 | @Data 18 | @NoArgsConstructor 19 | @AllArgsConstructor 20 | public class SendImageJson { 21 | private String touser; 22 | private String msgtype; 23 | private SendItemImageJson image; 24 | 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/org/hamster/weixinmp/model/send/SendMusicJson.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package org.hamster.weixinmp.model.send; 5 | 6 | import org.hamster.weixinmp.model.send.item.SendItemMusicJson; 7 | 8 | import lombok.AllArgsConstructor; 9 | import lombok.Data; 10 | import lombok.NoArgsConstructor; 11 | 12 | /** 13 | * @author grossopaforever@gmail.com 14 | * @version Dec 30, 2013 15 | * 16 | */ 17 | @Data 18 | @NoArgsConstructor 19 | @AllArgsConstructor 20 | public class SendMusicJson { 21 | private String touser; 22 | private String msgtype; 23 | private SendItemMusicJson music; 24 | 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/org/hamster/weixinmp/model/send/item/SendItemMusicJson.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package org.hamster.weixinmp.model.send.item; 5 | 6 | import lombok.AllArgsConstructor; 7 | import lombok.Data; 8 | import lombok.NoArgsConstructor; 9 | 10 | /** 11 | * @author grossopaforever@gmail.com 12 | * @version Dec 30, 2013 13 | * 14 | */ 15 | @Data 16 | @NoArgsConstructor 17 | @AllArgsConstructor 18 | public class SendItemMusicJson { 19 | private String title; 20 | private String description; 21 | private String musicurl; 22 | private String hqmusicurl; 23 | private String thumb_media_id; 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/org/hamster/weixinmp/model/send/SendItemPicDescJson.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package org.hamster.weixinmp.model.send; 5 | 6 | import lombok.AllArgsConstructor; 7 | import lombok.Data; 8 | import lombok.NoArgsConstructor; 9 | 10 | import org.hamster.weixinmp.model.send.item.wrapper.WxSendItemArticleWrapper; 11 | 12 | /** 13 | * @author grossopaforever@gmail.com 14 | * @version Dec 30, 2013 15 | * 16 | */ 17 | @Data 18 | @NoArgsConstructor 19 | @AllArgsConstructor 20 | public class SendItemPicDescJson { 21 | private String touser; 22 | private String msgtype; 23 | private WxSendItemArticleWrapper news; 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/org/hamster/weixinmp/model/send/item/wrapper/WxSendItemArticleWrapper.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package org.hamster.weixinmp.model.send.item.wrapper; 5 | 6 | import java.util.List; 7 | 8 | import lombok.AllArgsConstructor; 9 | import lombok.Data; 10 | import lombok.NoArgsConstructor; 11 | 12 | import org.hamster.weixinmp.model.send.item.SendItemArticleJson; 13 | 14 | /** 15 | * @author grossopaforever@gmail.com 16 | * @version Dec 30, 2013 17 | * 18 | */ 19 | @Data 20 | @NoArgsConstructor 21 | @AllArgsConstructor 22 | public class WxSendItemArticleWrapper { 23 | 24 | private List articles; 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/org/hamster/weixinmp/constant/WxMediaType.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package org.hamster.weixinmp.constant; 5 | 6 | /** 7 | * @author grossopaforever@gmail.com 8 | * @version Dec 29, 2013 9 | * 10 | */ 11 | public class WxMediaType { 12 | 13 | public static final String VIDEO = "Video"; 14 | public static final String VOICE = "Voice"; 15 | public static final String MUSIC = "Music"; 16 | public static final String THUMB = "Thumb"; 17 | public static final String IMAGE = "Image"; 18 | public static final String PIC_DESC = "Article"; 19 | public static final String DEFAULT = "Default"; 20 | 21 | private WxMediaType() { 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/org/hamster/weixinmp/service/handler/WxMessageHandlerIfc.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package org.hamster.weixinmp.service.handler; 5 | 6 | import java.util.Map; 7 | 8 | import org.hamster.weixinmp.constant.WxMsgTypeEnum; 9 | import org.hamster.weixinmp.dao.entity.base.WxBaseMsgEntity; 10 | import org.hamster.weixinmp.dao.entity.base.WxBaseRespEntity; 11 | 12 | /** 13 | * @author grossopaforever@gmail.com 14 | * @version Jan 5, 2014 15 | * 16 | */ 17 | public interface WxMessageHandlerIfc { 18 | 19 | WxMsgTypeEnum[] listIntetestedMessageType(); 20 | 21 | WxBaseRespEntity handle(WxBaseMsgEntity msg, Map context); 22 | 23 | Integer priority(); 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/org/hamster/weixinmp/dao/repository/item/WxItemPicDescDao.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package org.hamster.weixinmp.dao.repository.item; 5 | 6 | import java.util.List; 7 | 8 | import org.hamster.weixinmp.dao.entity.item.WxItemPicDescEntity; 9 | import org.springframework.data.repository.PagingAndSortingRepository; 10 | import org.springframework.stereotype.Repository; 11 | 12 | 13 | /** 14 | * @author grossopaforever@gmail.com 15 | * @version Jul 28, 2013 16 | * 17 | */ 18 | @Repository 19 | public interface WxItemPicDescDao extends PagingAndSortingRepository { 20 | /** 21 | * 22 | * @param ids 23 | * @return 24 | */ 25 | List findByIdIn(List ids); 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/org/hamster/weixinmp/constant/WxMenuBtnTypeEnum.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package org.hamster.weixinmp.constant; 5 | 6 | /** 7 | * @author grossopaforever@gmail.com 8 | * @version Jan 4, 2014 9 | * 10 | */ 11 | public enum WxMenuBtnTypeEnum { 12 | VIEW(WxMenuBtnType.VIEW), CLICK(WxMenuBtnType.CLICK); 13 | /** 14 | * @param text 15 | */ 16 | WxMenuBtnTypeEnum(final String text) { 17 | this._text = text; 18 | } 19 | 20 | private final String _text; 21 | 22 | /* 23 | * (non-Javadoc) 24 | * 25 | * @see java.lang.Enum#toString() 26 | */ 27 | @Override 28 | public String toString() { 29 | return _text; 30 | } 31 | 32 | public static WxMenuBtnTypeEnum inst(String strVal) { 33 | for (WxMenuBtnTypeEnum type : WxMenuBtnTypeEnum.values()) { 34 | if (type.toString().equalsIgnoreCase(strVal)) { 35 | return type; 36 | } 37 | } 38 | return null; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/org/hamster/weixinmp/dao/entity/resp/WxRespTextEntity.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package org.hamster.weixinmp.dao.entity.resp; 5 | 6 | import javax.persistence.Column; 7 | import javax.persistence.Entity; 8 | import javax.persistence.Table; 9 | 10 | import lombok.Data; 11 | import lombok.EqualsAndHashCode; 12 | import lombok.ToString; 13 | 14 | import org.hamster.weixinmp.config.WxConfig; 15 | import org.hamster.weixinmp.dao.entity.base.WxBaseRespEntity; 16 | 17 | 18 | /** 19 | * @author grossopaforever@gmail.com 20 | * @version Jul 28, 2013 21 | * 22 | */ 23 | @Entity 24 | @Table(name = WxConfig.TABLE_PREFIX + "resp_text") 25 | @Data 26 | @ToString(callSuper = true) 27 | @EqualsAndHashCode(callSuper = true) 28 | public class WxRespTextEntity extends WxBaseRespEntity { 29 | @Column(name = "content", length = WxConfig.COL_LEN_CONTENT, nullable = false) 30 | private String content; 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/org/hamster/weixinmp/dao/entity/item/WxItemThumbEntity.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package org.hamster.weixinmp.dao.entity.item; 5 | 6 | import javax.persistence.Column; 7 | import javax.persistence.Entity; 8 | import javax.persistence.Table; 9 | 10 | import lombok.Data; 11 | import lombok.EqualsAndHashCode; 12 | import lombok.ToString; 13 | 14 | import org.hamster.weixinmp.config.WxConfig; 15 | import org.hamster.weixinmp.dao.entity.base.WxBaseItemMediaEntity; 16 | 17 | /** 18 | * @author grossopaforever@gmail.com 19 | * @version Dec 29, 2013 20 | * 21 | */ 22 | @Entity 23 | @Table(name=WxConfig.TABLE_PREFIX + "item_thumb") 24 | @Data 25 | @ToString(callSuper = true) 26 | @EqualsAndHashCode(callSuper = true) 27 | public class WxItemThumbEntity extends WxBaseItemMediaEntity { 28 | @Column(name = "media_id", length = WxConfig.COL_LEN_INDICATOR, nullable = true) 29 | private String mediaId; 30 | } 31 | -------------------------------------------------------------------------------- /src/test/java/org/hamster/weixinmp/test/service/WxQrServiceTest.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package org.hamster.weixinmp.test.service; 5 | 6 | import org.hamster.weixinmp.exception.WxException; 7 | import org.hamster.weixinmp.service.WxAuthService; 8 | import org.hamster.weixinmp.service.WxQrService; 9 | import org.hamster.weixinmp.test.base.AbstractWxServiceTest; 10 | import org.junit.Test; 11 | import org.springframework.beans.factory.annotation.Autowired; 12 | 13 | /** 14 | * @author grossopaforever@gmail.com 15 | * @version Jan 5, 2014 16 | * 17 | */ 18 | public class WxQrServiceTest extends AbstractWxServiceTest { 19 | 20 | @Autowired 21 | WxAuthService authService; 22 | 23 | @Autowired 24 | WxQrService qrService; 25 | 26 | @Test 27 | public void testAll() throws WxException { 28 | qrService.remoteQrcodeCreate(accessToken, true, 10000l, 1800l); 29 | qrService.remoteQrcodeCreate(accessToken, false, 500l, null); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/test/java/org/hamster/weixinmp/test/service/WxUserServiceTest.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package org.hamster.weixinmp.test.service; 5 | 6 | import org.hamster.weixinmp.exception.WxException; 7 | import org.hamster.weixinmp.model.user.WxUserGetJson; 8 | import org.hamster.weixinmp.service.WxAuthService; 9 | import org.hamster.weixinmp.service.WxUserService; 10 | import org.hamster.weixinmp.test.base.AbstractWxServiceTest; 11 | import org.junit.Test; 12 | import org.springframework.beans.factory.annotation.Autowired; 13 | 14 | /** 15 | * @author grossopaforever@gmail.com 16 | * @version Jan 4, 2014 17 | * 18 | */ 19 | public class WxUserServiceTest extends AbstractWxServiceTest { 20 | 21 | @Autowired 22 | WxAuthService authService; 23 | @Autowired 24 | WxUserService userService; 25 | 26 | @Test 27 | public void testAll() throws WxException { 28 | WxUserGetJson userGet = userService.remoteUserGet(accessToken); 29 | System.out.println(userGet); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/org/hamster/weixinmp/dao/entity/resp/WxRespImageEntity.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package org.hamster.weixinmp.dao.entity.resp; 5 | 6 | import javax.persistence.Entity; 7 | import javax.persistence.JoinColumn; 8 | import javax.persistence.ManyToOne; 9 | import javax.persistence.Table; 10 | 11 | import lombok.Data; 12 | import lombok.EqualsAndHashCode; 13 | import lombok.ToString; 14 | 15 | import org.hamster.weixinmp.config.WxConfig; 16 | import org.hamster.weixinmp.dao.entity.base.WxBaseRespEntity; 17 | import org.hamster.weixinmp.dao.entity.item.WxItemImageEntity; 18 | 19 | /** 20 | * @author grossopaforever@gmail.com 21 | * @version Dec 29, 2013 22 | * 23 | */ 24 | @Entity 25 | @Table(name = WxConfig.TABLE_PREFIX + "resp_music") 26 | @Data 27 | @ToString(callSuper = true) 28 | @EqualsAndHashCode(callSuper = true) 29 | public class WxRespImageEntity extends WxBaseRespEntity { 30 | @ManyToOne 31 | @JoinColumn(name = "image_id") 32 | WxItemImageEntity image; 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/org/hamster/weixinmp/dao/entity/resp/WxRespVideoEntity.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package org.hamster.weixinmp.dao.entity.resp; 5 | 6 | import javax.persistence.Entity; 7 | import javax.persistence.JoinColumn; 8 | import javax.persistence.ManyToOne; 9 | import javax.persistence.Table; 10 | 11 | import lombok.Data; 12 | import lombok.EqualsAndHashCode; 13 | import lombok.ToString; 14 | 15 | import org.hamster.weixinmp.config.WxConfig; 16 | import org.hamster.weixinmp.dao.entity.base.WxBaseRespEntity; 17 | import org.hamster.weixinmp.dao.entity.item.WxItemVideoEntity; 18 | 19 | /** 20 | * @author grossopaforever@gmail.com 21 | * @version Dec 29, 2013 22 | * 23 | */ 24 | @Entity 25 | @Table(name = WxConfig.TABLE_PREFIX + "resp_video") 26 | @Data 27 | @ToString(callSuper = true) 28 | @EqualsAndHashCode(callSuper = true) 29 | public class WxRespVideoEntity extends WxBaseRespEntity { 30 | 31 | @ManyToOne 32 | @JoinColumn(name = "video_id") 33 | WxItemVideoEntity video; 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/org/hamster/weixinmp/dao/entity/resp/WxRespVoiceEntity.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package org.hamster.weixinmp.dao.entity.resp; 5 | 6 | import javax.persistence.Entity; 7 | import javax.persistence.JoinColumn; 8 | import javax.persistence.ManyToOne; 9 | import javax.persistence.Table; 10 | 11 | import lombok.Data; 12 | import lombok.EqualsAndHashCode; 13 | import lombok.ToString; 14 | 15 | import org.hamster.weixinmp.config.WxConfig; 16 | import org.hamster.weixinmp.dao.entity.base.WxBaseRespEntity; 17 | import org.hamster.weixinmp.dao.entity.item.WxItemVoiceEntity; 18 | 19 | /** 20 | * @author grossopaforever@gmail.com 21 | * @version Dec 29, 2013 22 | * 23 | */ 24 | @Entity 25 | @Table(name = WxConfig.TABLE_PREFIX + "resp_voice") 26 | @Data 27 | @ToString(callSuper = true) 28 | @EqualsAndHashCode(callSuper = true) 29 | public class WxRespVoiceEntity extends WxBaseRespEntity { 30 | 31 | @ManyToOne 32 | @JoinColumn(name = "voice_id") 33 | private WxItemVoiceEntity voice; 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/org/hamster/weixinmp/constant/WxMsgTypeEnum.java: -------------------------------------------------------------------------------- 1 | package org.hamster.weixinmp.constant; 2 | 3 | /** 4 | * @author grossopaforever@gmail.com 5 | * @version Jul 28, 2013 6 | * 7 | */ 8 | public enum WxMsgTypeEnum { 9 | 10 | 11 | TEXT(WxMsgType.TEXT), IMAGE(WxMsgType.IMAGE), LOCATION(WxMsgType.LOCATION), 12 | LINK(WxMsgType.LINK), EVENT(WxMsgType.EVENT), VIDEO(WxMsgType.VIDEO), VOICE(WxMsgType.VOICE); 13 | /** 14 | * @param text 15 | */ 16 | private WxMsgTypeEnum(final String text) { 17 | this._text = text; 18 | } 19 | 20 | private final String _text; 21 | 22 | /* 23 | * (non-Javadoc) 24 | * 25 | * @see java.lang.Enum#toString() 26 | */ 27 | @Override 28 | public String toString() { 29 | return _text; 30 | } 31 | 32 | public static WxMsgTypeEnum inst(String strVal) { 33 | for (WxMsgTypeEnum type : WxMsgTypeEnum.values()) { 34 | if (type.toString().equalsIgnoreCase(strVal)) { 35 | return type; 36 | } 37 | } 38 | return null; 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/org/hamster/weixinmp/dao/entity/item/WxItemImageEntity.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package org.hamster.weixinmp.dao.entity.item; 5 | 6 | import javax.persistence.Column; 7 | import javax.persistence.Entity; 8 | import javax.persistence.Table; 9 | 10 | import lombok.Data; 11 | import lombok.EqualsAndHashCode; 12 | import lombok.ToString; 13 | 14 | import org.hamster.weixinmp.config.WxConfig; 15 | import org.hamster.weixinmp.dao.entity.base.WxBaseItemMediaEntity; 16 | 17 | /** 18 | * @author grossopaforever@gmail.com 19 | * @version Dec 29, 2013 20 | * 21 | */ 22 | @Entity 23 | @Table(name=WxConfig.TABLE_PREFIX + "item_image") 24 | @Data 25 | @ToString(callSuper = true) 26 | @EqualsAndHashCode(callSuper = true) 27 | public class WxItemImageEntity extends WxBaseItemMediaEntity { 28 | @Column(name = "media_id", length = WxConfig.COL_LEN_INDICATOR, nullable = true) 29 | private String mediaId; 30 | @Column(name="pic_url", length=WxConfig.COL_LEN_URL, nullable=true) 31 | private String picUrl; 32 | } -------------------------------------------------------------------------------- /src/main/java/org/hamster/weixinmp/constant/WxMsgRespTypeEnum.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package org.hamster.weixinmp.constant; 5 | 6 | /** 7 | * @author grossopaforever@gmail.com 8 | * @version Jan 5, 2014 9 | * 10 | */ 11 | public enum WxMsgRespTypeEnum { 12 | TEXT(WxMsgRespType.TEXT), IMAGE(WxMsgRespType.IMAGE), MUSIC(WxMsgRespType.MUSIC), 13 | NEWS(WxMsgRespType.NEWS), VIDEO(WxMsgRespType.VIDEO), VOICE(WxMsgRespType.VOICE); 14 | /** 15 | * @param text 16 | */ 17 | private WxMsgRespTypeEnum(final String text) { 18 | this._text = text; 19 | } 20 | 21 | private final String _text; 22 | 23 | /* 24 | * (non-Javadoc) 25 | * 26 | * @see java.lang.Enum#toString() 27 | */ 28 | @Override 29 | public String toString() { 30 | return _text; 31 | } 32 | 33 | public static WxMsgRespTypeEnum inst(String strVal) { 34 | for (WxMsgRespTypeEnum type : WxMsgRespTypeEnum.values()) { 35 | if (type.toString().equalsIgnoreCase(strVal)) { 36 | return type; 37 | } 38 | } 39 | return null; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/org/hamster/weixinmp/dao/entity/auth/WxAuthReq.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package org.hamster.weixinmp.dao.entity.auth; 5 | 6 | import javax.persistence.Column; 7 | import javax.persistence.Entity; 8 | import javax.persistence.Table; 9 | 10 | import org.hamster.weixinmp.dao.entity.base.WxBaseEntity; 11 | 12 | import lombok.Data; 13 | import lombok.EqualsAndHashCode; 14 | import lombok.ToString; 15 | 16 | /** 17 | * @author grossopaforever@gmail.com 18 | * @version Jul 27, 2013 19 | */ 20 | @Entity 21 | @Table(name = "wx_auth_req") 22 | @Data 23 | @ToString 24 | @EqualsAndHashCode(callSuper = true) 25 | public class WxAuthReq extends WxBaseEntity { 26 | @Column(name = "signature", length = 100, nullable = false) 27 | private String signature; 28 | @Column(name = "timestamp", length = 50, nullable = false) 29 | private String timestamp; 30 | @Column(name = "nonce", length = 50, nullable = false) 31 | private String nonce; 32 | @Column(name = "echostr", length = 200, nullable = false) 33 | private String echostr; 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/org/hamster/weixinmp/dao/entity/msg/WxMsgTextEntity.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package org.hamster.weixinmp.dao.entity.msg; 5 | 6 | import javax.persistence.Column; 7 | import javax.persistence.DiscriminatorValue; 8 | import javax.persistence.Entity; 9 | import javax.persistence.Table; 10 | 11 | import org.hamster.weixinmp.config.WxConfig; 12 | import org.hamster.weixinmp.constant.WxMsgType; 13 | import org.hamster.weixinmp.dao.entity.base.WxBaseMsgEntity; 14 | 15 | import lombok.Data; 16 | import lombok.EqualsAndHashCode; 17 | import lombok.ToString; 18 | 19 | 20 | /** 21 | * @author grossopaforever@gmail.com 22 | * @version Jul 28, 2013 23 | * 24 | * 25 | */ 26 | @Entity 27 | @Table(name = WxConfig.TABLE_PREFIX + "msg_text") 28 | @DiscriminatorValue(WxMsgType.TEXT) 29 | @Data 30 | @ToString(callSuper = true) 31 | @EqualsAndHashCode(callSuper = true) 32 | public class WxMsgTextEntity extends WxBaseMsgEntity { 33 | @Column(name = "content", length = WxConfig.COL_LEN_CONTENT, nullable = false) 34 | private String content; 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/org/hamster/weixinmp/constant/WxMsgEventTypeEnum.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package org.hamster.weixinmp.constant; 5 | 6 | /** 7 | * @author grossopaforever@gmail.com 8 | * @version Jan 5, 2014 9 | * 10 | */ 11 | public enum WxMsgEventTypeEnum { 12 | SUBSCRIBE(WxMsgEventType.SUBSCRIBE), 13 | UNSUBSCRIBE(WxMsgEventType.UNSUBSCRIBE), 14 | SCAN(WxMsgEventType.SCAN), 15 | LOCATION(WxMsgEventType.LOCATION), 16 | CLICK(WxMsgEventType.CLICK); 17 | 18 | /** 19 | * @param text 20 | */ 21 | WxMsgEventTypeEnum(final String text) { 22 | this._text = text; 23 | } 24 | 25 | private final String _text; 26 | 27 | /* 28 | * (non-Javadoc) 29 | * 30 | * @see java.lang.Enum#toString() 31 | */ 32 | @Override 33 | public String toString() { 34 | return _text; 35 | } 36 | 37 | public static WxMsgEventTypeEnum inst(String strVal) { 38 | for (WxMsgEventTypeEnum type : WxMsgEventTypeEnum.values()) { 39 | if (type.toString().equalsIgnoreCase(strVal)) { 40 | return type; 41 | } 42 | } 43 | return null; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/org/hamster/weixinmp/dao/entity/resp/WxRespPicDescEntity.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package org.hamster.weixinmp.dao.entity.resp; 5 | 6 | import java.util.List; 7 | 8 | import javax.persistence.Entity; 9 | import javax.persistence.JoinTable; 10 | import javax.persistence.ManyToMany; 11 | import javax.persistence.Table; 12 | 13 | import org.hamster.weixinmp.config.WxConfig; 14 | import org.hamster.weixinmp.dao.entity.base.WxBaseRespEntity; 15 | import org.hamster.weixinmp.dao.entity.item.WxItemPicDescEntity; 16 | 17 | import lombok.Data; 18 | import lombok.EqualsAndHashCode; 19 | import lombok.ToString; 20 | 21 | 22 | /** 23 | * @author grossopaforever@gmail.com 24 | * @version Jul 28, 2013 25 | * 26 | */ 27 | @Entity 28 | @Table(name = WxConfig.TABLE_PREFIX + "resp_pic_desc") 29 | @Data 30 | @ToString(callSuper = true) 31 | @EqualsAndHashCode(callSuper = true) 32 | public class WxRespPicDescEntity extends WxBaseRespEntity { 33 | 34 | @ManyToMany 35 | @JoinTable(name = "wx_resp_pic_desc_item") 36 | private List articles; 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/org/hamster/weixinmp/constant/WxMediaTypeEnum.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package org.hamster.weixinmp.constant; 5 | 6 | /** 7 | * @author grossopaforever@gmail.com 8 | * @version Jan 4, 2014 9 | * 10 | */ 11 | public enum WxMediaTypeEnum { 12 | IMAGE(WxMediaType.IMAGE), 13 | MUSIC(WxMediaType.MUSIC), 14 | PIC_DESC(WxMediaType.PIC_DESC), 15 | THUMB(WxMediaType.THUMB), 16 | VIDEO(WxMediaType.VIDEO), 17 | VOICE(WxMediaType.VOICE), 18 | DEFAULT(WxMediaType.DEFAULT), 19 | ; 20 | 21 | /** 22 | * @param text 23 | */ 24 | WxMediaTypeEnum(final String text) { 25 | this._text = text; 26 | } 27 | 28 | private final String _text; 29 | 30 | /* 31 | * (non-Javadoc) 32 | * 33 | * @see java.lang.Enum#toString() 34 | */ 35 | @Override 36 | public String toString() { 37 | return _text; 38 | } 39 | 40 | public static WxMediaTypeEnum inst(String strVal) { 41 | for (WxMediaTypeEnum type : WxMediaTypeEnum.values()) { 42 | if (type.toString().equalsIgnoreCase(strVal)) { 43 | return type; 44 | } 45 | } 46 | return null; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/org/hamster/weixinmp/dao/entity/user/WxGroupEntity.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package org.hamster.weixinmp.dao.entity.user; 5 | 6 | import javax.persistence.Column; 7 | import javax.persistence.Entity; 8 | import javax.persistence.Table; 9 | 10 | import lombok.Data; 11 | import lombok.EqualsAndHashCode; 12 | import lombok.ToString; 13 | 14 | import org.hamster.weixinmp.config.WxConfig; 15 | import org.hamster.weixinmp.dao.entity.base.WxBaseEntity; 16 | 17 | import com.google.gson.annotations.SerializedName; 18 | 19 | /** 20 | * @author grossopaforever@gmail.com 21 | * @version Dec 30, 2013 22 | * 23 | */ 24 | @Entity 25 | @Table(name = WxConfig.TABLE_PREFIX + "user_group") 26 | @Data 27 | @ToString(callSuper = true) 28 | @EqualsAndHashCode(callSuper = true) 29 | public class WxGroupEntity extends WxBaseEntity { 30 | @SerializedName("id") 31 | @Column(name="wx_id", nullable=false) 32 | private Long wxId; 33 | @Column(name="name", length=WxConfig.COL_LEN_TITLE, nullable=false) 34 | private String name; 35 | @Column(name="count", nullable=false) 36 | private String count; 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/org/hamster/weixinmp/dao/entity/item/WxItemVoiceEntity.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package org.hamster.weixinmp.dao.entity.item; 5 | 6 | import javax.persistence.Column; 7 | import javax.persistence.Entity; 8 | import javax.persistence.Table; 9 | 10 | import lombok.Data; 11 | import lombok.EqualsAndHashCode; 12 | import lombok.ToString; 13 | 14 | import org.hamster.weixinmp.config.WxConfig; 15 | import org.hamster.weixinmp.dao.entity.base.WxBaseItemMediaEntity; 16 | 17 | /** 18 | * @author grossopaforever@gmail.com 19 | * @version Dec 29, 2013 20 | * 21 | */ 22 | @Entity 23 | @Table(name=WxConfig.TABLE_PREFIX + "item_voice") 24 | @Data 25 | @ToString(callSuper = true) 26 | @EqualsAndHashCode(callSuper = true) 27 | public class WxItemVoiceEntity extends WxBaseItemMediaEntity { 28 | @Column(name = "media_id", length = WxConfig.COL_LEN_INDICATOR, nullable = true) 29 | private String mediaId; 30 | @Column(name = "format", length = 10, nullable = true) 31 | private String format; 32 | @Column(name = "recognition", length = WxConfig.COL_LEN_TITLE, nullable = true) 33 | private String recognition; 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/org/hamster/weixinmp/dao/entity/msg/WxMsgVoiceEntity.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package org.hamster.weixinmp.dao.entity.msg; 5 | 6 | import javax.persistence.DiscriminatorValue; 7 | import javax.persistence.Entity; 8 | import javax.persistence.JoinColumn; 9 | import javax.persistence.ManyToOne; 10 | import javax.persistence.Table; 11 | 12 | import lombok.Data; 13 | import lombok.EqualsAndHashCode; 14 | import lombok.ToString; 15 | 16 | import org.hamster.weixinmp.config.WxConfig; 17 | import org.hamster.weixinmp.constant.WxMsgType; 18 | import org.hamster.weixinmp.dao.entity.base.WxBaseMsgEntity; 19 | import org.hamster.weixinmp.dao.entity.item.WxItemVoiceEntity; 20 | 21 | /** 22 | * @author grossopaforever@gmail.com 23 | * @version Dec 24, 2013 24 | * 25 | */ 26 | @Entity 27 | @Table(name = WxConfig.TABLE_PREFIX + "msg_voice") 28 | @DiscriminatorValue(WxMsgType.VOICE) 29 | @Data 30 | @ToString(callSuper = true) 31 | @EqualsAndHashCode(callSuper = true) 32 | public class WxMsgVoiceEntity extends WxBaseMsgEntity { 33 | @ManyToOne 34 | @JoinColumn(name="voice_id") 35 | WxItemVoiceEntity voice; 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/org/hamster/weixinmp/dao/entity/msg/WxMsgVideoEntity.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package org.hamster.weixinmp.dao.entity.msg; 5 | 6 | import javax.persistence.DiscriminatorValue; 7 | import javax.persistence.Entity; 8 | import javax.persistence.JoinColumn; 9 | import javax.persistence.ManyToOne; 10 | import javax.persistence.Table; 11 | 12 | import lombok.Data; 13 | import lombok.EqualsAndHashCode; 14 | import lombok.ToString; 15 | 16 | import org.hamster.weixinmp.config.WxConfig; 17 | import org.hamster.weixinmp.constant.WxMsgType; 18 | import org.hamster.weixinmp.dao.entity.base.WxBaseMsgEntity; 19 | import org.hamster.weixinmp.dao.entity.item.WxItemVideoEntity; 20 | 21 | /** 22 | * @author grossopaforever@gmail.com 23 | * @version Dec 24, 2013 24 | * 25 | */ 26 | @Entity 27 | @Table(name = WxConfig.TABLE_PREFIX + "msg_video") 28 | @DiscriminatorValue(WxMsgType.VIDEO) 29 | @Data 30 | @ToString(callSuper = true) 31 | @EqualsAndHashCode(callSuper = true) 32 | public class WxMsgVideoEntity extends WxBaseMsgEntity { 33 | @ManyToOne 34 | @JoinColumn(name="video_id") 35 | private WxItemVideoEntity video; 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/org/hamster/weixinmp/dao/entity/qr/WxQrEntity.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package org.hamster.weixinmp.dao.entity.qr; 5 | 6 | import javax.persistence.Column; 7 | import javax.persistence.Entity; 8 | import javax.persistence.Table; 9 | 10 | import lombok.Data; 11 | import lombok.EqualsAndHashCode; 12 | import lombok.ToString; 13 | 14 | import org.hamster.weixinmp.config.WxConfig; 15 | import org.hamster.weixinmp.dao.entity.base.WxBaseEntity; 16 | 17 | import com.google.gson.annotations.SerializedName; 18 | 19 | /** 20 | * @author grossopaforever@gmail.com 21 | * @version Jan 4, 2014 22 | * 23 | */ 24 | @Entity 25 | @Table(name = WxConfig.TABLE_PREFIX + "qr") 26 | @Data 27 | @ToString(callSuper = true) 28 | @EqualsAndHashCode(callSuper = true) 29 | public class WxQrEntity extends WxBaseEntity { 30 | @Column(name = "ticket", length = WxConfig.COL_LEN_TITLE, nullable = true) 31 | private String ticket; 32 | @Column(name = "scene", nullable = false) 33 | private Long scene; 34 | @Column(name = "expire_seconds", nullable = true) 35 | @SerializedName("expire_seconds") 36 | private Long expireSeconds; 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/org/hamster/weixinmp/exception/WxException.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package org.hamster.weixinmp.exception; 5 | 6 | import lombok.Getter; 7 | 8 | import org.hamster.weixinmp.model.WxRespCode; 9 | 10 | /** 11 | * @author grossopaforever@gmail.com 12 | * @version Jul 28, 2013 13 | * 14 | */ 15 | public class WxException extends Exception { 16 | 17 | private static final long serialVersionUID = -5181800588832010641L; 18 | @Getter 19 | private WxRespCode error; 20 | 21 | /** 22 | * 23 | */ 24 | public WxException() { 25 | } 26 | 27 | /** 28 | * @param message 29 | */ 30 | public WxException(String message) { 31 | super(message); 32 | } 33 | 34 | /** 35 | * @param cause 36 | */ 37 | public WxException(Throwable cause) { 38 | super(cause); 39 | } 40 | 41 | /** 42 | * @param message 43 | * @param cause 44 | */ 45 | public WxException(String message, Throwable cause) { 46 | super(message, cause); 47 | } 48 | 49 | 50 | /** 51 | * 52 | */ 53 | public WxException(WxRespCode errorJson) { 54 | super(errorJson.getErrmsg()); 55 | this.error = errorJson; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/main/java/org/hamster/weixinmp/dao/entity/msg/WxMsgImageEntity.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package org.hamster.weixinmp.dao.entity.msg; 5 | 6 | import javax.persistence.DiscriminatorValue; 7 | import javax.persistence.Entity; 8 | import javax.persistence.JoinColumn; 9 | import javax.persistence.ManyToOne; 10 | import javax.persistence.Table; 11 | 12 | import lombok.Data; 13 | import lombok.EqualsAndHashCode; 14 | import lombok.ToString; 15 | 16 | import org.hamster.weixinmp.config.WxConfig; 17 | import org.hamster.weixinmp.constant.WxMsgType; 18 | import org.hamster.weixinmp.dao.entity.base.WxBaseMsgEntity; 19 | import org.hamster.weixinmp.dao.entity.item.WxItemImageEntity; 20 | 21 | /** 22 | * @author grossopaforever@gmail.com 23 | * @version Jul 28, 2013 24 | * 25 | */ 26 | @Entity 27 | @Table(name = WxConfig.TABLE_PREFIX + "msg_image") 28 | @DiscriminatorValue(WxMsgType.IMAGE) 29 | @Data 30 | @ToString(callSuper = true) 31 | @EqualsAndHashCode(callSuper = true) 32 | public class WxMsgImageEntity extends WxBaseMsgEntity { 33 | 34 | @ManyToOne 35 | @JoinColumn(name = "image_id") 36 | private WxItemImageEntity image; 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/org/hamster/weixinmp/dao/entity/base/WxBaseEntity.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package org.hamster.weixinmp.dao.entity.base; 5 | 6 | import java.util.Date; 7 | 8 | import javax.persistence.Column; 9 | import javax.persistence.GeneratedValue; 10 | import javax.persistence.GenerationType; 11 | import javax.persistence.Id; 12 | import javax.persistence.MappedSuperclass; 13 | 14 | import com.google.gson.annotations.Expose; 15 | import com.google.gson.annotations.SerializedName; 16 | 17 | import lombok.Data; 18 | import lombok.EqualsAndHashCode; 19 | import lombok.ToString; 20 | 21 | /** 22 | * @author grossopaforever@gmail.com 23 | * @version Jul 27, 2013 24 | * 25 | */ 26 | @MappedSuperclass 27 | @Data 28 | @ToString(callSuper = false) 29 | @EqualsAndHashCode 30 | public abstract class WxBaseEntity { 31 | @Id 32 | @GeneratedValue(strategy = GenerationType.IDENTITY) 33 | @Expose(serialize = false, deserialize = false) 34 | @SerializedName("_id") 35 | protected Long id; 36 | @Column(name = "created_date") 37 | @Expose(serialize = false, deserialize = false) 38 | @SerializedName("_createddate") 39 | protected Date createdDate; 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/org/hamster/weixinmp/dao/entity/base/WxBaseRespEntity.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package org.hamster.weixinmp.dao.entity.base; 5 | 6 | import javax.persistence.Column; 7 | import javax.persistence.MappedSuperclass; 8 | 9 | import org.hamster.weixinmp.config.WxConfig; 10 | 11 | import lombok.Data; 12 | import lombok.EqualsAndHashCode; 13 | import lombok.ToString; 14 | 15 | /** 16 | * @author grossopaforever@gmail.com 17 | * @version Jul 28, 2013 18 | * 19 | */ 20 | @MappedSuperclass 21 | @Data 22 | @ToString(callSuper = true) 23 | @EqualsAndHashCode(callSuper = true) 24 | public abstract class WxBaseRespEntity extends WxBaseEntity { 25 | @Column(name="func_flag", nullable = false) 26 | protected Integer funcFlag; 27 | @Column(name = "to_user_name", length = WxConfig.COL_LEN_USER_NAME, nullable = false) 28 | protected String toUserName; 29 | @Column(name = "from_user_name", length = WxConfig.COL_LEN_USER_NAME, nullable = false) 30 | protected String fromUserName; 31 | @Column(name = "create_time", nullable = false) 32 | protected Long createTime; 33 | @Column(name = "msg_type", length = WxConfig.COL_LEN_INDICATOR, nullable = false) 34 | protected String msgType; 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/org/hamster/weixinmp/dao/entity/resp/WxRespMusicEntity.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package org.hamster.weixinmp.dao.entity.resp; 5 | 6 | import javax.persistence.Entity; 7 | import javax.persistence.JoinColumn; 8 | import javax.persistence.ManyToOne; 9 | import javax.persistence.Table; 10 | 11 | import lombok.Data; 12 | import lombok.EqualsAndHashCode; 13 | import lombok.ToString; 14 | 15 | import org.hamster.weixinmp.config.WxConfig; 16 | import org.hamster.weixinmp.dao.entity.base.WxBaseRespEntity; 17 | import org.hamster.weixinmp.dao.entity.item.WxItemMusicEntity; 18 | import org.hamster.weixinmp.dao.entity.item.WxItemThumbEntity; 19 | 20 | 21 | /** 22 | * @author grossopaforever@gmail.com 23 | * @version Jul 28, 2013 24 | * 25 | */ 26 | @Entity 27 | @Table(name = WxConfig.TABLE_PREFIX + "resp_music") 28 | @Data 29 | @ToString(callSuper = true) 30 | @EqualsAndHashCode(callSuper = true) 31 | public class WxRespMusicEntity extends WxBaseRespEntity { 32 | @ManyToOne 33 | @JoinColumn(name = "music_id", nullable = false) 34 | private WxItemMusicEntity music; 35 | @ManyToOne 36 | @JoinColumn(name = "thumb_id", nullable = false) 37 | private WxItemThumbEntity thumb; 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/org/hamster/weixinmp/dao/entity/item/WxItemPicDescEntity.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package org.hamster.weixinmp.dao.entity.item; 5 | 6 | import javax.persistence.Column; 7 | import javax.persistence.Entity; 8 | import javax.persistence.Table; 9 | 10 | import lombok.Data; 11 | import lombok.EqualsAndHashCode; 12 | import lombok.ToString; 13 | 14 | import org.hamster.weixinmp.config.WxConfig; 15 | import org.hamster.weixinmp.dao.entity.base.WxBaseItemMediaEntity; 16 | 17 | 18 | /** 19 | * @author grossopaforever@gmail.com 20 | * @version Jul 28, 2013 21 | * 22 | */ 23 | @Entity 24 | @Table(name=WxConfig.TABLE_PREFIX + "wx_item_pic_desc") 25 | @Data 26 | @ToString(callSuper = true) 27 | @EqualsAndHashCode(callSuper = true) 28 | public class WxItemPicDescEntity extends WxBaseItemMediaEntity { 29 | @Column(name="title", length = WxConfig.COL_LEN_TITLE, nullable = false) 30 | private String title; 31 | @Column(name="description", length = WxConfig.COL_LEN_CONTENT, nullable = false) 32 | private String description; 33 | @Column(name="pic_url", length = WxConfig.COL_LEN_URL, nullable = false) 34 | private String picUrl; 35 | @Column(name="url", length = WxConfig.COL_LEN_URL, nullable = false) 36 | private String url; 37 | } -------------------------------------------------------------------------------- /src/test/resources/log4j.properties: -------------------------------------------------------------------------------- 1 | # Output pattern : date [thread] priority category - message 2 | log4j.rootLogger=INFO, Console, RollingFile 3 | 4 | #Console 5 | log4j.appender.Console=org.apache.log4j.ConsoleAppender 6 | log4j.appender.Console.Target=System.out 7 | log4j.appender.Console.layout=org.apache.log4j.PatternLayout 8 | log4j.appender.Console.layout.ConversionPattern=%d [%t] %-5p [%c] - %m%n 9 | 10 | #RollingFile 11 | log4j.appender.RollingFile=org.apache.log4j.DailyRollingFileAppender 12 | log4j.appender.RollingFile.File=logs/candc.log 13 | log4j.appender.RollingFile.layout=org.apache.log4j.PatternLayout 14 | log4j.appender.RollingFile.layout.ConversionPattern=%d [%t] %-5p [%c] - %m%n 15 | 16 | #Task Configuration 17 | log4j.appender.Task=org.apache.log4j.DailyRollingFileAppender 18 | log4j.appender.Task.File=logs/candc-task.log 19 | log4j.appender.Task.layout=org.apache.log4j.PatternLayout 20 | log4j.appender.Task.layout.ConversionPattern=%d [%t] %-5p [%c] - %m%n 21 | 22 | #Project default level 23 | log4j.logger.com.hamster=INFO 24 | 25 | #Task level 26 | log4j.logger.com.hamster.service.task=INFO, Task 27 | log4j.logger.com.hamster.candc.task=INFO, Task 28 | 29 | #log4jdbc 30 | #log4j.logger.jdbc.sqltiming=INFO -------------------------------------------------------------------------------- /src/main/java/org/hamster/weixinmp/dao/entity/msg/WxMsgLinkEntity.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package org.hamster.weixinmp.dao.entity.msg; 5 | 6 | import javax.persistence.Column; 7 | import javax.persistence.DiscriminatorValue; 8 | import javax.persistence.Entity; 9 | import javax.persistence.Table; 10 | 11 | import org.hamster.weixinmp.config.WxConfig; 12 | import org.hamster.weixinmp.constant.WxMsgType; 13 | import org.hamster.weixinmp.dao.entity.base.WxBaseMsgEntity; 14 | 15 | import lombok.Data; 16 | import lombok.EqualsAndHashCode; 17 | import lombok.ToString; 18 | 19 | 20 | /** 21 | * @author grossopaforever@gmail.com 22 | * @version Jul 28, 2013 23 | * 24 | */ 25 | @Entity 26 | @Table(name = WxConfig.TABLE_PREFIX + "msg_link") 27 | @DiscriminatorValue(WxMsgType.LINK) 28 | @Data 29 | @ToString(callSuper = true) 30 | @EqualsAndHashCode(callSuper = true) 31 | public class WxMsgLinkEntity extends WxBaseMsgEntity { 32 | @Column(name = "title", length = WxConfig.COL_LEN_TITLE, nullable = false) 33 | private String title; 34 | @Column(name = "description", length = WxConfig.COL_LEN_CONTENT, nullable = false) 35 | private String description; 36 | @Column(name = "url", length = WxConfig.COL_LEN_URL, nullable = false) 37 | private String url; 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/org/hamster/weixinmp/dao/entity/msg/WxMsgLocEntity.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package org.hamster.weixinmp.dao.entity.msg; 5 | 6 | import javax.persistence.Column; 7 | import javax.persistence.DiscriminatorValue; 8 | import javax.persistence.Entity; 9 | import javax.persistence.Table; 10 | 11 | import org.hamster.weixinmp.config.WxConfig; 12 | import org.hamster.weixinmp.constant.WxMsgType; 13 | import org.hamster.weixinmp.dao.entity.base.WxBaseMsgEntity; 14 | 15 | import lombok.Data; 16 | import lombok.EqualsAndHashCode; 17 | import lombok.ToString; 18 | 19 | 20 | /** 21 | * @author grossopaforever@gmail.com 22 | * @version Jul 28, 2013 23 | * 24 | */ 25 | @Entity 26 | @Table(name = WxConfig.TABLE_PREFIX + "msg_loc") 27 | @DiscriminatorValue(WxMsgType.LOCATION) 28 | @Data 29 | @ToString(callSuper = true) 30 | @EqualsAndHashCode(callSuper = true) 31 | public class WxMsgLocEntity extends WxBaseMsgEntity { 32 | @Column(name = "location_x", nullable = false) 33 | private Double locationX; 34 | @Column(name = "location_y", nullable = false) 35 | private Double locationY; 36 | @Column(name = "scale", nullable = false) 37 | private Double scale; 38 | @Column(name = "label", length = WxConfig.COL_LEN_TITLE, nullable = false) 39 | private String label; 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/org/hamster/weixinmp/controller/util/WxJsonUtil.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package org.hamster.weixinmp.controller.util; 5 | 6 | import java.util.List; 7 | 8 | import org.hamster.weixinmp.dao.entity.menu.WxMenuBtnEntity; 9 | import org.hamster.weixinmp.model.WxAccessTokenJson; 10 | import org.hamster.weixinmp.model.WxRespCode; 11 | import org.hamster.weixinmp.model.menu.WxMenuCreateJson; 12 | 13 | import com.google.gson.Gson; 14 | 15 | 16 | /** 17 | * @author grossopaforever@gmail.com 18 | * @version Aug 4, 2013 19 | * 20 | */ 21 | public class WxJsonUtil { 22 | 23 | private WxJsonUtil() { 24 | } 25 | 26 | public static final String toMenuCreateReqBody(List wxMenuBtnList) { 27 | Gson gson = new Gson(); 28 | return gson.toJson(new WxMenuCreateJson(wxMenuBtnList)); 29 | } 30 | 31 | public static final WxRespCode toWxErrorJson(String errorResult) { 32 | if (errorResult != null && (errorResult.startsWith("{\"errcode") 33 | || errorResult.startsWith("{\"errmsg"))) { 34 | return new Gson().fromJson(errorResult, WxRespCode.class); 35 | } 36 | return null; 37 | } 38 | 39 | public static final WxAccessTokenJson toAccessTokenJson(String result) { 40 | return new Gson().fromJson(result, WxAccessTokenJson.class); 41 | } 42 | 43 | 44 | } -------------------------------------------------------------------------------- /src/main/java/org/hamster/weixinmp/dao/entity/item/WxItemVideoEntity.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package org.hamster.weixinmp.dao.entity.item; 5 | 6 | import javax.persistence.Column; 7 | import javax.persistence.Entity; 8 | import javax.persistence.JoinColumn; 9 | import javax.persistence.ManyToOne; 10 | import javax.persistence.Table; 11 | 12 | import lombok.Data; 13 | import lombok.EqualsAndHashCode; 14 | import lombok.ToString; 15 | 16 | import org.hamster.weixinmp.config.WxConfig; 17 | import org.hamster.weixinmp.dao.entity.base.WxBaseItemMediaEntity; 18 | 19 | /** 20 | * @author grossopaforever@gmail.com 21 | * @version Dec 29, 2013 22 | * 23 | */ 24 | @Entity 25 | @Table(name = WxConfig.TABLE_PREFIX + "item_video") 26 | @Data 27 | @ToString(callSuper = true) 28 | @EqualsAndHashCode(callSuper = true) 29 | public class WxItemVideoEntity extends WxBaseItemMediaEntity { 30 | @Column(name = "media_id", length = WxConfig.COL_LEN_INDICATOR, nullable = true) 31 | private String mediaId; 32 | @Column(name = "title", length = WxConfig.COL_LEN_TITLE, nullable = true) 33 | private String title; 34 | @Column(name = "description", length = WxConfig.COL_LEN_CONTENT, nullable = true) 35 | private String description; 36 | @ManyToOne 37 | @JoinColumn(name = "thumb_id", nullable = true) 38 | WxItemThumbEntity thumb; 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/org/hamster/weixinmp/dao/entity/msg/WxMsgEventEntity.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package org.hamster.weixinmp.dao.entity.msg; 5 | 6 | import javax.persistence.Column; 7 | import javax.persistence.Entity; 8 | import javax.persistence.Table; 9 | 10 | import lombok.Data; 11 | import lombok.EqualsAndHashCode; 12 | import lombok.ToString; 13 | 14 | import org.hamster.weixinmp.config.WxConfig; 15 | import org.hamster.weixinmp.dao.entity.base.WxBaseMsgEntity; 16 | 17 | /** 18 | * @author grossopaforever@gmail.com 19 | * @version Jul 28, 2013 20 | * 21 | */ 22 | @Entity 23 | @Table(name = WxConfig.TABLE_PREFIX + "msg_event") 24 | @Data 25 | @ToString(callSuper = true) 26 | @EqualsAndHashCode(callSuper = true) 27 | public class WxMsgEventEntity extends WxBaseMsgEntity { 28 | @Column(name = "event", length = WxConfig.COL_LEN_INDICATOR, nullable = false) 29 | private String event; 30 | @Column(name = "event_key", length = WxConfig.COL_LEN_TITLE, nullable = true) 31 | private String eventKey; 32 | @Column(name = "ticket", length = WxConfig.COL_LEN_TITLE, nullable = true) 33 | private String ticket; 34 | @Column(name = "latitude", nullable = true) 35 | private Double latitude; 36 | @Column(name = "longitude", nullable = true) 37 | private Double longitude; 38 | @Column(name = "precision", nullable = true) 39 | private Double precision; 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/org/hamster/weixinmp/dao/entity/item/WxItemMusicEntity.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package org.hamster.weixinmp.dao.entity.item; 5 | 6 | import javax.persistence.Column; 7 | import javax.persistence.Entity; 8 | import javax.persistence.Table; 9 | 10 | import lombok.Data; 11 | import lombok.EqualsAndHashCode; 12 | import lombok.ToString; 13 | 14 | import org.hamster.weixinmp.config.WxConfig; 15 | import org.hamster.weixinmp.dao.entity.base.WxBaseItemMediaEntity; 16 | 17 | 18 | /** 19 | * @author grossopaforever@gmail.com 20 | * @version Jul 28, 2013 21 | * 22 | */ 23 | @Entity 24 | @Table(name=WxConfig.TABLE_PREFIX + "item_music") 25 | @Data 26 | @ToString(callSuper = true) 27 | @EqualsAndHashCode(callSuper = true) 28 | public class WxItemMusicEntity extends WxBaseItemMediaEntity { 29 | @Column(name = "media_id", length = WxConfig.COL_LEN_INDICATOR, nullable = true) 30 | private String mediaId; 31 | @Column(name="title", length = WxConfig.COL_LEN_TITLE, nullable = true) 32 | private String title; 33 | @Column(name="description", length = WxConfig.COL_LEN_CONTENT, nullable = true) 34 | private String description; 35 | @Column(name="music_url", length = WxConfig.COL_LEN_URL, nullable = true) 36 | private String musicUrl; 37 | @Column(name="hq_music_url", length = WxConfig.COL_LEN_URL, nullable = true) 38 | private String hqMusicUrl; 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/org/hamster/weixinmp/dao/entity/auth/WxAuth.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package org.hamster.weixinmp.dao.entity.auth; 5 | 6 | import javax.persistence.Column; 7 | import javax.persistence.Entity; 8 | import javax.persistence.Table; 9 | 10 | import lombok.AllArgsConstructor; 11 | import lombok.Data; 12 | import lombok.EqualsAndHashCode; 13 | import lombok.NoArgsConstructor; 14 | import lombok.ToString; 15 | 16 | import org.hamster.weixinmp.dao.entity.base.WxBaseEntity; 17 | 18 | import com.google.gson.annotations.SerializedName; 19 | 20 | /** 21 | * 22 | * 23 | * @author grossopaforever@gmail.com 24 | * @version Aug 3, 2013 25 | * 26 | */ 27 | @Entity 28 | @Table(name = "wx_auth") 29 | @Data 30 | @ToString 31 | @EqualsAndHashCode(callSuper = true) 32 | @AllArgsConstructor 33 | @NoArgsConstructor 34 | public class WxAuth extends WxBaseEntity { 35 | @Column(name = "grant_type", length = 50, nullable = false) 36 | private String grantType; 37 | @Column(name = "appid", length = 100, nullable = false) 38 | private String appid; 39 | @Column(name = "secret", length = 100, nullable = false) 40 | private String secret; 41 | @SerializedName("access_token") 42 | @Column(name = "access_token", length = 200, nullable = false) 43 | private String accessToken; 44 | @SerializedName("expires_in") 45 | @Column(name = "expires_in", nullable = false) 46 | private Long expiresIn; 47 | 48 | } 49 | -------------------------------------------------------------------------------- /src/test/java/org/hamster/weixinmp/test/service/WxGroupServceTest.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package org.hamster.weixinmp.test.service; 5 | 6 | import java.util.List; 7 | 8 | import org.hamster.weixinmp.dao.entity.user.WxGroupEntity; 9 | import org.hamster.weixinmp.exception.WxException; 10 | import org.hamster.weixinmp.service.WxAuthService; 11 | import org.hamster.weixinmp.service.WxUserGroupService; 12 | import org.hamster.weixinmp.test.base.AbstractWxServiceTest; 13 | import org.junit.Test; 14 | import org.springframework.beans.factory.annotation.Autowired; 15 | 16 | /** 17 | * @author grossopaforever@gmail.com 18 | * @version Jan 1, 2014 19 | * 20 | */ 21 | public class WxGroupServceTest extends AbstractWxServiceTest { 22 | 23 | @Autowired 24 | WxAuthService authService; 25 | 26 | @Autowired 27 | WxUserGroupService userGroupService; 28 | 29 | @Test 30 | public void testAll() throws WxException { 31 | WxGroupEntity newgroup = userGroupService.remoteGroupsCreate(accessToken, "API测试组"); 32 | List groups = userGroupService.remoteGroupsGet(accessToken); 33 | 34 | boolean found = false; 35 | for (WxGroupEntity group : groups) { 36 | if (group.getName().equals(newgroup.getName())) { 37 | found = true; 38 | } 39 | } 40 | if (found == false) { 41 | throw new WxException("not found newly created group!"); 42 | } 43 | 44 | userGroupService.remoteGroupsUpdate(accessToken, newgroup.getWxId(), "API测试组2"); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/org/hamster/weixinmp/dao/entity/base/WxBaseMsgEntity.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package org.hamster.weixinmp.dao.entity.base; 5 | 6 | import javax.persistence.Column; 7 | import javax.persistence.DiscriminatorColumn; 8 | import javax.persistence.Entity; 9 | import javax.persistence.Inheritance; 10 | import javax.persistence.InheritanceType; 11 | import javax.persistence.Table; 12 | 13 | import org.hamster.weixinmp.config.WxConfig; 14 | 15 | import lombok.Data; 16 | import lombok.EqualsAndHashCode; 17 | import lombok.ToString; 18 | 19 | /** 20 | * @author grossopaforever@gmail.com 21 | * @version Jul 28, 2013 22 | * 23 | */ 24 | 25 | @Entity 26 | @Table(name = WxConfig.TABLE_PREFIX + "msg_base") 27 | @DiscriminatorColumn(name = "msg_type", length = 20) 28 | @Inheritance(strategy = InheritanceType.JOINED) 29 | @Data 30 | @ToString(callSuper = true) 31 | @EqualsAndHashCode(callSuper = true) 32 | public abstract class WxBaseMsgEntity extends WxBaseEntity { 33 | 34 | @Column(name = "to_user_name", length = WxConfig.COL_LEN_USER_NAME, nullable = false) 35 | protected String toUserName; 36 | @Column(name = "from_user_name", length = WxConfig.COL_LEN_USER_NAME, nullable = false) 37 | protected String fromUserName; 38 | @Column(name = "create_time", nullable = false) 39 | protected Long createTime; 40 | @Column(name = "msg_type", length = WxConfig.COL_LEN_INDICATOR, nullable = false) 41 | protected String msgType; 42 | @Column(name = "msg_id", nullable = true) 43 | protected Long msgId; 44 | } 45 | -------------------------------------------------------------------------------- /src/test/java/org/hamster/weixinmp/test/service/WxMediaServiceTest.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package org.hamster.weixinmp.test.service; 5 | 6 | import java.io.File; 7 | import java.io.FileNotFoundException; 8 | import java.io.FileReader; 9 | import java.io.IOException; 10 | 11 | import org.apache.commons.io.IOUtils; 12 | import org.hamster.weixinmp.constant.WxMediaTypeEnum; 13 | import org.hamster.weixinmp.dao.entity.item.WxItemImageEntity; 14 | import org.hamster.weixinmp.exception.WxException; 15 | import org.hamster.weixinmp.service.WxAuthService; 16 | import org.hamster.weixinmp.service.WxMediaService; 17 | import org.hamster.weixinmp.test.base.AbstractWxServiceTest; 18 | import org.junit.Ignore; 19 | import org.junit.Test; 20 | import org.springframework.beans.factory.annotation.Autowired; 21 | 22 | /** 23 | * @author grossopaforever@gmail.com 24 | * @version Jan 4, 2014 25 | * 26 | */ 27 | public class WxMediaServiceTest extends AbstractWxServiceTest { 28 | 29 | @Autowired 30 | WxAuthService authService; 31 | 32 | @Autowired 33 | WxMediaService mediaService; 34 | 35 | @Test 36 | @Ignore 37 | public void testMedia() throws WxException, FileNotFoundException, IOException { 38 | File imageFile = new File("src/test/resources/media/cat.jpg"); 39 | byte[] content = IOUtils.toByteArray(new FileReader(imageFile)); 40 | WxItemImageEntity imageMedia = (WxItemImageEntity) mediaService 41 | .remoteMediaUpload(accessToken, WxMediaTypeEnum.IMAGE, content); 42 | System.out.println(imageMedia); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/main/resources/applicationContext-weixinmp.xml: -------------------------------------------------------------------------------- 1 | 2 | 16 | 17 | WX Service Configration 18 | 19 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /src/main/java/org/hamster/weixinmp/dao/entity/menu/WxMenuBtnEntity.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package org.hamster.weixinmp.dao.entity.menu; 5 | 6 | import java.util.List; 7 | 8 | import javax.persistence.CascadeType; 9 | import javax.persistence.Column; 10 | import javax.persistence.Entity; 11 | import javax.persistence.JoinColumn; 12 | import javax.persistence.ManyToOne; 13 | import javax.persistence.OneToMany; 14 | import javax.persistence.Table; 15 | 16 | import lombok.Data; 17 | import lombok.EqualsAndHashCode; 18 | import lombok.ToString; 19 | 20 | import org.hamster.weixinmp.config.WxConfig; 21 | import org.hamster.weixinmp.dao.entity.base.WxBaseEntity; 22 | 23 | import com.google.gson.annotations.Expose; 24 | import com.google.gson.annotations.SerializedName; 25 | 26 | /** 27 | * @author grossopaforever@gmail.com 28 | * @version Aug 4, 2013 29 | * 30 | */ 31 | @Entity 32 | @Table(name = WxConfig.TABLE_PREFIX + "menu_btn") 33 | @Data 34 | @ToString(callSuper = true) 35 | @EqualsAndHashCode(callSuper = true) 36 | public class WxMenuBtnEntity extends WxBaseEntity { 37 | @Column(name = "key_", length = 128, nullable = false) 38 | private String key; 39 | @Column(name = "url", length = 256, nullable = false) 40 | private String url; 41 | @Column(name = "name", length = 80, nullable = false) 42 | private String name; 43 | @Column(name = "type", length = WxConfig.COL_LEN_INDICATOR, nullable = false) 44 | private String type; 45 | @ManyToOne(cascade = { CascadeType.ALL }) 46 | @JoinColumn(name = "parent_button_id") 47 | @Expose(serialize = false, deserialize = false) 48 | private WxMenuBtnEntity parentButton; 49 | @OneToMany(mappedBy = "parentButton") 50 | @SerializedName("sub_button") 51 | private List subButtons; 52 | } 53 | -------------------------------------------------------------------------------- /src/main/java/org/hamster/weixinmp/service/WxUserService.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package org.hamster.weixinmp.service; 5 | 6 | import static org.hamster.weixinmp.util.WxUtil.getAccessTokenParams; 7 | import static org.hamster.weixinmp.util.WxUtil.sendRequest; 8 | 9 | import java.util.Map; 10 | 11 | import org.apache.commons.lang3.StringUtils; 12 | import org.hamster.weixinmp.config.WxConfig; 13 | import org.hamster.weixinmp.dao.entity.user.WxUserEntity; 14 | import org.hamster.weixinmp.exception.WxException; 15 | import org.hamster.weixinmp.model.user.WxUserGetJson; 16 | import org.springframework.beans.factory.annotation.Autowired; 17 | import org.springframework.http.HttpMethod; 18 | import org.springframework.stereotype.Service; 19 | 20 | /** 21 | * @author grossopaforever@gmail.com 22 | * @version Dec 31, 2013 23 | * 24 | */ 25 | @Service 26 | public class WxUserService { 27 | 28 | @Autowired 29 | private WxConfig config; 30 | 31 | public WxUserEntity remoteUserInfo(String accessToken, String openId) throws WxException { 32 | Map params = getAccessTokenParams(accessToken); 33 | params.put("openid", openId); 34 | return sendRequest(config.getUserInfoUrl(), HttpMethod.GET, 35 | params, null, WxUserEntity.class); 36 | } 37 | 38 | public WxUserGetJson remoteUserGet(String accessToken, String nextOpenId) throws WxException { 39 | Map params = getAccessTokenParams(accessToken); 40 | if (!StringUtils.isBlank(nextOpenId)) { 41 | params.put("next_openid", nextOpenId); 42 | } 43 | return sendRequest(config.getUserGetUrl(), HttpMethod.GET, 44 | params, null, WxUserGetJson.class); 45 | } 46 | 47 | public WxUserGetJson remoteUserGet(String accessToken) throws WxException { 48 | return remoteUserGet(accessToken, ""); 49 | } 50 | } -------------------------------------------------------------------------------- /src/main/resources/wx.properties: -------------------------------------------------------------------------------- 1 | #(optional)override jdbc url for local development 2 | jdbc.driver=org.h2.Driver 3 | jdbc.url=jdbc:h2:mem:wx_mp;DB_CLOSE_DELAY=-1 4 | jdbc.username=sa 5 | jdbc.password= 6 | 7 | wx_token=HamsterNice123ILove 8 | wx_appid=wx3469fe8fd2c9991c 9 | wx_appsecret=6f5263f59377386ebb2d5e214581bcc0 10 | 11 | wx_menu_create_url=https://api.weixin.qq.com/cgi-bin/menu/create 12 | wx_menu_get_url=https://api.weixin.qq.com/cgi-bin/menu/get 13 | #?access_token=ACCESS_TOKEN 14 | wx_menu_delete_url=https://api.weixin.qq.com/cgi-bin/menu/delete 15 | #?access_token=ACCESS_TOKEN 16 | 17 | wx_media_upload_url=http://file.api.weixin.qq.com/cgi-bin/media/upload 18 | #?access_token=ACCESS_TOKEN&type=TYPE 19 | 20 | wx_qrcode_create_url=https://api.weixin.qq.com/cgi-bin/qrcode/create 21 | #?access_token=TOKEN 22 | wx_showqrcode_url=https://mp.weixin.qq.com/cgi-bin/showqrcode 23 | #?ticket=TICKET 24 | 25 | wx_user_info_url=https://api.weixin.qq.com/cgi-bin/user/info 26 | #?access_token=ACCESS_TOKEN&openid=OPENID 27 | wx_user_get_url=https://api.weixin.qq.com/cgi-bin/user/get 28 | #?access_token=ACCESS_TOKEN&next_openid=NEXT_OPENID 29 | 30 | 31 | wx_access_token_create_url=https://api.weixin.qq.com/cgi-bin/token 32 | #?grant_type=client_credential&appid=APPID&secret=APPSECRET 33 | wx_custom_send_url=https://api.weixin.qq.com/cgi-bin/message/custom/send 34 | #?access_token=ACCESS_TOKEN 35 | 36 | wx_groups_create_url=https://api.weixin.qq.com/cgi-bin/groups/create 37 | #?access_token=ACCESS_TOKEN 38 | wx_groups_get_url=https://api.weixin.qq.com/cgi-bin/groups/get 39 | #?access_token=ACCESS_TOKEN 40 | wx_groups_getid_url=https://api.weixin.qq.com/cgi-bin/groups/getid 41 | #?access_token=ACCESS_TOKEN 42 | wx_groups_update_url=https://api.weixin.qq.com/cgi-bin/groups/update 43 | #?access_token=ACCESS_TOKEN 44 | wx_groups_members_update_url=https://api.weixin.qq.com/cgi-bin/groups/members/update 45 | #?access_token=ACCESS_TOKEN -------------------------------------------------------------------------------- /src/test/resources/application.development.properties: -------------------------------------------------------------------------------- 1 | #(optional)override jdbc url for local development 2 | jdbc.driver=org.h2.Driver 3 | jdbc.url=jdbc:h2:mem:wx_mp;DB_CLOSE_DELAY=-1 4 | jdbc.username=sa 5 | jdbc.password= 6 | 7 | wx_token=HamsterNice123ILove 8 | wx_appid=wx3469fe8fd2c9991c 9 | wx_appsecret=6f5263f59377386ebb2d5e214581bcc0 10 | 11 | wx_menu_create_url=https://api.weixin.qq.com/cgi-bin/menu/create 12 | wx_menu_get_url=https://api.weixin.qq.com/cgi-bin/menu/get 13 | #?access_token=ACCESS_TOKEN 14 | wx_menu_delete_url=https://api.weixin.qq.com/cgi-bin/menu/delete 15 | #?access_token=ACCESS_TOKEN 16 | 17 | wx_media_upload_url=http://file.api.weixin.qq.com/cgi-bin/media/upload 18 | #?access_token=ACCESS_TOKEN&type=TYPE 19 | 20 | wx_qrcode_create_url=https://api.weixin.qq.com/cgi-bin/qrcode/create 21 | #?access_token=TOKEN 22 | wx_showqrcode_url=https://mp.weixin.qq.com/cgi-bin/showqrcode 23 | #?ticket=TICKET 24 | 25 | wx_user_info_url=https://api.weixin.qq.com/cgi-bin/user/info 26 | #?access_token=ACCESS_TOKEN&openid=OPENID 27 | wx_user_get_url=https://api.weixin.qq.com/cgi-bin/user/get 28 | #?access_token=ACCESS_TOKEN&next_openid=NEXT_OPENID 29 | 30 | 31 | wx_access_token_create_url=https://api.weixin.qq.com/cgi-bin/token 32 | #?grant_type=client_credential&appid=APPID&secret=APPSECRET 33 | wx_custom_send_url=https://api.weixin.qq.com/cgi-bin/message/custom/send 34 | #?access_token=ACCESS_TOKEN 35 | 36 | wx_groups_create_url=https://api.weixin.qq.com/cgi-bin/groups/create 37 | #?access_token=ACCESS_TOKEN 38 | wx_groups_get_url=https://api.weixin.qq.com/cgi-bin/groups/get 39 | #?access_token=ACCESS_TOKEN 40 | wx_groups_getid_url=https://api.weixin.qq.com/cgi-bin/groups/getid 41 | #?access_token=ACCESS_TOKEN 42 | wx_groups_update_url=https://api.weixin.qq.com/cgi-bin/groups/update 43 | #?access_token=ACCESS_TOKEN 44 | wx_groups_members_update_url=https://api.weixin.qq.com/cgi-bin/groups/members/update 45 | #?access_token=ACCESS_TOKEN -------------------------------------------------------------------------------- /src/main/java/org/hamster/weixinmp/service/WxQrService.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package org.hamster.weixinmp.service; 5 | 6 | import static org.hamster.weixinmp.util.WxUtil.getAccessTokenParams; 7 | import static org.hamster.weixinmp.util.WxUtil.sendRequest; 8 | import static org.hamster.weixinmp.util.WxUtil.toJsonStringEntity; 9 | 10 | import java.util.Map; 11 | 12 | import org.hamster.weixinmp.config.WxConfig; 13 | import org.hamster.weixinmp.dao.entity.qr.WxQrEntity; 14 | import org.hamster.weixinmp.exception.WxException; 15 | import org.hamster.weixinmp.model.qr.WxQrActionInfoJson; 16 | import org.hamster.weixinmp.model.qr.WxQrCreateJson; 17 | import org.hamster.weixinmp.model.qr.WxQrSceneJson; 18 | import org.springframework.beans.factory.annotation.Autowired; 19 | import org.springframework.http.HttpMethod; 20 | import org.springframework.stereotype.Service; 21 | 22 | /** 23 | * @author grossopaforever@gmail.com 24 | * @version Jan 4, 2014 25 | * 26 | */ 27 | @Service 28 | public class WxQrService { 29 | @Autowired 30 | private WxConfig config; 31 | 32 | public WxQrEntity remoteQrcodeCreate(String accessToken, 33 | boolean isTemporary, Long sceneId, Long expire_seconds) 34 | throws WxException { 35 | Map params = getAccessTokenParams(accessToken); 36 | 37 | WxQrSceneJson scene = new WxQrSceneJson(); 38 | scene.setScene_id(sceneId); 39 | WxQrActionInfoJson action = new WxQrActionInfoJson(); 40 | action.setScene(scene); 41 | WxQrCreateJson requestJson = new WxQrCreateJson(); 42 | requestJson.setAction_name(isTemporary ? "QR_LIMIT_SCENE" : "QR_SCENE"); 43 | requestJson.setAction_info(action); 44 | if (isTemporary) { 45 | requestJson.setExpire_seconds(expire_seconds); 46 | } 47 | 48 | WxQrEntity result = sendRequest(config.getQrcodeCreateUrl(), 49 | HttpMethod.POST, params, toJsonStringEntity(requestJson), 50 | WxQrEntity.class); 51 | result.setScene(sceneId); 52 | return result; 53 | } 54 | 55 | } 56 | -------------------------------------------------------------------------------- /src/main/java/org/hamster/weixinmp/gson/WxMenuBtnSerializer.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package org.hamster.weixinmp.gson; 5 | 6 | import java.lang.reflect.Type; 7 | 8 | import org.hamster.weixinmp.constant.WxMenuBtnTypeEnum; 9 | import org.hamster.weixinmp.dao.entity.menu.WxMenuBtnEntity; 10 | import org.springframework.util.CollectionUtils; 11 | 12 | import com.google.gson.JsonArray; 13 | import com.google.gson.JsonElement; 14 | import com.google.gson.JsonObject; 15 | import com.google.gson.JsonSerializationContext; 16 | import com.google.gson.JsonSerializer; 17 | 18 | /** 19 | * @author grossopaforever@gmail.com 20 | * @version Jan 4, 2014 21 | * 22 | */ 23 | public class WxMenuBtnSerializer implements JsonSerializer { 24 | 25 | /* 26 | * (non-Javadoc) 27 | * 28 | * @see com.google.gson.JsonSerializer#serialize(java.lang.Object, 29 | * java.lang.reflect.Type, com.google.gson.JsonSerializationContext) 30 | */ 31 | public JsonElement serialize(WxMenuBtnEntity src, Type typeOfSrc, 32 | JsonSerializationContext context) { 33 | return recursiveParse(src); 34 | } 35 | 36 | public JsonObject recursiveParse(WxMenuBtnEntity parentEntity) { 37 | JsonObject parent = new JsonObject(); 38 | parent.addProperty("type", parentEntity.getType()); 39 | parent.addProperty("name", parentEntity.getName()); 40 | 41 | WxMenuBtnTypeEnum type = WxMenuBtnTypeEnum.valueOf(parentEntity 42 | .getType()); 43 | switch (type) { 44 | case CLICK: 45 | parent.addProperty("key", parentEntity.getKey()); 46 | break; 47 | case VIEW: 48 | parent.addProperty("url", parentEntity.getUrl()); 49 | break; 50 | default: 51 | break; 52 | } 53 | if (!CollectionUtils.isEmpty(parentEntity.getSubButtons())) { 54 | JsonArray children = new JsonArray(); 55 | for (WxMenuBtnEntity child : parentEntity.getSubButtons()) { 56 | children.add(recursiveParse(child)); 57 | } 58 | parent.add("sub_button", children); 59 | } 60 | return parent; 61 | } 62 | 63 | } 64 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | weixin-mp-java 2 | 基于Java,Spring,Maven实现的微信公众平台一整套代码,从前端Controller到后端的Dao的实现
3 | ============== 4 | 5 | 1.0.1 2013-1月更新: 6 | 支持上传下载多媒体文件 7 | 支持接收消息(语音似乎总有问题,同时收到来自微信两个服务器的空的POST的请求,论坛上也有很多人反映此情况) 8 | 支持用户管理 9 | 支持自定义菜单CRD 10 | 支持推广支持接口 11 | 12 | 强化测试代码 13 | 优化代码结构,增加WxMessageHandlerIfc, 只要实现该接口的所有spring bean在收到消息后都会被自动调用. 14 | 15 | ============== 16 | 17 | 实现功能:消息接口,通用接口和菜单接口(没有内测号无法测试)
18 | 19 | ============== 20 | 21 | 由于涉及的框架比较杂乱,在此一一解释:
22 | 23 | 1. 简便实用的前置条件:
24 | 你的项目是基于Spring,Maven,Hibernate架构;
25 | 你的项目至少有一个已经存在的配置文件;
26 | 需要在配置文件(例子:application.properties)中添加
27 | wx_token=your_token
28 | wx_appid=asdf
29 | wx_appsecret=secret
30 | 没有在线的Maven仓库,强烈建议clone代码到本地作为子工程使用;
31 | 32 | 2. 如果你是通过spring-annotation配置bean的话,那么只要在你的Spring xml配置文件里加入以下两句便可:
33 | <context:component-scan base-package="com.hamster.weixinmp" />
34 | <util:properties id="wxProperties" location="classpath:/application.properties"/>
35 | 如果没有util的话,在beans xml声明中加入:
36 | xmlns:util="http://www.springframework.org/schema/util"
37 | xsi:schemaLocation="…..
38 | http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.1.xsd"
39 | 在org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean的packageToScan中添加org.hamster.weixinmp.dao 40 | 41 | 3. 如果不想用数据库,那么只扫描com.hamster.weixinmp.service和com.hamster.weixinmp.controller即可,所有的dao在wxService中配置模式均为可选,如果没有注入,则不会执行存储操作;
42 | 43 | 4. 项目使用了lombok生成Getter/Setter, toString, hashCode, equals方法,lombok有eclipse插件,具体怎么安装请看这里:http://projectlombok.org/download.html,如果不想用lombok的话那么就手动删掉那些注解并用eclipse等工具重新生成一下这些方法便可。
44 | 45 | 5. 如果你的项目是通过xml的方式配置的话,你需要将所有的dao,service和controller配置到xml中(浩大的工程= =)
46 | 47 | 6. 数据库的前缀为wx_,一般来说不会有冲突,真冲突了那就自己手动改改吧,反正也不麻烦
48 | 49 | 7. 数据库有些额外的字段,比如自增长的id,created_date等,用不到就无视吧
50 | 51 | 8. 如果你不用maven的话……那就把java代码都拷贝到自己的工程里面去吧……
-------------------------------------------------------------------------------- /src/main/java/org/hamster/weixinmp/dao/entity/user/WxUserEntity.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package org.hamster.weixinmp.dao.entity.user; 5 | 6 | import javax.persistence.Column; 7 | import javax.persistence.Entity; 8 | import javax.persistence.Table; 9 | 10 | import lombok.Data; 11 | import lombok.EqualsAndHashCode; 12 | import lombok.ToString; 13 | 14 | import org.hamster.weixinmp.config.WxConfig; 15 | import org.hamster.weixinmp.dao.entity.base.WxBaseEntity; 16 | 17 | import com.google.gson.annotations.SerializedName; 18 | 19 | /** 20 | * @author grossopaforever@gmail.com 21 | * @version Dec 30, 2013 22 | * 23 | */ 24 | @Entity 25 | @Table(name = WxConfig.TABLE_PREFIX + "user") 26 | @Data 27 | @ToString(callSuper = true) 28 | @EqualsAndHashCode(callSuper = true) 29 | public class WxUserEntity extends WxBaseEntity { 30 | @SerializedName("openid") 31 | @Column(name = "open_id", length = WxConfig.COL_LEN_INDICATOR, nullable = false) 32 | private String openId; 33 | @Column(name = "subscribe", nullable = false) 34 | private Integer subscribe; 35 | @SerializedName("nickname") 36 | @Column(name = "nickname", length = WxConfig.COL_LEN_USER_NAME, nullable = false) 37 | private String nickName; 38 | @Column(name = "sex", nullable = false) 39 | private Integer sex; 40 | @Column(name = "language", length = WxConfig.COL_LEN_INDICATOR, nullable = false) 41 | private String language; 42 | @Column(name = "city", length = WxConfig.COL_LEN_INDICATOR, nullable = false) 43 | private String city; 44 | @Column(name = "province", length = WxConfig.COL_LEN_INDICATOR, nullable = false) 45 | private String province; 46 | @Column(name = "country", length = WxConfig.COL_LEN_INDICATOR, nullable = false) 47 | private String country; 48 | @SerializedName("headimgurl") 49 | @Column(name = "head_img_url", length = WxConfig.COL_LEN_URL, nullable = false) 50 | private String headImgUrl; 51 | @SerializedName("subscribe_time") 52 | @Column(name = "subscribe_time", nullable = false) 53 | private Long subscribeTime; 54 | 55 | } 56 | -------------------------------------------------------------------------------- /src/test/java/org/hamster/weixinmp/test/service/WxMenuServiceTest.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package org.hamster.weixinmp.test.service; 5 | 6 | import org.hamster.weixinmp.exception.WxException; 7 | import org.hamster.weixinmp.model.menu.WxMenuCreateJson; 8 | import org.hamster.weixinmp.service.WxAuthService; 9 | import org.hamster.weixinmp.service.WxMenuService; 10 | import org.hamster.weixinmp.test.base.AbstractWxServiceTest; 11 | import org.junit.Test; 12 | import org.springframework.beans.factory.annotation.Autowired; 13 | 14 | import com.google.gson.Gson; 15 | 16 | /** 17 | * @author grossopaforever@gmail.com 18 | * @version Jan 4, 2014 19 | * 20 | */ 21 | public class WxMenuServiceTest extends AbstractWxServiceTest { 22 | 23 | public static final String MENU_CREATE_JSON = " {" + "\"button\":[" + "{ " 24 | + " \"type\":\"click\"," + " \"name\":\"今日歌曲\"," 25 | + " \"key\":\"V1001_TODAY_MUSIC\"" + "}," + "{" 26 | + " \"type\":\"click\"," + " \"name\":\"歌手简介\"," 27 | + " \"key\":\"V1001_TODAY_SINGER\"" + " }," + " {" 28 | + " \"name\":\"菜单\"," + " \"sub_button\":[" 29 | + " { " + " \"type\":\"view\"," 30 | + " \"name\":\"搜索\"," 31 | + " \"url\":\"http://www.soso.com/\"" + " }," + " {" 32 | + " \"type\":\"view\"," + " \"name\":\"视频\"," 33 | + " \"url\":\"http://v.qq.com/\"" + " }," + " {" 34 | + " \"type\":\"click\"," + " \"name\":\"赞一下我们\"," 35 | + " \"key\":\"V1001_GOOD\"" + " }]" + "}]" + "}"; 36 | 37 | @Autowired 38 | WxAuthService authService; 39 | @Autowired 40 | WxMenuService menuService; 41 | 42 | @Test 43 | public void testAll() throws WxException { 44 | Gson gson = new Gson(); 45 | WxMenuCreateJson dummyJson = gson.fromJson(MENU_CREATE_JSON, 46 | WxMenuCreateJson.class); 47 | 48 | menuService.menuCreate(accessToken, dummyJson.getButton()); 49 | 50 | System.out.println(menuService.menuGet(accessToken)); 51 | 52 | menuService.menuDelete(accessToken); 53 | } 54 | 55 | } 56 | -------------------------------------------------------------------------------- /src/test/java/org/hamster/weixinmp/test/base/AbstractWxServiceTest.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package org.hamster.weixinmp.test.base; 5 | 6 | import java.io.BufferedReader; 7 | import java.io.File; 8 | import java.io.FileReader; 9 | import java.io.FileWriter; 10 | import java.io.IOException; 11 | import java.util.Date; 12 | 13 | import org.apache.commons.lang3.StringUtils; 14 | import org.hamster.weixinmp.config.WxConfig; 15 | import org.hamster.weixinmp.dao.entity.auth.WxAuth; 16 | import org.hamster.weixinmp.exception.WxException; 17 | import org.hamster.weixinmp.service.WxAuthService; 18 | import org.junit.Before; 19 | import org.springframework.beans.factory.annotation.Autowired; 20 | 21 | /** 22 | * @author grossopaforever@gmail.com 23 | * @version Jan 5, 2014 24 | * 25 | */ 26 | public abstract class AbstractWxServiceTest extends AbstractServiceTest { 27 | 28 | public static final String TEST_FOLDER = "src/test/resources/tmp"; 29 | public static final String ACCESS_TOKEN_FILE = TEST_FOLDER + "/accessToken.txt"; 30 | 31 | 32 | protected String accessToken; 33 | 34 | @Autowired 35 | WxConfig config; 36 | 37 | @Autowired 38 | WxAuthService authService; 39 | 40 | @Before 41 | public void setUp() throws WxException, IOException { 42 | if (StringUtils.isBlank(accessToken)) { 43 | File testConfigFile = new File(ACCESS_TOKEN_FILE); 44 | Date currentDate = new Date(); 45 | if (!testConfigFile.exists() || currentDate.getTime() - testConfigFile.lastModified() > 86400000) { 46 | WxAuth auth = authService.getAccessToken(config.getAppid(), config.getAppsecret()); 47 | this.accessToken = auth.getAccessToken(); 48 | new File(TEST_FOLDER).mkdirs(); 49 | FileWriter writer = new FileWriter(ACCESS_TOKEN_FILE); 50 | writer.write(accessToken); 51 | writer.flush(); 52 | writer.close(); 53 | } else { 54 | BufferedReader reader = new BufferedReader(new FileReader(ACCESS_TOKEN_FILE)); 55 | this.accessToken = reader.readLine(); 56 | reader.close(); 57 | } 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/test/java/org/hamster/weixinmp/test/service/WxServiceTest.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package org.hamster.weixinmp.test.service; 5 | 6 | import org.hamster.weixinmp.dao.repository.msg.WxBaseMsgDao; 7 | import org.hamster.weixinmp.exception.WxException; 8 | import org.hamster.weixinmp.service.WxAuthService; 9 | import org.hamster.weixinmp.test.base.AbstractServiceTest; 10 | import org.junit.Assert; 11 | import org.junit.Test; 12 | import org.springframework.beans.factory.annotation.Autowired; 13 | 14 | 15 | /** 16 | * @author grossopaforever@gmail.com 17 | * @version Jul 28, 2013 18 | * 19 | */ 20 | public class WxServiceTest extends AbstractServiceTest { 21 | 22 | @Autowired 23 | WxAuthService authService; 24 | 25 | @Autowired 26 | WxBaseMsgDao wxBaseMsgDao; 27 | 28 | @Test 29 | public void testValidateAuth() throws WxException { 30 | Assert.assertTrue(authService.validateAuth( 31 | "9d31490b4386ad3bb9bbb8ac5150fb3e6230c171", 32 | "1375112572", "1375102247", 33 | "5906019193781128573")); 34 | } 35 | 36 | public static final String MSG_LOC_XML = "" 37 | + "" 38 | + "" 39 | + "1351776360" 40 | + "" 41 | + "23.134521" 42 | + "113.358803" 43 | + "20" 44 | + "" 45 | + "1234567890123456" + " "; 46 | 47 | // @Test 48 | // public void testMessageStorage() throws WxException, DocumentException { 49 | // wxService.saveMsgLoc(WxXmlUtil.toXML(MSG_LOC_XML)); 50 | // Iterable msgs = wxBaseMsgDao.findAll(); 51 | // for (WxBaseMsgEntity msg : msgs) { 52 | // System.out.println(msg.toString()); 53 | // } 54 | // } 55 | // 56 | // @Test 57 | // public void testCreateRespText() throws DocumentException { 58 | // WxRespTextEntity respText = wxService.createRespText("this is a content", "foo", "bar", 0); 59 | // WxXmlUtil.getRespTextXML(respText); 60 | // } 61 | 62 | 63 | } 64 | -------------------------------------------------------------------------------- /src/main/java/org/hamster/weixinmp/config/WxConfig.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package org.hamster.weixinmp.config; 5 | 6 | import lombok.Data; 7 | 8 | import org.springframework.beans.factory.annotation.Value; 9 | import org.springframework.context.annotation.Configuration; 10 | 11 | /** 12 | * @author grossopaforever@gmail.com 13 | * @version Jul 29, 2013 14 | * 15 | */ 16 | @Data 17 | @Configuration 18 | public class WxConfig { 19 | public static final String TABLE_PREFIX = "wx_"; 20 | public static final int COL_LEN_URL = 1024; 21 | public static final int COL_LEN_CONTENT = 4000; 22 | public static final int COL_LEN_TITLE = 200; 23 | public static final int COL_LEN_USER_NAME = 100; 24 | public static final int COL_LEN_INDICATOR = 64; 25 | 26 | private @Value("#{wxProperties.wx_token}") String token; 27 | private @Value("#{wxProperties.wx_appid}") String appid; 28 | private @Value("#{wxProperties.wx_appsecret}") String appsecret; 29 | 30 | private @Value("#{wxProperties.wx_menu_create_url}") String menuCreateUrl; 31 | private @Value("#{wxProperties.wx_menu_get_url}") String menuGetUrl; 32 | private @Value("#{wxProperties.wx_menu_delete_url}") String menuDeleteUrl; 33 | 34 | private @Value("#{wxProperties.wx_access_token_create_url}") String accessTokenCreateUrl; 35 | 36 | private @Value("#{wxProperties.wx_custom_send_url}") String customSendUrl; 37 | 38 | private @Value("#{wxProperties.wx_media_upload_url}") String mediaUploadUrl; 39 | 40 | private @Value("#{wxProperties.wx_qrcode_create_url}") String qrcodeCreateUrl; 41 | 42 | private @Value("#{wxProperties.wx_user_info_url}") String userInfoUrl; 43 | private @Value("#{wxProperties.wx_user_get_url}") String userGetUrl; 44 | 45 | private @Value("#{wxProperties.wx_groups_create_url}") String groupsCreateUrl; 46 | private @Value("#{wxProperties.wx_groups_get_url}") String groupsGetUrl; 47 | private @Value("#{wxProperties.wx_groups_getid_url}") String groupsGetIdUrl; 48 | private @Value("#{wxProperties.wx_groups_update_url}") String groupsUpdateUrl; 49 | private @Value("#{wxProperties.wx_groups_members_update_url}") String groupsMembersUpdateUrl; 50 | 51 | 52 | 53 | } 54 | -------------------------------------------------------------------------------- /src/main/java/org/hamster/weixinmp/controller/WxController.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package org.hamster.weixinmp.controller; 5 | 6 | import org.apache.log4j.Logger; 7 | import org.dom4j.DocumentException; 8 | import org.hamster.weixinmp.dao.entity.base.WxBaseMsgEntity; 9 | import org.hamster.weixinmp.dao.entity.base.WxBaseRespEntity; 10 | import org.hamster.weixinmp.exception.WxException; 11 | import org.hamster.weixinmp.service.WxAuthService; 12 | import org.hamster.weixinmp.service.WxMessageService; 13 | import org.springframework.beans.factory.annotation.Autowired; 14 | import org.springframework.stereotype.Controller; 15 | import org.springframework.web.bind.annotation.RequestBody; 16 | import org.springframework.web.bind.annotation.RequestMapping; 17 | import org.springframework.web.bind.annotation.RequestMethod; 18 | import org.springframework.web.bind.annotation.RequestParam; 19 | import org.springframework.web.bind.annotation.ResponseBody; 20 | 21 | 22 | /** 23 | * @author grossopaforever@gmail.com 24 | * @version Jul 28, 2013 25 | * 26 | */ 27 | @Controller 28 | @RequestMapping("/rest/weixinmp") 29 | public class WxController { 30 | private static final Logger log = Logger.getLogger(WxController.class); 31 | 32 | @Autowired 33 | private WxAuthService authService; 34 | @Autowired 35 | private WxMessageService messageService; 36 | 37 | @RequestMapping(method = {RequestMethod.GET,}) 38 | public @ResponseBody 39 | String authGet(@RequestParam("signature") String signature, 40 | @RequestParam("timestamp") String timestamp, 41 | @RequestParam("nonce") String nonce, 42 | @RequestParam("echostr") String echostr) throws WxException { 43 | if (authService.validateAuth(signature, timestamp, nonce, echostr)) { 44 | log.info("received authentication message from Weixin Server."); 45 | return echostr; 46 | } 47 | return null; 48 | } 49 | 50 | @RequestMapping(method = RequestMethod.POST) 51 | public @ResponseBody 52 | String post(@RequestBody String requestBody) throws DocumentException, WxException { 53 | WxBaseMsgEntity msg = messageService.parseXML(requestBody); 54 | log.info("received " + msg.getMsgType() + " message."); 55 | 56 | WxBaseRespEntity resp = messageService.handleMessage(msg); 57 | 58 | return messageService.parseRespXML(resp).asXML(); 59 | } 60 | 61 | } 62 | -------------------------------------------------------------------------------- /src/test/java/org/hamster/weixinmp/test/controller/WxControllerManualTest.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package org.hamster.weixinmp.test.controller; 5 | 6 | import java.io.IOException; 7 | import java.io.InputStream; 8 | import java.util.ArrayList; 9 | import java.util.List; 10 | 11 | import org.apache.commons.io.IOUtils; 12 | import org.apache.http.HttpEntity; 13 | import org.apache.http.HttpResponse; 14 | import org.apache.http.NameValuePair; 15 | import org.apache.http.client.ClientProtocolException; 16 | import org.apache.http.client.HttpClient; 17 | import org.apache.http.client.methods.HttpPost; 18 | import org.apache.http.entity.StringEntity; 19 | import org.apache.http.impl.client.HttpClientBuilder; 20 | import org.apache.http.message.BasicNameValuePair; 21 | import org.hamster.weixinmp.test.xml.WxXMLUtilTest; 22 | import org.junit.Ignore; 23 | import org.junit.Test; 24 | 25 | 26 | /** 27 | * @author grossopaforever@gmail.com 28 | * @version Jul 30, 2013 29 | */ 30 | public class WxControllerManualTest { 31 | 32 | public static final String WX_URL = "http://localhost:8080/rest/weixinmp"; 33 | 34 | @Test 35 | @Ignore 36 | public void testPostMsgText() throws ClientProtocolException, IOException { 37 | HttpClient httpclient = HttpClientBuilder.create().build(); 38 | HttpPost httppost = new HttpPost(WX_URL); 39 | 40 | // Request parameters and other properties. 41 | List params = new ArrayList(2); 42 | params.add(new BasicNameValuePair("signature", "38f004a5f222473f3abd85fd8e4b1de2349119c6")); 43 | params.add(new BasicNameValuePair("timestamp", "1375192987")); 44 | params.add(new BasicNameValuePair("nonce", "1374785014")); 45 | 46 | httppost.setEntity(new StringEntity(WxXMLUtilTest.MSG_TEXT_XML)); 47 | 48 | //Execute and get the response. 49 | HttpResponse response = httpclient.execute(httppost); 50 | HttpEntity entity = response.getEntity(); 51 | 52 | if (entity != null) { 53 | InputStream instream = entity.getContent(); 54 | try { 55 | String result = IOUtils.toString(instream); 56 | System.out.println(result); 57 | } finally { 58 | instream.close(); 59 | } 60 | } 61 | } 62 | 63 | public static final void main(String[] args) { 64 | try { 65 | new WxControllerManualTest().testPostMsgText(); 66 | } catch (ClientProtocolException e) { 67 | e.printStackTrace(); 68 | } catch (IOException e) { 69 | e.printStackTrace(); 70 | } 71 | } 72 | 73 | 74 | } 75 | -------------------------------------------------------------------------------- /src/main/java/org/hamster/weixinmp/service/WxMenuService.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package org.hamster.weixinmp.service; 5 | 6 | import static org.hamster.weixinmp.util.WxUtil.getAccessTokenParams; 7 | import static org.hamster.weixinmp.util.WxUtil.sendRequest; 8 | 9 | import java.io.UnsupportedEncodingException; 10 | import java.util.List; 11 | import java.util.Map; 12 | 13 | import org.apache.http.entity.StringEntity; 14 | import org.hamster.weixinmp.config.WxConfig; 15 | import org.hamster.weixinmp.dao.entity.menu.WxMenuBtnEntity; 16 | import org.hamster.weixinmp.dao.entity.user.WxUserEntity; 17 | import org.hamster.weixinmp.exception.WxException; 18 | import org.hamster.weixinmp.gson.WxMenuBtnSerializer; 19 | import org.hamster.weixinmp.model.WxRespCode; 20 | import org.hamster.weixinmp.model.menu.WxMenuCreateJson; 21 | import org.hamster.weixinmp.model.menu.WxMenuGetJson; 22 | import org.springframework.beans.factory.annotation.Autowired; 23 | import org.springframework.http.HttpMethod; 24 | import org.springframework.stereotype.Service; 25 | 26 | import com.google.gson.Gson; 27 | import com.google.gson.GsonBuilder; 28 | 29 | /** 30 | * @author grossopaforever@gmail.com 31 | * @version Jan 4, 2014 32 | * 33 | */ 34 | @Service 35 | public class WxMenuService { 36 | @Autowired 37 | WxConfig config; 38 | 39 | public WxRespCode menuCreate(String accessToken, List entities) 40 | throws WxException { 41 | Map params = getAccessTokenParams(accessToken); 42 | 43 | GsonBuilder gsonBuilder = new GsonBuilder(); 44 | gsonBuilder.registerTypeAdapter(WxUserEntity.class, 45 | new WxMenuBtnSerializer()); 46 | Gson gson = gsonBuilder.create(); 47 | 48 | WxMenuCreateJson wrapper = new WxMenuCreateJson(entities); 49 | wrapper.setButton(entities); 50 | 51 | try { 52 | return sendRequest(config.getMenuCreateUrl(), HttpMethod.POST, params, 53 | new StringEntity(gson.toJson(wrapper)), 54 | WxRespCode.class); 55 | } catch (UnsupportedEncodingException e) { 56 | throw new WxException(e); 57 | } 58 | } 59 | 60 | public List menuGet(String accessToken) throws WxException { 61 | Map params = getAccessTokenParams(accessToken); 62 | 63 | return sendRequest(config.getMenuGetUrl(), HttpMethod.GET, params, null, 64 | WxMenuGetJson.class).getMenu().getButton(); 65 | } 66 | 67 | public WxRespCode menuDelete(String accessToken) throws WxException { 68 | Map params = getAccessTokenParams(accessToken); 69 | return sendRequest(config.getMenuDeleteUrl(), HttpMethod.GET, params, null, 70 | WxRespCode.class); 71 | } 72 | 73 | 74 | } 75 | -------------------------------------------------------------------------------- /src/main/java/org/hamster/weixinmp/service/WxAuthService.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package org.hamster.weixinmp.service; 5 | 6 | import java.security.MessageDigest; 7 | import java.security.NoSuchAlgorithmException; 8 | import java.util.ArrayList; 9 | import java.util.Collections; 10 | import java.util.Date; 11 | import java.util.HashMap; 12 | import java.util.List; 13 | import java.util.Map; 14 | 15 | import org.hamster.weixinmp.config.WxConfig; 16 | import org.hamster.weixinmp.dao.entity.auth.WxAuth; 17 | import org.hamster.weixinmp.dao.entity.auth.WxAuthReq; 18 | import org.hamster.weixinmp.exception.WxException; 19 | import org.hamster.weixinmp.util.WxUtil; 20 | import org.slf4j.Logger; 21 | import org.slf4j.LoggerFactory; 22 | import org.springframework.beans.factory.annotation.Autowired; 23 | import org.springframework.http.HttpMethod; 24 | import org.springframework.stereotype.Service; 25 | 26 | /** 27 | * @author grossopaforever@gmail.com 28 | * @version Jan 1, 2014 29 | * 30 | */ 31 | @Service 32 | public class WxAuthService { 33 | 34 | private static final Logger log = LoggerFactory.getLogger(WxAuthService.class); 35 | 36 | @Autowired 37 | protected WxConfig config; 38 | 39 | public WxAuth getAccessToken(String appid, String appsecret) 40 | throws WxException { 41 | Map paramsJson = new HashMap(); 42 | paramsJson.put("grant_type", "client_credential"); 43 | paramsJson.put("appid", appid); 44 | paramsJson.put("secret", appsecret); 45 | 46 | WxAuth result = WxUtil.sendRequest(config.getAccessTokenCreateUrl(), 47 | HttpMethod.GET, paramsJson, null, WxAuth.class); 48 | result.setGrantType("client_credential"); 49 | result.setAppid(appid); 50 | result.setSecret(appsecret); 51 | return result; 52 | } 53 | 54 | public boolean validateAuth(String signature, String timestamp, 55 | String nonce, String echostr) throws WxException { 56 | WxAuthReq authReq = new WxAuthReq(); 57 | authReq.setCreatedDate(new Date()); 58 | authReq.setSignature(signature); 59 | authReq.setTimestamp(timestamp); 60 | authReq.setNonce(nonce); 61 | authReq.setEchostr(echostr); 62 | 63 | String excepted = hash(getStringToHash(timestamp, nonce, 64 | config.getToken())); 65 | 66 | if (signature == null || !signature.equals(excepted)) { 67 | log.error("Authentication failed! excepted echostr ->" + excepted); 68 | log.error(" actual ->" + signature); 69 | return false; 70 | } 71 | 72 | return true; 73 | } 74 | 75 | protected static String getStringToHash(String timestamp, String nonce, 76 | String token) { 77 | List list = new ArrayList(); 78 | list.add(timestamp); 79 | list.add(nonce); 80 | list.add(token); 81 | 82 | String result = ""; 83 | Collections.sort(list); 84 | for (int i = 0; i < list.size(); i++) { 85 | System.out.println(list.get(i)); 86 | result += list.get(i); 87 | } 88 | return result; 89 | } 90 | 91 | protected static String hash(String str) { 92 | try { 93 | MessageDigest md = MessageDigest.getInstance("SHA-1"); 94 | byte[] b = md.digest(str.getBytes()); 95 | StringBuffer sb = new StringBuffer(); 96 | for (int i = 0; i < b.length; i++) { 97 | sb.append(Integer.toString((b[i] & 0xff) + 0x100, 16) 98 | .substring(1)); 99 | } 100 | return sb.toString(); 101 | } catch (NoSuchAlgorithmException e) { 102 | // never happens 103 | } 104 | return null; 105 | } 106 | 107 | } 108 | -------------------------------------------------------------------------------- /src/test/resources/applicationContext-test-weixinmp.xml: -------------------------------------------------------------------------------- 1 | 2 | 15 | 16 | Weixin-MP Testing Configuration 17 | 18 | 20 | 21 | 23 | 24 | 25 | classpath:/application.development.properties 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | org.hibernate.cfg.ImprovedNamingStrategy 52 | create 53 | false 54 | false 55 | 56 | 57 | 58 | 59 | 62 | 63 | 64 | 66 | 67 | 68 | 69 | 70 | 71 | -------------------------------------------------------------------------------- /src/main/java/org/hamster/weixinmp/service/WxMediaService.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package org.hamster.weixinmp.service; 5 | 6 | import java.util.Date; 7 | import java.util.Map; 8 | 9 | import lombok.Data; 10 | 11 | import org.apache.http.entity.ContentType; 12 | import org.apache.http.entity.mime.MultipartEntityBuilder; 13 | import org.apache.http.entity.mime.content.ByteArrayBody; 14 | import org.apache.http.entity.mime.content.ContentBody; 15 | import org.hamster.weixinmp.config.WxConfig; 16 | import org.hamster.weixinmp.constant.WxMediaTypeEnum; 17 | import org.hamster.weixinmp.dao.entity.base.WxBaseItemMediaEntity; 18 | import org.hamster.weixinmp.dao.entity.item.WxItemImageEntity; 19 | import org.hamster.weixinmp.dao.entity.item.WxItemThumbEntity; 20 | import org.hamster.weixinmp.dao.entity.item.WxItemVideoEntity; 21 | import org.hamster.weixinmp.dao.entity.item.WxItemVoiceEntity; 22 | import org.hamster.weixinmp.exception.WxException; 23 | import org.hamster.weixinmp.util.WxUtil; 24 | import org.springframework.beans.factory.annotation.Autowired; 25 | import org.springframework.http.HttpMethod; 26 | import org.springframework.stereotype.Service; 27 | 28 | /** 29 | * @author grossopaforever@gmail.com 30 | * @version Jan 4, 2014 31 | * 32 | */ 33 | @Service 34 | public class WxMediaService { 35 | 36 | @Autowired 37 | WxConfig config; 38 | 39 | public WxBaseItemMediaEntity remoteMediaUpload(String accessToken, 40 | WxMediaTypeEnum type, byte[] content) throws WxException { 41 | MultipartEntityBuilder entityBuilder = MultipartEntityBuilder.create(); 42 | String typeString = null; 43 | switch (type) { 44 | case IMAGE: 45 | case THUMB: 46 | case VIDEO: 47 | case VOICE: 48 | typeString = type.toString().toLowerCase(); 49 | break; 50 | case MUSIC: 51 | case DEFAULT: 52 | case PIC_DESC: 53 | throw new WxException("Not supported upload type : " 54 | + type.toString()); 55 | default: 56 | break; 57 | } 58 | 59 | Map params = WxUtil.getAccessTokenParams(accessToken); 60 | System.out.println(typeString); 61 | params.put("type", typeString); 62 | ContentBody contentBody = new ByteArrayBody(content, ContentType.MULTIPART_FORM_DATA, "name.jpg"); 63 | entityBuilder.addPart("media", contentBody); 64 | MediaResultMapper result = WxUtil.sendRequest( 65 | config.getMediaUploadUrl(), HttpMethod.POST, params, 66 | entityBuilder.build(), MediaResultMapper.class); 67 | 68 | WxBaseItemMediaEntity resultEntity = null; 69 | switch (type) { 70 | case IMAGE: 71 | WxItemImageEntity imageEntity = new WxItemImageEntity(); 72 | imageEntity.setMediaId(result.getMedia_id()); 73 | imageEntity.setCreatedDate(new Date(result.getCreated_at() * 1000)); 74 | resultEntity = imageEntity; 75 | break; 76 | case THUMB: 77 | WxItemThumbEntity thumbEntity = new WxItemThumbEntity(); 78 | thumbEntity.setMediaId(result.getMedia_id()); 79 | thumbEntity.setCreatedDate(new Date(result.getCreated_at() * 1000)); 80 | resultEntity = thumbEntity; 81 | break; 82 | case VIDEO: 83 | WxItemVideoEntity videoEntity = new WxItemVideoEntity(); 84 | videoEntity.setMediaId(result.getMedia_id()); 85 | videoEntity.setCreatedDate(new Date(result.getCreated_at() * 1000)); 86 | resultEntity = videoEntity; 87 | break; 88 | case VOICE: 89 | WxItemVoiceEntity voiceEntity = new WxItemVoiceEntity(); 90 | voiceEntity.setMediaId(result.getMedia_id()); 91 | voiceEntity.setCreatedDate(new Date(result.getCreated_at() * 1000)); 92 | resultEntity = voiceEntity; 93 | break; 94 | case MUSIC: 95 | case DEFAULT: 96 | case PIC_DESC: 97 | throw new WxException("Not supported upload type : " 98 | + type.toString()); 99 | default: 100 | break; 101 | } 102 | return resultEntity; 103 | } 104 | 105 | } 106 | 107 | @Data 108 | class MediaResultMapper { 109 | private String type; 110 | private String media_id; 111 | private Long created_at; 112 | } -------------------------------------------------------------------------------- /src/main/java/org/hamster/weixinmp/util/WxUtil.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package org.hamster.weixinmp.util; 5 | 6 | import java.io.IOException; 7 | import java.net.URISyntaxException; 8 | import java.util.Date; 9 | import java.util.HashMap; 10 | import java.util.Map; 11 | 12 | import org.apache.http.Consts; 13 | import org.apache.http.HttpEntity; 14 | import org.apache.http.HttpResponse; 15 | import org.apache.http.client.HttpClient; 16 | import org.apache.http.client.methods.HttpGet; 17 | import org.apache.http.client.methods.HttpPost; 18 | import org.apache.http.client.methods.HttpRequestBase; 19 | import org.apache.http.client.utils.URIBuilder; 20 | import org.apache.http.entity.StringEntity; 21 | import org.apache.http.impl.client.HttpClientBuilder; 22 | import org.apache.http.util.EntityUtils; 23 | import org.hamster.weixinmp.dao.entity.base.WxBaseEntity; 24 | import org.hamster.weixinmp.exception.WxException; 25 | import org.hamster.weixinmp.model.WxRespCode; 26 | import org.springframework.http.HttpMethod; 27 | 28 | import com.google.gson.Gson; 29 | 30 | /** 31 | * @author grossopaforever@gmail.com 32 | * @version Jul 28, 2013 33 | * 34 | */ 35 | public class WxUtil { 36 | 37 | private WxUtil() { 38 | } 39 | 40 | public static final Long currentTimeInSec() { 41 | return Long.valueOf(new Date().getTime() / 1000); 42 | } 43 | 44 | @SuppressWarnings("unchecked") 45 | public static final T sendRequest(String url, HttpMethod method, 46 | Map params, HttpEntity requestEntity, 47 | Class resultClass) throws WxException { 48 | HttpClient client = HttpClientBuilder.create().build(); 49 | HttpRequestBase request = null; 50 | 51 | try { 52 | if (HttpMethod.GET.equals(method)) { 53 | request = new HttpGet(); 54 | } else if (HttpMethod.POST.equals(method)) { 55 | request = new HttpPost(); 56 | if (requestEntity != null) { 57 | ((HttpPost) request).setEntity(requestEntity); 58 | } 59 | } 60 | URIBuilder builder = new URIBuilder(url); 61 | 62 | if (params != null) { 63 | for (Map.Entry entry : params.entrySet()) { 64 | builder.addParameter(entry.getKey(), entry.getValue()); 65 | } 66 | } 67 | request.setURI(builder.build()); 68 | 69 | HttpResponse response = client.execute(request); 70 | HttpEntity entity = response.getEntity(); 71 | String respBody = EntityUtils.toString(entity); 72 | if (entity != null) { 73 | EntityUtils.consume(entity); 74 | } 75 | 76 | if (String.class.isAssignableFrom(resultClass)) { 77 | return (T) respBody; 78 | } else { 79 | Gson gson = new Gson(); 80 | 81 | if (respBody.indexOf("{\"errcode\"") == 0 82 | || respBody.indexOf("{\"errmsg\"") == 0) { 83 | WxRespCode exJson = gson.fromJson(respBody, 84 | WxRespCode.class); 85 | if (WxRespCode.class.getName().equals( 86 | resultClass.getName()) 87 | && exJson.getErrcode() == 0) { 88 | return (T) exJson; 89 | } else { 90 | throw new WxException(exJson); 91 | } 92 | } 93 | T result = gson.fromJson(respBody, resultClass); 94 | if (result instanceof WxBaseEntity) { 95 | ((WxBaseEntity) result).setCreatedDate(new Date()); 96 | } 97 | return result; 98 | } 99 | 100 | } catch (IOException e) { 101 | throw new WxException(e); 102 | } catch (URISyntaxException e) { 103 | throw new WxException(e); 104 | } 105 | } 106 | 107 | public static StringEntity toJsonStringEntity(Object obj) { 108 | Gson gson = new Gson(); 109 | return new StringEntity(gson.toJson(obj), Consts.UTF_8); 110 | } 111 | 112 | public static Map getAccessTokenParams(String accessToken) { 113 | Map result = new HashMap(); 114 | result.put("access_token", accessToken); 115 | return result; 116 | } 117 | 118 | public static String getParameterizedUrl(String url, String... args) { 119 | String result = url; 120 | for (int i = 0; i < args.length; i += 2) { 121 | String p = args[i]; 122 | String v = args[i + 1]; 123 | result = result.replaceAll(p, v); 124 | } 125 | return result; 126 | } 127 | 128 | } 129 | -------------------------------------------------------------------------------- /src/main/java/org/hamster/weixinmp/service/WxMessageService.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package org.hamster.weixinmp.service; 5 | 6 | import java.util.ArrayList; 7 | import java.util.Collections; 8 | import java.util.Comparator; 9 | import java.util.Date; 10 | import java.util.HashMap; 11 | import java.util.List; 12 | import java.util.Map; 13 | 14 | import org.dom4j.DocumentException; 15 | import org.dom4j.DocumentHelper; 16 | import org.dom4j.Element; 17 | import org.hamster.weixinmp.constant.WxMsgRespType; 18 | import org.hamster.weixinmp.constant.WxMsgRespTypeEnum; 19 | import org.hamster.weixinmp.constant.WxMsgTypeEnum; 20 | import org.hamster.weixinmp.controller.util.WxXmlUtil; 21 | import org.hamster.weixinmp.dao.entity.base.WxBaseMsgEntity; 22 | import org.hamster.weixinmp.dao.entity.base.WxBaseRespEntity; 23 | import org.hamster.weixinmp.dao.entity.resp.WxRespImageEntity; 24 | import org.hamster.weixinmp.dao.entity.resp.WxRespMusicEntity; 25 | import org.hamster.weixinmp.dao.entity.resp.WxRespPicDescEntity; 26 | import org.hamster.weixinmp.dao.entity.resp.WxRespTextEntity; 27 | import org.hamster.weixinmp.dao.entity.resp.WxRespVideoEntity; 28 | import org.hamster.weixinmp.dao.entity.resp.WxRespVoiceEntity; 29 | import org.hamster.weixinmp.exception.WxException; 30 | import org.hamster.weixinmp.service.handler.WxMessageHandlerIfc; 31 | import org.springframework.beans.factory.annotation.Autowired; 32 | import org.springframework.stereotype.Service; 33 | 34 | /** 35 | * @author grossopaforever@gmail.com 36 | * @version Dec 30, 2013 37 | * 38 | */ 39 | @Service 40 | public class WxMessageService { 41 | 42 | @Autowired(required=false) 43 | List handlers; 44 | 45 | public WxBaseMsgEntity parseXML(String xml) throws DocumentException, 46 | WxException { 47 | Element ele = DocumentHelper.parseText(xml).getRootElement(); 48 | String msgType = null; 49 | if ((msgType = ele.elementText("MsgType")) == null) { 50 | throw new WxException("cannot find MsgType Node!\n" + xml); 51 | } 52 | WxMsgTypeEnum msgTypeEnum = WxMsgTypeEnum.inst(msgType); 53 | switch (msgTypeEnum) { 54 | case EVENT: 55 | return WxXmlUtil.getMsgEvent(ele); 56 | case IMAGE: 57 | return WxXmlUtil.getMsgImage(ele); 58 | case LINK: 59 | return WxXmlUtil.getMsgLink(ele); 60 | case LOCATION: 61 | return WxXmlUtil.getMsgLoc(ele); 62 | case TEXT: 63 | return WxXmlUtil.getMsgText(ele); 64 | case VIDEO: 65 | return WxXmlUtil.getMsgVideo(ele); 66 | case VOICE: 67 | return WxXmlUtil.getMsgVoice(ele); 68 | default: 69 | // never happens 70 | break; 71 | } 72 | return null; 73 | } 74 | 75 | public WxBaseRespEntity handleMessage(WxBaseMsgEntity msg) { 76 | List handlerList = new ArrayList(); 77 | handlerList.addAll(handlers); 78 | Collections.sort(handlerList, new WxMessageHandlerComparator()); 79 | 80 | Map context = new HashMap(); 81 | WxBaseRespEntity result = null; 82 | for (WxMessageHandlerIfc handler : handlerList) { 83 | result = handler.handle(msg, context); 84 | } 85 | 86 | if (result == null) { 87 | result = defaultResult(msg.getToUserName(), msg.getFromUserName()); 88 | } 89 | return result; 90 | } 91 | 92 | public Element parseRespXML(WxBaseRespEntity resp) throws DocumentException { 93 | WxMsgRespTypeEnum type = WxMsgRespTypeEnum.inst(resp.getMsgType()); 94 | switch (type) { 95 | case IMAGE: 96 | return WxXmlUtil.getRespImage((WxRespImageEntity) resp); 97 | case MUSIC: 98 | return WxXmlUtil.getRespMusic((WxRespMusicEntity) resp, ((WxRespMusicEntity) resp).getThumb()); 99 | case NEWS: 100 | return WxXmlUtil.getRespPicDesc((WxRespPicDescEntity) resp); 101 | case TEXT: 102 | return WxXmlUtil.getRespTextXML((WxRespTextEntity) resp); 103 | case VIDEO: 104 | return WxXmlUtil.getRespVideo((WxRespVideoEntity) resp); 105 | case VOICE: 106 | return WxXmlUtil.getRespVoice((WxRespVoiceEntity) resp); 107 | default: 108 | break; 109 | } 110 | return null; 111 | } 112 | 113 | protected WxRespTextEntity defaultResult(String fromUserName, String toUserName) { 114 | WxRespTextEntity result = new WxRespTextEntity(); 115 | result.setContent("您好,您的消息已收到."); 116 | result.setCreatedDate(new Date()); 117 | result.setCreateTime(new Date().getTime() / 1000); 118 | result.setFromUserName(fromUserName); 119 | result.setMsgType(WxMsgRespType.TEXT); 120 | result.setToUserName(toUserName); 121 | return result; 122 | } 123 | 124 | 125 | } 126 | 127 | class WxMessageHandlerComparator implements Comparator { 128 | 129 | /* (non-Javadoc) 130 | * @see java.util.Comparator#compare(java.lang.Object, java.lang.Object) 131 | */ 132 | public int compare(WxMessageHandlerIfc o1, WxMessageHandlerIfc o2) { 133 | if (o1.priority() > o2.priority()) { 134 | return -1; 135 | } else if (o1.priority() < o2.priority()) { 136 | return 1; 137 | } else { 138 | return 0; 139 | } 140 | } 141 | 142 | } 143 | -------------------------------------------------------------------------------- /src/test/java/org/hamster/weixinmp/test/xml/WxXMLUtilTest.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package org.hamster.weixinmp.test.xml; 5 | 6 | import org.dom4j.DocumentException; 7 | import org.hamster.weixinmp.controller.util.WxXmlUtil; 8 | import org.hamster.weixinmp.dao.entity.base.WxBaseMsgEntity; 9 | import org.hamster.weixinmp.dao.entity.msg.WxMsgEventEntity; 10 | import org.hamster.weixinmp.dao.entity.msg.WxMsgImageEntity; 11 | import org.hamster.weixinmp.dao.entity.msg.WxMsgLinkEntity; 12 | import org.hamster.weixinmp.dao.entity.msg.WxMsgLocEntity; 13 | import org.hamster.weixinmp.dao.entity.msg.WxMsgTextEntity; 14 | import org.junit.Assert; 15 | import org.junit.Test; 16 | 17 | 18 | /** 19 | * @author grossopaforever@gmail.com 20 | * @version Jul 28, 2013 21 | * 22 | */ 23 | public class WxXMLUtilTest { 24 | 25 | public static final String MSG_TEXT_XML = "" 26 | + "" 27 | + " " 28 | + "1348831860" 29 | + "" 30 | + "" 31 | + "1234567890123456" + ""; 32 | 33 | @Test 34 | public void testGetMsgText() throws DocumentException { 35 | WxMsgTextEntity msgText = WxXmlUtil.getMsgText(WxXmlUtil.toXML(MSG_TEXT_XML)); 36 | assertBaseFieldsWithMsgId(msgText); 37 | Assert.assertEquals("this is a test", msgText.getContent()); 38 | } 39 | 40 | public static final String MSG_IMG_XML = "" 41 | + "" 42 | + "" 43 | + "1348831860" 44 | + "" 45 | + "" 46 | + "" 47 | + "1234567890123456" + ""; 48 | 49 | @Test 50 | public void testGetMsgImg() throws DocumentException { 51 | WxMsgImageEntity msgImg = WxXmlUtil.getMsgImage(WxXmlUtil.toXML(MSG_IMG_XML)); 52 | assertBaseFieldsWithMsgId(msgImg); 53 | //Assert.assertEquals("this is a url", msgImg.getImage().getPicUrl()); 54 | } 55 | 56 | public static final String MSG_LOC_XML = "" 57 | + "" 58 | + "" 59 | + "1351776360" 60 | + "" 61 | + "23.134521" 62 | + "113.358803" 63 | + "20" 64 | + "" 65 | + "1234567890123456" + " "; 66 | 67 | @Test 68 | public void testGetMsgLoc() throws DocumentException { 69 | WxMsgLocEntity msgLoc = WxXmlUtil.getMsgLoc(WxXmlUtil.toXML(MSG_LOC_XML)); 70 | assertBaseFieldsWithMsgId(msgLoc); 71 | Assert.assertEquals(Double.valueOf(23.134521d), msgLoc.getLocationX()); 72 | Assert.assertEquals(Double.valueOf(113.358803d), msgLoc.getLocationY()); 73 | Assert.assertEquals(Double.valueOf(20), msgLoc.getScale()); 74 | Assert.assertEquals("位置信息", msgLoc.getLabel()); 75 | } 76 | 77 | public static final String MSG_LINK_XML = "" 78 | + "" 79 | + "" 80 | + "1351776360" 81 | + "" 82 | + "<![CDATA[公众平台官网链接]]>" 83 | + "" 84 | + "" + "1234567890123456" 85 | + " "; 86 | 87 | @Test 88 | public void testGetMsgLink() throws DocumentException { 89 | WxMsgLinkEntity msgLink = WxXmlUtil.getMsgLink(WxXmlUtil.toXML(MSG_LINK_XML)); 90 | assertBaseFieldsWithMsgId(msgLink); 91 | Assert.assertEquals("公众平台官网链接", msgLink.getTitle()); 92 | Assert.assertEquals("公众平台官网链接123", msgLink.getDescription()); 93 | Assert.assertEquals("url", msgLink.getUrl()); 94 | } 95 | 96 | public static final String MSG_EVENT_XML = "" 97 | + "" 98 | + "" 99 | + "123456789" 100 | + "" 101 | + "" 102 | + "" + ""; 103 | 104 | @Test 105 | public void testGetMsgEvent() throws DocumentException { 106 | WxMsgEventEntity msgEvent = WxXmlUtil.getMsgEvent(WxXmlUtil.toXML(MSG_EVENT_XML)); 107 | assertBaseFields(msgEvent); 108 | Assert.assertEquals("EVENT", msgEvent.getEvent()); 109 | Assert.assertEquals("EVENTKEY", msgEvent.getEventKey()); 110 | } 111 | 112 | private void assertBaseFields(WxBaseMsgEntity entity) { 113 | Assert.assertNotNull(entity.getFromUserName()); 114 | Assert.assertNotNull(entity.getToUserName()); 115 | Assert.assertNotNull(entity.getCreateTime()); 116 | Assert.assertNotNull(entity.getMsgType()); 117 | } 118 | 119 | private void assertBaseFieldsWithMsgId(WxBaseMsgEntity entity) { 120 | assertBaseFields(entity); 121 | Assert.assertNotNull(entity.getMsgId()); 122 | } 123 | 124 | } 125 | -------------------------------------------------------------------------------- /src/main/java/org/hamster/weixinmp/service/WxUserGroupService.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package org.hamster.weixinmp.service; 5 | 6 | import static org.hamster.weixinmp.util.WxUtil.getAccessTokenParams; 7 | import static org.hamster.weixinmp.util.WxUtil.sendRequest; 8 | import static org.hamster.weixinmp.util.WxUtil.toJsonStringEntity; 9 | 10 | import java.util.HashMap; 11 | import java.util.List; 12 | import java.util.Map; 13 | 14 | import lombok.Data; 15 | import lombok.Getter; 16 | import lombok.Setter; 17 | 18 | import org.hamster.weixinmp.config.WxConfig; 19 | import org.hamster.weixinmp.dao.entity.user.WxGroupEntity; 20 | import org.hamster.weixinmp.exception.WxException; 21 | import org.hamster.weixinmp.model.WxRespCode; 22 | import org.springframework.beans.factory.annotation.Autowired; 23 | import org.springframework.http.HttpMethod; 24 | import org.springframework.stereotype.Service; 25 | 26 | /** 27 | * @author grossopaforever@gmail.com 28 | * @version Jan 1, 2014 29 | * 30 | */ 31 | @Service 32 | public class WxUserGroupService { 33 | @Autowired 34 | @Setter 35 | @Getter 36 | private WxConfig config; 37 | 38 | /** 39 | * http请求方式: POST(请使用https协议)
40 | * https://api.weixin.qq.com/cgi-bin/groups/create?access_token=ACCESS_TOKEN
41 | * POST数据格式:json
42 | * POST数据例子:{"group":{"name":"test"}}
43 | * 44 | * { "group": { "id": 107, "name": "test" } }
45 | * 46 | * @param groupName 47 | * @return 48 | * @throws WxException 49 | */ 50 | public WxGroupEntity remoteGroupsCreate(String accessToken, String groupName) 51 | throws WxException { 52 | Map requestJson = new HashMap(); 53 | Map l1Json = new HashMap(); 54 | l1Json.put("name", groupName); 55 | requestJson.put("group", l1Json); 56 | 57 | ResultMapper result = sendRequest(config.getGroupsCreateUrl(), 58 | HttpMethod.POST, getAccessTokenParams(accessToken), 59 | toJsonStringEntity(requestJson), ResultMapper.class); 60 | return result.getGroup(); 61 | } 62 | 63 | /** 64 | * http请求方式: GET(请使用https协议)
65 | * https://api.weixin.qq.com/cgi-bin/groups/get?access_token=ACCESS_TOKEN
66 | * 67 | * { "groups": [ { "id": 0, "name": "未分组", "count": 72596 }, { "id": 1, 68 | * "name": "黑名单", "count": 36 }, { "id": 2, "name": "星标组", "count": 8 }, { 69 | * "id": 104, "name": "华东媒", "count": 4 }, { "id": 106, "name": "★不测试组★", 70 | * "count": 1 } ] }
71 | * 72 | * @return 73 | * @throws WxException 74 | */ 75 | public List remoteGroupsGet(String accessToken) 76 | throws WxException { 77 | return sendRequest(config.getGroupsGetUrl(), HttpMethod.GET, 78 | getAccessTokenParams(accessToken), null, ResultMapper.class) 79 | .getGroups(); 80 | } 81 | 82 | /** 83 | * http请求方式: POST(请使用https协议)
84 | * https://api.weixin.qq.com/cgi-bin/groups/getid?access_token=ACCESS_TOKEN
85 | * POST数据格式:json POST数据例子:{"openid":"od8XIjsmk6QdVTETa9jLtGWA6KBc"}
86 | * {"groupid": 102 }
87 | * 88 | * @param openId 89 | * @return 90 | * @throws WxException 91 | */ 92 | public Long remoteGroupsGetId(String accessToken, String openId) 93 | throws WxException { 94 | Map requestJson = new HashMap(); 95 | requestJson.put("openid", openId); 96 | return sendRequest(config.getGroupsGetIdUrl(), HttpMethod.POST, 97 | getAccessTokenParams(accessToken), toJsonStringEntity(requestJson), 98 | ResultMapper.class).getGroupid(); 99 | } 100 | 101 | /** 102 | * http请求方式: POST(请使用https协议)
103 | * https://api.weixin.qq.com/cgi-bin/groups/update?access_token=ACCESS_TOKEN
104 | * POST数据格式:json
105 | * POST数据例子:{"group":{"id":108,"name":"test2_modify2"}}
106 | * 107 | * {"errcode": 0, "errmsg": "ok"}
108 | * 109 | * @param id 110 | * @param name 111 | * @return 112 | * @throws WxException 113 | */ 114 | public WxRespCode remoteGroupsUpdate(String accessToken, Long id, 115 | String name) throws WxException { 116 | Map requestJson = new HashMap(); 117 | Map l1Json = new HashMap(); 118 | l1Json.put("id", id); 119 | l1Json.put("name", name); 120 | requestJson.put("group", l1Json); 121 | return sendRequest(config.getGroupsUpdateUrl(), HttpMethod.POST, 122 | getAccessTokenParams(accessToken), toJsonStringEntity(requestJson), 123 | WxRespCode.class); 124 | } 125 | 126 | /** 127 | * http请求方式: POST(请使用https协议)
128 | * https://api.weixin.qq.com/cgi-bin/groups/members/update?access_token= 129 | * ACCESS_TOKEN
130 | * POST数据格式:json
131 | * POST数据例子:{"openid":"oDF3iYx0ro3_7jD4HFRDfrjdCM58","to_groupid":108}
132 | * {"errcode": 0, "errmsg": "ok"}
133 | * 134 | * @param openid 135 | * @param to_groupid 136 | * @return 137 | * @throws WxException 138 | */ 139 | public WxRespCode remoteGroupsMembersUpdate(String accessToken, 140 | String openid, Long to_groupid) throws WxException { 141 | Map requestJson = new HashMap(); 142 | requestJson.put("openid", openid); 143 | requestJson.put("to_groupid", to_groupid); 144 | return sendRequest(config.getGroupsMembersUpdateUrl(), HttpMethod.POST, 145 | getAccessTokenParams(accessToken), toJsonStringEntity(requestJson), 146 | WxRespCode.class); 147 | } 148 | 149 | } 150 | 151 | @Data 152 | final class ResultMapper { 153 | private WxGroupEntity group; 154 | private List groups; 155 | private Long groupid; 156 | } -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | weixin-mp 6 | Weixin Multi Platform 7 | 1.0.2 8 | org.hamster 9 | 10 | 11 | 0.11.0 12 | 1.3.2.RELEASE 13 | 2.2.2 14 | 3.1.3.RELEASE 15 | 1.7.2 16 | 1.2.17 17 | 2.4 18 | 4.3.1 19 | 3.1 20 | 4.1.8.Final 21 | 3.0.1 22 | 1.3.170 23 | 4.11 24 | 2.2.4 25 | 15.0 26 | 27 | UTF-8 28 | 29 | 30 | 31 | 32 | 33 | 34 | org.projectlombok 35 | lombok 36 | ${lombok.version} 37 | 38 | 39 | org.springframework.data 40 | spring-data-jpa 41 | ${spring-data-jpa.version} 42 | 43 | 44 | junit 45 | junit-dep 46 | 47 | 48 | 49 | 50 | 51 | cglib 52 | cglib 53 | ${cglib.version} 54 | 55 | 56 | 57 | com.google.code.gson 58 | gson 59 | ${gson.version} 60 | 61 | 62 | 63 | com.google.guava 64 | guava 65 | ${guava.version} 66 | 67 | 68 | 69 | 70 | org.springframework 71 | spring-webmvc 72 | ${spring.version} 73 | 74 | 75 | 76 | 77 | org.slf4j 78 | slf4j-api 79 | ${slf4j.version} 80 | 81 | 82 | org.slf4j 83 | slf4j-simple 84 | ${slf4j.version} 85 | 86 | 87 | org.slf4j 88 | slf4j-log4j12 89 | ${slf4j.version} 90 | 91 | 92 | org.slf4j 93 | jcl-over-slf4j 94 | ${slf4j.version} 95 | 96 | 97 | org.slf4j 98 | jul-to-slf4j 99 | ${slf4j.version} 100 | 101 | 102 | log4j 103 | log4j 104 | ${log4j.version} 105 | 106 | 107 | 108 | 109 | org.apache.httpcomponents 110 | httpclient 111 | ${httpclient.version} 112 | 113 | 114 | org.apache.httpcomponents 115 | httpmime 116 | ${httpclient.version} 117 | 118 | 119 | 120 | org.apache.commons 121 | commons-lang3 122 | ${commons-lang3.version} 123 | 124 | 125 | commons-io 126 | commons-io 127 | ${commons-io.version} 128 | 129 | 130 | 131 | org.hibernate 132 | hibernate-entitymanager 133 | ${hibernate.version} 134 | 135 | 136 | 137 | 138 | junit 139 | junit 140 | ${junit.version} 141 | test 142 | 143 | 144 | 145 | com.h2database 146 | h2 147 | ${h2.version} 148 | test 149 | 150 | 151 | 152 | org.springframework 153 | spring-test 154 | ${spring.version} 155 | test 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | org.projectlombok 165 | lombok 166 | 167 | 168 | org.springframework.data 169 | spring-data-jpa 170 | 171 | 172 | junit 173 | junit-dep 174 | 175 | 176 | 177 | 178 | 179 | cglib 180 | cglib 181 | 182 | 183 | 184 | com.google.code.gson 185 | gson 186 | 187 | 188 | 189 | com.google.guava 190 | guava 191 | 192 | 193 | 194 | 195 | org.springframework 196 | spring-webmvc 197 | 198 | 199 | 200 | 201 | org.slf4j 202 | slf4j-api 203 | 204 | 205 | org.slf4j 206 | slf4j-simple 207 | 208 | 209 | org.slf4j 210 | slf4j-log4j12 211 | 212 | 213 | org.slf4j 214 | jcl-over-slf4j 215 | 216 | 217 | org.slf4j 218 | jul-to-slf4j 219 | 220 | 221 | log4j 222 | log4j 223 | 224 | 225 | 226 | 227 | org.apache.httpcomponents 228 | httpclient 229 | 230 | 231 | org.apache.httpcomponents 232 | httpmime 233 | 234 | 235 | org.apache.commons 236 | commons-lang3 237 | 238 | 239 | commons-io 240 | commons-io 241 | 242 | 243 | 244 | org.hibernate 245 | hibernate-entitymanager 246 | 247 | 248 | 249 | 250 | junit 251 | junit 252 | test 253 | 254 | 255 | 256 | com.h2database 257 | h2 258 | test 259 | 260 | 261 | 262 | org.springframework 263 | spring-test 264 | test 265 | 266 | 267 | 268 | 269 | -------------------------------------------------------------------------------- /src/main/java/org/hamster/weixinmp/service/WxStorageService.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package org.hamster.weixinmp.service; 5 | 6 | import java.util.Date; 7 | import java.util.List; 8 | 9 | import lombok.Setter; 10 | 11 | import org.apache.log4j.Logger; 12 | import org.dom4j.DocumentException; 13 | import org.dom4j.Element; 14 | import org.hamster.weixinmp.config.WxConfig; 15 | import org.hamster.weixinmp.constant.WxMsgRespType; 16 | import org.hamster.weixinmp.controller.util.WxXmlUtil; 17 | import org.hamster.weixinmp.dao.entity.base.WxBaseMsgEntity; 18 | import org.hamster.weixinmp.dao.entity.base.WxBaseRespEntity; 19 | import org.hamster.weixinmp.dao.entity.item.WxItemMusicEntity; 20 | import org.hamster.weixinmp.dao.entity.item.WxItemPicDescEntity; 21 | import org.hamster.weixinmp.dao.entity.msg.WxMsgEventEntity; 22 | import org.hamster.weixinmp.dao.entity.msg.WxMsgImageEntity; 23 | import org.hamster.weixinmp.dao.entity.msg.WxMsgLinkEntity; 24 | import org.hamster.weixinmp.dao.entity.msg.WxMsgLocEntity; 25 | import org.hamster.weixinmp.dao.entity.msg.WxMsgTextEntity; 26 | import org.hamster.weixinmp.dao.entity.resp.WxRespMusicEntity; 27 | import org.hamster.weixinmp.dao.entity.resp.WxRespPicDescEntity; 28 | import org.hamster.weixinmp.dao.entity.resp.WxRespTextEntity; 29 | import org.hamster.weixinmp.dao.repository.auth.WxAuthDao; 30 | import org.hamster.weixinmp.dao.repository.auth.WxAuthReqDao; 31 | import org.hamster.weixinmp.dao.repository.item.WxItemImageDao; 32 | import org.hamster.weixinmp.dao.repository.item.WxItemMusicDao; 33 | import org.hamster.weixinmp.dao.repository.item.WxItemPicDescDao; 34 | import org.hamster.weixinmp.dao.repository.item.WxItemThumbDao; 35 | import org.hamster.weixinmp.dao.repository.item.WxItemVideoDao; 36 | import org.hamster.weixinmp.dao.repository.item.WxItemVoiceDao; 37 | import org.hamster.weixinmp.dao.repository.menu.WxMenuBtnDao; 38 | import org.hamster.weixinmp.dao.repository.msg.WxMsgEventDao; 39 | import org.hamster.weixinmp.dao.repository.msg.WxMsgImageDao; 40 | import org.hamster.weixinmp.dao.repository.msg.WxMsgLinkDao; 41 | import org.hamster.weixinmp.dao.repository.msg.WxMsgLocDao; 42 | import org.hamster.weixinmp.dao.repository.msg.WxMsgTextDao; 43 | import org.hamster.weixinmp.dao.repository.msg.WxMsgVideoDao; 44 | import org.hamster.weixinmp.dao.repository.msg.WxMsgVoiceDao; 45 | import org.hamster.weixinmp.dao.repository.resp.WxRespImageDao; 46 | import org.hamster.weixinmp.dao.repository.resp.WxRespMusicDao; 47 | import org.hamster.weixinmp.dao.repository.resp.WxRespPicDescDao; 48 | import org.hamster.weixinmp.dao.repository.resp.WxRespTextDao; 49 | import org.hamster.weixinmp.dao.repository.resp.WxRespVideoDao; 50 | import org.hamster.weixinmp.dao.repository.resp.WxRespVoiceDao; 51 | import org.hamster.weixinmp.dao.repository.user.WxGroupDao; 52 | import org.hamster.weixinmp.dao.repository.user.WxUserDao; 53 | import org.hamster.weixinmp.util.WxUtil; 54 | import org.springframework.beans.factory.annotation.Autowired; 55 | import org.springframework.stereotype.Service; 56 | import org.springframework.transaction.annotation.Transactional; 57 | 58 | /** 59 | * @author grossopaforever@gmail.com 60 | * @version Jul 28, 2013 61 | * 62 | */ 63 | @Service 64 | @Transactional(readOnly = true) 65 | public class WxStorageService { 66 | public static final Logger log = Logger.getLogger(WxStorageService.class); 67 | 68 | @Autowired(required = false) 69 | protected WxAuthDao authDao; 70 | @Autowired(required = false) 71 | protected WxAuthReqDao authReqDao; 72 | 73 | @Autowired(required = false) 74 | protected WxMsgTextDao msgTextDao; 75 | @Autowired(required = false) 76 | protected WxMsgImageDao msgImgDao; 77 | @Autowired(required = false) 78 | protected WxMsgLinkDao msgLinkDao; 79 | @Autowired(required = false) 80 | protected WxMsgLocDao msgLocDao; 81 | @Autowired(required = false) 82 | protected WxMsgEventDao msgEventDao; 83 | @Autowired(required = false) 84 | protected WxMsgVideoDao msgVideoDao; 85 | @Autowired(required = false) 86 | protected WxMsgVoiceDao msgVoiceDao; 87 | 88 | @Autowired(required = false) 89 | protected WxRespTextDao respTextDao; 90 | @Autowired(required = false) 91 | protected WxRespPicDescDao respPicDescDao; 92 | @Autowired(required = false) 93 | protected WxRespMusicDao respMusicDao; 94 | @Autowired(required = false) 95 | protected WxRespImageDao respImageDao; 96 | @Autowired(required = false) 97 | protected WxRespVideoDao respVideoDao; 98 | @Autowired(required = false) 99 | protected WxRespVoiceDao respVoiceDao; 100 | 101 | @Autowired(required = false) 102 | protected WxItemImageDao itemImageDao; 103 | @Autowired(required = false) 104 | protected WxItemMusicDao itemMusicDao; 105 | @Autowired(required = false) 106 | protected WxItemPicDescDao wxItemPicDescDao; 107 | @Autowired(required = false) 108 | protected WxItemThumbDao itemThumbDao; 109 | @Autowired(required = false) 110 | protected WxItemVideoDao itemVideoDao; 111 | @Autowired(required = false) 112 | protected WxItemVoiceDao itemVoiceDao; 113 | 114 | @Autowired(required = false) 115 | protected WxMenuBtnDao wxMenuBtnDao; 116 | 117 | @Autowired(required = false) 118 | protected WxGroupDao groupDao; 119 | @Autowired(required = false) 120 | protected WxUserDao userDao; 121 | 122 | @Setter 123 | protected String token; 124 | 125 | @Autowired(required = false) 126 | protected WxConfig wxConfig; 127 | 128 | public WxMsgTextEntity saveMsgText(Element ele) throws DocumentException { 129 | WxMsgTextEntity msgText = WxXmlUtil.getMsgText(ele); 130 | if (msgTextDao != null) { 131 | msgTextDao.save(msgText); 132 | } else { 133 | 134 | } 135 | return msgText; 136 | } 137 | 138 | public WxMsgImageEntity saveMsgImg(Element ele) throws DocumentException { 139 | WxMsgImageEntity msgImg = WxXmlUtil.getMsgImage(ele); 140 | if (msgImgDao != null) { 141 | msgImgDao.save(msgImg); 142 | } else { 143 | 144 | } 145 | return msgImg; 146 | } 147 | 148 | public WxMsgLinkEntity saveMsgLink(Element ele) throws DocumentException { 149 | WxMsgLinkEntity msgLink = WxXmlUtil.getMsgLink(ele); 150 | if (msgLinkDao != null) { 151 | msgLinkDao.save(msgLink); 152 | } else { 153 | 154 | } 155 | return msgLink; 156 | } 157 | 158 | public WxMsgLocEntity saveMsgLoc(Element ele) throws DocumentException { 159 | WxMsgLocEntity msgLoc = WxXmlUtil.getMsgLoc(ele); 160 | if (msgLocDao != null) { 161 | msgLocDao.save(msgLoc); 162 | } else { 163 | 164 | } 165 | return msgLoc; 166 | } 167 | 168 | public WxMsgEventEntity saveMsgEvent(Element ele) throws DocumentException { 169 | WxMsgEventEntity msgEvent = WxXmlUtil.getMsgEvent(ele); 170 | if (msgEventDao != null) { 171 | msgEventDao.save(msgEvent); 172 | } else { 173 | 174 | } 175 | return msgEvent; 176 | } 177 | 178 | public WxRespTextEntity createRespText(String content, String fromUserName, 179 | String toUserName, Integer funcFlag) { 180 | WxRespTextEntity respText = new WxRespTextEntity(); 181 | respText.setContent(content); 182 | respText.setCreatedDate(new Date()); 183 | respText.setCreateTime(WxUtil.currentTimeInSec()); 184 | respText.setFromUserName(fromUserName); 185 | respText.setToUserName(toUserName); 186 | respText.setFuncFlag(funcFlag); 187 | respText.setMsgType(WxMsgRespType.TEXT); 188 | if (respTextDao != null) { 189 | respTextDao.save(respText); 190 | } else { 191 | 192 | } 193 | return respText; 194 | } 195 | 196 | public WxRespPicDescEntity createRespPicDesc( 197 | List articles, String fromUserName, 198 | String toUserName, Integer funcFlag) { 199 | WxRespPicDescEntity respPicDesc = new WxRespPicDescEntity(); 200 | respPicDesc.setCreatedDate(new Date()); 201 | respPicDesc.setCreateTime(WxUtil.currentTimeInSec()); 202 | respPicDesc.setFromUserName(fromUserName); 203 | respPicDesc.setToUserName(toUserName); 204 | respPicDesc.setFuncFlag(funcFlag); 205 | respPicDesc.setMsgType(WxMsgRespType.NEWS); 206 | respPicDesc.setArticles(articles); 207 | if (respPicDescDao != null) { 208 | respPicDescDao.save(respPicDesc); 209 | } else { 210 | 211 | } 212 | return respPicDesc; 213 | } 214 | 215 | public WxRespPicDescEntity createRespPicDesc2(List articleIds, 216 | String fromUserName, String toUserName, Integer funcFlag) { 217 | WxRespPicDescEntity respPicDesc = new WxRespPicDescEntity(); 218 | respPicDesc.setCreatedDate(new Date()); 219 | respPicDesc.setCreateTime(WxUtil.currentTimeInSec()); 220 | respPicDesc.setFromUserName(fromUserName); 221 | respPicDesc.setToUserName(toUserName); 222 | respPicDesc.setFuncFlag(funcFlag); 223 | respPicDesc.setMsgType(WxMsgRespType.NEWS); 224 | respPicDesc.setArticles(wxItemPicDescDao.findByIdIn(articleIds)); 225 | if (respPicDescDao != null) { 226 | respPicDescDao.save(respPicDesc); 227 | } else { 228 | 229 | } 230 | return respPicDesc; 231 | } 232 | 233 | public WxRespMusicEntity createRespMusic(String fromUserName, 234 | String toUserName, Integer funcFlag, WxItemMusicEntity itemMusic) { 235 | WxRespMusicEntity respMusic = new WxRespMusicEntity(); 236 | respMusic.setCreatedDate(new Date()); 237 | respMusic.setCreateTime(WxUtil.currentTimeInSec()); 238 | respMusic.setFromUserName(fromUserName); 239 | respMusic.setToUserName(toUserName); 240 | respMusic.setFuncFlag(funcFlag); 241 | respMusic.setMsgType(WxMsgRespType.MUSIC); 242 | // respMusic.setMusic(itemMusic); 243 | if (respMusicDao != null) { 244 | respMusicDao.save(respMusic); 245 | } else { 246 | 247 | } 248 | return respMusic; 249 | } 250 | 251 | // /////////////// 252 | // common parts // 253 | // /////////////// 254 | public WxBaseRespEntity handleMessage(WxBaseMsgEntity msg) { 255 | WxRespTextEntity respText = createRespText( 256 | "Only test message, please ignore this.", msg.getToUserName(), 257 | msg.getFromUserName(), 1); 258 | return respText; 259 | } 260 | } 261 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, and 10 | distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by the copyright 13 | owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all other entities 16 | that control, are controlled by, or are under common control with that entity. 17 | For the purposes of this definition, "control" means (i) the power, direct or 18 | indirect, to cause the direction or management of such entity, whether by 19 | contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the 20 | outstanding shares, or (iii) beneficial ownership of such entity. 21 | 22 | "You" (or "Your") shall mean an individual or Legal Entity exercising 23 | permissions granted by this License. 24 | 25 | "Source" form shall mean the preferred form for making modifications, including 26 | but not limited to software source code, documentation source, and configuration 27 | files. 28 | 29 | "Object" form shall mean any form resulting from mechanical transformation or 30 | translation of a Source form, including but not limited to compiled object code, 31 | generated documentation, and conversions to other media types. 32 | 33 | "Work" shall mean the work of authorship, whether in Source or Object form, made 34 | available under the License, as indicated by a copyright notice that is included 35 | in or attached to the work (an example is provided in the Appendix below). 36 | 37 | "Derivative Works" shall mean any work, whether in Source or Object form, that 38 | is based on (or derived from) the Work and for which the editorial revisions, 39 | annotations, elaborations, or other modifications represent, as a whole, an 40 | original work of authorship. For the purposes of this License, Derivative Works 41 | shall not include works that remain separable from, or merely link (or bind by 42 | name) to the interfaces of, the Work and Derivative Works thereof. 43 | 44 | "Contribution" shall mean any work of authorship, including the original version 45 | of the Work and any modifications or additions to that Work or Derivative Works 46 | thereof, that is intentionally submitted to Licensor for inclusion in the Work 47 | by the copyright owner or by an individual or Legal Entity authorized to submit 48 | on behalf of the copyright owner. For the purposes of this definition, 49 | "submitted" means any form of electronic, verbal, or written communication sent 50 | to the Licensor or its representatives, including but not limited to 51 | communication on electronic mailing lists, source code control systems, and 52 | issue tracking systems that are managed by, or on behalf of, the Licensor for 53 | the purpose of discussing and improving the Work, but excluding communication 54 | that is conspicuously marked or otherwise designated in writing by the copyright 55 | owner as "Not a Contribution." 56 | 57 | "Contributor" shall mean Licensor and any individual or Legal Entity on behalf 58 | of whom a Contribution has been received by Licensor and subsequently 59 | incorporated within the Work. 60 | 61 | 2. Grant of Copyright License. 62 | 63 | Subject to the terms and conditions of this License, each Contributor hereby 64 | grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, 65 | irrevocable copyright license to reproduce, prepare Derivative Works of, 66 | publicly display, publicly perform, sublicense, and distribute the Work and such 67 | Derivative Works in Source or Object form. 68 | 69 | 3. Grant of Patent License. 70 | 71 | Subject to the terms and conditions of this License, each Contributor hereby 72 | grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, 73 | irrevocable (except as stated in this section) patent license to make, have 74 | made, use, offer to sell, sell, import, and otherwise transfer the Work, where 75 | such license applies only to those patent claims licensable by such Contributor 76 | that are necessarily infringed by their Contribution(s) alone or by combination 77 | of their Contribution(s) with the Work to which such Contribution(s) was 78 | submitted. If You institute patent litigation against any entity (including a 79 | cross-claim or counterclaim in a lawsuit) alleging that the Work or a 80 | Contribution incorporated within the Work constitutes direct or contributory 81 | patent infringement, then any patent licenses granted to You under this License 82 | for that Work shall terminate as of the date such litigation is filed. 83 | 84 | 4. Redistribution. 85 | 86 | You may reproduce and distribute copies of the Work or Derivative Works thereof 87 | in any medium, with or without modifications, and in Source or Object form, 88 | provided that You meet the following conditions: 89 | 90 | You must give any other recipients of the Work or Derivative Works a copy of 91 | this License; and 92 | You must cause any modified files to carry prominent notices stating that You 93 | changed the files; and 94 | You must retain, in the Source form of any Derivative Works that You distribute, 95 | all copyright, patent, trademark, and attribution notices from the Source form 96 | of the Work, excluding those notices that do not pertain to any part of the 97 | Derivative Works; and 98 | If the Work includes a "NOTICE" text file as part of its distribution, then any 99 | Derivative Works that You distribute must include a readable copy of the 100 | attribution notices contained within such NOTICE file, excluding those notices 101 | that do not pertain to any part of the Derivative Works, in at least one of the 102 | following places: within a NOTICE text file distributed as part of the 103 | Derivative Works; within the Source form or documentation, if provided along 104 | with the Derivative Works; or, within a display generated by the Derivative 105 | Works, if and wherever such third-party notices normally appear. The contents of 106 | the NOTICE file are for informational purposes only and do not modify the 107 | License. You may add Your own attribution notices within Derivative Works that 108 | You distribute, alongside or as an addendum to the NOTICE text from the Work, 109 | provided that such additional attribution notices cannot be construed as 110 | modifying the License. 111 | You may add Your own copyright statement to Your modifications and may provide 112 | additional or different license terms and conditions for use, reproduction, or 113 | distribution of Your modifications, or for any such Derivative Works as a whole, 114 | provided Your use, reproduction, and distribution of the Work otherwise complies 115 | with the conditions stated in this License. 116 | 117 | 5. Submission of Contributions. 118 | 119 | Unless You explicitly state otherwise, any Contribution intentionally submitted 120 | for inclusion in the Work by You to the Licensor shall be under the terms and 121 | conditions of this License, without any additional terms or conditions. 122 | Notwithstanding the above, nothing herein shall supersede or modify the terms of 123 | any separate license agreement you may have executed with Licensor regarding 124 | such Contributions. 125 | 126 | 6. Trademarks. 127 | 128 | This License does not grant permission to use the trade names, trademarks, 129 | service marks, or product names of the Licensor, except as required for 130 | reasonable and customary use in describing the origin of the Work and 131 | reproducing the content of the NOTICE file. 132 | 133 | 7. Disclaimer of Warranty. 134 | 135 | Unless required by applicable law or agreed to in writing, Licensor provides the 136 | Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, 137 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, 138 | including, without limitation, any warranties or conditions of TITLE, 139 | NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are 140 | solely responsible for determining the appropriateness of using or 141 | redistributing the Work and assume any risks associated with Your exercise of 142 | permissions under this License. 143 | 144 | 8. Limitation of Liability. 145 | 146 | In no event and under no legal theory, whether in tort (including negligence), 147 | contract, or otherwise, unless required by applicable law (such as deliberate 148 | and grossly negligent acts) or agreed to in writing, shall any Contributor be 149 | liable to You for damages, including any direct, indirect, special, incidental, 150 | or consequential damages of any character arising as a result of this License or 151 | out of the use or inability to use the Work (including but not limited to 152 | damages for loss of goodwill, work stoppage, computer failure or malfunction, or 153 | any and all other commercial damages or losses), even if such Contributor has 154 | been advised of the possibility of such damages. 155 | 156 | 9. Accepting Warranty or Additional Liability. 157 | 158 | While redistributing the Work or Derivative Works thereof, You may choose to 159 | offer, and charge a fee for, acceptance of support, warranty, indemnity, or 160 | other liability obligations and/or rights consistent with this License. However, 161 | in accepting such obligations, You may act only on Your own behalf and on Your 162 | sole responsibility, not on behalf of any other Contributor, and only if You 163 | agree to indemnify, defend, and hold each Contributor harmless for any liability 164 | incurred by, or claims asserted against, such Contributor by reason of your 165 | accepting any such warranty or additional liability. 166 | 167 | END OF TERMS AND CONDITIONS 168 | 169 | APPENDIX: How to apply the Apache License to your work 170 | 171 | To apply the Apache License to your work, attach the following boilerplate 172 | notice, with the fields enclosed by brackets "[]" replaced with your own 173 | identifying information. (Don't include the brackets!) The text should be 174 | enclosed in the appropriate comment syntax for the file format. We also 175 | recommend that a file or class name and description of purpose be included on 176 | the same "printed page" as the copyright notice for easier identification within 177 | third-party archives. 178 | 179 | Copyright [yyyy] [name of copyright owner] 180 | 181 | Licensed under the Apache License, Version 2.0 (the "License"); 182 | you may not use this file except in compliance with the License. 183 | You may obtain a copy of the License at 184 | 185 | http://www.apache.org/licenses/LICENSE-2.0 186 | 187 | Unless required by applicable law or agreed to in writing, software 188 | distributed under the License is distributed on an "AS IS" BASIS, 189 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 190 | See the License for the specific language governing permissions and 191 | limitations under the License. 192 | -------------------------------------------------------------------------------- /src/main/java/org/hamster/weixinmp/controller/util/WxXmlUtil.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package org.hamster.weixinmp.controller.util; 5 | 6 | import java.util.Date; 7 | 8 | import org.apache.commons.lang3.StringUtils; 9 | import org.dom4j.Document; 10 | import org.dom4j.DocumentException; 11 | import org.dom4j.DocumentHelper; 12 | import org.dom4j.Element; 13 | import org.hamster.weixinmp.constant.WxMsgTypeEnum; 14 | import org.hamster.weixinmp.dao.entity.auth.WxAuthReq; 15 | import org.hamster.weixinmp.dao.entity.base.WxBaseMsgEntity; 16 | import org.hamster.weixinmp.dao.entity.base.WxBaseRespEntity; 17 | import org.hamster.weixinmp.dao.entity.item.WxItemImageEntity; 18 | import org.hamster.weixinmp.dao.entity.item.WxItemPicDescEntity; 19 | import org.hamster.weixinmp.dao.entity.item.WxItemThumbEntity; 20 | import org.hamster.weixinmp.dao.entity.item.WxItemVideoEntity; 21 | import org.hamster.weixinmp.dao.entity.item.WxItemVoiceEntity; 22 | import org.hamster.weixinmp.dao.entity.msg.WxMsgEventEntity; 23 | import org.hamster.weixinmp.dao.entity.msg.WxMsgImageEntity; 24 | import org.hamster.weixinmp.dao.entity.msg.WxMsgLinkEntity; 25 | import org.hamster.weixinmp.dao.entity.msg.WxMsgLocEntity; 26 | import org.hamster.weixinmp.dao.entity.msg.WxMsgTextEntity; 27 | import org.hamster.weixinmp.dao.entity.msg.WxMsgVideoEntity; 28 | import org.hamster.weixinmp.dao.entity.msg.WxMsgVoiceEntity; 29 | import org.hamster.weixinmp.dao.entity.resp.WxRespImageEntity; 30 | import org.hamster.weixinmp.dao.entity.resp.WxRespMusicEntity; 31 | import org.hamster.weixinmp.dao.entity.resp.WxRespPicDescEntity; 32 | import org.hamster.weixinmp.dao.entity.resp.WxRespTextEntity; 33 | import org.hamster.weixinmp.dao.entity.resp.WxRespVideoEntity; 34 | import org.hamster.weixinmp.dao.entity.resp.WxRespVoiceEntity; 35 | import org.hamster.weixinmp.util.WxUtil; 36 | 37 | 38 | /** 39 | * @author grossopaforever@gmail.com 40 | * @version Jul 28, 2013 41 | * 42 | */ 43 | public class WxXmlUtil { 44 | 45 | private WxXmlUtil() { 46 | } 47 | 48 | public static WxAuthReq getAuthReq(String signature, String timestamp, 49 | String nonce, String echostr) { 50 | WxAuthReq result = new WxAuthReq(); 51 | result.setSignature(signature); 52 | result.setTimestamp(timestamp); 53 | result.setNonce(nonce); 54 | result.setEchostr(echostr); 55 | return result; 56 | } 57 | 58 | /** 59 | * 60 | * <xml>
61 | *   <ToUserName><![CDATA[toUser]]></ToUserName>
62 | *   <FromUserName><![CDATA[fromUser]]></ 63 | * FromUserName>
64 | *   <CreateTime>1348831860</CreateTime>
65 | *   <MsgType><![CDATA[text]]></MsgType>
66 | *   <Content><![CDATA[this is a 67 | * test]]></Content>
68 | *   <MsgId>1234567890123456</MsgId>
69 | * </xml>
70 | *
71 | * 72 | * @param xmlstr 73 | * @return 74 | * @throws DocumentException 75 | */ 76 | public static WxMsgTextEntity getMsgText(Element ele) throws DocumentException { 77 | WxMsgTextEntity result = msgEntityFactory(WxMsgTextEntity.class, ele); 78 | result.setMsgId(longVal(ele, "MsgId")); 79 | result.setContent(strVal(ele, "Content")); 80 | return result; 81 | } 82 | 83 | /** 84 | * 85 | * <xml> 86 | *   <ToUserName><![CDATA[toUser]]></ToUserName> 87 | *   <FromUserName><![CDATA[fromUser]]></FromUserName> 88 | *   <CreateTime>1348831860</CreateTime> 89 | *   <MsgType><![CDATA[image]]></MsgType> 90 | *   <PicUrl><![CDATA[this is a url]]></PicUrl> 91 | *   <MediaId><![CDATA[media_id]]></MediaId> 92 | *   <MsgId>1234567890123456</MsgId> 93 | * </xml> 94 | * 95 | * 96 | * @param xmlstr 97 | * @return 98 | * @throws DocumentException 99 | */ 100 | public static WxMsgImageEntity getMsgImage(Element ele) throws DocumentException { 101 | WxMsgImageEntity result = msgEntityFactory(WxMsgImageEntity.class, ele); 102 | WxItemImageEntity image = new WxItemImageEntity(); 103 | image.setMediaId(strVal(ele, "MediaId")); 104 | image.setPicUrl(strVal(ele, "PicUrl")); 105 | result.setImage(image); 106 | return result; 107 | } 108 | 109 | /** 110 | * 111 | * <xml>
112 | *   <ToUserName><![CDATA[toUser]]></ToUserName>
113 | *   <FromUserName><![CDATA[fromUser]]></FromUserName>
114 | *   <CreateTime>1357290913</CreateTime>
115 | *   <MsgType><![CDATA[voice]]></MsgType>
116 | *   <MediaId><![CDATA[media_id]]></MediaId>
117 | *   <Format><![CDATA[Format]]></Format>
118 | *   <MsgId>1234567890123456</MsgId>
119 | * </xml> 120 | *
121 | * 122 | * @param ele 123 | * @return 124 | * @throws DocumentException 125 | */ 126 | public static WxMsgVoiceEntity getMsgVoice(Element ele) throws DocumentException { 127 | WxMsgVoiceEntity result = msgEntityFactory(WxMsgVideoEntity.class, ele); 128 | WxItemVoiceEntity voice = new WxItemVoiceEntity(); 129 | voice.setMediaId(strVal(ele, "MediaId")); 130 | voice.setFormat(strVal(ele, "Format")); 131 | if (!StringUtils.isEmpty(ele.elementText("Recognition"))) { 132 | voice.setRecognition(strVal(ele, "Recognition")); 133 | } 134 | result.setVoice(voice); 135 | return result; 136 | } 137 | 138 | 139 | /** 140 | * 141 | * <xml>
142 | *   <ToUserName><![CDATA[toUser]]></ToUserName>
143 | *   <FromUserName><![CDATA[fromUser]]></FromUserName>
144 | *   <CreateTime>1357290913</CreateTime>
145 | *   <MsgType><![CDATA[video]]></MsgType>
146 | *   <MediaId><![CDATA[media_id]]></MediaId>
147 | *   <ThumbMediaId><![CDATA[thumb_media_id]]></ThumbMediaId>
148 | *   <MsgId>1234567890123456</MsgId>
149 | * </xml> 150 | *
151 | * @param ele 152 | * @return 153 | * @throws DocumentException 154 | */ 155 | public static WxMsgVideoEntity getMsgVideo(Element ele) throws DocumentException { 156 | WxMsgVideoEntity result = msgEntityFactory(WxMsgVideoEntity.class, ele); 157 | WxItemVideoEntity video = new WxItemVideoEntity(); 158 | video.setMediaId(strVal(ele, "MediaId")); 159 | WxItemThumbEntity thumb = new WxItemThumbEntity(); 160 | thumb.setMediaId(strVal(ele, "ThumbMediaId")); 161 | video.setThumb(thumb); 162 | result.setVideo(video); 163 | return result; 164 | } 165 | 166 | /** 167 | * 168 | * <xml>
169 | *   <ToUserName><![CDATA[toUser]]></ToUserName>
170 | *   <FromUserName><![CDATA[fromUser]]></FromUserName>
171 | *   <CreateTime>1351776360</CreateTime>
172 | *   <MsgType><![CDATA[location]]></MsgType>
173 | *   <Location_X>23.134521</Location_X>
174 | *   <Location_Y>113.358803</Location_Y>
175 | *   <Scale>20</Scale>
176 | *   <Label><![CDATA[Location Information]]></Label>
177 | *   <MsgId>1234567890123456</MsgId>
178 | * </xml> 179 | *
180 | * 181 | * 182 | * @param xmlstr 183 | * @return 184 | * @throws DocumentException 185 | */ 186 | public static WxMsgLocEntity getMsgLoc(Element ele) throws DocumentException { 187 | WxMsgLocEntity result = msgEntityFactory(WxMsgLocEntity.class, ele); 188 | result.setLabel(strVal(ele, "Label")); 189 | result.setLocationX(doubleVal(ele, "Location_X")); 190 | result.setLocationY(doubleVal(ele, "Location_Y")); 191 | result.setScale(doubleVal(ele, "Scale")); 192 | return result; 193 | } 194 | 195 | /** 196 | * 197 | * <xml>
198 | *   <ToUserName><![CDATA[toUser]]></ToUserName>
199 | *   <FromUserName><![CDATA[fromUser]]></FromUserName>
200 | *   <CreateTime>1351776360</CreateTime>
201 | *   <MsgType><![CDATA[link]]></MsgType>
202 | *   <Title><![CDATA[公众平台官网链接]]></Title>
203 | *   <Description><![CDATA[公众平台官网链接]]></Description>
204 | *   <Url><![CDATA[url]]></Url>
205 | *   <MsgId>1234567890123456</MsgId>
206 | * </xml> 207 | *
208 | * 209 | * @param xmlstr 210 | * @return 211 | * @throws DocumentException 212 | */ 213 | public static WxMsgLinkEntity getMsgLink(Element ele) throws DocumentException { 214 | WxMsgLinkEntity result = msgEntityFactory(WxMsgLinkEntity.class, ele); 215 | result.setTitle(strVal(ele, "Title")); 216 | result.setDescription(strVal(ele, "Description")); 217 | result.setUrl(strVal(ele, "Url")); 218 | return result; 219 | } 220 | 221 | /** 222 | * 223 | * <xml>
224 | *   <ToUserName><![CDATA[toUser]]></ToUserName>
225 | *   <FromUserName><![CDATA[FromUser]]></FromUserName>
226 | *   <CreateTime>123456789</CreateTime>
227 | *   <MsgType><![CDATA[event]]></MsgType>
228 | *   <Event><![CDATA[EVENT]]></Event>
229 | *   <EventKey><![CDATA[EVENTKEY]]></EventKey>
230 | * </xml> 231 | *
232 | * 233 | * @param xmlstr 234 | * @return 235 | * @throws DocumentException 236 | */ 237 | public static WxMsgEventEntity getMsgEvent(Element ele) throws DocumentException { 238 | WxMsgEventEntity result = msgEntityFactory(WxMsgEventEntity.class, ele); 239 | result.setEvent(strVal(ele, "Event")); 240 | if (ele.elementText("EventKey") != null) { 241 | result.setEventKey(strVal(ele, "EventKey")); 242 | } 243 | if (ele.elementText("Ticket") != null) { 244 | result.setEventKey(strVal(ele, "Ticket")); 245 | } 246 | return result; 247 | } 248 | 249 | /** 250 | * 251 | * <xml>
252 | *   <ToUserName><![CDATA[toUser]]></ToUserName>
253 | *   <FromUserName><![CDATA[fromUser]]></FromUserName>
254 | *   <CreateTime>12345678</CreateTime>
255 | *   <MsgType><![CDATA[text]]></MsgType>
256 | *   <Content><![CDATA[content]]></Content>
257 | *   <FuncFlag>0</FuncFlag>
258 | * </xml> 259 | *
260 | * 261 | * @param respText 262 | * @return 263 | * @throws DocumentException 264 | */ 265 | public static Element getRespTextXML(WxRespTextEntity respText) throws DocumentException { 266 | Element ele = respEntityFactory(respText); 267 | ele.addElement("Content").addCDATA(respText.getContent()); 268 | return ele; 269 | } 270 | 271 | /** 272 | * 273 | * <xml>
274 | *   <ToUserName><![CDATA[toUser]]></ToUserName>
275 | *   <FromUserName><![CDATA[fromUser]]></FromUserName>
276 | *   <CreateTime>12345678</CreateTime>
277 | *   <MsgType><![CDATA[image]]></MsgType>
278 | *   <Image>
279 | *     <MediaId><![CDATA[media_id]]></MediaId>
280 | *   </Image>
281 | * </xml>
282 | *
283 | * 284 | * @param respImage 285 | * @return 286 | * @throws DocumentException 287 | */ 288 | public static Element getRespImage(WxRespImageEntity respImage) throws DocumentException { 289 | Element ele = respEntityFactory(respImage); 290 | Element imageEle = ele.addElement("Image"); 291 | imageEle.addElement("MediaId").addCDATA(respImage.getImage().getMediaId()); 292 | return ele; 293 | } 294 | 295 | /** 296 | * 297 | * <xml>
298 | *   <ToUserName><![CDATA[toUser]]></ToUserName>
299 | *   <FromUserName><![CDATA[fromUser]]></FromUserName>
300 | *   <CreateTime>12345678</CreateTime>
301 | *   <MsgType><![CDATA[voice]]></MsgType>
302 | *   <Voice>
303 | *     <MediaId><![CDATA[media_id]]></MediaId>
304 | *   </Voice>
305 | * </xml>
306 | *
307 | * 308 | * @param respVoice 309 | * @return 310 | * @throws DocumentException 311 | */ 312 | public static Element getRespVoice(WxRespVoiceEntity respVoice) throws DocumentException { 313 | Element ele = respEntityFactory(respVoice); 314 | Element voiceEle = ele.addElement("Voice"); 315 | voiceEle.addElement("MediaId").addCDATA(respVoice.getVoice().getMediaId()); 316 | return ele; 317 | } 318 | 319 | /** 320 | * 321 | * <xml>
322 | *   <ToUserName><![CDATA[toUser]]></ToUserName>
323 | *   <FromUserName><![CDATA[fromUser]]></FromUserName>
324 | *   <CreateTime>12345678</CreateTime>
325 | *   <MsgType><![CDATA[video]]></MsgType>
326 | *   <Video>
327 | *     <MediaId><![CDATA[media_id]]></MediaId>
328 | *     <Title><![CDATA[title]]></Title>
329 | *     <Description><![CDATA[description]]></Description>
330 | *   </Video>
331 | * </xml>
332 | *
333 | * 334 | * @param respVideo 335 | * @return 336 | * @throws DocumentException 337 | */ 338 | public static Element getRespVideo(WxRespVideoEntity respVideo) throws DocumentException { 339 | Element ele = respEntityFactory(respVideo); 340 | Element videoEle = ele.addElement("Video"); 341 | videoEle.addElement("MediaId").addCDATA(respVideo.getVideo().getMediaId()); 342 | videoEle.addElement("Title").addCDATA(StringUtils.defaultString(respVideo.getVideo().getTitle())); 343 | videoEle.addElement("Description").addCDATA(StringUtils.defaultString(respVideo.getVideo().getDescription())); 344 | return ele; 345 | } 346 | 347 | /** 348 | * 349 | * <xml>
350 | *   <ToUserName><![CDATA[toUser]]></ToUserName>
351 | *   <FromUserName><![CDATA[fromUser]]></FromUserName>
352 | *   <CreateTime>12345678</CreateTime>
353 | *   <MsgType><![CDATA[music]]></MsgType>
354 | *   <Music>
355 | *     <Title><![CDATA[TITLE]]></Title>
356 | *     <Description><![CDATA[DESCRIPTION]]></Description>
357 | *     <MusicUrl><![CDATA[MUSIC_Url]]></MusicUrl>
358 | *     <HQMusicUrl><![CDATA[HQ_MUSIC_Url]]></HQMusicUrl>
359 | *     <ThumbMediaId><![CDATA[media_id]]></ThumbMediaId>
360 | *   </Music>
361 | *   <FuncFlag>0</FuncFlag>
362 | * </xml> 363 | *
364 | * 365 | * @param respMusic 366 | * @return 367 | * @throws DocumentException 368 | */ 369 | public static Element getRespMusic(WxRespMusicEntity respMusic, WxItemThumbEntity thumb) throws DocumentException { 370 | Element ele = respEntityFactory(respMusic); 371 | Element musicEle = ele.addElement("Music"); 372 | musicEle.addElement("Title").addCDATA(StringUtils.defaultString(respMusic.getMusic().getTitle())); 373 | musicEle.addElement("Description").addCDATA(StringUtils.defaultString(respMusic.getMusic().getDescription())); 374 | musicEle.addElement("MusicUrl").addCDATA(StringUtils.defaultString(respMusic.getMusic().getMusicUrl())); 375 | musicEle.addElement("HQMusicUrl").addCDATA(StringUtils.defaultString(respMusic.getMusic().getHqMusicUrl())); 376 | musicEle.addElement("ThumbMediaId").addCDATA(thumb.getMediaId()); 377 | return ele; 378 | } 379 | 380 | /** 381 | * 382 | * <xml>
383 | *   <ToUserName><![CDATA[toUser]]></ToUserName>
384 | *   <FromUserName><![CDATA[fromUser]]></FromUserName>
385 | *   <CreateTime>12345678</CreateTime>
386 | *   <MsgType><![CDATA[news]]></MsgType>
387 | *   <ArticleCount>2</ArticleCount>
388 | *   <Articles>
389 | *     <item>
390 | *       <Title><![CDATA[title1]]></Title>
391 | *       <Description><![CDATA[description1]]></Description>
392 | *       <PicUrl><![CDATA[picurl]]></PicUrl>
393 | *       <Url><![CDATA[url]]></Url>
394 | *     </item>
395 | *     <item>
396 | *       <Title><![CDATA[title]]></Title>
397 | *       <Description><![CDATA[description]]></Description>
398 | *       <PicUrl><![CDATA[picurl]]></PicUrl>
399 | *       <Url><![CDATA[url]]></Url>
400 | *     </item>
401 | *   </Articles>
402 | *   <FuncFlag>1</FuncFlag>
403 | * </xml> 404 | *
405 | * 406 | * @param respPicDesc 407 | * @return 408 | * @throws DocumentException 409 | */ 410 | public static Element getRespPicDesc(WxRespPicDescEntity respPicDesc) throws DocumentException { 411 | Element ele = respEntityFactory(respPicDesc); 412 | ele.addElement("ArticleCount").addText(String.valueOf(respPicDesc.getArticles().size())); 413 | Element articlesEle = ele.addElement("Articles"); 414 | for (WxItemPicDescEntity item : respPicDesc.getArticles()) { 415 | Element itemEle = articlesEle.addElement("item"); 416 | itemEle.addElement("Title").addCDATA(item.getTitle()); 417 | itemEle.addElement("Description").addCDATA(item.getDescription()); 418 | itemEle.addElement("PicUrl").addCDATA(item.getPicUrl()); 419 | itemEle.addElement("HQMusicUrl").addCDATA(item.getUrl()); 420 | } 421 | return ele; 422 | } 423 | 424 | public static Element toXML(String xmlstr) throws DocumentException { 425 | Document doc = DocumentHelper.parseText(xmlstr); 426 | return doc.getRootElement(); 427 | } 428 | 429 | public static WxMsgTypeEnum getReqType(Element ele) { 430 | String type = ele.element("MsgType").getTextTrim(); 431 | return WxMsgTypeEnum.inst(type); 432 | } 433 | 434 | 435 | ////////////////////////////////////////////////// 436 | // Private Methods // 437 | ////////////////////////////////////////////////// 438 | 439 | @SuppressWarnings("unchecked") 440 | private static T msgEntityFactory( 441 | Class clazz, Element ele) { 442 | WxBaseMsgEntity result; 443 | try { 444 | result = clazz.newInstance(); 445 | result.setToUserName(strVal(ele, "ToUserName")); 446 | result.setFromUserName(strVal(ele, "FromUserName")); 447 | result.setCreateTime(longVal(ele, "CreateTime")); 448 | result.setCreatedDate(new Date()); 449 | result.setMsgType(strVal(ele, "MsgType")); 450 | if (ele.element("MsgId") != null) { 451 | result.setMsgId(longVal(ele, "MsgId")); 452 | } 453 | return (T) result; 454 | } catch (Exception e) { 455 | // never occurs 456 | return null; 457 | } 458 | } 459 | 460 | private static Element respEntityFactory(WxBaseRespEntity entity) { 461 | Element ele = DocumentHelper.createElement("xml"); 462 | ele.addElement("ToUserName").addCDATA(entity.getToUserName()); 463 | ele.addElement("FromUserName").addCDATA(entity.getFromUserName()); 464 | String createTime = String.valueOf(entity.getCreateTime()); 465 | if (StringUtils.isBlank(createTime)) { 466 | Long currentTime = WxUtil.currentTimeInSec(); 467 | entity.setCreateTime(currentTime); 468 | createTime = String.valueOf(currentTime); 469 | } 470 | ele.addElement("CreateTime").setText(createTime); 471 | ele.addElement("MsgType").addCDATA(entity.getMsgType()); 472 | ele.addElement("FuncFlag").setText(String.valueOf(entity.getFuncFlag())); 473 | return ele; 474 | } 475 | 476 | private static String strVal(Element ele, String name) { 477 | return ele.element(name).getStringValue(); 478 | } 479 | 480 | private static Long longVal(Element ele, String name) { 481 | return Long.valueOf(ele.element(name).getStringValue()); 482 | } 483 | 484 | private static Double doubleVal(Element ele, String name) { 485 | return Double.valueOf(ele.element(name).getStringValue()); 486 | } 487 | 488 | } 489 | --------------------------------------------------------------------------------