仰望星空〃 8 ヶ月 前
コミット
f4a869abd8

+ 6 - 0
bus-biz/src/main/java/bus/service/impl/WChatUserServiceImpl.java

@@ -64,6 +64,12 @@ public class WChatUserServiceImpl implements WChatUserService {
     private String productNo;
     @Resource
     private SnowflakeUtil snowflakeUtil;
+
+    // Redis key
+    private static final String WX_ACCESS_TOKEN_KEY = "wx:access_token";
+    // access_token 有效期为 7200 秒,我们设置缓存时间为 7000 秒,留出一些余量
+    private static final long ACCESS_TOKEN_EXPIRE = 7000L;
+
     @Override
     public SsoUserAuthDto wxLogin(HttpServletRequest request, HttpServletResponse response, WxLoginReq wxLoginReq) {
         //根据用户名称查询底座接口

+ 1 - 1
bus-boot/src/main/resources/bootstrap-dev.yaml

@@ -6,7 +6,7 @@ server:
 spring:
   datasource:
     driver-class-name: com.mysql.cj.jdbc.Driver
-    url: jdbc:mysql://matrix34.tpddns.cn:13306/bus_allot?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
+    url: jdbc:mysql://metapixels.top:13306/bus_allot?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
     username: root
     password: 9a41012499f38251
 

+ 11 - 0
bus-common/src/main/java/bus/model/vo/WXDecrypt.java

@@ -0,0 +1,11 @@
+package bus.model.vo;
+
+import lombok.Data;
+
+@Data
+public class WXDecrypt {
+
+    private String  unionId;
+
+    private String  phoneNumber;
+}

+ 14 - 0
bus-common/src/main/java/bus/model/vo/WxEncryptedData.java

@@ -0,0 +1,14 @@
+package bus.model.vo;
+
+import lombok.Data;
+
+@Data
+public class WxEncryptedData {
+
+    private String  encryptedData;
+
+    private String  sessionKey;
+
+    private String  iv;
+
+}

+ 123 - 0
bus-web/src/main/java/bus/controller/biz/WChatUserController.java

@@ -1,9 +1,12 @@
 package bus.controller.biz;
 
 import bus.model.dto.req.WxLoginReq;
+import bus.model.vo.WXDecrypt;
+import bus.model.vo.WxEncryptedData;
 import cn.hutool.core.util.StrUtil;
 import cn.hutool.http.HttpUtil;
 import cn.hutool.json.JSONObject;
+import cn.hutool.json.JSONUtil;
 import com.alibaba.fastjson.JSON;
 import com.github.pagehelper.PageHelper;
 import com.github.pagehelper.PageSerializable;
@@ -18,14 +21,21 @@ import com.sun.jndi.toolkit.url.UrlUtil;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.codec.binary.Base64;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.redis.core.StringRedisTemplate;
 import org.springframework.web.bind.annotation.*;
 import com.qzwisdom.qzframework.core.tool.base.controller.BaseController;
 
+import javax.crypto.Cipher;
+import javax.crypto.spec.IvParameterSpec;
+import javax.crypto.spec.SecretKeySpec;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
+import java.security.AlgorithmParameters;
 import java.util.HashMap;
 import java.util.Map;
+import java.util.concurrent.TimeUnit;
 
 
 /**
@@ -51,6 +61,43 @@ public class WChatUserController implements BaseController {
 
     private static final String ERROR_CODE_STR = "errcode";
 
+    @Autowired
+    private  StringRedisTemplate stringRedisTemplate;
+
+    private static final String WX_ACCESS_TOKEN_KEY = "wx:access_token";
+    // access_token 有效期为 7200 秒,我们设置缓存时间为 7000 秒,留出一些余量
+    private static final long ACCESS_TOKEN_EXPIRE = 7000L;
+
+    private String getAccessToken() {
+        // 先从Redis获取
+        String accessToken = stringRedisTemplate.opsForValue().get(WX_ACCESS_TOKEN_KEY);
+        if (StrUtil.isNotBlank(accessToken)) {
+            return accessToken;
+        }
+        // Redis中不存在,则从微信服务器获取
+        String accessTokenUrl = "https://api.weixin.qq.com/cgi-bin/token" +
+                "?grant_type=client_credential" +
+                "&appid=" + appId +
+                "&secret=" + appSecret;
+
+        String tokenJson = HttpUtil.get(accessTokenUrl, TIME_OUT);
+        JSONObject tokenObj = new JSONObject(tokenJson);
+        if (tokenObj.get(ERROR_CODE_STR) != null && tokenObj.get(ERROR_CODE_STR, Integer.class) != 0) {
+            throw new BusinessException("获取access_token失败");
+        }
+
+        // 获取新的access_token
+        accessToken = tokenObj.getStr("access_token");
+        // 存入Redis并设置过期时间
+        stringRedisTemplate.opsForValue().set(
+                WX_ACCESS_TOKEN_KEY,
+                accessToken,
+                ACCESS_TOKEN_EXPIRE,
+                TimeUnit.SECONDS
+        );
+        return accessToken;
+    }
+
     @RequestMapping(value = "/auto/login", method = RequestMethod.POST)
     @ApiOperation(value = "小程序登陆调用")
     public SsoUserAuthDto wxLogin(HttpServletRequest request, HttpServletResponse response,
@@ -88,7 +135,49 @@ public class WChatUserController implements BaseController {
         return map;
     }
 
+    @RequestMapping(value = "/getPhoneNumber", method = RequestMethod.POST)
+    @ApiOperation(value = "新板本-获取微信小程序手机号")
+    public String getPhoneNumber(@RequestParam(required = true) String code) {
+        if (StrUtil.isBlank(code)) {
+            throw new BusinessException("code不能为空");
+        }
+
+        String accessToken = getAccessToken();
+        String phoneUrl = "https://api.weixin.qq.com/wxa/business/getuserphonenumber" +
+                "?access_token=" + accessToken;
 
+        Map<String, Object> paramMap = new HashMap<>();
+        paramMap.put("code", code);
+        String phoneJson = HttpUtil.post(phoneUrl, JSON.toJSONString(paramMap));
+
+        JSONObject phoneObj = new JSONObject(phoneJson);
+        if (phoneObj.get(ERROR_CODE_STR) != null && phoneObj.get(ERROR_CODE_STR, Integer.class) != 0) {
+            throw new BusinessException("获取手机号失败");
+        }
+        return phoneJson;
+    }
+
+    @ApiOperation(value = "老板本-解密获取手机号")
+    @RequestMapping(value = "/encryptedData", method = RequestMethod.POST)
+    @ResponseBody
+    public WXDecrypt encryptedData(@RequestBody WxEncryptedData wxEncryptedData) throws Exception {
+        // 第一个,加密数据串(String);
+        // 第二个,session_key需要通过微信小程序的code获得(String);
+        // 第三个,数据加密时所使用的偏移量,解密时需要使用(String);第四个,编码
+        String encryptedData = wxEncryptedData.getEncryptedData();
+        String sessionKey = wxEncryptedData.getSessionKey();
+        String iv = wxEncryptedData.getIv();
+
+        String result = decrypt(encryptedData, sessionKey, iv, "UTF-8");
+
+        if (null != result && result.length() > 0) {
+            // 将解密后的JSON格式字符串转化为对象
+            WXDecrypt wxDecrypt = JSONUtil.toBean(result, WXDecrypt.class);
+            return wxDecrypt;
+        } else {
+            return null;
+        }
+    }
 
     /**
      * 详情
@@ -127,4 +216,38 @@ public class WChatUserController implements BaseController {
 //        return "删除成功";
 //    }
 
+    /**
+     * 解密
+     * @param data
+     * @param key
+     * @param iv
+     * @param encodingFormat
+     * @return
+     * @throws Exception
+     */
+    public static String decrypt(String data, String key, String iv, String encodingFormat) throws Exception {
+        // 被加密的数据
+        byte[] dataByte = Base64.decodeBase64(data);
+        // 加密秘钥
+        byte[] keyByte = Base64.decodeBase64(key);
+        // 偏移量
+        byte[] ivByte = Base64.decodeBase64(iv);
+        try {
+            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding");
+            SecretKeySpec spec = new SecretKeySpec(keyByte, "AES");
+            AlgorithmParameters parameters = AlgorithmParameters.getInstance("AES");
+            parameters.init(new IvParameterSpec(ivByte));
+            cipher.init(Cipher.DECRYPT_MODE, spec, parameters);// 初始化
+            byte[] resultByte = cipher.doFinal(dataByte);
+            if (null != resultByte && resultByte.length > 0) {
+                String result = new String(resultByte, encodingFormat);
+                return result;
+            }
+            return null;
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return null;
+    }
+
 }