| src/main/java/com/nq/common/interceptor/ApiUserAuthorityInterceptor.java | ●●●●● patch | view | raw | blame | history | |
| src/main/java/com/nq/controller/protol/UserController.java | ●●●●● patch | view | raw | blame | history | |
| src/main/java/com/nq/dao/PaymentRechargeMapper.java | ●●●●● patch | view | raw | blame | history | |
| src/main/java/com/nq/pojo/PaymentRecharge.java | ●●●●● patch | view | raw | blame | history | |
| src/main/java/com/nq/pojo/PaymentResponse.java | ●●●●● patch | view | raw | blame | history | |
| src/main/java/com/nq/pojo/RechargeCallbackVo.java | ●●●●● patch | view | raw | blame | history | |
| src/main/java/com/nq/service/IPayService.java | ●●●●● patch | view | raw | blame | history | |
| src/main/java/com/nq/service/PaymentRechargeService.java | ●●●●● patch | view | raw | blame | history | |
| src/main/java/com/nq/service/impl/PayServiceImpl.java | ●●●●● patch | view | raw | blame | history | |
| src/main/java/com/nq/service/impl/PaymentRechargeServiceImpl.java | ●●●●● patch | view | raw | blame | history |
src/main/java/com/nq/common/interceptor/ApiUserAuthorityInterceptor.java
@@ -72,6 +72,12 @@ if ("/user/pay/flyPay.do".equals(url)) { return true; } if ("/user/thirdPartyRecharge.do".equals(url)) { return true; } if ("/user/rechargeCallback.do".equals(url)) {//支付回调 return true; } User currentUser = getCurrentUser(httpServletRequest); GoogleTranslateUtil googleTranslateUtil = new GoogleTranslateUtil(); String lang = httpServletRequest.getHeader("lang"); src/main/java/com/nq/controller/protol/UserController.java
@@ -1,22 +1,26 @@ package com.nq.controller.protol; import com.baomidou.mybatisplus.core.toolkit.ObjectUtils; import com.google.common.collect.Maps; import com.google.gson.Gson; import com.nq.common.ServerResponse; import com.nq.enums.EStockType; import com.nq.pojo.ApplyLever; import com.nq.pojo.StockSubscribe; import com.nq.pojo.UserStockSubscribe; import com.nq.pojo.*; import com.nq.service.*; import com.nq.service.impl.PayServiceImpl; import com.nq.utils.PropertiesUtil; import java.io.IOException; import java.math.BigDecimal; import java.util.Map; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import com.nq.utils.translate.GoogleTranslateUtil; import com.nq.vo.stock.UserStockSubscribeAddIn; import org.apache.ibatis.annotations.Property; import org.slf4j.Logger; @@ -61,7 +65,8 @@ @Autowired IUserRechargeService iUserRechargeService; @Autowired PayServiceImpl payService; @Autowired IApplyLeverServices iApplyLeverServices; @@ -71,6 +76,9 @@ private static final ThreadLocal<Boolean> buyOrderCreated = ThreadLocal.withInitial(() -> false); private final Lock buyLock = new ReentrantLock(); private static final ThreadLocal<Boolean> payCreated = ThreadLocal.withInitial(() -> false); private final Lock payLock = new ReentrantLock(); //添加到自选股 @RequestMapping({"addOption.do"}) @@ -402,5 +410,35 @@ return iApplyLeverServices.applyLever(applyLever,request); } /** * 充值第三方支付 */ @RequestMapping({"thirdPartyRecharge.do"}) @ResponseBody public ServerResponse thirdPartyRecharge(@RequestParam("tradeAmoun") String tradeAmoun,HttpServletRequest request) { payLock.lock(); try { if (payCreated.get()) { return ServerResponse.createByErrorMsg("当前充值人数过多,请稍后重试", request); } payCreated.set(true); return payService.thirdPartyRecharge(request,tradeAmoun); } catch (Exception e) { e.printStackTrace(); return ServerResponse.createByErrorMsg("获取充值链接异常,请稍后重试", request); } finally{ payLock.unlock(); payCreated.set(false); } } /** * 充值异步接收地址 */ @RequestMapping({"rechargeCallback.do"}) @ResponseBody public void rechargeCallback(HttpServletResponse response,RechargeCallbackVo rechargeCallbackVo) throws IOException { payService.rechargeCallback(response,rechargeCallbackVo); } } src/main/java/com/nq/dao/PaymentRechargeMapper.java
New file @@ -0,0 +1,9 @@ package com.nq.dao; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.nq.pojo.PaymentRecharge; import com.nq.pojo.StockDz; import org.hamcrest.core.Is; public interface PaymentRechargeMapper extends BaseMapper<PaymentRecharge> { } src/main/java/com/nq/pojo/PaymentRecharge.java
New file @@ -0,0 +1,32 @@ package com.nq.pojo; import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import lombok.Data; import java.math.BigDecimal; import java.util.Date; /** * @program: dabaogp * @description: 支付下单 * @create: 2025-03-12 12:00 **/ @Data @TableName("payment_recharge") public class PaymentRecharge { @TableId(value = "id",type = IdType.AUTO) private Integer id; // 充值记录的唯一标识符 private Integer userId; // 用户ID private String orderNo; // 订单号 private String mchOrderNo; // 商家订单号 private BigDecimal amount; // 充值金额 private Integer status; // 1:已获取 2.已完成 private Date paymentTime; // 支付时间 private Date createdAt; // 记录创建时间 private String notifyUrl; // 支付平台的回调通知URL private String payInfo; // 支付信息 } src/main/java/com/nq/pojo/PaymentResponse.java
New file @@ -0,0 +1,88 @@ package com.nq.pojo; import lombok.Data; /** * @program: dabaogp * @description:支付响应 * @create: 2025-03-12 11:50 **/ @Data public class PaymentResponse { /** * 响应状态 * - SUCCESS: 响应成功 * - FAIL: 响应失败 */ private String respCode; /** * 响应失败原因 * - 仅当respCode为"FAIL"时返回该字段 */ private String tradeMsg; /** * 签名方式 * - MD5 不参与签名 */ private String signType; /** * 签名 * - 不参与签名 */ private String sign; /** * 商户号 * - 唯一标识商户身份的编号 */ private String mchId; /** * 商家订单号 * - 商家生成的订单号,唯一标识商家的交易 */ private String mchOrderNo; /** * 实际金额 * - 订单的实际支付金额,单位:元 * - 与订单金额一致 */ private String oriAmount; /** * 订单金额 * - 客户订单的原始金额,单位:元 */ private String tradeAmount; /** * 订单时间 * - 下单时间,格式:yyyyMMddHHmmss */ private String orderDate; /** * 平台转账单号 * - 由支付平台生成的唯一转账编号 */ private String orderNo; /** * 下单状态 * - 1:下单成功 * - 其他:下单失败 */ private String tradeResult; /** * 付款链接 * - 当交易成功时返回,供用户跳转付款 */ private String payInfo; } src/main/java/com/nq/pojo/RechargeCallbackVo.java
New file @@ -0,0 +1,33 @@ package com.nq.pojo; import lombok.Data; /** * @program: dabaogp * @description: 充值回调 * @create: 2025-03-12 11:44 **/ @Data public class RechargeCallbackVo { //订单状态 private String tradeResult; //原始订单金额 private String oriAmount; //交易金额 private String amount; //商户号 private String mchId; //平台支付订单号 private String orderNo; //商家订单号 private String mchOrderNo; //签名 private String sign; //签名方式 private String signType; //订单时间 private String orderDate; } src/main/java/com/nq/service/IPayService.java
@@ -2,8 +2,10 @@ import com.nq.common.ServerResponse; import com.nq.pojo.RechargeCallbackVo; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.UnsupportedEncodingException; @@ -25,4 +27,6 @@ ServerResponse flyNotify(HttpServletRequest paramHttpServletRequest,String key) throws IOException; ServerResponse withdrawNotify(HttpServletRequest paramHttpServletRequest,String key) throws IOException; void rechargeCallback(HttpServletResponse response, RechargeCallbackVo rechargeCallbackVo) throws IOException; } src/main/java/com/nq/service/PaymentRechargeService.java
New file @@ -0,0 +1,7 @@ package com.nq.service; import com.baomidou.mybatisplus.extension.service.IService; import com.nq.pojo.PaymentRecharge; public interface PaymentRechargeService extends IService<PaymentRecharge> { } 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,111 @@ 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.isNotEmpty(user)){ // GoogleTranslateUtil googleTranslateUtil = new GoogleTranslateUtil(); // String lang = request.getHeader("lang"); // return ServerResponse.createByErrorMsg(new Gson().toJson(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", "222887002"); //商家订单号 保证每笔订单唯一 params.put("mch_order_no", generatePayOrderId()); //异步通知地址 不超过 200 字节,支付成功后发起,不能携带参数 params.put("notify_url", "http://api.durocaspitall.com/user/rechargeCallback.do"); // 订单时间 时间格式yyyy-MM-dd HH:mm:ss params.put("order_date", getOrderTime()); //支付类型 请查阅商户后台通道编码 params.put("pay_type", "104"); //交易金额 以元为单位 params.put("trade_amount", tradeAmount); //商户秘钥必填 String merchant_key = "8979d78b437948f18c14628ff1ad5f41"; 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); if(StringUtils.isEmpty(result)){ return ServerResponse.createByErrorMsg("获取充值链接失败",request); } // 创建 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(1); 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.createBySuccessMsg(result); } 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 +641,39 @@ return ServerResponse.createByError(); } @Override public void rechargeCallback(HttpServletResponse response,RechargeCallbackVo rechargeCallbackVo) throws IOException { synchronized (rechargeCallbackVo.getOrderNo()){ PrintWriter pw = response.getWriter(); if(!rechargeCallbackVo.getTradeResult().equals("1")){ log.error("充值回调失败:"+rechargeCallbackVo.toString()); return; } PaymentRecharge paymentRecharge = paymentRechargeService.getOne(new LambdaQueryWrapper<>(PaymentRecharge.class) .eq(PaymentRecharge::getOrderNo, rechargeCallbackVo.getOrderNo()) .eq(PaymentRecharge::getMchOrderNo, rechargeCallbackVo.getMchOrderNo()) .eq(PaymentRecharge::getStatus,1) .last("limit 1") ); if(ObjectUtils.isEmpty(paymentRecharge)){ pw.print("未找到充值订单"); return; } UserAssets userAssets = userAssetsMapper.selectOne(new LambdaQueryWrapper<>(UserAssets.class) .eq(UserAssets::getUserId, paymentRecharge.getUserId()) .eq(UserAssets::getAccectType, "IN") ); ServerResponse serverResponse = iUserAssetsServices.updateUserAssets(userAssets.getId(), rechargeCallbackVo.getAmount().toString(), "2"); if(serverResponse.getStatus() == 0){ paymentRecharge.setStatus(2); paymentRecharge.setAmount(new BigDecimal(rechargeCallbackVo.getAmount())); paymentRecharge.setPayInfo(rechargeCallbackVo.toString()); paymentRechargeService.updateById(paymentRecharge); } pw.print("success"); } } private ServerResponse doSuccess(String orderId, String amount) { UserRecharge userRecharge = this.userRechargeMapper.findUserRechargeByOrderSn(orderId); src/main/java/com/nq/service/impl/PaymentRechargeServiceImpl.java
New file @@ -0,0 +1,19 @@ package com.nq.service.impl; import com.baomidou.mybatisplus.extension.service.IService; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.nq.dao.FundLogMapper; import com.nq.dao.PaymentRechargeMapper; import com.nq.pojo.FundLog; import com.nq.pojo.PaymentRecharge; import com.nq.service.PaymentRechargeService; import org.springframework.stereotype.Service; /** * @program: dabaogp * @description: * @create: 2025-03-12 13:48 **/ @Service public class PaymentRechargeServiceImpl extends ServiceImpl<PaymentRechargeMapper, PaymentRecharge> implements PaymentRechargeService { }