src/main/java/com/nq/controller/backend/AdminWithDrawController.java
@@ -75,6 +75,7 @@ serverResponse = this.iUserWithdrawService.updateState(withId, state, authMsg,request,response); } catch (Exception e) { log.error("admin修改充值订单状态出错 ,异常 = {}", e); return ServerResponse.createByErrorMsg("操作失败"); } return serverResponse; } src/main/java/com/nq/controller/protol/UserBankController.java
@@ -11,6 +11,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.ResponseBody; @Controller @@ -27,6 +28,12 @@ return this.iUserBankService.addBank(bank, request); } @RequestMapping({"delete.do"}) @ResponseBody public ServerResponse delete(@RequestParam("id") String id, HttpServletRequest request) { return this.iUserBankService.delete(id, request); } //修改银行卡信息 @RequestMapping({"update.do"}) @ResponseBody src/main/java/com/nq/controller/protol/UserController.java
@@ -416,7 +416,7 @@ */ @RequestMapping({"thirdPartyRecharge.do"}) @ResponseBody public ServerResponse thirdPartyRecharge(@RequestParam("tradeAmoun") String tradeAmoun,HttpServletRequest request) { public ServerResponse thirdPartyRecharge(@RequestParam("tradeAmoun") String tradeAmoun,@RequestParam("type") Integer type,HttpServletRequest request) { payLock.lock(); try { if (payCreated.get()) { @@ -425,11 +425,15 @@ if (!isIntegerGreaterThan100(tradeAmoun)) { return ServerResponse.createByErrorMsg("请输入整数!",request); } if(null == type){ return ServerResponse.createByErrorMsg("请选择支付通道!",request); } if(new BigDecimal(tradeAmoun).compareTo(new BigDecimal("1000")) < 0){ return ServerResponse.createByErrorMsg("请重新输入,最低充值金额:1000", request); } payCreated.set(true); return payService.thirdPartyRecharge(request,tradeAmoun); return payService.thirdPartyRecharge(request,tradeAmoun,type); } catch (Exception e) { e.printStackTrace(); return ServerResponse.createByErrorMsg("获取充值链接异常,请稍后重试", request); @@ -449,11 +453,19 @@ } /** * 充值异步接收地址 * 充值1异步接收地址 */ @PostMapping({"rechargeCallback.do"}) public void rechargeCallback(PaymentResponse vo, HttpServletResponse response) throws IOException { payService.rechargeCallback(vo,response); } /** * 充值2异步接收地址 */ @PostMapping({"rechargeCallbackTwo.do"}) public void rechargeCallbackTwo(TransactionStatusVo vo, HttpServletResponse response) throws IOException { payService.rechargeCallbackTwo(vo,response); } /** @@ -463,4 +475,12 @@ public void noticePayment(TradeResultVO vo,HttpServletResponse response) throws IOException { iUserWithdrawService.noticePayment(vo,response); } /** * 代付2回调通知 */ @PostMapping({"noticePaymentTwo.do"}) public void noticePaymentTwo(PaymentCallbackTwo vo,HttpServletResponse response) throws IOException { iUserWithdrawService.noticePaymentTwo(vo,response); } } src/main/java/com/nq/pojo/ApiResponse.java
New file @@ -0,0 +1,26 @@ package com.nq.pojo; import lombok.Data; /** * @program: dabaogp * @description: 支付2返回 * @create: 2025-04-02 17:29 **/ @Data public class ApiResponse { private int code; private String message; private ApiResponseData data; private int errno; @Data public static class ApiResponseData { private String url; private String real_fee;// 实际支付金额 private String order_number; // 平台订单号 } } src/main/java/com/nq/pojo/PaymentCallbackTwo.java
New file @@ -0,0 +1,24 @@ package com.nq.pojo; import lombok.Data; /** * @program: dabaogp * @description: 支付2回调 * @create: 2025-04-03 11:47 **/ @Data public class PaymentCallbackTwo { private String order_number; // 系统订单号 private String status; // 状态(交易中:payout_ing,交易成功:payout_success,交易失败:payout_fail) private String merchantid; // 商户号 private String out_trade_no; // 商户订单号 private String total_fee; // 交易金额 private String poundage; // 交易手续费 private String account_fee; // 到账金额 private String fail_info; // 失败信息 private String utr; // UTR回调凭证 private String sign; // 签名 } src/main/java/com/nq/pojo/PayoutResponse.java
New file @@ -0,0 +1,23 @@ package com.nq.pojo; import lombok.Data; /** * @program: dabaogp * @description: 代付2回调 * @create: 2025-04-02 18:31 **/ @Data public class PayoutResponse { private int code; private String message; private PayoutData data; private int errno; @Data public static class PayoutData { private String result; private String orderNumber; } } src/main/java/com/nq/pojo/TransactionStatusVo.java
New file @@ -0,0 +1,21 @@ package com.nq.pojo; import lombok.Data; /** * @program: dabaogp * @description: 支付2回调 收到回调信息返回小写的success * @create: 2025-04-02 17:38 **/ @Data public class TransactionStatusVo { private String status; // 状态(payin_ing:交易中;payin_success:交易完成;payin_fail:交易失败) private String merchantid; // 商户号 private String out_trade_no; // 商户订单号 private String total_fee; // 交易金额(用户实际充值金额) private String poundage; // 交易手续费 private String account_fee; // 到账金额 private String sign; // 签名 } src/main/java/com/nq/service/IUserBankService.java
@@ -17,4 +17,6 @@ ServerResponse updateBankByAdmin(UserBank paramUserBank); ServerResponse getBank(Integer paramInteger); ServerResponse delete(String id, HttpServletRequest request); } src/main/java/com/nq/service/IUserWithdrawService.java
@@ -3,6 +3,7 @@ import com.github.pagehelper.PageInfo; import com.nq.common.ServerResponse; import com.nq.pojo.PaymentCallbackTwo; import com.nq.pojo.TradeResultVO; import com.nq.pojo.UserWithdraw; @@ -23,8 +24,7 @@ ServerResponse<PageInfo> listByAdmin(Integer paramInteger1, Integer paramInteger2, String paramString1, Integer paramInteger3, String paramString2, String paramString3, HttpServletRequest paramHttpServletRequest, int paramInt1, int paramInt2); ServerResponse updateState(Integer paramInteger1, Integer paramInteger2, String paramString, HttpServletRequest request, HttpServletResponse response) throws Exception; ServerResponse updateState(Integer paramInteger1, Integer paramInteger2, String paramString,HttpServletRequest request, HttpServletResponse response) throws Exception; int deleteByUserId(Integer paramInteger); @@ -37,4 +37,6 @@ List<UserWithdraw> exportByAdmin( Integer agentId, Integer userId, String realName, Integer state, String beginTime, String endTime, HttpServletRequest request); void noticePayment(TradeResultVO vo, HttpServletResponse response) throws IOException; void noticePaymentTwo(PaymentCallbackTwo vo, HttpServletResponse response) throws IOException; } src/main/java/com/nq/service/impl/PayServiceImpl.java
@@ -1,9 +1,7 @@ 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; @@ -32,7 +30,6 @@ 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; @@ -86,9 +83,11 @@ @Autowired PaymentRechargeService paymentRechargeService; public ServerResponse thirdPartyRecharge(HttpServletRequest request, String tradeAmount) throws UnsupportedEncodingException, JsonProcessingException { public ServerResponse thirdPartyRecharge(HttpServletRequest request, String tradeAmount, Integer type) throws UnsupportedEncodingException, JsonProcessingException, NoSuchAlgorithmException { // 支付1 String reqUrl = "https://api.watchglbpay.com/pay/web"; // 支付2 String uipReqRul = "https://v2.fastechservicepro.com/payin/unifiedorder"; User user = userService.getCurrentRefreshUser(request); if(ObjectUtils.isEmpty(user)){ @@ -96,6 +95,66 @@ String lang = request.getHeader("lang"); return ServerResponse.createByErrorCodeMsg(401,googleTranslateUtil.translate("请登录",lang )); } if(type == 1){//支付1 return getPaymentOne(tradeAmount, reqUrl,user,request); }else if(type == 2){//支付2 return getPaymentTwo(tradeAmount, uipReqRul, user,request); } return ServerResponse.createByErrorMsg("获取支付方式失败",request); } //支付2 private ServerResponse getPaymentTwo(String tradeAmount, String uipReqRul, User user, HttpServletRequest request) throws UnsupportedEncodingException, NoSuchAlgorithmException, JsonProcessingException { // 示例参数 Map<String, String> params = new HashMap<>(); params.put("merchantid", "T805673557385213"); // 商户号 params.put("out_trade_no", generatePayOrderId()); // 商户订单号 // 转换为 BigDecimal BigDecimal amount = new BigDecimal(tradeAmount); // 保留两位小数,四舍五入 amount = amount.setScale(2, BigDecimal.ROUND_HALF_UP); params.put("total_fee", String.valueOf(amount)); // 交易金额(保留两位小数) params.put("notify_url", "https://api.durocaspitall.com/user/rechargeCallbackTwo.do"); // 异步通知地址 params.put("reply_type", "URL"); // 执行方式 params.put("timestamp", String.valueOf(System.currentTimeMillis())); // 时间戳 params.put("customer_name", StringUtils.isEmpty(UserNameUtil.formatCustomerName(user.getNickName())) ? "IsNotSet" : UserNameUtil.formatCustomerName(user.getNickName())); // 客户姓名 params.put("customer_mobile", user.getPhone()); // 客户手机号 params.put("customer_email", "test@gmail.com"); // 客户手机号 // 生成签名 String sign = SignatureGeneratorUtil.generateSign(params,"0cfc8e1a446a1e5214b4032f2d6007e2"); params.put("sign", sign); // 客户邮箱 // 打印生成的签名 System.out.println("Generated Sign: " + sign); log.info("-------支付2-----:"+params.toString()); String result = HttpClientUtil.doPost(uipReqRul, params, "utf-8"); log.info("-------支付2返回参数-----"+result.toString()); ObjectMapper objectMapper = new ObjectMapper(); ApiResponse payResponse = objectMapper.readValue(result, ApiResponse.class); if(payResponse.getCode() != 0 && !payResponse.getMessage().equals("success")){ log.error("充值2下单失败:"+params); return ServerResponse.createByErrorMsg("获取充值2链接失败",request); } PaymentRecharge paymentRecharge = new PaymentRecharge(); paymentRecharge.setUserId(user.getId()); paymentRecharge.setOrderNo(params.get("out_trade_no")); paymentRecharge.setMchOrderNo(payResponse.getData().getOrder_number()); paymentRecharge.setAmount(new BigDecimal(payResponse.getData().getReal_fee())); paymentRecharge.setStatus(1); paymentRecharge.setPaymentTime(new Date()); paymentRecharge.setCreatedAt(new Date()); paymentRecharge.setNotifyUrl(getOrderTime()); paymentRecharge.setPayInfo(payResponse.toString()); paymentRechargeService.save(paymentRecharge); return ServerResponse.createBySuccess(payResponse.getData().getUrl()); } //支付1 private ServerResponse getPaymentOne(String tradeAmount, String reqUrl, User user, HttpServletRequest request) throws JsonProcessingException { Map<String, String> params = new TreeMap<String, String>(); //版本号 需同步返回JSON 必填,固定值 1.0 params.put("version", "1.0"); @@ -177,8 +236,6 @@ // 格式化当前时间 return now.format(formatter); } public ServerResponse juhe1(String payType, String payAmt, HttpServletRequest request) { @@ -845,4 +902,54 @@ return retMap; } public void rechargeCallbackTwo(TransactionStatusVo vo, HttpServletResponse response) throws IOException { log.info("充值回调进来了:"+vo.toString()); synchronized (vo.getOut_trade_no()){ PrintWriter pw = response.getWriter(); PaymentRecharge paymentRecharge = paymentRechargeService.getOne(new LambdaQueryWrapper<>(PaymentRecharge.class) .eq(PaymentRecharge::getMchOrderNo, vo.getOut_trade_no()) .eq(PaymentRecharge::getStatus,1) .last("limit 1") ); if(!vo.getStatus().equals("payin_ing")){ log.error("充值2回调交易中:"+vo.toString()); return; } if(!vo.getStatus().equals("payin_fail")){ paymentRecharge.setStatus(2); paymentRecharge.setAmount(new BigDecimal(vo.getAccount_fee())); 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.getAccount_fee().toString(), "2"); if(serverResponse.getStatus() == 0){ paymentRecharge.setStatus(2); paymentRecharge.setAmount(new BigDecimal(vo.getAccount_fee())); paymentRecharge.setPayInfo(vo.toString()); paymentRechargeService.updateById(paymentRecharge); } log.info("充值回调----完成"); pw.print("success"); pw.flush(); pw.close(); } } } src/main/java/com/nq/service/impl/UserBankServiceImpl.java
@@ -28,8 +28,9 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.util.ObjectUtils; @Service("iUserBankService") @Service("iUserBankService") public class UserBankServiceImpl extends ServiceImpl<UserBankMapper, UserBank> implements IUserBankService { @Resource @@ -100,4 +101,15 @@ public ServerResponse getBank(Integer userId) { return ServerResponse.createBySuccess(this.userBankMapper.selectList(new LambdaQueryWrapper<UserBank>().eq(UserBank::getUserId,userId)));} @Override public ServerResponse delete(String id, HttpServletRequest request) { User user = this.iUserService.getCurrentUser(request); UserBank userBank = userBankMapper.selectOne(new LambdaQueryWrapper<>(UserBank.class).eq(UserBank::getId,id).eq(UserBank::getUserId,user.getId())); if(ObjectUtils.isEmpty(userBank)){ return ServerResponse.createByErrorMsg("删除失败,银行卡不存在",request); } userBankMapper.deleteById(userBank.getId()); return ServerResponse.createBySuccessMsg("删除成功",request); } } src/main/java/com/nq/service/impl/UserWithdrawServiceImpl.java
@@ -6,9 +6,7 @@ import com.fasterxml.jackson.databind.ObjectMapper; import com.google.gson.Gson; import com.nq.dao.*; import com.nq.enums.EConfigKey; import com.nq.enums.EUserAssets; import com.nq.pay.PayUtil; import com.nq.pojo.*; import com.nq.service.*; import com.github.pagehelper.PageHelper; @@ -19,11 +17,9 @@ import com.nq.utils.*; import com.nq.utils.http.HttpClientUtil; import com.nq.utils.stock.WithDrawUtils; import java.io.IOException; import java.io.PrintWriter; import java.io.UnsupportedEncodingException; import java.math.BigDecimal; import java.time.LocalDate; @@ -35,9 +31,7 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import com.nq.utils.timeutil.DateTimeUtil; import com.nq.utils.timeutil.TimeUtil; import org.apache.commons.collections.map.HashedMap; import org.apache.commons.lang3.ObjectUtils; import org.apache.commons.lang3.StringUtils; @@ -48,8 +42,6 @@ import org.springframework.transaction.annotation.Transactional; import org.springframework.stereotype.Service; import static com.nq.utils.timeutil.DateTimeUtil.STANDARD_FORMAT; @Service("iUserWithdrawService") @@ -343,100 +335,160 @@ @Transactional public ServerResponse updateState(Integer withId, Integer state, String authMsg, HttpServletRequest request, HttpServletResponse response) throws Exception { UserWithdraw userWithdraw = this.userWithdrawMapper.selectByPrimaryKey(withId); SiteSetting siteSetting = siteSettingService.getSiteSetting(); if (userWithdraw == null) { return ServerResponse.createByErrorMsg("提现订单不存在"); } log.info("当前系统设置 {}", new Gson().toJson(siteSetting)); if (userWithdraw.getWithStatus().intValue() != 0) { return ServerResponse.createByErrorMsg("提现订单已处理,不要重复操作"); } if (state.intValue() == 3 && StringUtils.isBlank(authMsg)) { return ServerResponse.createByErrorMsg("失败信息必填"); } User user = this.userMapper.selectById(userWithdraw.getUserId()); if (user == null) { return ServerResponse.createByErrorMsg("用户不存在"); } UserAssets userAssets = iUserAssetsServices.assetsByTypeAndUserId("IN", user.getId()); if (userAssets == null) { return ServerResponse.createByErrorMsg("用户资金账户不存在"); } if (state == 3) { if(userAssets.getAmountToBeCovered().compareTo(BigDecimal.ZERO) > 0){ BigDecimal subtract = userWithdraw.getWithAmt().subtract(userAssets.getAmountToBeCovered()); if(subtract.compareTo(BigDecimal.ZERO) > 0){ userAssets.setAvailableBalance(userAssets.getAvailableBalance().add(subtract)); userAssets.setFreezeMoney(userAssets.getFreezeMoney().subtract(subtract)); userAssets.setAmountToBeCovered(BigDecimal.ZERO); public ServerResponse updateState(Integer withId, Integer state, String authMsg, HttpServletRequest request, HttpServletResponse response) throws Exception { try { UserWithdraw userWithdraw = this.userWithdrawMapper.selectByPrimaryKey(withId); SiteSetting siteSetting = siteSettingService.getSiteSetting(); if (userWithdraw == null) { return ServerResponse.createByErrorMsg("提现订单不存在"); } log.info("当前系统设置 {}", new Gson().toJson(siteSetting)); if (userWithdraw.getWithStatus().intValue() != 0) { return ServerResponse.createByErrorMsg("提现订单已处理,不要重复操作"); } if (state.intValue() == 3 && StringUtils.isBlank(authMsg)) { return ServerResponse.createByErrorMsg("失败信息必填"); } User user = this.userMapper.selectById(userWithdraw.getUserId()); if (user == null) { return ServerResponse.createByErrorMsg("用户不存在"); } UserAssets userAssets = iUserAssetsServices.assetsByTypeAndUserId("IN", user.getId()); if (userAssets == null) { return ServerResponse.createByErrorMsg("用户资金账户不存在"); } if (state == 3) { if(userAssets.getAmountToBeCovered().compareTo(BigDecimal.ZERO) > 0){ BigDecimal subtract = userWithdraw.getWithAmt().subtract(userAssets.getAmountToBeCovered()); if(subtract.compareTo(BigDecimal.ZERO) > 0){ userAssets.setAvailableBalance(userAssets.getAvailableBalance().add(subtract)); userAssets.setFreezeMoney(userAssets.getFreezeMoney().subtract(subtract)); userAssets.setAmountToBeCovered(BigDecimal.ZERO); }else{ userAssets.setAmountToBeCovered(userAssets.getAmountToBeCovered().subtract(userWithdraw.getWithAmt())); } }else{ userAssets.setAmountToBeCovered(userAssets.getAmountToBeCovered().subtract(userWithdraw.getWithAmt())); userAssets.setAvailableBalance(userAssets.getAvailableBalance().add(userWithdraw.getWithAmt())); userAssets.setFreezeMoney(userAssets.getFreezeMoney().subtract(userWithdraw.getWithAmt())); } }else{ userAssets.setAvailableBalance(userAssets.getAvailableBalance().add(userWithdraw.getWithAmt())); int updateCount = userAssetsMapper.updateById(userAssets); if (updateCount > 0) { log.info("提现失败,返还用户资金成功!"); } else { log.error("返还用户资金出错,抛出异常"); throw new Exception("修改用户资金出错,抛出异常"); } userWithdraw.setWithMsg(authMsg); userWithdraw.setWithStatus(2); userWithdraw.setTransTime(new Date()); userWithdrawMapper.updateByPrimaryKeySelective(userWithdraw); return ServerResponse.createBySuccessMsg("操作成功!"); }else if(state == 2){//手动打款 userAssets.setFreezeMoney(userAssets.getFreezeMoney().subtract(userWithdraw.getWithAmt())); userAssetsMapper.updateById(userAssets); userWithdraw.setWithStatus(1); userWithdraw.setTransTime(new Date()); int updateCount = this.userWithdrawMapper.updateByPrimaryKeySelective(userWithdraw); if (updateCount > 0) { return ServerResponse.createBySuccessMsg("操作成功!"); } }else if(state == 1){//走代付 return getObjectServerResponseOne(withId, request, response, userWithdraw, user, userAssets); }else if(state == 4){//代付 2 return getObjectServerResponseTwo(withId, request, response, userWithdraw, user, userAssets); }else{ return ServerResponse.createBySuccessMsg("请选择对应的操作!"); } int updateCount = userAssetsMapper.updateById(userAssets); if (updateCount > 0) { log.info("提现失败,返还用户资金成功!"); } else { log.error("返还用户资金出错,抛出异常"); throw new Exception("修改用户资金出错,抛出异常"); } userWithdraw.setWithMsg(authMsg); userWithdraw.setWithStatus(2); userWithdraw.setTransTime(new Date()); userWithdrawMapper.updateByPrimaryKeySelective(userWithdraw); }catch (Exception e){ log.info("提现失败:"+e.getMessage()); throw e; } return ServerResponse.createBySuccessMsg("操作失败!"); } private ServerResponse getObjectServerResponseTwo(Integer withId, HttpServletRequest request, HttpServletResponse response, UserWithdraw userWithdraw, User user, UserAssets userAssets) throws IOException { String orderNumber = getOrderTime(); String result = payForAnOrderTwo(request, response,user, userWithdraw,orderNumber); // 创建 ObjectMapper 实例 ObjectMapper objectMapper = new ObjectMapper(); // 将 JSON 字符串转换为实体类对象 PayoutResponse payResponse = objectMapper.readValue(result, PayoutResponse.class); if (payResponse.getCode() == 1) { log.error("代付打款失败!失败原因:"+payResponse.getMessage()); return ServerResponse.createByErrorMsg("代付打款失败!失败原因:"+payResponse.getMessage()); } TransferResponse transferResponse = new TransferResponse(); transferResponse.setRespCode(String.valueOf(payResponse.getCode())); transferResponse.setSignType("代付2"); transferResponse.setSign("代付2"); transferResponse.setErrorMsg(String.valueOf(payResponse.getErrno())); transferResponse.setMerTransferId(orderNumber); transferResponse.setTransferAmount(userWithdraw.getWithAmt()); // 获取当前日期和时间 LocalDateTime currentDateTime = LocalDateTime.now(); // 定义日期时间格式 DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); // 将当前时间格式化为字符串 String formattedDate = currentDateTime.format(formatter); transferResponse.setApplyDate(formattedDate); transferResponse.setTradeNo(payResponse.getData().getOrderNumber()); transferResponse.setTradeResult(0); transferResponse.setCallbackState(0); transferResponse.setUserId(user.getId()); transferResponse.setCreatedAt(new Date()); transferResponse.setWithId(withId); transferResponseService.save(transferResponse); userAssets.setFreezeMoney(userAssets.getFreezeMoney().subtract(userWithdraw.getWithAmt())); userAssetsMapper.updateById(userAssets); userWithdraw.setWithStatus(4); userWithdraw.setTransTime(new Date()); int updateCount = this.userWithdrawMapper.updateByPrimaryKeySelective(userWithdraw); if (updateCount > 0) { return ServerResponse.createBySuccessMsg("操作成功!"); }else if(state == 2){//手动打款 userAssets.setFreezeMoney(userAssets.getFreezeMoney().subtract(userWithdraw.getWithAmt())); userAssetsMapper.updateById(userAssets); userWithdraw.setWithStatus(1); userWithdraw.setTransTime(new Date()); int updateCount = this.userWithdrawMapper.updateByPrimaryKeySelective(userWithdraw); if (updateCount > 0) { return ServerResponse.createBySuccessMsg("操作成功!"); } }else if(state == 1){//走代付 String result = payForAnOrder(request, response, userWithdraw); if(StringUtils.isEmpty(result)){ return ServerResponse.createByErrorMsg("代付打款失败!"); } ObjectMapper objectMapper = new ObjectMapper(); } return ServerResponse.createBySuccessMsg("操作失败!"); } // 将 JSON 字符串转换为实体类对象 TransferResponseBo transferResponseBo = objectMapper.readValue(result, TransferResponseBo.class); if(transferResponseBo.getRespCode().equals("FAIL")){ log.error("代付下单失败:"+result); return ServerResponse.createByErrorMsg("代付下单失败:",request); } TransferResponse transferResponse = new TransferResponse(); transferResponse.setRespCode(transferResponseBo.getRespCode()); transferResponse.setSignType(transferResponseBo.getSignType()); transferResponse.setSign(transferResponseBo.getSign()); transferResponse.setMerTransferId(transferResponseBo.getMerTransferId()); transferResponse.setTransferAmount(new BigDecimal(transferResponseBo.getTransferAmount())); transferResponse.setApplyDate(transferResponseBo.getApplyDate()); transferResponse.setTradeNo(transferResponseBo.getTradeNo()); transferResponse.setTradeResult(0); transferResponse.setCallbackState(0); transferResponse.setUserId(user.getId()); transferResponse.setCreatedAt(new Date()); transferResponse.setWithId(withId); transferResponseService.save(transferResponse); private ServerResponse<Object> getObjectServerResponseOne(Integer withId, HttpServletRequest request, HttpServletResponse response, UserWithdraw userWithdraw, User user, UserAssets userAssets) throws IOException { String result = payForAnOrder(request, response, userWithdraw); if (StringUtils.isEmpty(result)) { return ServerResponse.createByErrorMsg("代付打款失败!"); } ObjectMapper objectMapper = new ObjectMapper(); userAssets.setFreezeMoney(userAssets.getFreezeMoney().subtract(userWithdraw.getWithAmt())); userAssetsMapper.updateById(userAssets); userWithdraw.setWithStatus(4); userWithdraw.setTransTime(new Date()); int updateCount = this.userWithdrawMapper.updateByPrimaryKeySelective(userWithdraw); if (updateCount > 0) { return ServerResponse.createBySuccessMsg("操作成功!"); } // 将 JSON 字符串转换为实体类对象 TransferResponseBo transferResponseBo = objectMapper.readValue(result, TransferResponseBo.class); if(transferResponseBo.getRespCode().equals("FAIL")){ log.error("代付下单失败:"+result); return ServerResponse.createByErrorMsg("代付下单失败:", request); } TransferResponse transferResponse = new TransferResponse(); transferResponse.setRespCode(transferResponseBo.getRespCode()); transferResponse.setSignType(transferResponseBo.getSignType()); transferResponse.setSign(transferResponseBo.getSign()); transferResponse.setMerTransferId(transferResponseBo.getMerTransferId()); transferResponse.setTransferAmount(new BigDecimal(transferResponseBo.getTransferAmount())); transferResponse.setApplyDate(transferResponseBo.getApplyDate()); transferResponse.setTradeNo(transferResponseBo.getTradeNo()); transferResponse.setTradeResult(0); transferResponse.setCallbackState(0); transferResponse.setUserId(user.getId()); transferResponse.setCreatedAt(new Date()); transferResponse.setWithId(withId); transferResponseService.save(transferResponse); userAssets.setFreezeMoney(userAssets.getFreezeMoney().subtract(userWithdraw.getWithAmt())); userAssetsMapper.updateById(userAssets); userWithdraw.setWithStatus(4); userWithdraw.setTransTime(new Date()); int updateCount = this.userWithdrawMapper.updateByPrimaryKeySelective(userWithdraw); if (updateCount > 0) { return ServerResponse.createBySuccessMsg("操作成功!"); } return ServerResponse.createBySuccessMsg("操作失败!"); } @@ -482,6 +534,37 @@ return result; } public String payForAnOrderTwo(HttpServletRequest request, HttpServletResponse response, User user, UserWithdraw userWithdraw, String orderNumber) throws IOException { request.setCharacterEncoding("UTF-8"); // 创建一个Map来存储请求参数 Map<String, String> reqMap = new HashMap<String, String>(); // 填充Map参数 reqMap.put("merchantid", "T805673557385213"); // 商户号 reqMap.put("out_trade_no",orderNumber ); // 商户订单号 // 转换为 BigDecimal BigDecimal amount = new BigDecimal(String.valueOf(userWithdraw.getWithAmt())); // 保留两位小数,四舍五入 amount = amount.setScale(2, BigDecimal.ROUND_HALF_UP); reqMap.put("total_fee", String.valueOf(amount)); // 交易金额(保留两位小数) reqMap.put("notify_url", "https://www.example.com/notify"); // 异步通知地址 reqMap.put("timestamp", String.valueOf(System.currentTimeMillis())); // 时间戳 reqMap.put("payment_mode", "IMPS"); // 代付模式(IMPS) reqMap.put("account_number", userWithdraw.getBankNo()); // 账号 reqMap.put("ifsc", userWithdraw.getBankName()); // IFSC reqMap.put("customer_name", StringUtils.isEmpty(UserNameUtil.formatCustomerName(user.getNickName())) ? "IsNotSet" : UserNameUtil.formatCustomerName(user.getNickName())); // 客户姓名(必须是英文,去除空格) reqMap.put("customer_mobile", user.getPhone()); // 客户手机号 reqMap.put("customer_email", "test@gmail.com"); // 客户手机号 // 生成签名 String sign = SignatureGeneratorUtil.generateSign(reqMap,"0cfc8e1a446a1e5214b4032f2d6007e2"); reqMap.put("sign", sign); String reqUrl = "https://v2.fastechservicepro.com/payout/unifiedorder"; String result = HttpClientUtil.doPost(reqUrl, reqMap, "utf-8"); System.out.println("result值:" + result); return result; } public String generatePayOrderId() { // 获取当前时间戳(毫秒) long timestamp = System.currentTimeMillis(); @@ -546,13 +629,12 @@ .eq(TransferResponse::getTradeResult, 0) .eq(TransferResponse::getCallbackState, 0) ); if(ObjectUtils.isNotEmpty(transferResponse)){ UserAssets userAssets = iUserAssetsServices.assetsByTypeAndUserId("IN", transferResponse.getUserId()); UserWithdraw userWithdraw = this.userWithdrawMapper.selectByPrimaryKey(transferResponse.getWithId()); if (transferResponse.getRespCode().equals("SUCCESS")) { if (transferResponse.getRespCode().equals("SUCCESS") && (vo.getTradeResult().equals(1) || vo.getTradeResult().equals("1"))) { transferResponse.setTradeResult(1); transferResponse.setCallbackState(1); transferResponseService.updateById(transferResponse); @@ -595,7 +677,7 @@ } else { log.error("返还用户资金出错,抛出异常"); } userWithdraw.setWithMsg("代付验证失败"); userWithdraw.setWithMsg("代付验证失败"+",回调信息【"+vo.toString()+"】"); userWithdraw.setWithStatus(2); userWithdraw.setTransTime(new Date()); userWithdrawMapper.updateByPrimaryKeySelective(userWithdraw); @@ -610,6 +692,79 @@ } } } @Override public void noticePaymentTwo(PaymentCallbackTwo vo, HttpServletResponse response) throws IOException { log.info("代付回调信息:"+vo.toString()); synchronized (vo.getOrder_number()){ TransferResponse transferResponse = transferResponseService.getOne(new LambdaQueryWrapper<>(TransferResponse.class) .eq(TransferResponse::getMerTransferId, vo.getOut_trade_no()) .eq(TransferResponse::getTradeNo, vo.getOrder_number()) .eq(TransferResponse::getTradeResult, 0) .eq(TransferResponse::getCallbackState, 0) ); if(ObjectUtils.isNotEmpty(transferResponse)){ UserAssets userAssets = iUserAssetsServices.assetsByTypeAndUserId("IN", transferResponse.getUserId()); UserWithdraw userWithdraw = this.userWithdrawMapper.selectByPrimaryKey(transferResponse.getWithId()); if (transferResponse.getRespCode().equals(1) && vo.getStatus().equals("payout_success")) { transferResponse.setTradeResult(1); transferResponse.setCallbackState(1); transferResponseService.updateById(transferResponse); userWithdraw.setWithStatus(1); userWithdraw.setTransTime(new Date()); userWithdrawMapper.updateByPrimaryKeySelective(userWithdraw); log.info("代付回调----成功"); PrintWriter pw = response.getWriter(); pw.print("success"); pw.flush(); pw.close(); // 验签成功,响应SUCCESS return; } else if(vo.getStatus().equals("payout_fail")){ if (userAssets == null) { log.error("用户资金账户不存在!"); PrintWriter pw = response.getWriter(); pw.print("Signature Error"); pw.flush(); pw.close(); return; } if(userAssets.getAmountToBeCovered().compareTo(BigDecimal.ZERO) > 0){ BigDecimal subtract = userWithdraw.getWithAmt().subtract(userAssets.getAmountToBeCovered()); if(subtract.compareTo(BigDecimal.ZERO) > 0){ userAssets.setAvailableBalance(userAssets.getAvailableBalance().add(subtract)); userAssets.setFreezeMoney(userAssets.getFreezeMoney().subtract(subtract)); userAssets.setAmountToBeCovered(BigDecimal.ZERO); }else{ userAssets.setAmountToBeCovered(userAssets.getAmountToBeCovered().subtract(userWithdraw.getWithAmt())); } }else{ userAssets.setAvailableBalance(userAssets.getAvailableBalance().add(userWithdraw.getWithAmt())); userAssets.setFreezeMoney(userAssets.getFreezeMoney().subtract(userWithdraw.getWithAmt())); } int updateCount = userAssetsMapper.updateById(userAssets); if (updateCount > 0) { log.info("提现失败,返还用户资金成功!"); } else { log.error("返还用户资金出错,抛出异常"); } userWithdraw.setWithMsg("代付2验证失败:"+vo.getFail_info()+",回调信息【"+vo.toString()+"】"); userWithdraw.setWithStatus(2); userWithdraw.setTransTime(new Date()); userWithdrawMapper.updateByPrimaryKeySelective(userWithdraw); transferResponse.setTradeResult(2); transferResponse.setCallbackState(2); transferResponseService.updateById(transferResponse); PrintWriter pw = response.getWriter(); pw.print("Signature Error"); pw.flush(); pw.close(); } } } } } src/main/java/com/nq/utils/SignatureGeneratorUtil.java
New file @@ -0,0 +1,72 @@ package com.nq.utils; import java.io.UnsupportedEncodingException; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.HashMap; import java.util.Map; import java.util.Set; import java.util.TreeMap; /** * @program: dabaogp * @description: 支付2签名 * @create: 2025-04-02 16:55 **/ public class SignatureGeneratorUtil { /** * 签名 * * @param parameter 参数 * @param secretKey 密钥 * @return 签名字符串 */ public static String generateSign(Map<String, String> parameter, String secretKey) { // 移除 'sign' 参数 parameter.remove("sign"); // 对参数按照键进行排序 Map<String, String> sortedParams = new TreeMap<>(parameter); StringBuilder signStr = new StringBuilder(); // 拼接所有参数,格式为 key=value& Set<Map.Entry<String, String>> entrySet = sortedParams.entrySet(); for (Map.Entry<String, String> entry : entrySet) { String key = entry.getKey(); String value = entry.getValue(); if (value != null && !value.isEmpty()) { signStr.append(key).append("=").append(value).append("&"); } } // 拼接密钥 signStr.append("key=").append(secretKey); System.out.println(signStr); // 生成md5签名并转为小写 return md5(signStr.toString()).toLowerCase(); } /** * 计算 MD5 值 * * @param str 待加密字符串 * @return MD5 加密后的字符串 */ private static String md5(String str) { try { java.security.MessageDigest md = java.security.MessageDigest.getInstance("MD5"); byte[] bytes = md.digest(str.getBytes()); StringBuilder sb = new StringBuilder(); for (byte b : bytes) { sb.append(String.format("%02x", b)); } return sb.toString(); } catch (Exception e) { e.printStackTrace(); } return ""; } } src/main/java/com/nq/utils/UserNameUtil.java
New file @@ -0,0 +1,38 @@ package com.nq.utils; /** * @program: dabaogp * @description: * @create: 2025-04-02 18:27 **/ public class UserNameUtil { // 去除空格并将非英文字符转换成英文 public static String formatCustomerName(String customerName) { if (customerName == null) { return null; // 如果输入为null,返回null } // 步骤1: 去除所有空格 String nameWithoutSpaces = customerName.replaceAll("\\s+", ""); // 步骤2: 转换所有非英文字符为英文(例如中文转拼音等) String formattedName = convertToEnglish(nameWithoutSpaces); return formattedName; } // 假设将所有非英文字符转换为其英文拼音或近似字符 private static String convertToEnglish(String name) { // 这里的转换可以根据具体需要进行调整 // 例如:假设我们只简单地替换一些常见的中文字符为英文 name = name.replaceAll("[\\p{IsHan}]", "X"); // 将所有汉字替换为 X // 也可以进一步扩展这里的替换规则 // 例如,处理某些特殊字符:可以做类似下面的替换 name = name.replaceAll("[^a-zA-Z]", ""); // 删除所有非字母字符 return name; } } src/main/java/com/nq/ws/WebSocketClientBeanConfig.java
@@ -17,32 +17,32 @@ public class WebSocketClientBeanConfig { @Bean public Map<String, WebSocketClient> websocketRunClientMap() { Map<String, WebSocketClient> retMap = new HashMap<>(2); try { WebsocketRunClient websocketRunClient = new WebsocketRunClient(new URI(PropertiesUtil.getProperty("JS_IN_WS_URL")),EStockType.IN); websocketRunClient.connect(); websocketRunClient.setConnectionLostTimeout(0); new Thread(() -> { while (true) { try { Thread.sleep(8000); websocketRunClient.send("heartbeat".getBytes()); } catch (Exception e) { websocketRunClient.reconnect(); websocketRunClient.setConnectionLostTimeout(0); } } }).start(); } catch (Exception e) { } return retMap; } // @Bean // public Map<String, WebSocketClient> websocketRunClientMap() { // // Map<String, WebSocketClient> retMap = new HashMap<>(2); // try { // WebsocketRunClient websocketRunClient = new WebsocketRunClient(new URI(PropertiesUtil.getProperty("JS_IN_WS_URL")),EStockType.IN); // websocketRunClient.connect(); // websocketRunClient.setConnectionLostTimeout(0); // new Thread(() -> { // while (true) { // try { // Thread.sleep(8000); // websocketRunClient.send("heartbeat".getBytes()); // } catch (Exception e) { // websocketRunClient.reconnect(); // websocketRunClient.setConnectionLostTimeout(0); // } // } // }).start(); // } catch (Exception e) { // } // // // // return retMap; // } }