| | |
| | | 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; |
| | |
| | | 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; |
| | |
| | | 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; |
| | |
| | | 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"; |
| | |
| | | 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 { |
| | |
| | | } |
| | | } |
| | | |
| | | @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(); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 代付回调处理 |
| | | */ |
| | |
| | | TransferResponse transferResponse = transferResponseService.getOne( |
| | | new LambdaQueryWrapper<>(TransferResponse.class) |
| | | .eq(TransferResponse::getMerTransferId, vo.getMerchantOrderId()) |
| | | .last("limit 1") |
| | | ); |
| | | |
| | | if (ObjectUtils.isEmpty(transferResponse)) { |
| | |
| | | TransferResponse transfer = transferResponseService.getOne( |
| | | new LambdaQueryWrapper<TransferResponse>() |
| | | .eq(TransferResponse::getMerTransferId, data.getMerchantOrderNo()) |
| | | .last("limit 1") |
| | | ); |
| | | |
| | | if (transfer == null) { |
| | |
| | | } |
| | | |
| | | /** |
| | | * 代付 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()) |
| | | ); |
| | | 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, |