mirror of
https://gitee.com/binary/weixin-java-tools.git
synced 2025-10-30 01:58:23 +08:00
issue #39 公众号添加oauth2的支持
This commit is contained in:
@ -25,7 +25,7 @@ public interface WxMpConfigStorage {
|
||||
|
||||
public int getExpiresIn();
|
||||
|
||||
public String getOauth2redirectUrl();
|
||||
public String getOauth2redirectUri();
|
||||
|
||||
public String getHttp_proxy_host();
|
||||
|
||||
|
||||
@ -20,7 +20,7 @@ public class WxMpInMemoryConfigStorage implements WxMpConfigStorage {
|
||||
protected int http_proxy_port;
|
||||
protected String http_proxy_username;
|
||||
protected String http_proxy_password;
|
||||
protected String oauth2redirectUrl;
|
||||
protected String oauth2redirectUri;
|
||||
|
||||
public void updateAccessToken(WxAccessToken accessToken) {
|
||||
updateAccessToken(accessToken.getAccessToken(), accessToken.getExpiresIn());
|
||||
@ -80,12 +80,12 @@ public class WxMpInMemoryConfigStorage implements WxMpConfigStorage {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getOauth2redirectUrl() {
|
||||
return this.oauth2redirectUrl;
|
||||
public String getOauth2redirectUri() {
|
||||
return this.oauth2redirectUri;
|
||||
}
|
||||
|
||||
public void setOauth2redirectUrl(String oauth2redirectUrl) {
|
||||
this.oauth2redirectUrl = oauth2redirectUrl;
|
||||
public void setOauth2redirectUri(String oauth2redirectUri) {
|
||||
this.oauth2redirectUri = oauth2redirectUri;
|
||||
}
|
||||
|
||||
public String getHttp_proxy_host() {
|
||||
|
||||
@ -27,13 +27,11 @@ import org.apache.http.client.CredentialsProvider;
|
||||
import org.apache.http.client.config.RequestConfig;
|
||||
import org.apache.http.client.methods.CloseableHttpResponse;
|
||||
import org.apache.http.client.methods.HttpGet;
|
||||
import org.apache.http.client.utils.URIUtils;
|
||||
import org.apache.http.impl.client.BasicCredentialsProvider;
|
||||
import org.apache.http.impl.client.BasicResponseHandler;
|
||||
import org.apache.http.impl.client.CloseableHttpClient;
|
||||
import org.apache.http.impl.client.HttpClients;
|
||||
|
||||
import javax.print.DocFlavor;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
@ -303,7 +301,7 @@ public class WxMpServiceImpl implements WxMpService {
|
||||
public String oauth2buildAuthorizationUrl(String scope, String state) {
|
||||
String url = "https://open.weixin.qq.com/connect/oauth2/authorize?" ;
|
||||
url += "appid=" + wxMpConfigStorage.getAppId();
|
||||
url += "&redirect_uri=" + URIUtil.encodeURIComponent(wxMpConfigStorage.getOauth2redirectUrl());
|
||||
url += "&redirect_uri=" + URIUtil.encodeURIComponent(wxMpConfigStorage.getOauth2redirectUri());
|
||||
url += "&response_type=code";
|
||||
url += "&scope=" + scope;
|
||||
if (state != null) {
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
package me.chanjar.weixin.mp.bean.result;
|
||||
|
||||
import me.chanjar.weixin.common.util.json.WxGsonBuilder;
|
||||
import me.chanjar.weixin.mp.util.json.WxMpGsonBuilder;
|
||||
|
||||
/**
|
||||
* Created by qianjia on 14/11/26.
|
||||
@ -58,7 +59,17 @@ public class WxMpOAuth2AccessToken {
|
||||
}
|
||||
|
||||
public static WxMpOAuth2AccessToken fromJson(String json) {
|
||||
return WxGsonBuilder.create().fromJson(json, WxMpOAuth2AccessToken.class);
|
||||
return WxMpGsonBuilder.create().fromJson(json, WxMpOAuth2AccessToken.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "WxMpOAuth2AccessToken{" +
|
||||
"accessToken='" + accessToken + '\'' +
|
||||
", expiresIn=" + expiresIn +
|
||||
", refreshToken='" + refreshToken + '\'' +
|
||||
", openId='" + openId + '\'' +
|
||||
", scope='" + scope + '\'' +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
||||
@ -9,7 +9,7 @@ import me.chanjar.weixin.mp.util.json.WxMpGsonBuilder;
|
||||
*/
|
||||
public class WxMpUser {
|
||||
|
||||
protected boolean subscribe;
|
||||
protected Boolean subscribe;
|
||||
protected String openId;
|
||||
protected String nickname;
|
||||
protected String sex;
|
||||
@ -18,13 +18,13 @@ public class WxMpUser {
|
||||
protected String province;
|
||||
protected String country;
|
||||
protected String headImgUrl;
|
||||
protected long subscribeTime;
|
||||
protected Long subscribeTime;
|
||||
protected String unionId;
|
||||
|
||||
public boolean isSubscribe() {
|
||||
public Boolean isSubscribe() {
|
||||
return subscribe;
|
||||
}
|
||||
public void setSubscribe(boolean subscribe) {
|
||||
public void setSubscribe(Boolean subscribe) {
|
||||
this.subscribe = subscribe;
|
||||
}
|
||||
public String getOpenId() {
|
||||
@ -75,10 +75,10 @@ public class WxMpUser {
|
||||
public void setHeadImgUrl(String headImgUrl) {
|
||||
this.headImgUrl = headImgUrl;
|
||||
}
|
||||
public long getSubscribeTime() {
|
||||
public Long getSubscribeTime() {
|
||||
return subscribeTime;
|
||||
}
|
||||
public void setSubscribeTime(long subscribeTime) {
|
||||
public void setSubscribeTime(Long subscribeTime) {
|
||||
this.subscribeTime = subscribeTime;
|
||||
}
|
||||
public String getUnionId() {
|
||||
@ -92,4 +92,20 @@ public class WxMpUser {
|
||||
return WxMpGsonBuilder.INSTANCE.create().fromJson(json, WxMpUser.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "WxMpUser{" +
|
||||
"subscribe=" + subscribe +
|
||||
", openId='" + openId + '\'' +
|
||||
", nickname='" + nickname + '\'' +
|
||||
", sex='" + sex + '\'' +
|
||||
", language='" + language + '\'' +
|
||||
", city='" + city + '\'' +
|
||||
", province='" + province + '\'' +
|
||||
", country='" + country + '\'' +
|
||||
", headImgUrl='" + headImgUrl + '\'' +
|
||||
", subscribeTime=" + subscribeTime +
|
||||
", unionId='" + unionId + '\'' +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
||||
@ -4,6 +4,7 @@ import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import me.chanjar.weixin.mp.bean.*;
|
||||
import me.chanjar.weixin.mp.bean.result.*;
|
||||
import me.chanjar.weixin.mp.bean.result.WxMpOAuth2AccessToken;
|
||||
|
||||
public class WxMpGsonBuilder {
|
||||
|
||||
@ -24,6 +25,7 @@ public class WxMpGsonBuilder {
|
||||
INSTANCE.registerTypeAdapter(WxMpQrCodeTicket.class, new WxQrCodeTicketAdapter());
|
||||
INSTANCE.registerTypeAdapter(WxMpTemplateMessage.class, new WxMpTemplateMessageGsonAdapter());
|
||||
INSTANCE.registerTypeAdapter(WxMpSemanticQueryResult.class, new WxMpSemanticQueryResultAdapter());
|
||||
INSTANCE.registerTypeAdapter(WxMpOAuth2AccessToken.class, new WxMpOAuth2AccessTokenAdapter());
|
||||
}
|
||||
|
||||
public static Gson create() {
|
||||
|
||||
@ -0,0 +1,38 @@
|
||||
package me.chanjar.weixin.mp.util.json;
|
||||
|
||||
import com.google.gson.*;
|
||||
import me.chanjar.weixin.common.bean.WxAccessToken;
|
||||
import me.chanjar.weixin.common.util.json.GsonHelper;
|
||||
import me.chanjar.weixin.mp.bean.result.WxMpOAuth2AccessToken;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
|
||||
/**
|
||||
* Created by qianjia on 14/11/28.
|
||||
*/
|
||||
public class WxMpOAuth2AccessTokenAdapter implements JsonDeserializer<WxMpOAuth2AccessToken> {
|
||||
|
||||
public WxMpOAuth2AccessToken deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws
|
||||
JsonParseException {
|
||||
WxMpOAuth2AccessToken accessToken = new WxMpOAuth2AccessToken();
|
||||
JsonObject accessTokenJsonObject = json.getAsJsonObject();
|
||||
|
||||
if (accessTokenJsonObject.get("access_token") != null && !accessTokenJsonObject.get("access_token").isJsonNull()) {
|
||||
accessToken.setAccessToken(GsonHelper.getAsString(accessTokenJsonObject.get("access_token")));
|
||||
}
|
||||
if (accessTokenJsonObject.get("expires_in") != null && !accessTokenJsonObject.get("expires_in").isJsonNull()) {
|
||||
accessToken.setExpiresIn(GsonHelper.getAsPrimitiveInt(accessTokenJsonObject.get("expires_in")));
|
||||
}
|
||||
if (accessTokenJsonObject.get("refresh_token") != null && !accessTokenJsonObject.get("refresh_token").isJsonNull()) {
|
||||
accessToken.setRefreshToken(GsonHelper.getAsString(accessTokenJsonObject.get("refresh_token")));
|
||||
}
|
||||
if (accessTokenJsonObject.get("openid") != null && !accessTokenJsonObject.get("openid").isJsonNull()) {
|
||||
accessToken.setOpenId(GsonHelper.getAsString(accessTokenJsonObject.get("openid")));
|
||||
}
|
||||
if (accessTokenJsonObject.get("scope") != null && !accessTokenJsonObject.get("scope").isJsonNull()) {
|
||||
accessToken.setScope(GsonHelper.getAsString(accessTokenJsonObject.get("scope")));
|
||||
}
|
||||
return accessToken;
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,20 +1,127 @@
|
||||
package me.chanjar.weixin.mp.demo;
|
||||
|
||||
import me.chanjar.weixin.common.api.WxConsts;
|
||||
import me.chanjar.weixin.common.bean.result.WxMediaUploadResult;
|
||||
import me.chanjar.weixin.common.exception.WxErrorException;
|
||||
import me.chanjar.weixin.mp.api.*;
|
||||
import me.chanjar.weixin.mp.bean.WxMpMpXmlOutImageMessage;
|
||||
import me.chanjar.weixin.mp.bean.WxMpXmlMessage;
|
||||
import me.chanjar.weixin.mp.bean.WxMpXmlOutMessage;
|
||||
import me.chanjar.weixin.mp.bean.WxMpXmlOutTextMessage;
|
||||
import org.eclipse.jetty.server.Server;
|
||||
import org.eclipse.jetty.servlet.ServletHandler;
|
||||
import org.eclipse.jetty.servlet.*;
|
||||
|
||||
import javax.xml.bind.JAXBException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author Daniel Qian
|
||||
*/
|
||||
public class WxMpDemoServer {
|
||||
|
||||
private static WxMpConfigStorage wxMpConfigStorage;
|
||||
private static WxMpService wxMpService;
|
||||
private static WxMpMessageRouter wxMpMessageRouter;
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
initWeixin();
|
||||
|
||||
Server server = new Server(8080);
|
||||
|
||||
ServletHandler handler = new ServletHandler();
|
||||
server.setHandler(handler);
|
||||
|
||||
handler.addServletWithMapping(WxMpDemoServlet.class, "/*");
|
||||
ServletHolder endpointServletHolder = new ServletHolder(new WxMpEndpointServlt(wxMpConfigStorage, wxMpService, wxMpMessageRouter));
|
||||
handler.addServletWithMapping(endpointServletHolder, "/*");
|
||||
|
||||
ServletHolder oauthServletHolder = new ServletHolder(new WxMpOAuth2Servlet(wxMpService));
|
||||
handler.addServletWithMapping(oauthServletHolder, "/oauth2/*");
|
||||
|
||||
server.setHandler(handler);
|
||||
server.start();
|
||||
server.join();
|
||||
}
|
||||
|
||||
private static void initWeixin() {
|
||||
try {
|
||||
InputStream is1 = ClassLoader.getSystemResourceAsStream("test-config.xml");
|
||||
WxMpDemoInMemoryConfigStorage config = WxMpDemoInMemoryConfigStorage.fromXml(is1);
|
||||
|
||||
wxMpConfigStorage = config;
|
||||
wxMpService = new WxMpServiceImpl();
|
||||
wxMpService.setWxMpConfigStorage(config);
|
||||
|
||||
WxMpMessageHandler textHandler = new WxMpMessageHandler() {
|
||||
@Override
|
||||
public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, Map<String, Object> context,
|
||||
WxMpService wxMpService) {
|
||||
WxMpXmlOutTextMessage m
|
||||
= WxMpXmlOutMessage.TEXT().content("测试加密消息").fromUser(wxMessage.getToUserName())
|
||||
.toUser(wxMessage.getFromUserName()).build();
|
||||
return m;
|
||||
}
|
||||
};
|
||||
|
||||
WxMpMessageHandler imageHandler = new WxMpMessageHandler() {
|
||||
@Override
|
||||
public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, Map<String, Object> context,
|
||||
WxMpService wxMpService) {
|
||||
try {
|
||||
WxMediaUploadResult wxMediaUploadResult = wxMpService
|
||||
.mediaUpload(WxConsts.MEDIA_IMAGE, WxConsts.FILE_JPG, ClassLoader.getSystemResourceAsStream("mm.jpeg"));
|
||||
WxMpMpXmlOutImageMessage m
|
||||
= WxMpXmlOutMessage
|
||||
.IMAGE()
|
||||
.mediaId(wxMediaUploadResult.getMediaId())
|
||||
.fromUser(wxMessage.getToUserName())
|
||||
.toUser(wxMessage.getFromUserName())
|
||||
.build();
|
||||
return m;
|
||||
} catch (WxErrorException e) {
|
||||
e.printStackTrace();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
WxMpMessageHandler oauth2handler = new WxMpMessageHandler() {
|
||||
@Override
|
||||
public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, Map<String, Object> context,
|
||||
WxMpService wxMpService) {
|
||||
String href = "<a href=\"" + wxMpService.oauth2buildAuthorizationUrl(WxConsts.OAUTH2_SCOPE_USER_INFO, null)
|
||||
+ "\">测试oauth2</a>";
|
||||
return WxMpXmlOutMessage
|
||||
.TEXT()
|
||||
.content(href)
|
||||
.fromUser(wxMessage.getToUserName())
|
||||
.toUser(wxMessage.getFromUserName()).build();
|
||||
}
|
||||
};
|
||||
|
||||
wxMpMessageRouter = new WxMpMessageRouter(wxMpService);
|
||||
wxMpMessageRouter
|
||||
.rule()
|
||||
.async(false)
|
||||
.content("哈哈") // 拦截内容为“哈哈”的消息
|
||||
.handler(textHandler)
|
||||
.end()
|
||||
.rule()
|
||||
.async(false)
|
||||
.content("图片")
|
||||
.handler(imageHandler)
|
||||
.end()
|
||||
.rule()
|
||||
.async(false)
|
||||
.content("oauth")
|
||||
.handler(oauth2handler)
|
||||
.end()
|
||||
;
|
||||
|
||||
} catch (JAXBException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -22,71 +22,17 @@ import java.util.Map;
|
||||
/**
|
||||
* @author Daniel Qian
|
||||
*/
|
||||
public class WxMpDemoServlet extends HttpServlet {
|
||||
public class WxMpEndpointServlt extends HttpServlet {
|
||||
|
||||
protected WxMpConfigStorage wxMpConfigStorage;
|
||||
protected WxMpService wxMpService;
|
||||
protected WxMpMessageRouter wxMpMessageRouter;
|
||||
|
||||
@Override public void init() throws ServletException {
|
||||
//
|
||||
super.init();
|
||||
try {
|
||||
InputStream is1 = ClassLoader.getSystemResourceAsStream("test-config.xml");
|
||||
WxMpDemoInMemoryConfigStorage config = WxMpDemoInMemoryConfigStorage.fromXml(is1);
|
||||
|
||||
wxMpConfigStorage = config;
|
||||
wxMpService = new WxMpServiceImpl();
|
||||
wxMpService.setWxMpConfigStorage(config);
|
||||
|
||||
WxMpMessageHandler textHandler = new WxMpMessageHandler() {
|
||||
@Override public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, Map<String, Object> context, WxMpService wxMpService) {
|
||||
WxMpXmlOutTextMessage m
|
||||
= WxMpXmlOutMessage.TEXT().content("测试加密消息").fromUser(wxMessage.getToUserName())
|
||||
.toUser(wxMessage.getFromUserName()).build();
|
||||
return m;
|
||||
}
|
||||
};
|
||||
|
||||
WxMpMessageHandler imageHandler = new WxMpMessageHandler() {
|
||||
@Override public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, Map<String, Object> context, WxMpService wxMpService) {
|
||||
try {
|
||||
WxMediaUploadResult wxMediaUploadResult = wxMpService
|
||||
.mediaUpload(WxConsts.MEDIA_IMAGE, WxConsts.FILE_JPG, ClassLoader.getSystemResourceAsStream("mm.jpeg"));
|
||||
WxMpMpXmlOutImageMessage m
|
||||
= WxMpXmlOutMessage
|
||||
.IMAGE()
|
||||
.mediaId(wxMediaUploadResult.getMediaId())
|
||||
.fromUser(wxMessage.getToUserName())
|
||||
.toUser(wxMessage.getFromUserName())
|
||||
.build();
|
||||
return m;
|
||||
} catch (WxErrorException e) {
|
||||
e.printStackTrace();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
wxMpMessageRouter = new WxMpMessageRouter(wxMpService);
|
||||
wxMpMessageRouter
|
||||
.rule()
|
||||
.async(false)
|
||||
.content("哈哈") // 拦截内容为“哈哈”的消息
|
||||
.handler(textHandler)
|
||||
.end()
|
||||
.rule()
|
||||
.async(false)
|
||||
.content("图片")
|
||||
.handler(imageHandler)
|
||||
.end()
|
||||
;
|
||||
|
||||
} catch (JAXBException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
public WxMpEndpointServlt(WxMpConfigStorage wxMpConfigStorage, WxMpService wxMpService,
|
||||
WxMpMessageRouter wxMpMessageRouter) {
|
||||
this.wxMpConfigStorage = wxMpConfigStorage;
|
||||
this.wxMpService = wxMpService;
|
||||
this.wxMpMessageRouter = wxMpMessageRouter;
|
||||
}
|
||||
|
||||
@Override protected void service(HttpServletRequest request, HttpServletResponse response)
|
||||
@ -0,0 +1,68 @@
|
||||
package me.chanjar.weixin.mp.demo;
|
||||
|
||||
import me.chanjar.weixin.common.api.WxConsts;
|
||||
import me.chanjar.weixin.common.bean.result.WxMediaUploadResult;
|
||||
import me.chanjar.weixin.common.exception.WxErrorException;
|
||||
import me.chanjar.weixin.common.util.StringUtils;
|
||||
import me.chanjar.weixin.mp.api.*;
|
||||
import me.chanjar.weixin.mp.bean.WxMpMpXmlOutImageMessage;
|
||||
import me.chanjar.weixin.mp.bean.WxMpXmlMessage;
|
||||
import me.chanjar.weixin.mp.bean.WxMpXmlOutMessage;
|
||||
import me.chanjar.weixin.mp.bean.WxMpXmlOutTextMessage;
|
||||
import me.chanjar.weixin.mp.bean.result.WxMpOAuth2AccessToken;
|
||||
import me.chanjar.weixin.mp.bean.result.WxMpUser;
|
||||
|
||||
import javax.servlet.ServletContext;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.xml.bind.JAXBException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author Daniel Qian
|
||||
*/
|
||||
public class WxMpOAuth2Servlet extends HttpServlet {
|
||||
|
||||
protected WxMpService wxMpService;
|
||||
|
||||
public WxMpOAuth2Servlet(WxMpService wxMpService) {
|
||||
this.wxMpService = wxMpService;
|
||||
}
|
||||
|
||||
@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);
|
||||
|
||||
WxMpOAuth2AccessToken wxMpOAuth2AccessToken = wxMpService.oauth2getAccessToken(code);
|
||||
response.getWriter().println("<h1>access token</h1>");
|
||||
response.getWriter().println(wxMpOAuth2AccessToken.toString());
|
||||
|
||||
WxMpUser wxMpUser = wxMpService.oauth2getUserInfo(wxMpOAuth2AccessToken, null);
|
||||
response.getWriter().println("<h1>user info</h1>");
|
||||
response.getWriter().println(wxMpUser.toString());
|
||||
|
||||
wxMpOAuth2AccessToken = wxMpService.oauth2refreshAccessToken(wxMpOAuth2AccessToken.getRefreshToken());
|
||||
response.getWriter().println("<h1>after refresh</h1>");
|
||||
response.getWriter().println(wxMpOAuth2AccessToken.toString());
|
||||
|
||||
} catch (WxErrorException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
response.getWriter().flush();
|
||||
response.getWriter().close();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@ -6,4 +6,5 @@
|
||||
<accessToken>可以不填写</accessToken>
|
||||
<expiresIn>可以不填写</expiresIn>
|
||||
<openId>某个加你公众号的用户的openId</openId>
|
||||
<oauth2redirectUri>网页授权获取用户信息回调地址</oauth2redirectUri>
|
||||
</xml>
|
||||
|
||||
Reference in New Issue
Block a user