diff --git a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/compent/justauth/AuthExtendSource.java b/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/compent/justauth/AuthExtendSource.java new file mode 100644 index 000000000..e005114ac --- /dev/null +++ b/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/compent/justauth/AuthExtendSource.java @@ -0,0 +1,33 @@ +package cn.iocoder.yudao.coreservice.modules.system.compent.justauth; + +import me.zhyd.oauth.config.AuthSource; + +public enum AuthExtendSource implements AuthSource { + + /** + * 微信小程序授权登录 + */ + WECHAT_MINI_PROGRAM{ + @Override + public String authorize() { + // https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/login.html + throw new UnsupportedOperationException("不支持获取授权url, 请使用小程序内置函数wx.login()登录获取code"); + } + + @Override + public String accessToken() { + // https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/login/auth.code2Session.html + // 获取openid, unionid , session_key + return "https://api.weixin.qq.com/sns/jscode2session"; + } + + @Override + public String userInfo() { + //https://developers.weixin.qq.com/miniprogram/dev/api/open-api/user-info/wx.getUserProfile.html + throw new UnsupportedOperationException("不支持获取用户信息url, 请使用小程序内置函数wx.getUserProfile()获取用户信息"); + } + } + + ; + +} diff --git a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/compent/justauth/AuthExtendToken.java b/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/compent/justauth/AuthExtendToken.java new file mode 100644 index 000000000..b336511cb --- /dev/null +++ b/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/compent/justauth/AuthExtendToken.java @@ -0,0 +1,21 @@ +package cn.iocoder.yudao.coreservice.modules.system.compent.justauth; + +import lombok.*; +import me.zhyd.oauth.model.AuthToken; + +/** + * @author timfruit + * @date 2021-10-29 + */ +@Getter +@Setter +@NoArgsConstructor +@AllArgsConstructor +public class AuthExtendToken extends AuthToken { + /** + * 微信小程序 会话密钥 + */ + private String miniSessionKey; + + +} diff --git a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/compent/justauth/AuthWeChatMiniProgramRequest.java b/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/compent/justauth/AuthWeChatMiniProgramRequest.java new file mode 100644 index 000000000..84c920b3d --- /dev/null +++ b/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/compent/justauth/AuthWeChatMiniProgramRequest.java @@ -0,0 +1,85 @@ +package cn.iocoder.yudao.coreservice.modules.system.compent.justauth; + +import com.alibaba.fastjson.JSONObject; +import me.zhyd.oauth.cache.AuthStateCache; +import me.zhyd.oauth.config.AuthConfig; +import me.zhyd.oauth.exception.AuthException; +import me.zhyd.oauth.model.AuthCallback; +import me.zhyd.oauth.model.AuthToken; +import me.zhyd.oauth.model.AuthUser; +import me.zhyd.oauth.request.AuthDefaultRequest; +import me.zhyd.oauth.utils.HttpUtils; +import me.zhyd.oauth.utils.UrlBuilder; + +/** + * 微信小程序 + * + * @author timfruit + * @date 2021-10-29 + */ +public class AuthWeChatMiniProgramRequest extends AuthDefaultRequest { + public AuthWeChatMiniProgramRequest(AuthConfig config) { + super(config, AuthExtendSource.WECHAT_MINI_PROGRAM); + } + + public AuthWeChatMiniProgramRequest(AuthConfig config, AuthStateCache authStateCache) { + super(config, AuthExtendSource.WECHAT_MINI_PROGRAM, authStateCache); + } + + @Override + protected AuthToken getAccessToken(AuthCallback authCallback) { + // https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/login/auth.code2Session.html + String response = new HttpUtils(config.getHttpConfig()).get(accessTokenUrl(authCallback.getCode())); + JSONObject accessTokenObject = JSONObject.parseObject(response); + + this.checkResponse(accessTokenObject); + + AuthExtendToken token=new AuthExtendToken(); + token.setMiniSessionKey(accessTokenObject.getString("session_key")); + token.setOpenId(accessTokenObject.getString("openid")); + token.setUnionId(accessTokenObject.getString("unionid")); + return token; + } + + @Override + protected AuthUser getUserInfo(AuthToken authToken) { + // https://developers.weixin.qq.com/miniprogram/dev/api/open-api/user-info/wx.getUserProfile.html + // 如果需要用户信息,需要在小程序调用函数后传给后端 + return AuthUser.builder() + .uuid(authToken.getOpenId()) + //TODO 是使用默认值,还是有小程序获取用户信息 和 code 一起传过来 + .nickname("") + .avatar("") + .token(authToken) + .source(source.toString()) + .build(); + } + + /** + * 检查响应内容是否正确 + * + * @param object 请求响应内容 + */ + private void checkResponse(JSONObject object) { + int code = object.getIntValue("errcode"); + if(code != 0){ + throw new AuthException(object.getIntValue("errcode"), object.getString("errmsg")); + } + } + + /** + * 返回获取accessToken的url + * + * @param code 授权码 + * @return 返回获取accessToken的url + */ + @Override + protected String accessTokenUrl(String code) { + return UrlBuilder.fromBaseUrl(source.accessToken()) + .queryParam("appid", config.getClientId()) + .queryParam("secret", config.getClientSecret()) + .queryParam("js_code", code) + .queryParam("grant_type", "authorization_code") + .build(); + } +} diff --git a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/enums/social/SysSocialTypeEnum.java b/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/enums/social/SysSocialTypeEnum.java index 8532283c1..d36d8a727 100644 --- a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/enums/social/SysSocialTypeEnum.java +++ b/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/enums/social/SysSocialTypeEnum.java @@ -20,21 +20,28 @@ public enum SysSocialTypeEnum implements IntArrayValuable { GITEE(10, "GITEE"), // https://gitee.com/api/v5/oauth_doc#/ DINGTALK(20, "DINGTALK"), // https://developers.dingtalk.com/document/app/obtain-identity-credentials + /** + * 企业微信 + */ WECHAT_ENTERPRISE(30, "WECHAT_ENTERPRISE"), // https://xkcoding.com/2019/08/06/use-justauth-integration-wechat-enterprise.html - // TODO @timfruit:微信平台,从 30 开始递增哈。另外,尽量不要出现,先 12,然后 11,有序,嘿嘿。 /** - * 微信公众平台 - H5 + * 微信公众平台 - 移动端H5 */ - WECHAT_MP(12, "WECHAT_MP"), // https://www.cnblogs.com/juewuzhe/p/11905461.html + WECHAT_MP(31, "WECHAT_MP"), // https://www.cnblogs.com/juewuzhe/p/11905461.html /** - * 微信开放平台 - 小程序 + * 微信开放平台 - 网站应用 pc端扫码授权登录 */ - WECHAT_OPEN(11, "WECHAT_OPEN"), // https://justauth.wiki/guide/oauth/wechat_open/#_2-%E7%94%B3%E8%AF%B7%E5%BC%80%E5%8F%91%E8%80%85%E8%B5%84%E8%B4%A8%E8%AE%A4%E8%AF%81 + WECHAT_OPEN(32, "WECHAT_OPEN"), // https://justauth.wiki/guide/oauth/wechat_open/#_2-%E7%94%B3%E8%AF%B7%E5%BC%80%E5%8F%91%E8%80%85%E8%B5%84%E8%B4%A8%E8%AE%A4%E8%AF%81 + /** + * 微信小程序 + */ + WECHAT_MINI_PROGRAM(33, "WECHAT_MINI_PROGRAM"), // https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/login.html ; public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(SysSocialTypeEnum::getType).toArray(); - public static final List WECHAT_ALL = ListUtil.toList(WECHAT_ENTERPRISE.type, WECHAT_MP.type, WECHAT_OPEN.type); + public static final List WECHAT_ALL = ListUtil.toList(WECHAT_ENTERPRISE.type, WECHAT_MP.type, WECHAT_OPEN.type, + WECHAT_MINI_PROGRAM.type); /** * 类型 diff --git a/yudao-user-server/src/main/resources/application-local.yaml b/yudao-user-server/src/main/resources/application-local.yaml index 74f8abbb2..e5756b9c9 100644 --- a/yudao-user-server/src/main/resources/application-local.yaml +++ b/yudao-user-server/src/main/resources/application-local.yaml @@ -158,10 +158,19 @@ justauth: client-secret: 1wTb7hYxnpT2TUbIeHGXGo7T0odav1ic10mLdyyATOw agent-id: 1000004 ignore-check-redirect-uri: true - WECHAT_MP: # 微信公众平台 - H5 https://mp.weixin.qq.com/debug/cgi-bin/sandboxinfo?action=showinfo&t=sandbox/index + WECHAT_MP: # 微信公众平台 - 移动端H5 https://mp.weixin.qq.com/debug/cgi-bin/sandboxinfo?action=showinfo&t=sandbox/index client-id: wxa5a05b85ac361f96 client-secret: 247073c7cebb67f27f0e769195c2a57e ignore-check-redirect-uri: true + extend: + enum-class: cn.iocoder.yudao.coreservice.modules.system.compent.justauth.AuthExtendSource + config: + WECHAT_MINI_PROGRAM: # 微信小程序 扩展 + request-class: cn.iocoder.yudao.coreservice.modules.system.compent.justauth.AuthWeChatMiniProgramRequest + client-id: wx44d047d87e6284d8 + client-secret: 21c3b7a8a51ee1b8f5cf875848ed4466 + ignore-check-redirect-uri: true + ignore-check-state: true cache: type: REDIS prefix: 'social_auth_state:' # 缓存前缀,目前只对 Redis 缓存生效,默认 JUSTAUTH::STATE::