Explorar o código

微信手机号登录

ximinghao hai 3 meses
pai
achega
2b37165a58

+ 11 - 0
src/main/java/com/skyversation/xjcy/controller/LoginController.java

@@ -34,6 +34,17 @@ public class LoginController {
             return MessageManage.getInstance().getResultContent(500, e.getMessage(), "未知错误");
         }
     }
+    @RequestMapping(value = "/wechatPhone", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
+    public String byWechatPhone(@RequestParam(required = false)String jsCode) {
+        try {
+            if (jsCode == null) {
+                return MessageManage.getInstance().getResultContent(-1,"缺失jsCode","缺失jsCode");
+            }
+            return authService.logOrRegWeChatPhoneAccount(jsCode);
+        } catch (Exception e) {
+            return MessageManage.getInstance().getResultContent(500, e.getMessage(), "未知错误");
+        }
+    }
     @RequestMapping(value = "/phone")
     public String byPhone(@RequestParam(required = false)String phone,@RequestParam(required = false)String code){
         try {

+ 17 - 1
src/main/java/com/skyversation/xjcy/service/AuthService.java

@@ -301,7 +301,22 @@ public class AuthService {
             return MessageManage.getInstance().getResultContent(-1, result.getError(), result.getError());
         }
     }
-
+    /**
+     * 通过微信手机号一键登录登录到OAuth系统
+     * 每个用户都会被分配一个OAuth账户,用户名与手机号关联
+     * 逻辑:尝试登录,无法登录时尝试建立OAuth账户
+     *
+     * @param jsCode wx getPhoneNumber 生成的jsCode
+     * @return 完整的response.body
+     */
+    public String logOrRegWeChatPhoneAccount(String jsCode) {
+        WeChatService.PhoneResult result = weChatService.wxPhoneLogin(jsCode);
+        if (result.isSuccess()) {
+            return logOrReg(generateAccount(result.getPhone(), PHONE_NAME_PREFIX, PHONE_PASSWORD_PREFIX, PHONE_SALT));
+        } else {
+            return MessageManage.getInstance().getResultContent(-1, result.getError(), result.getError());
+        }
+    }
     /**
      * 仅测试用<br/>
      * 无需凭证一键登录
@@ -440,6 +455,7 @@ public class AuthService {
         }
         allSuccess = allSuccess && updateRole(userContent, Collections.singletonList("41"), Collections.emptyList(), "11");
         allSuccess = allSuccess && updateRole(userContent, Collections.singletonList("45"), Collections.emptyList(), "12");
+        allSuccess = allSuccess && updateRole(userContent, Collections.singletonList("48"), Collections.emptyList(), "2");
         return allSuccess;
     }
 

+ 37 - 4
src/main/java/com/skyversation/xjcy/service/WeChatService.java

@@ -23,6 +23,7 @@ import java.util.Objects;
 
 @SuppressWarnings("SpellCheckingInspection")
 public class WeChatService {
+
     @Getter
     @AllArgsConstructor
     public static class Result {
@@ -32,6 +33,14 @@ public class WeChatService {
         private final String wxSessionKey;
     }
 
+    @Getter
+    @AllArgsConstructor
+    public static class PhoneResult {
+        private final boolean success;
+        private final String error;
+        private final String phone;
+    }
+
     @Value("${app.wechat.secret-key}")
     private String secretKey;
     @Value("${app.wechat.appid}")
@@ -43,6 +52,7 @@ public class WeChatService {
     private static final String WX_AUTH_PATH = "https://api.weixin.qq.com/sns/jscode2session";
     private static final String WX_ACCESS_KEY_PATH = "https://api.weixin.qq.com/cgi-bin/token";
     private static final String WX_ACODE_PATH = "https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=";
+    private static final String WX_PHONE_PATH = "https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_token=";
 
     public Result wxLogin(String code) {
         MultiValueMap<String, String> params = new LinkedMultiValueMap<String, String>();
@@ -56,7 +66,7 @@ public class WeChatService {
             String openId = jsonObject.getString("openid");
             String sessionKey = jsonObject.getString("session_key");
             Integer errcode = jsonObject.getInteger("errcode");
-            if (errcode == null) {
+            if (errcode == null || errcode == 0) {
                 return new Result(true, null, openId, sessionKey);
             } else {
                 return new Result(false, errcode == 40029 ? "提供的code无效" : "微信鉴权异常" + errcode, null, null);
@@ -66,6 +76,29 @@ public class WeChatService {
         }
     }
 
+    public PhoneResult wxPhoneLogin(String jsCode) {
+        String currectUrl = WX_PHONE_PATH + getAccessToken();
+
+        Map<String, String> params = new HashMap<>();
+        params.put("code", jsCode);
+        Map<String, String> headers = new HashMap<>();
+        headers.put("Content-Type", "application/json");
+        String body = new String(Objects.requireNonNull(HttpUtil.requestPostWithJson(currectUrl, params, headers).getBody()),StandardCharsets.UTF_8);
+        try {
+            JSONObject jsonObject = JSONObject.parseObject(body);
+            Integer errcode = jsonObject.getInteger("errcode");
+            if (errcode == null || errcode == 0) {
+                JSONObject phoneInfo = jsonObject.getJSONObject("phone_info");
+                String phoneNumber = phoneInfo.getString("phoneNumber");
+                return new PhoneResult(true, null, phoneNumber);
+            } else {
+                return new PhoneResult(false, errcode == 40029 ? "提供的code无效" : "微信鉴权异常" + errcode, null);
+            }
+        } catch (NullPointerException e) {
+            return new PhoneResult(false, "无法访问wx鉴权接口", null);
+        }
+    }
+
     public ResponseEntity<byte[]> createWxacode(String path, String scene) {
         Map<String, String> body = new HashMap<>();
         body.put("page", path);
@@ -76,12 +109,12 @@ public class WeChatService {
                 null
         );
 
-        if(Objects.requireNonNull(res.getHeaders().get(HttpHeaders.CONTENT_TYPE)).contains("application/json")){
+        if (Objects.requireNonNull(res.getHeaders().get(HttpHeaders.CONTENT_TYPE)).contains("application/json")) {
             if (res.getBody() != null) {
                 String json = new String(res.getBody(), StandardCharsets.UTF_8);
                 JSONObject jsonObject = JSONObject.parseObject(json);
                 String errcode = jsonObject.getString("errcode");
-                if (errcode != null&&errcode.equals("40001")) {
+                if (errcode != null && errcode.equals("40001")) {
                     refreshAccessToken();
                     res = HttpUtil.requestPostWithJson(
                             WX_ACODE_PATH + getAccessToken(),
@@ -96,7 +129,7 @@ public class WeChatService {
         copyHeader(headers, res.getHeaders(), HttpHeaders.CONTENT_TYPE);
         copyHeader(headers, res.getHeaders(), HttpHeaders.CONTENT_LENGTH);
 
-        headers.add(HttpHeaders.CACHE_CONTROL,"public, max-age=3600");
+        headers.add(HttpHeaders.CACHE_CONTROL, "public, max-age=3600");
         return new ResponseEntity<>(res.getBody(), headers, res.getStatusCode());
     }
 

+ 7 - 3
src/main/resources/application.yml

@@ -49,8 +49,12 @@ spring:
 app:
   dms:
     path: http://127.0.0.1:10081/dms
+#  wechat:
+#    appid: ungiven
+#    secret-key: ungiven
+#    enable: false
+#
   wechat:
-    appid: ungiven
-    secret-key: ungiven
-    enable: false
+    appid: ${XJCY_WECHAT_APPID:wx125843453562c86c}
+    secret-key: ${XJCY_WECHAT_SECRET:6028cc345cfdbc76224d750a13519762}
 #   微信小程序的鉴权要求统一的access token维护服务,所以在测试时不提供鉴权信息避免破坏正式环境的运行