From efb07bcec37c49228d9760794f215c8549243ad2 Mon Sep 17 00:00:00 2001
From: zj <1772600164@qq.com>
Date: Mon, 23 Mar 2026 18:52:21 +0800
Subject: [PATCH] 1
---
src/main/java/com/nq/service/impl/PayServiceImpl.java | 353 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 353 insertions(+), 0 deletions(-)
diff --git a/src/main/java/com/nq/service/impl/PayServiceImpl.java b/src/main/java/com/nq/service/impl/PayServiceImpl.java
index c61efce..d00f6e1 100644
--- a/src/main/java/com/nq/service/impl/PayServiceImpl.java
+++ b/src/main/java/com/nq/service/impl/PayServiceImpl.java
@@ -6,6 +6,7 @@
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.gson.Gson;
import com.nq.common.CmcPayConfig;
+import com.nq.common.PayV2GatewayKeys;
import com.nq.common.ServerResponse;
import com.nq.dao.*;
import com.nq.enums.EStockType;
@@ -14,7 +15,9 @@
import com.nq.pojo.*;
import com.nq.service.*;
import com.nq.utils.*;
+import com.nq.utils.http.HttpClientRequest;
import com.nq.utils.http.HttpClientUtil;
+import com.nq.utils.pay.PayV2RsaSignUtil;
import com.nq.utils.pay.CmcPayOuterRequestUtil;
import com.nq.utils.pay.CmcPayTool;
import com.nq.utils.timeutil.DateTimeUtil;
@@ -25,6 +28,7 @@
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
+import java.math.RoundingMode;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
import java.security.Key;
@@ -104,6 +108,11 @@
private static final String KEY_ALGORITHM = "AES";
private static final String AES128CBC = "AES/CBC/PKCS5Padding";
+ /** 代收 v2/payCreate 完整 URL(由商户后台提供域名与路径) */
+ private static final String PAY_V2_PAY_CREATE_URL = "https://pay.kkpay100.com/v2/payCreate";
+ /** 商户 id */
+ private static final int PAY_V2_MID = 10724;
+
public ServerResponse thirdPartyRecharge(HttpServletRequest request, String tradeAmount, Integer type) throws Exception {
// 支付1
String reqUrl = "https://api.watchglb.com/pay/web";
@@ -127,8 +136,127 @@
return getPaymentTwo(tradeAmount, uipReqRul, user,request);
}else if(type == 1){
return getPaymentThree(tradeAmount, threeUrl, user,request);
+ }else if(type == 4){
+ return getPaymentFour(tradeAmount, user, request);
}
return ServerResponse.createByErrorMsg("获取支付方式失败",request);
+ }
+
+ /**
+ * 支付4:代收 v2/payCreate(JSON)
+ */
+ private ServerResponse getPaymentFour(String tradeAmount, User user, HttpServletRequest request) throws Exception {
+ String orderId = generatePayOrderId();
+ BigDecimal amount = new BigDecimal(tradeAmount).setScale(2, RoundingMode.HALF_UP);
+
+ String notifyUrl = "https://api.greenbackcaps.top/user/rechargeCallbackFour.do";
+ String custId = "U" + user.getId();
+ String mobile = StringUtils.isNotBlank(user.getPhone()) ? user.getPhone() : "0000000000";
+ if (mobile.length() > 16) {
+ mobile = mobile.substring(0, 16);
+ }
+ String fn = UserNameUtil.formatCustomerName(user.getNickName());
+ if (StringUtils.isBlank(fn)) {
+ fn = "User";
+ }
+ if (fn.length() > 16) {
+ fn = fn.substring(0, 16);
+ }
+ String ln = String.valueOf(user.getId());
+ if (ln.length() > 16) {
+ ln = ln.substring(0, 16);
+ }
+ String email = custId + "@user.local";
+ if (email.length() > 64) {
+ email = email.substring(0, 64);
+ }
+
+ Map<String, String> signParams = new TreeMap<>();
+ signParams.put("amount", amount.toPlainString());
+ signParams.put("currency", "INR");
+ signParams.put("custId", custId);
+ signParams.put("email", email);
+ signParams.put("firstName", fn);
+ signParams.put("lastName", ln);
+ signParams.put("mid", String.valueOf(PAY_V2_MID));
+ signParams.put("mobile", mobile);
+ signParams.put("notifyUrl", notifyUrl);
+ signParams.put("orderId", orderId);
+ String signBaseString = PayV2RsaSignUtil.buildStringA(signParams);
+ String sign = PayV2RsaSignUtil.sign(signBaseString, PayV2GatewayKeys.MERCHANT_PRIVATE_KEY_PEM);
+ log.info("支付4代收签名串 stringA={}", signBaseString);
+
+ Map<String, Object> body = new LinkedHashMap<>();
+ body.put("mid", PAY_V2_MID);
+ body.put("orderId", orderId);
+ body.put("amount", amount.toPlainString());
+ body.put("currency", "INR");
+ body.put("custId", custId);
+ body.put("firstName", fn);
+ body.put("lastName", ln);
+ body.put("mobile", mobile);
+ body.put("email", email);
+ body.put("notifyUrl", notifyUrl);
+ body.put("sign", sign);
+
+ String json = new Gson().toJson(body);
+ log.info("支付4代收请求:{}", json);
+ String result = HttpClientRequest.doPostJsonBody(PAY_V2_PAY_CREATE_URL, json);
+ log.info("支付4代收返回:{}", result);
+
+ ObjectMapper objectMapper = new ObjectMapper();
+ PayV2PayCreateResponse resp = objectMapper.readValue(result, PayV2PayCreateResponse.class);
+ if (resp.getStatus() != 1 || resp.getData() == null) {
+ log.error("支付4下单失败:{}", result);
+ return ServerResponse.createByErrorMsg(
+ StringUtils.isNotBlank(resp.getMsg()) ? resp.getMsg() : "获取支付链接失败", request);
+ }
+
+ PayV2PayCreateResponse.Data data = resp.getData();
+ Map<String, String> respSignParams = new TreeMap<>();
+ if (StringUtils.isNotBlank(data.getAmount())) {
+ respSignParams.put("amount", data.getAmount());
+ }
+ if (StringUtils.isNotBlank(data.getMOrder())) {
+ respSignParams.put("m_order", data.getMOrder());
+ }
+ if (StringUtils.isNotBlank(data.getOrderId())) {
+ respSignParams.put("order_id", data.getOrderId());
+ }
+ if (StringUtils.isNotBlank(data.getUrl())) {
+ respSignParams.put("url", data.getUrl());
+ }
+ if (!PayV2RsaSignUtil.verify(respSignParams, data.getSign(), PayV2GatewayKeys.PLATFORM_PUBLIC_KEY)) {
+ log.warn("支付4返回签名验证未通过,stringA={}, sign={}",
+ PayV2RsaSignUtil.buildStringA(respSignParams), data.getSign());
+ }
+
+ PaymentRecharge paymentRecharge = new PaymentRecharge();
+ paymentRecharge.setUserId(user.getId());
+ paymentRecharge.setOrderNo(orderId);
+ paymentRecharge.setMchOrderNo(data.getOrderId());
+ paymentRecharge.setAmount(amount);
+ paymentRecharge.setStatus(1);
+ paymentRecharge.setPaymentTime(new Date());
+ paymentRecharge.setCreatedAt(new Date());
+ paymentRecharge.setNotifyUrl(notifyUrl);
+ paymentRecharge.setPayInfo(result);
+ paymentRechargeService.save(paymentRecharge);
+
+ UserRecharge userRecharge = new UserRecharge();
+ userRecharge.setUserId(user.getId());
+ userRecharge.setNickName(user.getRealName());
+ userRecharge.setAgentId(user.getAgentId());
+ userRecharge.setOrderSn(orderId);
+ userRecharge.setPayChannel("Payment 4");
+ userRecharge.setPayAmt(amount);
+ userRecharge.setAddTime(new Date());
+ userRecharge.setPayTime(new Date());
+ userRecharge.setOrderStatus(0);
+ userRecharge.setPayId(4);
+ userRechargeMapper.insert(userRecharge);
+
+ return ServerResponse.createBySuccess(data.getUrl());
}
private ServerResponse getPaymentZero(String tradeAmount, String uipReqRul, User user, HttpServletRequest request) throws Exception {
@@ -1342,6 +1470,112 @@
}
}
+ @Override
+ public void rechargeCallbackFour(PayV2NotifyRequest vo, HttpServletResponse response) throws IOException {
+ log.info("支付4充值回调:{}", vo);
+ PrintWriter pw = response.getWriter();
+ response.setStatus(200);
+ response.setContentType("text/plain;charset=UTF-8");
+ if (vo == null || StringUtils.isBlank(vo.getMOrder())) {
+ pw.print("FAIL");
+ pw.flush();
+ pw.close();
+ return;
+ }
+ synchronized (vo.getMOrder()) {
+ Map<String, String> signParams = new TreeMap<>();
+ if (vo.getMid() != null) {
+ signParams.put("mid", String.valueOf(vo.getMid()));
+ }
+ signParams.put("m_order", vo.getMOrder());
+ signParams.put("order_id", vo.getOrderId());
+ signParams.put("amount", vo.getAmount());
+ if (StringUtils.isNotBlank(vo.getUtr())) {
+ signParams.put("utr", vo.getUtr());
+ }
+ if (vo.getPayStatus() != null) {
+ signParams.put("pay_status", String.valueOf(vo.getPayStatus()));
+ }
+ if (vo.getRTime() != null) {
+ signParams.put("r_time", String.valueOf(vo.getRTime()));
+ }
+ if (!PayV2RsaSignUtil.verify(signParams, vo.getSign(), PayV2GatewayKeys.PLATFORM_PUBLIC_KEY)) {
+ log.error("支付4回调签名验证失败:{}, stringA={}", vo, PayV2RsaSignUtil.buildStringA(signParams));
+ pw.print("FAIL");
+ pw.flush();
+ pw.close();
+ return;
+ }
+
+ PaymentRecharge paymentRecharge = paymentRechargeService.getOne(new LambdaQueryWrapper<>(PaymentRecharge.class)
+ .eq(PaymentRecharge::getOrderNo, vo.getMOrder())
+ .eq(PaymentRecharge::getStatus, 1)
+ .last("limit 1"));
+ if (ObjectUtils.isEmpty(paymentRecharge)) {
+ log.info("支付4未找到充值订单");
+ pw.print("FAIL");
+ pw.flush();
+ pw.close();
+ return;
+ }
+ UserRecharge userRecharge = userRechargeMapper.selectOne(new LambdaQueryWrapper<>(UserRecharge.class)
+ .eq(UserRecharge::getOrderSn, paymentRecharge.getOrderNo())
+ .eq(UserRecharge::getOrderStatus, 0)
+ .last("limit 1"));
+ if (ObjectUtils.isEmpty(userRecharge)) {
+ log.info("支付4未找到待支付充值记录");
+ pw.print("OK");
+ pw.flush();
+ pw.close();
+ return;
+ }
+
+ Integer ps = vo.getPayStatus();
+ if (ps != null && ps == 0) {
+ pw.print("OK");
+ pw.flush();
+ pw.close();
+ return;
+ }
+ if (ps != null && (ps == 3 || ps == 4)) {
+ paymentRecharge.setStatus(2);
+ paymentRecharge.setAmount(new BigDecimal(vo.getAmount()));
+ paymentRecharge.setPayInfo(vo.toString());
+ paymentRechargeService.updateById(paymentRecharge);
+ userRecharge.setOrderStatus(2);
+ userRechargeMapper.updateById(userRecharge);
+ log.warn("支付4回调失败状态 pay_status={}:{}", ps, vo);
+ pw.print("OK");
+ pw.flush();
+ pw.close();
+ return;
+ }
+ if (ps == null || ps != 1) {
+ log.error("支付4回调未知状态:{}", vo);
+ pw.print("OK");
+ pw.flush();
+ pw.close();
+ return;
+ }
+
+ userAssetsServices.availablebalanceChange(EStockType.IN.getCode(),
+ paymentRecharge.getUserId(), EUserAssets.TOP_UP, new BigDecimal(vo.getAmount()), "", "");
+
+ paymentRecharge.setStatus(2);
+ paymentRecharge.setAmount(new BigDecimal(vo.getAmount()));
+ paymentRecharge.setPayInfo(vo.toString());
+ paymentRechargeService.updateById(paymentRecharge);
+
+ userRecharge.setOrderStatus(1);
+ userRechargeMapper.updateById(userRecharge);
+
+ log.info("支付4充值回调完成");
+ pw.print("OK");
+ pw.flush();
+ pw.close();
+ }
+ }
+
/**
* 代付回调处理
*/
@@ -1560,6 +1794,125 @@
}
/**
+ * 代付 v2(payOutCreate)异步通知
+ */
+ @Override
+ public void payoutCallbackThree(PayV2PayoutNotifyRequest vo, HttpServletResponse response) throws IOException {
+ log.info("代付v2回调:{}", vo);
+ response.setStatus(200);
+ response.setContentType("text/plain;charset=UTF-8");
+ PrintWriter pw = response.getWriter();
+ if (vo == null || StringUtils.isBlank(vo.getMOrder()) || vo.getMid() == null
+ || vo.getPayStatus() == null || vo.getRTime() == null) {
+ pw.print("FAIL");
+ pw.flush();
+ pw.close();
+ return;
+ }
+ Map<String, String> signParams = new TreeMap<>();
+ if (StringUtils.isNotBlank(vo.getAmount())) {
+ signParams.put("amount", vo.getAmount());
+ }
+ if (StringUtils.isNotBlank(vo.getErrMsg())) {
+ signParams.put("err_msg", vo.getErrMsg());
+ }
+ signParams.put("mid", String.valueOf(vo.getMid()));
+ signParams.put("m_order", vo.getMOrder());
+ signParams.put("order_id", vo.getOrderId());
+ signParams.put("pay_status", String.valueOf(vo.getPayStatus()));
+ signParams.put("r_time", String.valueOf(vo.getRTime()));
+ if (StringUtils.isNotBlank(vo.getUtr())) {
+ signParams.put("utr", vo.getUtr());
+ }
+ if (!PayV2RsaSignUtil.verify(signParams, vo.getSign(), PayV2GatewayKeys.PLATFORM_PUBLIC_KEY)) {
+ log.error("代付v2回调签名验证失败, stringA={}", PayV2RsaSignUtil.buildStringA(signParams));
+ pw.print("FAIL");
+ pw.flush();
+ pw.close();
+ return;
+ }
+ synchronized (vo.getMOrder()) {
+ TransferResponse transfer = transferResponseService.getOne(
+ new LambdaQueryWrapper<>(TransferResponse.class)
+ .eq(TransferResponse::getMerTransferId, vo.getMOrder())
+ .last("limit 1"));
+ if (transfer == null) {
+ pw.print("FAIL");
+ pw.flush();
+ pw.close();
+ return;
+ }
+ if (transfer.getCallbackState() != 0) {
+ pw.print("OK");
+ pw.flush();
+ pw.close();
+ return;
+ }
+ UserWithdraw withdraw = userWithdrawMapper.selectByPrimaryKey(transfer.getWithId());
+ if (withdraw == null) {
+ pw.print("FAIL");
+ pw.flush();
+ pw.close();
+ return;
+ }
+ Integer ps = vo.getPayStatus();
+ if (ps != null && ps == 0) {
+ pw.print("OK");
+ pw.flush();
+ pw.close();
+ return;
+ }
+ if (ps != null && ps == 1) {
+ transfer.setTradeResult(1);
+ transfer.setCallbackState(1);
+ transfer.setRespCode("SUCCESS");
+ transfer.setSignType("MD5");
+ transfer.setSign(vo.getSign());
+ transfer.setUpdatedAt(new Date());
+ transferResponseService.updateById(transfer);
+
+ withdraw.setWithStatus(1);
+ withdraw.setWithMsg("代付成功");
+ withdraw.setTransTime(new Date());
+ userWithdrawMapper.updateByPrimaryKeySelective(withdraw);
+
+ UserAssets assets = iUserAssetsServices.assetsByTypeAndUserId("IN", withdraw.getUserId());
+ if (assets != null) {
+ assets.setFreezeMoney(assets.getFreezeMoney().subtract(withdraw.getWithAmt()));
+ userAssetsMapper.updateById(assets);
+ }
+ } else if (ps != null && (ps == 2 || ps == 3)) {
+ String err = StringUtils.defaultIfBlank(vo.getErrMsg(), "");
+ transfer.setTradeResult(2);
+ transfer.setCallbackState(2);
+ transfer.setRespCode("FAIL");
+ transfer.setErrorMsg(err);
+ transfer.setSignType("MD5");
+ transfer.setSign(vo.getSign());
+ transfer.setUpdatedAt(new Date());
+ transferResponseService.updateById(transfer);
+
+ withdraw.setWithStatus(2);
+ withdraw.setWithMsg("Withdrawal failed:" + err);
+ withdraw.setTransTime(new Date());
+ userWithdrawMapper.updateByPrimaryKeySelective(withdraw);
+
+ UserAssets assets = iUserAssetsServices.assetsByTypeAndUserId("IN", withdraw.getUserId());
+ if (assets != null) {
+ assets.setAvailableBalance(assets.getAvailableBalance().add(withdraw.getWithAmt()));
+ assets.setFreezeMoney(assets.getFreezeMoney().subtract(withdraw.getWithAmt()));
+ userAssetsMapper.updateById(assets);
+ }
+ } else {
+ log.warn("代付v2回调未知 pay_status={}", ps);
+ }
+ pw.print("OK");
+ pw.flush();
+ pw.close();
+ }
+ }
+
+ /**
* 处理成功回调
*/
private void handleSuccess(TransferResponse transfer, UserWithdraw withdraw,
--
Gitblit v1.9.3