From b78b51d384a3c4d9880ba604ebe35f40de8c527f Mon Sep 17 00:00:00 2001
From: sjm <1191068887@qq.com>
Date: Thu, 10 Aug 2023 19:02:21 +0800
Subject: [PATCH] =?UTF-8?q?=E5=B0=8F=E7=A8=8B=E5=BA=8F=E7=99=BB=E5=BD=95?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../web/core/config/H5MemberInterceptor.java | 1 +
.../ruoyi/common/utils/AesCryptoUtils.java | 2 +
ruoyi-mall/pom.xml | 5 ++
.../config/AESForWeixinGetPhoneNumber.java | 80 +++++++++++++++++++
.../cyl/h5/controller/H5MemberController.java | 17 +++-
.../java/com/cyl/h5/pojo/dto/H5LoginDTO.java | 12 +++
.../com/cyl/h5/service/H5MemberService.java | 55 +++++++++++++
.../com/cyl/h5/service/H5OrderService.java | 2 +-
8 files changed, 169 insertions(+), 5 deletions(-)
create mode 100644 ruoyi-mall/src/main/java/com/cyl/config/AESForWeixinGetPhoneNumber.java
create mode 100644 ruoyi-mall/src/main/java/com/cyl/h5/pojo/dto/H5LoginDTO.java
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/core/config/H5MemberInterceptor.java b/ruoyi-admin/src/main/java/com/ruoyi/web/core/config/H5MemberInterceptor.java
index 6759cb6..8cbe353 100644
--- a/ruoyi-admin/src/main/java/com/ruoyi/web/core/config/H5MemberInterceptor.java
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/core/config/H5MemberInterceptor.java
@@ -25,6 +25,7 @@ public class H5MemberInterceptor extends HandlerInterceptorAdapter {
private static String[] WHITE_PATHS = {
"/h5/sms/login",
+ "/h5/wechat/login",
"/h5/account/login",
"/h5/register",
"/h5/validate"
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/AesCryptoUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/AesCryptoUtils.java
index e509e42..e908fd3 100644
--- a/ruoyi-common/src/main/java/com/ruoyi/common/utils/AesCryptoUtils.java
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/AesCryptoUtils.java
@@ -10,6 +10,7 @@ import cn.hutool.crypto.symmetric.AES;
public class AesCryptoUtils {
public static String encrypt(String key, String content){
+ SecureUtil.disableBouncyCastle();
if (StringUtils.isBlank(key) || StringUtils.isBlank(content)){
throw new RuntimeException("错误");
}
@@ -19,6 +20,7 @@ public class AesCryptoUtils {
}
public static String decrypt(String key, String content){
+ SecureUtil.disableBouncyCastle();
if (StringUtils.isBlank(key) || StringUtils.isBlank(content)){
throw new RuntimeException("错误");
}
diff --git a/ruoyi-mall/pom.xml b/ruoyi-mall/pom.xml
index 30f6a37..1f10156 100644
--- a/ruoyi-mall/pom.xml
+++ b/ruoyi-mall/pom.xml
@@ -62,6 +62,11 @@
junit
test
+
+ org.bouncycastle
+ bcprov-jdk15to18
+ 1.64
+
org.springframework
spring-test
diff --git a/ruoyi-mall/src/main/java/com/cyl/config/AESForWeixinGetPhoneNumber.java b/ruoyi-mall/src/main/java/com/cyl/config/AESForWeixinGetPhoneNumber.java
new file mode 100644
index 0000000..0d308a0
--- /dev/null
+++ b/ruoyi-mall/src/main/java/com/cyl/config/AESForWeixinGetPhoneNumber.java
@@ -0,0 +1,80 @@
+package com.cyl.config;
+
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
+import org.bouncycastle.jce.provider.BouncyCastleProvider;
+
+import javax.crypto.Cipher;
+import javax.crypto.spec.IvParameterSpec;
+import javax.crypto.spec.SecretKeySpec;
+import java.nio.charset.StandardCharsets;
+import java.security.AlgorithmParameters;
+import java.security.Key;
+import java.security.NoSuchAlgorithmException;
+import java.security.Security;
+import java.security.spec.InvalidParameterSpecException;
+import java.util.Base64;
+
+public class AESForWeixinGetPhoneNumber {
+ //加密方式
+ private static String keyAlgorithm = "AES";
+ //避免重复new生成多个BouncyCastleProvider对象,因为GC回收不了,会造成内存溢出
+ //只在第一次调用decrypt()方法时才new 对象
+ private static boolean initialized = false;
+ //用于Base64解密
+ private Base64.Decoder decoder = Base64.getDecoder();
+
+ //待解密的数据
+ private String originalContent;
+ //会话密钥sessionKey
+ private String encryptKey;
+ //加密算法的初始向量
+ private String iv;
+
+ public AESForWeixinGetPhoneNumber(String originalContent, String encryptKey, String iv) {
+ this.originalContent = originalContent;
+ this.encryptKey = encryptKey;
+ this.iv = iv;
+ }
+
+ /**
+ * AES解密
+ * 填充模式AES/CBC/PKCS7Padding
+ * 解密模式128
+ *
+ * @return 解密后的信息对象
+ */
+ public JSONObject decrypt() {
+ initialize();
+ try {
+ //数据填充方式
+ Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding","BC");
+// Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding");
+ Key sKeySpec = new SecretKeySpec(decoder.decode(this.encryptKey), keyAlgorithm);
+ // 初始化
+ cipher.init(Cipher.DECRYPT_MODE, sKeySpec, generateIV(decoder.decode(this.iv)));
+ byte[]data = cipher.doFinal(decoder.decode(this.originalContent));
+ String datastr = new String(data, StandardCharsets.UTF_8);
+ return JSON.parseObject(datastr);
+ } catch (Exception e) {
+ e.printStackTrace();
+ return null;
+ }
+ }
+
+ /**BouncyCastle作为安全提供,防止我们加密解密时候因为jdk内置的不支持改模式运行报错。**/
+ private static void initialize() {
+ if (initialized) {
+ return;
+ }
+ Security.addProvider(new BouncyCastleProvider());
+ initialized = true;
+ }
+
+ // 生成iv
+ private static AlgorithmParameters generateIV(byte[] iv) throws NoSuchAlgorithmException, InvalidParameterSpecException {
+ AlgorithmParameters params = AlgorithmParameters.getInstance(keyAlgorithm);
+ params.init(new IvParameterSpec(iv));
+ return params;
+ }
+}
diff --git a/ruoyi-mall/src/main/java/com/cyl/h5/controller/H5MemberController.java b/ruoyi-mall/src/main/java/com/cyl/h5/controller/H5MemberController.java
index 46f17a6..cb4d62f 100644
--- a/ruoyi-mall/src/main/java/com/cyl/h5/controller/H5MemberController.java
+++ b/ruoyi-mall/src/main/java/com/cyl/h5/controller/H5MemberController.java
@@ -1,20 +1,20 @@
package com.cyl.h5.controller;
+import com.alibaba.fastjson.JSON;
+import com.cyl.h5.pojo.dto.H5LoginDTO;
import com.cyl.h5.pojo.request.RegisterRequest;
import com.cyl.h5.pojo.response.RegisterResponse;
import com.cyl.h5.pojo.response.ValidatePhoneResponse;
import com.cyl.h5.pojo.response.H5LoginResponse;
import com.cyl.h5.service.H5MemberService;
import com.cyl.manager.ums.pojo.vo.MemberVO;
-import com.cyl.wechat.WechatAuthService;
-import com.cyl.wechat.response.WechatUserAuth;
-import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.domain.model.LoginMember;
-import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.framework.web.service.TokenService;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
+import org.springframework.util.Base64Utils;
+import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
@@ -47,6 +47,15 @@ public class H5MemberController {
return ResponseEntity.ok(service.accountLogin(data));
}
+ @PostMapping("/wechat/login")
+ public ResponseEntity wechatLogin(String data) throws Exception {
+ if (StringUtils.isEmpty(data)) {
+ return ResponseEntity.ok(null);
+ }
+ H5LoginDTO params = JSON.parseObject(new String(Base64Utils.decodeFromString(data)), H5LoginDTO.class);
+ return ResponseEntity.ok(service.wechatLogin(params));
+ }
+
@ApiOperation("sms登录")
@PostMapping("/sms/login")
public ResponseEntity smsLogin(@RequestBody String data){
diff --git a/ruoyi-mall/src/main/java/com/cyl/h5/pojo/dto/H5LoginDTO.java b/ruoyi-mall/src/main/java/com/cyl/h5/pojo/dto/H5LoginDTO.java
new file mode 100644
index 0000000..74d4977
--- /dev/null
+++ b/ruoyi-mall/src/main/java/com/cyl/h5/pojo/dto/H5LoginDTO.java
@@ -0,0 +1,12 @@
+package com.cyl.h5.pojo.dto;
+
+import lombok.Data;
+
+@Data
+public class H5LoginDTO {
+
+ private String data;
+ private String key;
+ private String sessionKey;
+ private String openId;
+}
diff --git a/ruoyi-mall/src/main/java/com/cyl/h5/service/H5MemberService.java b/ruoyi-mall/src/main/java/com/cyl/h5/service/H5MemberService.java
index 49ba446..89acf2c 100644
--- a/ruoyi-mall/src/main/java/com/cyl/h5/service/H5MemberService.java
+++ b/ruoyi-mall/src/main/java/com/cyl/h5/service/H5MemberService.java
@@ -3,8 +3,11 @@ package com.cyl.h5.service;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
+import com.cyl.config.AESForWeixinGetPhoneNumber;
+import com.cyl.h5.pojo.dto.H5LoginDTO;
import com.cyl.h5.pojo.request.BindOpenIdRequest;
import com.cyl.h5.pojo.request.H5AccountLoginRequest;
import com.cyl.h5.pojo.request.H5SmsLoginRequest;
@@ -329,4 +332,56 @@ public class H5MemberService {
memberLogininfor.setLoginTime(LocalDateTime.now());
memberLogininforMapper.insert(memberLogininfor);
}
+
+ public H5LoginResponse wechatLogin(H5LoginDTO params) throws Exception {
+ String openId = params.getOpenId();
+ String sessionKey = params.getSessionKey();
+ //解密手机号
+ String mobile = getMobile(sessionKey, params.getKey(), params.getData());
+ if(StringUtils.isEmpty(mobile)) {
+ throw new Exception("登录异常");
+ }
+ Member member = createOrUpdateMember(openId,mobile);
+ return getLoginResponse(member.getId());
+ }
+
+ private Member createOrUpdateMember(String openId,String mobile){
+ //查会员
+ QueryWrapper qw = new QueryWrapper<>();
+ qw.eq("phone_encrypted", AesCryptoUtils.encrypt(aesKey, mobile));
+ Member member = memberMapper.selectOne(qw);
+ if (member == null){
+ //新会员,注册并登录
+ member = new Member();
+ member.setPhoneEncrypted(AesCryptoUtils.encrypt(aesKey, mobile));
+ member.setPhoneHidden(PhoneUtils.hidePhone(mobile));
+ member.setNickname("用户" + mobile.substring(7,11));
+ member.setStatus(Constants.MEMBER_ACCOUNT_STATUS.NORMAL);
+ member.setGender(0);
+ member.setCreateTime(LocalDateTime.now());
+ int rows = memberMapper.insert(member);
+ if (rows < 1){
+ throw new RuntimeException("注册失败,请重试");
+ }
+ MemberWechat memberWechat = new MemberWechat();
+ memberWechat.setMemberId(member.getId());
+ memberWechat.setRoutineOpenid(openId);
+ memberWechat.setCreateTime(LocalDateTime.now());
+ memberWechat.setCreateBy(member.getId());
+ rows = memberWechatMapper.insert(memberWechat);
+ if (rows < 1){
+ throw new RuntimeException("注册失败,请重试");
+ }
+ }
+ return member;
+ }
+
+ private String getMobile(String sessionKey, String key, String data) {
+ AESForWeixinGetPhoneNumber aes = new AESForWeixinGetPhoneNumber(data, sessionKey, key);
+ JSONObject decrypt = aes.decrypt();
+ if (decrypt != null) {
+ return decrypt.getString("phoneNumber");
+ }
+ return null;
+ }
}
diff --git a/ruoyi-mall/src/main/java/com/cyl/h5/service/H5OrderService.java b/ruoyi-mall/src/main/java/com/cyl/h5/service/H5OrderService.java
index 6bc5c8d..596ae77 100644
--- a/ruoyi-mall/src/main/java/com/cyl/h5/service/H5OrderService.java
+++ b/ruoyi-mall/src/main/java/com/cyl/h5/service/H5OrderService.java
@@ -472,7 +472,7 @@ public class H5OrderService {
//保存微信支付历史
LocalDateTime optDate = LocalDateTime.now();
QueryWrapper wxPaymentQw = new QueryWrapper<>();
- wxPaymentQw.eq("order_id", orderList.get(0).getId());
+ wxPaymentQw.eq("order_id", orderList.get(0).getPayId());
wxPaymentQw.eq("op_type", Constants.PaymentOpType.PAY);
WechatPaymentHistory wechatPaymentHistory = wechatPaymentHistoryMapper.selectOne(wxPaymentQw);
if (wechatPaymentHistory == null){