Browse Source

增加小程序授权登录

timfruit 3 years ago
parent
commit
de21034186

+ 33 - 0
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()获取用户信息");
+        }
+    }
+
+    ;
+
+}

+ 21 - 0
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;
+
+
+}

+ 85 - 0
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();
+    }
+}

+ 13 - 6
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(31, "WECHAT_MP"), // https://www.cnblogs.com/juewuzhe/p/11905461.html
+    /**
+     * 微信开放平台 - 网站应用 pc端扫码授权登录
      */
-    WECHAT_MP(12, "WECHAT_MP"), // https://www.cnblogs.com/juewuzhe/p/11905461.html
+    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_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_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<Integer> WECHAT_ALL = ListUtil.toList(WECHAT_ENTERPRISE.type, WECHAT_MP.type, WECHAT_OPEN.type);
+    public static final List<Integer> WECHAT_ALL = ListUtil.toList(WECHAT_ENTERPRISE.type, WECHAT_MP.type, WECHAT_OPEN.type,
+            WECHAT_MINI_PROGRAM.type);
 
     /**
      * 类型

+ 10 - 1
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::