├── .classpath ├── .gitignore ├── .project ├── LICENSE ├── META-INF ├── LICENSE ├── NOTICE.txt ├── README.md └── wechat4j.properties.sample ├── README.md ├── doc ├── api │ ├── allclasses-frame.html │ ├── allclasses-noframe.html │ ├── constant-values.html │ ├── deprecated-list.html │ ├── help-doc.html │ ├── index-files │ │ ├── index-1.html │ │ ├── index-10.html │ │ ├── index-11.html │ │ ├── index-12.html │ │ ├── index-13.html │ │ ├── index-14.html │ │ ├── index-15.html │ │ ├── index-16.html │ │ ├── index-17.html │ │ ├── index-2.html │ │ ├── index-3.html │ │ ├── index-4.html │ │ ├── index-5.html │ │ ├── index-6.html │ │ ├── index-7.html │ │ ├── index-8.html │ │ └── index-9.html │ ├── index.html │ ├── org │ │ └── sword │ │ │ └── wechat4j │ │ │ ├── WechatSupport.html │ │ │ ├── class-use │ │ │ └── WechatSupport.html │ │ │ ├── common │ │ │ ├── Config.html │ │ │ ├── MediaFile.html │ │ │ ├── MediaType.html │ │ │ ├── ValidateSignature.html │ │ │ ├── class-use │ │ │ │ ├── Config.html │ │ │ │ ├── MediaFile.html │ │ │ │ ├── MediaType.html │ │ │ │ └── ValidateSignature.html │ │ │ ├── package-frame.html │ │ │ ├── package-summary.html │ │ │ ├── package-tree.html │ │ │ └── package-use.html │ │ │ ├── event │ │ │ ├── EventType.html │ │ │ ├── MsgType.html │ │ │ ├── class-use │ │ │ │ ├── EventType.html │ │ │ │ └── MsgType.html │ │ │ ├── package-frame.html │ │ │ ├── package-summary.html │ │ │ ├── package-tree.html │ │ │ └── package-use.html │ │ │ ├── message │ │ │ ├── CustomerMsg.html │ │ │ ├── TemplateMsg.html │ │ │ ├── class-use │ │ │ │ ├── CustomerMsg.html │ │ │ │ └── TemplateMsg.html │ │ │ ├── package-frame.html │ │ │ ├── package-summary.html │ │ │ ├── package-tree.html │ │ │ ├── package-use.html │ │ │ └── template │ │ │ │ ├── TemplateMsgBody.html │ │ │ │ ├── TemplateMsgData.html │ │ │ │ ├── class-use │ │ │ │ ├── TemplateMsgBody.html │ │ │ │ └── TemplateMsgData.html │ │ │ │ ├── package-frame.html │ │ │ │ ├── package-summary.html │ │ │ │ ├── package-tree.html │ │ │ │ └── package-use.html │ │ │ ├── package-frame.html │ │ │ ├── package-summary.html │ │ │ ├── package-tree.html │ │ │ ├── package-use.html │ │ │ ├── param │ │ │ ├── SignatureParam.html │ │ │ ├── WechatParamName.html │ │ │ ├── class-use │ │ │ │ ├── SignatureParam.html │ │ │ │ └── WechatParamName.html │ │ │ ├── package-frame.html │ │ │ ├── package-summary.html │ │ │ ├── package-tree.html │ │ │ └── package-use.html │ │ │ ├── request │ │ │ ├── Item.html │ │ │ ├── ScanCodeInfo.html │ │ │ ├── SendLocationInfo.html │ │ │ ├── SendPicsInfo.html │ │ │ ├── WechatRequest.html │ │ │ ├── class-use │ │ │ │ ├── Item.html │ │ │ │ ├── ScanCodeInfo.html │ │ │ │ ├── SendLocationInfo.html │ │ │ │ ├── SendPicsInfo.html │ │ │ │ └── WechatRequest.html │ │ │ ├── package-frame.html │ │ │ ├── package-summary.html │ │ │ ├── package-tree.html │ │ │ └── package-use.html │ │ │ ├── response │ │ │ ├── ArticleResponse.html │ │ │ ├── ImageResponse.html │ │ │ ├── MusicResponse.html │ │ │ ├── VideoResponse.html │ │ │ ├── VoiceResponse.html │ │ │ ├── WechatResponse.html │ │ │ ├── class-use │ │ │ │ ├── ArticleResponse.html │ │ │ │ ├── ImageResponse.html │ │ │ │ ├── MusicResponse.html │ │ │ │ ├── VideoResponse.html │ │ │ │ ├── VoiceResponse.html │ │ │ │ └── WechatResponse.html │ │ │ ├── package-frame.html │ │ │ ├── package-summary.html │ │ │ ├── package-tree.html │ │ │ └── package-use.html │ │ │ ├── token │ │ │ ├── AccessToken.html │ │ │ ├── Ticket.html │ │ │ ├── TicketType.html │ │ │ ├── Token.html │ │ │ ├── TokenListener.html │ │ │ ├── TokenProxy.html │ │ │ ├── class-use │ │ │ │ ├── AccessToken.html │ │ │ │ ├── Ticket.html │ │ │ │ ├── TicketType.html │ │ │ │ ├── Token.html │ │ │ │ ├── TokenListener.html │ │ │ │ └── TokenProxy.html │ │ │ ├── package-frame.html │ │ │ ├── package-summary.html │ │ │ ├── package-tree.html │ │ │ ├── package-use.html │ │ │ ├── server │ │ │ │ ├── AbsServer.html │ │ │ │ ├── AccessTokenMemServer.html │ │ │ │ ├── AccessTokenServer.html │ │ │ │ ├── CustomerServer.html │ │ │ │ ├── IServer.html │ │ │ │ ├── JsApiTicketMemServer.html │ │ │ │ ├── JsApiTicketServer.html │ │ │ │ ├── TicketServer.html │ │ │ │ ├── TokenServer.html │ │ │ │ ├── class-use │ │ │ │ │ ├── AbsServer.html │ │ │ │ │ ├── AccessTokenMemServer.html │ │ │ │ │ ├── AccessTokenServer.html │ │ │ │ │ ├── CustomerServer.html │ │ │ │ │ ├── IServer.html │ │ │ │ │ ├── JsApiTicketMemServer.html │ │ │ │ │ ├── JsApiTicketServer.html │ │ │ │ │ ├── TicketServer.html │ │ │ │ │ └── TokenServer.html │ │ │ │ ├── package-frame.html │ │ │ │ ├── package-summary.html │ │ │ │ ├── package-tree.html │ │ │ │ └── package-use.html │ │ │ └── timer │ │ │ │ ├── AccessTokenTimer.html │ │ │ │ ├── JsApiTicketTimer.html │ │ │ │ ├── class-use │ │ │ │ ├── AccessTokenTimer.html │ │ │ │ └── JsApiTicketTimer.html │ │ │ │ ├── package-frame.html │ │ │ │ ├── package-summary.html │ │ │ │ ├── package-tree.html │ │ │ │ └── package-use.html │ │ │ └── user │ │ │ ├── AccountManager.html │ │ │ ├── UserManager.html │ │ │ ├── class-use │ │ │ ├── AccountManager.html │ │ │ └── UserManager.html │ │ │ ├── package-frame.html │ │ │ ├── package-summary.html │ │ │ ├── package-tree.html │ │ │ └── package-use.html │ ├── overview-frame.html │ ├── overview-summary.html │ ├── overview-tree.html │ ├── package-list │ ├── resources │ │ └── inherit.gif │ └── stylesheet.css ├── index.html └── wiki │ ├── anlijieshao.html │ ├── commonMsg.html │ ├── customerMsg.html │ ├── eventMsg.html │ ├── getAccessToken.html │ ├── getUserList.html │ ├── index.html │ ├── jieruzhinan.html │ ├── jssdk.html │ ├── kaifazhewenda.html │ ├── msgValidation.html │ ├── responseMsg.html │ ├── sendAllMsg.html │ ├── static │ ├── 02da6b362196e50cd396d4117c7fa3ea.css │ ├── 9b265d49c0b1c003517c76eed9e302bf.css │ ├── assets │ │ ├── ac9be2eafdeb95d50b28fa7cd75bb499.jpg │ │ └── f2f7d30aa3411cb6688869baa817725a.jpg │ └── bff18ac75ffc4119cb2bef02c142e2ba.js │ ├── templateMsg.html │ ├── upDownMediaFile.html │ └── voiceTextMsg.html ├── lib └── readme.md ├── src ├── log4j.properties ├── org │ └── sword │ │ └── wechat4j │ │ ├── WechatSupport.java │ │ ├── ai │ │ └── readme.md │ │ ├── card │ │ └── readme.md │ │ ├── common │ │ ├── Config.java │ │ ├── MediaFile.java │ │ ├── MediaType.java │ │ └── ValidateSignature.java │ │ ├── csc │ │ ├── CustomerServices.java │ │ ├── CustomerServicesManager.java │ │ ├── CustomerServicesSession.java │ │ ├── Record.java │ │ └── RecordOperCode.java │ │ ├── event │ │ ├── EventType.java │ │ └── MsgType.java │ │ ├── exception │ │ ├── WeChatException.java │ │ └── WeChatReturnCode.java │ │ ├── iot │ │ └── readme.md │ │ ├── jsapi │ │ ├── JsApiManager.java │ │ ├── JsApiParam.java │ │ └── readme.md │ │ ├── menu │ │ ├── Menu.java │ │ ├── MenuButton.java │ │ ├── MenuButtonType.java │ │ └── MenuManager.java │ │ ├── message │ │ ├── CustomerMsg.java │ │ ├── TemplateMsg.java │ │ └── template │ │ │ ├── TemplateMsgBody.java │ │ │ └── TemplateMsgData.java │ │ ├── oauth │ │ ├── OAuthException.java │ │ ├── OAuthManager.java │ │ ├── protocol │ │ │ ├── get_access_token │ │ │ │ ├── GetAccessTokenRequest.java │ │ │ │ └── GetAccessTokenResponse.java │ │ │ ├── get_userinfo │ │ │ │ ├── GetUserinfoRequest.java │ │ │ │ └── GetUserinfoResponse.java │ │ │ ├── refresh_access_token │ │ │ │ ├── RefreshAccessTokenRequest.java │ │ │ │ └── RefreshAccessTokenResponse.java │ │ │ └── valid_access_token │ │ │ │ ├── ValidAccessTokenRequest.java │ │ │ │ └── ValidAccessTokenResponse.java │ │ └── readme.md │ │ ├── param │ │ ├── SignatureParam.java │ │ └── WechatParamName.java │ │ ├── pay │ │ ├── H5PayParam.java │ │ ├── PayCode.java │ │ ├── PayManager.java │ │ ├── exception │ │ │ ├── PayApiException.java │ │ │ ├── PayBusinessException.java │ │ │ └── SignatureException.java │ │ ├── protocol │ │ │ ├── closeorder │ │ │ │ ├── CloseorderRequest.java │ │ │ │ └── CloseorderResponse.java │ │ │ ├── downloadbill │ │ │ │ └── DownloadbillRequest.java │ │ │ ├── orderquery │ │ │ │ ├── OrderqueryRequest.java │ │ │ │ └── OrderqueryResponse.java │ │ │ ├── pay_result_notify │ │ │ │ └── PayResultNotifyResponse.java │ │ │ ├── refund │ │ │ │ ├── RefundRequest.java │ │ │ │ └── RefundResponse.java │ │ │ ├── refundquery │ │ │ │ ├── RefundqueryRequest.java │ │ │ │ └── RefundqueryResponse.java │ │ │ ├── report │ │ │ │ ├── ReportRequest.java │ │ │ │ └── ReportResponse.java │ │ │ └── unifiedorder │ │ │ │ ├── UnifiedorderRequest.java │ │ │ │ └── UnifiedorderResponse.java │ │ └── readme.md │ │ ├── request │ │ ├── Item.java │ │ ├── ScanCodeInfo.java │ │ ├── SendLocationInfo.java │ │ ├── SendPicsInfo.java │ │ └── WechatRequest.java │ │ ├── response │ │ ├── ArticleResponse.java │ │ ├── ImageResponse.java │ │ ├── MusicResponse.java │ │ ├── TransInfoResponse.java │ │ ├── VideoResponse.java │ │ ├── VoiceResponse.java │ │ └── WechatResponse.java │ │ ├── shop │ │ └── readme.md │ │ ├── token │ │ ├── AccessToken.java │ │ ├── Ticket.java │ │ ├── TicketType.java │ │ ├── Token.java │ │ ├── TokenListener.java │ │ ├── TokenProxy.java │ │ ├── server │ │ │ ├── AbsServer.java │ │ │ ├── AccessTokenMemServer.java │ │ │ ├── AccessTokenServer.java │ │ │ ├── CustomerServer.java │ │ │ ├── IServer.java │ │ │ ├── JsApiTicketMemServer.java │ │ │ ├── JsApiTicketServer.java │ │ │ ├── TicketServer.java │ │ │ └── TokenServer.java │ │ └── timer │ │ │ ├── AccessTokenTimer.java │ │ │ └── JsApiTicketTimer.java │ │ ├── user │ │ ├── AccountManager.java │ │ ├── Data.java │ │ ├── Follwers.java │ │ ├── Group.java │ │ ├── LanguageType.java │ │ ├── Qrcode.java │ │ ├── QrcodeType.java │ │ ├── User.java │ │ └── UserManager.java │ │ └── util │ │ ├── RandomStringGenerator.java │ │ └── WeChatUtil.java └── wechat4j.properties.sample └── test ├── log4j.properties ├── org └── sword │ └── wechat4j │ ├── SendMsgTest.java │ ├── Wechat.java │ ├── WechatSupportTest.java │ ├── WechatTest.java │ ├── WechatTestSuite.java │ ├── common │ ├── ConfigTest.java │ ├── MediaFileTest.java │ ├── weixin.jpg │ └── weixin_down.jpg │ ├── csc │ └── CustomerServicesTest.java │ ├── jsapi │ └── JsapiTest.java │ ├── menu │ └── MenuTest.java │ ├── oauth │ └── OAuthTest.java │ ├── pay │ └── PayTest.java │ ├── token │ ├── AccessTokenServerTest.java │ ├── AccessTokenTest.java │ ├── TicketTest.java │ └── TokenProxyTest.java │ └── user │ ├── AccountTest.java │ └── UserTest.java └── wechat4j.properties /.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.class 2 | 3 | # Mobile Tools for Java (J2ME) 4 | .mtj.tmp/ 5 | 6 | # Package Files # 7 | *.jar 8 | *.war 9 | *.ear 10 | 11 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 12 | hs_err_pid* 13 | /bin 14 | -------------------------------------------------------------------------------- /.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | wechat4j 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.jdt.core.javabuilder 10 | 11 | 12 | 13 | 14 | 15 | org.eclipse.jdt.core.javanature 16 | 17 | 18 | -------------------------------------------------------------------------------- /META-INF/NOTICE.txt: -------------------------------------------------------------------------------- 1 | ====project home 2 | https://github.com/sword-org/wachat4j 3 | 4 | ====need jar 5 | commons-codec-1.9.jar 6 | commons-lang3-3.1.jar 7 | fastjson-1.2.0.jar 8 | log4j-1.2.14.jar 9 | 10 | httpclient-4.3.6.jar 11 | fluent-hc-4.3.6.jar(httpclient依赖) 12 | httpcore-4.3.3.jar (httpclient依赖) 13 | 14 | servlet-api.jar 15 | 16 | 17 | -------------------------------------------------------------------------------- /META-INF/README.md: -------------------------------------------------------------------------------- 1 |  2 | -------------------------------------------------------------------------------- /META-INF/wechat4j.properties.sample: -------------------------------------------------------------------------------- 1 | 2 | #you wechat token 3 | wechat.token=token 4 | #message secret key,if don't set then message is cleartext 5 | wechat.encodingaeskey= 6 | 7 | #wechat appid 8 | wechat.appid=appid 9 | #wechat app secret 10 | wechat.appsecret=appsecret 11 | 12 | #wechat access token server ,when you save in db,must implement you server class 13 | #this class must extend org.sword.wechat4j.token.server.CustomerServer 14 | #if no this property,then token server is default memery accesstoken server 15 | wechat.accessToken.server.class= 16 | 17 | #jsapi_ticket customer server class name, 18 | #this class must extend org.sword.wechat4j.token.server.CustomerServer 19 | #if no this property,then ticket server is default memery ticket server 20 | wechat.ticket.jsapi.server.class= -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | wechat4j 2 | ======== 3 | 4 | ##What is wechat4j? 5 | wechat develop framework for java(微信开发框架JAVA版,最简单易用微信开发框架) 6 | 7 | ##wechat4j可以用来干什么? 8 | wechat4j是一个帮助你开发微信应用的jar包,使用它,你开发微信公众号应用只需要几秒钟的时间,完全不用关注太细节的东西。 9 | 10 | ##wechat4j快速开始 11 | 可以去下载wechat4j示例项目[wechat4jDemo](https://github.com/repoproject/wechat4jDemo),然后在其基础之上修改即可。如果你要自己搭建,那么使用wechat4j只需要三步就可以搭建微信开发环境。 12 | 1. 创建一个web工程,导入jdk和相关的web工程jar包。 13 | 2. 下载wechat4j.jar包,下载地址[wechat4j下载](https://github.com/sword-org/wechat4j/releases)。 14 | 3. 创建wechat4j配置文件,在src目录下(java根目录)创建wechat4j.properties文件,配置你微信公众号的相关信息。内容如下: 15 | ```properties 16 | #you wechat token 17 | wechat.token=token 18 | #wechat appid 19 | wechat.appid=appid 20 | #wechat app secret 21 | wechat.appsecret=secret 22 | ``` 23 | 你也可以在jar包的META-INF目录下找到wechat4j.properties.sample文件,复制到src目录下修改名称即可。wechat4j.properties配置文件的详细配置项意义参见[wechat4j配置文件解读](https://github.com/sword-org/wechat4j/wiki/wechat4j%E9%85%8D%E7%BD%AE%E6%96%87%E4%BB%B6%E8%A7%A3%E8%AF%BB) 24 | 25 | 通过以上步骤,你的微信工程就完全搭好了。 26 | 27 | ##wechat4j 运行环境 28 | wechat4j要求的最低java运行环境是jdk1.6 29 | 30 | wechat4j.jar的依赖jar包 31 | > * commons-codec.jar 1.3以上 32 | > * commons-lang3.jar 33 | > * log4j.jar 1.2以上 34 | > * fastjson-1.2.0.jar 35 | > * sword-lang-1.2 (https://github.com/sword-org/sword-lang/releases) 36 | > * fluent-hc-4.3.6.jar(httpclient依赖) 37 | > * httpclient-4.3.6.jar 38 | > * httpcore-4.3.3.jar (httpclient依赖) 39 | > * servlet-api.jar 如果你是web工程,导入支持web工程的包就会包括,例如tomcat包 40 | 41 | 你可以去集中下载这些jar包的集合[wechat4j所需jar下载](http://files.cnblogs.com/chengn/wechat4j-lib.rar),也可以去maven库或者对应jar包的项目官网下载. 42 | 43 | ##开发自己的微信应用 44 | wechat4j开发环境搭好之后,就可以开始开发自己的微信应用了。比如我有一个微信号的token是lejian,下面就以她为例子来说明。 45 | ###创建自己公众号服务类 46 | 创建自己的微信公众号服务类,需要继承wechat4j的WechatSupport类,然后实现其抽象方法即可,下面以文本消息处理为例子 47 | ```java 48 | public class Lejian extends WechatSupport{ 49 | public Lejian(HttpServletRequest request) { 50 | super(request); 51 | } 52 | 53 | @Override 54 | protected void onText() { 55 | this.wechatRequest.getFromUserName(); 56 | String content = "test ok"; 57 | responseText(content); 58 | } 59 | } 60 | ``` 61 | 上面代码中的``onText()``是WechatSupport的抽象方法,需要你自己的类来实现,表示对文本消息的处理,示例中是接收到用户的消息之后,返回给用户“test ok”文本消息。 62 | 63 | ###创建微信服务地址 64 | 创建微信服务地址(微信公众平台中配置的自己服务器地址)servlet类。如果是springmvc则创建对应的controller,如果是struts则创建对应的action类。servlet类示例如下: 65 | ```java 66 | protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 67 | Lejian lejian = new Lejian(request); 68 | String result = lejian.execute(); 69 | response.getOutputStream().write(result.getBytes()); 70 | } 71 | protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 72 | Lejian lejian = new Lejian(request); 73 | String result = lejian.execute(); 74 | response.getOutputStream().write(result.getBytes()); 75 | 76 | } 77 | ``` 78 | 通过上面两步你的微信服务就可以运行了 79 | 80 | ##如何得到微信的请求参数 81 | 继承了``WechatSupport``类之后,你可以通过``wechatRequest.getFromUserName()``类似的方法来得到微信服务器请求的参数。详细信息请阅读[微信请求参数](https://github.com/sword-org/wechat4j/wiki/%E5%BE%97%E5%88%B0%E5%BE%AE%E4%BF%A1%E8%AF%B7%E6%B1%82%E5%8F%82%E6%95%B0) 82 | ##如何设置响应参数 83 | 继承了``WechatSupport``类之后,你可以通过``wechatResponse.setFromUserName(fromUser)``类似的方法来设置给微信服务器的响应参数。详细信息请阅读[响应微信服务器参数](https://github.com/sword-org/wechat4j/wiki/%E8%AE%BE%E7%BD%AE%E5%93%8D%E5%BA%94%E5%BE%AE%E4%BF%A1%E5%8F%82%E6%95%B0) 84 | ##如何响应用户信息 85 | 以文本信息为例,响应文本信息只需要在你的``onText``方法中使用``responseText(content)``即可(参见上面的代码例子) 86 | 87 | ##wechat4j示例项目 88 | * [wechat4jDemo](https://github.com/repoproject/wechat4jDemo) 89 | 90 | 如果你有好的demo项目,请邮件或者修改本文件然后pull request给我,我会列在上面。 91 | 92 | ##技术支持 93 | * [wechat4j开发者文档中心](http://www.chengn.com/wechat4j/) 94 | * [wechat4j开发文档](https://github.com/sword-org/wechat4j/wiki) 95 | * wechat4j技术交流QQ群 **423134346** 96 | 97 | 98 | ##贡献代码 99 | 1. 如果你觉得本项目不错,希望你能够点击一下右上角的star 100 | 2. 如果你希望参与改进本项目,那么请点击右上角的fork,修改之后pull request即可。如果你的贡献不错,你就会收到加入[sword](https://github.com/sword-org)开源社区的邀请。 101 | 3. 如果你发现了一个bug,请你创建一个issue来报告。 102 | 非常非常欢迎你能够参与本项目的建设,每人做出一点点贡献,对整个项目来说就是一个非常大的贡献,希望集合众人的力量,让项目走的更好,能够为更多的人服务。 103 | 104 | ###贡献者列表 105 | * [@chengn](https://github.com/chengn) 106 | * [@truecn](https://github.com/truecn) 107 | * [@Zhangys-hh](https://github.com/Zhangys-hh) 108 | * [@uncoseason](https://github.com/uncoseason) 109 | * [@neilrence](https://github.com/neilrence) 110 | * [@subaochen](https://github.com/subaochen) 111 | * [@Brandon007](https://github.com/Brandon007) 112 | 113 | ###分支 114 | * [maven版](https://github.com/subaochen/wechat4j) 115 | * [gradle版](https://github.com/neilrencn/wechat4j) 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | -------------------------------------------------------------------------------- /doc/api/deprecated-list.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 已过时项目列表 9 | 10 | 11 | 12 | 13 | 14 | 15 | 23 | 25 | 26 | 27 | 28 | 29 |
30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 52 | 55 | 56 | 57 | 58 | 61 | 77 | 78 |
53 | 54 |
79 | 80 | 81 | 82 |
83 |
84 |

85 | 已过时的 API

86 |
87 |
88 | 目录 90 | 91 |
92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 114 | 117 | 118 | 119 | 120 | 123 | 139 | 140 |
115 | 116 |
141 | 142 | 143 | 144 |
145 | 146 | 147 | 148 | -------------------------------------------------------------------------------- /doc/api/index.html: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | wechat4j 9 | 10 | 21 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | <H2> 32 | 框架警报</H2> 33 | 34 | <P> 35 | 请使用框架功能查看此文档。如果看到此消息,则表明您使用的是不支持框架的 Web 客户机。 36 | <BR> 37 | 链接到<A HREF="overview-summary.html">非框架版本。</A> 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /doc/api/org/sword/wechat4j/common/package-frame.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | org.sword.wechat4j.common 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | org.sword.wechat4j.common 21 | 22 | 23 | 32 | 33 |
24 | 类  25 | 26 |
27 | Config 28 |
29 | MediaFile 30 |
31 | ValidateSignature
34 | 35 | 36 | 37 | 38 | 43 | 44 |
39 | 枚举  40 | 41 |
42 | MediaType
45 | 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /doc/api/org/sword/wechat4j/event/package-frame.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | org.sword.wechat4j.event 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | org.sword.wechat4j.event 21 | 22 | 23 | 30 | 31 |
24 | 枚举  25 | 26 |
27 | EventType 28 |
29 | MsgType
32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /doc/api/org/sword/wechat4j/message/package-frame.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | org.sword.wechat4j.message 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | org.sword.wechat4j.message 21 | 22 | 23 | 30 | 31 |
24 | 类  25 | 26 |
27 | CustomerMsg 28 |
29 | TemplateMsg
32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /doc/api/org/sword/wechat4j/message/template/package-frame.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | org.sword.wechat4j.message.template 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | org.sword.wechat4j.message.template 21 | 22 | 23 | 30 | 31 |
24 | 类  25 | 26 |
27 | TemplateMsgBody 28 |
29 | TemplateMsgData
32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /doc/api/org/sword/wechat4j/package-frame.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | org.sword.wechat4j 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | org.sword.wechat4j 21 | 22 | 23 | 28 | 29 |
24 | 类  25 | 26 |
27 | WechatSupport
30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /doc/api/org/sword/wechat4j/package-use.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 软件包 org.sword.wechat4j 的使用 9 | 10 | 11 | 12 | 13 | 14 | 15 | 23 | 25 | 26 | 27 | 28 | 29 |
30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 52 | 55 | 56 | 57 | 58 | 61 | 77 | 78 |
53 | 54 |
79 | 80 | 81 | 82 |
83 |
84 |

85 | 软件包 org.sword.wechat4j
的使用

86 |
87 | 没有 org.sword.wechat4j 的用法 88 |

89 |


90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 112 | 115 | 116 | 117 | 118 | 121 | 137 | 138 |
113 | 114 |
139 | 140 | 141 | 142 |
143 | 144 | 145 | 146 | -------------------------------------------------------------------------------- /doc/api/org/sword/wechat4j/param/package-frame.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | org.sword.wechat4j.param 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | org.sword.wechat4j.param 21 | 22 | 23 | 30 | 31 |
24 | 类  25 | 26 |
27 | SignatureParam 28 |
29 | WechatParamName
32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /doc/api/org/sword/wechat4j/request/package-frame.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | org.sword.wechat4j.request 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | org.sword.wechat4j.request 21 | 22 | 23 | 36 | 37 |
24 | 类  25 | 26 |
27 | Item 28 |
29 | ScanCodeInfo 30 |
31 | SendLocationInfo 32 |
33 | SendPicsInfo 34 |
35 | WechatRequest
38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /doc/api/org/sword/wechat4j/response/package-frame.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | org.sword.wechat4j.response 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | org.sword.wechat4j.response 21 | 22 | 23 | 38 | 39 |
24 | 类  25 | 26 |
27 | ArticleResponse 28 |
29 | ImageResponse 30 |
31 | MusicResponse 32 |
33 | VideoResponse 34 |
35 | VoiceResponse 36 |
37 | WechatResponse
40 | 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /doc/api/org/sword/wechat4j/token/package-frame.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | org.sword.wechat4j.token 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | org.sword.wechat4j.token 21 | 22 | 23 | 36 | 37 |
24 | 类  25 | 26 |
27 | AccessToken 28 |
29 | Ticket 30 |
31 | Token 32 |
33 | TokenListener 34 |
35 | TokenProxy
38 | 39 | 40 | 41 | 42 | 47 | 48 |
43 | 枚举  44 | 45 |
46 | TicketType
49 | 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /doc/api/org/sword/wechat4j/token/server/package-frame.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | org.sword.wechat4j.token.server 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | org.sword.wechat4j.token.server 21 | 22 | 23 | 32 | 33 |
24 | 接口  25 | 26 |
27 | IServer 28 |
29 | TicketServer 30 |
31 | TokenServer
34 | 35 | 36 | 37 | 38 | 53 | 54 |
39 | 类  40 | 41 |
42 | AbsServer 43 |
44 | AccessTokenMemServer 45 |
46 | AccessTokenServer 47 |
48 | CustomerServer 49 |
50 | JsApiTicketMemServer 51 |
52 | JsApiTicketServer
55 | 56 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /doc/api/org/sword/wechat4j/token/timer/package-frame.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | org.sword.wechat4j.token.timer 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | org.sword.wechat4j.token.timer 21 | 22 | 23 | 30 | 31 |
24 | 类  25 | 26 |
27 | AccessTokenTimer 28 |
29 | JsApiTicketTimer
32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /doc/api/org/sword/wechat4j/user/package-frame.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | org.sword.wechat4j.user 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | org.sword.wechat4j.user 21 | 22 | 23 | 30 | 31 |
24 | 类  25 | 26 |
27 | AccountManager 28 |
29 | UserManager
32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /doc/api/overview-frame.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 概述列表 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 24 | 25 |
23 |
26 | 27 | 28 | 29 | 59 | 60 |
所有类 30 |

31 | 32 | 软件包 33 |
34 | org.sword.wechat4j 35 |
36 | org.sword.wechat4j.common 37 |
38 | org.sword.wechat4j.event 39 |
40 | org.sword.wechat4j.message 41 |
42 | org.sword.wechat4j.message.template 43 |
44 | org.sword.wechat4j.param 45 |
46 | org.sword.wechat4j.request 47 |
48 | org.sword.wechat4j.response 49 |
50 | org.sword.wechat4j.token 51 |
52 | org.sword.wechat4j.token.server 53 |
54 | org.sword.wechat4j.token.timer 55 |
56 | org.sword.wechat4j.user 57 |
58 |

61 | 62 |

63 |   64 | 65 | 66 | -------------------------------------------------------------------------------- /doc/api/package-list: -------------------------------------------------------------------------------- 1 | org.sword.wechat4j 2 | org.sword.wechat4j.common 3 | org.sword.wechat4j.event 4 | org.sword.wechat4j.message 5 | org.sword.wechat4j.message.template 6 | org.sword.wechat4j.param 7 | org.sword.wechat4j.request 8 | org.sword.wechat4j.response 9 | org.sword.wechat4j.token 10 | org.sword.wechat4j.token.server 11 | org.sword.wechat4j.token.timer 12 | org.sword.wechat4j.user 13 | -------------------------------------------------------------------------------- /doc/api/resources/inherit.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sword-org/wechat4j/02e681dceb1b4be2896a3c4858e5b8363a95d861/doc/api/resources/inherit.gif -------------------------------------------------------------------------------- /doc/api/stylesheet.css: -------------------------------------------------------------------------------- 1 | /* Javadoc 样式表 */ 2 | 3 | /* 在此处定义颜色、字体和其他样式属性以覆盖默认值 */ 4 | 5 | /* 页面背景颜色 */ 6 | body { background-color: #FFFFFF; color:#000000 } 7 | 8 | /* 标题 */ 9 | h1 { font-size: 145% } 10 | 11 | /* 表格颜色 */ 12 | .TableHeadingColor { background: #CCCCFF; color:#000000 } /* 深紫色 */ 13 | .TableSubHeadingColor { background: #EEEEFF; color:#000000 } /* 淡紫色 */ 14 | .TableRowColor { background: #FFFFFF; color:#000000 } /* 白色 */ 15 | 16 | /* 左侧的框架列表中使用的字体 */ 17 | .FrameTitleFont { font-size: 100%; font-family: Helvetica, Arial, sans-serif; color:#000000 } 18 | .FrameHeadingFont { font-size: 90%; font-family: Helvetica, Arial, sans-serif; color:#000000 } 19 | .FrameItemFont { font-size: 90%; font-family: Helvetica, Arial, sans-serif; color:#000000 } 20 | 21 | /* 导航栏字体和颜色 */ 22 | .NavBarCell1 { background-color:#EEEEFF; color:#000000} /* 淡紫色 */ 23 | .NavBarCell1Rev { background-color:#00008B; color:#FFFFFF} /* 深蓝色 */ 24 | .NavBarFont1 { font-family: Arial, Helvetica, sans-serif; color:#000000;color:#000000;} 25 | .NavBarFont1Rev { font-family: Arial, Helvetica, sans-serif; color:#FFFFFF;color:#FFFFFF;} 26 | 27 | .NavBarCell2 { font-family: Arial, Helvetica, sans-serif; background-color:#FFFFFF; color:#000000} 28 | .NavBarCell3 { font-family: Arial, Helvetica, sans-serif; background-color:#FFFFFF; color:#000000} 29 | 30 | -------------------------------------------------------------------------------- /doc/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | wechat4j doc 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 |

20 |

wechat4j doc

21 |

wechat4j is wechat(weixin) develop framework for java 微信开发框架JAVA版,最简单易用微信开发框架

22 |

github项目地址: https://github.com/sword-org/wechat4j

23 |

github项目wiki: https://github.com/sword-org/wechat4j/wiki

24 |

25 | 开发者文档 26 |

27 |

微信开发者文档提供了同微信公众平台开发者文档类似的说明,不过文档中的内容都是如何用wechat4j来实现官方文档中的内容,读者可以两者一起对比阅读,这样就会更加深入的理解wechat4j和微信开发接口。ps:本文档的样式采用了微信官方文档的模板样式,如有侵权,请联系作者。

28 |

29 | API接口手册 30 |

31 |

API接口文档是通过javadoc生成的wechat4j的所有公开的接口,包括了包,类,方法和参数的说明,方便读者深入研究wechat4j和作为开发过程中的手册使用。

32 |
33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /doc/wiki/static/assets/ac9be2eafdeb95d50b28fa7cd75bb499.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sword-org/wechat4j/02e681dceb1b4be2896a3c4858e5b8363a95d861/doc/wiki/static/assets/ac9be2eafdeb95d50b28fa7cd75bb499.jpg -------------------------------------------------------------------------------- /doc/wiki/static/assets/f2f7d30aa3411cb6688869baa817725a.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sword-org/wechat4j/02e681dceb1b4be2896a3c4858e5b8363a95d861/doc/wiki/static/assets/f2f7d30aa3411cb6688869baa817725a.jpg -------------------------------------------------------------------------------- /lib/readme.md: -------------------------------------------------------------------------------- 1 | jar folder 2 | 3 | ====need jar 4 | commons-codec-1.9.jar 5 | commons-lang3-3.1.jar 6 | commons-httpclient-3.1.jar 7 | fastjson-1.2.0.jar 8 | log4j-1.2.14.jar 9 | servlet-api.jar -------------------------------------------------------------------------------- /src/log4j.properties: -------------------------------------------------------------------------------- 1 | # Root logger option 2 | log4j.rootLogger=INFO, file, stdout 3 | 4 | # Direct log messages to a log file 5 | log4j.appender.file=org.apache.log4j.RollingFileAppender 6 | log4j.appender.file.File=D:\\ims.log 7 | log4j.appender.file.MaxFileSize=10MB 8 | log4j.appender.file.MaxBackupIndex=10 9 | log4j.appender.file.layout=org.apache.log4j.PatternLayout 10 | log4j.appender.file.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n 11 | 12 | # Direct log messages to stdout 13 | log4j.appender.stdout=org.apache.log4j.ConsoleAppender 14 | log4j.appender.stdout.Target=System.out 15 | log4j.appender.stdout.layout=org.apache.log4j.PatternLayout 16 | log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n -------------------------------------------------------------------------------- /src/org/sword/wechat4j/ai/readme.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sword-org/wechat4j/02e681dceb1b4be2896a3c4858e5b8363a95d861/src/org/sword/wechat4j/ai/readme.md -------------------------------------------------------------------------------- /src/org/sword/wechat4j/card/readme.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sword-org/wechat4j/02e681dceb1b4be2896a3c4858e5b8363a95d861/src/org/sword/wechat4j/card/readme.md -------------------------------------------------------------------------------- /src/org/sword/wechat4j/common/Config.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package org.sword.wechat4j.common; 5 | 6 | import java.io.IOException; 7 | import java.io.InputStream; 8 | import java.util.Properties; 9 | 10 | import org.apache.commons.lang3.StringUtils; 11 | import org.apache.log4j.Logger; 12 | 13 | /** 14 | * @author ChengNing 15 | * @date 2014年12月8日 16 | */ 17 | public class Config { 18 | 19 | private static Logger logger = Logger.getLogger(Config.class); 20 | 21 | private static final String configFile = "/wechat4j.properties"; 22 | 23 | private String url; 24 | private String token; 25 | private String encodingAESKey; 26 | private String appid; 27 | private String appSecret; 28 | private String mchId; 29 | private String mchKey; 30 | private String accessTokenServer; 31 | private String jsApiTicketServer; 32 | private static Config config = new Config(); 33 | 34 | private Config(){ 35 | Properties p = new Properties(); 36 | InputStream inStream = this.getClass().getResourceAsStream(configFile); 37 | if(inStream == null){ 38 | logger.error("根目录下找不到wechat4j.properties文件"); 39 | return; 40 | } 41 | try { 42 | p.load(inStream); 43 | this.url = p.getProperty("wechat.url"); 44 | if(StringUtils.isNotBlank(url))this.url = this.url.trim(); 45 | this.encodingAESKey = p.getProperty("wechat.encodingaeskey"); 46 | if(StringUtils.isNotBlank(encodingAESKey))this.encodingAESKey = this.encodingAESKey.trim(); 47 | this.token = p.getProperty("wechat.token"); 48 | if(StringUtils.isNotBlank(token))this.token = this.token.trim(); 49 | this.appid = p.getProperty("wechat.appid"); 50 | if(StringUtils.isNotBlank(appid))this.appid = this.appid.trim(); 51 | this.appSecret = p.getProperty("wechat.appsecret"); 52 | if(StringUtils.isNotBlank(appSecret))this.appSecret = this.appSecret.trim(); 53 | this.mchId = p.getProperty("wechat.mch.id"); 54 | if(StringUtils.isNotBlank(mchId))this.mchId = this.mchId.trim(); 55 | this.mchKey = p.getProperty("wechat.mch.key"); 56 | if(StringUtils.isNotBlank(mchKey))this.mchKey = this.mchKey.trim(); 57 | this.accessTokenServer = p.getProperty("wechat.accessToken.server.class"); 58 | if(StringUtils.isNotBlank(accessTokenServer))this.accessTokenServer = this.accessTokenServer.trim(); 59 | this.jsApiTicketServer = p.getProperty("wechat.ticket.jsapi.server.class"); 60 | if(StringUtils.isNotBlank(jsApiTicketServer))this.jsApiTicketServer = this.jsApiTicketServer.trim(); 61 | inStream.close(); 62 | } catch (IOException e) { 63 | logger.error("load wechat4j.properties error,class根目录下找不到wechat4j.properties文件"); 64 | e.printStackTrace(); 65 | } 66 | logger.info("load wechat4j.properties success"); 67 | } 68 | 69 | public static Config instance(){ 70 | return config; 71 | } 72 | public String getToken() { 73 | return token; 74 | } 75 | public String getAppid() { 76 | return appid; 77 | } 78 | public String getAppSecret() { 79 | return appSecret; 80 | } 81 | 82 | public String getMchId() { 83 | return mchId; 84 | } 85 | 86 | public String getMchKey() { 87 | return mchKey; 88 | } 89 | 90 | public String getUrl() { 91 | return url; 92 | } 93 | 94 | public String getEncodingAESKey() { 95 | return encodingAESKey; 96 | } 97 | 98 | public String getAccessTokenServer(){ 99 | return accessTokenServer; 100 | } 101 | 102 | public String getJsApiTicketServer() { 103 | return jsApiTicketServer; 104 | } 105 | 106 | 107 | } 108 | -------------------------------------------------------------------------------- /src/org/sword/wechat4j/common/MediaFile.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package org.sword.wechat4j.common; 5 | 6 | import java.io.File; 7 | 8 | import org.apache.commons.lang3.StringUtils; 9 | import org.sword.lang.HttpUtils; 10 | import org.sword.wechat4j.token.TokenProxy; 11 | 12 | import com.alibaba.fastjson.JSONObject; 13 | 14 | /** 15 | * 上传下载多媒体文件 16 | * @author ChengNing 17 | * @date 2015年1月6日 18 | */ 19 | public class MediaFile { 20 | 21 | private static final String UPLOAD = "http://file.api.weixin.qq.com/cgi-bin/media/upload?access_token="; 22 | private static final String DOWNLOAD = "http://file.api.weixin.qq.com/cgi-bin/media/get?access_token="; 23 | private static final String PARAM_FILE = "media"; 24 | private static final String PARAM_MEDIA_ID = "media_id"; 25 | private static final String PARAM_TYPE = "type"; 26 | private static final String PARAM_CREATE_TIME = "created_at"; 27 | 28 | private MediaType type; 29 | private File file; 30 | private String mediaId; //3天失效 31 | private String createdTimestamp;//文件创建时间戳,上传之后返回 32 | 33 | 34 | /** 35 | * 文件上传url 36 | * @return 37 | */ 38 | private String uploadUrl(){ 39 | String url = UPLOAD + TokenProxy.accessToken() + "&" 40 | + PARAM_TYPE + "=" + this.type.name(); 41 | return url; 42 | } 43 | 44 | /** 45 | * 文件下载url 46 | * @return 47 | */ 48 | private String downloadUrl(){ 49 | String url = DOWNLOAD + TokenProxy.accessToken() + "&" 50 | + PARAM_MEDIA_ID + "=" + this.mediaId; 51 | return url; 52 | } 53 | 54 | /** 55 | * 文件上传 56 | * success: {"type":"TYPE","media_id":"MEDIA_ID","created_at":123456789} 57 | * error: {"errcode":40004,"errmsg":"invalid media type"} 58 | * @return media_id 成功返回 media_id, 失败返回null 59 | */ 60 | public String upload(File file,MediaType type){ 61 | this.file = file; 62 | this.type = type; 63 | String url = uploadUrl(); 64 | String result = HttpUtils.postFile(url,PARAM_FILE, file); 65 | parseUploadResult(result); 66 | if(StringUtils.isNotBlank(this.mediaId)) 67 | return this.mediaId; 68 | return null; 69 | } 70 | 71 | private void parseUploadResult(String result){ 72 | JSONObject jsonObject = JSONObject.parseObject(result); 73 | if(jsonObject.containsKey(PARAM_MEDIA_ID)){ 74 | this.mediaId = jsonObject.getString(PARAM_MEDIA_ID); 75 | this.createdTimestamp = jsonObject.getString(PARAM_CREATE_TIME); 76 | } 77 | else{ 78 | this.mediaId = null; 79 | this.createdTimestamp = null; 80 | } 81 | } 82 | 83 | /** 84 | * 文件下载 85 | * @return byte[] 86 | */ 87 | public byte[] download(String mediaId){ 88 | this.mediaId = mediaId; 89 | String url = downloadUrl(); 90 | byte[] fb = HttpUtils.getFile(url); 91 | if(fb == null || fb.length == 0) 92 | return null; 93 | return fb; 94 | } 95 | 96 | public MediaType getType() { 97 | return type; 98 | } 99 | 100 | public String getMediaId() { 101 | return mediaId; 102 | } 103 | 104 | public String getCreatedTimestamp() { 105 | return createdTimestamp; 106 | } 107 | 108 | 109 | } 110 | -------------------------------------------------------------------------------- /src/org/sword/wechat4j/common/MediaType.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package org.sword.wechat4j.common; 5 | 6 | /** 7 | * @author ChengNing 8 | * @date 2015年1月26日 9 | */ 10 | public enum MediaType { 11 | image, 12 | voice, 13 | video, 14 | thumb 15 | } 16 | -------------------------------------------------------------------------------- /src/org/sword/wechat4j/common/ValidateSignature.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package org.sword.wechat4j.common; 5 | 6 | import java.util.Arrays; 7 | 8 | import org.apache.commons.codec.digest.DigestUtils; 9 | 10 | /** 11 | * 用于微信的前面验证 12 | * @author ChengNing 13 | * @date 2014-12-4 14 | */ 15 | public class ValidateSignature { 16 | 17 | private String signature; 18 | private String timestamp; 19 | private String nonce; 20 | private String token; 21 | 22 | /** 23 | * 前面验证构造 24 | * @param signature 25 | * @param timestamp 26 | * @param nonce 27 | * @param token 28 | */ 29 | public ValidateSignature(String signature,String timestamp,String nonce,String token){ 30 | this.signature = signature; 31 | this.timestamp = timestamp; 32 | this.nonce = nonce; 33 | this.token = token; 34 | } 35 | 36 | /** 37 | * 验证 38 | * @param token 39 | * @return true 验证通过,false 验证失败 40 | */ 41 | public boolean check(){ 42 | String sha1 = encode(); 43 | return sha1.equals(this.signature); 44 | } 45 | 46 | /** 47 | * 得到加密后的数据 48 | * @return 49 | */ 50 | private String encode(){ 51 | String[] sa = {this.token,this.timestamp, this.nonce}; 52 | Arrays.sort(sa); 53 | String sortStr = sa[0] + sa[1] + sa[2]; 54 | return DigestUtils.sha1Hex(sortStr); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/org/sword/wechat4j/csc/CustomerServices.java: -------------------------------------------------------------------------------- 1 | package org.sword.wechat4j.csc; 2 | 3 | import com.alibaba.fastjson.annotation.JSONField; 4 | 5 | /** 6 | * 客服基本信息 7 | * @author Zhangxs 8 | * @date 2015-7-8 9 | * @version 10 | */ 11 | public class CustomerServices { 12 | private String kfAccount;//完整客服账号,格式为:账号前缀@公众号微信号 13 | private String kfId;// 客服工号 14 | private String kfHeadimgurl;//客服头像url 15 | private String kfNick;// 客服昵称 16 | private Integer status;// 客服在线状态 17 | private Integer autoAccept;// 客服设置的最大自动接入数 18 | private Integer acceptedCase;// 客服当前正在接待的会话数 19 | 20 | /** 21 | * 完整客服账号
22 | * 格式为:账号前缀@公众号微信号 23 | * @return 24 | */ 25 | @JSONField(name="kf_account") 26 | public String getKfAccount() { 27 | return kfAccount; 28 | } 29 | @JSONField(name="kf_account") 30 | public void setKfAccount(String kfAccount) { 31 | this.kfAccount = kfAccount; 32 | } 33 | /** 34 | * 客服工号 35 | * @return 36 | */ 37 | @JSONField(name="kf_id") 38 | public String getKfId() { 39 | return kfId; 40 | } 41 | @JSONField(name="kf_id") 42 | public void setKfId(String kfId) { 43 | this.kfId = kfId; 44 | } 45 | /** 46 | * 客服头像url 47 | * @return 48 | */ 49 | @JSONField(name="kf_headimgurl") 50 | public String getKfHeadimgurl() { 51 | return kfHeadimgurl; 52 | } 53 | @JSONField(name="kf_headimgurl") 54 | public void setKfHeadimgurl(String kfHeadimgurl) { 55 | this.kfHeadimgurl = kfHeadimgurl; 56 | } 57 | /** 58 | * 客服昵称 59 | * @return 60 | */ 61 | @JSONField(name="kf_nick") 62 | public String getKfNick() { 63 | return kfNick; 64 | } 65 | @JSONField(name="kf_nick") 66 | public void setKfNick(String kfNick) { 67 | this.kfNick = kfNick; 68 | } 69 | /** 70 | * 客服在线状态
71 | * 1:pc在线
72 | * 2:手机在线
73 | * 3:pc和手机同时在线 74 | * @return 75 | */ 76 | @JSONField(name="status") 77 | public Integer getStatus() { 78 | return status; 79 | } 80 | @JSONField(name="status") 81 | public void setStatus(Integer status) { 82 | this.status = status; 83 | } 84 | /** 85 | * 客服设置的最大自动接入数 86 | * @return 87 | */ 88 | @JSONField(name="auto_accept") 89 | public Integer getAutoAccept() { 90 | return autoAccept; 91 | } 92 | @JSONField(name="auto_accept") 93 | public void setAutoAccept(Integer autoAccept) { 94 | this.autoAccept = autoAccept; 95 | } 96 | /** 97 | * 客服当前正在接待的会话数 98 | * @return 99 | */ 100 | @JSONField(name="accepted_case") 101 | public Integer getAcceptedCase() { 102 | return acceptedCase; 103 | } 104 | @JSONField(name="accepted_case") 105 | public void setAcceptedCase(Integer acceptedCase) { 106 | this.acceptedCase = acceptedCase; 107 | } 108 | 109 | 110 | } 111 | -------------------------------------------------------------------------------- /src/org/sword/wechat4j/csc/CustomerServicesSession.java: -------------------------------------------------------------------------------- 1 | package org.sword.wechat4j.csc; 2 | 3 | import com.alibaba.fastjson.annotation.JSONField; 4 | 5 | /** 6 | * 会话状态 7 | * @author Zhangxs 8 | * @date 2015-7-8 9 | * @version 10 | */ 11 | public class CustomerServicesSession { 12 | 13 | private int createTime;//会话接入的时间 14 | private String kfAccount;//客服 15 | private String openId;//客户openid 16 | /** 17 | * 会话接入的时间 18 | * @return 19 | */ 20 | @JSONField(name="createtime") 21 | public int getCreateTime() { 22 | return createTime; 23 | } 24 | @JSONField(name="createtime") 25 | public void setCreateTime(int createTime) { 26 | this.createTime = createTime; 27 | } 28 | /** 29 | * 客服 30 | * @return 31 | */ 32 | @JSONField(name="kf_account") 33 | public String getKfAccount() { 34 | return kfAccount; 35 | } 36 | @JSONField(name="kf_account") 37 | public void setKfAccount(String kfAccount) { 38 | this.kfAccount = kfAccount; 39 | } 40 | /** 41 | * 客户openid 42 | * @return 43 | */ 44 | @JSONField(name="openid") 45 | public String getOpenId() { 46 | return openId; 47 | } 48 | @JSONField(name="openid") 49 | public void setOpenId(String openId) { 50 | this.openId = openId; 51 | } 52 | 53 | 54 | 55 | 56 | } 57 | -------------------------------------------------------------------------------- /src/org/sword/wechat4j/csc/Record.java: -------------------------------------------------------------------------------- 1 | package org.sword.wechat4j.csc; 2 | 3 | /** 4 | * 聊天记录 5 | * @author Zhangxs 6 | * @date 2015-7-7 7 | * @version 8 | */ 9 | public class Record { 10 | 11 | private String openid;//用户的标识 12 | private int opercode;//操作ID(会话状态) 13 | private String text;//聊天记录 14 | private int time;//操作时间,UNIX时间戳 15 | private String worker;//客服账号 16 | 17 | public Record() { 18 | super(); 19 | } 20 | public Record(String openid, int opercode, 21 | String text, int time, String worker) { 22 | super(); 23 | this.openid = openid; 24 | this.opercode = opercode; 25 | this.text = text; 26 | this.time = time; 27 | this.worker = worker; 28 | } 29 | 30 | /** 31 | * 用户的标识 32 | * @return 33 | */ 34 | public String getOpenid() { 35 | return openid; 36 | } 37 | public void setOpenid(String openid) { 38 | this.openid = openid; 39 | } 40 | /** 41 | * 操作ID(会话状态) 42 | * @see RecordOperCode#getSessionState(int) 43 | */ 44 | public int getOpercode() { 45 | return opercode; 46 | } 47 | public void setOpercode(int opercode) { 48 | this.opercode = opercode; 49 | } 50 | /** 51 | * 聊天记录 52 | * @return 53 | */ 54 | public String getText() { 55 | return text; 56 | } 57 | public void setText(String text) { 58 | this.text = text; 59 | } 60 | /** 61 | * 操作时间,UNIX时间戳 62 | * @return 63 | */ 64 | public int getTime() { 65 | return time; 66 | } 67 | public void setTime(int time) { 68 | this.time = time; 69 | } 70 | /** 71 | * 客服账号 72 | * @return 73 | */ 74 | public String getWorker() { 75 | return worker; 76 | } 77 | public void setWorker(String worker) { 78 | this.worker = worker; 79 | } 80 | 81 | } 82 | -------------------------------------------------------------------------------- /src/org/sword/wechat4j/csc/RecordOperCode.java: -------------------------------------------------------------------------------- 1 | package org.sword.wechat4j.csc; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | /** 6 | * 操作ID(会话状态)说明 7 | * @author Zhangxs 8 | * @date 2015-7-8 9 | * @version 10 | */ 11 | public class RecordOperCode { 12 | private final static Map operCodeMap = new HashMap(); 13 | 14 | static { 15 | operCodeMap.put(1000,"创建未接入会话"); 16 | operCodeMap.put(1001,"接入会话"); 17 | operCodeMap.put(1002,"主动发起会话"); 18 | operCodeMap.put(1004,"关闭会话"); 19 | operCodeMap.put(1005,"抢接会话"); 20 | operCodeMap.put(2001,"公众号收到消息"); 21 | operCodeMap.put(2002,"客服发送消息"); 22 | operCodeMap.put(2003,"客服收到消息"); 23 | } 24 | /** 25 | * 根据opercode返回会话状态 26 | * @param opercode 27 | * @return 28 | */ 29 | public static String getSessionState(int opercode){ 30 | if (operCodeMap.containsKey(opercode)) { 31 | return operCodeMap.get(opercode); 32 | } 33 | return ""; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/org/sword/wechat4j/event/EventType.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package org.sword.wechat4j.event; 5 | 6 | /** 7 | * 微信事件类型,event字段的枚举
8 | * scancode_push、scancode_waitmsg、pic_sysphoto、pic_photo_or_album、pic_weixin、location_select
9 | * 仅支持微信iPhone5.4.1以上版本,和Android5.4以上版本的微信用户
10 | * media_id,view_limited
11 | * 仅限第三方平台旗下未微信认证(具体而言,是资质认证未通过)的订阅号准备的事件类型,没有事件推送 12 | * @author ChengNing 13 | * @author Zhangxs 14 | * @date 2015-7-6 15 | * 16 | */ 17 | public enum EventType { 18 | subscribe, //关注 19 | unsubscribe, //取消关注 20 | /** 创建菜单使用 */ 21 | click, 22 | CLICK, //点击 23 | /** 创建菜单使用 */ 24 | view, 25 | VIEW, //跳转链接 26 | SCAN, //扫描 27 | LOCATION, //上报地理位置 28 | TEMPLATESENDJOBFINISH, //模板消息发送成功之后事件 29 | scancode_push, //扫码推事件 30 | scancode_waitmsg, //扫码推事件且弹出“消息接收中”提示框的事件 31 | pic_sysphoto, //弹出系统拍照发图的事件 32 | pic_photo_or_album, //弹出拍照或者相册发图的事件 33 | pic_weixin, //弹出微信相册发图器的事件 34 | location_select, //弹出地理位置选择器的事件 35 | media_id, //下发消息(除文本消息) 36 | view_limited, //跳转图文消息URL 37 | kf_create_session, //接入会话 38 | kf_close_session, //关闭会话 39 | kf_switch_session, //转接会话 40 | } 41 | -------------------------------------------------------------------------------- /src/org/sword/wechat4j/event/MsgType.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package org.sword.wechat4j.event; 5 | 6 | /** 7 | * 微信消息类型,大小写对应微信接口,msgType的枚举值 8 | * @author ChengNing 9 | * @date 2014-12-4 10 | */ 11 | public enum MsgType { 12 | event, //事件 13 | text, //文本消息 14 | image, 15 | location, 16 | link, 17 | voice, 18 | video, 19 | shortvideo, //小视频消息 20 | music, 21 | news, 22 | transfer_customer_service;//客服系统 23 | } 24 | -------------------------------------------------------------------------------- /src/org/sword/wechat4j/exception/WeChatException.java: -------------------------------------------------------------------------------- 1 | package org.sword.wechat4j.exception; 2 | 3 | /** 4 | * 异常处理 5 | * @author Zhangxs 6 | * @version 2015-7-4 7 | */ 8 | public class WeChatException extends Exception { 9 | private static final long serialVersionUID = 1L; 10 | public WeChatException(String msg){ 11 | super(msg); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/org/sword/wechat4j/iot/readme.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sword-org/wechat4j/02e681dceb1b4be2896a3c4858e5b8363a95d861/src/org/sword/wechat4j/iot/readme.md -------------------------------------------------------------------------------- /src/org/sword/wechat4j/jsapi/JsApiManager.java: -------------------------------------------------------------------------------- 1 | package org.sword.wechat4j.jsapi; 2 | 3 | import org.apache.commons.codec.digest.DigestUtils; 4 | import org.apache.log4j.Logger; 5 | import org.sword.wechat4j.token.TokenProxy; 6 | import org.sword.wechat4j.util.RandomStringGenerator; 7 | 8 | /** 9 | * JS SDK 管理类 10 | *

参考开发文档

11 | * Created by xuwen on 2015-12-11. 12 | */ 13 | public class JsApiManager { 14 | 15 | private static Logger logger = Logger.getLogger(JsApiManager.class); 16 | 17 | /** 18 | * 给需要调用JS SDK的URL签名 19 | * 20 | * @param url 21 | * @return 22 | */ 23 | public static JsApiParam signature(String url) { 24 | StringBuffer signatureSource = new StringBuffer(); 25 | String nonceStr = RandomStringGenerator.generate(); 26 | String timestamp = Long.toString(System.currentTimeMillis() / 1000); 27 | String jsapiTicket = TokenProxy.jsApiTicket(); 28 | signatureSource.append("jsapi_ticket=").append(jsapiTicket); 29 | signatureSource.append("&noncestr=").append(nonceStr); 30 | signatureSource.append("×tamp=").append(timestamp); 31 | signatureSource.append("&url=").append(url); 32 | logger.info("sign source : " + signatureSource); 33 | String signature = DigestUtils.sha1Hex(signatureSource.toString()); 34 | logger.info("sign : " + signature); 35 | return new JsApiParam(url, jsapiTicket, nonceStr, timestamp, signature); 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /src/org/sword/wechat4j/jsapi/JsApiParam.java: -------------------------------------------------------------------------------- 1 | package org.sword.wechat4j.jsapi; 2 | 3 | import org.sword.wechat4j.common.Config; 4 | 5 | /** 6 | * JS API 配置对象 7 | *

参考开发文档

8 | * Created by xuwen on 2015-12-11. 9 | */ 10 | public class JsApiParam { 11 | 12 | private String appid = Config.instance().getAppid(); 13 | private String url; 14 | private String jsapiTicket; 15 | private String nonceStr; 16 | private String timeStamp; 17 | private String signature; 18 | 19 | public JsApiParam(String url, String jsapiTicket, String nonceStr, String timeStamp, String signature) { 20 | this.url = url; 21 | this.jsapiTicket = jsapiTicket; 22 | this.nonceStr = nonceStr; 23 | this.timeStamp = timeStamp; 24 | this.signature = signature; 25 | } 26 | 27 | public String getAppid() { 28 | return appid; 29 | } 30 | 31 | public void setAppid(String appid) { 32 | this.appid = appid; 33 | } 34 | 35 | public String getUrl() { 36 | return url; 37 | } 38 | 39 | public void setUrl(String url) { 40 | this.url = url; 41 | } 42 | 43 | public String getJsapiTicket() { 44 | return jsapiTicket; 45 | } 46 | 47 | public void setJsapiTicket(String jsapiTicket) { 48 | this.jsapiTicket = jsapiTicket; 49 | } 50 | 51 | public String getNonceStr() { 52 | return nonceStr; 53 | } 54 | 55 | public void setNonceStr(String nonceStr) { 56 | this.nonceStr = nonceStr; 57 | } 58 | 59 | public String getTimeStamp() { 60 | return timeStamp; 61 | } 62 | 63 | public void setTimeStamp(String timeStamp) { 64 | this.timeStamp = timeStamp; 65 | } 66 | 67 | public String getSignature() { 68 | return signature; 69 | } 70 | 71 | public void setSignature(String signature) { 72 | this.signature = signature; 73 | } 74 | 75 | @Override 76 | public String toString() { 77 | return "JsApiConfig{" + 78 | "appid='" + appid + '\'' + 79 | ", url='" + url + '\'' + 80 | ", jsapiTicket='" + jsapiTicket + '\'' + 81 | ", nonceStr='" + nonceStr + '\'' + 82 | ", timeStamp='" + timeStamp + '\'' + 83 | ", signature='" + signature + '\'' + 84 | '}'; 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /src/org/sword/wechat4j/jsapi/readme.md: -------------------------------------------------------------------------------- 1 | 使用本包需要在公众号设置中配置JS接口安全域名 2 | 3 | 菜单:公众号设置-功能设置 4 | 选项:JS接口安全域名 5 | 6 | 在需要调用JS接口的页面引入如下JS文件,(支持https):http://res.wx.qq.com/open/js/jweixin-1.0.0.js 7 | 请注意,如果你的页面启用了https,务必引入 https://res.wx.qq.com/open/js/jweixin-1.0.0.js ,否则将无法在iOS9.0以上系统中成功使用JSSDK 8 | 如需使用摇一摇周边功能,请引入 jweixin-1.1.0.js 9 | 10 | 备注:支持使用 AMD/CMD 标准模块加载方法加载 11 | 12 | 开发文档:http://mp.weixin.qq.com/wiki/7/aaa137b55fb2e0456bf8dd9148dd613f.html -------------------------------------------------------------------------------- /src/org/sword/wechat4j/menu/Menu.java: -------------------------------------------------------------------------------- 1 | package org.sword.wechat4j.menu; 2 | 3 | import java.util.List; 4 | 5 | 6 | /** 7 | * 微信菜单 8 | * @author Zhangxs 9 | * @version 2015-7-4 10 | */ 11 | public class Menu { 12 | private List button; 13 | 14 | public List getButton() { 15 | return button; 16 | } 17 | 18 | public void setButton(List button) { 19 | this.button = button; 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /src/org/sword/wechat4j/menu/MenuButton.java: -------------------------------------------------------------------------------- 1 | package org.sword.wechat4j.menu; 2 | 3 | import java.util.List; 4 | 5 | import org.sword.wechat4j.event.EventType; 6 | 7 | 8 | import com.alibaba.fastjson.annotation.JSONField; 9 | /** 10 | * 菜单按钮 11 | * @author Zhangxs 12 | * @version 2015-7-4 13 | */ 14 | public class MenuButton { 15 | private EventType type;//菜单的响应动作类型 16 | private String name;//菜单标题,不超过16个字节,子菜单不超过40个字节 17 | private String key;//click等点击类型必须 菜单KEY值,用于消息接口推送,不超过128字节 18 | private String url;//view类型必须 网页链接,用户点击菜单可打开链接,不超过256字节 19 | private String mediaId;//media_id类型和view_limited类型必须 调用新增永久素材接口返回的合法media_id 20 | private List subButton;//子菜单,每个一级菜单最多包含5个二级菜单 21 | 22 | public EventType getType() { 23 | return type; 24 | } 25 | public void setType(EventType type) { 26 | this.type = type; 27 | } 28 | public String getName() { 29 | return name; 30 | } 31 | public void setName(String name) { 32 | this.name = name; 33 | } 34 | public String getKey() { 35 | return key; 36 | } 37 | public void setKey(String key) { 38 | this.key = key; 39 | } 40 | public String getUrl() { 41 | return url; 42 | } 43 | public void setUrl(String url) { 44 | this.url = url; 45 | } 46 | @JSONField(name="media_id") 47 | public String getMediaId() { 48 | return mediaId; 49 | } 50 | @JSONField(name="media_id") 51 | public void setMediaId(String mediaId) { 52 | this.mediaId = mediaId; 53 | } 54 | @JSONField(name="sub_button") 55 | public List getSubButton() { 56 | return subButton; 57 | } 58 | @JSONField(name="sub_button") 59 | public void setSubButton(List subButton) { 60 | this.subButton = subButton; 61 | } 62 | 63 | } 64 | -------------------------------------------------------------------------------- /src/org/sword/wechat4j/menu/MenuButtonType.java: -------------------------------------------------------------------------------- 1 | package org.sword.wechat4j.menu; 2 | 3 | /** 4 | * 菜单按钮类型 5 | * @author Zhangxs 6 | * @version 2015-7-4 7 | */ 8 | public enum MenuButtonType { 9 | /** 点击 */ 10 | click, 11 | /** 跳转URL */ 12 | view, 13 | /** 扫码推事件 */ 14 | scancode_push, 15 | /** 扫码推事件且弹出“消息接收中”提示框 */ 16 | scancode_waitmsg, 17 | /** 弹出系统拍照发图 */ 18 | pic_sysphoto, 19 | /** 弹出拍照或者相册发图 */ 20 | pic_photo_or_album, 21 | /** 弹出微信相册发图器 */ 22 | pic_weixin, 23 | /** 弹出地理位置选择器 */ 24 | location_select, 25 | /** //下发消息(除文本消息) */ 26 | media_id, 27 | /** 跳转图文消息URL */ 28 | view_limited; 29 | } 30 | -------------------------------------------------------------------------------- /src/org/sword/wechat4j/menu/MenuManager.java: -------------------------------------------------------------------------------- 1 | package org.sword.wechat4j.menu; 2 | 3 | 4 | 5 | import org.apache.log4j.Logger; 6 | import org.sword.lang.HttpUtils; 7 | import org.sword.wechat4j.exception.WeChatException; 8 | import org.sword.wechat4j.token.TokenProxy; 9 | import org.sword.wechat4j.util.WeChatUtil; 10 | 11 | import com.alibaba.fastjson.JSON; 12 | import com.alibaba.fastjson.JSONObject; 13 | /** 14 | * 微信菜单操作 15 | * @author Zhangxs 16 | * @version 2015-7-4 17 | */ 18 | public class MenuManager { 19 | private static Logger logger = Logger.getLogger(MenuManager.class); 20 | 21 | private static final String MENU_CREATE_POST_URL = "https://api.weixin.qq.com/cgi-bin/menu/create?access_token="; 22 | private static final String MENU_GET_GET_URL = "https://api.weixin.qq.com/cgi-bin/menu/get?access_token="; 23 | private static final String MENU_DEL_GET_URL = "https://api.weixin.qq.com/cgi-bin/menu/delete?access_token="; 24 | 25 | private String accessToken; 26 | public MenuManager() { 27 | this.accessToken = TokenProxy.accessToken(); 28 | } 29 | /** 30 | * 创建菜单 31 | * @throws WeChatException 32 | */ 33 | public void create(Menu menu) throws WeChatException{ 34 | logger.info("创建菜单"); 35 | String resultStr = HttpUtils.post(MENU_CREATE_POST_URL+this.accessToken, JSON.toJSONString(menu)); 36 | WeChatUtil.isSuccess(resultStr); 37 | } 38 | 39 | /** 40 | * 查询菜单 41 | */ 42 | public Menu getMenu() { 43 | logger.info("查询菜单"); 44 | String resultStr = HttpUtils.get(MENU_GET_GET_URL+this.accessToken); 45 | try { 46 | WeChatUtil.isSuccess(resultStr); 47 | } catch (WeChatException e) { 48 | e.printStackTrace(); 49 | return null; 50 | } 51 | JSONObject menuObject = JSONObject.parseObject(resultStr); 52 | Menu menu = menuObject.getObject("menu", Menu.class); 53 | return menu; 54 | } 55 | /** 56 | * 删除菜单 57 | * @throws WeChatException 58 | */ 59 | public void delete() throws WeChatException{ 60 | logger.info("删除菜单"); 61 | String resultStr = HttpUtils.get(MENU_DEL_GET_URL+this.accessToken); 62 | WeChatUtil.isSuccess(resultStr); 63 | } 64 | 65 | } 66 | -------------------------------------------------------------------------------- /src/org/sword/wechat4j/message/TemplateMsg.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 对应接口文档地址 3 | * http://mp.weixin.qq.com/wiki/17/304c1885ea66dbedf7dc170d84999a9d.html 4 | */ 5 | package org.sword.wechat4j.message; 6 | 7 | import org.apache.log4j.Logger; 8 | import org.sword.lang.HttpUtils; 9 | import org.sword.wechat4j.message.template.TemplateMsgBody; 10 | import org.sword.wechat4j.message.template.TemplateMsgData; 11 | import org.sword.wechat4j.token.TokenProxy; 12 | 13 | import com.alibaba.fastjson.JSONObject; 14 | 15 | /** 16 | * 模板消息接口 17 | * @author ChengNing 18 | * @date 2014年12月24日 19 | */ 20 | public class TemplateMsg { 21 | 22 | private static Logger logger = Logger.getLogger(TemplateMsg.class); 23 | 24 | //设置所属行业接口地址 25 | public static final String SET_INDUSTRY_URL = "https://api.weixin.qq.com/cgi-bin/template/api_set_industry?access_token="; 26 | //添加模板id接口地址 27 | public static final String GET_TEMPLATE_ID_URL = "https://api.weixin.qq.com/cgi-bin/template/api_add_template?access_token="; 28 | //发送模板消息接口地址 29 | public static final String SEND_MSG_URL = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token="; 30 | 31 | private String accessToken; 32 | 33 | public TemplateMsg(){ 34 | this.accessToken = TokenProxy.accessToken(); 35 | } 36 | 37 | /** 38 | * 设置所属行业 39 | * 接口说明中没有给出 40 | */ 41 | public void setIndustry(String...industrys){ 42 | String url = SET_INDUSTRY_URL + this.accessToken; 43 | JSONObject json = new JSONObject(); 44 | for(int i=0;i keynote; 21 | private List data; 22 | public String getTouser() { 23 | return touser; 24 | } 25 | public void setTouser(String touser) { 26 | this.touser = touser; 27 | } 28 | public String getTemplateId() { 29 | return templateId; 30 | } 31 | public void setTemplateId(String templateId) { 32 | this.templateId = templateId; 33 | } 34 | public String getUrl() { 35 | return url; 36 | } 37 | public void setUrl(String url) { 38 | this.url = url; 39 | } 40 | public String getTopcolor() { 41 | return topcolor; 42 | } 43 | public void setTopcolor(String topcolor) { 44 | this.topcolor = topcolor; 45 | } 46 | // public TemplateMsgData getFirst() { 47 | // return first; 48 | // } 49 | // public void setFirst(TemplateMsgData first) { 50 | // this.first = first; 51 | // } 52 | // public TemplateMsgData getRemark() { 53 | // return remark; 54 | // } 55 | // public void setRemark(TemplateMsgData remark) { 56 | // this.remark = remark; 57 | // } 58 | // public List getKeynote() { 59 | // return keynote; 60 | // } 61 | // public void setKeynote(List keynote) { 62 | // this.keynote = keynote; 63 | // } 64 | public List getData() { 65 | return data; 66 | } 67 | public void setData(List data) { 68 | this.data = data; 69 | } 70 | 71 | 72 | 73 | 74 | 75 | } 76 | -------------------------------------------------------------------------------- /src/org/sword/wechat4j/message/template/TemplateMsgData.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package org.sword.wechat4j.message.template; 5 | 6 | /** 7 | * @author ChengNing 8 | * @date 2014年12月24日 9 | */ 10 | public class TemplateMsgData { 11 | private String name; //json中的数据名称 12 | private String value; //keynote value 13 | private String color; //data keynote color 14 | 15 | 16 | public String getName() { 17 | return name; 18 | } 19 | public void setName(String name) { 20 | this.name = name; 21 | } 22 | public String getValue() { 23 | return value; 24 | } 25 | public void setValue(String value) { 26 | this.value = value; 27 | } 28 | public String getColor() { 29 | return color; 30 | } 31 | public void setColor(String color) { 32 | this.color = color; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/org/sword/wechat4j/oauth/OAuthException.java: -------------------------------------------------------------------------------- 1 | package org.sword.wechat4j.oauth; 2 | 3 | /** 4 | * OAuth API 调用异常 5 | * Created by xuwen on 2015-12-11. 6 | */ 7 | public class OAuthException extends Exception { 8 | 9 | public OAuthException() { 10 | } 11 | 12 | public OAuthException(String errcode, String errmsg) { 13 | this.errcode = errcode; 14 | this.errmsg = errmsg; 15 | } 16 | 17 | private String errcode; 18 | private String errmsg; 19 | 20 | public String getErrcode() { 21 | return errcode; 22 | } 23 | 24 | public void setErrcode(String errcode) { 25 | this.errcode = errcode; 26 | } 27 | 28 | public String getErrmsg() { 29 | return errmsg; 30 | } 31 | 32 | public void setErrmsg(String errmsg) { 33 | this.errmsg = errmsg; 34 | } 35 | 36 | @Override 37 | public String toString() { 38 | return "OAuthException{" + 39 | "errcode='" + errcode + '\'' + 40 | ", errmsg='" + errmsg + '\'' + 41 | '}'; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/org/sword/wechat4j/oauth/protocol/get_access_token/GetAccessTokenRequest.java: -------------------------------------------------------------------------------- 1 | package org.sword.wechat4j.oauth.protocol.get_access_token; 2 | 3 | import org.sword.wechat4j.common.Config; 4 | 5 | /** 6 | * 请求:通过code换取网页授权access_token 7 | * Created by xuwen on 2015-12-11. 8 | */ 9 | public class GetAccessTokenRequest { 10 | 11 | public GetAccessTokenRequest(String code) { 12 | this.code = code; 13 | } 14 | 15 | private String appid = Config.instance().getAppid(); 16 | private String secret = Config.instance().getAppSecret(); 17 | private String code; 18 | private String grant_type = "authorization_code"; 19 | 20 | public String getAppid() { 21 | return appid; 22 | } 23 | 24 | public void setAppid(String appid) { 25 | this.appid = appid; 26 | } 27 | 28 | public String getSecret() { 29 | return secret; 30 | } 31 | 32 | public void setSecret(String secret) { 33 | this.secret = secret; 34 | } 35 | 36 | public String getCode() { 37 | return code; 38 | } 39 | 40 | public void setCode(String code) { 41 | this.code = code; 42 | } 43 | 44 | public String getGrant_type() { 45 | return grant_type; 46 | } 47 | 48 | public void setGrant_type(String grant_type) { 49 | this.grant_type = grant_type; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/org/sword/wechat4j/oauth/protocol/get_access_token/GetAccessTokenResponse.java: -------------------------------------------------------------------------------- 1 | package org.sword.wechat4j.oauth.protocol.get_access_token; 2 | 3 | /** 4 | * 响应:通过code换取网页授权access_token 5 | * Created by xuwen on 2015-12-11. 6 | */ 7 | public class GetAccessTokenResponse { 8 | 9 | private String access_token; 10 | private int expires_in; 11 | private String refresh_token; 12 | private String openid; 13 | private String scope; 14 | private String unionid; 15 | 16 | public String getAccess_token() { 17 | return access_token; 18 | } 19 | 20 | public void setAccess_token(String access_token) { 21 | this.access_token = access_token; 22 | } 23 | 24 | public int getExpires_in() { 25 | return expires_in; 26 | } 27 | 28 | public void setExpires_in(int expires_in) { 29 | this.expires_in = expires_in; 30 | } 31 | 32 | public String getRefresh_token() { 33 | return refresh_token; 34 | } 35 | 36 | public void setRefresh_token(String refresh_token) { 37 | this.refresh_token = refresh_token; 38 | } 39 | 40 | public String getOpenid() { 41 | return openid; 42 | } 43 | 44 | public void setOpenid(String openid) { 45 | this.openid = openid; 46 | } 47 | 48 | public String getScope() { 49 | return scope; 50 | } 51 | 52 | public void setScope(String scope) { 53 | this.scope = scope; 54 | } 55 | 56 | public String getUnionid() { 57 | return unionid; 58 | } 59 | 60 | public void setUnionid(String unionid) { 61 | this.unionid = unionid; 62 | } 63 | 64 | @Override 65 | public String toString() { 66 | return "GetAccessTokenResponse{" + 67 | "access_token='" + access_token + '\'' + 68 | ", expires_in=" + expires_in + 69 | ", refresh_token='" + refresh_token + '\'' + 70 | ", openid='" + openid + '\'' + 71 | ", scope='" + scope + '\'' + 72 | ", unionid='" + unionid + '\'' + 73 | '}'; 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /src/org/sword/wechat4j/oauth/protocol/get_userinfo/GetUserinfoRequest.java: -------------------------------------------------------------------------------- 1 | package org.sword.wechat4j.oauth.protocol.get_userinfo; 2 | 3 | /** 4 | * 请求:拉取用户信息(需scope为 snsapi_userinfo) 5 | * Created by xuwen on 2015-12-11. 6 | */ 7 | public class GetUserinfoRequest { 8 | 9 | public GetUserinfoRequest(String access_token, String openid) { 10 | this.access_token = access_token; 11 | this.openid = openid; 12 | } 13 | 14 | public GetUserinfoRequest(String access_token, String openid, String lang) { 15 | this.access_token = access_token; 16 | this.openid = openid; 17 | this.lang = lang; 18 | } 19 | 20 | private String access_token; 21 | private String openid; 22 | private String lang = "zh_CN"; 23 | 24 | public String getAccess_token() { 25 | return access_token; 26 | } 27 | 28 | public void setAccess_token(String access_token) { 29 | this.access_token = access_token; 30 | } 31 | 32 | public String getOpenid() { 33 | return openid; 34 | } 35 | 36 | public void setOpenid(String openid) { 37 | this.openid = openid; 38 | } 39 | 40 | public String getLang() { 41 | return lang; 42 | } 43 | 44 | public void setLang(String lang) { 45 | this.lang = lang; 46 | } 47 | 48 | @Override 49 | public String toString() { 50 | return "GetUserinfoRequest{" + 51 | "access_token='" + access_token + '\'' + 52 | ", openid='" + openid + '\'' + 53 | ", lang='" + lang + '\'' + 54 | '}'; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/org/sword/wechat4j/oauth/protocol/get_userinfo/GetUserinfoResponse.java: -------------------------------------------------------------------------------- 1 | package org.sword.wechat4j.oauth.protocol.get_userinfo; 2 | 3 | import java.util.Arrays; 4 | 5 | /** 6 | * 响应:拉取用户信息(需scope为 snsapi_userinfo) 7 | * Created by xuwen on 2015-12-11. 8 | */ 9 | public class GetUserinfoResponse { 10 | 11 | private String openid; 12 | private String nickname; 13 | private String sex; 14 | private String province; 15 | private String city; 16 | private String country; 17 | private String headimgurl; 18 | private String[] privilege; 19 | private String unionid; 20 | 21 | public String getOpenid() { 22 | return openid; 23 | } 24 | 25 | public void setOpenid(String openid) { 26 | this.openid = openid; 27 | } 28 | 29 | public String getNickname() { 30 | return nickname; 31 | } 32 | 33 | public void setNickname(String nickname) { 34 | this.nickname = nickname; 35 | } 36 | 37 | public String getSex() { 38 | return sex; 39 | } 40 | 41 | public void setSex(String sex) { 42 | this.sex = sex; 43 | } 44 | 45 | public String getProvince() { 46 | return province; 47 | } 48 | 49 | public void setProvince(String province) { 50 | this.province = province; 51 | } 52 | 53 | public String getCity() { 54 | return city; 55 | } 56 | 57 | public void setCity(String city) { 58 | this.city = city; 59 | } 60 | 61 | public String getCountry() { 62 | return country; 63 | } 64 | 65 | public void setCountry(String country) { 66 | this.country = country; 67 | } 68 | 69 | public String getHeadimgurl() { 70 | return headimgurl; 71 | } 72 | 73 | public void setHeadimgurl(String headimgurl) { 74 | this.headimgurl = headimgurl; 75 | } 76 | 77 | public String[] getPrivilege() { 78 | return privilege; 79 | } 80 | 81 | public void setPrivilege(String[] privilege) { 82 | this.privilege = privilege; 83 | } 84 | 85 | public String getUnionid() { 86 | return unionid; 87 | } 88 | 89 | public void setUnionid(String unionid) { 90 | this.unionid = unionid; 91 | } 92 | 93 | @Override 94 | public String toString() { 95 | return "GetUserinfoResponse{" + 96 | "openid='" + openid + '\'' + 97 | ", nickname='" + nickname + '\'' + 98 | ", sex='" + sex + '\'' + 99 | ", province='" + province + '\'' + 100 | ", city='" + city + '\'' + 101 | ", country='" + country + '\'' + 102 | ", headimgurl='" + headimgurl + '\'' + 103 | ", privilege=" + Arrays.toString(privilege) + 104 | ", unionid='" + unionid + '\'' + 105 | '}'; 106 | } 107 | } 108 | 109 | -------------------------------------------------------------------------------- /src/org/sword/wechat4j/oauth/protocol/refresh_access_token/RefreshAccessTokenRequest.java: -------------------------------------------------------------------------------- 1 | package org.sword.wechat4j.oauth.protocol.refresh_access_token; 2 | 3 | import org.sword.wechat4j.common.Config; 4 | 5 | /** 6 | * 响应:刷新access_token(如果需要) 7 | * Created by xuwen on 2015-12-11. 8 | */ 9 | public class RefreshAccessTokenRequest { 10 | 11 | public RefreshAccessTokenRequest(String refresh_token) { 12 | this.refresh_token = refresh_token; 13 | } 14 | 15 | private String appid = Config.instance().getAppid(); 16 | private String grant_type = "refresh_token"; 17 | private String refresh_token; 18 | 19 | public String getAppid() { 20 | return appid; 21 | } 22 | 23 | public void setAppid(String appid) { 24 | this.appid = appid; 25 | } 26 | 27 | public String getGrant_type() { 28 | return grant_type; 29 | } 30 | 31 | public void setGrant_type(String grant_type) { 32 | this.grant_type = grant_type; 33 | } 34 | 35 | public String getRefresh_token() { 36 | return refresh_token; 37 | } 38 | 39 | public void setRefresh_token(String refresh_token) { 40 | this.refresh_token = refresh_token; 41 | } 42 | 43 | @Override 44 | public String toString() { 45 | return "RefreshAccessTokenRequest{" + 46 | "appid='" + appid + '\'' + 47 | ", grant_type='" + grant_type + '\'' + 48 | ", refresh_token='" + refresh_token + '\'' + 49 | '}'; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/org/sword/wechat4j/oauth/protocol/refresh_access_token/RefreshAccessTokenResponse.java: -------------------------------------------------------------------------------- 1 | package org.sword.wechat4j.oauth.protocol.refresh_access_token; 2 | 3 | /** 4 | * 响应:刷新access_token(如果需要) 5 | * Created by xuwen on 2015-12-11. 6 | */ 7 | public class RefreshAccessTokenResponse { 8 | 9 | private String access_token; 10 | private int expires_in; 11 | private String refresh_token; 12 | private String openid; 13 | private String scope; 14 | 15 | public String getAccess_token() { 16 | return access_token; 17 | } 18 | 19 | public void setAccess_token(String access_token) { 20 | this.access_token = access_token; 21 | } 22 | 23 | public int getExpires_in() { 24 | return expires_in; 25 | } 26 | 27 | public void setExpires_in(int expires_in) { 28 | this.expires_in = expires_in; 29 | } 30 | 31 | public String getRefresh_token() { 32 | return refresh_token; 33 | } 34 | 35 | public void setRefresh_token(String refresh_token) { 36 | this.refresh_token = refresh_token; 37 | } 38 | 39 | public String getOpenid() { 40 | return openid; 41 | } 42 | 43 | public void setOpenid(String openid) { 44 | this.openid = openid; 45 | } 46 | 47 | public String getScope() { 48 | return scope; 49 | } 50 | 51 | public void setScope(String scope) { 52 | this.scope = scope; 53 | } 54 | 55 | @Override 56 | public String toString() { 57 | return "RefreshAccessTokenResponse{" + 58 | "access_token='" + access_token + '\'' + 59 | ", expires_in=" + expires_in + 60 | ", refresh_token='" + refresh_token + '\'' + 61 | ", openid='" + openid + '\'' + 62 | ", scope='" + scope + '\'' + 63 | '}'; 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/org/sword/wechat4j/oauth/protocol/valid_access_token/ValidAccessTokenRequest.java: -------------------------------------------------------------------------------- 1 | package org.sword.wechat4j.oauth.protocol.valid_access_token; 2 | 3 | /** 4 | * 响应:检验授权凭证(access_token)是否有效 5 | * Created by xuwen on 2015-12-11. 6 | */ 7 | public class ValidAccessTokenRequest { 8 | 9 | public ValidAccessTokenRequest(String access_token, String openid) { 10 | this.access_token = access_token; 11 | this.openid = openid; 12 | } 13 | 14 | private String access_token; 15 | private String openid; 16 | 17 | public String getAccess_token() { 18 | return access_token; 19 | } 20 | 21 | public void setAccess_token(String access_token) { 22 | this.access_token = access_token; 23 | } 24 | 25 | public String getOpenid() { 26 | return openid; 27 | } 28 | 29 | public void setOpenid(String openid) { 30 | this.openid = openid; 31 | } 32 | 33 | @Override 34 | public String toString() { 35 | return "ValidAccessTokenRequest{" + 36 | "access_token='" + access_token + '\'' + 37 | ", openid='" + openid + '\'' + 38 | '}'; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/org/sword/wechat4j/oauth/protocol/valid_access_token/ValidAccessTokenResponse.java: -------------------------------------------------------------------------------- 1 | package org.sword.wechat4j.oauth.protocol.valid_access_token; 2 | 3 | /** 4 | * 响应:检验授权凭证(access_token)是否有效 5 | * Created by xuwen on 2015-12-11. 6 | */ 7 | public class ValidAccessTokenResponse { 8 | 9 | private String errcode; 10 | private String errmsg; 11 | 12 | public String getErrcode() { 13 | return errcode; 14 | } 15 | 16 | public void setErrcode(String errcode) { 17 | this.errcode = errcode; 18 | } 19 | 20 | public String getErrmsg() { 21 | return errmsg; 22 | } 23 | 24 | public void setErrmsg(String errmsg) { 25 | this.errmsg = errmsg; 26 | } 27 | 28 | public boolean ok(){ 29 | return this.errmsg != null && "ok".equals(this.errmsg); 30 | } 31 | 32 | @Override 33 | public String toString() { 34 | return "ValidAccessTokenResponse{" + 35 | "errcode='" + errcode + '\'' + 36 | ", errmsg='" + errmsg + '\'' + 37 | '}'; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/org/sword/wechat4j/oauth/readme.md: -------------------------------------------------------------------------------- 1 | 使用本包需要在公众号设置中配置授权回调页面域名 2 | 3 | 菜单:开发-接口权限 4 | 选项:网页服务-网页账号-网页授权获取用户基本信息 5 | 6 | 用户在网页授权页同意授权给公众号后,微信会将授权数据传给一个回调页面,回调页面需在此域名下,以确保安全可靠。回调页面域名不支持IP地址。 7 | 8 | 开发文档:http://mp.weixin.qq.com/wiki/17/c0f37d5704f0b64713d5d2c37b468d75.html -------------------------------------------------------------------------------- /src/org/sword/wechat4j/param/SignatureParam.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package org.sword.wechat4j.param; 5 | 6 | import javax.servlet.http.HttpServletRequest; 7 | 8 | /** 9 | * 微信身份认证参数 10 | * @author ChengNing 11 | * @date 2014年12月6日 12 | */ 13 | public class SignatureParam { 14 | 15 | private String signature; 16 | private String timestamp ; 17 | private String nonce; 18 | private String echostr; 19 | 20 | public SignatureParam(HttpServletRequest request){ 21 | signature = request.getParameter(WechatParamName.SIGNATURE); 22 | timestamp = request.getParameter(WechatParamName.TIMESTAMP); 23 | nonce = request.getParameter(WechatParamName.NONCE); 24 | echostr = request.getParameter(WechatParamName.ECHOSTR); 25 | } 26 | 27 | public String getSignature() { 28 | return signature; 29 | } 30 | 31 | public void setSignature(String signature) { 32 | this.signature = signature; 33 | } 34 | 35 | public String getTimestamp() { 36 | return timestamp; 37 | } 38 | 39 | public void setTimestamp(String timestamp) { 40 | this.timestamp = timestamp; 41 | } 42 | 43 | public String getNonce() { 44 | return nonce; 45 | } 46 | 47 | public void setNonce(String nonce) { 48 | this.nonce = nonce; 49 | } 50 | 51 | public String getEchostr() { 52 | return echostr; 53 | } 54 | 55 | public void setEchostr(String echostr) { 56 | this.echostr = echostr; 57 | } 58 | 59 | 60 | 61 | } 62 | -------------------------------------------------------------------------------- /src/org/sword/wechat4j/param/WechatParamName.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package org.sword.wechat4j.param; 5 | 6 | /** 7 | * 微信接口中get请求方式中的参数名称 8 | * @author ChengNing 9 | * @date 2014-12-4 10 | */ 11 | public class WechatParamName { 12 | 13 | public static final String ECHOSTR = "echostr"; 14 | public static final String SIGNATURE = "signature"; 15 | public static final String TIMESTAMP = "timestamp"; 16 | public static final String NONCE = "nonce"; 17 | 18 | 19 | } 20 | -------------------------------------------------------------------------------- /src/org/sword/wechat4j/pay/H5PayParam.java: -------------------------------------------------------------------------------- 1 | package org.sword.wechat4j.pay; 2 | 3 | import org.sword.wechat4j.common.Config; 4 | 5 | import javax.xml.bind.annotation.XmlElement; 6 | 7 | /** 8 | * H5调起支付API的参数对象 9 | *

开发文档

10 | *

11 | * Created by xuwen on 2015-12-10. 12 | */ 13 | public class H5PayParam { 14 | private String appid = Config.instance().getAppid(); 15 | private String timeStamp; 16 | private String nonceStr; 17 | private String packageWithPrepayId; // 参数名package 18 | private String signType = "MD5"; 19 | private String paySign; 20 | 21 | @XmlElement(name = "appId") 22 | public String getAppid() { 23 | return appid; 24 | } 25 | 26 | public void setAppid(String appid) { 27 | this.appid = appid; 28 | } 29 | 30 | public String getTimeStamp() { 31 | return timeStamp; 32 | } 33 | 34 | public void setTimeStamp(String timeStamp) { 35 | this.timeStamp = timeStamp; 36 | } 37 | 38 | public String getNonceStr() { 39 | return nonceStr; 40 | } 41 | 42 | public void setNonceStr(String nonceStr) { 43 | this.nonceStr = nonceStr; 44 | } 45 | 46 | @XmlElement(name = "package") 47 | public String getPackageWithPrepayId() { 48 | return packageWithPrepayId; 49 | } 50 | 51 | public void setPackageWithPrepayId(String packageWithPrepayId) { 52 | this.packageWithPrepayId = packageWithPrepayId; 53 | } 54 | 55 | public String getSignType() { 56 | return signType; 57 | } 58 | 59 | public void setSignType(String signType) { 60 | this.signType = signType; 61 | } 62 | 63 | public String getPaySign() { 64 | return paySign; 65 | } 66 | 67 | public void setPaySign(String paySign) { 68 | this.paySign = paySign; 69 | } 70 | 71 | @Override 72 | public String toString() { 73 | return "H5PayConfig{" + 74 | "appid='" + appid + '\'' + 75 | ", timeStamp='" + timeStamp + '\'' + 76 | ", nonceStr='" + nonceStr + '\'' + 77 | ", packageWithPrepayId='" + packageWithPrepayId + '\'' + 78 | ", signType='" + signType + '\'' + 79 | ", paySign='" + paySign + '\'' + 80 | '}'; 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /src/org/sword/wechat4j/pay/PayCode.java: -------------------------------------------------------------------------------- 1 | package org.sword.wechat4j.pay; 2 | 3 | /** 4 | * 支付的结果 5 | * 对应以下2项返回数据 6 | * return_code 7 | * result_code 8 | *

9 | * Created by xuwen on 2015-12-13. 10 | */ 11 | public enum PayCode { 12 | 13 | SUCCESS, 14 | FAIL; 15 | 16 | public boolean equals(String payCode) { 17 | return this.toString().equals(payCode); 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /src/org/sword/wechat4j/pay/exception/PayApiException.java: -------------------------------------------------------------------------------- 1 | package org.sword.wechat4j.pay.exception; 2 | 3 | 4 | import org.sword.wechat4j.pay.PayCode; 5 | 6 | import javax.xml.bind.annotation.XmlRootElement; 7 | 8 | /** 9 | * 支付API调用异常 10 | * return_code=FAIL 11 | *

12 | * Created by xuwen on 2015-12-11. 13 | */ 14 | @XmlRootElement(name = "xml") 15 | public class PayApiException extends Exception { 16 | 17 | public PayApiException() { 18 | } 19 | 20 | 21 | 22 | public PayApiException(PayCode payCode, String return_msg) { 23 | this.return_code = payCode.toString(); 24 | this.return_msg = return_msg; 25 | } 26 | 27 | public PayApiException(String return_code, String return_msg) { 28 | this.return_code = return_code; 29 | this.return_msg = return_msg; 30 | } 31 | 32 | private String return_code; 33 | private String return_msg; 34 | 35 | public String getReturn_code() { 36 | return return_code; 37 | } 38 | 39 | public void setReturn_code(String return_code) { 40 | this.return_code = return_code; 41 | } 42 | 43 | public String getReturn_msg() { 44 | return return_msg; 45 | } 46 | 47 | public void setReturn_msg(String return_msg) { 48 | this.return_msg = return_msg; 49 | } 50 | 51 | @Override 52 | public String toString() { 53 | return "PayApiException{" + 54 | "return_code='" + return_code + '\'' + 55 | ", return_msg='" + return_msg + '\'' + 56 | '}'; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/org/sword/wechat4j/pay/exception/PayBusinessException.java: -------------------------------------------------------------------------------- 1 | package org.sword.wechat4j.pay.exception; 2 | 3 | import org.sword.wechat4j.pay.PayCode; 4 | 5 | import javax.xml.bind.annotation.XmlRootElement; 6 | 7 | /** 8 | * 支付业务异常 9 | * result_code=FAIL 10 | *

11 | * Created by xuwen on 2015-12-13. 12 | */ 13 | @XmlRootElement(name = "xml") 14 | public class PayBusinessException extends Exception { 15 | 16 | public PayBusinessException() { 17 | } 18 | 19 | public PayBusinessException(PayCode payCode, String err_code, String err_code_des) { 20 | this.result_code = payCode.toString(); 21 | this.err_code = err_code; 22 | this.err_code_des = err_code_des; 23 | } 24 | 25 | private String result_code; 26 | private String err_code; 27 | private String err_code_des; 28 | 29 | public String getResult_code() { 30 | return result_code; 31 | } 32 | 33 | public void setResult_code(String result_code) { 34 | this.result_code = result_code; 35 | } 36 | 37 | public String getErr_code() { 38 | return err_code; 39 | } 40 | 41 | public void setErr_code(String err_code) { 42 | this.err_code = err_code; 43 | } 44 | 45 | public String getErr_code_des() { 46 | return err_code_des; 47 | } 48 | 49 | public void setErr_code_des(String err_code_des) { 50 | this.err_code_des = err_code_des; 51 | } 52 | 53 | @Override 54 | public String toString() { 55 | return this.getClass().getSimpleName() + "{" + 56 | "result_code='" + result_code + '\'' + 57 | ", err_code='" + err_code + '\'' + 58 | ", err_code_des='" + err_code_des + '\'' + 59 | '}'; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/org/sword/wechat4j/pay/exception/SignatureException.java: -------------------------------------------------------------------------------- 1 | package org.sword.wechat4j.pay.exception; 2 | 3 | /** 4 | * 签名异常 5 | * Created by xuwen on 2015-12-12. 6 | */ 7 | public class SignatureException extends Exception { 8 | 9 | public SignatureException() { 10 | super("返回结果的签名校验失败,数据可能已经被篡改"); 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /src/org/sword/wechat4j/pay/protocol/closeorder/CloseorderRequest.java: -------------------------------------------------------------------------------- 1 | package org.sword.wechat4j.pay.protocol.closeorder; 2 | 3 | import org.sword.wechat4j.common.Config; 4 | 5 | import javax.xml.bind.annotation.XmlRootElement; 6 | 7 | /** 8 | * 关闭订单请求对象 9 | *

参考开发文档

10 | *

11 | * Created by xuwen on 2015-12-13. 12 | */ 13 | @XmlRootElement(name = "xml") 14 | public class CloseorderRequest { 15 | 16 | private String appid = Config.instance().getAppid(); 17 | private String mch_id = Config.instance().getMchId(); 18 | private String out_trade_no; 19 | private String nonce_str; 20 | private String sign; 21 | 22 | public String getAppid() { 23 | return appid; 24 | } 25 | 26 | public void setAppid(String appid) { 27 | this.appid = appid; 28 | } 29 | 30 | public String getMch_id() { 31 | return mch_id; 32 | } 33 | 34 | public void setMch_id(String mch_id) { 35 | this.mch_id = mch_id; 36 | } 37 | 38 | public String getOut_trade_no() { 39 | return out_trade_no; 40 | } 41 | 42 | public void setOut_trade_no(String out_trade_no) { 43 | this.out_trade_no = out_trade_no; 44 | } 45 | 46 | public String getNonce_str() { 47 | return nonce_str; 48 | } 49 | 50 | public void setNonce_str(String nonce_str) { 51 | this.nonce_str = nonce_str; 52 | } 53 | 54 | public String getSign() { 55 | return sign; 56 | } 57 | 58 | public void setSign(String sign) { 59 | this.sign = sign; 60 | } 61 | 62 | @Override 63 | public String toString() { 64 | return "CloseorderRequest{" + 65 | "appid='" + appid + '\'' + 66 | ", mch_id='" + mch_id + '\'' + 67 | ", out_trade_no='" + out_trade_no + '\'' + 68 | ", nonce_str='" + nonce_str + '\'' + 69 | ", sign='" + sign + '\'' + 70 | '}'; 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /src/org/sword/wechat4j/pay/protocol/closeorder/CloseorderResponse.java: -------------------------------------------------------------------------------- 1 | package org.sword.wechat4j.pay.protocol.closeorder; 2 | 3 | import javax.xml.bind.annotation.XmlRootElement; 4 | 5 | /** 6 | * 关闭订单响应对象 7 | *

开发文档

8 | *

9 | * Created by xuwen on 2015-12-13. 10 | */ 11 | @XmlRootElement(name = "xml") 12 | public class CloseorderResponse { 13 | 14 | private String appid; 15 | private String mch_id; 16 | private String nonce_str; 17 | private String sign; 18 | private String result_code; 19 | private String err_code; 20 | private String err_code_des; 21 | 22 | public String getAppid() { 23 | return appid; 24 | } 25 | 26 | public void setAppid(String appid) { 27 | this.appid = appid; 28 | } 29 | 30 | public String getMch_id() { 31 | return mch_id; 32 | } 33 | 34 | public void setMch_id(String mch_id) { 35 | this.mch_id = mch_id; 36 | } 37 | 38 | public String getNonce_str() { 39 | return nonce_str; 40 | } 41 | 42 | public void setNonce_str(String nonce_str) { 43 | this.nonce_str = nonce_str; 44 | } 45 | 46 | public String getSign() { 47 | return sign; 48 | } 49 | 50 | public void setSign(String sign) { 51 | this.sign = sign; 52 | } 53 | 54 | public String getResult_code() { 55 | return result_code; 56 | } 57 | 58 | public void setResult_code(String result_code) { 59 | this.result_code = result_code; 60 | } 61 | 62 | public String getErr_code() { 63 | return err_code; 64 | } 65 | 66 | public void setErr_code(String err_code) { 67 | this.err_code = err_code; 68 | } 69 | 70 | public String getErr_code_des() { 71 | return err_code_des; 72 | } 73 | 74 | public void setErr_code_des(String err_code_des) { 75 | this.err_code_des = err_code_des; 76 | } 77 | 78 | @Override 79 | public String toString() { 80 | return "CloseorderResponse{" + 81 | "appid='" + appid + '\'' + 82 | ", mch_id='" + mch_id + '\'' + 83 | ", nonce_str='" + nonce_str + '\'' + 84 | ", sign='" + sign + '\'' + 85 | ", result_code='" + result_code + '\'' + 86 | ", err_code='" + err_code + '\'' + 87 | ", err_code_des='" + err_code_des + '\'' + 88 | '}'; 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /src/org/sword/wechat4j/pay/protocol/downloadbill/DownloadbillRequest.java: -------------------------------------------------------------------------------- 1 | package org.sword.wechat4j.pay.protocol.downloadbill; 2 | 3 | import org.sword.wechat4j.common.Config; 4 | 5 | import javax.xml.bind.annotation.XmlRootElement; 6 | 7 | /** 8 | * 下载对账单请求对象 9 | *

参考开发文档

10 | *

11 | * Created by xuwen on 2015-12-13. 12 | */ 13 | @XmlRootElement(name = "xml") 14 | public class DownloadbillRequest { 15 | 16 | private String appid = Config.instance().getAppid(); 17 | private String mch_id = Config.instance().getMchId(); 18 | private String device_info; 19 | private String nonce_str; 20 | private String sign; 21 | private String bill_date; 22 | private String bill_type; 23 | 24 | public String getAppid() { 25 | return appid; 26 | } 27 | 28 | public void setAppid(String appid) { 29 | this.appid = appid; 30 | } 31 | 32 | public String getMch_id() { 33 | return mch_id; 34 | } 35 | 36 | public void setMch_id(String mch_id) { 37 | this.mch_id = mch_id; 38 | } 39 | 40 | public String getDevice_info() { 41 | return device_info; 42 | } 43 | 44 | public void setDevice_info(String device_info) { 45 | this.device_info = device_info; 46 | } 47 | 48 | public String getNonce_str() { 49 | return nonce_str; 50 | } 51 | 52 | public void setNonce_str(String nonce_str) { 53 | this.nonce_str = nonce_str; 54 | } 55 | 56 | public String getSign() { 57 | return sign; 58 | } 59 | 60 | public void setSign(String sign) { 61 | this.sign = sign; 62 | } 63 | 64 | public String getBill_date() { 65 | return bill_date; 66 | } 67 | 68 | public void setBill_date(String bill_date) { 69 | this.bill_date = bill_date; 70 | } 71 | 72 | public String getBill_type() { 73 | return bill_type; 74 | } 75 | 76 | public void setBill_type(String bill_type) { 77 | this.bill_type = bill_type; 78 | } 79 | 80 | @Override 81 | public String toString() { 82 | return "DownloadbillRequest{" + 83 | "appid='" + appid + '\'' + 84 | ", mch_id='" + mch_id + '\'' + 85 | ", device_info='" + device_info + '\'' + 86 | ", nonce_str='" + nonce_str + '\'' + 87 | ", sign='" + sign + '\'' + 88 | ", bill_date='" + bill_date + '\'' + 89 | ", bill_type='" + bill_type + '\'' + 90 | '}'; 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /src/org/sword/wechat4j/pay/protocol/orderquery/OrderqueryRequest.java: -------------------------------------------------------------------------------- 1 | package org.sword.wechat4j.pay.protocol.orderquery; 2 | 3 | import org.sword.wechat4j.common.Config; 4 | 5 | import javax.xml.bind.annotation.XmlRootElement; 6 | 7 | /** 8 | * 查询订单请求对象 9 | *

参考开发文档

10 | *

11 | * Created by xuwen on 2015-12-13. 12 | */ 13 | @XmlRootElement(name = "xml") 14 | public class OrderqueryRequest { 15 | 16 | private String appid = Config.instance().getAppid(); 17 | private String mch_id = Config.instance().getMchId(); 18 | private String transaction_id; 19 | private String out_trade_no; 20 | private String nonce_str; 21 | private String sign; 22 | 23 | public String getAppid() { 24 | return appid; 25 | } 26 | 27 | public void setAppid(String appid) { 28 | this.appid = appid; 29 | } 30 | 31 | public String getMch_id() { 32 | return mch_id; 33 | } 34 | 35 | public void setMch_id(String mch_id) { 36 | this.mch_id = mch_id; 37 | } 38 | 39 | public String getTransaction_id() { 40 | return transaction_id; 41 | } 42 | 43 | public void setTransaction_id(String transaction_id) { 44 | this.transaction_id = transaction_id; 45 | } 46 | 47 | public String getOut_trade_no() { 48 | return out_trade_no; 49 | } 50 | 51 | public void setOut_trade_no(String out_trade_no) { 52 | this.out_trade_no = out_trade_no; 53 | } 54 | 55 | public String getNonce_str() { 56 | return nonce_str; 57 | } 58 | 59 | public void setNonce_str(String nonce_str) { 60 | this.nonce_str = nonce_str; 61 | } 62 | 63 | public String getSign() { 64 | return sign; 65 | } 66 | 67 | public void setSign(String sign) { 68 | this.sign = sign; 69 | } 70 | 71 | @Override 72 | public String toString() { 73 | return "OrderqueryRequest{" + 74 | "appid='" + appid + '\'' + 75 | ", mch_id='" + mch_id + '\'' + 76 | ", transaction_id='" + transaction_id + '\'' + 77 | ", out_trade_no='" + out_trade_no + '\'' + 78 | ", nonce_str='" + nonce_str + '\'' + 79 | ", sign='" + sign + '\'' + 80 | '}'; 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /src/org/sword/wechat4j/pay/protocol/refund/RefundRequest.java: -------------------------------------------------------------------------------- 1 | package org.sword.wechat4j.pay.protocol.refund; 2 | 3 | import org.sword.wechat4j.common.Config; 4 | 5 | import javax.xml.bind.annotation.XmlRootElement; 6 | 7 | /** 8 | * 申请退款请求对象 9 | *

参考开发文档

10 | *

11 | * Created by xuwen on 2015-12-10. 12 | */ 13 | @XmlRootElement(name = "xml") 14 | public class RefundRequest { 15 | 16 | private String appid = Config.instance().getAppid(); 17 | private String mch_id = Config.instance().getMchId(); 18 | private String device_info; 19 | private String nonce_str; 20 | private String sign; 21 | private String transaction_id; 22 | private String out_trade_no; 23 | private String out_refund_no; 24 | private int total_fee; 25 | private int refund_fee; 26 | private String refund_fee_type = "CNY"; 27 | private String op_user_id; 28 | 29 | public String getAppid() { 30 | return appid; 31 | } 32 | 33 | public void setAppid(String appid) { 34 | this.appid = appid; 35 | } 36 | 37 | public String getMch_id() { 38 | return mch_id; 39 | } 40 | 41 | public void setMch_id(String mch_id) { 42 | this.mch_id = mch_id; 43 | } 44 | 45 | public String getDevice_info() { 46 | return device_info; 47 | } 48 | 49 | public void setDevice_info(String device_info) { 50 | this.device_info = device_info; 51 | } 52 | 53 | public String getNonce_str() { 54 | return nonce_str; 55 | } 56 | 57 | public void setNonce_str(String nonce_str) { 58 | this.nonce_str = nonce_str; 59 | } 60 | 61 | public String getSign() { 62 | return sign; 63 | } 64 | 65 | public void setSign(String sign) { 66 | this.sign = sign; 67 | } 68 | 69 | public String getTransaction_id() { 70 | return transaction_id; 71 | } 72 | 73 | public void setTransaction_id(String transaction_id) { 74 | this.transaction_id = transaction_id; 75 | } 76 | 77 | public String getOut_trade_no() { 78 | return out_trade_no; 79 | } 80 | 81 | public void setOut_trade_no(String out_trade_no) { 82 | this.out_trade_no = out_trade_no; 83 | } 84 | 85 | public String getOut_refund_no() { 86 | return out_refund_no; 87 | } 88 | 89 | public void setOut_refund_no(String out_refund_no) { 90 | this.out_refund_no = out_refund_no; 91 | } 92 | 93 | public int getTotal_fee() { 94 | return total_fee; 95 | } 96 | 97 | public void setTotal_fee(int total_fee) { 98 | this.total_fee = total_fee; 99 | } 100 | 101 | public int getRefund_fee() { 102 | return refund_fee; 103 | } 104 | 105 | public void setRefund_fee(int refund_fee) { 106 | this.refund_fee = refund_fee; 107 | } 108 | 109 | public String getRefund_fee_type() { 110 | return refund_fee_type; 111 | } 112 | 113 | public void setRefund_fee_type(String refund_fee_type) { 114 | this.refund_fee_type = refund_fee_type; 115 | } 116 | 117 | public String getOp_user_id() { 118 | return op_user_id; 119 | } 120 | 121 | public void setOp_user_id(String op_user_id) { 122 | this.op_user_id = op_user_id; 123 | } 124 | 125 | @Override 126 | public String toString() { 127 | return "RefundRequest{" + 128 | "appid='" + appid + '\'' + 129 | ", mch_id='" + mch_id + '\'' + 130 | ", device_info='" + device_info + '\'' + 131 | ", nonce_str='" + nonce_str + '\'' + 132 | ", sign='" + sign + '\'' + 133 | ", transaction_id='" + transaction_id + '\'' + 134 | ", out_trade_no='" + out_trade_no + '\'' + 135 | ", out_refund_no='" + out_refund_no + '\'' + 136 | ", total_fee=" + total_fee + 137 | ", refund_fee=" + refund_fee + 138 | ", refund_fee_type='" + refund_fee_type + '\'' + 139 | ", op_user_id='" + op_user_id + '\'' + 140 | '}'; 141 | } 142 | } 143 | -------------------------------------------------------------------------------- /src/org/sword/wechat4j/pay/protocol/refundquery/RefundqueryRequest.java: -------------------------------------------------------------------------------- 1 | package org.sword.wechat4j.pay.protocol.refundquery; 2 | 3 | import org.sword.wechat4j.common.Config; 4 | 5 | import javax.xml.bind.annotation.XmlRootElement; 6 | 7 | /** 8 | * 查询退款请求对象 9 | *

参考开发文档

10 | *

11 | * Created by xuwen on 2015-12-10. 12 | */ 13 | @XmlRootElement(name = "xml") 14 | public class RefundqueryRequest { 15 | 16 | private String appid = Config.instance().getAppid(); 17 | private String mch_id = Config.instance().getMchId(); 18 | private String device_info; 19 | private String nonce_str; 20 | private String sign; 21 | private String transaction_id; 22 | private String out_trade_no; 23 | private String out_refund_no; 24 | private String refund_id; 25 | 26 | public String getAppid() { 27 | return appid; 28 | } 29 | 30 | public void setAppid(String appid) { 31 | this.appid = appid; 32 | } 33 | 34 | public String getMch_id() { 35 | return mch_id; 36 | } 37 | 38 | public void setMch_id(String mch_id) { 39 | this.mch_id = mch_id; 40 | } 41 | 42 | public String getDevice_info() { 43 | return device_info; 44 | } 45 | 46 | public void setDevice_info(String device_info) { 47 | this.device_info = device_info; 48 | } 49 | 50 | public String getNonce_str() { 51 | return nonce_str; 52 | } 53 | 54 | public void setNonce_str(String nonce_str) { 55 | this.nonce_str = nonce_str; 56 | } 57 | 58 | public String getSign() { 59 | return sign; 60 | } 61 | 62 | public void setSign(String sign) { 63 | this.sign = sign; 64 | } 65 | 66 | public String getTransaction_id() { 67 | return transaction_id; 68 | } 69 | 70 | public void setTransaction_id(String transaction_id) { 71 | this.transaction_id = transaction_id; 72 | } 73 | 74 | public String getOut_trade_no() { 75 | return out_trade_no; 76 | } 77 | 78 | public void setOut_trade_no(String out_trade_no) { 79 | this.out_trade_no = out_trade_no; 80 | } 81 | 82 | public String getOut_refund_no() { 83 | return out_refund_no; 84 | } 85 | 86 | public void setOut_refund_no(String out_refund_no) { 87 | this.out_refund_no = out_refund_no; 88 | } 89 | 90 | public String getRefund_id() { 91 | return refund_id; 92 | } 93 | 94 | public void setRefund_id(String refund_id) { 95 | this.refund_id = refund_id; 96 | } 97 | 98 | @Override 99 | public String toString() { 100 | return "RefundqueryRequest{" + 101 | "appid='" + appid + '\'' + 102 | ", mch_id='" + mch_id + '\'' + 103 | ", device_info='" + device_info + '\'' + 104 | ", nonce_str='" + nonce_str + '\'' + 105 | ", sign='" + sign + '\'' + 106 | ", transaction_id='" + transaction_id + '\'' + 107 | ", out_trade_no='" + out_trade_no + '\'' + 108 | ", out_refund_no='" + out_refund_no + '\'' + 109 | ", refund_id='" + refund_id + '\'' + 110 | '}'; 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /src/org/sword/wechat4j/pay/protocol/report/ReportRequest.java: -------------------------------------------------------------------------------- 1 | package org.sword.wechat4j.pay.protocol.report; 2 | 3 | import org.sword.wechat4j.common.Config; 4 | 5 | import javax.xml.bind.annotation.XmlRootElement; 6 | 7 | /** 8 | * 测速上报请求对象 9 | *

参考开发文档

10 | *

11 | * Created by xuwen on 2015-12-13. 12 | */ 13 | @XmlRootElement(name = "xml") 14 | public class ReportRequest { 15 | 16 | private String appid = Config.instance().getAppid(); 17 | private String mch_id = Config.instance().getMchId(); 18 | private String device_info; 19 | private String nonce_str; 20 | private String sign; 21 | private String interface_url; 22 | private int execute_time_; 23 | private String return_code; 24 | private String return_msg; 25 | private String result_code; 26 | private String err_code; 27 | private String err_code_des; 28 | private String out_trade_no; 29 | private String user_ip; 30 | private String time; 31 | 32 | public String getAppid() { 33 | return appid; 34 | } 35 | 36 | public void setAppid(String appid) { 37 | this.appid = appid; 38 | } 39 | 40 | public String getMch_id() { 41 | return mch_id; 42 | } 43 | 44 | public void setMch_id(String mch_id) { 45 | this.mch_id = mch_id; 46 | } 47 | 48 | public String getDevice_info() { 49 | return device_info; 50 | } 51 | 52 | public void setDevice_info(String device_info) { 53 | this.device_info = device_info; 54 | } 55 | 56 | public String getNonce_str() { 57 | return nonce_str; 58 | } 59 | 60 | public void setNonce_str(String nonce_str) { 61 | this.nonce_str = nonce_str; 62 | } 63 | 64 | public String getSign() { 65 | return sign; 66 | } 67 | 68 | public void setSign(String sign) { 69 | this.sign = sign; 70 | } 71 | 72 | public String getInterface_url() { 73 | return interface_url; 74 | } 75 | 76 | public void setInterface_url(String interface_url) { 77 | this.interface_url = interface_url; 78 | } 79 | 80 | public int getExecute_time_() { 81 | return execute_time_; 82 | } 83 | 84 | public void setExecute_time_(int execute_time_) { 85 | this.execute_time_ = execute_time_; 86 | } 87 | 88 | public String getReturn_code() { 89 | return return_code; 90 | } 91 | 92 | public void setReturn_code(String return_code) { 93 | this.return_code = return_code; 94 | } 95 | 96 | public String getReturn_msg() { 97 | return return_msg; 98 | } 99 | 100 | public void setReturn_msg(String return_msg) { 101 | this.return_msg = return_msg; 102 | } 103 | 104 | public String getResult_code() { 105 | return result_code; 106 | } 107 | 108 | public void setResult_code(String result_code) { 109 | this.result_code = result_code; 110 | } 111 | 112 | public String getErr_code() { 113 | return err_code; 114 | } 115 | 116 | public void setErr_code(String err_code) { 117 | this.err_code = err_code; 118 | } 119 | 120 | public String getErr_code_des() { 121 | return err_code_des; 122 | } 123 | 124 | public void setErr_code_des(String err_code_des) { 125 | this.err_code_des = err_code_des; 126 | } 127 | 128 | public String getOut_trade_no() { 129 | return out_trade_no; 130 | } 131 | 132 | public void setOut_trade_no(String out_trade_no) { 133 | this.out_trade_no = out_trade_no; 134 | } 135 | 136 | public String getUser_ip() { 137 | return user_ip; 138 | } 139 | 140 | public void setUser_ip(String user_ip) { 141 | this.user_ip = user_ip; 142 | } 143 | 144 | public String getTime() { 145 | return time; 146 | } 147 | 148 | public void setTime(String time) { 149 | this.time = time; 150 | } 151 | 152 | @Override 153 | public String toString() { 154 | return "ReportRequest{" + 155 | "appid='" + appid + '\'' + 156 | ", mch_id='" + mch_id + '\'' + 157 | ", device_info='" + device_info + '\'' + 158 | ", nonce_str='" + nonce_str + '\'' + 159 | ", sign='" + sign + '\'' + 160 | ", interface_url='" + interface_url + '\'' + 161 | ", execute_time_='" + execute_time_ + '\'' + 162 | ", return_code='" + return_code + '\'' + 163 | ", return_msg='" + return_msg + '\'' + 164 | ", result_code='" + result_code + '\'' + 165 | ", err_code='" + err_code + '\'' + 166 | ", err_code_des='" + err_code_des + '\'' + 167 | ", out_trade_no='" + out_trade_no + '\'' + 168 | ", user_ip='" + user_ip + '\'' + 169 | ", time='" + time + '\'' + 170 | '}'; 171 | } 172 | } 173 | -------------------------------------------------------------------------------- /src/org/sword/wechat4j/pay/protocol/report/ReportResponse.java: -------------------------------------------------------------------------------- 1 | package org.sword.wechat4j.pay.protocol.report; 2 | 3 | import javax.xml.bind.annotation.XmlRootElement; 4 | 5 | /** 6 | * 测速上报请求对象 7 | *

参考开发文档

8 | *

9 | * Created by xuwen on 2015-12-13. 10 | */ 11 | @XmlRootElement(name = "xml") 12 | public class ReportResponse { 13 | 14 | private String result_code; 15 | 16 | public String getResult_code() { 17 | return result_code; 18 | } 19 | 20 | public void setResult_code(String result_code) { 21 | this.result_code = result_code; 22 | } 23 | 24 | @Override 25 | public String toString() { 26 | return "ReportResponse{" + 27 | "result_code='" + result_code + '\'' + 28 | '}'; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/org/sword/wechat4j/pay/protocol/unifiedorder/UnifiedorderRequest.java: -------------------------------------------------------------------------------- 1 | package org.sword.wechat4j.pay.protocol.unifiedorder; 2 | 3 | import org.sword.wechat4j.common.Config; 4 | 5 | import javax.xml.bind.annotation.XmlRootElement; 6 | 7 | 8 | /** 9 | * 统一下单请求对象 10 | *

参考开发文档

11 | *

12 | * Created by xuwen on 2015-12-10. 13 | */ 14 | @XmlRootElement(name = "xml") 15 | public class UnifiedorderRequest { 16 | 17 | private String appid = Config.instance().getAppid(); 18 | private String mch_id = Config.instance().getMchId(); 19 | private String device_info = "WEB"; 20 | private String nonce_str; 21 | private String sign; 22 | private String body; 23 | private String detail; 24 | private String attach; 25 | private String out_trade_no; 26 | private String fee_type = "CNY"; 27 | private int total_fee; 28 | private String spbill_create_ip; 29 | private String time_start; 30 | private String time_expire; 31 | private String goods_tag; 32 | private String notify_url; 33 | private String trade_type; 34 | private String product_id; 35 | private String limit_pay; 36 | private String openid; 37 | 38 | public String getAppid() { 39 | return appid; 40 | } 41 | 42 | public void setAppid(String appid) { 43 | this.appid = appid; 44 | } 45 | 46 | public String getMch_id() { 47 | return mch_id; 48 | } 49 | 50 | public void setMch_id(String mch_id) { 51 | this.mch_id = mch_id; 52 | } 53 | 54 | public String getDevice_info() { 55 | return device_info; 56 | } 57 | 58 | public void setDevice_info(String device_info) { 59 | this.device_info = device_info; 60 | } 61 | 62 | public String getNonce_str() { 63 | return nonce_str; 64 | } 65 | 66 | public void setNonce_str(String nonce_str) { 67 | this.nonce_str = nonce_str; 68 | } 69 | 70 | public String getSign() { 71 | return sign; 72 | } 73 | 74 | public void setSign(String sign) { 75 | this.sign = sign; 76 | } 77 | 78 | public String getBody() { 79 | return body; 80 | } 81 | 82 | public void setBody(String body) { 83 | this.body = body; 84 | } 85 | 86 | public String getDetail() { 87 | return detail; 88 | } 89 | 90 | public void setDetail(String detail) { 91 | this.detail = detail; 92 | } 93 | 94 | public String getAttach() { 95 | return attach; 96 | } 97 | 98 | public void setAttach(String attach) { 99 | this.attach = attach; 100 | } 101 | 102 | public String getOut_trade_no() { 103 | return out_trade_no; 104 | } 105 | 106 | public void setOut_trade_no(String out_trade_no) { 107 | this.out_trade_no = out_trade_no; 108 | } 109 | 110 | public String getFee_type() { 111 | return fee_type; 112 | } 113 | 114 | public void setFee_type(String fee_type) { 115 | this.fee_type = fee_type; 116 | } 117 | 118 | public int getTotal_fee() { 119 | return total_fee; 120 | } 121 | 122 | public void setTotal_fee(int total_fee) { 123 | this.total_fee = total_fee; 124 | } 125 | 126 | public String getSpbill_create_ip() { 127 | return spbill_create_ip; 128 | } 129 | 130 | public void setSpbill_create_ip(String spbill_create_ip) { 131 | this.spbill_create_ip = spbill_create_ip; 132 | } 133 | 134 | public String getTime_start() { 135 | return time_start; 136 | } 137 | 138 | public void setTime_start(String time_start) { 139 | this.time_start = time_start; 140 | } 141 | 142 | public String getTime_expire() { 143 | return time_expire; 144 | } 145 | 146 | public void setTime_expire(String time_expire) { 147 | this.time_expire = time_expire; 148 | } 149 | 150 | public String getGoods_tag() { 151 | return goods_tag; 152 | } 153 | 154 | public void setGoods_tag(String goods_tag) { 155 | this.goods_tag = goods_tag; 156 | } 157 | 158 | public String getNotify_url() { 159 | return notify_url; 160 | } 161 | 162 | public void setNotify_url(String notify_url) { 163 | this.notify_url = notify_url; 164 | } 165 | 166 | public String getTrade_type() { 167 | return trade_type; 168 | } 169 | 170 | public void setTrade_type(String trade_type) { 171 | this.trade_type = trade_type; 172 | } 173 | 174 | public String getProduct_id() { 175 | return product_id; 176 | } 177 | 178 | public void setProduct_id(String product_id) { 179 | this.product_id = product_id; 180 | } 181 | 182 | public String getLimit_pay() { 183 | return limit_pay; 184 | } 185 | 186 | public void setLimit_pay(String limit_pay) { 187 | this.limit_pay = limit_pay; 188 | } 189 | 190 | public String getOpenid() { 191 | return openid; 192 | } 193 | 194 | public void setOpenid(String openid) { 195 | this.openid = openid; 196 | } 197 | } 198 | -------------------------------------------------------------------------------- /src/org/sword/wechat4j/pay/protocol/unifiedorder/UnifiedorderResponse.java: -------------------------------------------------------------------------------- 1 | package org.sword.wechat4j.pay.protocol.unifiedorder; 2 | 3 | import javax.xml.bind.annotation.XmlRootElement; 4 | 5 | /** 6 | * 统一下单响应对象 7 | *

参考开发文档

8 | *

9 | * Created by xuwen on 2015-12-10. 10 | */ 11 | @XmlRootElement(name = "xml") 12 | public class UnifiedorderResponse { 13 | 14 | private String appid; 15 | private String mch_id; 16 | private String device_info; 17 | private String nonce_str; 18 | private String sign; 19 | private String result_code; 20 | private String err_code; 21 | private String err_code_des; 22 | /*以下字段在return_code 和result_code都为SUCCESS的时候有返回*/ 23 | private String trade_type; 24 | private String prepay_id; 25 | private String code_url; 26 | 27 | public String getAppid() { 28 | return appid; 29 | } 30 | 31 | public void setAppid(String appid) { 32 | this.appid = appid; 33 | } 34 | 35 | public String getMch_id() { 36 | return mch_id; 37 | } 38 | 39 | public void setMch_id(String mch_id) { 40 | this.mch_id = mch_id; 41 | } 42 | 43 | public String getDevice_info() { 44 | return device_info; 45 | } 46 | 47 | public void setDevice_info(String device_info) { 48 | this.device_info = device_info; 49 | } 50 | 51 | public String getNonce_str() { 52 | return nonce_str; 53 | } 54 | 55 | public void setNonce_str(String nonce_str) { 56 | this.nonce_str = nonce_str; 57 | } 58 | 59 | public String getSign() { 60 | return sign; 61 | } 62 | 63 | public void setSign(String sign) { 64 | this.sign = sign; 65 | } 66 | 67 | public String getResult_code() { 68 | return result_code; 69 | } 70 | 71 | public void setResult_code(String result_code) { 72 | this.result_code = result_code; 73 | } 74 | 75 | public String getErr_code() { 76 | return err_code; 77 | } 78 | 79 | public void setErr_code(String err_code) { 80 | this.err_code = err_code; 81 | } 82 | 83 | public String getErr_code_des() { 84 | return err_code_des; 85 | } 86 | 87 | public void setErr_code_des(String err_code_des) { 88 | this.err_code_des = err_code_des; 89 | } 90 | 91 | public String getTrade_type() { 92 | return trade_type; 93 | } 94 | 95 | public void setTrade_type(String trade_type) { 96 | this.trade_type = trade_type; 97 | } 98 | 99 | public String getPrepay_id() { 100 | return prepay_id; 101 | } 102 | 103 | public void setPrepay_id(String prepay_id) { 104 | this.prepay_id = prepay_id; 105 | } 106 | 107 | public String getCode_url() { 108 | return code_url; 109 | } 110 | 111 | public void setCode_url(String code_url) { 112 | this.code_url = code_url; 113 | } 114 | 115 | @Override 116 | public String toString() { 117 | return "UnifiedorderResponse{" + 118 | "appid='" + appid + '\'' + 119 | ", mch_id='" + mch_id + '\'' + 120 | ", device_info='" + device_info + '\'' + 121 | ", nonce_str='" + nonce_str + '\'' + 122 | ", sign='" + sign + '\'' + 123 | ", result_code='" + result_code + '\'' + 124 | ", err_code='" + err_code + '\'' + 125 | ", err_code_des='" + err_code_des + '\'' + 126 | ", trade_type='" + trade_type + '\'' + 127 | ", prepay_id='" + prepay_id + '\'' + 128 | ", code_url='" + code_url + '\'' + 129 | '}'; 130 | } 131 | } 132 | -------------------------------------------------------------------------------- /src/org/sword/wechat4j/pay/readme.md: -------------------------------------------------------------------------------- 1 | 使用本包需要申请开通微信支付功能并设置商户API密钥 2 | 3 | 商户平台登录入口:https://pay.weixin.qq.com/index.php/home/login 4 | 菜单:API安全 5 | 选项:设置API密钥 6 | 7 | 需要在配置文件中配置: 8 | 商户号 wechat.mch.id 9 | 商户API密钥 wechat.mch.key 10 | 11 | 开发文档:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=4_1 -------------------------------------------------------------------------------- /src/org/sword/wechat4j/request/Item.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package org.sword.wechat4j.request; 5 | 6 | import javax.xml.bind.annotation.XmlElement; 7 | 8 | /** 9 | * @author ChengNing 10 | * @date 2015年1月6日 11 | */ 12 | public class Item { 13 | private String PicMd5Sum; 14 | 15 | @XmlElement(name="PicMd5Sum") 16 | public String getPicMd5Sum() { 17 | return PicMd5Sum; 18 | } 19 | public void setPicMd5Sum(String picMd5Sum) { 20 | PicMd5Sum = picMd5Sum; 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /src/org/sword/wechat4j/request/ScanCodeInfo.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package org.sword.wechat4j.request; 5 | 6 | import javax.xml.bind.annotation.XmlElement; 7 | 8 | /** 9 | * @author ChengNing 10 | * @date 2015年1月7日 11 | */ 12 | public class ScanCodeInfo { 13 | private String ScanType; //扫描类型,一般是qrcode 14 | private String ScanResult; //扫描结果,即二维码对应的字符串信息 15 | 16 | @XmlElement(name="ScanType") 17 | public String getScanType() { 18 | return ScanType; 19 | } 20 | public void setScanType(String scanType) { 21 | ScanType = scanType; 22 | } 23 | @XmlElement(name="ScanResult") 24 | public String getScanResult() { 25 | return ScanResult; 26 | } 27 | public void setScanResult(String scanResult) { 28 | ScanResult = scanResult; 29 | } 30 | 31 | 32 | } 33 | -------------------------------------------------------------------------------- /src/org/sword/wechat4j/request/SendLocationInfo.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package org.sword.wechat4j.request; 5 | 6 | import javax.xml.bind.annotation.XmlElement; 7 | 8 | /** 9 | * @author ChengNing 10 | * @date 2015年1月7日 11 | */ 12 | public class SendLocationInfo { 13 | private String Location_X; 14 | private String Location_Y; 15 | private String Scale; 16 | private String Label; 17 | private String Poiname; 18 | 19 | @XmlElement(name="Location_X") 20 | public String getLocation_X() { 21 | return Location_X; 22 | } 23 | public void setLocation_X(String location_X) { 24 | Location_X = location_X; 25 | } 26 | @XmlElement(name="Location_Y") 27 | public String getLocation_Y() { 28 | return Location_Y; 29 | } 30 | public void setLocation_Y(String location_Y) { 31 | Location_Y = location_Y; 32 | } 33 | @XmlElement(name="Scale") 34 | public String getScale() { 35 | return Scale; 36 | } 37 | public void setScale(String scale) { 38 | Scale = scale; 39 | } 40 | @XmlElement(name="Label") 41 | public String getLabel() { 42 | return Label; 43 | } 44 | public void setLabel(String label) { 45 | Label = label; 46 | } 47 | @XmlElement(name="Poiname") 48 | public String getPoiname() { 49 | return Poiname; 50 | } 51 | public void setPoiname(String poiname) { 52 | Poiname = poiname; 53 | } 54 | 55 | 56 | 57 | 58 | } 59 | -------------------------------------------------------------------------------- /src/org/sword/wechat4j/request/SendPicsInfo.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package org.sword.wechat4j.request; 5 | 6 | import java.util.List; 7 | 8 | import javax.xml.bind.annotation.XmlElement; 9 | import javax.xml.bind.annotation.XmlElementWrapper; 10 | 11 | /** 12 | * @author ChengNing 13 | * @date 2015年1月6日 14 | */ 15 | public class SendPicsInfo { 16 | private String Count; 17 | private List item; 18 | 19 | @XmlElement(name="Count") 20 | public String getCount() { 21 | return Count; 22 | } 23 | public void setCount(String count) { 24 | Count = count; 25 | } 26 | @XmlElementWrapper(name="PicList") 27 | @XmlElement(name="item") 28 | public List getItem() { 29 | return item; 30 | } 31 | public void setItem(List item) { 32 | this.item = item; 33 | } 34 | 35 | 36 | 37 | 38 | } 39 | -------------------------------------------------------------------------------- /src/org/sword/wechat4j/response/ArticleResponse.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package org.sword.wechat4j.response; 5 | 6 | import javax.xml.bind.annotation.XmlElement; 7 | 8 | /** 9 | * 图文消息体 10 | * @author ChengNing 11 | * @date 2014年12月7日 12 | */ 13 | public class ArticleResponse { 14 | 15 | private String Title; //图文消息标题 16 | private String Description; //图文消息描述 17 | private String PicUrl; //图片链接,支持JPG、PNG格式,较好的效果为大图360*200,小图200*200 18 | private String Url; //点击图文消息跳转链接 19 | 20 | @XmlElement(name="Title") 21 | public String getTitle() { 22 | return Title; 23 | } 24 | public void setTitle(String title) { 25 | Title = title; 26 | } 27 | @XmlElement(name="Description") 28 | public String getDescription() { 29 | return Description; 30 | } 31 | public void setDescription(String description) { 32 | Description = description; 33 | } 34 | @XmlElement(name="PicUrl") 35 | public String getPicUrl() { 36 | return PicUrl; 37 | } 38 | public void setPicUrl(String picUrl) { 39 | PicUrl = picUrl; 40 | } 41 | @XmlElement(name="Url") 42 | public String getUrl() { 43 | return Url; 44 | } 45 | public void setUrl(String url) { 46 | Url = url; 47 | } 48 | 49 | 50 | 51 | } 52 | -------------------------------------------------------------------------------- /src/org/sword/wechat4j/response/ImageResponse.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package org.sword.wechat4j.response; 5 | 6 | import javax.xml.bind.annotation.XmlElement; 7 | 8 | /** 9 | * @author ChengNing 10 | * @date 2014年12月7日 11 | */ 12 | public class ImageResponse { 13 | private String MediaId; 14 | 15 | @XmlElement(name="MediaId") 16 | public String getMediaId() { 17 | return MediaId; 18 | } 19 | 20 | public void setMediaId(String mediaId) { 21 | MediaId = mediaId; 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /src/org/sword/wechat4j/response/MusicResponse.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package org.sword.wechat4j.response; 5 | 6 | import javax.xml.bind.annotation.XmlElement; 7 | 8 | /** 9 | * 音乐消息类型 10 | * @author ChengNing 11 | * @date 2014-12-4 12 | */ 13 | public class MusicResponse { 14 | 15 | private String Title; //音乐标题 16 | private String Description; //音乐描述 17 | private String MusicURL; //音乐链接 18 | private String HQMusicUrl; //高质量音乐链接,WIFI环境优先使用该链接播放音乐 19 | private String ThumbMediaId; //缩略图的媒体id,通过上传多媒体文件,得到的id 20 | 21 | 22 | @XmlElement(name="Title") 23 | public String getTitle() { 24 | return Title; 25 | } 26 | public void setTitle(String title) { 27 | Title = title; 28 | } 29 | @XmlElement(name="Description") 30 | public String getDescription() { 31 | return Description; 32 | } 33 | public void setDescription(String description) { 34 | Description = description; 35 | } 36 | @XmlElement(name="MusicURL") 37 | public String getMusicURL() { 38 | return MusicURL; 39 | } 40 | public void setMusicURL(String musicURL) { 41 | MusicURL = musicURL; 42 | } 43 | @XmlElement(name="HQMusicUrl") 44 | public String getHQMusicUrl() { 45 | return HQMusicUrl; 46 | } 47 | public void setHQMusicUrl(String hQMusicUrl) { 48 | HQMusicUrl = hQMusicUrl; 49 | } 50 | @XmlElement(name="ThumbMediaId") 51 | public String getThumbMediaId() { 52 | return ThumbMediaId; 53 | } 54 | public void setThumbMediaId(String thumbMediaId) { 55 | ThumbMediaId = thumbMediaId; 56 | } 57 | 58 | 59 | } 60 | -------------------------------------------------------------------------------- /src/org/sword/wechat4j/response/TransInfoResponse.java: -------------------------------------------------------------------------------- 1 | package org.sword.wechat4j.response; 2 | 3 | import javax.xml.bind.annotation.XmlElement; 4 | 5 | /** 6 | * 指定客服 7 | * @author Zhangxs 8 | * @version 2015-7-7 9 | */ 10 | 11 | public class TransInfoResponse { 12 | private String KfAccount;//指定会话接入的客服账号 13 | 14 | public TransInfoResponse() { 15 | super(); 16 | } 17 | 18 | public TransInfoResponse(String kfAccount) { 19 | super(); 20 | KfAccount = kfAccount; 21 | } 22 | 23 | @XmlElement(name="KfAccount") 24 | public String getKfAccount() { 25 | return KfAccount; 26 | } 27 | 28 | public void setKfAccount(String kfAccount) { 29 | KfAccount = kfAccount; 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /src/org/sword/wechat4j/response/VideoResponse.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package org.sword.wechat4j.response; 5 | 6 | import javax.xml.bind.annotation.XmlElement; 7 | 8 | /** 9 | * 视频消息 10 | * @author ChengNing 11 | * @date 2014年12月7日 12 | */ 13 | public class VideoResponse { 14 | 15 | private String MediaId; //通过上传多媒体文件,得到的id 16 | private String Title; //视频消息的标题 17 | private String Description; //视频消息的描述 18 | private String ThumbMediaId; 19 | 20 | @XmlElement(name="MediaId") 21 | public String getMediaId() { 22 | return MediaId; 23 | } 24 | public void setMediaId(String mediaId) { 25 | MediaId = mediaId; 26 | } 27 | @XmlElement(name="Title") 28 | public String getTitle() { 29 | return Title; 30 | } 31 | public void setTitle(String title) { 32 | Title = title; 33 | } 34 | @XmlElement(name="Description") 35 | public String getDescription() { 36 | return Description; 37 | } 38 | public void setDescription(String description) { 39 | Description = description; 40 | } 41 | @XmlElement(name="ThumbMediaId") 42 | public String getThumbMediaId() { 43 | return ThumbMediaId; 44 | } 45 | public void setThumbMediaId(String thumbMediaId) { 46 | ThumbMediaId = thumbMediaId; 47 | } 48 | 49 | 50 | 51 | 52 | } 53 | -------------------------------------------------------------------------------- /src/org/sword/wechat4j/response/VoiceResponse.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package org.sword.wechat4j.response; 5 | 6 | import javax.xml.bind.annotation.XmlElement; 7 | 8 | /** 9 | * @author ChengNing 10 | * @date 2014年12月7日 11 | */ 12 | public class VoiceResponse { 13 | 14 | private String MediaId; 15 | 16 | @XmlElement(name="MediaId") 17 | public String getMediaId() { 18 | return MediaId; 19 | } 20 | 21 | public void setMediaId(String mediaId) { 22 | MediaId = mediaId; 23 | } 24 | 25 | 26 | } 27 | -------------------------------------------------------------------------------- /src/org/sword/wechat4j/response/WechatResponse.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package org.sword.wechat4j.response; 5 | 6 | import java.util.List; 7 | 8 | import javax.xml.bind.annotation.XmlElement; 9 | import javax.xml.bind.annotation.XmlElementWrapper; 10 | import javax.xml.bind.annotation.XmlRootElement; 11 | 12 | 13 | /** 14 | * 用于回复的基本消息类型 15 | * @author ChengNing 16 | * @date 2014-12-4 17 | */ 18 | @XmlRootElement(name="xml") 19 | public class WechatResponse { 20 | 21 | private String ToUserName; 22 | private String FromUserName; 23 | private String CreateTime; 24 | private String MsgType; 25 | private String Content; 26 | private String ArticleCount; 27 | 28 | private ImageResponse Image; 29 | private VoiceResponse Voice; 30 | private VideoResponse Video; 31 | private MusicResponse Music; 32 | private List article; 33 | private TransInfoResponse TransInfo; 34 | 35 | 36 | 37 | public static String[] CDATA_TAG = {"ToUserName", 38 | "FromUserName","MsgType","Event","MsgId","Content","MediaId","Title","Description","MusicUrl","HQMusicUrl","ThumbMediaId", 39 | "PicUrl","Url" 40 | }; 41 | 42 | 43 | @XmlElement(name="ToUserName") 44 | public String getToUserName() { 45 | return ToUserName; 46 | } 47 | public void setToUserName(String toUserName) { 48 | ToUserName = toUserName; 49 | } 50 | @XmlElement(name="FromUserName") 51 | public String getFromUserName() { 52 | return FromUserName; 53 | } 54 | public void setFromUserName(String fromUserName) { 55 | FromUserName = fromUserName; 56 | } 57 | @XmlElement(name="CreateTime") 58 | public String getCreateTime() { 59 | return CreateTime; 60 | } 61 | public void setCreateTime(String createTime) { 62 | CreateTime = createTime; 63 | } 64 | @XmlElement(name="MsgType") 65 | public String getMsgType() { 66 | return MsgType; 67 | } 68 | public void setMsgType(String msgType) { 69 | MsgType = msgType; 70 | } 71 | @XmlElement(name="Content") 72 | public String getContent() { 73 | return Content; 74 | } 75 | public void setContent(String content) { 76 | Content = content; 77 | } 78 | @XmlElement(name="ArticleCount") 79 | public String getArticleCount() { 80 | return ArticleCount; 81 | } 82 | public void setArticleCount(String articleCount) { 83 | ArticleCount = articleCount; 84 | } 85 | 86 | @XmlElement(name="Image") 87 | public ImageResponse getImage() { 88 | return Image; 89 | } 90 | public void setImage(ImageResponse image) { 91 | Image = image; 92 | } 93 | @XmlElement(name="Voice") 94 | public VoiceResponse getVoice() { 95 | return Voice; 96 | } 97 | public void setVoice(VoiceResponse voice) { 98 | Voice = voice; 99 | } 100 | @XmlElement(name="Video") 101 | public VideoResponse getVideo() { 102 | return Video; 103 | } 104 | public void setVideo(VideoResponse video) { 105 | Video = video; 106 | } 107 | @XmlElement(name="Music") 108 | public MusicResponse getMusic() { 109 | return Music; 110 | } 111 | public void setMusic(MusicResponse music) { 112 | Music = music; 113 | } 114 | @XmlElementWrapper(name="Articles") 115 | @XmlElement(name="item") 116 | public List getArticle() { 117 | return article; 118 | } 119 | public void setArticle(List article) { 120 | this.article = article; 121 | } 122 | @XmlElement(name="TransInfo") 123 | public TransInfoResponse getTransInfo() { 124 | return TransInfo; 125 | } 126 | public void setTransInfo(TransInfoResponse transInfo) { 127 | TransInfo = transInfo; 128 | } 129 | 130 | 131 | } 132 | -------------------------------------------------------------------------------- /src/org/sword/wechat4j/shop/readme.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sword-org/wechat4j/02e681dceb1b4be2896a3c4858e5b8363a95d861/src/org/sword/wechat4j/shop/readme.md -------------------------------------------------------------------------------- /src/org/sword/wechat4j/token/AccessToken.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package org.sword.wechat4j.token; 5 | 6 | 7 | import org.apache.log4j.Logger; 8 | import org.sword.wechat4j.common.Config; 9 | 10 | 11 | /** 12 | * Access token实体模型 13 | * @author ChengNing 14 | * @date 2014年12月12日 15 | */ 16 | public class AccessToken extends Token { 17 | 18 | private static Logger logger = Logger.getLogger(AccessToken.class); 19 | private static final String ACCESS_TOKEN_URL = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential"; 20 | 21 | 22 | @Override 23 | protected String tokenName() { 24 | return "access_token"; 25 | } 26 | 27 | @Override 28 | protected String expiresInName() { 29 | return "expires_in"; 30 | } 31 | 32 | /** 33 | * 组织accesstoken的请求utl 34 | */ 35 | @Override 36 | protected String accessTokenUrl() { 37 | String appid = Config.instance().getAppid(); 38 | String appsecret = Config.instance().getAppSecret(); 39 | String url = ACCESS_TOKEN_URL + "&appid=" + appid + "&secret=" + appsecret; 40 | logger.info("创建获取access_token url"); 41 | return url; 42 | } 43 | 44 | 45 | } 46 | -------------------------------------------------------------------------------- /src/org/sword/wechat4j/token/Ticket.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package org.sword.wechat4j.token; 5 | 6 | import org.apache.log4j.Logger; 7 | 8 | 9 | /** 10 | * 微信ticket操作类 11 | * ticket和token的逻辑在腾讯是差不多的,所以继承抽象类token 12 | * @author ChengNing 13 | * @date 2015年1月29日 14 | */ 15 | public class Ticket extends Token { 16 | 17 | private static Logger logger = Logger.getLogger(Ticket.class); 18 | 19 | private static final String TICKET_URL = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?"; 20 | private static final String TICKET_NAME = "ticket"; 21 | private static final String EXPIRESIN_NAME = "expires_in"; 22 | 23 | private String type; 24 | 25 | public Ticket(TicketType ticketType){ 26 | super(); 27 | this.type = ticketType.name(); 28 | } 29 | 30 | /* (non-Javadoc) 31 | * @see org.sword.wechat4j.token.Token#accessTokenUrl() 32 | */ 33 | @Override 34 | protected String accessTokenUrl() { 35 | String access_token = TokenProxy.accessToken(); 36 | String url = TICKET_URL + "access_token=" + access_token + "&type=" + this.type; 37 | logger.info("获取ticket,ticket类型" + this.type); 38 | return url; 39 | } 40 | 41 | /* (non-Javadoc) 42 | * @see org.sword.wechat4j.token.Token#tokenName() 43 | */ 44 | @Override 45 | protected String tokenName() { 46 | return TICKET_NAME; 47 | } 48 | 49 | /* (non-Javadoc) 50 | * @see org.sword.wechat4j.token.Token#expiresInName() 51 | */ 52 | @Override 53 | protected String expiresInName() { 54 | return EXPIRESIN_NAME; 55 | } 56 | 57 | 58 | } 59 | -------------------------------------------------------------------------------- /src/org/sword/wechat4j/token/TicketType.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package org.sword.wechat4j.token; 5 | 6 | /** 7 | * @author ChengNing 8 | * @date 2015年1月29日 9 | */ 10 | public enum TicketType { 11 | /** 12 | * jsapi_ticket 13 | */ 14 | jsapi 15 | } 16 | -------------------------------------------------------------------------------- /src/org/sword/wechat4j/token/Token.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package org.sword.wechat4j.token; 5 | 6 | import java.util.Date; 7 | 8 | import org.apache.commons.lang3.StringUtils; 9 | import org.apache.log4j.Logger; 10 | import org.sword.lang.HttpUtils; 11 | 12 | 13 | import com.alibaba.fastjson.JSONObject; 14 | 15 | /** 16 | * @author ChengNing 17 | * @date 2015年1月29日 18 | */ 19 | public abstract class Token { 20 | private static Logger logger = Logger.getLogger(Token.class); 21 | 22 | private String token; //token 23 | private long expires; //token有效时间 24 | 25 | private long tokenTime; //token产生时间 26 | private int redundance = 10*1000; //冗余时间,提前10秒就去请求新的token 27 | 28 | /** 29 | * 得到access token 30 | */ 31 | public String getToken(){ 32 | return this.token; 33 | } 34 | 35 | /** 36 | * 得到有效时间 37 | */ 38 | public long getExpires() { 39 | return expires; 40 | } 41 | 42 | /** 43 | * 请求信的access token 44 | * http请求方式: GET 45 | https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET 46 | {"access_token":"ACCESS_TOKEN","expires_in":7200} 47 | {"errcode":40013,"errmsg":"invalid appid"} 48 | */ 49 | public boolean request(){ 50 | String url = accessTokenUrl(); 51 | String result = HttpUtils.get(url); 52 | if(StringUtils.isBlank(result)) 53 | return false; 54 | if(!parseData(result)){ 55 | return false; 56 | } 57 | logger.info("token获取成功"); 58 | return true; 59 | } 60 | 61 | /** 62 | * 解析token数据 63 | * @param data 64 | * @return 65 | */ 66 | private boolean parseData(String data){ 67 | JSONObject jsonObject = JSONObject.parseObject(data); 68 | String tokenName = tokenName(); 69 | String expiresInName = expiresInName(); 70 | try { 71 | String token = jsonObject.get(tokenName).toString(); 72 | if(StringUtils.isBlank(token)){ 73 | logger.error("token获取失败,获取结果" + data); 74 | return false; 75 | } 76 | this.token = token; 77 | this.tokenTime = (new Date()).getTime(); 78 | String expiresIn = jsonObject.get(expiresInName).toString(); 79 | if(StringUtils.isBlank(expiresIn)){ 80 | logger.error("token获取失败,获取结果" + expiresIn); 81 | return false; 82 | } 83 | else{ 84 | this.expires = Long.valueOf(expiresIn); 85 | } 86 | } catch (Exception e) { 87 | logger.error("token 结果解析失败,token参数名称: " + tokenName 88 | + "有效期参数名称:" + expiresInName 89 | + "token请求结果:" + data); 90 | e.printStackTrace(); 91 | return false; 92 | } 93 | return true; 94 | } 95 | 96 | /** 97 | * token的参数名称 98 | * @return 99 | */ 100 | protected abstract String tokenName(); 101 | /** 102 | * expireIn的参数名称 103 | * @return 104 | */ 105 | protected abstract String expiresInName(); 106 | 107 | /** 108 | * 组织accesstoken的请求utl 109 | * @return 110 | */ 111 | protected abstract String accessTokenUrl(); 112 | 113 | /** 114 | * accessToken 是否有效 115 | * @return true:有效,false: 无效 116 | */ 117 | public boolean isValid(){ 118 | //黑名单判定法 119 | if(StringUtils.isBlank(this.token)) 120 | return false; 121 | if(this.expires <= 0) 122 | return false; 123 | //过期 124 | if(isExpire()) 125 | return false; 126 | return true; 127 | } 128 | 129 | /** 130 | * 是否过期 131 | * @return true 过期 false:有效 132 | */ 133 | private boolean isExpire(){ 134 | Date currentDate = new Date(); 135 | long currentTime = currentDate.getTime(); 136 | long expiresTime = expires * 1000 - redundance; 137 | //判断是否过期 138 | if((tokenTime + expiresTime) > currentTime) 139 | return false; 140 | return true; 141 | } 142 | } 143 | -------------------------------------------------------------------------------- /src/org/sword/wechat4j/token/TokenListener.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package org.sword.wechat4j.token; 5 | 6 | import java.util.Timer; 7 | 8 | import javax.servlet.ServletContextEvent; 9 | import javax.servlet.ServletContextListener; 10 | 11 | import org.apache.log4j.Logger; 12 | import org.sword.wechat4j.token.timer.AccessTokenTimer; 13 | import org.sword.wechat4j.token.timer.JsApiTicketTimer; 14 | 15 | 16 | /** 17 | * Access Token 监听器 18 | * @author ChengNing 19 | * @date 2015年1月8日 20 | */ 21 | public class TokenListener implements ServletContextListener{ 22 | 23 | private static Logger log = Logger.getLogger(TokenListener.class); 24 | 25 | private Timer timer = null; 26 | 27 | @Override 28 | public void contextInitialized(ServletContextEvent arg0) { 29 | log.info("accessToken监听器启动.........."); 30 | timer = new Timer(true); 31 | //注册定时任务 32 | registeAccessTokenTimer(); 33 | //注册jsapi_ticket定时器 34 | registeJsApiTicketTimer(); 35 | } 36 | 37 | @Override 38 | public void contextDestroyed(ServletContextEvent arg0) { 39 | timer.cancel(); 40 | } 41 | 42 | /** 43 | * 注册accessToken定时器 44 | */ 45 | private void registeAccessTokenTimer(){ 46 | AccessTokenTimer accessTokenTimer = new AccessTokenTimer(); 47 | timer.schedule(accessTokenTimer, AccessTokenTimer.DELAY,AccessTokenTimer.PERIOD); 48 | log.info("accessToken定时器注册成功,执行间隔为" + AccessTokenTimer.PERIOD); 49 | } 50 | 51 | /** 52 | * 注册jsapi_ticket定时器 53 | */ 54 | private void registeJsApiTicketTimer(){ 55 | JsApiTicketTimer jsApiTicketTimer = new JsApiTicketTimer(); 56 | timer.schedule(jsApiTicketTimer, JsApiTicketTimer.DELAY,JsApiTicketTimer.PERIOD); 57 | } 58 | 59 | } 60 | -------------------------------------------------------------------------------- /src/org/sword/wechat4j/token/TokenProxy.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package org.sword.wechat4j.token; 5 | 6 | import org.sword.wechat4j.token.server.AccessTokenServer; 7 | import org.sword.wechat4j.token.server.JsApiTicketServer; 8 | import org.sword.wechat4j.token.server.TicketServer; 9 | import org.sword.wechat4j.token.server.TokenServer; 10 | 11 | 12 | /** 13 | * AccessToken代理 14 | * 所有获取accessToken的地方都通过此代理获得 15 | * 获得方法String token = AccessTokenProxy.token() 16 | * @author ChengNing 17 | * @date 2015年1月9日 18 | */ 19 | public class TokenProxy { 20 | 21 | /** 22 | * 通过代理得到accessToken的串 23 | */ 24 | public static String accessToken(){ 25 | TokenServer accessTokenServer = new AccessTokenServer(); 26 | return accessTokenServer.token(); 27 | } 28 | 29 | /** 30 | * 通过代理得到jsapi_ticket 31 | */ 32 | public static String jsApiTicket(){ 33 | TicketServer ticketServer = new JsApiTicketServer(); 34 | return ticketServer.ticket(); 35 | } 36 | 37 | 38 | 39 | 40 | } 41 | -------------------------------------------------------------------------------- /src/org/sword/wechat4j/token/server/AbsServer.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package org.sword.wechat4j.token.server; 5 | 6 | import org.apache.commons.lang3.StringUtils; 7 | import org.apache.log4j.Logger; 8 | 9 | /** 10 | * @author ChengNing 11 | * @date 2015年1月29日 12 | */ 13 | public abstract class AbsServer implements IServer{ 14 | 15 | private static Logger logger = Logger.getLogger(AbsServer.class); 16 | 17 | protected String customerServerClass; 18 | 19 | public AbsServer(){ 20 | this.customerServerClass = getCustomerServerClass(); 21 | } 22 | 23 | @Override 24 | public String token(){ 25 | return server().token(); 26 | } 27 | /** 28 | * 得到系统可用的中控服务器 29 | * @return 正在使用的中控服务器 30 | */ 31 | public IServer server(){ 32 | if(isCustomer()) 33 | return customerServer(); 34 | return defaultServer(); 35 | } 36 | 37 | /** 38 | * 加载自定义中控服务器 39 | * @return 自定义的中控服务器 40 | */ 41 | public IServer customerServer(){ 42 | String className = customerServerClass; 43 | IServer customerServer = null; 44 | try { 45 | Class clazz = Class.forName(className); 46 | customerServer = (IServer)clazz.newInstance(); 47 | } catch (Exception e) { 48 | logger.error("系统找不到" + className); 49 | logger.error("自定义server实例化失败," + e.getMessage()); 50 | e.printStackTrace(); 51 | } 52 | return customerServer; 53 | } 54 | 55 | /** 56 | * 如果配置文件中配置了AccessTokenServer,那么使用客户自定义server 57 | * @return 是否配置了自定义中控服务器 58 | */ 59 | public boolean isCustomer(){ 60 | if(StringUtils.isBlank(customerServerClass)) 61 | return false; 62 | return true; 63 | } 64 | 65 | /** 66 | * 指定的默认中控服务器 67 | * @return 默认的中控服务器 68 | */ 69 | public abstract IServer defaultServer() ; 70 | 71 | /** 72 | * 自定义服务器的类 73 | * @return 74 | */ 75 | protected abstract String getCustomerServerClass(); 76 | } 77 | -------------------------------------------------------------------------------- /src/org/sword/wechat4j/token/server/AccessTokenMemServer.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package org.sword.wechat4j.token.server; 5 | 6 | import org.sword.wechat4j.token.AccessToken; 7 | import org.sword.wechat4j.token.Ticket; 8 | import org.sword.wechat4j.token.TicketType; 9 | 10 | /** 11 | * 内存中控服务器 12 | * access_token 中控服务器 13 | * access_token保存在内存中,过期则自动刷新 14 | * 此中控服务器采用单例模式,提供单一的访问点,并且持有全局唯一的accessToken对象 15 | * 采用这种模式而不是AccessToken提供全局唯一访问是 16 | * 因为AccessToken需要为其他类型的中控服务器提供服务, 17 | * 比如是定时器刷新存数据库或者文件之类的就不需要提供全局唯一 18 | * @author ChengNing 19 | * @date 2015年1月8日 20 | */ 21 | public class AccessTokenMemServer implements IServer{ 22 | 23 | 24 | private static AccessTokenMemServer tokenServer = new AccessTokenMemServer(); 25 | 26 | private AccessToken accessToken = new AccessToken(); 27 | 28 | private int requestTimes = 1;//token请求失败后重新请求的次数 29 | 30 | /** 31 | * 私有构造 32 | */ 33 | private AccessTokenMemServer(){ 34 | //获取新的token 35 | refresh(); 36 | } 37 | 38 | /** 39 | * token中控服务器实例 40 | * @return 中控服务器实例 41 | */ 42 | public static AccessTokenMemServer instance(){ 43 | return tokenServer; 44 | } 45 | 46 | /** 47 | * 通过中控服务器得到token 48 | * @return 49 | */ 50 | private AccessToken accessToken(){ 51 | //没有可用的token,则去刷新 52 | if(!this.accessToken.isValid()){ 53 | refresh(); 54 | } 55 | return this.accessToken; 56 | } 57 | 58 | /** 59 | * 通过中控服务器得到accessToken 60 | * @return 61 | */ 62 | public String token(){ 63 | return accessToken().getToken(); 64 | } 65 | 66 | /** 67 | * 服务器刷新token 68 | */ 69 | private void refresh(){ 70 | for(int i=0;i openid; 14 | 15 | public List getOpenid() { 16 | return openid; 17 | } 18 | 19 | public void setOpenid(List openid) { 20 | this.openid = openid; 21 | } 22 | } -------------------------------------------------------------------------------- /src/org/sword/wechat4j/user/Follwers.java: -------------------------------------------------------------------------------- 1 | package org.sword.wechat4j.user; 2 | 3 | import com.alibaba.fastjson.annotation.JSONField; 4 | 5 | /** 6 | * 关注者集合 7 | * @author Zhangxs 8 | * @version 2015-7-5 9 | */ 10 | public class Follwers { 11 | private int total;// 关注该公众账号的总用户数 12 | private int count;// 拉取的OPENID个数,最大值为10000 13 | private Data data;// 列表数据,OPENID的列表 14 | private String nextOpenid;//拉取列表的后一个用户的OPENID 15 | public int getTotal() { 16 | return total; 17 | } 18 | public void setTotal(int total) { 19 | this.total = total; 20 | } 21 | public int getCount() { 22 | return count; 23 | } 24 | public void setCount(int count) { 25 | this.count = count; 26 | } 27 | public Data getData() { 28 | return data; 29 | } 30 | public void setData(Data data) { 31 | this.data = data; 32 | } 33 | @JSONField(name="next_openid") 34 | public String getNextOpenid() { 35 | return nextOpenid; 36 | } 37 | @JSONField(name="next_openid") 38 | public void setNextOpenid(String nextOpenid) { 39 | this.nextOpenid = nextOpenid; 40 | } 41 | 42 | } 43 | 44 | -------------------------------------------------------------------------------- /src/org/sword/wechat4j/user/Group.java: -------------------------------------------------------------------------------- 1 | package org.sword.wechat4j.user; 2 | /** 3 | * 分组 4 | * @author Zhangxs 5 | * @version 2015-7-5 6 | */ 7 | public class Group { 8 | /**分组id*/ 9 | private Integer id; 10 | /**分组名字*/ 11 | private String name; 12 | /**分组内用户数量*/ 13 | private int count; 14 | public Integer getId() { 15 | return id; 16 | } 17 | public void setId(Integer id) { 18 | this.id = id; 19 | } 20 | public String getName() { 21 | return name; 22 | } 23 | public void setName(String name) { 24 | this.name = name; 25 | } 26 | public int getCount() { 27 | return count; 28 | } 29 | public void setCount(int count) { 30 | this.count = count; 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /src/org/sword/wechat4j/user/LanguageType.java: -------------------------------------------------------------------------------- 1 | package org.sword.wechat4j.user; 2 | /** 3 | * 语言种类 4 | * @author Zhangxs 5 | * @version 2015-7-5 6 | */ 7 | public enum LanguageType { 8 | /** 简体 */ 9 | zh_CN, 10 | /** 繁体 */ 11 | zh_TW, 12 | /** 英语 */ 13 | en; 14 | 15 | } 16 | -------------------------------------------------------------------------------- /src/org/sword/wechat4j/user/Qrcode.java: -------------------------------------------------------------------------------- 1 | package org.sword.wechat4j.user; 2 | 3 | import com.alibaba.fastjson.annotation.JSONField; 4 | import org.sword.lang.HttpUtils; 5 | 6 | import java.io.File; 7 | import java.io.FileOutputStream; 8 | import java.net.URLEncoder; 9 | 10 | /** 11 | * 二维码 12 | * @author Zhangxs 13 | * @version 2015-7-5 14 | */ 15 | public class Qrcode { 16 | //通过ticket换取二维码 17 | private static final String SHOWQRCODE_POST_URL = "https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket="; 18 | private String ticket;// 获取的二维码ticket,凭借此ticket可以在有效时间内换取二维码。 19 | private Integer expireSeconds;// 二维码的有效时间,以秒为单位。最大不超过1800。 20 | private String url;// 二维码图片解析后的地址,开发者可根据该地址自行生成需要的二维码图片 21 | public String getTicket() { 22 | return ticket; 23 | } 24 | public void setTicket(String ticket) { 25 | this.ticket = ticket; 26 | } 27 | @JSONField(name="expire_seconds") 28 | public Integer getExpireSeconds() { 29 | return expireSeconds; 30 | } 31 | @JSONField(name="expire_seconds") 32 | public void setExpireSeconds(Integer expireSeconds) { 33 | this.expireSeconds = expireSeconds; 34 | } 35 | public String getUrl() { 36 | return url; 37 | } 38 | public void setUrl(String url) { 39 | this.url = url; 40 | } 41 | 42 | /** 43 | * 换取二维码 44 | * @param qrcodeFile 二维码存储路径 45 | */ 46 | public void getQrcode(String qrcodeFile){ 47 | try { 48 | byte[] b = HttpUtils.getFile(SHOWQRCODE_POST_URL + URLEncoder.encode(ticket, "UTF-8")); 49 | File file = new File(qrcodeFile); 50 | FileOutputStream fStream = new FileOutputStream(file); 51 | fStream.write(b); 52 | fStream.flush(); 53 | fStream.close(); 54 | } catch (Exception e) { 55 | e.printStackTrace(); 56 | } 57 | } 58 | 59 | /** 60 | * 通过二维码获取二维码URL 61 | * @return 62 | */ 63 | public String getQrcodeUrl(){ 64 | return SHOWQRCODE_POST_URL + ticket; 65 | } 66 | 67 | } 68 | -------------------------------------------------------------------------------- /src/org/sword/wechat4j/user/QrcodeType.java: -------------------------------------------------------------------------------- 1 | package org.sword.wechat4j.user; 2 | /** 3 | * 二维码类型 4 | * @author Zhangxs 5 | * @version 2015-7-5 6 | */ 7 | public enum QrcodeType { 8 | /** 临时二维码 */ 9 | QR_SCENE, 10 | /** 永久二维码 */ 11 | QR_LIMIT_SCENE, 12 | /** 永久的字符串参数值 */ 13 | QR_LIMIT_STR_SCENE; 14 | } 15 | -------------------------------------------------------------------------------- /src/org/sword/wechat4j/user/User.java: -------------------------------------------------------------------------------- 1 | package org.sword.wechat4j.user; 2 | 3 | import com.alibaba.fastjson.annotation.JSONField; 4 | 5 | /** 6 | * 用户实体类 7 | * @author Zhangxs 8 | * @version 2015-7-5 9 | */ 10 | public class User { 11 | private int subscribe;// 用户是否订阅该公众号标识,值为0时,代表此用户没有关注该公众号,拉取不到其余信息。 12 | private String openId;// 用户的标识,对当前公众号唯一 13 | private String nickName;// 用户的昵称 14 | private int sex;// 用户的性别,值为1时是男性,值为2时是女性,值为0时是未知 15 | private String city;// 用户所在城市 16 | private String country;// 用户所在国家 17 | private String province;// 用户所在省份 18 | private LanguageType language;// 用户的语言,简体中文为zh_CN 19 | private String headimgUrl;// 用户头像,最后一个数值代表正方形头像大小(有0、46、64、96、132数值可选,0代表640*640正方形头像),用户没有头像时该项为空。若用户更换头像,原有头像URL将失效。 20 | private String subscribeTime;// 用户关注时间,为时间戳。如果用户曾多次关注,则取最后关注时间 21 | private String unionId;// 只有在用户将公众号绑定到微信开放平台帐号后,才会出现该字段。详见:获取用户个人信息(UnionID机制) 22 | private String remark;// 公众号运营者对粉丝的备注,公众号运营者可在微信公众平台用户管理界面对粉丝添加备注 23 | private int groupId;// 用户所在的分组ID 24 | 25 | /** 26 | * 用户是否订阅该公众号标识 27 | * 值为0时,代表此用户没有关注该公众号,拉取不到其余信息 28 | */ 29 | public int getSubscribe() { 30 | return subscribe; 31 | } 32 | public void setSubscribe(int subscribe) { 33 | this.subscribe = subscribe; 34 | } 35 | /** 36 | * 用户的标识,对当前公众号唯一 37 | */ 38 | @JSONField(name="openid") 39 | public String getOpenId() { 40 | return openId; 41 | } 42 | 43 | @JSONField(name="openid") 44 | public void setOpenId(String openId) { 45 | this.openId = openId; 46 | } 47 | 48 | /** 49 | * 用户的昵称 50 | */ 51 | @JSONField(name="nickname") 52 | public String getNickName() { 53 | return nickName; 54 | } 55 | @JSONField(name="nickname") 56 | public void setNickName(String nickName) { 57 | this.nickName = nickName; 58 | } 59 | /** 60 | * 用户的性别, 61 | * 值为1时是男性, 62 | * 值为2时是女性, 63 | * 值为0时是未知 64 | */ 65 | public int getSex() { 66 | return sex; 67 | } 68 | public void setSex(int sex) { 69 | this.sex = sex; 70 | } 71 | /** 72 | * 用户所在城市 73 | */ 74 | public String getCity() { 75 | return city; 76 | } 77 | public void setCity(String city) { 78 | this.city = city; 79 | } 80 | /** 81 | * 用户所在国家 82 | */ 83 | public String getCountry() { 84 | return country; 85 | } 86 | public void setCountry(String country) { 87 | this.country = country; 88 | } 89 | /** 90 | * 用户所在省份 91 | */ 92 | public String getProvince() { 93 | return province; 94 | } 95 | public void setProvince(String province) { 96 | this.province = province; 97 | } 98 | /** 99 | * 用户的语言 100 | */ 101 | public void setLanguage(LanguageType language) { 102 | this.language = language; 103 | } 104 | public LanguageType getLanguage() { 105 | return language; 106 | } 107 | /** 108 | * 用户头像, 109 | * 最后一个数值代表正方形头像大小(有0、46、64、96、132数值可选,0代表640*640正方形头像), 110 | * 用户没有头像时该项为空。 111 | * 若用户更换头像,原有头像URL将失效。 112 | */ 113 | @JSONField(name="headimgurl") 114 | public String getHeadimgUrl() { 115 | return headimgUrl; 116 | } 117 | @JSONField(name="headimgurl") 118 | public void setHeadimgUrl(String headimgUrl) { 119 | this.headimgUrl = headimgUrl; 120 | } 121 | /** 122 | * 用户关注时间,为时间戳。 123 | * 如果用户曾多次关注,则取最后关注时间 124 | */ 125 | 126 | @JSONField(name="subscribe_time") 127 | public String getSubscribeTime() { 128 | return subscribeTime; 129 | } 130 | @JSONField(name="subscribe_time") 131 | public void setSubscribeTime(String subscribeTime) { 132 | this.subscribeTime = subscribeTime; 133 | } 134 | /** 135 | * 只有在用户将公众号绑定到微信开放平台帐号后,才会出现该字段。 136 | * 详见:获取用户个人信息(UnionID机制) 137 | */ 138 | 139 | @JSONField(name="unionid") 140 | public String getUnionId() { 141 | return unionId; 142 | } 143 | @JSONField(name="unionid") 144 | public void setUnionId(String unionId) { 145 | this.unionId = unionId; 146 | } 147 | /** 148 | * 公众号运营者对粉丝的备注, 149 | * 公众号运营者可在微信公众平台用户管理界面对粉丝添加备注 150 | */ 151 | public String getRemark() { 152 | return remark; 153 | } 154 | public void setRemark(String remark) { 155 | this.remark = remark; 156 | } 157 | /** 158 | * 用户所在的分组ID 159 | */ 160 | @JSONField(name="groupid") 161 | public int getGroupId() { 162 | return groupId; 163 | } 164 | @JSONField(name="groupid") 165 | public void setGroupId(int groupId) { 166 | this.groupId = groupId; 167 | } 168 | 169 | @Override 170 | public String toString() { 171 | return "User [subscribe=" + subscribe + ", openId=" + openId 172 | + ", nickName=" + nickName + ", sex=" + sex + ", city=" + city 173 | + ", country=" + country + ", province=" + province 174 | + ", language=" + language + ", headimgUrl=" + headimgUrl 175 | + ", subscribeTime=" + subscribeTime + ", unionId=" + unionId 176 | + ", remark=" + remark + ", groupId=" + groupId + "]"; 177 | } 178 | 179 | 180 | 181 | } 182 | -------------------------------------------------------------------------------- /src/org/sword/wechat4j/util/RandomStringGenerator.java: -------------------------------------------------------------------------------- 1 | package org.sword.wechat4j.util; 2 | 3 | import java.util.Random; 4 | 5 | /** 6 | * 随机字符串生成器 7 | */ 8 | public class RandomStringGenerator { 9 | 10 | private static final int defaultLength = 32; 11 | private static final String CHARACTERS = "abcdefghijklmnopqrstuvwxyz0123456789"; 12 | 13 | /** 14 | * 获取一定长度的随机字符串 15 | * 16 | * @param length 指定字符串长度 17 | * @return 一定长度的字符串 18 | */ 19 | public static String generate(int length) { 20 | Random random = new Random(); 21 | StringBuffer sb = new StringBuffer(); 22 | for (int i = 0; i < length; i++) { 23 | int number = random.nextInt(CHARACTERS.length()); 24 | sb.append(CHARACTERS.charAt(number)); 25 | } 26 | return sb.toString(); 27 | } 28 | 29 | /** 30 | * 获取默认长度的随机字符串 31 | * 32 | * @return 默认长度的字符串 33 | */ 34 | public static String generate() { 35 | return generate(defaultLength); 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /src/org/sword/wechat4j/util/WeChatUtil.java: -------------------------------------------------------------------------------- 1 | package org.sword.wechat4j.util; 2 | 3 | import org.sword.wechat4j.exception.WeChatException; 4 | import org.sword.wechat4j.exception.WeChatReturnCode; 5 | 6 | import com.alibaba.fastjson.JSONObject; 7 | /** 8 | * 工具类 9 | * @author Zhangxs 10 | * @version 2015-7-4 11 | */ 12 | public class WeChatUtil { 13 | /** 14 | * 判断是否请求成功 15 | * @param resultStr 16 | * @throws WeChatException 17 | */ 18 | public static void isSuccess(String resultStr) throws WeChatException{ 19 | JSONObject jsonObject = JSONObject.parseObject(resultStr); 20 | Integer errCode =jsonObject.getIntValue("errcode"); 21 | if (errCode!=null && errCode!=0) { 22 | String errMsg = WeChatReturnCode.getMsg(errCode); 23 | if (errMsg.equals("")) { 24 | errMsg = jsonObject.getString("errmsg"); 25 | } 26 | throw new WeChatException("异常码:"+errCode+";异常说明:"+errMsg); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/wechat4j.properties.sample: -------------------------------------------------------------------------------- 1 | 2 | #you server url 3 | wechat.url= 4 | #you wechat token 5 | wechat.token=token 6 | #message secret key,if don't set then message is cleartext 7 | wechat.encodingaeskey= 8 | 9 | #wechat appid 10 | wechat.appid=appid 11 | #wechat app secret 12 | wechat.appsecret=appsecret 13 | 14 | #wechat mch id 15 | wechat.mch.id= 16 | #wechat mch api secret key, must be 32 length 17 | wechat.mch.key= 18 | 19 | #wechat access token server ,when you save in db,must implement you server class 20 | #this class must extend org.sword.wechat4j.token.server.CustomerServer 21 | #if no this property,then token server is default memery accesstoken server 22 | wechat.accessToken.server.class= 23 | 24 | #jsapi_ticket customer server class name, 25 | #this class must extend org.sword.wechat4j.token.server.CustomerServer 26 | #if no this property,then ticket server is default memery ticket server 27 | wechat.ticket.jsapi.server.class= -------------------------------------------------------------------------------- /test/log4j.properties: -------------------------------------------------------------------------------- 1 | # Root logger option 2 | log4j.rootLogger=INFO, file, stdout 3 | 4 | # Direct log messages to a log file 5 | log4j.appender.file=org.apache.log4j.RollingFileAppender 6 | log4j.appender.file.File=D:\\ims.log 7 | log4j.appender.file.MaxFileSize=10MB 8 | log4j.appender.file.MaxBackupIndex=10 9 | log4j.appender.file.layout=org.apache.log4j.PatternLayout 10 | log4j.appender.file.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n 11 | 12 | # Direct log messages to stdout 13 | log4j.appender.stdout=org.apache.log4j.ConsoleAppender 14 | log4j.appender.stdout.Target=System.out 15 | log4j.appender.stdout.layout=org.apache.log4j.PatternLayout 16 | log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n -------------------------------------------------------------------------------- /test/org/sword/wechat4j/SendMsgTest.java: -------------------------------------------------------------------------------- 1 | package org.sword.wechat4j; 2 | 3 | import static org.junit.Assert.*; 4 | 5 | import org.junit.Test; 6 | import org.sword.wechat4j.message.CustomerMsg; 7 | 8 | import com.alibaba.fastjson.JSONObject; 9 | 10 | 11 | 12 | public class SendMsgTest { 13 | CustomerMsg senMsg = new CustomerMsg(""); 14 | 15 | @Test 16 | public void testSendText() { 17 | // String expected = "Hello World"; 18 | // senMsg.sendText(expected); 19 | //// String actual = senMsg.getMsgBody(); 20 | // JSONObject json = JSONObject.parseObject(actual); 21 | // actual = json.getJSONObject("text").getString("content"); 22 | // 23 | // assertEquals(expected, actual); 24 | } 25 | 26 | // @Test 27 | // public void testSendImage() { 28 | // fail("Not yet implemented"); 29 | // } 30 | // 31 | // @Test 32 | // public void testSendVoice() { 33 | // fail("Not yet implemented"); 34 | // } 35 | // 36 | // @Test 37 | // public void testSendVideoStringStringStringString() { 38 | // fail("Not yet implemented"); 39 | // } 40 | // 41 | // @Test 42 | // public void testSendVideoVideoResponse() { 43 | // fail("Not yet implemented"); 44 | // } 45 | // 46 | // @Test 47 | // public void testSendMusicStringStringStringStringString() { 48 | // fail("Not yet implemented"); 49 | // } 50 | // 51 | // @Test 52 | // public void testSendMusicMusicResponse() { 53 | // fail("Not yet implemented"); 54 | // } 55 | 56 | @Test 57 | public void testsendNew() { 58 | // String expected = "Hello World"; 59 | // senMsg.sendNew("title", expected, "picUrl", "picUrl"); 60 | // String actual = senMsg.getMsgBody(); 61 | // JSONObject json = JSONObject.parseObject(actual); 62 | // actual = json.getJSONObject("news").getJSONArray("articles").getJSONObject(0).getString("description"); 63 | // 64 | // assertEquals(expected, actual); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /test/org/sword/wechat4j/Wechat.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package org.sword.wechat4j; 5 | 6 | import javax.servlet.http.HttpServletRequest; 7 | 8 | /** 9 | * @author ChengNing 10 | * @date 2014年12月7日 11 | */ 12 | public class Wechat extends WechatSupport{ 13 | 14 | public Wechat(HttpServletRequest request) { 15 | super(request); 16 | } 17 | 18 | @Override 19 | protected void onText() { 20 | // TODO Auto-generated method stub 21 | 22 | } 23 | 24 | @Override 25 | protected void onImage() { 26 | // TODO Auto-generated method stub 27 | 28 | } 29 | 30 | @Override 31 | protected void onVoice() { 32 | // TODO Auto-generated method stub 33 | 34 | } 35 | 36 | @Override 37 | protected void onVideo() { 38 | // TODO Auto-generated method stub 39 | 40 | } 41 | 42 | @Override 43 | protected void onLocation() { 44 | // TODO Auto-generated method stub 45 | 46 | } 47 | 48 | @Override 49 | protected void onLink() { 50 | // TODO Auto-generated method stub 51 | 52 | } 53 | 54 | @Override 55 | protected void onUnknown() { 56 | // TODO Auto-generated method stub 57 | 58 | } 59 | 60 | @Override 61 | protected void click() { 62 | // TODO Auto-generated method stub 63 | 64 | } 65 | 66 | @Override 67 | protected void subscribe() { 68 | // TODO Auto-generated method stub 69 | 70 | } 71 | 72 | @Override 73 | protected void unSubscribe() { 74 | // TODO Auto-generated method stub 75 | 76 | } 77 | 78 | @Override 79 | protected void scan() { 80 | // TODO Auto-generated method stub 81 | 82 | } 83 | 84 | @Override 85 | protected void location() { 86 | // TODO Auto-generated method stub 87 | 88 | } 89 | 90 | @Override 91 | protected void view() { 92 | // TODO Auto-generated method stub 93 | 94 | } 95 | 96 | @Override 97 | protected void templateMsgCallback() { 98 | // TODO Auto-generated method stub 99 | 100 | } 101 | 102 | @Override 103 | protected void scanCodePush() { 104 | // TODO Auto-generated method stub 105 | 106 | } 107 | 108 | @Override 109 | protected void scanCodeWaitMsg() { 110 | // TODO Auto-generated method stub 111 | 112 | } 113 | 114 | @Override 115 | protected void picSysPhoto() { 116 | // TODO Auto-generated method stub 117 | 118 | } 119 | 120 | @Override 121 | protected void picPhotoOrAlbum() { 122 | // TODO Auto-generated method stub 123 | 124 | } 125 | 126 | @Override 127 | protected void picWeixin() { 128 | // TODO Auto-generated method stub 129 | 130 | } 131 | 132 | @Override 133 | protected void locationSelect() { 134 | // TODO Auto-generated method stub 135 | 136 | } 137 | 138 | @Override 139 | protected void onShortVideo() { 140 | // TODO Auto-generated method stub 141 | 142 | } 143 | 144 | @Override 145 | protected void kfCreateSession() { 146 | // TODO Auto-generated method stub 147 | 148 | } 149 | 150 | @Override 151 | protected void kfCloseSession() { 152 | // TODO Auto-generated method stub 153 | 154 | } 155 | 156 | @Override 157 | protected void kfSwitchSession() { 158 | // TODO Auto-generated method stub 159 | 160 | } 161 | 162 | 163 | } 164 | -------------------------------------------------------------------------------- /test/org/sword/wechat4j/WechatSupportTest.java: -------------------------------------------------------------------------------- 1 | package org.sword.wechat4j; 2 | 3 | import static org.junit.Assert.*; 4 | 5 | import org.junit.Test; 6 | 7 | public class WechatSupportTest { 8 | 9 | @Test 10 | public void test() { 11 | 12 | } 13 | 14 | } 15 | -------------------------------------------------------------------------------- /test/org/sword/wechat4j/WechatTest.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package org.sword.wechat4j; 5 | 6 | 7 | 8 | import org.junit.After; 9 | import org.junit.Before; 10 | import org.junit.Test; 11 | 12 | 13 | /** 14 | * @author ChengNing 15 | * @date 2014年12月7日 16 | */ 17 | public class WechatTest { 18 | 19 | private String url = "http://localhost:8080/phdc/lejian?signature=de8de4d90ab29dc1edca1d80863115e5385e25aa×tamp=1418008326&nonce=1917848460"; 20 | 21 | 22 | /** 23 | * @throws java.lang.Exception 24 | */ 25 | @Before 26 | public void setUp() throws Exception { 27 | } 28 | 29 | /** 30 | * @throws java.lang.Exception 31 | */ 32 | @After 33 | public void tearDown() throws Exception { 34 | } 35 | 36 | @Test 37 | public void textTest() { 38 | // HttpClient client = new HttpClient(); 39 | // PostMethod post = new PostMethod(url); 40 | // post.setRequestBody("1418007611"); 41 | // 42 | // String expected = "test ok"; 43 | // String actual = ""; 44 | // try { 45 | // client.executeMethod(post); 46 | // actual = post.getResponseBodyAsString(); 47 | // } catch (Exception e) { 48 | // e.printStackTrace(); 49 | // } 50 | // Assert.assertEquals(expected, actual); 51 | } 52 | 53 | @Test 54 | public void linkTest(){ 55 | // HttpClient client = new HttpClient(); 56 | // PostMethod post = new PostMethod(url); 57 | // post.setRequestBody("<![CDATA[test ok]]>12345678901234561418007611"); 58 | // 59 | // String expected = "test ok"; 60 | // String actual = ""; 61 | // try { 62 | // client.executeMethod(post); 63 | // actual = post.getResponseBodyAsString(); 64 | // } catch (Exception e) { 65 | // e.printStackTrace(); 66 | // } 67 | // Assert.assertEquals(expected, actual); 68 | } 69 | 70 | @Test 71 | public void clickTest(){ 72 | 73 | } 74 | 75 | 76 | } 77 | -------------------------------------------------------------------------------- /test/org/sword/wechat4j/WechatTestSuite.java: -------------------------------------------------------------------------------- 1 | package org.sword.wechat4j; 2 | 3 | import org.junit.runner.RunWith; 4 | import org.junit.runners.Suite; 5 | import org.junit.runners.Suite.SuiteClasses; 6 | 7 | @RunWith(Suite.class) 8 | @SuiteClasses({}) 9 | public class WechatTestSuite { 10 | 11 | } 12 | -------------------------------------------------------------------------------- /test/org/sword/wechat4j/common/ConfigTest.java: -------------------------------------------------------------------------------- 1 | package org.sword.wechat4j.common; 2 | 3 | import static org.junit.Assert.*; 4 | 5 | import org.junit.Test; 6 | 7 | public class ConfigTest { 8 | 9 | @Test 10 | public void testInstance() { 11 | Config c = Config.instance(); 12 | String appid = c.getAppid(); 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /test/org/sword/wechat4j/common/MediaFileTest.java: -------------------------------------------------------------------------------- 1 | package org.sword.wechat4j.common; 2 | 3 | import static org.junit.Assert.*; 4 | 5 | import java.io.File; 6 | import java.io.FileOutputStream; 7 | 8 | import org.apache.log4j.Logger; 9 | import org.junit.Test; 10 | 11 | public class MediaFileTest { 12 | 13 | private static Logger logger = Logger.getLogger(MediaFileTest.class); 14 | private String uploadFile = MediaFileTest.class.getResource("").getPath() + "weixin.jpg"; 15 | private String downFile = MediaFileTest.class.getResource("").getPath() + "weixin_down.jpg"; 16 | private String mediaId; 17 | 18 | /** 19 | * 多媒体文件上传 20 | */ 21 | public void testUpload() { 22 | MediaFile mediaFile = new MediaFile(); 23 | 24 | File file = new File(uploadFile); 25 | String result = mediaFile.upload(file,MediaType.image); 26 | this.mediaId = result; 27 | 28 | assertTrue(result != null); 29 | logger.info("mediaFile upload result: " + result); 30 | } 31 | 32 | /** 33 | * 多媒体文件下载 34 | * @return 35 | */ 36 | public byte[] testDownload() { 37 | MediaFile mediaFile = new MediaFile(); 38 | byte[] b = mediaFile.download(mediaId); 39 | 40 | assertTrue(b != null); 41 | return b; 42 | } 43 | 44 | /** 45 | * 多媒体文件上传下载测试套件 46 | */ 47 | @Test 48 | public void testSuite(){ 49 | //上传得到mediaId 50 | testUpload(); 51 | //根据mediaId下载刚才上传的文件 52 | byte[] b = testDownload(); 53 | 54 | //下载的文件另存为 55 | File file = new File(downFile); 56 | FileOutputStream fStream = null; 57 | try { 58 | fStream = new FileOutputStream(file); 59 | fStream.write(b); 60 | fStream.flush(); 61 | } catch (Exception e) { 62 | e.printStackTrace(); 63 | } 64 | logger.info("文件下载成功,请去查看,路径" + downFile ); 65 | } 66 | 67 | } 68 | -------------------------------------------------------------------------------- /test/org/sword/wechat4j/common/weixin.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sword-org/wechat4j/02e681dceb1b4be2896a3c4858e5b8363a95d861/test/org/sword/wechat4j/common/weixin.jpg -------------------------------------------------------------------------------- /test/org/sword/wechat4j/common/weixin_down.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sword-org/wechat4j/02e681dceb1b4be2896a3c4858e5b8363a95d861/test/org/sword/wechat4j/common/weixin_down.jpg -------------------------------------------------------------------------------- /test/org/sword/wechat4j/jsapi/JsapiTest.java: -------------------------------------------------------------------------------- 1 | package org.sword.wechat4j.jsapi; 2 | 3 | import org.junit.Test; 4 | 5 | /** 6 | * Created by xuwen on 2015-12-13. 7 | */ 8 | public class JsapiTest { 9 | 10 | @Test 11 | public void testSign() { 12 | JsApiParam param = JsApiManager.signature("http://uncoseason.xicp.net/"); 13 | System.out.println(param); 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /test/org/sword/wechat4j/menu/MenuTest.java: -------------------------------------------------------------------------------- 1 | package org.sword.wechat4j.menu; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | import org.junit.Before; 7 | import org.junit.Test; 8 | import org.sword.wechat4j.event.EventType; 9 | import org.sword.wechat4j.exception.WeChatException; 10 | /** 11 | * 微信自定义菜单接口测试 12 | * @author Zhangxs 13 | * @version 2015-7-4 14 | */ 15 | public class MenuTest { 16 | private MenuManager manager; 17 | @Before 18 | public void init(){ 19 | manager = new MenuManager(); 20 | } 21 | /** 22 | * 创建菜单 23 | */ 24 | @Test 25 | public void createMenu(){ 26 | //单击按钮 27 | MenuButton btnClick= new MenuButton(); 28 | btnClick.setName("单击按钮"); 29 | btnClick.setType(EventType.click); 30 | btnClick.setKey("单击按钮"); 31 | //跳转URL 32 | MenuButton btnView= new MenuButton(); 33 | btnView.setName("跳转URL"); 34 | btnView.setType(EventType.view); 35 | btnView.setUrl("http://www.baidu.com"); 36 | //扫码推事件 37 | MenuButton btnScanCodePush= new MenuButton(); 38 | btnScanCodePush.setName("扫码推事件"); 39 | btnScanCodePush.setType(EventType.scancode_push); 40 | btnScanCodePush.setKey("扫码推事件"); 41 | //扫码带提示 42 | MenuButton btnScanCodeWaitMsg= new MenuButton(); 43 | btnScanCodeWaitMsg.setName("扫码带提示"); 44 | btnScanCodeWaitMsg.setType(EventType.scancode_waitmsg); 45 | btnScanCodeWaitMsg.setKey("扫码带提示"); 46 | 47 | //弹出系统拍照发图 48 | MenuButton btnPicSysPhoto= new MenuButton(); 49 | btnPicSysPhoto.setName("拍照发图"); 50 | btnPicSysPhoto.setType(EventType.pic_sysphoto); 51 | btnPicSysPhoto.setKey("拍照发图"); 52 | //弹出拍照或者相册发图 53 | MenuButton btnPicPhotoOrAlbum= new MenuButton(); 54 | btnPicPhotoOrAlbum.setName("拍照/相册发图"); 55 | btnPicPhotoOrAlbum.setType(EventType.pic_photo_or_album); 56 | btnPicPhotoOrAlbum.setKey("拍照/相册发图"); 57 | //弹出微信相册发图器 58 | MenuButton btnPicWeixin= new MenuButton(); 59 | btnPicWeixin.setName("相册发图"); 60 | btnPicWeixin.setType(EventType.pic_weixin); 61 | btnPicWeixin.setKey("相册发图"); 62 | //弹出地理位置选择器 63 | MenuButton btnLocationSelect= new MenuButton(); 64 | btnLocationSelect.setName("地理位置"); 65 | btnLocationSelect.setType(EventType.location_select); 66 | btnLocationSelect.setKey("地理位置"); 67 | 68 | //下发消息(除文本消息) 69 | btnLocationSelect.setType(EventType.location_select); 70 | MenuButton btnMediaId = new MenuButton(); 71 | btnMediaId.setName(""); 72 | btnMediaId.setType(EventType.media_id); 73 | btnMediaId.setMediaId(""); 74 | //跳转图文消息URL 75 | MenuButton btnViewLimited = new MenuButton(); 76 | btnViewLimited.setName(""); 77 | btnViewLimited.setType(EventType.view_limited); 78 | btnViewLimited.setMediaId(""); 79 | 80 | List subBut1 = new ArrayList(); 81 | subBut1.add(btnScanCodePush); 82 | subBut1.add(btnScanCodeWaitMsg); 83 | subBut1.add(btnPicSysPhoto); 84 | subBut1.add(btnPicPhotoOrAlbum); 85 | subBut1.add(btnPicWeixin); 86 | List subBut2 = new ArrayList(); 87 | subBut2.add(btnClick); 88 | subBut2.add(btnView); 89 | //二级菜单 90 | MenuButton subButScanCode = new MenuButton(); 91 | subButScanCode.setName("扫码"); 92 | subButScanCode.setSubButton(subBut1); 93 | MenuButton sub1 = new MenuButton(); 94 | sub1.setName("单击"); 95 | sub1.setSubButton(subBut2); 96 | 97 | List button = new ArrayList(); 98 | button.add(sub1); 99 | button.add(subButScanCode); 100 | button.add(btnLocationSelect); 101 | Menu menu = new Menu(); 102 | menu.setButton(button); 103 | 104 | try { 105 | manager.create(menu); 106 | System.out.println("菜单创建成功"); 107 | } catch (WeChatException e) { 108 | System.out.println("菜单创建失败"); 109 | e.printStackTrace(); 110 | } 111 | } 112 | /** 113 | * 查询菜单 114 | */ 115 | @Test 116 | public void getMenu(){ 117 | Menu menu = manager.getMenu(); 118 | System.out.println(menu.getButton().size()); 119 | } 120 | /** 121 | * 删除菜单 122 | */ 123 | @Test 124 | public void delete(){ 125 | try { 126 | manager.delete(); 127 | System.out.println("菜单删除成功"); 128 | } catch (WeChatException e) { 129 | System.out.println("菜单删除失败"); 130 | e.printStackTrace(); 131 | } 132 | } 133 | } 134 | -------------------------------------------------------------------------------- /test/org/sword/wechat4j/oauth/OAuthTest.java: -------------------------------------------------------------------------------- 1 | package org.sword.wechat4j.oauth; 2 | 3 | import org.junit.Test; 4 | import org.sword.wechat4j.oauth.protocol.get_access_token.GetAccessTokenRequest; 5 | import org.sword.wechat4j.oauth.protocol.get_access_token.GetAccessTokenResponse; 6 | import org.sword.wechat4j.oauth.protocol.get_userinfo.GetUserinfoRequest; 7 | import org.sword.wechat4j.oauth.protocol.get_userinfo.GetUserinfoResponse; 8 | import org.sword.wechat4j.oauth.protocol.refresh_access_token.RefreshAccessTokenRequest; 9 | import org.sword.wechat4j.oauth.protocol.refresh_access_token.RefreshAccessTokenResponse; 10 | import org.sword.wechat4j.oauth.protocol.valid_access_token.ValidAccessTokenRequest; 11 | import org.sword.wechat4j.oauth.protocol.valid_access_token.ValidAccessTokenResponse; 12 | 13 | /** 14 | * Created by xuwen on 2015-12-13. 15 | */ 16 | public class OAuthTest { 17 | 18 | @Test 19 | public void testGenerateRedirectURI(){ 20 | System.out.println(OAuthManager.generateRedirectURI("http://uncoseason.xicp.net/", "snsapi_userinfo", "test info")); 21 | } 22 | 23 | // @Test 24 | public void testOAuth() throws OAuthException { 25 | // 这个用例需要重定向URI带回的code参数 26 | String code = "重定向URI带回的code参数"; 27 | GetAccessTokenResponse getAccessTokenResponse = OAuthManager.getAccessToken(new GetAccessTokenRequest(code)); 28 | System.out.println(getAccessTokenResponse); 29 | GetUserinfoResponse getUserinfoResponse = OAuthManager.getUserinfo(new GetUserinfoRequest(getAccessTokenResponse.getAccess_token(),getAccessTokenResponse.getOpenid())); 30 | System.out.println(getUserinfoResponse); 31 | ValidAccessTokenResponse validAccessTokenResponse = OAuthManager.validAccessToken(new ValidAccessTokenRequest(getAccessTokenResponse.getAccess_token(),getAccessTokenResponse.getOpenid())); 32 | System.out.println(validAccessTokenResponse); 33 | RefreshAccessTokenResponse refreshAccessTokenResponse = OAuthManager.refreshAccessToken(new RefreshAccessTokenRequest(getAccessTokenResponse.getRefresh_token())); 34 | System.out.println(refreshAccessTokenResponse); 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /test/org/sword/wechat4j/token/AccessTokenServerTest.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package org.sword.wechat4j.token; 5 | 6 | import org.apache.log4j.Logger; 7 | import org.junit.Test; 8 | import org.sword.lang.HttpUtils; 9 | import org.sword.wechat4j.token.server.AccessTokenServer; 10 | 11 | /** 12 | * @author ChengNing 13 | * @date 2015年1月30日 14 | */ 15 | public class AccessTokenServerTest { 16 | 17 | private static Logger logger = Logger.getLogger(AccessTokenServerTest.class); 18 | @Test 19 | public void test(){ 20 | AccessTokenServer accessTokenServer = new AccessTokenServer(); 21 | accessTokenServer.defaultServer(); 22 | } 23 | 24 | @Test 25 | public void testGet(){ 26 | try { 27 | String result = HttpUtils.get("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=wx925a77489e94a7e6&secret=d29ae7a0b55d2f8570107d90985034dc"); 28 | logger.info(result); 29 | } catch (Exception e) { 30 | // TODO: handle exception 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /test/org/sword/wechat4j/token/AccessTokenTest.java: -------------------------------------------------------------------------------- 1 | package org.sword.wechat4j.token; 2 | 3 | 4 | import org.junit.Test; 5 | 6 | public class AccessTokenTest { 7 | 8 | @Test 9 | public void testRequest() { 10 | AccessToken accessToken = new AccessToken(); 11 | accessToken.request(); 12 | String result = accessToken.getToken(); 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /test/org/sword/wechat4j/token/TicketTest.java: -------------------------------------------------------------------------------- 1 | package org.sword.wechat4j.token; 2 | 3 | import org.junit.Test; 4 | 5 | public class TicketTest { 6 | 7 | @Test 8 | public void test(){ 9 | String jsapiTicket = TokenProxy.jsApiTicket(); 10 | String expi = ""; 11 | System.out.println(jsapiTicket); 12 | } 13 | 14 | } 15 | -------------------------------------------------------------------------------- /test/org/sword/wechat4j/token/TokenProxyTest.java: -------------------------------------------------------------------------------- 1 | package org.sword.wechat4j.token; 2 | 3 | import static org.junit.Assert.*; 4 | 5 | import org.junit.After; 6 | import org.junit.Before; 7 | import org.junit.Test; 8 | 9 | public class TokenProxyTest { 10 | 11 | @Before 12 | public void setUp() throws Exception { 13 | } 14 | 15 | @After 16 | public void tearDown() throws Exception { 17 | } 18 | 19 | 20 | // @Test 21 | // public void tokenTest(){ 22 | // String accessToken = TokenProxy.accessToken(); 23 | // System.out.println(accessToken); 24 | // 25 | // } 26 | 27 | @Test 28 | public void jsApiTicketTest(){ 29 | String jsApiTicket = TokenProxy.jsApiTicket(); 30 | System.out.println(jsApiTicket); 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /test/org/sword/wechat4j/user/AccountTest.java: -------------------------------------------------------------------------------- 1 | package org.sword.wechat4j.user; 2 | 3 | import org.junit.Before; 4 | import org.junit.Test; 5 | /** 6 | * 账号管理接口测试 7 | * @author Zhangxs 8 | * @version 2015-7-5 9 | */ 10 | public class AccountTest { 11 | private AccountManager accountManager; 12 | @Before 13 | public void init(){ 14 | accountManager = new AccountManager(); 15 | } 16 | /** 17 | * 创建临时二维码 18 | */ 19 | @Test 20 | public void createQrcodeTemporary(){ 21 | long sceneId =100; 22 | int expireSeconds = 1860; 23 | Qrcode qrcode= accountManager.createQrcodeTemporary(sceneId, expireSeconds); 24 | System.out.println("二维码有效时间:"+qrcode.getExpireSeconds()); 25 | System.out.println("二维码Ticket:"+qrcode.getTicket()); 26 | System.out.println("二维码图片解析后的地址:"+qrcode.getUrl()); 27 | } 28 | /** 29 | * 创建永久二维码 30 | */ 31 | @Test 32 | public void createQrcodePerpetualstr(){ 33 | String sceneStr = "wtb"; 34 | Qrcode qrcode = accountManager.createQrcodePerpetualstr(sceneStr); 35 | System.out.println("二维码Ticket:"+qrcode.getTicket()); 36 | System.out.println("二维码图片解析后的地址:"+qrcode.getUrl()); 37 | } 38 | /** 39 | * 创建永久二维码 40 | */ 41 | @Test 42 | public void createQrcodePerpetual(){ 43 | int sceneId = 123; 44 | Qrcode qrcode = accountManager.createQrcodePerpetual(sceneId); 45 | System.out.println("二维码Ticket:"+qrcode.getTicket()); 46 | System.out.println("二维码图片解析后的地址:"+qrcode.getUrl()); 47 | 48 | } 49 | /** 50 | * 长链接转短链接接口 51 | */ 52 | @Test 53 | public void shortUrl(){ 54 | String longUrl="https://github.com/Zhangys-hh/wechat4j"; 55 | String shortUrl = accountManager.shortUrl(longUrl); 56 | System.out.println("转换后的Url:"+shortUrl); 57 | } 58 | /** 59 | * 获取二维码图片 60 | */ 61 | @Test 62 | public void getQrcode(){ 63 | String qrcodeFile="/tmp/qrcode.png"; 64 | long sceneId =100; 65 | int expireSeconds = 1860; 66 | Qrcode qrcode= accountManager.createQrcodeTemporary(sceneId, expireSeconds); 67 | qrcode.getQrcode(qrcodeFile); 68 | } 69 | 70 | } 71 | -------------------------------------------------------------------------------- /test/org/sword/wechat4j/user/UserTest.java: -------------------------------------------------------------------------------- 1 | package org.sword.wechat4j.user; 2 | 3 | 4 | import java.util.List; 5 | 6 | import org.junit.Before; 7 | import org.junit.Test; 8 | import org.sword.wechat4j.exception.WeChatException; 9 | 10 | public class UserTest { 11 | private UserManager manager; 12 | @Before 13 | public void init(){ 14 | manager = new UserManager(); 15 | } 16 | /** 17 | * 获取所有的关注者列表 18 | */ 19 | @Test 20 | public void allSubscriber(){ 21 | List openids = manager.allSubscriber(); 22 | for (String openid : openids) { 23 | System.out.println(openid); 24 | } 25 | } 26 | /** 27 | * 获取前10000个关注者列表 28 | */ 29 | @Test 30 | public void subscriberList(){ 31 | Follwers follwers = manager.subscriberList(); 32 | System.out.println("关注者数量:"+follwers.getCount()); 33 | } 34 | /** 35 | * 设置用户备注名 36 | */ 37 | @Test 38 | public void updateRemark(){ 39 | try { 40 | manager.updateRemark("otweTt8vRASrS-zji8v4YSStH-cc", "张永帅"); 41 | System.out.println("备注名设置成功"); 42 | } catch (WeChatException e) { 43 | System.out.println("备注名设置失败"); 44 | e.printStackTrace(); 45 | } 46 | } 47 | /** 48 | * 获取用户基本信息 49 | */ 50 | @Test 51 | public void getUserInfo(){ 52 | String openId = "otweTt8vRASrS-zji8v4YSStH-cc"; 53 | User user = manager.getUserInfo(openId); 54 | System.out.println(user.toString()); 55 | user = manager.getUserInfo(openId,LanguageType.en); 56 | System.out.println(user.toString()); 57 | } 58 | /** 59 | * 创建分组 60 | */ 61 | @Test 62 | public void createGroup(){ 63 | try { 64 | manager.createGroup("分组1"); 65 | System.out.println("创建分组成功"); 66 | } catch (WeChatException e) { 67 | System.out.println("创建分组失败"); 68 | e.printStackTrace(); 69 | } 70 | 71 | } 72 | /** 73 | * 查询所有分组 74 | */ 75 | @Test 76 | public void getGroup(){ 77 | List groups = manager.getGroup(); 78 | for (Group group : groups) { 79 | System.out.println("分组Id:"+group.getId()); 80 | System.out.println("分组名称:"+group.getName()); 81 | System.out.println("分组人数:"+group.getCount()); 82 | } 83 | } 84 | /** 85 | * 查询用户所在分组 86 | */ 87 | @Test 88 | public void getIdGroup(){ 89 | String openId ="otweTt8vRASrS-zji8v4YSStH-cc"; 90 | int groupId = manager.getIdGroup(openId); 91 | System.out.println("分组Id:"+groupId); 92 | } 93 | /** 94 | * 修改分组名 95 | */ 96 | @Test 97 | public void updateGroup(){ 98 | int groupId=106; 99 | String name = "分组4"; 100 | try { 101 | manager.updateGroup(groupId, name); 102 | System.out.println("操作成功"); 103 | } catch (WeChatException e) { 104 | System.out.println("操作失败"); 105 | e.printStackTrace(); 106 | } 107 | } 108 | /** 109 | * 移动用户分组 110 | */ 111 | @Test 112 | public void membersUpdateGroup(){ 113 | int groupId = 106; 114 | String openId="otweTt8vRASrS-zji8v4YSStH-cc"; 115 | try { 116 | manager.membersUpdateGroup(openId, groupId); 117 | System.out.println("操作成功"); 118 | } catch (WeChatException e) { 119 | System.out.println("操作失败"); 120 | e.printStackTrace(); 121 | } 122 | } 123 | /** 124 | * 批量移动用户分组 125 | */ 126 | @Test 127 | public void membersDatchUpdateGroup(){ 128 | String [] openIds={"otweTt8vRASrS-zji8v4YSStH-cc","otweTt4fjjPDZtGlQx_w5XfV42sc"}; 129 | int groupId=103; 130 | try { 131 | manager.membersDatchUpdateGroup(openIds, groupId); 132 | System.out.println("操作成功"); 133 | } catch (WeChatException e) { 134 | System.out.println("操作失败"); 135 | e.printStackTrace(); 136 | } 137 | } 138 | /** 139 | * 删除分组 140 | */ 141 | @Test 142 | public void deleteGroup(){ 143 | int groupId = 109; 144 | try { 145 | manager.deleteGroup(groupId); 146 | System.out.println("操作成功"); 147 | } catch (WeChatException e) { 148 | System.out.println("操作失败"); 149 | e.printStackTrace(); 150 | } 151 | } 152 | } 153 | -------------------------------------------------------------------------------- /test/wechat4j.properties: -------------------------------------------------------------------------------- 1 | 2 | 3 | #url 4 | wechat.url= 5 | #token 6 | wechat.token=lejian 7 | #encodingaeskey 8 | wechat.encodingaeskey= 9 | 10 | #wechat appid 11 | wechat.appid=wx575d25f1d917ea69 12 | #wechat app secret 13 | wechat.appsecret=a338496aaed7c84f0466b494a51c88f1 14 | #wechat mch id 15 | wechat.mch.id= 16 | #wechat mch api secret key, must be 32 length 17 | wechat.mch.key= 18 | 19 | 20 | #wechat access token server ,when you save in db,must implement you server class 21 | #this class must extend org.sword.wechat4j.token.server.CustomerServer 22 | #if no this property,then token server is default memery accesstoken server 23 | wechat.accessToken.server.class= 24 | 25 | #jsapi_ticket customer server class name, 26 | #this class must extend org.sword.wechat4j.token.server.CustomerServer 27 | #if no this property,then ticket server is default memery ticket server 28 | wechat.ticket.jsapi.server.class= --------------------------------------------------------------------------------