| @@ -27,6 +27,8 @@ public interface WxCpConfigStorage { | |||||
| public int getExpiresIn(); | public int getExpiresIn(); | ||||
| public String getOauth2redirectUri(); | |||||
| public String getHttp_proxy_host(); | public String getHttp_proxy_host(); | ||||
| public int getHttp_proxy_port(); | public int getHttp_proxy_port(); | ||||
| @@ -18,6 +18,8 @@ public class WxCpInMemoryConfigStorage implements WxCpConfigStorage { | |||||
| protected String agentId; | protected String agentId; | ||||
| protected int expiresIn; | protected int expiresIn; | ||||
| protected String oauth2redirectUri; | |||||
| protected String http_proxy_host; | protected String http_proxy_host; | ||||
| protected int http_proxy_port; | protected int http_proxy_port; | ||||
| protected String http_proxy_username; | protected String http_proxy_username; | ||||
| @@ -88,6 +90,15 @@ public class WxCpInMemoryConfigStorage implements WxCpConfigStorage { | |||||
| this.agentId = agentId; | this.agentId = agentId; | ||||
| } | } | ||||
| @Override | |||||
| public String getOauth2redirectUri() { | |||||
| return this.oauth2redirectUri; | |||||
| } | |||||
| public void setOauth2redirectUri(String oauth2redirectUri) { | |||||
| this.oauth2redirectUri = oauth2redirectUri; | |||||
| } | |||||
| public String getHttp_proxy_host() { | public String getHttp_proxy_host() { | ||||
| return http_proxy_host; | return http_proxy_host; | ||||
| } | } | ||||
| @@ -274,6 +274,26 @@ public interface WxCpService { | |||||
| */ | */ | ||||
| public void tagAddUsers(String tagId, List<String> userIds) throws WxErrorException; | public void tagAddUsers(String tagId, List<String> userIds) throws WxErrorException; | ||||
| /** | |||||
| * <pre> | |||||
| * 构造oauth2授权的url连接 | |||||
| * 详情请见: http://qydev.weixin.qq.com/wiki/index.php?title=企业获取code | |||||
| * </pre> | |||||
| * @param state | |||||
| * @return code | |||||
| */ | |||||
| public String oauth2buildAuthorizationUrl(String state); | |||||
| /** | |||||
| * <pre> | |||||
| * 用oauth2获取用户信息 | |||||
| * http://qydev.weixin.qq.com/wiki/index.php?title=根据code获取成员信息 | |||||
| * </pre> | |||||
| * @param code | |||||
| * @return [userid, deviceid] | |||||
| */ | |||||
| public String[] oauth2getUserInfo(String code) throws WxErrorException; | |||||
| /** | /** | ||||
| * 移除标签成员 | * 移除标签成员 | ||||
| * | * | ||||
| @@ -316,6 +316,41 @@ public class WxCpServiceImpl implements WxCpService { | |||||
| execute(new SimplePostRequestExecutor(), url, jsonObject.toString()); | execute(new SimplePostRequestExecutor(), url, jsonObject.toString()); | ||||
| } | } | ||||
| @Override | |||||
| public String oauth2buildAuthorizationUrl(String state) { | |||||
| String url = "https://open.weixin.qq.com/connect/oauth2/authorize?" ; | |||||
| url += "appid=" + wxCpConfigStorage.getCorpId(); | |||||
| url += "&redirect_uri=" + URIUtil.encodeURIComponent(wxCpConfigStorage.getOauth2redirectUri()); | |||||
| url += "&response_type=code"; | |||||
| url += "&scope=snsapi_base"; | |||||
| if (state != null) { | |||||
| url += "&state=" + state; | |||||
| } | |||||
| url += "#wechat_redirect"; | |||||
| return url; | |||||
| } | |||||
| @Override | |||||
| public String[] oauth2getUserInfo(String code) throws WxErrorException { | |||||
| String url = "https://qyapi.weixin.qq.com/cgi-bin/user/getuserinfo?"; | |||||
| url += "access_token=" + wxCpConfigStorage.getAccessToken(); | |||||
| url += "&code=" + code; | |||||
| url += "agendid=" + wxCpConfigStorage.getAgentId(); | |||||
| try { | |||||
| RequestExecutor<String, String> executor = new SimpleGetRequestExecutor(); | |||||
| String responseText = executor.execute(getHttpclient(), httpProxy, url, null); | |||||
| JsonElement je = Streams.parse(new JsonReader(new StringReader(responseText))); | |||||
| JsonObject jo = je.getAsJsonObject(); | |||||
| return new String[] {GsonHelper.getString(jo, "UserId"), GsonHelper.getString(jo, "DeviceId")}; | |||||
| } catch (ClientProtocolException e) { | |||||
| throw new RuntimeException(e); | |||||
| } catch (IOException e) { | |||||
| throw new RuntimeException(e); | |||||
| } | |||||
| } | |||||
| public String get(String url, String queryParam) throws WxErrorException { | public String get(String url, String queryParam) throws WxErrorException { | ||||
| return execute(new SimpleGetRequestExecutor(), url, queryParam); | return execute(new SimpleGetRequestExecutor(), url, queryParam); | ||||
| } | } | ||||
| @@ -1,20 +1,93 @@ | |||||
| package me.chanjar.weixin.cp.demo; | package me.chanjar.weixin.cp.demo; | ||||
| import me.chanjar.weixin.common.api.WxConsts; | |||||
| import me.chanjar.weixin.cp.api.*; | |||||
| import me.chanjar.weixin.cp.bean.WxCpXmlMessage; | |||||
| import me.chanjar.weixin.cp.bean.WxCpXmlOutMessage; | |||||
| import me.chanjar.weixin.cp.bean.WxCpXmlOutTextMessage; | |||||
| import org.eclipse.jetty.server.Server; | import org.eclipse.jetty.server.Server; | ||||
| import org.eclipse.jetty.servlet.ServletHandler; | import org.eclipse.jetty.servlet.ServletHandler; | ||||
| import org.eclipse.jetty.servlet.ServletHolder; | |||||
| import javax.xml.bind.JAXBException; | |||||
| import java.io.InputStream; | |||||
| import java.util.Map; | |||||
| /** | |||||
| * @author Daniel Qian | |||||
| */ | |||||
| public class WxCpDemoServer { | public class WxCpDemoServer { | ||||
| private static WxCpConfigStorage wxCpConfigStorage; | |||||
| private static WxCpService wxCpService; | |||||
| private static WxCpMessageRouter wxCpMessageRouter; | |||||
| public static void main(String[] args) throws Exception { | public static void main(String[] args) throws Exception { | ||||
| Server server = new Server(8080); | Server server = new Server(8080); | ||||
| ServletHandler handler = new ServletHandler(); | ServletHandler handler = new ServletHandler(); | ||||
| server.setHandler(handler); | server.setHandler(handler); | ||||
| handler.addServletWithMapping(WxCpDemoServlet.class, "/*"); | |||||
| ServletHolder endpointServletHolder = new ServletHolder(new WxCpEndpointServlet(wxCpConfigStorage, wxCpService, wxCpMessageRouter)); | |||||
| handler.addServletWithMapping(endpointServletHolder, "/*"); | |||||
| ServletHolder oauthServletHolder = new ServletHolder(new WxCpOAuth2Servlet(wxCpService)); | |||||
| handler.addServletWithMapping(oauthServletHolder, "/oauth2/*"); | |||||
| server.start(); | server.start(); | ||||
| server.join(); | server.join(); | ||||
| } | } | ||||
| private static void init() { | |||||
| try { | |||||
| InputStream is1 = ClassLoader.getSystemResourceAsStream("test-config.xml"); | |||||
| WxCpDemoInMemoryConfigStorage config = WxCpDemoInMemoryConfigStorage.fromXml(is1); | |||||
| wxCpConfigStorage = config; | |||||
| wxCpService = new WxCpServiceImpl(); | |||||
| wxCpService.setWxCpConfigStorage(config); | |||||
| WxCpMessageHandler handler = new WxCpMessageHandler() { | |||||
| @Override | |||||
| public WxCpXmlOutMessage handle(WxCpXmlMessage wxMessage, Map<String, Object> context, | |||||
| WxCpService wxCpService) { | |||||
| WxCpXmlOutTextMessage m = WxCpXmlOutMessage | |||||
| .TEXT() | |||||
| .content("测试加密消息") | |||||
| .fromUser(wxMessage.getToUserName()) | |||||
| .toUser(wxMessage.getFromUserName()) | |||||
| .build(); | |||||
| return m; | |||||
| } | |||||
| }; | |||||
| WxCpMessageHandler oauth2handler = new WxCpMessageHandler() { | |||||
| @Override | |||||
| public WxCpXmlOutMessage handle(WxCpXmlMessage wxMessage, Map<String, Object> context, | |||||
| WxCpService wxCpService) { | |||||
| String href = "<a href=\"" + wxCpService.oauth2buildAuthorizationUrl(null) | |||||
| + "\">测试oauth2</a>"; | |||||
| return WxCpXmlOutMessage | |||||
| .TEXT() | |||||
| .content(href) | |||||
| .fromUser(wxMessage.getToUserName()) | |||||
| .toUser(wxMessage.getFromUserName()).build(); | |||||
| } | |||||
| }; | |||||
| wxCpMessageRouter = new WxCpMessageRouter(wxCpService); | |||||
| wxCpMessageRouter | |||||
| .rule() | |||||
| .async(false) | |||||
| .content("哈哈") // 拦截内容为“哈哈”的消息 | |||||
| .handler(handler) | |||||
| .end() | |||||
| .rule() | |||||
| .async(false) | |||||
| .content("oauth") | |||||
| .handler(oauth2handler) | |||||
| .end() | |||||
| ; | |||||
| } catch (JAXBException e) { | |||||
| throw new RuntimeException(e); | |||||
| } | |||||
| } | |||||
| } | } | ||||
| @@ -19,49 +19,21 @@ import java.util.Map; | |||||
| /** | /** | ||||
| * @author Daniel Qian | * @author Daniel Qian | ||||
| */ | */ | ||||
| public class WxCpDemoServlet extends HttpServlet { | |||||
| public class WxCpEndpointServlet extends HttpServlet { | |||||
| protected WxCpConfigStorage wxCpConfigStorage; | protected WxCpConfigStorage wxCpConfigStorage; | ||||
| protected WxCpService wxCpService; | protected WxCpService wxCpService; | ||||
| protected WxCpMessageRouter wxCpMessageRouter; | protected WxCpMessageRouter wxCpMessageRouter; | ||||
| @Override public void init() throws ServletException { | |||||
| // | |||||
| super.init(); | |||||
| try { | |||||
| InputStream is1 = ClassLoader.getSystemResourceAsStream("test-config.xml"); | |||||
| WxCpDemoInMemoryConfigStorage config = WxCpDemoInMemoryConfigStorage.fromXml(is1); | |||||
| wxCpConfigStorage = config; | |||||
| wxCpService = new WxCpServiceImpl(); | |||||
| wxCpService.setWxCpConfigStorage(config); | |||||
| WxCpMessageHandler handler = new WxCpMessageHandler() { | |||||
| @Override public WxCpXmlOutMessage handle(WxCpXmlMessage wxMessage, Map<String, Object> context, WxCpService wxCpService) { | |||||
| WxCpXmlOutTextMessage m = WxCpXmlOutMessage | |||||
| .TEXT() | |||||
| .content("测试加密消息") | |||||
| .fromUser(wxMessage.getToUserName()) | |||||
| .toUser(wxMessage.getFromUserName()) | |||||
| .build(); | |||||
| return m; | |||||
| } | |||||
| }; | |||||
| wxCpMessageRouter = new WxCpMessageRouter(wxCpService); | |||||
| wxCpMessageRouter | |||||
| .rule() | |||||
| .async(false) | |||||
| .content("哈哈") // 拦截内容为“哈哈”的消息 | |||||
| .handler(handler) | |||||
| .end(); | |||||
| } catch (JAXBException e) { | |||||
| throw new RuntimeException(e); | |||||
| } | |||||
| public WxCpEndpointServlet(WxCpConfigStorage wxCpConfigStorage, WxCpService wxCpService, | |||||
| WxCpMessageRouter wxCpMessageRouter) { | |||||
| this.wxCpConfigStorage = wxCpConfigStorage; | |||||
| this.wxCpService = wxCpService; | |||||
| this.wxCpMessageRouter = wxCpMessageRouter; | |||||
| } | } | ||||
| @Override protected void service(HttpServletRequest request, HttpServletResponse response) | |||||
| @Override | |||||
| protected void service(HttpServletRequest request, HttpServletResponse response) | |||||
| throws ServletException, IOException { | throws ServletException, IOException { | ||||
| response.setContentType("text/html;charset=utf-8"); | response.setContentType("text/html;charset=utf-8"); | ||||
| @@ -85,7 +57,8 @@ public class WxCpDemoServlet extends HttpServlet { | |||||
| return; | return; | ||||
| } | } | ||||
| WxCpXmlMessage inMessage = WxCpXmlMessage.fromEncryptedXml(request.getInputStream(), wxCpConfigStorage, timestamp, nonce, msgSignature); | |||||
| WxCpXmlMessage inMessage = WxCpXmlMessage | |||||
| .fromEncryptedXml(request.getInputStream(), wxCpConfigStorage, timestamp, nonce, msgSignature); | |||||
| WxCpXmlOutMessage outMessage = wxCpMessageRouter.route(inMessage); | WxCpXmlOutMessage outMessage = wxCpMessageRouter.route(inMessage); | ||||
| if (outMessage != null) { | if (outMessage != null) { | ||||
| response.getWriter().write(outMessage.toEncryptedXml(wxCpConfigStorage)); | response.getWriter().write(outMessage.toEncryptedXml(wxCpConfigStorage)); | ||||
| @@ -0,0 +1,48 @@ | |||||
| package me.chanjar.weixin.cp.demo; | |||||
| import me.chanjar.weixin.common.exception.WxErrorException; | |||||
| import me.chanjar.weixin.cp.api.WxCpService; | |||||
| import javax.servlet.ServletException; | |||||
| import javax.servlet.http.HttpServlet; | |||||
| import javax.servlet.http.HttpServletRequest; | |||||
| import javax.servlet.http.HttpServletResponse; | |||||
| import java.io.IOException; | |||||
| import java.util.Arrays; | |||||
| /** | |||||
| * Created by qianjia on 14/11/28. | |||||
| */ | |||||
| public class WxCpOAuth2Servlet extends HttpServlet { | |||||
| protected WxCpService wxCpService; | |||||
| public WxCpOAuth2Servlet(WxCpService wxCpService) { | |||||
| this.wxCpService = wxCpService; | |||||
| } | |||||
| @Override protected void service(HttpServletRequest request, HttpServletResponse response) | |||||
| throws ServletException, IOException { | |||||
| response.setContentType("text/html;charset=utf-8"); | |||||
| response.setStatus(HttpServletResponse.SC_OK); | |||||
| String code = request.getParameter("code"); | |||||
| try { | |||||
| response.getWriter().println("<h1>code</h1>"); | |||||
| response.getWriter().println(code); | |||||
| String[] res = wxCpService.oauth2getUserInfo(code); | |||||
| response.getWriter().println("<h1>result</h1>"); | |||||
| response.getWriter().println(Arrays.toString(res)); | |||||
| } catch (WxErrorException e) { | |||||
| e.printStackTrace(); | |||||
| } | |||||
| response.getWriter().flush(); | |||||
| response.getWriter().close(); | |||||
| } | |||||
| } | |||||
| @@ -9,4 +9,5 @@ | |||||
| <userId>企业号通讯录里的某个userid</userId> | <userId>企业号通讯录里的某个userid</userId> | ||||
| <departmentId>企业号通讯录的某个部门id</departmentId> | <departmentId>企业号通讯录的某个部门id</departmentId> | ||||
| <tagId>企业号通讯录里的某个tagid</tagId> | <tagId>企业号通讯录里的某个tagid</tagId> | ||||
| <oauth2redirectUri>网页授权获取用户信息回调地址</oauth2redirectUri> | |||||
| </xml> | </xml> | ||||
| @@ -16,11 +16,12 @@ public class WxMpInMemoryConfigStorage implements WxMpConfigStorage { | |||||
| protected String aesKey; | protected String aesKey; | ||||
| protected int expiresIn; | protected int expiresIn; | ||||
| protected String oauth2redirectUri; | |||||
| protected String http_proxy_host; | protected String http_proxy_host; | ||||
| protected int http_proxy_port; | protected int http_proxy_port; | ||||
| protected String http_proxy_username; | protected String http_proxy_username; | ||||
| protected String http_proxy_password; | protected String http_proxy_password; | ||||
| protected String oauth2redirectUri; | |||||
| public void updateAccessToken(WxAccessToken accessToken) { | public void updateAccessToken(WxAccessToken accessToken) { | ||||
| updateAccessToken(accessToken.getAccessToken(), accessToken.getExpiresIn()); | updateAccessToken(accessToken.getAccessToken(), accessToken.getExpiresIn()); | ||||
| @@ -16,9 +16,6 @@ import java.io.IOException; | |||||
| import java.io.InputStream; | import java.io.InputStream; | ||||
| import java.util.Map; | import java.util.Map; | ||||
| /** | |||||
| * @author Daniel Qian | |||||
| */ | |||||
| public class WxMpDemoServer { | public class WxMpDemoServer { | ||||
| private static WxMpConfigStorage wxMpConfigStorage; | private static WxMpConfigStorage wxMpConfigStorage; | ||||
| @@ -22,9 +22,6 @@ import java.io.IOException; | |||||
| import java.io.InputStream; | import java.io.InputStream; | ||||
| import java.util.Map; | import java.util.Map; | ||||
| /** | |||||
| * @author Daniel Qian | |||||
| */ | |||||
| public class WxMpOAuth2Servlet extends HttpServlet { | public class WxMpOAuth2Servlet extends HttpServlet { | ||||
| protected WxMpService wxMpService; | protected WxMpService wxMpService; | ||||