yangdamao 2 minggu lalu
induk
melakukan
440e73f594

+ 7 - 0
zhichen-api/src/main/java/com/zhichen/controller/user/LoginController.java

@@ -80,4 +80,11 @@ public class LoginController extends BaseController {
         iUserService.account_loginOutRecord(bo);
         return AjaxResult.success();
     }
+
+    @ApiOperation("预约估分账号登录")
+    @PostMapping("/score/account_login")
+    public AjaxResult scoreAccount_login(@RequestBody UserAppAccountLoginBo bo) {
+        Map<String,Object> map = iUserService.liveAccount_login(bo);
+        return AjaxResult.success(map);
+    }
 }

+ 65 - 0
zhichen-api/src/main/java/com/zhichen/controller/wx/WeChatJsApiController.java

@@ -0,0 +1,65 @@
+package com.zhichen.controller.wx;
+
+
+import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
+import com.github.xiaoymin.knife4j.annotations.ApiSupport;
+import com.zhichen.common.core.domain.AjaxResult;
+import com.zhichen.common.core.redis.RedisCache;
+import com.zhichen.framework.web.service.WeChatSignatureService;
+import io.swagger.annotations.Api;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
+
+@Api(tags ="微信配置管理")
+@ApiSupport(order = 2)
+@RestController
+public class WeChatJsApiController {
+
+    @Autowired
+    private WeChatSignatureService signatureService;
+    @Autowired
+    private RedisCache redisCache;
+
+    /**
+     * 获取JS-SDK配置
+     * 前端调用这个接口获取config配置
+     */
+    @GetMapping("/app/common/wechat/getJsConfig")
+    public AjaxResult getJsConfig(@RequestParam String url) {
+        // 注意:URL必须是当前页面的完整URL(不包含#后面的部分)
+        // 前端传递:window.location.href.split('#')[0]
+
+        Map<String, String> config = signatureService.generateSignature(url);
+
+        // 可选:添加调试信息
+        config.put("debug", "false");
+
+        return AjaxResult.success(config);
+    }
+
+    /**
+     * 获取配置(带缓存版本)
+     */
+    @GetMapping("/app/common/wechat/getJsConfigWithCache")
+    public AjaxResult getJsConfigWithCache(@RequestParam String url) {
+        // 使用缓存,避免频繁调用微信接口
+        String cacheKey = "wechat:js_config:" + url;
+        Map<String, String> cached = redisCache.getCacheMap(cacheKey);
+
+        if (CollectionUtils.isNotEmpty(cached)) {
+            return AjaxResult.success(cached);
+        }
+
+        Map<String, String> config = signatureService.generateSignature(url);
+
+        // 缓存7000秒(小于7200秒)
+        redisCache.setCacheObject(cacheKey, config, 7000, TimeUnit.SECONDS);
+
+        return AjaxResult.success(config);
+    }
+}

+ 14 - 0
zhichen-api/src/main/java/com/zhichen/controller/wx/WxLoginController.java

@@ -209,4 +209,18 @@ public class WxLoginController
         Map<String,String> map = wxLoginService.checkGzh_openId(loginBody);
         return AjaxResult.success(map);
     }
+
+    /**
+     * 一建扫码直播公众号登录
+     *
+     * @param loginBody 一建扫码直播公众号登录
+     * @return 结果
+     */
+    @ApiOperation("一建扫码直播公众号登录")
+    @PostMapping("/app/common/score/gzh_login")
+    public AjaxResult score_login(@RequestBody WxLoginBody loginBody)
+    {
+        Map<String,String> map = wxLoginService.liveGzh_login(loginBody);
+        return AjaxResult.success(map);
+    }
 }

+ 101 - 0
zhichen-framework/src/main/java/com/zhichen/framework/web/service/UserServiceImpl.java

@@ -64,6 +64,10 @@ import com.zhichen.modules.grade.bo.ClassGradeUserQueryBo;
 import com.zhichen.modules.grade.service.IClassGradeUserService;
 import com.zhichen.modules.grade.service.impl.ClassGradeServiceImpl;
 import com.zhichen.modules.grade.vo.ClassGradeUserGoodsVo;
+import com.zhichen.modules.order.domain.Order;
+import com.zhichen.modules.order.domain.OrderGoods;
+import com.zhichen.modules.order.service.IOrderGoodsService;
+import com.zhichen.modules.order.service.IOrderService;
 import com.zhichen.modules.order.vo.OrderListVo;
 import com.zhichen.modules.system.domain.SysTask;
 import com.zhichen.modules.system.domain.SysTenant;
@@ -184,6 +188,10 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IU
     private ICourseService iCourseService;
     @Autowired
     private ICourseSectionService iCourseSectionService;
+    @Autowired
+    private IOrderService iOrderService;
+    @Autowired
+    private IOrderGoodsService iOrderGoodsService;
     @Value("${liveGotoURL}")
     private String liveGotoURL;
     @Value("${oldSys.goods}")
@@ -2336,6 +2344,99 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IU
         }
     }
 
+    @Override
+    public User queryByOpenId(String openId) {
+        return baseMapper.queryByOpenId(openId);
+    }
+
+    @Override
+    public Map<String, Object> liveAccount_login(UserAppAccountLoginBo bo) {
+        if(Validator.isEmpty(bo.getAccount())){
+            throw new CustomException("账号不能为空");
+        }
+        LambdaQueryWrapper<User> queryWrapper =new LambdaQueryWrapper<User>();
+        queryWrapper.and(wq -> wq
+                .eq(User::getTelphone,EncryptHandler.encrypt(bo.getAccount()))
+                .or()
+                .eq(User::getIdCard,EncryptHandler.encrypt(bo.getAccount())));
+        User user = getOne(queryWrapper);
+        if(Validator.isEmpty(user)){
+            iUserLoginErrorService.saveErrorLog(bo.getAccount());
+            throw new CustomException("登录信息错误");
+        } else if (UserStatus.DISABLE.getCode().equals(user.getStatus())) {
+            throw new CustomException("对不起,您的账号:已停用");
+        }
+
+        String password = null;
+        if(bo.getPwd().length()>20){
+            String rsaPrivate = null;
+            try {
+                InputStream certStream = Thread.currentThread().getContextClassLoader().getResourceAsStream("config/pri.key");
+                rsaPrivate = AES.getStringByInputStream_1(certStream);
+                certStream.close();
+                password = AES.decrypt(bo.getPwd(),rsaPrivate);
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+        }else{
+            password = bo.getPwd();
+        }
+
+        if (!SecurityUtils.matchesPassword(password,user.getPassword())) {
+            iUserLoginErrorService.saveErrorLog(bo.getAccount());
+            throw new CustomException("登录信息错误");
+        }
+
+        //是否领取直播课程
+        String goodsId = configService.selectConfigByKey("score.gzh.goodsid");
+        if (StringUtils.isNotBlank(goodsId)){
+            Long number = iOrderService.countByGoodsId(user.getUserId(),Long.valueOf(goodsId));
+            if (number <= 0){
+                //没有领取,创建订单
+                Goods goods = iGoodsService.getById(goodsId);
+                //生成订单号
+                String out_trade_no = DateUtils.getDateOrderSn();
+                Order order = new Order();
+                order.setOrderSn(out_trade_no);
+                order.setUserId(user.getUserId());
+                order.setOrderPrice(goods.getStandPrice());
+                order.setOrderStatus(1);
+                order.setCreateTime(DateUtils.getNowTime());
+                order.setUpdateTime(DateUtils.getNowTime());
+                order.setPayType(1);
+                order.setStatus(1);
+                order.setOrderType(2);
+                order.setPayPrice(goods.getStandPrice());
+                order.setOrderFrom(3);
+                order.setPayStatus(3);
+                order.setCheckStatus(1);
+                order.setOrderRefundStatus(1);
+                order.setFinishStatus(1);
+
+                //订单商品
+                OrderGoods orderGoods = new OrderGoods();
+                orderGoods.setOrderSn(out_trade_no);
+                orderGoods.setGoodsYear("2026");
+                orderGoods.setStatus(1);
+                orderGoods.setPayStatus(4);
+                orderGoods.setCreateTime(DateUtils.getNowTime());
+                orderGoods.setUpdateTime(DateUtils.getNowTime());
+                orderGoods.setGoodsId(Long.valueOf(goodsId));
+
+                iOrderGoodsService.save(orderGoods);
+                iOrderService.save(order);
+            }
+        }
+
+        ClientLoginUser loginUser = new ClientLoginUser();
+        loginUser.setUser(user);
+        Map<String,Object> map = new HashMap<>();
+        map.put(Constants.TOKEN,wxTokenService.createToken(loginUser));
+        map.put("user_account",user.getUserAccount());
+        map.put("full_info",Validator.isEmpty(user.getIdCard())?false:true); //是否完善身份信息
+        return map;
+    }
+
     private String getTelPhone(){
         String mobile = TelPhoneUtils.createMobile();
         int count = count(new LambdaQueryWrapper<User>().eq(User::getIdCard, EncryptHandler.encrypt(mobile)));

+ 143 - 0
zhichen-framework/src/main/java/com/zhichen/framework/web/service/WeChatSignatureService.java

@@ -0,0 +1,143 @@
+package com.zhichen.framework.web.service;
+
+import com.alibaba.fastjson.JSONObject;
+import com.zhichen.common.utils.http.HttpUtils;
+import org.springframework.stereotype.Component;
+
+import java.nio.charset.StandardCharsets;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Random;
+
+@Component
+public class WeChatSignatureService {
+
+    private static final String APPID = "wx292447d602eebfc1";
+    private static final String SECRET = "38eef517b06108597ff9aba5d648d207";
+
+    public Map<String, String> generateSignature(String url) {
+        Map<String, String> result = new HashMap<>();
+
+        try {
+            // 1. 获取jsapi_ticket
+            String jsapiTicket = getJsApiTicket();
+
+            // 2. 生成随机字符串
+            String nonceStr = generateNonceStr();
+
+            // 3. 生成时间戳
+            String timestamp = Long.toString(System.currentTimeMillis() / 1000);
+
+            // 4. 拼接签名字符串
+            String stringToSign = buildStringToSign(jsapiTicket, nonceStr, timestamp, url);
+
+            // 5. 计算签名(SHA1加密)
+            String signature = SHA1(stringToSign);
+
+            // 6. 返回配置信息
+            result.put("appId", APPID);
+            result.put("timestamp", timestamp);
+            result.put("nonceStr", nonceStr);
+            result.put("signature", signature);
+
+            return result;
+
+        } catch (Exception e) {
+            e.printStackTrace();
+            throw new RuntimeException("生成签名失败", e);
+        }
+    }
+
+    /**
+     * 获取access_token(有效期7200秒,需缓存)
+     */
+    private String getAccessToken() {
+        String url = "https://api.weixin.qq.com/cgi-bin/token";
+        String param = String.format(
+                "grant_type=client_credential&appid=%s&secret=%s",
+                APPID, SECRET
+        );
+
+        String result = HttpUtils.sendGet(url,param);
+        JSONObject json = JSONObject.parseObject(result);
+
+        if (json.containsKey("access_token")) {
+            return json.getString("access_token");
+        } else {
+            throw new RuntimeException("获取access_token失败: " + json.getString("errmsg"));
+        }
+    }
+
+    /**
+     * 获取jsapi_ticket(有效期7200秒,需缓存)
+     */
+    public String getJsApiTicket() {
+        String accessToken = getAccessToken();
+        String url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket";
+        String param = String.format(
+                "access_token=%s&type=jsapi",
+                accessToken
+        );
+
+        String result = HttpUtils.sendGet(url,param);
+        JSONObject json = JSONObject.parseObject(result);
+
+        if (json.containsKey("ticket")) {
+            return json.getString("ticket");
+        } else {
+            throw new RuntimeException("获取jsapi_ticket失败: " + json.getString("errmsg"));
+        }
+    }
+
+
+    /**
+     * 构建签名字符串
+     * 格式:jsapi_ticket=xxx&noncestr=xxx&timestamp=xxx&url=xxx
+     */
+    private String buildStringToSign(String jsapiTicket, String nonceStr, String timestamp, String url) {
+        return String.format(
+                "jsapi_ticket=%s&noncestr=%s&timestamp=%s&url=%s",
+                jsapiTicket, nonceStr, timestamp, url
+        );
+    }
+
+    /**
+     * 生成随机字符串(16位)
+     */
+    private String generateNonceStr() {
+        String chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
+        StringBuilder sb = new StringBuilder();
+        Random random = new Random();
+        for (int i = 0; i < 16; i++) {
+            sb.append(chars.charAt(random.nextInt(chars.length())));
+        }
+        return sb.toString();
+    }
+
+    /**
+     * SHA1加密
+     */
+    private String SHA1(String str) {
+        try {
+            MessageDigest digest = MessageDigest.getInstance("SHA-1");
+            byte[] bytes = digest.digest(str.getBytes(StandardCharsets.UTF_8));
+
+            StringBuilder sb = new StringBuilder();
+            for (byte b : bytes) {
+                String hex = Integer.toHexString(b & 0xFF);
+                if (hex.length() == 1) {
+                    sb.append("0");
+                }
+                sb.append(hex);
+            }
+            return sb.toString();
+
+        } catch (NoSuchAlgorithmException e) {
+            throw new RuntimeException("SHA1加密失败", e);
+        }
+    }
+
+
+}

+ 75 - 0
zhichen-framework/src/main/java/com/zhichen/framework/web/service/WxLoginService.java

@@ -31,6 +31,10 @@ import com.zhichen.modules.goods.domain.Goods;
 import com.zhichen.modules.goods.service.IGoodsService;
 import com.zhichen.modules.goods.vo.GoodsVo;
 import com.zhichen.modules.grade.domain.ClassGradeUser;
+import com.zhichen.modules.order.domain.Order;
+import com.zhichen.modules.order.domain.OrderGoods;
+import com.zhichen.modules.order.service.IOrderGoodsService;
+import com.zhichen.modules.order.service.IOrderService;
 import com.zhichen.modules.system.domain.SysConfig;
 import com.zhichen.modules.system.domain.SysTenant;
 import com.zhichen.modules.system.service.ISysConfigService;
@@ -174,6 +178,12 @@ public class WxLoginService implements IWxLoginService {
     @Autowired
     private ISysConfigService iSysConfigService;
 
+    @Autowired
+    private IOrderService iOrderService;
+
+    @Autowired
+    private IOrderGoodsService iOrderGoodsService;
+
     private final String KEY_PREFIX = "GOODS_SHARE";
 
     public void initData(){
@@ -1280,6 +1290,71 @@ public class WxLoginService implements IWxLoginService {
         return jsonObject.get("url_link").toString();
     }
 
+    @Override
+    public Map<String, String> liveGzh_login(WxLoginBody loginBody) {
+//        initData();
+//        String param = String.format(gzh_wxAuthParam, gzh_appid, gzh_appsrcret, loginBody.getCode());
+//        String resultString = HttpUtils.sendGet(gzh_wxAuthUrl, param);
+//        //解析json
+//        JSONObject jsonObject = (JSONObject) JSONObject.parse(resultString);
+//        String openId = String.valueOf(jsonObject.get("openid"));
+        String openId = "omVp-2IJwoD9yY0nmkn03ZRI-Dd0";
+        User user = iUserService.queryByOpenId(openId);;
+        Map<String, String> map = new HashMap<>();
+        if (user == null) {
+            map.put("isUser","1");
+            map.put("openId",openId);
+            return map;
+        }
+        //是否领取直播课程
+        String goodsId = iSysConfigService.selectConfigByKey("score.gzh.goodsid");
+        if (StringUtils.isNotBlank(goodsId)){
+            Long number = iOrderService.countByGoodsId(user.getUserId(),Long.valueOf(goodsId));
+            if (number <= 0){
+                //没有领取,创建订单
+                Goods goods = iGoodsService.getById(goodsId);
+                //生成订单号
+                String out_trade_no = DateUtils.getDateOrderSn();
+                Order order = new Order();
+                order.setOrderSn(out_trade_no);
+                order.setUserId(user.getUserId());
+                order.setOrderPrice(goods.getStandPrice());
+                order.setOrderStatus(1);
+                order.setCreateTime(DateUtils.getNowTime());
+                order.setUpdateTime(DateUtils.getNowTime());
+                order.setPayType(1);
+                order.setStatus(1);
+                order.setOrderType(2);
+                order.setPayPrice(goods.getStandPrice());
+                order.setOrderFrom(3);
+                order.setPayStatus(3);
+                order.setCheckStatus(1);
+                order.setOrderRefundStatus(1);
+                order.setFinishStatus(1);
+
+                //订单商品
+                OrderGoods orderGoods = new OrderGoods();
+                orderGoods.setOrderSn(out_trade_no);
+                orderGoods.setGoodsYear("2026");
+                orderGoods.setStatus(1);
+                orderGoods.setPayStatus(4);
+                orderGoods.setCreateTime(DateUtils.getNowTime());
+                orderGoods.setUpdateTime(DateUtils.getNowTime());
+                orderGoods.setGoodsId(Long.valueOf(goodsId));
+
+                iOrderGoodsService.save(orderGoods);
+                iOrderService.save(order);
+            }
+        }
+
+        ClientLoginUser loginUser = new ClientLoginUser();
+        loginUser.setUser(user);
+        map.put("openId",openId);
+        map.put("isUser","0");
+        map.put(Constants.TOKEN, wxTokenService.createToken(loginUser));
+        return map;
+    }
+
     public Boolean subGzh(String openId) {
         String unionId = getWxGzhUserCgiInfo(openId);
         if (Validator.isNotEmpty(unionId)) {

+ 13 - 0
zhichen-system/src/main/java/com/zhichen/modules/bank/service/impl/QuestionServiceImpl.java

@@ -4474,7 +4474,20 @@ public class QuestionServiceImpl extends ServiceImpl<QuestionMapper, Question> i
                             questionInfoVo.setAnswerQuestion(index2.toString());
                             vv1.add(questionInfoVo);
                             a = a+y;
+                        }else if (questionImportV41.getAnalysisContent().equals("问答题")){
+                            //问答下取1格
+                            y = 1;
+                            List<QuestionImportV4> questionImportV8 = vv.subList(i1, i1 + y);
+                            QuestionImportV4 questionImportV42 = questionImportV8.get(0);
+                            QuestionInfoVo questionInfoVo = new QuestionInfoVo();
+                            questionInfoVo.setContent(questionImage(questionImportV42.getQuestionName()));
+                            questionInfoVo.setType(5);
+                            questionInfoVo.setAnswerQuestion("");
+                            questionInfoVo.setAnalysisContent(questionImportV42.getDescribe());
+                            vv1.add(questionInfoVo);
+                            a = a+y;
                         }
+
                         i1 = i1+y-1;
                     }
                     question.setJsonStr(JSONArray.toJSONString(vv1));

+ 2 - 0
zhichen-system/src/main/java/com/zhichen/modules/order/mapper/OrderMapper.java

@@ -94,4 +94,6 @@ public interface OrderMapper extends BaseMapper<Order> {
 
     @InterceptorIgnore(tenantLine = "true")
     String getOrderSnByYW(String orderSn);
+
+    Long countByGoodsId(@Param("userId")Long userId,@Param("goodsId") Long goodsId);
 }

+ 2 - 0
zhichen-system/src/main/java/com/zhichen/modules/order/service/IOrderService.java

@@ -152,4 +152,6 @@ public interface IOrderService extends IService<Order> {
 	List<UserStudyConditionVo> getUserStudyCondition(UserStudyConditionBo bo);
 
 	List<OrderKaoqianListExportVo> exportKaoqianList(OrderQueryBo bo);
+
+    Long countByGoodsId(Long userId, Long goodsId);
 }

+ 5 - 0
zhichen-system/src/main/java/com/zhichen/modules/order/service/impl/OrderServiceImpl.java

@@ -3805,6 +3805,11 @@ public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements
         return list;
     }
 
+    @Override
+    public Long countByGoodsId(Long userId, Long goodsId) {
+        return baseMapper.countByGoodsId(userId,goodsId);
+    }
+
     /**
      * 根据身份证号码判断性别
      *

+ 2 - 0
zhichen-system/src/main/java/com/zhichen/modules/user/mapper/UserMapper.java

@@ -98,4 +98,6 @@ public interface UserMapper extends BaseMapper<User> {
     List<UserBusinessGoodsVo> getCourseByUser(UserBusinessGoodsBo item);
 
     Integer getBusinessPhotoSign(@Param("orderGoodsId")Long orderGoodsId);
+
+    User queryByOpenId(String openId);
 }

+ 4 - 0
zhichen-system/src/main/java/com/zhichen/modules/user/service/IUserService.java

@@ -184,4 +184,8 @@ public interface IUserService extends IService<User> {
 
     void synchronizationUser(Integer orgId);
 
+    User queryByOpenId(String openId);
+
+	Map<String, Object> liveAccount_login(UserAppAccountLoginBo bo);
+
 }

+ 3 - 0
zhichen-system/src/main/java/com/zhichen/modules/wx/service/IWxLoginService.java

@@ -4,6 +4,7 @@ package com.zhichen.modules.wx.service;
 import com.zhichen.modules.course.bo.SectionWatchPerBo;
 import com.zhichen.modules.wx.bo.WxInfoBo;
 import com.zhichen.modules.wx.bo.WxInfoQuery;
+import com.zhichen.modules.wx.bo.WxLoginBody;
 import com.zhichen.modules.wx.bo.WxShareGoodsBo;
 
 import java.util.Map;
@@ -40,4 +41,6 @@ public interface IWxLoginService
     String getWxSmallLink();
 
     String getWxSmallStudyCentreLink();
+
+    Map<String, String> liveGzh_login(WxLoginBody loginBody);
 }

+ 13 - 0
zhichen-system/src/main/resources/mapper/modules/order/OrderMapper.xml

@@ -1302,4 +1302,17 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
           AND o.input_order_sn IS NOT NULL
     </select>
 
+    <select id="countByGoodsId" parameterType="java.lang.Long" resultType="java.lang.Long">
+        SELECT
+            COUNT(*)
+        FROM
+            `order` o
+                LEFT JOIN order_goods og ON o.order_sn = og.order_sn
+        WHERE
+            o.`status` = 1
+          AND o.user_id = #{userId}
+          AND og.goods_id = #{goodsId}
+          AND og.`status` = 1
+    </select>
+
 </mapper>

+ 11 - 0
zhichen-system/src/main/resources/mapper/modules/user/UserMapper.xml

@@ -819,4 +819,15 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         order by u.user_id desc
     </select>
 
+    <select id="queryByOpenId" resultType="com.zhichen.modules.user.domain.User">
+        SELECT
+            u.*
+        FROM
+            `user` u
+        WHERE
+            u.`status` = 1
+          AND u.gzh_open_id = #{openId}
+            LIMIT 1
+    </select>
+
 </mapper>