Ver código fonte

boman-wechat

shiqian 3 anos atrás
pai
commit
d8c05827fb

+ 6 - 0
boman-wechat/pom.xml

@@ -107,6 +107,12 @@
             <artifactId>boman-api-wechat</artifactId>
             <version>${project.version}</version>
         </dependency>
+
+<!--        <dependency>-->
+<!--            <groupId>com.boman</groupId>-->
+<!--            <artifactId>boman-domain</artifactId>-->
+<!--            <version>2.5.0-SNAPSHOT</version>-->
+<!--        </dependency>-->
     </dependencies>
 
     <build>

+ 30 - 0
boman-wechat/src/main/java/com/boman/wechat/controller/AppletLoginController.java

@@ -0,0 +1,30 @@
+package com.boman.wechat.controller;
+
+import com.boman.domain.AppletLoginForm;
+import com.boman.domain.dto.AjaxResult;
+import com.boman.domain.dto.AppletSessionDTO;
+import com.boman.wechat.utils.WxCodeSessionUtil;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.annotation.Resource;
+
+/**
+ * @author shiqian
+ * @date 2021年09月08日 17:29
+ **/
+@RestController
+@RequestMapping("appletLogin/")
+public class AppletLoginController {
+
+    @Resource
+    private WxCodeSessionUtil codeUtil;
+
+    @PostMapping
+    public AjaxResult appletLogin(@RequestBody AppletLoginForm form) {
+        AppletSessionDTO dto = codeUtil.jscode2Session(form);
+        return AjaxResult.success(dto);
+    }
+}

+ 36 - 49
boman-wechat/src/main/java/com/boman/wechat/controller/WechatInfoController.java

@@ -1,50 +1,37 @@
-package com.boman.wechat.controller;
-
-import com.boman.domain.dto.AjaxResult;
-import com.boman.domain.form.LoginBody;
-import com.boman.wechat.service.WechatService;
-import com.boman.wechat.service.WxPushService;
-import io.swagger.annotations.ApiOperation;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.web.bind.annotation.*;
-
-import javax.annotation.Resource;
-
-/**
- * 微信登录验证
- *
- * @author zhong.h
- */
-@RequestMapping("/wechat/p/c")
-@RestController
-public class WechatInfoController {
-
-    @Resource
-    private WxPushService wxPushService;
-
-    @Autowired
-    private WechatService wechatService;
-
-    @ApiOperation(value = "小程序相关信息获取")
-    @RequestMapping(value = "/wechatInfo", method = RequestMethod.POST)
-    public AjaxResult getWechatInfo(@RequestBody LoginBody loginBody) {
-        return wechatService.getWechatInfo(loginBody);
-    }
-
-    @ApiOperation(value = "小程序模板id获取")
-    @GetMapping("/tmpIds")
-    public AjaxResult getTmpIds() {
-        return wechatService.getTmpIds();
-    }
-
-    /**
-     * 发送消息
-     *
-     * @param dto
-     * @return
-     */
-//    @PostMapping("/pushMsg")
-//    public Map<String, Object> pushMsg(@RequestBody WxMsgDto dto) {
-//        return wxPushService.pushToUser(dto);
+//package com.boman.wechat.controller;
+//
+//import com.boman.domain.dto.AjaxResult;
+//import com.boman.domain.form.LoginBody;
+//import com.boman.wechat.service.WechatService;
+//import com.boman.wechat.service.WxPushService;
+//import io.swagger.annotations.ApiOperation;
+//import org.springframework.beans.factory.annotation.Autowired;
+//import org.springframework.web.bind.annotation.*;
+//
+//import javax.annotation.Resource;
+//
+///**
+// * 微信登录验证
+// *
+// * @author zhong.h
+// */
+//@RequestMapping("/wechat/p/c")
+//@RestController
+//public class WechatInfoController {
+//
+//    @Autowired
+//    private WechatService wechatService;
+//
+//    @ApiOperation(value = "小程序相关信息获取")
+//    @RequestMapping(value = "/wechatInfo", method = RequestMethod.POST)
+//    public AjaxResult getWechatInfo(@RequestBody LoginBody loginBody) {
+//        return wechatService.getWechatInfo(loginBody);
 //    }
-}
+//
+//    @ApiOperation(value = "小程序模板id获取")
+//    @GetMapping("/tmpIds")
+//    public AjaxResult getTmpIds() {
+//        return wechatService.getTmpIds();
+//    }
+//
+//}

+ 20 - 20
boman-wechat/src/main/java/com/boman/wechat/service/WechatService.java

@@ -1,20 +1,20 @@
-package com.boman.wechat.service;
-
-import com.boman.domain.dto.AjaxResult;
-import com.boman.domain.form.LoginBody;
-
-/**
- * 获取微信信息接口
- *
- * @author zhong.h
- */
-public interface WechatService {
-
-    AjaxResult getWechatInfo(LoginBody loginBody);
-
-    /**
-     * 获取模板id集合
-     * @return
-     */
-    AjaxResult getTmpIds();
-}
+//package com.boman.wechat.service;
+//
+//import com.boman.domain.dto.AjaxResult;
+//import com.boman.domain.form.LoginBody;
+//
+///**
+// * 获取微信信息接口
+// *
+// * @author zhong.h
+// */
+//public interface WechatService {
+//
+//    AjaxResult getWechatInfo(LoginBody loginBody);
+//
+//    /**
+//     * 获取模板id集合
+//     * @return
+//     */
+//    AjaxResult getTmpIds();
+//}

+ 142 - 142
boman-wechat/src/main/java/com/boman/wechat/service/impl/WechatServiceImpl.java

@@ -1,142 +1,142 @@
-package com.boman.wechat.service.impl;
-
-import com.alibaba.fastjson.JSON;
-import com.alibaba.fastjson.JSONObject;
-import com.boman.common.redis.RedisKey;
-import com.boman.common.redis.service.RedisService;
-import com.boman.domain.dto.AjaxResult;
-import com.boman.domain.form.LoginBody;
-import com.boman.wechat.config.WechatProperties;
-import com.boman.wechat.service.WechatService;
-import com.boman.wechat.utils.HttpClientUtils;
-import lombok.extern.slf4j.Slf4j;
-import org.apache.commons.lang3.StringUtils;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Service;
-
-import javax.annotation.Resource;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.concurrent.TimeUnit;
-
-@Slf4j
-@Service
-public class WechatServiceImpl implements WechatService {
-
-    private static final Logger logger = LoggerFactory.getLogger(WechatServiceImpl.class);
-
-    @Resource
-    private RedisService redisService;
-    @Autowired
-    private WechatProperties properties;
-
-    @Override
-    public AjaxResult getWechatInfo(LoginBody loginBody) {
-        JSONObject infoJsonObject = new JSONObject();
-        String code = loginBody.getCode();
-        // 获取openId && sessionKey
-        String openId = "";
-        // 这里的ErrorCodeEnum是自定义错误字段,可以删除,用自己的方式处理
-        String sessionKey = "";
-
-        // logger报错的话,删掉就好,或者替换为自己的日志对象
-        logger.info("Start get SessionKey,loginRequest的数据为:" + JSONObject.toJSONString(loginBody));
-        JSONObject authInfo = null;
-        try {
-            authInfo = this.getSessionKeyAndOpenId(code);
-        }catch (Exception e) {
-            return AjaxResult.error(-1, "获取信息失败");
-        }
-        // 这里的ErrorCodeEnum是自定义错误字段,可以删除,用自己的方式处理
-        if(authInfo == null) {
-            return AjaxResult.error(-1, "未获取到认证");
-        }
-        logger.info("微信返回的数据:" + authInfo.toJSONString());
-        String errMsg = this.validatWechatInfo(authInfo);
-        if(StringUtils.isNotEmpty(errMsg)) {
-            return AjaxResult.error(-1, errMsg);
-        }
-        // 获取openId && sessionKey
-        openId = authInfo.getString("openid");
-        // 这里的ErrorCodeEnum是自定义错误字段,可以删除,用自己的方式处理
-        sessionKey = authInfo.getString("session_key");
-        // 根据code保存openId和sessionKey
-        JSONObject sessionObj = new JSONObject();
-        sessionObj.put("openId", openId);
-        sessionObj.put("sessionKey", sessionKey);
-        // sessionkey 保存到redis
-        redisService.setCacheObject(RedisKey.USER_OPPEN_ID_AND_SESSION_KEY_PREFIX + code, sessionObj.toJSONString(), 10L, TimeUnit.DAYS);
-        infoJsonObject.put("unionid", authInfo.get("unionid"));
-        infoJsonObject.put("openId", openId);
-        infoJsonObject.put("sessionKey", sessionKey);
-        logger.info("微信登陆验证返回的数据: " + infoJsonObject.toJSONString());
-        return AjaxResult.successZero(infoJsonObject);
-    }
-
-    @Override
-    public AjaxResult getTmpIds() {
-        String str = properties.getTemplateId();
-        String[] ids = str.split(",");
-        return AjaxResult.success(ids);
-    }
-
-    /**
-     * 解析返回的状态码对应的问题
-     *
-     * @param authInfo
-     * @return
-     */
-    private String validatWechatInfo(JSONObject authInfo) {
-        String errMsg = "";
-        Integer errcode =  (Integer) authInfo.get("errcode");
-        if(errcode == null) {
-            return errMsg;
-        }
-        switch (errcode) {
-            case -1:
-                errMsg = "系统繁忙,此时请开发者稍候再试";
-                break;
-            case 40029:
-                errMsg = "code 无效";
-                break;
-            case 41002:
-                errMsg = "appId 丢失";
-                break;
-            case 45011:
-                errMsg = "频率限制,每个用户每分钟100次";
-            case 40163:
-                errMsg = "code已经被使用";
-                break;
-            default:
-                errMsg = (String) authInfo.get("errmsg");
-                break;
-        }
-        return errMsg;
-    }
-
-    /**
-     * 获取小程序验证信息
-     * @param code
-     * @return
-     * @throws Exception
-     */
-    private JSONObject getSessionKeyAndOpenId(String code) throws Exception {
-        Map<String, String> requestUrlParam = new HashMap<>();
-        // 小程序appId,自己补充
-        requestUrlParam.put("appid", properties.getAppId());
-        // 小程序secret,自己补充
-        requestUrlParam.put("secret", properties.getSecret());
-        // 小程序端返回的code
-        requestUrlParam.put("js_code", code);
-        // 默认参数
-        requestUrlParam.put("grant_type", properties.getGrantType());
-        // 发送post请求读取调用微信接口获取openid用户唯一标识
-        String result = HttpClientUtils.doGet(properties.getHost(), requestUrlParam);
-        if(StringUtils.isEmpty(result)) {
-            return null;
-        }
-        return JSON.parseObject(result);
-    }
-}
+//package com.boman.wechat.service.impl;
+//
+//import com.alibaba.fastjson.JSON;
+//import com.alibaba.fastjson.JSONObject;
+//import com.boman.common.redis.RedisKey;
+//import com.boman.common.redis.service.RedisService;
+//import com.boman.domain.dto.AjaxResult;
+//import com.boman.domain.form.LoginBody;
+//import com.boman.wechat.config.WechatProperties;
+//import com.boman.wechat.service.WechatService;
+//import com.boman.wechat.utils.HttpClientUtils;
+//import lombok.extern.slf4j.Slf4j;
+//import org.apache.commons.lang3.StringUtils;
+//import org.slf4j.Logger;
+//import org.slf4j.LoggerFactory;
+//import org.springframework.beans.factory.annotation.Autowired;
+//import org.springframework.stereotype.Service;
+//
+//import javax.annotation.Resource;
+//import java.util.HashMap;
+//import java.util.Map;
+//import java.util.concurrent.TimeUnit;
+//
+//@Slf4j
+//@Service
+//public class WechatServiceImpl implements WechatService {
+//
+//    private static final Logger logger = LoggerFactory.getLogger(WechatServiceImpl.class);
+//
+//    @Resource
+//    private RedisService redisService;
+//    @Autowired
+//    private WechatProperties properties;
+//
+//    @Override
+//    public AjaxResult getWechatInfo(LoginBody loginBody) {
+//        JSONObject infoJsonObject = new JSONObject();
+//        String code = loginBody.getCode();
+//        // 获取openId && sessionKey
+//        String openId = "";
+//        // 这里的ErrorCodeEnum是自定义错误字段,可以删除,用自己的方式处理
+//        String sessionKey = "";
+//
+//        // logger报错的话,删掉就好,或者替换为自己的日志对象
+//        logger.info("Start get SessionKey,loginRequest的数据为:" + JSONObject.toJSONString(loginBody));
+//        JSONObject authInfo = null;
+//        try {
+//            authInfo = this.getSessionKeyAndOpenId(code);
+//        }catch (Exception e) {
+//            return AjaxResult.error(-1, "获取信息失败");
+//        }
+//        // 这里的ErrorCodeEnum是自定义错误字段,可以删除,用自己的方式处理
+//        if(authInfo == null) {
+//            return AjaxResult.error(-1, "未获取到认证");
+//        }
+//        logger.info("微信返回的数据:" + authInfo.toJSONString());
+//        String errMsg = this.validatWechatInfo(authInfo);
+//        if(StringUtils.isNotEmpty(errMsg)) {
+//            return AjaxResult.error(-1, errMsg);
+//        }
+//        // 获取openId && sessionKey
+//        openId = authInfo.getString("openid");
+//        // 这里的ErrorCodeEnum是自定义错误字段,可以删除,用自己的方式处理
+//        sessionKey = authInfo.getString("session_key");
+//        // 根据code保存openId和sessionKey
+//        JSONObject sessionObj = new JSONObject();
+//        sessionObj.put("openId", openId);
+//        sessionObj.put("sessionKey", sessionKey);
+//        // sessionkey 保存到redis
+//        redisService.setCacheObject(RedisKey.USER_OPPEN_ID_AND_SESSION_KEY_PREFIX + code, sessionObj.toJSONString(), 10L, TimeUnit.DAYS);
+//        infoJsonObject.put("unionid", authInfo.get("unionid"));
+//        infoJsonObject.put("openId", openId);
+//        infoJsonObject.put("sessionKey", sessionKey);
+//        logger.info("微信登陆验证返回的数据: " + infoJsonObject.toJSONString());
+//        return AjaxResult.successZero(infoJsonObject);
+//    }
+//
+//    @Override
+//    public AjaxResult getTmpIds() {
+//        String str = properties.getTemplateId();
+//        String[] ids = str.split(",");
+//        return AjaxResult.success(ids);
+//    }
+//
+//    /**
+//     * 解析返回的状态码对应的问题
+//     *
+//     * @param authInfo
+//     * @return
+//     */
+//    private String validatWechatInfo(JSONObject authInfo) {
+//        String errMsg = "";
+//        Integer errcode =  (Integer) authInfo.get("errcode");
+//        if(errcode == null) {
+//            return errMsg;
+//        }
+//        switch (errcode) {
+//            case -1:
+//                errMsg = "系统繁忙,此时请开发者稍候再试";
+//                break;
+//            case 40029:
+//                errMsg = "code 无效";
+//                break;
+//            case 41002:
+//                errMsg = "appId 丢失";
+//                break;
+//            case 45011:
+//                errMsg = "频率限制,每个用户每分钟100次";
+//            case 40163:
+//                errMsg = "code已经被使用";
+//                break;
+//            default:
+//                errMsg = (String) authInfo.get("errmsg");
+//                break;
+//        }
+//        return errMsg;
+//    }
+//
+//    /**
+//     * 获取小程序验证信息
+//     * @param code
+//     * @return
+//     * @throws Exception
+//     */
+//    private JSONObject getSessionKeyAndOpenId(String code) throws Exception {
+//        Map<String, String> requestUrlParam = new HashMap<>();
+//        // 小程序appId,自己补充
+//        requestUrlParam.put("appid", properties.getAppId());
+//        // 小程序secret,自己补充
+//        requestUrlParam.put("secret", properties.getSecret());
+//        // 小程序端返回的code
+//        requestUrlParam.put("js_code", code);
+//        // 默认参数
+//        requestUrlParam.put("grant_type", properties.getGrantType());
+//        // 发送post请求读取调用微信接口获取openid用户唯一标识
+//        String result = HttpClientUtils.doGet(properties.getHost(), requestUrlParam);
+//        if(StringUtils.isEmpty(result)) {
+//            return null;
+//        }
+//        return JSON.parseObject(result);
+//    }
+//}

+ 20 - 0
boman-wechat/src/main/java/com/boman/wechat/utils/HttpClientUtils.java

@@ -83,6 +83,26 @@ public class HttpClientUtils {
         return resultString;
     }
 
+    public static String doGet1(String url) throws IOException {
+        // 创建Httpclient对象
+        CloseableHttpClient httpClient = HttpClients.createDefault();
+        CloseableHttpResponse response = null;
+        String resultString = "";
+        try {
+            // 创建Http Post请求
+            HttpGet httpGet = new HttpGet(url);
+            // 执行http请求
+            response = httpClient.execute(httpGet);
+            resultString = EntityUtils.toString(response.getEntity(), "UTF-8");
+        } catch (Exception e) {
+            throw e;
+        } finally {
+            assert response != null;
+            response.close();
+        }
+        return resultString;
+    }
+
     private static RequestConfig builderRequestConfig() {
         return RequestConfig.custom()
                 .setConnectTimeout(TIMEOUT_MSEC)

+ 115 - 0
boman-wechat/src/main/java/com/boman/wechat/utils/WxCodeSessionUtil.java

@@ -0,0 +1,115 @@
+package com.boman.wechat.utils;
+
+
+import com.alibaba.fastjson.JSONObject;
+import com.boman.domain.AppletLoginForm;
+import com.boman.domain.dto.AppletSessionDTO;
+import com.boman.domain.utils.AppletDecryptDataUtil;
+import com.boman.domain.utils.Base64;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.cloud.context.config.annotation.RefreshScope;
+import org.springframework.stereotype.Component;
+
+/**
+ *
+ */
+@Component
+@Slf4j
+@RefreshScope
+public class WxCodeSessionUtil {
+
+
+    /**
+     * 根据code获取小程序openid和unionid
+     */
+    private static final String JSCODE_SESSION_API = "https://api.weixin.qq.com/sns/jscode2session?appid=APPID&secret=SECRET&js_code=JSCODE&grant_type=authorization_code";
+
+    /**
+     * 小程序appId
+     */
+    @Value("${wx.appId}")
+    private String appId;
+
+    /**
+     * 小程序密钥
+     */
+    @Value("${wx.appSecret}")
+    private String appSecret;
+
+
+    /**
+     * 根据code获取小程序openid和unionid
+     *
+     * @param form
+     * @return
+     */
+    public AppletSessionDTO jscode2Session(AppletLoginForm form) {
+        // 获取openId和sessionKey
+        JSONObject result;
+        try {
+            String requestUrl = JSCODE_SESSION_API.replace("APPID", this.appId)
+                    .replace("SECRET", this.appSecret)
+                    .replace("JSCODE", form.getCode().trim());
+
+            String jsonStr = HttpClientUtils.doGet1(requestUrl);
+            result = JSONObject.parseObject(jsonStr);
+            if (StringUtils.isEmpty(result.toString())) {
+                throw new RuntimeException("错误");
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+            throw new RuntimeException("错误");
+        }
+
+        int errcode = result.getIntValue("errcode");
+        if (errcode != 0) {
+            String errmsg = result.getString("errmsg");
+            throw new RuntimeException("获取小程序授权错误信息, " + errmsg);
+        }
+        // 获取openId,unionId,sessionKey
+        AppletSessionDTO appletSession = new AppletSessionDTO();
+        appletSession.setOpenId(result.getString("openid"));
+        // unionId有可能是空
+        appletSession.setUnionId(result.getString("unionid"));
+        appletSession.setSessionKey(result.getString("session_key"));
+
+        String phoneNumber = getPhoneNumber(form, appletSession);
+        appletSession.setPhoneNumber(phoneNumber);
+        return appletSession;
+    }
+
+    /**
+     * 手机号解密
+     */
+    private String getPhoneNumber(AppletLoginForm form, AppletSessionDTO appletSession) {
+
+        // 解密文件
+        String encryptedData = form.getEncryptedData();
+        // 解密向量
+        String iv = form.getIv();
+        // 加密秘钥
+        byte[] dataByte = Base64.decode(encryptedData);
+        // session_key
+        byte[] keyByte = Base64.decode(appletSession.getSessionKey());
+        // 偏移量
+        byte[] ivByte = Base64.decode(iv);
+        JSONObject result;
+        try {
+            result = AppletDecryptDataUtil.decryptData(keyByte, ivByte, dataByte);
+        } catch (Exception e) {
+            e.printStackTrace();
+            return null;
+        }
+
+        assert result != null;
+        String purePhoneNumber = result.getString("purePhoneNumber");
+        if (null == purePhoneNumber || purePhoneNumber.isEmpty()) {
+            throw new RuntimeException("获取手机号失败");
+        }
+        return purePhoneNumber;
+    }
+
+
+}

+ 3 - 3
boman-wechat/src/main/resources/bootstrap.yml

@@ -5,15 +5,15 @@ spring:
   application:
     name: boman-wechat
   profiles:
-    active: jiaoyu
+    active: dev
   cloud:
     nacos:
       discovery:
         server-addr: 192.168.101.10:8848
-        namespace: d8110874-ad03-4826-80bc-ff00126c1644  #潜山教育
+        namespace: 0886e975-9ff6-4602-8ed2-f17b4d0ef1bc  #潜山数据
       config:
         server-addr: 192.168.101.10:8848
         file-extension: yml
         shared-configs:
           - application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}
-        namespace: d8110874-ad03-4826-80bc-ff00126c1644  #潜山教育
+        namespace: 0886e975-9ff6-4602-8ed2-f17b4d0ef1bc  #潜山数据