Forráskód Böngészése

fix(security): 修复支付回调与跨租户重置密码

微信回调补齐break防止重复入账,汇付回调启用RSA验签,重置密码增加数据权限校验。

Co-authored-by: Cursor <cursoragent@cursor.com>
吴树波 22 órája
szülő
commit
909d908a6a

+ 2 - 0
fs-admin/src/main/java/com/fs/web/controller/system/SysUserController.java

@@ -211,6 +211,8 @@ public class SysUserController extends BaseController
     public AjaxResult resetPwd(@RequestBody SysUser user)
     {
         userService.checkUserAllowed(user);
+        // 增加数据权限校验,防止跨租户/跨部门重置密码
+        userService.checkUserDataScope(user.getUserId());
         user.setPassword(SecurityUtils.encryptPassword(user.getPassword()));
         user.setUpdateBy(getUsername());
         return toAjax(userService.resetPwd(user));

+ 11 - 1
fs-user-app/src/main/java/com/fs/app/controller/WxPayController.java

@@ -87,25 +87,35 @@ public class WxPayController {
                 String outtradeno = result.getOutTradeNo();
                 String tradeNo = result.getTransactionId();
                 String[] orderId=outtradeno.split("-");
+                // 每个 case 必须 break,避免 fall-through 导致一笔支付重复入账多个业务线
                 switch (orderId[0]){
                     case "inquiry":
                         inquiryOrderService.payConfirm("",orderId[1],tradeNo,"",1,tradeNo,null);
+                        break;
                     case "store":
                         storeOrderService.payConfirm("",orderId[1],tradeNo,"",1,tradeNo,null);
+                        break;
                     case "package":
                         packageOrderService.payConfirm("",orderId[1],tradeNo,"",1,tradeNo,null);
+                        break;
                     case "course":
                         courseOrderService.payConfirm("",orderId[1],tradeNo,"",1,tradeNo,null);
+                        break;
                     case "appvip":
                         userVipOrderService.payConfirm("",orderId[1],tradeNo,"",1,tradeNo,null);
+                        break;
                     case "integral":
                         integralOrderService.payConfirm("",orderId[1],tradeNo,"",1,tradeNo,null);
                         break;
                     case "product":
                         courseProductOrderService.payConfirm("",orderId[1],tradeNo,"",1,tradeNo,null);
+                        break;
                     case "payment":
                         paymentService.payConfirm(orderId[1], outtradeno,tradeNo,null);
-
+                        break;
+                    default:
+                        logger.warn("未知订单前缀: {}", orderId[0]);
+                        break;
                 }
                 return WxPayNotifyResponse.success("处理成功!");
             }else{

+ 22 - 1
fs-user-app/src/main/java/com/fs/app/controller/store/PayScrmController.java

@@ -2,6 +2,7 @@ package com.fs.app.controller.store;
 
 
 import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
 import com.fs.common.config.FSSysConfig;
 import com.fs.common.core.controller.BaseController;
 import com.fs.common.core.redis.RedisCache;
@@ -10,7 +11,11 @@ import com.fs.company.service.ICompanyUserService;
 import com.fs.erp.service.IErpOrderService;
 import com.fs.hisStore.service.*;
 import com.fs.huifuPay.domain.HuiFuResult;
+import com.fs.huifuPay.sdk.opps.core.BasePay;
+import com.fs.huifuPay.sdk.opps.core.sign.JsonUtils;
 import com.fs.huifuPay.sdk.opps.core.utils.HuiFuUtils;
+import com.fs.huifuPay.sdk.opps.core.utils.RsaUtils;
+import com.fs.common.utils.StringUtils;
 import com.fs.live.service.ILiveOrderService;
 import com.fs.ybPay.domain.OrderCallback;
 import com.fs.ybPay.domain.OrderResult;
@@ -74,7 +79,23 @@ public class PayScrmController {
     @ApiOperation("汇付第三方支付回调")
     @PostMapping(value="/hfPayNotify")
     public String hfPayNotify(@RequestParam String resp_desc, @RequestParam String resp_code, @RequestParam String sign, @RequestParam String resp_data) throws Exception {
-        //验证
+        // 先验签,防止伪造支付成功回调
+        if (StringUtils.isEmpty(sign) || StringUtils.isEmpty(resp_data)) {
+            logger.error("汇付回调缺少签名或业务数据");
+            return "fail";
+        }
+        try {
+            JSONObject data = JSON.parseObject(resp_data);
+            String sortedData = JsonUtils.sort4JsonString(JSONObject.toJSONString(data), 5);
+            String publicKey = BasePay.HUIFU_DEFAULT_PUBLIC_KEY;
+            if (!RsaUtils.verify(sortedData, publicKey, sign)) {
+                logger.error("汇付回调验签失败, resp_data={}", resp_data);
+                return "fail";
+            }
+        } catch (Exception e) {
+            logger.error("汇付回调验签异常", e);
+            return "fail";
+        }
         HuiFuResult o = JSON.parseObject(resp_data, HuiFuResult.class);
         logger.info("汇付支付回调:"+o);
         if(o.getResp_code().equals("00000000") && o.getNotify_type().equals("1")){