1
zj
2025-03-17 c0bc900b8f801c63b6b78350dfd79faea5452fae
src/main/java/com/nq/service/impl/PayServiceImpl.java
@@ -1,6 +1,11 @@
package com.nq.service.impl;
import cn.hutool.core.date.DateUtil;
import cn.hutool.cron.timingwheel.SystemTimer;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.gson.Gson;
import com.nq.common.CmcPayConfig;
import com.nq.common.ServerResponse;
@@ -13,22 +18,29 @@
import com.nq.utils.pay.CmcPayOuterRequestUtil;
import com.nq.utils.pay.CmcPayTool;
import com.nq.utils.timeutil.DateTimeUtil;
import com.nq.utils.translate.GoogleTranslateUtil;
import com.nq.vo.pay.GuoPayVO;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.net.URLDecoder;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import net.sf.json.JSONObject;
import org.apache.commons.collections.map.HashedMap;
import org.apache.commons.collections.map.LinkedMap;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -63,12 +75,108 @@
    IUserAssetsServices iUserAssetsServices;
    @Resource
    UserWithdrawMapper userWithdrawMapper;
    UserAssetsMapper userAssetsMapper;
    @Resource
    UserWithdrawMapper userWithdrawMapper;
    @Autowired
    ISiteInfoService siteInfoService;
    @Autowired
    PaymentRechargeService paymentRechargeService;
    public ServerResponse thirdPartyRecharge(HttpServletRequest request, String tradeAmount) throws UnsupportedEncodingException, JsonProcessingException {
        String reqUrl = "https://api.watchglbpay.com/pay/web";
        User user = userService.getCurrentRefreshUser(request);
        if(ObjectUtils.isEmpty(user)){
            GoogleTranslateUtil googleTranslateUtil = new GoogleTranslateUtil();
            String lang = request.getHeader("lang");
            return ServerResponse.createByErrorCodeMsg(401,googleTranslateUtil.translate("请登录",lang ));
        }
        Map<String, String> params = new TreeMap<String, String>();
        //版本号 需同步返回JSON 必填,固定值 1.0
        params.put("version", "1.0");
        //商品名称
//        params.put("goods_name", "用户:"+user.getId()+",充值");
        params.put("goods_name", "用户充值");
        //商户号  平台分配唯一
        params.put("mch_id", "100789033");
        //商家订单号 保证每笔订单唯一
        params.put("mch_order_no", generatePayOrderId());
        //异步通知地址 不超过 200 字节,支付成功后发起,不能携带参数
        params.put("notify_url", "https://api.durocaspitall.com/user/rechargeCallback.do");
        // 订单时间  时间格式yyyy-MM-dd HH:mm:ss
        params.put("order_date", getOrderTime());
        //支付类型 请查阅商户后台通道编码
        params.put("pay_type", "151");
        //交易金额 以元为单位
        params.put("trade_amount", tradeAmount);
        //商户秘钥必填
        String merchant_key = "6ef36aa4d88a47a9a177c33c7199fff6";
        String signInfo = SignUtil.sortData(params);
        // 签名   signInfo签名参数排序,  merchant_key商户私钥
        String sign = SignAPI.sign(signInfo, merchant_key);
        params.put("sign", sign);
        //固定值 MD5,不参与签名
        params.put("sign_type", "MD5");
        System.out.println("请求参数:" + params.toString());
        String result = HttpClientUtil.doPost(reqUrl, params, "utf-8");
        System.out.println("签名参数排序:" + signInfo.length() + " --> " + signInfo);
        System.out.println("sign值:" + sign.length() + " --> " + sign);
        System.out.println("result值:" + result);
        // 创建 ObjectMapper 实例
        ObjectMapper objectMapper = new ObjectMapper();
        // 将 JSON 字符串转换为实体类对象
        PaymentResponse payResponse = objectMapper.readValue(result, PaymentResponse.class);
        if(payResponse.getRespCode().equals("FAIL")){
            log.error("充值下单失败:"+result);
            return ServerResponse.createByErrorMsg("获取充值链接失败",request);
        }
        PaymentRecharge paymentRecharge = new PaymentRecharge();
        paymentRecharge.setUserId(user.getId());
        paymentRecharge.setOrderNo(payResponse.getOrderNo());
        paymentRecharge.setMchOrderNo(payResponse.getMchOrderNo());
        paymentRecharge.setAmount(new BigDecimal(payResponse.getOriAmount()));
        paymentRecharge.setStatus(1);
        paymentRecharge.setPaymentTime(DateUtil.parse(payResponse.getOrderDate(),"yyyy-MM-dd HH:mm:ss"));
        paymentRecharge.setCreatedAt(new Date());
        paymentRecharge.setNotifyUrl(payResponse.getPayInfo());
        paymentRecharge.setPayInfo(payResponse.toString());
        paymentRechargeService.save(paymentRecharge);
        return ServerResponse.createBySuccess(payResponse.getPayInfo());
    }
    public String generatePayOrderId() {
        // 获取当前时间戳(毫秒)
        long timestamp = System.currentTimeMillis();
        // 生成一个随机的UUID并截取前8位
        String randomUUID = UUID.randomUUID().toString().replace("-", "").substring(0, 8);
        // 将时间戳和随机UUID结合生成订单号
        return timestamp + randomUUID;
    }
    public static String getOrderTime() {
        // 获取当前时间
        LocalDateTime now = LocalDateTime.now();
        // 定义输出格式
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        // 格式化当前时间
        return now.format(formatter);
    }
@@ -530,6 +638,51 @@
        return ServerResponse.createByError();
    }
    @Override
    public void rechargeCallback(PaymentResponse vo,HttpServletResponse response) throws IOException {
        log.info("充值回调进来了:"+vo.toString());
        synchronized (vo.getOrderNo()){
            PrintWriter pw = response.getWriter();
            PaymentRecharge paymentRecharge = paymentRechargeService.getOne(new LambdaQueryWrapper<>(PaymentRecharge.class)
                    .eq(PaymentRecharge::getOrderNo, vo.getOrderNo())
                    .eq(PaymentRecharge::getMchOrderNo, vo.getMchOrderNo())
                    .eq(PaymentRecharge::getStatus,1)
                    .last("limit 1")
            );
            if(!vo.getTradeResult().equals("1")){
                paymentRecharge.setStatus(2);
                paymentRecharge.setAmount(new BigDecimal(vo.getOriAmount()));
                paymentRecharge.setPayInfo(vo.toString());
                paymentRechargeService.updateById(paymentRecharge);
                log.error("充值回调失败:"+vo.toString());
                return;
            }
            if(ObjectUtils.isEmpty(paymentRecharge)){
                log.info("未找到充值订单");
                pw.print("error 未找到充值订单");
                return;
            }
            UserAssets userAssets = userAssetsMapper.selectOne(new LambdaQueryWrapper<>(UserAssets.class)
                    .eq(UserAssets::getUserId, paymentRecharge.getUserId())
                    .eq(UserAssets::getAccectType, "IN")
            );
            ServerResponse serverResponse = iUserAssetsServices.updateUserAssets(userAssets.getId(), vo.getOriAmount().toString(), "2");
            if(serverResponse.getStatus() == 0){
                paymentRecharge.setStatus(2);
                paymentRecharge.setAmount(new BigDecimal(vo.getOriAmount()));
                paymentRecharge.setPayInfo(vo.toString());
                paymentRechargeService.updateById(paymentRecharge);
            }
            log.info("充值回调----完成");
            pw.print("success");
            pw.flush();
            pw.close();
        }
    }
    private ServerResponse doSuccess(String orderId, String amount) {
        UserRecharge userRecharge = this.userRechargeMapper.findUserRechargeByOrderSn(orderId);