From e1b1f32ad968da303fbd4827ace995704743cdda Mon Sep 17 00:00:00 2001 From: liujie <1793218484@qq.com> Date: 星期三, 17 九月 2025 09:41:32 +0800 Subject: [PATCH] 拉卡拉支付 --- ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TSysOrderController.java | 227 ++++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 files changed, 211 insertions(+), 16 deletions(-) diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TSysOrderController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TSysOrderController.java index 43c9faa..9680c68 100644 --- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TSysOrderController.java +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TSysOrderController.java @@ -1,11 +1,21 @@ package com.ruoyi.web.controller.api; +import cn.hutool.http.HttpRequest; +import cn.hutool.http.HttpResponse; +import cn.hutool.http.HttpUtil; +import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.lkl.laop.sdk.exception.SDKException; import com.ruoyi.common.core.domain.R; import com.ruoyi.common.core.domain.entity.SysUser; +import com.ruoyi.common.utils.DateUtils; +import com.ruoyi.common.utils.ip.IpUtils; import com.ruoyi.framework.web.service.TokenService; +import com.ruoyi.system.model.TCrmSupplier; +import com.ruoyi.system.model.TErpProcurement; +import com.ruoyi.system.model.TErpProcurementGoods; import com.ruoyi.system.query.TErpGoodsWarehouseQuery; import com.ruoyi.system.service.*; import com.ruoyi.web.core.config.LakalaConfig; @@ -22,11 +32,9 @@ import org.apache.http.conn.ssl.SSLSocketFactory; import org.apache.http.entity.StringEntity; import org.apache.http.impl.client.DefaultHttpClient; +import org.apache.poi.ss.formula.functions.T; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; import javax.net.ssl.SSLContext; import javax.net.ssl.TrustManager; @@ -34,11 +42,20 @@ import javax.servlet.http.HttpServletRequest; import javax.validation.Valid; import java.io.*; +import java.math.BigDecimal; import java.nio.charset.StandardCharsets; import java.security.*; import java.security.cert.*; import java.security.spec.InvalidKeySpecException; import java.security.spec.PKCS8EncodedKeySpec; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.stream.Collectors; /** * <p> @@ -54,12 +71,18 @@ public class TSysOrderController { private final TErpProcurementService erpProcurementService; + private final TErpProcurementGoodsService erpProcurementGoodsService; + private final TCrmSupplierService crmSupplierService; + private final TokenService tokenService; + @Autowired - public TSysOrderController(TErpProcurementService erpProcurementService, TokenService tokenService) { + public TSysOrderController(TErpProcurementService erpProcurementService, TokenService tokenService, TErpProcurementGoodsService erpProcurementGoodsService, TCrmSupplierService crmSupplierService) { this.erpProcurementService = erpProcurementService; this.tokenService = tokenService; + this.erpProcurementGoodsService = erpProcurementGoodsService; + this.crmSupplierService = crmSupplierService; } private static final String SYMBOLS = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; @@ -81,27 +104,41 @@ @ApiOperation(value = "支付") @PostMapping(value = "/payOrder") @SneakyThrows - public R<?> payOrder(@RequestBody @Valid TErpGoodsWarehouseQuery query, HttpServletRequest request) { + public R<?> payOrder(@RequestParam String id, String type, HttpServletRequest request) { SysUser user = tokenService.getLoginUser().getUser(); try { // 查出采购单 算出价格 下单 算出应该分佣金额 应该分给谁 + TErpProcurement erpProcurement = erpProcurementService.getById(id); - String apiPath = "/api/v3/labs/trans/preorder"; + String ipAddr = IpUtils.getIpAddr(request); + String time = DateUtils.dateTimeNow(); + + // SYMBOLS 随机取4位数 + String nonce = ""; + for (int i = 0; i < 6; i++) { + nonce += SYMBOLS.charAt(RANDOM.nextInt(SYMBOLS.length())); + } + String outTradeNo = time + nonce; + String amount = String.valueOf(erpProcurement.getPayMoney().multiply(new BigDecimal("100")).intValue()); + + + String apiPath = "sit/api/v3/labs/trans/preorder"; String body = "{\n" + - "\t\"req_time\": \"20250915115329\",\n" + + "\t\"req_time\": \"" + time + "\",\n" + "\t\"version\": \"3.0\",\n" + "\t\"req_data\": {\n" + - "\t\t\"out_trade_no\": \"c13c493182e1ee84\",\n" + + "\t\t\"out_trade_no\": \"" + outTradeNo + "\",\n" + "\t\t\"merchant_no\": \"822290059430BFA\",\n" + "\t\t\"term_no\": \"D9261078\",\n" + "\t\t\"notify_url\": \"http://221.182.45.100:8089/t-sys-order/messageHandle\",\n" + "\t\t\"location_info\": {\n" + - "\t\t\t\"request_ip\": \"180.157.249.160\"\n" + + "\t\t\t\"request_ip\": \"" + ipAddr + "\"\n" + "\t\t},\n" + - "\t\t\"subject\": \"cc测试\",\n" + - "\t\t\"total_amount\": 1,\n" + - "\t\t\"account_type\": \"ALIPAY\",\n" + + "\t\t\"subject\": \"商品采购\",\n" + + "\t\t\"settle_type\": \"1\",\n" + + "\t\t\"total_amount\": " + amount + ",\n" + + "\t\t\"account_type\": \"" + type + "\",\n" + "\t\t\"trans_type\": \"41\"\n" + "\t}\n" + "}"; @@ -112,6 +149,19 @@ + IOUtils.toString(response.getEntity().getContent(), ENCODING)); } String responseStr = IOUtils.toString(response.getEntity().getContent(), ENCODING); + + + erpProcurement.setPayNumber(outTradeNo); + JSONObject jsonObject = JSONObject.parseObject(responseStr); + JSONObject jsonObject1 = jsonObject.getJSONObject("resp_data"); + String code = jsonObject1.getString("log_no"); + erpProcurement.setPayTransactionId(code); + erpProcurement.setStatus(2); + erpProcurement.setTermNo("D9261078"); + erpProcurement.setAccountType(type); + erpProcurement.setTransType("41"); + erpProcurementService.updateById(erpProcurement); + return R.ok(responseStr); } catch (SDKException e) { e.printStackTrace(); @@ -120,6 +170,10 @@ } + public static void main(String[] args) { + String a = "{\"code\":\"BBS00000\",\"msg\":\"成功\",\"resp_time\":\"20250916114506\",\"resp_data\":{\"merchant_no\":\"822290059430BFA\",\"out_trade_no\":\"202509161144582Kck\",\"trade_no\":\"2025091666200821320234\",\"log_no\":\"66200821320234\",\"settle_merchant_no\":\"\",\"settle_term_no\":\"\",\"trade_req_date\":\"20250916\",\"acc_resp_fields\":{\"code\":\"https://qr.alipay.com/bax01747cbtdjneesjaz0044\",\"code_image\":\"\",\"prepay_id\":\"\",\"app_id\":\"\",\"pay_sign\":\"\",\"time_stamp\":\"\",\"nonce_str\":\"\",\"package\":\"\",\"sign_type\":\"\",\"form_data\":\"\",\"redirect_url\":\"\",\"best_pay_info\":\"\",\"partner_id\":\"\",\"sub_mch_id\":\"2088240727800097\"}}}"; + + } @RequestMapping("/messageHandle") @ApiOperation(value = "拉卡拉支付信息回调接口") @@ -146,9 +200,151 @@ X509Certificate lklCertificate = loadCertificate(new FileInputStream(new File(LakalaConfig.getLklNotifyCerStr()))); String preSignData = timestamp + "\n" + nonce + "\n" + body + "\n"; boolean verify = verify(lklCertificate, preSignData.getBytes(ENCODING), signature); + // 先处理支付完成 修改状态 后处理分账 后走分账回调 + JSONObject jsonObject1 = JSONObject.parseObject(body); + Object o = jsonObject1.get("out_trade_no"); + TErpProcurement erpProcurement = erpProcurementService.getOne(new LambdaQueryWrapper<TErpProcurement>().eq(TErpProcurement::getPayNumber, o)); + if (verify && erpProcurement.getStatus()==2) { + erpProcurement.setPayTime(LocalDateTime.now()); + erpProcurement.setStatus(3); + erpProcurementService.updateById(erpProcurement); + List<TErpProcurementGoods> list = erpProcurementGoodsService.list(new LambdaQueryWrapper<TErpProcurementGoods>().eq(TErpProcurementGoods::getProcurementId, erpProcurement.getId())); - if (verify) { - // 先处理支付完成 修改状态 后处理分账 后走分账回调 + + // 操作分账 + HttpRequest post = HttpUtil.createPost(LakalaConfig.getServerUrl() + "sit/api/v3/sacs/separate"); + HashMap<String, Object> map = new HashMap<>(); + map.put("merchant_no", "822290059430BFA"); + map.put("log_no", erpProcurement.getPayTransactionId()); + map.put("log_date", DateUtils.dateTime()); + map.put("notify_url", "http://221.182.45.100:8089/t-sys-order/messageSeparateHandle"); + String time = DateUtils.dateTimeNow(); + + // SYMBOLS 随机取4位数 + String str = ""; + for (int i = 0; i < 6; i++) { + str += SYMBOLS.charAt(RANDOM.nextInt(SYMBOLS.length())); + } + String outTradeNo = time + str; + map.put("out_separate_no", outTradeNo); + map.put("total_amt", erpProcurement.getPayMoney().multiply(BigDecimal.valueOf(100)).intValue() + ""); + // 平台应得分账 + BigDecimal payMoney = erpProcurement.getPayMoney(); + ArrayList<HashMap<String, Object>> objects = new ArrayList<>(); + // 根据供应商id分组 + Map<String, List<TErpProcurementGoods>> collect = list.stream().collect(Collectors.groupingBy(TErpProcurementGoods::getSupplierId)); + for (Map.Entry<String, List<TErpProcurementGoods>> entry : collect.entrySet()) { + HashMap<String, Object> map1 = new HashMap<>(); + String supplierId = entry.getKey(); + TCrmSupplier supplier = crmSupplierService.getById(supplierId); + List<TErpProcurementGoods> value = entry.getValue(); + BigDecimal reduce = value.stream().map(TErpProcurementGoods::getSupplierMoney).reduce(BigDecimal.ZERO, BigDecimal::add); + payMoney = payMoney.subtract(reduce); + map1.put("recv_merchant_no", supplier.getRecvMerchantNo()); + map1.put("separate_value", reduce.multiply(BigDecimal.valueOf(100)).intValue() + ""); + objects.add(map1); + } + + // 添加平台的 + map.put("recv_datas", objects); + String jsonString = JSON.toJSONString(map); + post.body(jsonString); + HttpResponse response = post.execute(); + String responseStr = response.body(); + JSONObject jsonObject = JSONObject.parseObject(responseStr); + if ("成功".equals(jsonObject.getString("msg"))) { + Object o1 = jsonObject.get("resp_data"); + JSONObject jsonObject2 = JSONObject.parseObject(o1.toString()); + String separate_no = jsonObject2.getString("separate_no"); + erpProcurement.setSeparateNo(separate_no); + erpProcurementService.updateById(erpProcurement); + } + + // 响应success + JSONObject responseJsonObject = new JSONObject(); + responseJsonObject.put("code", "SUCCESS"); + responseJsonObject.put("message", "执行成功"); + return responseJsonObject; + } + return null; + } + + @RequestMapping("/messageSeparateHandle") + @ApiOperation(value = "拉卡拉分账信息回调接口") + public Object messageSeparateHandle(HttpServletRequest request) throws Exception { + String body = this.getBody(request); + String authorization = request.getHeader("Authorization"); + String timestamp = null; + String nonce = null; + String signature = null; + authorization = authorization.replaceAll("LKLAPI-SHA256withRSA ", ""); + String[] split = authorization.split(","); + for (String s : split) { + if (s.startsWith("timestamp")) { + timestamp = s.split("=")[1].replaceAll("\"", ""); + } + if (s.startsWith("nonce")) { + nonce = s.split("=")[1].replaceAll("\"", ""); + } + if (s.startsWith("signature")) { + // 取出签名 + signature = s.split("signature=")[1].replaceAll("\"", ""); + } + } + X509Certificate lklCertificate = loadCertificate(new FileInputStream(new File(LakalaConfig.getLklNotifyCerStr()))); + String preSignData = timestamp + "\n" + nonce + "\n" + body + "\n"; + boolean verify = verify(lklCertificate, preSignData.getBytes(ENCODING), signature); + // 先处理支付完成 修改状态 后处理分账 后走分账回调 + JSONObject jsonObject1 = JSONObject.parseObject(body); + Object o = jsonObject1.get("out_trade_no"); + TErpProcurement erpProcurement = erpProcurementService.getOne(new LambdaQueryWrapper<TErpProcurement>().eq(TErpProcurement::getPayNumber, o)); + if (verify && erpProcurement.getStatus()==2) { + erpProcurement.setPayTime(LocalDateTime.now()); + erpProcurement.setStatus(3); + erpProcurementService.updateById(erpProcurement); + + List<TErpProcurementGoods> list = erpProcurementGoodsService.list(new LambdaQueryWrapper<TErpProcurementGoods>().eq(TErpProcurementGoods::getProcurementId, erpProcurement.getId())); + // 操作分账 + HttpRequest post = HttpUtil.createPost(LakalaConfig.getServerUrl() + "sit/api/v3/sacs/separate"); + HashMap<String, Object> map = new HashMap<>(); + map.put("merchant_no", "822290059430BFA"); + map.put("log_no", erpProcurement.getPayTransactionId()); + map.put("log_date", DateUtils.dateTime()); + map.put("notify_url", DateUtils.dateTime()); + String time = DateUtils.dateTimeNow(); + + // SYMBOLS 随机取4位数 + String str = ""; + for (int i = 0; i < 6; i++) { + str += SYMBOLS.charAt(RANDOM.nextInt(SYMBOLS.length())); + } + String outTradeNo = time + str; + map.put("out_separate_no", outTradeNo); + map.put("total_amt", erpProcurement.getPayMoney().multiply(BigDecimal.valueOf(100)).intValue() + ""); + // 平台应得分账 + BigDecimal payMoney = erpProcurement.getPayMoney(); + ArrayList<HashMap<String, Object>> objects = new ArrayList<>(); + // 根据供应商id分组 + Map<String, List<TErpProcurementGoods>> collect = list.stream().collect(Collectors.groupingBy(TErpProcurementGoods::getSupplierId)); + for (Map.Entry<String, List<TErpProcurementGoods>> entry : collect.entrySet()) { + HashMap<String, Object> map1 = new HashMap<>(); + String supplierId = entry.getKey(); + TCrmSupplier supplier = crmSupplierService.getById(supplierId); + List<TErpProcurementGoods> value = entry.getValue(); + BigDecimal reduce = value.stream().map(TErpProcurementGoods::getSupplierMoney).reduce(BigDecimal.ZERO, BigDecimal::add); + payMoney = payMoney.subtract(reduce); + map1.put("recv_merchant_no", supplier.getRecvMerchantNo()); + map1.put("separate_value", reduce.multiply(BigDecimal.valueOf(100)).intValue() + ""); + objects.add(map1); + } + + // 添加平台的 + map.put("recv_datas", objects); + String jsonString = JSON.toJSONString(map); + post.body(jsonString); + HttpResponse response = post.execute(); + String responseStr = response.body(); + // 响应success JSONObject jsonObject = new JSONObject(); @@ -256,7 +452,6 @@ throw new RuntimeException("无效的私钥", e); } } - public final String getBody(HttpServletRequest request) { -- Gitblit v1.7.1