From d615fc515fc52d6ed970c11d59a017e48de4be32 Mon Sep 17 00:00:00 2001
From: zj <1772600164@qq.com>
Date: Tue, 16 Jun 2026 16:43:58 +0800
Subject: [PATCH] 1

---
 src/main/java/com/nq/service/impl/PayServiceImpl.java |  259 +++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 255 insertions(+), 4 deletions(-)

diff --git a/src/main/java/com/nq/service/impl/PayServiceImpl.java b/src/main/java/com/nq/service/impl/PayServiceImpl.java
index 20d7e71..29ee199 100644
--- a/src/main/java/com/nq/service/impl/PayServiceImpl.java
+++ b/src/main/java/com/nq/service/impl/PayServiceImpl.java
@@ -4,16 +4,25 @@
 import com.nq.common.ServerResponse;
 import com.nq.dao.UserMapper;
 import com.nq.dao.UserRechargeMapper;
+import com.nq.pojo.SiteSetting;
 import com.nq.pojo.User;
 import com.nq.pojo.UserRecharge;
 import com.nq.service.IPayService;
+import com.nq.service.ISiteSettingService;
 import com.nq.service.IUserService;
 import com.nq.utils.KeyUtils;
 import com.nq.utils.PropertiesUtil;
+import com.nq.utils.RechargeAmtValidator;
+import com.nq.utils.UserFundUtil;
+import com.nq.utils.pay.AlipayPayUtil;
 import com.nq.utils.pay.CmcPayOuterRequestUtil;
 import com.nq.utils.pay.CmcPayTool;
+import com.nq.utils.pay.OcocnPayUtil;
+import com.alipay.api.AlipayApiException;
+import com.nq.vo.pay.AlipayPayVO;
 import com.nq.vo.pay.FlyPayVO;
 import com.nq.vo.pay.GuoPayVO;
+import com.nq.vo.pay.OcocnPayVO;
 
 import java.io.UnsupportedEncodingException;
 import java.math.BigDecimal;
@@ -22,6 +31,7 @@
 import java.security.NoSuchAlgorithmException;
 import java.text.SimpleDateFormat;
 import java.util.Date;
+import java.util.Map;
 import java.util.Random;
 import javax.servlet.http.HttpServletRequest;
 
@@ -47,6 +57,9 @@
 
     @Autowired
     UserMapper userMapper;
+
+    @Autowired
+    ISiteSettingService iSiteSettingService;
 
     private static final String juhe1_key = "vd7omkkexkt7fvl6wm2jl9yan3g79y6i";
 
@@ -288,10 +301,7 @@
         if (updateCount > 0) {
             log.info("后台通知,修改订单状态成功");
 
-            BigDecimal total_amt = user.getUserAmt().add(userRecharge.getPayAmt());
-            user.setUserAmt(total_amt);
-            BigDecimal total_enable = user.getEnableAmt().add(userRecharge.getPayAmt());
-            user.setEnableAmt(total_enable);
+            UserFundUtil.creditUserBalance(user, userRecharge.getPayAmt());
             int updateUserCount = this.userMapper.updateByPrimaryKeySelective(user);
             if (updateUserCount > 0) {
                 return ServerResponse.createBySuccessMsg("后台通知 处理成功");
@@ -375,6 +385,247 @@
     }
 
     @Override
+    public ServerResponse ococnPay(String payType, String payAmt, HttpServletRequest request) {
+        if (StringUtils.isBlank(payType) || StringUtils.isBlank(payAmt)) {
+            return ServerResponse.createByErrorMsg("参数不能为空");
+        }
+        BigDecimal payAmtBig = new BigDecimal(payAmt);
+        if (payAmtBig.compareTo(BigDecimal.ZERO) <= 0) {
+            return ServerResponse.createByErrorMsg("支付金额必须大于0");
+        }
+
+        User user = this.iUserService.getCurrentRefreshUser(request);
+        if (user == null) {
+            return ServerResponse.createByErrorMsg("请先登录");
+        }
+
+        String ordersn = KeyUtils.getRechargeOrderSn();
+        String money = payAmtBig.setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString();
+        String pid = PropertiesUtil.getProperty("ococn.pay.pid");
+        String key = PropertiesUtil.getProperty("ococn.pay.key");
+        String submitUrl = PropertiesUtil.getProperty("ococn.pay.url");
+        String apiDomain = trimTrailingSlash(PropertiesUtil.getProperty("website.domain.url"));
+        if (StringUtils.isAnyBlank(pid, key, submitUrl, apiDomain)) {
+            return ServerResponse.createByErrorMsg("支付配置不完整,请联系管理员");
+        }
+        String notifyUrl = apiDomain + "/api/pay/ococnNotify.do";
+        String returnUrl = apiDomain + "/api/pay/ococnReturn.do";
+        String sitename = StringUtils.defaultString(PropertiesUtil.getProperty("ococn.pay.sitename", ""), "");
+        String productName = PropertiesUtil.getProperty("ococn.pay.name", "账户充值");
+
+        UserRecharge userRecharge = new UserRecharge();
+        userRecharge.setUserId(user.getId());
+        userRecharge.setNickName(user.getRealName());
+        userRecharge.setAgentId(user.getAgentId());
+        userRecharge.setOrderSn(ordersn);
+        userRecharge.setPayChannel(getOcocnChannelName(payType));
+        userRecharge.setPayAmt(payAmtBig);
+        userRecharge.setOrderStatus(Integer.valueOf(0));
+        userRecharge.setAddTime(new Date());
+
+        int insertCount = this.userRechargeMapper.insert(userRecharge);
+        if (insertCount <= 0) {
+            return ServerResponse.createByErrorMsg("创建支付订单失败");
+        }
+
+        String sign = OcocnPayUtil.buildSubmitSign(money, productName, notifyUrl, ordersn, pid, returnUrl, sitename, payType, key);
+        log.info("ococn支付 notifyUrl={} returnUrl={}", notifyUrl, returnUrl);
+        StringBuilder payUrlBuilder = new StringBuilder(submitUrl).append("?");
+        payUrlBuilder.append("pid=").append(pid)
+                .append("&type=").append(payType)
+                .append("&out_trade_no=").append(ordersn)
+                .append("&notify_url=").append(OcocnPayUtil.encode(notifyUrl))
+                .append("&return_url=").append(OcocnPayUtil.encode(returnUrl))
+                .append("&name=").append(OcocnPayUtil.encode(productName))
+                .append("&money=").append(money);
+        if (StringUtils.isNotBlank(sitename)) {
+            payUrlBuilder.append("&sitename=").append(OcocnPayUtil.encode(sitename));
+        }
+        payUrlBuilder.append("&sign=").append(sign).append("&sign_type=MD5");
+        String payUrl = payUrlBuilder.toString();
+
+        OcocnPayVO ococnPayVO = new OcocnPayVO();
+        ococnPayVO.setPayUrl(payUrl);
+        log.info("ococn支付,创建订单成功 orderSn={}", ordersn);
+        return ServerResponse.createBySuccess(ococnPayVO);
+    }
+
+    @Override
+    public ServerResponse ococnNotify(HttpServletRequest request) {
+        Map<String, String> params = OcocnPayUtil.parseRequestParams(request);
+        log.info("ococn支付通知参数: {}", params);
+
+        String outTradeNo = params.get("out_trade_no");
+        String tradeNo = params.get("trade_no");
+        String money = params.get("money");
+        String tradeStatus = params.get("trade_status");
+        String sign = params.get("sign");
+
+        if (StringUtils.isAnyBlank(outTradeNo, tradeNo, money, tradeStatus, sign)) {
+            return ServerResponse.createByErrorMsg("回调参数不完整");
+        }
+
+        String key = PropertiesUtil.getProperty("ococn.pay.key");
+        if (!OcocnPayUtil.verifyNotifySign(params, key)) {
+            log.error("ococn支付通知签名校验失败, remoteSign={}, params={}", sign, params);
+            return ServerResponse.createByErrorMsg("签名校验失败");
+        }
+
+        if (!"TRADE_SUCCESS".equals(tradeStatus)) {
+            return ServerResponse.createByErrorMsg("支付未成功");
+        }
+
+        UserRecharge existing = this.userRechargeMapper.findUserRechargeByOrderSn(outTradeNo);
+        if (existing != null && existing.getOrderStatus().intValue() != 0) {
+            return ServerResponse.createBySuccessMsg("订单已处理");
+        }
+
+        return doSuccess(outTradeNo, money);
+    }
+
+    @Override
+    public String ococnReturn(HttpServletRequest request) {
+        Map<String, String> params = OcocnPayUtil.parseRequestParams(request);
+        log.info("ococn支付同步跳转: {}", params);
+        String frontendUrl = StringUtils.defaultIfBlank(
+                PropertiesUtil.getProperty("ococn.pay.frontend_redirect"),
+                trimTrailingSlash(PropertiesUtil.getProperty("frontend.domain.url", "")) + "/#/user"
+        );
+        return frontendUrl;
+    }
+
+    private String getOcocnChannelName(String payType) {
+        if ("alipay".equals(payType)) {
+            return "支付宝-线上";
+        }
+        if ("wxpay".equals(payType)) {
+            return "微信-线上";
+        }
+        if ("qqpay".equals(payType)) {
+            return "QQ钱包-线上";
+        }
+        if ("tenpay".equals(payType)) {
+            return "财付通-线上";
+        }
+        return "线上支付";
+    }
+
+    private String trimTrailingSlash(String url) {
+        if (url == null) {
+            return null;
+        }
+        return url.endsWith("/") ? url.substring(0, url.length() - 1) : url;
+    }
+
+    @Override
+    public ServerResponse alipayPagePay(String payAmt, HttpServletRequest request) {
+        if (StringUtils.isBlank(payAmt)) {
+            return ServerResponse.createByErrorMsg("参数不能为空");
+        }
+        BigDecimal payAmtBig = new BigDecimal(payAmt);
+        if (payAmtBig.compareTo(BigDecimal.ZERO) <= 0) {
+            return ServerResponse.createByErrorMsg("支付金额必须大于0");
+        }
+        SiteSetting siteSetting = this.iSiteSettingService.getSiteSetting();
+        ServerResponse amtCheck = RechargeAmtValidator.validate(siteSetting, payAmtBig);
+        if (!amtCheck.isSuccess()) {
+            return amtCheck;
+        }
+        String configError = AlipayPayUtil.getConfigError();
+        if (configError != null) {
+            return ServerResponse.createByErrorMsg(configError);
+        }
+
+        User user = this.iUserService.getCurrentRefreshUser(request);
+        if (user == null) {
+            return ServerResponse.createByErrorMsg("请先登录");
+        }
+
+        String apiDomain = trimTrailingSlash(PropertiesUtil.getProperty("website.domain.url"));
+        if (StringUtils.isBlank(apiDomain)) {
+            return ServerResponse.createByErrorMsg("支付配置不完整,请联系管理员");
+        }
+
+        String ordersn = KeyUtils.getRechargeOrderSn();
+        String money = payAmtBig.setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString();
+        String notifyUrl = apiDomain + "/api/pay/alipayNotify.do";
+        String returnUrl = apiDomain + "/api/pay/alipayReturn.do";
+        String quitUrl = PropertiesUtil.getProperty("alipay.frontend-redirect",
+                trimTrailingSlash(PropertiesUtil.getProperty("frontend.domain.url", "")) + "/#/rechargelist");
+        String productName = PropertiesUtil.getProperty("alipay.product-name", "账户充值");
+
+        UserRecharge userRecharge = new UserRecharge();
+        userRecharge.setUserId(user.getId());
+        userRecharge.setNickName(user.getRealName());
+        userRecharge.setAgentId(user.getAgentId());
+        userRecharge.setOrderSn(ordersn);
+        userRecharge.setPayChannel("支付宝-WAP");
+        userRecharge.setPayAmt(payAmtBig);
+        userRecharge.setOrderStatus(Integer.valueOf(0));
+        userRecharge.setAddTime(new Date());
+
+        int insertCount = this.userRechargeMapper.insert(userRecharge);
+        if (insertCount <= 0) {
+            return ServerResponse.createByErrorMsg("创建支付订单失败");
+        }
+
+        try {
+            String payForm = AlipayPayUtil.buildWapPayForm(ordersn, money, productName, notifyUrl, returnUrl, quitUrl);
+            AlipayPayVO alipayPayVO = new AlipayPayVO();
+            alipayPayVO.setPayForm(payForm);
+            log.info("支付宝WAP支付,创建订单成功 orderSn={}", ordersn);
+            return ServerResponse.createBySuccess(alipayPayVO);
+        } catch (AlipayApiException e) {
+            log.error("支付宝WAP支付下单失败 orderSn={}", ordersn, e);
+            String msg = e.getMessage();
+            if (msg != null && (msg.contains("私钥") || msg.contains("公钥") || msg.contains("RSA2"))) {
+                return ServerResponse.createByErrorMsg(msg);
+            }
+            return ServerResponse.createByErrorMsg("发起支付宝支付失败,请稍后重试");
+        } catch (Exception e) {
+            log.error("支付宝网页支付下单失败 orderSn={}", ordersn, e);
+            return ServerResponse.createByErrorMsg("发起支付宝支付失败,请稍后重试");
+        }
+    }
+
+    @Override
+    public ServerResponse alipayNotify(HttpServletRequest request) {
+        Map<String, String> params = AlipayPayUtil.parseRequestParams(request);
+        log.info("支付宝支付通知参数: {}", params);
+
+        String outTradeNo = params.get("out_trade_no");
+        String totalAmount = params.get("total_amount");
+        String tradeStatus = params.get("trade_status");
+
+        if (StringUtils.isAnyBlank(outTradeNo, totalAmount, tradeStatus)) {
+            return ServerResponse.createByErrorMsg("回调参数不完整");
+        }
+        if (!AlipayPayUtil.verifyNotify(params)) {
+            log.error("支付宝支付通知签名校验失败, params={}", params);
+            return ServerResponse.createByErrorMsg("签名校验失败");
+        }
+        if (!"TRADE_SUCCESS".equals(tradeStatus) && !"TRADE_FINISHED".equals(tradeStatus)) {
+            return ServerResponse.createByErrorMsg("支付未成功");
+        }
+
+        UserRecharge existing = this.userRechargeMapper.findUserRechargeByOrderSn(outTradeNo);
+        if (existing != null && existing.getOrderStatus().intValue() != 0) {
+            return ServerResponse.createBySuccessMsg("订单已处理");
+        }
+        return doSuccess(outTradeNo, totalAmount);
+    }
+
+    @Override
+    public String alipayReturn(HttpServletRequest request) {
+        Map<String, String> params = AlipayPayUtil.parseRequestParams(request);
+        log.info("支付宝支付同步跳转: {}", params);
+        return StringUtils.defaultIfBlank(
+                PropertiesUtil.getProperty("alipay.frontend-redirect"),
+                trimTrailingSlash(PropertiesUtil.getProperty("frontend.domain.url", "")) + "/#/rechargelist"
+        );
+    }
+
+    @Override
     public ServerResponse juhenewpayNotify(HttpServletRequest request) throws UnsupportedEncodingException {
         LinkedMap map = new LinkedMap();
         String out_trade_no = request.getParameter("out_trade_no");

--
Gitblit v1.9.3