liujie
2 天以前 f7e3925846166283517af0575dee3fcaf79f25fd
患者诊疗
8个文件已修改
3个文件已添加
1406 ■■■■■ 已修改文件
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TErpClinicWarehousingController.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TOrderController.java 673 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TSysOrderController.java 623 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/mapper/TErpGoodsMapper.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/mapper/TSysOrderMapper.java 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/model/TSysOrder.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/query/TSysOrderQuery.java 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/TSysOrderService.java 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TSysOrderServiceImpl.java 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/vo/TSysOrderPageVo.java 30 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/resources/mapper/system/TSysOrderMapper.xml 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TErpClinicWarehousingController.java
@@ -142,7 +142,7 @@
    @ApiOperation(value = "诊所 盘点 出库 商品选择")
    @ApiOperation(value = "诊所 盘点 出库 商品选择  患者诊疗商品选择")
    @PostMapping(value = "/pageInventoryGoodsPageList")
    public R<PageInfo<TErpGoodsInventoryVO>> pageInventoryGoodsPageList(@RequestBody @Valid TErpGoodsInventoryQuery query) {
        SysUser user = tokenService.getLoginUser().getUser();
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TOrderController.java
New file
@@ -0,0 +1,673 @@
package com.ruoyi.web.controller.api;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
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.service.TCrmSupplierService;
import com.ruoyi.system.service.TErpProcurementGoodsService;
import com.ruoyi.system.service.TErpProcurementService;
import com.ruoyi.web.core.config.LakalaConfig;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.SneakyThrows;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.io.IOUtils;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ClientConnectionManager;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.scheme.SchemeRegistry;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import javax.servlet.http.HttpServletRequest;
import java.io.*;
import java.math.BigDecimal;
import java.math.RoundingMode;
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.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
 * <p>
 * 订单管理 前端控制器
 * </p>
 *
 * @author xiaochen
 * @since 2025-08-20
 */
@RestController
@RequestMapping("/t-sys-order")
@Api(tags = "支付管理")
public class TOrderController {
    private final TErpProcurementService erpProcurementService;
    private final TErpProcurementGoodsService erpProcurementGoodsService;
    private final TCrmSupplierService crmSupplierService;
    private final TokenService tokenService;
    @Autowired
    public TOrderController(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";
    /**
     * API schema ,固定 LKLAPI-SHA256withRSA
     */
    public final static String SCHEMA = "LKLAPI-SHA256withRSA";
    /**
     * 字符集固定 utf-8
     */
    public static final String ENCODING = "utf-8";
    private static final SecureRandom RANDOM = new SecureRandom();
    @ApiOperation(value = "支付")
    @PostMapping(value = "/payOrder")
    @SneakyThrows
    public R<?> payOrder(@RequestParam String id, String type, HttpServletRequest request) {
        try {
            // 查出采购单 算出价格  下单  算出应该分佣金额 应该分给谁
            TErpProcurement erpProcurement = erpProcurementService.getById(id);
            if (erpProcurement.getStatus()>2) {
                return R.fail("订单已支付");
            }
            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());
            TCrmSupplier supplier = crmSupplierService.getById(erpProcurement.getSupplierId());
            String trans_type ="41";
            if("WECHAT".equals(type)){
                trans_type= "51";
            }
            String apiPath = "sit/api/v3/labs/trans/preorder";
            String body = "{\n" +
                    "\t\"req_time\": \"" + time + "\",\n" +
                    "\t\"version\": \"3.0\",\n" +
                    "\t\"req_data\": {\n" +
                    "\t\t\"out_trade_no\": \"" + outTradeNo + "\",\n" +
                    "\t\t\"merchant_no\": \""+supplier.getRecvMerchantNo()+"\",\n" +
                    "\t\t\"term_no\": \""+supplier.getTermNo()+"\",\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\": \"" + ipAddr + "\"\n" +
                    "\t\t},\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\": \""+trans_type+"\"\n" +
                    "\t}\n" +
                    "}";
            String authorization = getAuthorization(body);
            org.apache.http.HttpResponse response = post(LakalaConfig.getServerUrl() + apiPath, body, authorization);
            if (response.getStatusLine().getStatusCode() != 200) {
                return R.fail(500, "请求失败,statusCode  " + response.getStatusLine()
                        + 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(supplier.getTermNo());
            erpProcurement.setAccountType(type);
            erpProcurement.setTransType(trans_type);
            erpProcurementService.updateById(erpProcurement);
            return R.ok(responseStr);
        } catch (SDKException e) {
            e.printStackTrace();
        }
        return R.fail(500, "调用支付宝支付预下单接口错误");
    }
    @RequestMapping("/messageHandle")
    @ApiOperation(value = "拉卡拉支付信息回调接口")
    public Object messageHandle(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);
            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> reqMap = new HashMap<>();
            reqMap.put("version", "3.0");
            reqMap.put("req_time", DateUtils.dateTimeNow());
            HashMap<String, Object> map = new HashMap<>();
            map.put("merchant_no", erpProcurement.getMerchantNo());
            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 allMoney = erpProcurement.getPayMoney();
            // 平台应得分账
            BigDecimal payMoney = erpProcurement.getMoney();
            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_no", supplier.getRecvMerchantNo());
//                map1.put("separate_value", reduce.multiply(BigDecimal.valueOf(100)).intValue() + "");
////                objects.add(map1);
//            }
            HashMap<String, Object> map1 = new HashMap<>();
            //TODO hzt
            map1.put("recv_no", "SR2024000006413");
            // 手续费
            BigDecimal bigDecimal = allMoney.multiply(new BigDecimal("0.038")).setScale(2, RoundingMode.HALF_UP);
            payMoney = payMoney.subtract(bigDecimal);
            map1.put("separate_value", payMoney.multiply(BigDecimal.valueOf(100)).intValue() + "");
            if(payMoney.doubleValue()>0){
                objects.add(map1);
            }
            erpProcurement.setMoney(payMoney);
            erpProcurement.setOutSeparateNo(outTradeNo);
            erpProcurementService.updateById(erpProcurement);
            // 添加平台的
            map.put("recv_datas", objects);
            reqMap.put("req_data", map);
            String jsonString = JSON.toJSONString(reqMap);
//            String authorization1 = getAuthorization(jsonString);
//            post.header("Authorization", SCHEMA + " " + authorization);
//
//            post.body(jsonString);
//            HttpResponse response = post.execute();
//            String responseStr = response.body();
            String authorization1 = getAuthorization(jsonString);
            org.apache.http.HttpResponse response1 = post(LakalaConfig.getServerUrl() + "sit/api/v3/sacs/separate", jsonString, authorization1);
            String responseStr = IOUtils.toString(response1.getEntity().getContent(), ENCODING);
            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);
        // 先处理支付完成  修改状态 后处理分账  后走分账回调
        JSONObject jsonObject1 = JSONObject.parseObject(body);
        Object o = jsonObject1.get("out_separate_no");
        Object status = jsonObject1.get("status");
        Object cmd_type = jsonObject1.get("cmd_type");
        Object detail_datas = jsonObject1.get("detail_datas");
        JSONArray jsonArray = JSONArray.parseArray(detail_datas.toString());
        if("SEPARATE".equals(cmd_type.toString())){
            TErpProcurement erpProcurement = erpProcurementService.getOne(new LambdaQueryWrapper<TErpProcurement>().eq(TErpProcurement::getOutSeparateNo, o.toString()));
            if ( erpProcurement!=null && "SUCCESS".equals(status)) {
                erpProcurement.setRefundStatus(1);
                erpProcurementService.updateById(erpProcurement);
                // 修改分账状态
                List<TErpProcurementGoods> list1 = erpProcurementGoodsService.list(new LambdaQueryWrapper<TErpProcurementGoods>().eq(TErpProcurementGoods::getProcurementId, erpProcurement.getId()));
                list1.stream().forEach(e->e.setStatus(1));
                erpProcurementGoodsService.updateBatchById(list1);
                // 响应success
                JSONObject jsonObject = new JSONObject();
                jsonObject.put("code", "SUCCESS");
                jsonObject.put("message", "执行成功");
                return jsonObject;
            }
        }else if("FALLBACK".equals(cmd_type.toString())){
            TErpProcurement erpProcurement = erpProcurementService.getOne(new LambdaQueryWrapper<TErpProcurement>().eq(TErpProcurement::getRefundOutSeparateNo, o.toString()));
            if ( erpProcurement!=null && "SUCCESS".equals(status) && erpProcurement.getRefundStatus()==1) {
                erpProcurement.setRefundStatus(2);
                erpProcurementService.updateById(erpProcurement);
                List<TErpProcurementGoods> list1 = erpProcurementGoodsService.list(new LambdaQueryWrapper<TErpProcurementGoods>().eq(TErpProcurementGoods::getProcurementId, erpProcurement.getId()));
                list1.stream().forEach(e->e.setStatus(2));
                erpProcurementGoodsService.updateBatchById(list1);
                // 发起退款
                String time = DateUtils.dateTimeNow();
                String ipAddr = IpUtils.getIpAddr(request);
                // SYMBOLS 随机取4位数
                String str = "";
                for (int i = 0; i < 6; i++) {
                    str += SYMBOLS.charAt(RANDOM.nextInt(SYMBOLS.length()));
                }
                String outTradeNo = time + str;
                String refund_amount = erpProcurement.getPayMoney().multiply(BigDecimal.valueOf(100)).intValue() + "";
                String apiPath = "sit/api/v3/rfd/refund_front/refund";
                String body1 = "{\n" +
                        "\t\"req_time\": \"" + time + "\",\n" +
                        "\t\"version\": \"3.0\",\n" +
                        "\t\"req_data\": {\n" +
                        "\t\t\"merchant_no\": \""+erpProcurement.getMerchantNo()+"\",\n" +
                        "\t\t\"term_no\": \""+erpProcurement.getTermNo()+"\",\n" +
                        "\t\t\"refund_amount\": " + refund_amount + ",\n" +
                        "\t\t\"out_trade_no\": \"" + outTradeNo + "\",\n" +
                        "\t\t\"notify_url\": \"" + "http://221.182.45.100:8089/t-sys-order/messageRefundHandle" + "\",\n" +
                        "\t\t\"origin_log_no\": \"" + erpProcurement.getPayTransactionId() + "\",\n" +
                        "\t\t\"location_info\": {\n" +
                        "\t\t\t\"request_ip\": \"" + ipAddr + "\"\n" +
                        "\t\t},\n" +
                        "\t}\n" +
                        "}";
                String authorization = getAuthorization(body1);
                org.apache.http.HttpResponse response = post(LakalaConfig.getServerUrl() + apiPath, body1, authorization);
                if (response.getStatusLine().getStatusCode() != 200) {
                    return R.fail(500, "请求失败,statusCode  " + response.getStatusLine()
                            + IOUtils.toString(response.getEntity().getContent(), ENCODING));
                }
                String responseStr = IOUtils.toString(response.getEntity().getContent(), ENCODING);
                JSONObject jsonObject = JSONObject.parseObject(responseStr);
                JSONObject jsonObject2 = jsonObject.getJSONObject("resp_data");
                String code = jsonObject2.getString("log_no");
                erpProcurement.setRefundLogNo(code);
                erpProcurement.setRefundNo(outTradeNo);
                erpProcurementService.updateById(erpProcurement);
                // 响应success
                JSONObject jsonObject3 = new JSONObject();
                jsonObject3.put("code", "SUCCESS");
                jsonObject3.put("message", "执行成功");
                return jsonObject3;
            }
        }
        return null;
    }
    @RequestMapping("/messageRefundHandle")
    @ApiOperation(value = "拉卡拉退款信息回调接口")
    public Object messageRefundHandle(HttpServletRequest request) throws Exception {
        String body = this.getBody(request);
        // 先处理支付完成  修改状态 后处理分账  后走分账回调
        JSONObject jsonObject1 = JSONObject.parseObject(body);
        Object status = jsonObject1.get("trade_status");
        Object out_trade_no = jsonObject1.get("out_trade_no");
        if(status !=null && "SUCCESS".equals(status.toString())){
            TErpProcurement erpProcurement = erpProcurementService.getOne(new LambdaQueryWrapper<TErpProcurement>().eq(TErpProcurement::getRefundNo, out_trade_no.toString()));
            if ( erpProcurement!=null && "SUCCESS".equals(status)) {
                erpProcurement.setStatus(6);
                erpProcurementService.updateById(erpProcurement);
                // 响应success
                JSONObject jsonObject = new JSONObject();
                jsonObject.put("code", "SUCCESS");
                jsonObject.put("message", "执行成功");
                return jsonObject;
            }
        }
        return null;
    }
    @ApiOperation(value = "退款")
    @PostMapping(value = "/refundOrder")
    @SneakyThrows
    public R<?> refundOrder(@RequestParam String id, HttpServletRequest request) {
        SysUser user = tokenService.getLoginUser().getUser();
        try {
            // 先退分账  在退订单
            // 查出采购单 算出价格  下单  算出应该分佣金额 应该分给谁
            TErpProcurement erpProcurement = erpProcurementService.getById(id);
            // 还未分账成功不能退款
        if(erpProcurement.getStatus()==null || erpProcurement.getStatus()!=1){
            return R.fail("订单处理中,请稍后操作");
        }
            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;
            // 操作分账
//            HttpRequest post = HttpUtil.createPost(LakalaConfig.getServerUrl() + "sit/api/v3/sacs/fallback");
            HashMap<String, Object> reqMap = new HashMap<>();
            reqMap.put("version", "3.0");
            reqMap.put("req_time", DateUtils.dateTimeNow());
            HashMap<String, Object> map = new HashMap<>();
            map.put("merchant_no", erpProcurement.getMerchantNo());
            map.put("origin_separate_no", erpProcurement.getSeparateNo());
            map.put("out_separate_no",outTradeNo);
            erpProcurement.setRefundOutSeparateNo(outTradeNo);
            erpProcurementService.updateById(erpProcurement);
//            List<TErpProcurementGoods> list = erpProcurementGoodsService.list(new LambdaQueryWrapper<TErpProcurementGoods>().eq(TErpProcurementGoods::getProcurementId, erpProcurement.getId()));
            // 根据供应商id分组
//            Map<String, List<TErpProcurementGoods>> collect = list.stream().collect(Collectors.groupingBy(TErpProcurementGoods::getSupplierId));
            ArrayList<HashMap<String, Object>> objects = new ArrayList<>();
//            BigDecimal allMoney = list.stream().map(TErpProcurementGoods::getSupplierMoney).reduce(BigDecimal.ZERO, BigDecimal::add);
//            for (Map.Entry<String, List<TErpProcurementGoods>> entry : collect.entrySet()) {
//
//                List<TErpProcurementGoods> value = entry.getValue();
//                BigDecimal reduce = value.stream().map(TErpProcurementGoods::getSupplierMoney).reduce(BigDecimal.ZERO, BigDecimal::add);
//                String recv_no = value.stream().map(TErpProcurementGoods::getRecvNo).collect(Collectors.toList()).get(0);
//            }
            HashMap<String, Object> map1 = new HashMap<>();
            // TODO hzt
            map1.put("recv_no", "SR2024000006413");
            map1.put("amt", erpProcurement.getMoney().multiply(BigDecimal.valueOf(100)).intValue() + "");
            objects.add(map1);
            map.put("total_amt",erpProcurement.getMoney().multiply(BigDecimal.valueOf(100)).intValue() + "");
            map.put("origin_recv_datas",objects);
            reqMap.put("req_data", map);
            String jsonString = JSON.toJSONString(reqMap);
            String authorization1 = getAuthorization(jsonString);
            org.apache.http.HttpResponse response1 = post(LakalaConfig.getServerUrl() + "sit/api/v3/sacs/fallback", jsonString, authorization1);
            String responseStr = IOUtils.toString(response1.getEntity().getContent(), ENCODING);
//            post.body(jsonString);
//            HttpResponse response = post.execute();
//            String responseStr = response.body();
            return R.ok(responseStr);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return R.fail(500, "退款失败请联系平台管理员");
    }
    public org.apache.http.HttpResponse post(String url, String message, String authorization) throws Exception {
        SSLContext ctx = SSLContext.getInstance("TLS");
        X509TrustManager tm = new X509TrustManager() {
            public X509Certificate[] getAcceptedIssuers() {
                return null;
            }
            public void checkClientTrusted(X509Certificate[] xcs, String str) {
            }
            public void checkServerTrusted(X509Certificate[] xcs, String str) {
            }
        };
        HttpClient http = new DefaultHttpClient();
        ClientConnectionManager ccm = http.getConnectionManager();
        ctx.init(null, new TrustManager[]{tm}, null);
        SSLSocketFactory ssf = new SSLSocketFactory(ctx);
        ssf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
        SchemeRegistry registry = ccm.getSchemeRegistry();
        registry.register(new Scheme("https", ssf, 443));
        HttpPost post = new HttpPost(url);
        StringEntity myEntity = new StringEntity(message, ENCODING);
        post.setEntity(myEntity);
        post.setHeader("Authorization", SCHEMA + " " + authorization);
        post.setHeader("Accept", "application/json");
        post.setHeader("Content-Type", "application/json");
        return http.execute(post);
    }
    public final String getAuthorization(String body) throws IOException {
        String nonceStr = generateNonceStr();
        long timestamp = generateTimestamp();
        String message = LakalaConfig.getAppId() + "\n" + LakalaConfig.getMerchantNo() + "\n" + timestamp + "\n" + nonceStr + "\n" + body + "\n";
        System.out.println("getToken message :  " + message);
        PrivateKey merchantPrivateKey = loadPrivateKey(new FileInputStream(new File(LakalaConfig.getPriKeyStr())));
        String signature = this.sign(message.getBytes(ENCODING), merchantPrivateKey);
        String authorization = "appid=\"" + LakalaConfig.getAppId() + "\"," + "serial_no=\"" + LakalaConfig.getMerchantNo() + "\"," + "timestamp=\""
                + timestamp + "\"," + "nonce_str=\"" + nonceStr + "\"," + "signature=\"" + signature + "\"";
        System.out.println("authorization message :" + authorization);
        return authorization;
    }
    public long generateTimestamp() {
        return System.currentTimeMillis() / 1000;
    }
    public String generateNonceStr() {
        char[] nonceChars = new char[32];
        for (int index = 0; index < nonceChars.length; ++index) {
            nonceChars[index] = SYMBOLS.charAt(RANDOM.nextInt(SYMBOLS.length()));
        }
        return new String(nonceChars);
    }
    public static PrivateKey loadPrivateKey(InputStream inputStream) {
        try {
            ByteArrayOutputStream array = new ByteArrayOutputStream();
            byte[] buffer = new byte[1024];
            int length;
            while ((length = inputStream.read(buffer)) != -1) {
                array.write(buffer, 0, length);
            }
            String privateKey = array.toString("utf-8").replace("-----BEGIN PRIVATE KEY-----", "")
                    .replace("-----END PRIVATE KEY-----", "").replaceAll("\\s+", "");
            KeyFactory kf = KeyFactory.getInstance("RSA");
            return kf.generatePrivate(new PKCS8EncodedKeySpec(Base64.decodeBase64(privateKey)));
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException("当前Java环境不支持RSA", e);
        } catch (InvalidKeySpecException e) {
            throw new RuntimeException("无效的密钥格式");
        } catch (IOException e) {
            throw new RuntimeException("无效的密钥");
        }
    }
    public String sign(byte[] message, PrivateKey privateKey) {
        try {
            Signature sign = Signature.getInstance("SHA256withRSA");
            sign.initSign(privateKey);
            sign.update(message);
            return new String(Base64.encodeBase64(sign.sign()));
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException("当前Java环境不支持SHA256withRSA", e);
        } catch (SignatureException e) {
            throw new RuntimeException("签名计算失败", e);
        } catch (InvalidKeyException e) {
            throw new RuntimeException("无效的私钥", e);
        }
    }
    public final String getBody(HttpServletRequest request) {
        InputStreamReader in = null;
        try {
            in = new InputStreamReader(request.getInputStream(), StandardCharsets.UTF_8);
            StringBuffer bf = new StringBuffer();
            int len;
            char[] chs = new char[1024];
            while ((len = in.read(chs)) != -1) {
                bf.append(new String(chs, 0, len));
            }
            return bf.toString();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (null != in) {
                try {
                    in.close();
                } catch (Exception e) {
                }
            }
        }
        return null;
    }
    public static X509Certificate loadCertificate(InputStream inputStream) {
        try {
            CertificateFactory cf = CertificateFactory.getInstance("X509");
            X509Certificate cert = (X509Certificate) cf.generateCertificate(inputStream);
            cert.checkValidity();
            return cert;
        } catch (CertificateExpiredException e) {
            throw new RuntimeException("证书已过期", e);
        } catch (CertificateNotYetValidException e) {
            throw new RuntimeException("证书尚未生效", e);
        } catch (CertificateException e) {
            throw new RuntimeException("无效的证书", e);
        }
    }
    private static boolean verify(X509Certificate certificate, byte[] message, String signature) {
        try {
            Signature sign = Signature.getInstance("SHA256withRSA");
            sign.initVerify(certificate);
            sign.update(message);
            byte[] signatureB = Base64.decodeBase64(signature);
            return sign.verify(signatureB);
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException("当前Java环境不支持SHA256withRSA", e);
        } catch (SignatureException e) {
            throw new RuntimeException("签名验证过程发生了错误", e);
        } catch (InvalidKeyException e) {
            throw new RuntimeException("无效的证书", e);
        }
    }
}
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TSysOrderController.java
@@ -8,17 +8,21 @@
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.lkl.laop.sdk.exception.SDKException;
import com.ruoyi.common.basic.PageInfo;
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.model.*;
import com.ruoyi.system.query.TErpGoodsWarehouseQuery;
import com.ruoyi.system.query.TSysAppUserQuery;
import com.ruoyi.system.query.TSysEducationalInfoQuery;
import com.ruoyi.system.query.TSysOrderQuery;
import com.ruoyi.system.service.*;
import com.ruoyi.system.vo.TSysOrderPageVo;
import com.ruoyi.web.core.config.LakalaConfig;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
@@ -68,607 +72,60 @@
 * @since 2025-08-20
 */
@RestController
@RequestMapping("/t-sys-order")
@RequestMapping("")
@Api(tags = "订单管理")
public class TSysOrderController {
    private final TErpProcurementService erpProcurementService;
    private final TErpProcurementGoodsService erpProcurementGoodsService;
    private final TCrmSupplierService crmSupplierService;
    private final TSysOrderService sysOrderService;
    private final TokenService tokenService;
    private final TCrmClinicService crmClinicService;
    private final TSysAppUserService sysAppUserService;
    @Autowired
    public TSysOrderController(TErpProcurementService erpProcurementService, TokenService tokenService, TErpProcurementGoodsService erpProcurementGoodsService, TCrmSupplierService crmSupplierService) {
        this.erpProcurementService = erpProcurementService;
    public TSysOrderController(TokenService tokenService, TSysOrderService sysOrderService, TCrmClinicService crmClinicService, TSysAppUserService sysAppUserService) {
        this.sysOrderService = sysOrderService;
        this.tokenService = tokenService;
        this.erpProcurementGoodsService = erpProcurementGoodsService;
        this.crmSupplierService = crmSupplierService;
    }
        this.crmClinicService = crmClinicService;
        this.sysAppUserService = sysAppUserService;
    private static final String SYMBOLS = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
    }
    /**
     * API schema ,固定 LKLAPI-SHA256withRSA
     * 获取诊所患者诊疗 订单列表
     */
    public final static String SCHEMA = "LKLAPI-SHA256withRSA";
    @ApiOperation(value = "获取诊所患者诊疗订单列表")
    @PostMapping(value = "/pageList")
    public R<PageInfo<TSysOrderPageVo>> pageList(@RequestBody TSysOrderQuery query) {
    /**
     * 字符集固定 utf-8
     */
    public static final String ENCODING = "utf-8";
    private static final SecureRandom RANDOM = new SecureRandom();
    @ApiOperation(value = "支付")
    @PostMapping(value = "/payOrder")
    @SneakyThrows
    public R<?> payOrder(@RequestParam String id, String type, HttpServletRequest request) {
        try {
            // 查出采购单 算出价格  下单  算出应该分佣金额 应该分给谁
            TErpProcurement erpProcurement = erpProcurementService.getById(id);
            if (erpProcurement.getStatus()>2) {
                return R.fail("订单已支付");
            }
            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());
            TCrmSupplier supplier = crmSupplierService.getById(erpProcurement.getSupplierId());
            String trans_type ="41";
            if("WECHAT".equals(type)){
                trans_type= "51";
            }
            String apiPath = "sit/api/v3/labs/trans/preorder";
            String body = "{\n" +
                    "\t\"req_time\": \"" + time + "\",\n" +
                    "\t\"version\": \"3.0\",\n" +
                    "\t\"req_data\": {\n" +
                    "\t\t\"out_trade_no\": \"" + outTradeNo + "\",\n" +
                    "\t\t\"merchant_no\": \""+supplier.getRecvMerchantNo()+"\",\n" +
                    "\t\t\"term_no\": \""+supplier.getTermNo()+"\",\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\": \"" + ipAddr + "\"\n" +
                    "\t\t},\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\": \""+trans_type+"\"\n" +
                    "\t}\n" +
                    "}";
            String authorization = getAuthorization(body);
            org.apache.http.HttpResponse response = post(LakalaConfig.getServerUrl() + apiPath, body, authorization);
            if (response.getStatusLine().getStatusCode() != 200) {
                return R.fail(500, "请求失败,statusCode  " + response.getStatusLine()
                        + 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(supplier.getTermNo());
            erpProcurement.setAccountType(type);
            erpProcurement.setTransType(trans_type);
            erpProcurementService.updateById(erpProcurement);
            return R.ok(responseStr);
        } catch (SDKException e) {
            e.printStackTrace();
        }
        return R.fail(500, "调用支付宝支付预下单接口错误");
    }
    @RequestMapping("/messageHandle")
    @ApiOperation(value = "拉卡拉支付信息回调接口")
    public Object messageHandle(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);
            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> reqMap = new HashMap<>();
            reqMap.put("version", "3.0");
            reqMap.put("req_time", DateUtils.dateTimeNow());
            HashMap<String, Object> map = new HashMap<>();
            map.put("merchant_no", erpProcurement.getMerchantNo());
            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 allMoney = erpProcurement.getPayMoney();
            // 平台应得分账
            BigDecimal payMoney = erpProcurement.getMoney();
            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_no", supplier.getRecvMerchantNo());
//                map1.put("separate_value", reduce.multiply(BigDecimal.valueOf(100)).intValue() + "");
////                objects.add(map1);
//            }
            HashMap<String, Object> map1 = new HashMap<>();
            //TODO hzt
            map1.put("recv_no", "SR2024000006413");
            // 手续费
            BigDecimal bigDecimal = allMoney.multiply(new BigDecimal("0.038")).setScale(2, RoundingMode.HALF_UP);
            payMoney = payMoney.subtract(bigDecimal);
            map1.put("separate_value", payMoney.multiply(BigDecimal.valueOf(100)).intValue() + "");
            if(payMoney.doubleValue()>0){
                objects.add(map1);
            }
            erpProcurement.setMoney(payMoney);
            erpProcurement.setOutSeparateNo(outTradeNo);
            erpProcurementService.updateById(erpProcurement);
            // 添加平台的
            map.put("recv_datas", objects);
            reqMap.put("req_data", map);
            String jsonString = JSON.toJSONString(reqMap);
//            String authorization1 = getAuthorization(jsonString);
//            post.header("Authorization", SCHEMA + " " + authorization);
//
//            post.body(jsonString);
//            HttpResponse response = post.execute();
//            String responseStr = response.body();
            String authorization1 = getAuthorization(jsonString);
            org.apache.http.HttpResponse response1 = post(LakalaConfig.getServerUrl() + "sit/api/v3/sacs/separate", jsonString, authorization1);
            String responseStr = IOUtils.toString(response1.getEntity().getContent(), ENCODING);
            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);
        // 先处理支付完成  修改状态 后处理分账  后走分账回调
        JSONObject jsonObject1 = JSONObject.parseObject(body);
        Object o = jsonObject1.get("out_separate_no");
        Object status = jsonObject1.get("status");
        Object cmd_type = jsonObject1.get("cmd_type");
        Object detail_datas = jsonObject1.get("detail_datas");
        JSONArray jsonArray = JSONArray.parseArray(detail_datas.toString());
        if("SEPARATE".equals(cmd_type.toString())){
            TErpProcurement erpProcurement = erpProcurementService.getOne(new LambdaQueryWrapper<TErpProcurement>().eq(TErpProcurement::getOutSeparateNo, o.toString()));
            if ( erpProcurement!=null && "SUCCESS".equals(status)) {
                erpProcurement.setRefundStatus(1);
                erpProcurementService.updateById(erpProcurement);
                // 修改分账状态
                List<TErpProcurementGoods> list1 = erpProcurementGoodsService.list(new LambdaQueryWrapper<TErpProcurementGoods>().eq(TErpProcurementGoods::getProcurementId, erpProcurement.getId()));
                list1.stream().forEach(e->e.setStatus(1));
                erpProcurementGoodsService.updateBatchById(list1);
                // 响应success
                JSONObject jsonObject = new JSONObject();
                jsonObject.put("code", "SUCCESS");
                jsonObject.put("message", "执行成功");
                return jsonObject;
            }
        }else if("FALLBACK".equals(cmd_type.toString())){
            TErpProcurement erpProcurement = erpProcurementService.getOne(new LambdaQueryWrapper<TErpProcurement>().eq(TErpProcurement::getRefundOutSeparateNo, o.toString()));
            if ( erpProcurement!=null && "SUCCESS".equals(status) && erpProcurement.getRefundStatus()==1) {
                erpProcurement.setRefundStatus(2);
                erpProcurementService.updateById(erpProcurement);
                List<TErpProcurementGoods> list1 = erpProcurementGoodsService.list(new LambdaQueryWrapper<TErpProcurementGoods>().eq(TErpProcurementGoods::getProcurementId, erpProcurement.getId()));
                list1.stream().forEach(e->e.setStatus(2));
                erpProcurementGoodsService.updateBatchById(list1);
                // 发起退款
                String time = DateUtils.dateTimeNow();
                String ipAddr = IpUtils.getIpAddr(request);
                // SYMBOLS 随机取4位数
                String str = "";
                for (int i = 0; i < 6; i++) {
                    str += SYMBOLS.charAt(RANDOM.nextInt(SYMBOLS.length()));
                }
                String outTradeNo = time + str;
                String refund_amount = erpProcurement.getPayMoney().multiply(BigDecimal.valueOf(100)).intValue() + "";
                String apiPath = "sit/api/v3/rfd/refund_front/refund";
                String body1 = "{\n" +
                        "\t\"req_time\": \"" + time + "\",\n" +
                        "\t\"version\": \"3.0\",\n" +
                        "\t\"req_data\": {\n" +
                        "\t\t\"merchant_no\": \""+erpProcurement.getMerchantNo()+"\",\n" +
                        "\t\t\"term_no\": \""+erpProcurement.getTermNo()+"\",\n" +
                        "\t\t\"refund_amount\": " + refund_amount + ",\n" +
                        "\t\t\"out_trade_no\": \"" + outTradeNo + "\",\n" +
                        "\t\t\"notify_url\": \"" + "http://221.182.45.100:8089/t-sys-order/messageRefundHandle" + "\",\n" +
                        "\t\t\"origin_log_no\": \"" + erpProcurement.getPayTransactionId() + "\",\n" +
                        "\t\t\"location_info\": {\n" +
                        "\t\t\t\"request_ip\": \"" + ipAddr + "\"\n" +
                        "\t\t},\n" +
                        "\t}\n" +
                        "}";
                String authorization = getAuthorization(body1);
                org.apache.http.HttpResponse response = post(LakalaConfig.getServerUrl() + apiPath, body1, authorization);
                if (response.getStatusLine().getStatusCode() != 200) {
                    return R.fail(500, "请求失败,statusCode  " + response.getStatusLine()
                            + IOUtils.toString(response.getEntity().getContent(), ENCODING));
                }
                String responseStr = IOUtils.toString(response.getEntity().getContent(), ENCODING);
                JSONObject jsonObject = JSONObject.parseObject(responseStr);
                JSONObject jsonObject2 = jsonObject.getJSONObject("resp_data");
                String code = jsonObject2.getString("log_no");
                erpProcurement.setRefundLogNo(code);
                erpProcurement.setRefundNo(outTradeNo);
                erpProcurementService.updateById(erpProcurement);
                // 响应success
                JSONObject jsonObject3 = new JSONObject();
                jsonObject3.put("code", "SUCCESS");
                jsonObject3.put("message", "执行成功");
                return jsonObject3;
            }
        }
        return null;
    }
    @RequestMapping("/messageRefundHandle")
    @ApiOperation(value = "拉卡拉退款信息回调接口")
    public Object messageRefundHandle(HttpServletRequest request) throws Exception {
        String body = this.getBody(request);
        // 先处理支付完成  修改状态 后处理分账  后走分账回调
        JSONObject jsonObject1 = JSONObject.parseObject(body);
        Object status = jsonObject1.get("trade_status");
        Object out_trade_no = jsonObject1.get("out_trade_no");
        if(status !=null && "SUCCESS".equals(status.toString())){
            TErpProcurement erpProcurement = erpProcurementService.getOne(new LambdaQueryWrapper<TErpProcurement>().eq(TErpProcurement::getRefundNo, out_trade_no.toString()));
            if ( erpProcurement!=null && "SUCCESS".equals(status)) {
                erpProcurement.setStatus(6);
                erpProcurementService.updateById(erpProcurement);
                // 响应success
                JSONObject jsonObject = new JSONObject();
                jsonObject.put("code", "SUCCESS");
                jsonObject.put("message", "执行成功");
                return jsonObject;
            }
        }
        return null;
    }
    @ApiOperation(value = "退款")
    @PostMapping(value = "/refundOrder")
    @SneakyThrows
    public R<?> refundOrder(@RequestParam String id, HttpServletRequest request) {
        SysUser user = tokenService.getLoginUser().getUser();
        try {
            // 先退分账  在退订单
            // 查出采购单 算出价格  下单  算出应该分佣金额 应该分给谁
            TErpProcurement erpProcurement = erpProcurementService.getById(id);
            // 还未分账成功不能退款
        if(erpProcurement.getStatus()==null || erpProcurement.getStatus()!=1){
            return R.fail("订单处理中,请稍后操作");
        Integer roleType = user.getRoleType();
        if(roleType == 5){
            // 诊所
            TCrmClinic crmClinic = crmClinicService.getOne(Wrappers.lambdaQuery(TCrmClinic.class)
                    .eq(TCrmClinic::getUserId, user.getUserId())
                    .last("LIMIT 1"));
            query.setClinicId(crmClinic.getId());
        }
            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;
            // 操作分账
//            HttpRequest post = HttpUtil.createPost(LakalaConfig.getServerUrl() + "sit/api/v3/sacs/fallback");
            HashMap<String, Object> reqMap = new HashMap<>();
            reqMap.put("version", "3.0");
            reqMap.put("req_time", DateUtils.dateTimeNow());
        return R.ok(sysOrderService.pageList(query));
    }
            HashMap<String, Object> map = new HashMap<>();
            map.put("merchant_no", erpProcurement.getMerchantNo());
            map.put("origin_separate_no", erpProcurement.getSeparateNo());
            map.put("out_separate_no",outTradeNo);
            erpProcurement.setRefundOutSeparateNo(outTradeNo);
            erpProcurementService.updateById(erpProcurement);
//            List<TErpProcurementGoods> list = erpProcurementGoodsService.list(new LambdaQueryWrapper<TErpProcurementGoods>().eq(TErpProcurementGoods::getProcurementId, erpProcurement.getId()));
            // 根据供应商id分组
//            Map<String, List<TErpProcurementGoods>> collect = list.stream().collect(Collectors.groupingBy(TErpProcurementGoods::getSupplierId));
            ArrayList<HashMap<String, Object>> objects = new ArrayList<>();
//            BigDecimal allMoney = list.stream().map(TErpProcurementGoods::getSupplierMoney).reduce(BigDecimal.ZERO, BigDecimal::add);
//            for (Map.Entry<String, List<TErpProcurementGoods>> entry : collect.entrySet()) {
//
//                List<TErpProcurementGoods> value = entry.getValue();
//                BigDecimal reduce = value.stream().map(TErpProcurementGoods::getSupplierMoney).reduce(BigDecimal.ZERO, BigDecimal::add);
//                String recv_no = value.stream().map(TErpProcurementGoods::getRecvNo).collect(Collectors.toList()).get(0);
//            }
            HashMap<String, Object> map1 = new HashMap<>();
            // TODO hzt
            map1.put("recv_no", "SR2024000006413");
            map1.put("amt", erpProcurement.getMoney().multiply(BigDecimal.valueOf(100)).intValue() + "");
            objects.add(map1);
            map.put("total_amt",erpProcurement.getMoney().multiply(BigDecimal.valueOf(100)).intValue() + "");
            map.put("origin_recv_datas",objects);
            reqMap.put("req_data", map);
            String jsonString = JSON.toJSONString(reqMap);
            String authorization1 = getAuthorization(jsonString);
            org.apache.http.HttpResponse response1 = post(LakalaConfig.getServerUrl() + "sit/api/v3/sacs/fallback", jsonString, authorization1);
            String responseStr = IOUtils.toString(response1.getEntity().getContent(), ENCODING);
//            post.body(jsonString);
//            HttpResponse response = post.execute();
//            String responseStr = response.body();
            return R.ok(responseStr);
        } catch (Exception e) {
            e.printStackTrace();
    @ApiOperation(value = "获取诊所患者诊疗--搜索用户")
    @PostMapping(value = "/userList")
    public R<List<TSysAppUser>> pageList(@RequestBody TSysAppUserQuery query) {
        LambdaQueryWrapper<TSysAppUser> eq = new LambdaQueryWrapper<TSysAppUser>().eq(TSysAppUser::getStatus, 1);
        if(query.getNickName() != null && !query.getNickName().isEmpty()){
            eq.like(TSysAppUser::getNickName, query.getNickName());
        }
        return R.fail(500, "退款失败请联系平台管理员");
    }
    public org.apache.http.HttpResponse post(String url, String message, String authorization) throws Exception {
        SSLContext ctx = SSLContext.getInstance("TLS");
        X509TrustManager tm = new X509TrustManager() {
            public X509Certificate[] getAcceptedIssuers() {
                return null;
            }
            public void checkClientTrusted(X509Certificate[] xcs, String str) {
            }
            public void checkServerTrusted(X509Certificate[] xcs, String str) {
            }
        };
        HttpClient http = new DefaultHttpClient();
        ClientConnectionManager ccm = http.getConnectionManager();
        ctx.init(null, new TrustManager[]{tm}, null);
        SSLSocketFactory ssf = new SSLSocketFactory(ctx);
        ssf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
        SchemeRegistry registry = ccm.getSchemeRegistry();
        registry.register(new Scheme("https", ssf, 443));
        HttpPost post = new HttpPost(url);
        StringEntity myEntity = new StringEntity(message, ENCODING);
        post.setEntity(myEntity);
        post.setHeader("Authorization", SCHEMA + " " + authorization);
        post.setHeader("Accept", "application/json");
        post.setHeader("Content-Type", "application/json");
        return http.execute(post);
    }
    public final String getAuthorization(String body) throws IOException {
        String nonceStr = generateNonceStr();
        long timestamp = generateTimestamp();
        String message = LakalaConfig.getAppId() + "\n" + LakalaConfig.getMerchantNo() + "\n" + timestamp + "\n" + nonceStr + "\n" + body + "\n";
        System.out.println("getToken message :  " + message);
        PrivateKey merchantPrivateKey = loadPrivateKey(new FileInputStream(new File(LakalaConfig.getPriKeyStr())));
        String signature = this.sign(message.getBytes(ENCODING), merchantPrivateKey);
        String authorization = "appid=\"" + LakalaConfig.getAppId() + "\"," + "serial_no=\"" + LakalaConfig.getMerchantNo() + "\"," + "timestamp=\""
                + timestamp + "\"," + "nonce_str=\"" + nonceStr + "\"," + "signature=\"" + signature + "\"";
        System.out.println("authorization message :" + authorization);
        return authorization;
    }
    public long generateTimestamp() {
        return System.currentTimeMillis() / 1000;
    }
    public String generateNonceStr() {
        char[] nonceChars = new char[32];
        for (int index = 0; index < nonceChars.length; ++index) {
            nonceChars[index] = SYMBOLS.charAt(RANDOM.nextInt(SYMBOLS.length()));
        if(query.getPhone() != null && !query.getPhone().isEmpty()){
            eq.like(TSysAppUser::getPhone, query.getPhone());
        }
        return new String(nonceChars);
        List<TSysAppUser> list = sysAppUserService.list(eq);
        return R.ok(list);
    }
    public static PrivateKey loadPrivateKey(InputStream inputStream) {
        try {
            ByteArrayOutputStream array = new ByteArrayOutputStream();
            byte[] buffer = new byte[1024];
            int length;
            while ((length = inputStream.read(buffer)) != -1) {
                array.write(buffer, 0, length);
            }
            String privateKey = array.toString("utf-8").replace("-----BEGIN PRIVATE KEY-----", "")
                    .replace("-----END PRIVATE KEY-----", "").replaceAll("\\s+", "");
            KeyFactory kf = KeyFactory.getInstance("RSA");
            return kf.generatePrivate(new PKCS8EncodedKeySpec(Base64.decodeBase64(privateKey)));
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException("当前Java环境不支持RSA", e);
        } catch (InvalidKeySpecException e) {
            throw new RuntimeException("无效的密钥格式");
        } catch (IOException e) {
            throw new RuntimeException("无效的密钥");
        }
    }
    public String sign(byte[] message, PrivateKey privateKey) {
        try {
            Signature sign = Signature.getInstance("SHA256withRSA");
            sign.initSign(privateKey);
            sign.update(message);
            return new String(Base64.encodeBase64(sign.sign()));
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException("当前Java环境不支持SHA256withRSA", e);
        } catch (SignatureException e) {
            throw new RuntimeException("签名计算失败", e);
        } catch (InvalidKeyException e) {
            throw new RuntimeException("无效的私钥", e);
        }
    }
    public final String getBody(HttpServletRequest request) {
        InputStreamReader in = null;
        try {
            in = new InputStreamReader(request.getInputStream(), StandardCharsets.UTF_8);
            StringBuffer bf = new StringBuffer();
            int len;
            char[] chs = new char[1024];
            while ((len = in.read(chs)) != -1) {
                bf.append(new String(chs, 0, len));
            }
            return bf.toString();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (null != in) {
                try {
                    in.close();
                } catch (Exception e) {
                }
            }
        }
        return null;
    }
    public static X509Certificate loadCertificate(InputStream inputStream) {
        try {
            CertificateFactory cf = CertificateFactory.getInstance("X509");
            X509Certificate cert = (X509Certificate) cf.generateCertificate(inputStream);
            cert.checkValidity();
            return cert;
        } catch (CertificateExpiredException e) {
            throw new RuntimeException("证书已过期", e);
        } catch (CertificateNotYetValidException e) {
            throw new RuntimeException("证书尚未生效", e);
        } catch (CertificateException e) {
            throw new RuntimeException("无效的证书", e);
        }
    }
    private static boolean verify(X509Certificate certificate, byte[] message, String signature) {
        try {
            Signature sign = Signature.getInstance("SHA256withRSA");
            sign.initVerify(certificate);
            sign.update(message);
            byte[] signatureB = Base64.decodeBase64(signature);
            return sign.verify(signatureB);
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException("当前Java环境不支持SHA256withRSA", e);
        } catch (SignatureException e) {
            throw new RuntimeException("签名验证过程发生了错误", e);
        } catch (InvalidKeyException e) {
            throw new RuntimeException("无效的证书", e);
        }
    }
}
ruoyi-system/src/main/java/com/ruoyi/system/mapper/TErpGoodsMapper.java
@@ -35,7 +35,7 @@
    List<TErpGoodsInventoryVO> pageInventoryGoodsList1(@Param("warehouseId") String warehouseId, @Param("user") SysUser user, @Param("supplierClinicId") String supplierClinicId, @Param("endDate") Date endDate);
    List<TErpGoodsInventoryVO> pageInventoryGoodsPageList1(@Param("query") TErpGoodsInventoryQuery query, @Param("pageInfo") PageInfo<TErpGoodsInventoryVO> pageInfo, @Param("user") SysUser user, @Param("supplierClinicId") String supplierClinicId, @Param("endDate") Date endDate);
    List<TErpGoodsInventoryVO> pageInventoryGoodsPageList1(@Param("query") TErpGoodsInventoryQuery query, @Param("pageInfo") PageInfo<TErpGoodsInventoryVO> pageInfo, @Param("user") SysUser user, @Param("supplierClinicId") String supplierClinicId, @Param("time") Date endDate);
    TErpGoods getGoodsById(@Param("goodsId") String goodsId);
ruoyi-system/src/main/java/com/ruoyi/system/mapper/TSysOrderMapper.java
@@ -1,7 +1,10 @@
package com.ruoyi.system.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.ruoyi.common.basic.PageInfo;
import com.ruoyi.system.model.TSysOrder;
import com.ruoyi.system.query.TSysOrderQuery;
import com.ruoyi.system.vo.TSysOrderPageVo;
import com.ruoyi.system.vo.TSysOrderVO;
import org.apache.ibatis.annotations.Param;
@@ -24,4 +27,8 @@
     * @return 订单列表
     */
    List<TSysOrderVO> queryListByAppUserId(@Param("appUserId") String appUserId);
    List<TSysOrderPageVo> pageList(@Param("page") PageInfo<TSysOrderPageVo> page, @Param("query") TSysOrderQuery query, @Param("sTime") String sTime, @Param("eTime") String eTime);
}
ruoyi-system/src/main/java/com/ruoyi/system/model/TSysOrder.java
@@ -35,6 +35,10 @@
    @TableField("app_user_id")
    private String appUserId;
    @ApiModelProperty(value = "诊所id")
    @TableField("clinic_id")
    private String clinicId;
    @ApiModelProperty(value = "检测信息id")
    @TableField("inspection_id")
    private String inspectionId;
ruoyi-system/src/main/java/com/ruoyi/system/query/TSysOrderQuery.java
New file
@@ -0,0 +1,23 @@
package com.ruoyi.system.query;
import com.ruoyi.common.core.domain.BasePage;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
@ApiModel("患者诊疗 订单列表query")
public class TSysOrderQuery extends BasePage {
    @ApiModelProperty("用户名称")
    private String userName;
    @ApiModelProperty("手机号")
    private String phone;
    @ApiModelProperty("时间 2022-02-02 - 2022-02-02")
    private String time;
    private String clinicId;
}
ruoyi-system/src/main/java/com/ruoyi/system/service/TSysOrderService.java
@@ -1,7 +1,10 @@
package com.ruoyi.system.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.ruoyi.common.basic.PageInfo;
import com.ruoyi.system.model.TSysOrder;
import com.ruoyi.system.query.TSysOrderQuery;
import com.ruoyi.system.vo.TSysOrderPageVo;
import com.ruoyi.system.vo.TSysOrderVO;
import java.util.List;
@@ -22,4 +25,7 @@
     * @return
     */
    List<TSysOrderVO> queryListByAppUserId(String id);
    PageInfo<TSysOrderPageVo> pageList(TSysOrderQuery query);
}
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TSysOrderServiceImpl.java
@@ -2,11 +2,14 @@
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.common.basic.PageInfo;
import com.ruoyi.system.mapper.TSysOrderGoodsMapper;
import com.ruoyi.system.mapper.TSysOrderMapper;
import com.ruoyi.system.model.TSysOrder;
import com.ruoyi.system.model.TSysOrderGoods;
import com.ruoyi.system.query.TSysOrderQuery;
import com.ruoyi.system.service.TSysOrderService;
import com.ruoyi.system.vo.TSysOrderPageVo;
import com.ruoyi.system.vo.TSysOrderVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@@ -43,4 +46,19 @@
        }
        return this.baseMapper.queryListByAppUserId(id);
    }
    @Override
    public PageInfo<TSysOrderPageVo> pageList(TSysOrderQuery query) {
        PageInfo<TSysOrderPageVo> page = new PageInfo<>(query.getPageNum(), query.getPageSize());
        String sTime =null;
        String eTime = null;
        if(query.getTime() != null && !query.getTime().isEmpty()){
            String[] split = query.getTime().split(" - ");
            sTime = split[0] + " 00:00:00";
            eTime = split[1] + " 23:59:59";
        }
        List<TSysOrderPageVo> sysOrderPageVOS = this.baseMapper.pageList(page, query,sTime,eTime);
        page.setRecords(sysOrderPageVOS);
        return page;
    }
}
ruoyi-system/src/main/java/com/ruoyi/system/vo/TSysOrderPageVo.java
New file
@@ -0,0 +1,30 @@
package com.ruoyi.system.vo;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.math.BigDecimal;
import java.util.Date;
@Data
@ApiModel("患者诊疗 订单管理分页对象")
public class TSysOrderPageVo {
    @ApiModelProperty("id")
    private String id;
    @ApiModelProperty("用户名称")
    private String userName;
    @ApiModelProperty("手机号")
    private String phone;
    @ApiModelProperty("时间")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
    private Date createTime;
    @ApiModelProperty("金额")
    private BigDecimal totalMoney;
}
ruoyi-system/src/main/resources/mapper/system/TSysOrderMapper.xml
@@ -28,4 +28,22 @@
        where app_user_id = #{appUserId} and disabled = ${@com.ruoyi.common.enums.DisabledEnum@NO.getCode()}
    </select>
    <select id="pageList" resultType="com.ruoyi.system.vo.TSysOrderPageVo">
        select t1.id,t1.create_time,t1.total_money,t2.nick_name as userName,t2.phone from t_sys_order t1
        left join t_sys_app_user t2 on t1.app_user_id = t2.id
        where t1.disabled = 0  and t1.clinic_id =#{query.clinicId}
        <if test="query.userName != null and query.userName != ''">
            and t2.nick_name like concat('%',#{query.userName},'%')
        </if>
        <if test="query.phone != null and query.phone != ''">
            and t2.phone like concat('%',#{query.phone},'%')
        </if>
        <if test="sTime != null and eTime != ''">
            and t1.create_time between #{sTime} and #{eTime}
        </if>
        order by t1.create_time desc
    </select>
</mapper>