@@ -1,20 +1,25 @@ | |||
package me.chanjar.weixin.cp.api; | |||
import me.chanjar.weixin.common.error.WxErrorException; | |||
import me.chanjar.weixin.cp.bean.WxCpOauth2UserInfo; | |||
import me.chanjar.weixin.cp.bean.WxCpUserDetail; | |||
/** | |||
* <pre> | |||
* OAuth2相关管理接口 | |||
* OAuth2相关管理接口. | |||
* Created by BinaryWang on 2017/6/24. | |||
* </pre> | |||
* | |||
* @author <a href="https://github.com/binarywang">Binary Wang</a> | |||
*/ | |||
public interface WxCpOAuth2Service { | |||
String URL_GET_USER_INFO = "https://qyapi.weixin.qq.com/cgi-bin/user/getuserinfo?code=%s&agentid=%d"; | |||
String URL_GET_USER_DETAIL = "https://qyapi.weixin.qq.com/cgi-bin/user/getuserdetail"; | |||
String URL_OAUTH_2_AUTHORIZE = "https://open.weixin.qq.com/connect/oauth2/authorize"; | |||
/** | |||
* <pre> | |||
* 构造oauth2授权的url连接 | |||
* 构造oauth2授权的url连接. | |||
* </pre> | |||
* | |||
* @param state 状态码 | |||
@@ -24,7 +29,7 @@ public interface WxCpOAuth2Service { | |||
/** | |||
* <pre> | |||
* 构造oauth2授权的url连接 | |||
* 构造oauth2授权的url连接. | |||
* 详情请见: http://qydev.weixin.qq.com/wiki/index.php?title=企业获取code | |||
* </pre> | |||
* | |||
@@ -57,16 +62,18 @@ public interface WxCpOAuth2Service { | |||
* </pre> | |||
* | |||
* @param code 微信oauth授权返回的代码 | |||
* @return [userid, deviceid] | |||
* @return WxCpOauth2UserInfo | |||
* @throws WxErrorException 异常 | |||
* @see #getUserInfo(Integer, String) | |||
*/ | |||
String[] getUserInfo(String code) throws WxErrorException; | |||
WxCpOauth2UserInfo getUserInfo(String code) throws WxErrorException; | |||
/** | |||
* <pre> | |||
* 根据code获取成员信息 | |||
* http://qydev.weixin.qq.com/wiki/index.php?title=根据code获取成员信息 | |||
* https://work.weixin.qq.com/api/doc#10028/根据code获取成员信息 | |||
* https://work.weixin.qq.com/api/doc#90000/90135/91023 获取访问用户身份 | |||
* 因为企业号oauth2.0必须在应用设置里设置通过ICP备案的可信域名,所以无法测试,因此这个方法很可能是坏的。 | |||
* | |||
* 注意: 这个方法不使用WxCpConfigStorage里的agentId,需要开发人员自己给出 | |||
@@ -74,10 +81,11 @@ public interface WxCpOAuth2Service { | |||
* | |||
* @param agentId 企业号应用的id | |||
* @param code 通过成员授权获取到的code,最大为512字节。每次成员授权带上的code将不一样,code只能使用一次,5分钟未被使用自动过期。 | |||
* @return [UserId, DeviceId, OpenId, user_ticket, expires_in] | |||
* @return WxCpOauth2UserInfo | |||
* @throws WxErrorException 异常 | |||
* @see #getUserInfo(String) | |||
*/ | |||
String[] getUserInfo(Integer agentId, String code) throws WxErrorException; | |||
WxCpOauth2UserInfo getUserInfo(Integer agentId, String code) throws WxErrorException; | |||
/** | |||
* <pre> | |||
@@ -92,6 +100,8 @@ public interface WxCpOAuth2Service { | |||
* </pre> | |||
* | |||
* @param userTicket 成员票据 | |||
* @return WxCpUserDetail | |||
* @throws WxErrorException 异常 | |||
*/ | |||
WxCpUserDetail getUserDetail(String userTicket) throws WxErrorException; | |||
} |
@@ -3,30 +3,31 @@ package me.chanjar.weixin.cp.api.impl; | |||
import com.google.gson.JsonElement; | |||
import com.google.gson.JsonObject; | |||
import com.google.gson.JsonParser; | |||
import lombok.AllArgsConstructor; | |||
import me.chanjar.weixin.common.api.WxConsts; | |||
import me.chanjar.weixin.common.error.WxErrorException; | |||
import me.chanjar.weixin.common.util.http.URIUtil; | |||
import me.chanjar.weixin.common.util.json.GsonHelper; | |||
import me.chanjar.weixin.cp.api.WxCpOAuth2Service; | |||
import me.chanjar.weixin.cp.api.WxCpService; | |||
import me.chanjar.weixin.cp.bean.WxCpOauth2UserInfo; | |||
import me.chanjar.weixin.cp.bean.WxCpUserDetail; | |||
import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; | |||
import static me.chanjar.weixin.common.api.WxConsts.OAuth2Scope.SNSAPI_PRIVATEINFO; | |||
import static me.chanjar.weixin.common.api.WxConsts.OAuth2Scope.SNSAPI_USERINFO; | |||
/** | |||
* <pre> | |||
* | |||
* oauth2相关接口实现类. | |||
* Created by Binary Wang on 2017-6-25. | |||
* @author <a href="https://github.com/binarywang">Binary Wang</a> | |||
* | |||
* @author Binary Wang | |||
* </pre> | |||
* | |||
* @author <a href="https://github.com/binarywang">Binary Wang</a> | |||
*/ | |||
@AllArgsConstructor | |||
public class WxCpOAuth2ServiceImpl implements WxCpOAuth2Service { | |||
private WxCpService mainService; | |||
public WxCpOAuth2ServiceImpl(WxCpService mainService) { | |||
this.mainService = mainService; | |||
} | |||
private final WxCpService mainService; | |||
@Override | |||
public String buildAuthorizationUrl(String state) { | |||
@@ -43,50 +44,49 @@ public class WxCpOAuth2ServiceImpl implements WxCpOAuth2Service { | |||
@Override | |||
public String buildAuthorizationUrl(String redirectUri, String state, String scope) { | |||
StringBuilder url = new StringBuilder("https://open.weixin.qq.com/connect/oauth2/authorize?"); | |||
url.append("appid=").append(this.mainService.getWxCpConfigStorage().getCorpId()); | |||
StringBuilder url = new StringBuilder(WxCpOAuth2Service.URL_OAUTH_2_AUTHORIZE); | |||
url.append("?appid=").append(this.mainService.getWxCpConfigStorage().getCorpId()); | |||
url.append("&redirect_uri=").append(URIUtil.encodeURIComponent(redirectUri)); | |||
url.append("&response_type=code"); | |||
url.append("&scope=").append(scope); | |||
if (WxConsts.OAuth2Scope.SNSAPI_PRIVATEINFO.equals(scope) | |||
|| WxConsts.OAuth2Scope.SNSAPI_USERINFO.equals(scope)) { | |||
if (SNSAPI_PRIVATEINFO.equals(scope) || SNSAPI_USERINFO.equals(scope)) { | |||
url.append("&agentid=").append(this.mainService.getWxCpConfigStorage().getAgentId()); | |||
} | |||
if (state != null) { | |||
url.append("&state=").append(state); | |||
} | |||
url.append("#wechat_redirect"); | |||
return url.toString(); | |||
} | |||
@Override | |||
public String[] getUserInfo(String code) throws WxErrorException { | |||
public WxCpOauth2UserInfo getUserInfo(String code) throws WxErrorException { | |||
return this.getUserInfo(this.mainService.getWxCpConfigStorage().getAgentId(), code); | |||
} | |||
@Override | |||
public String[] getUserInfo(Integer agentId, String code) throws WxErrorException { | |||
String url = String.format("https://qyapi.weixin.qq.com/cgi-bin/user/getuserinfo?code=%s&agentid=%d", | |||
code, agentId); | |||
String responseText = this.mainService.get(url, null); | |||
public WxCpOauth2UserInfo getUserInfo(Integer agentId, String code) throws WxErrorException { | |||
String responseText = this.mainService.get(String.format(WxCpOAuth2Service.URL_GET_USER_INFO, code, agentId), null); | |||
JsonElement je = new JsonParser().parse(responseText); | |||
JsonObject jo = je.getAsJsonObject(); | |||
return new String[]{GsonHelper.getString(jo, "UserId"), | |||
GsonHelper.getString(jo, "DeviceId"), | |||
GsonHelper.getString(jo, "OpenId"), | |||
GsonHelper.getString(jo, "user_ticket"), | |||
GsonHelper.getString(jo, "expires_in") | |||
}; | |||
return WxCpOauth2UserInfo.builder() | |||
.userId(GsonHelper.getString(jo, "UserId")) | |||
.deviceId(GsonHelper.getString(jo, "DeviceId")) | |||
.openId(GsonHelper.getString(jo, "OpenId")) | |||
.userTicket(GsonHelper.getString(jo, "user_ticket")) | |||
.expiresIn(GsonHelper.getString(jo, "expires_in")) | |||
.build(); | |||
} | |||
@Override | |||
public WxCpUserDetail getUserDetail(String userTicket) throws WxErrorException { | |||
String url = "https://qyapi.weixin.qq.com/cgi-bin/user/getuserdetail"; | |||
JsonObject param = new JsonObject(); | |||
param.addProperty("user_ticket", userTicket); | |||
String responseText = this.mainService.post(url, param.toString()); | |||
String responseText = this.mainService.post(WxCpOAuth2Service.URL_GET_USER_DETAIL, param.toString()); | |||
return WxCpGsonBuilder.create().fromJson(responseText, WxCpUserDetail.class); | |||
} | |||
} |
@@ -0,0 +1,28 @@ | |||
package me.chanjar.weixin.cp.bean; | |||
import lombok.AllArgsConstructor; | |||
import lombok.Builder; | |||
import lombok.Data; | |||
import lombok.NoArgsConstructor; | |||
import lombok.experimental.Accessors; | |||
/** | |||
* <pre> | |||
* 用oauth2获取用户信息的结果类 | |||
* Created by BinaryWang on 2019/5/26. | |||
* </pre> | |||
* | |||
* @author <a href="https://github.com/binarywang">Binary Wang</a> | |||
*/ | |||
@Data | |||
@Accessors(chain = true) | |||
@NoArgsConstructor | |||
@AllArgsConstructor | |||
@Builder | |||
public class WxCpOauth2UserInfo { | |||
private String openId; | |||
private String deviceId; | |||
private String userId; | |||
private String userTicket; | |||
private String expiresIn; | |||
} |
@@ -4,10 +4,13 @@ import com.google.inject.Inject; | |||
import me.chanjar.weixin.common.error.WxErrorException; | |||
import me.chanjar.weixin.cp.api.ApiTestModule; | |||
import me.chanjar.weixin.cp.api.WxCpService; | |||
import me.chanjar.weixin.cp.bean.WxCpOauth2UserInfo; | |||
import me.chanjar.weixin.cp.bean.WxCpUserDetail; | |||
import org.testng.annotations.Guice; | |||
import org.testng.annotations.Test; | |||
import static org.assertj.core.api.Assertions.assertThat; | |||
/** | |||
* <pre> | |||
* Created by BinaryWang on 2018/4/22. | |||
@@ -28,6 +31,13 @@ public class WxCpOAuth2ServiceImplTest { | |||
@Test | |||
public void testGetUserInfo() throws WxErrorException { | |||
this.wxService.getOauth2Service().getUserInfo("abc"); | |||
final WxCpOauth2UserInfo result = this.wxService.getOauth2Service().getUserInfo("abc"); | |||
assertThat(result).isNotNull(); | |||
System.out.println(result); | |||
} | |||
@Test | |||
public void testBuildAuthorizationUrl() { | |||
} | |||
} |
@@ -2,6 +2,7 @@ package me.chanjar.weixin.cp.demo; | |||
import me.chanjar.weixin.common.error.WxErrorException; | |||
import me.chanjar.weixin.cp.api.WxCpService; | |||
import me.chanjar.weixin.cp.bean.WxCpOauth2UserInfo; | |||
import javax.servlet.http.HttpServlet; | |||
import javax.servlet.http.HttpServletRequest; | |||
@@ -30,9 +31,9 @@ public class WxCpOAuth2Servlet extends HttpServlet { | |||
response.getWriter().println("<h1>code</h1>"); | |||
response.getWriter().println(code); | |||
String[] res = this.wxCpService.getOauth2Service().getUserInfo(code); | |||
WxCpOauth2UserInfo res = this.wxCpService.getOauth2Service().getUserInfo(code); | |||
response.getWriter().println("<h1>result</h1>"); | |||
response.getWriter().println(Arrays.toString(res)); | |||
response.getWriter().println(res); | |||
} catch (WxErrorException e) { | |||
e.printStackTrace(); | |||
} | |||