liujie
2025-11-24 8601dadb2ac1f3c59b7619ef037b1dcdf426bf4c
Merge branch 'master' of http://120.76.84.145:10101/gitblit/r/java/JiaYiXing2025
9个文件已添加
13个文件已修改
1044 ■■■■■ 已修改文件
DriverJYXTravel/guns-admin/pom.xml 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
DriverJYXTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/account/req/UserWithdrawalReq.java 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
DriverJYXTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/api/RegionController.java 68 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
DriverJYXTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/model/UserWithdrawal.java 4 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
DriverJYXTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/service/IRegionService.java 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
DriverJYXTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/service/impl/RegionServiceImpl.java 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
EurekaJYXTravel/target/classes/application.yml 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ManagementJYXTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/huifu/biz/DouGongBasicDataBiz.java 37 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ManagementJYXTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/huifu/biz/DouGongWithdrawBiz.java 170 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ManagementJYXTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/huifu/biz/FenZhangUtil.java 52 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ManagementJYXTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/huifu/controller/DouGongNotifyController.java 106 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ManagementJYXTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/controller/general/TCompanyWithdrawController.java 69 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ManagementJYXTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/controller/general/TEnterpriseWithdrawalController.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ManagementJYXTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/controller/general/TPubWithdrawalController.java 44 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ManagementJYXTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/controller/specialTrain/TOrderLogisticsController.java 55 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ManagementJYXTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/model/TCompanyWithdraw.java 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ManagementJYXTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/model/TPubWithdrawal.java 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
UserJYXTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/account/req/UserWithdrawalReq.java 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
UserJYXTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/api/RegionController.java 69 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
UserJYXTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/huifu/DouGongNotifyController.java 43 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
UserJYXTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/huifu/biz/DouGongWithdrawBiz.java 168 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
UserJYXTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/controller/BlackboardController.java 1 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
DriverJYXTravel/guns-admin/pom.xml
@@ -22,16 +22,34 @@
            <groupId>com.github.binarywang</groupId>
            <artifactId>weixin-java-mp</artifactId>
            <version>2.6.0</version>
            <exclusions>
                <exclusion>
                    <artifactId>guava</artifactId>
                    <groupId>com.google.guava</groupId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
            <exclusions>
                <exclusion>
                    <artifactId>guava</artifactId>
                    <groupId>com.google.guava</groupId>
                </exclusion>
            </exclusions>
        </dependency>
        <!--整合hystrix-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
            <exclusions>
                <exclusion>
                    <artifactId>guava</artifactId>
                    <groupId>com.google.guava</groupId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>com.stylefeng</groupId>
DriverJYXTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/account/req/UserWithdrawalReq.java
@@ -38,7 +38,7 @@
    private String certificateExpireTime;
    @TableField("licenceIssuingAuthority")
    @ApiModelProperty(value = "发证机关")
    @ApiModelProperty(value = "【废弃】发证机关")
    private String licenceIssuingAuthority;
    @TableField("bankName")
@@ -50,11 +50,11 @@
    private String bankCardCode;
    @TableField("bankCode")
    @ApiModelProperty(value = "开户银行编码")
    @ApiModelProperty(value = "【废弃】开户银行编码")
    private String bankCode;
    @TableField("bankBranchCode")
    @ApiModelProperty(value = "开户银行联行号")
    @ApiModelProperty(value = "【废弃】开户银行联行号")
    private String bankBranchCode;
    @TableField("openAccountName")
@@ -62,7 +62,7 @@
    private String openAccountName;
    @TableField("transactionAuthorizationCode")
    @ApiModelProperty(value = "交易授权码")
    @ApiModelProperty(value = "【废弃】交易授权码")
    private String transactionAuthorizationCode;
    @TableField("phone")
@@ -70,11 +70,11 @@
    private String phone;
    @TableField("idCardFrontPicture")
    @ApiModelProperty(value = "法人身份证照片正面")
    @ApiModelProperty(value = "【废弃】法人身份证照片正面")
    private String idCardFrontPicture;
    @TableField("idCardReversePicture")
    @ApiModelProperty(value = "法人身份证照片反面")
    @ApiModelProperty(value = "【废弃】法人身份证照片反面")
    private String idCardReversePicture;
    /*@TableField("isAudit")
@@ -87,20 +87,26 @@
    @TableField("status")
    @TableLogic
    @ApiModelProperty(value = "状态")
    @ApiModelProperty(value = "【废弃】状态")
    private Boolean status;
    @TableField("createTime")
    @ApiModelProperty(value = "创建时间")
    private DateTime createTime;
    @ApiModelProperty(value = "验证码")
    @ApiModelProperty(value = "【废弃】验证码")
    private String code;
    @ApiModelProperty(value = "身份证正面id")
    @ApiModelProperty(value = "【废弃】身份证正面id")
    private String copy1;
    @ApiModelProperty(value = "身份证反面id")
    @ApiModelProperty(value = "【废弃】身份证反面id")
    private String copy2;
    @ApiModelProperty(value = "银行所在省编码")
    private String bankCardProvinceCode;
    @ApiModelProperty(value = "银行所在市编码")
    private String bankCardCityCode;
}
DriverJYXTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/api/RegionController.java
New file
@@ -0,0 +1,68 @@
package com.stylefeng.guns.modular.api;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.stylefeng.guns.core.base.controller.BaseController;
import com.stylefeng.guns.modular.system.model.Region;
import com.stylefeng.guns.modular.system.service.INoticeService;
import com.stylefeng.guns.modular.system.service.IRegionService;
import com.stylefeng.guns.modular.system.util.ResultUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
/**
 * 总览信息
 *
 * @author fengshuonan
 * @Date 2017年3月4日23:05:54
 */
@Api(tags = "区域管理")
@RestController
@RequestMapping("/region")
public class RegionController extends BaseController {
    @Autowired
    private IRegionService regionService;
    /**
     * 获取省份列表
     */
    @ApiOperation("获取省份列表")
    @GetMapping("/province")
    public ResultUtil<List<Region>> blackboard() {
        List<Region> provinceList = regionService.selectList(new EntityWrapper<Region>().eq("parent_id", 0));
        return ResultUtil.success(provinceList);
    }
    /**
     * 根据区域编码获取下级列表
     * @param code
     * @return
     */
    @ApiOperation("根据区域编码获取下级列表")
    @GetMapping(value = "/change")
    @ApiImplicitParam(name = "code", value = "区域编码", required = true, dataType = "String", paramType = "query")
    public ResultUtil<List<Region>> change(@RequestParam String code) {
        List<Region> list = new ArrayList<>();
        if (StringUtils.isNotBlank(code)){
            Region region = regionService.selectOne(new EntityWrapper<Region>().eq("code", code));
            if (Objects.nonNull(region)) {
                list = regionService.selectList(new EntityWrapper<Region>().eq("parent_id", region.getId()));
            }
        }
        return ResultUtil.success(list);
    }
}
DriverJYXTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/model/UserWithdrawal.java
@@ -158,10 +158,10 @@
    @ApiModelProperty(value = "验证码")
    private String code;
    @ApiModelProperty(value = "开户行所在省编码")
    @ApiModelProperty(value = "银行所在省编码")
    private String bankCardProvinceCode;
    @ApiModelProperty(value = "开户行所在市编码")
    @ApiModelProperty(value = "银行所在市编码")
    private String bankCardCityCode;
    @ApiModelProperty(value = "进件类型 0-江苏银行;1-汇付")
DriverJYXTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/service/IRegionService.java
New file
@@ -0,0 +1,7 @@
package com.stylefeng.guns.modular.system.service;
import com.baomidou.mybatisplus.service.IService;
import com.stylefeng.guns.modular.system.model.Region;
public interface IRegionService extends IService<Region> {
}
DriverJYXTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/service/impl/RegionServiceImpl.java
New file
@@ -0,0 +1,11 @@
package com.stylefeng.guns.modular.system.service.impl;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.stylefeng.guns.modular.system.dao.RegionMapper;
import com.stylefeng.guns.modular.system.model.Region;
import com.stylefeng.guns.modular.system.service.IRegionService;
import org.springframework.stereotype.Service;
@Service
public class RegionServiceImpl extends ServiceImpl<RegionMapper, Region> implements IRegionService {
}
EurekaJYXTravel/target/classes/application.yml
New file
@@ -0,0 +1,24 @@
server:
  port: 8000  #服务端口号
spring:
  application:
    name: eureka-center #服务名称
  security:
    basic:
      enable: true #开启基于HTTP basic的认证
    user: #配置用户的账号信息
      name: sinata
      password: sinata
eureka:
  instance:
    hostname: 127.0.0.1 #注册中心地址
  client:
    service-url: #客户端调用地址
      defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
    register-with-eureka: false #是否将自己注册到Eureka服务中,因为该应用本身就是注册中心,不需要再注册自己(集群的时候为true)
    fetch-registry: false #是否从Eureka中获取注册信息,因为自己为注册中心,不会在该应用中的检索服务信息
  server:
    enable-self-preservation: false #禁用自我保护模式,服务不可用时及时从注册中心剔除
    eviction-interval-timer-in-ms: 4000
ManagementJYXTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/huifu/biz/DouGongBasicDataBiz.java
@@ -1,5 +1,6 @@
package com.stylefeng.guns.modular.huifu.biz;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.huifu.bspay.sdk.opps.core.BasePay;
import com.huifu.bspay.sdk.opps.core.config.MerConfig;
@@ -13,6 +14,7 @@
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
@@ -379,4 +381,39 @@
        log.info("企业业务入驻修改返回参数:{}", response);
        return response;
    }
    /**
     * 电子账户余额查询
     *
     * @return
     * @throws Exception
     */
    public BigDecimal balanceQuery(String huifuId) throws Exception {
        // 1. 数据初始化,填入对应的商户配置
        MerConfig merConfig = new MerConfig();
        merConfig.setProcutId(huiFuProperties.getProductId());
        merConfig.setSysId(huiFuProperties.getSysId());
        merConfig.setRsaPrivateKey(huiFuProperties.getRsaPrivateKey());
        merConfig.setRsaPublicKey(huiFuProperties.getRsaPublicKey());
        BasePay.initWithMerConfig(merConfig);
        // 2.组装请求参数
        Map<String, Object> paramsInfo = new HashMap<>();
        // 汇付ID
        paramsInfo.put("huifu_id", huifuId);
        // 请求流水号
        paramsInfo.put("req_seq_id", RequestSeqUtil.generateForHuiFu());
        // 请求日期
        paramsInfo.put("req_date", DateUtil.format(new Date(), "yyyyMMdd"));
        log.info("账户余额信息查询返回参数:{}", paramsInfo);
        // 3. 发起API调用
        Map<String, Object> response = BasePayRequest.requestBasePay("v2/trade/acctpayment/balance/query", paramsInfo, null, false);
        log.info("账户余额信息查询返回参数:{}", response);
        JSONArray accountList = JSONArray.parseArray(JSONObject.toJSONString(response.get("acctInfo_list")));
        if (accountList != null && !accountList.isEmpty()) {
            JSONObject acctInfo = accountList.getJSONObject(0);
            log.info("账户余额信息查询返回余额:{}", acctInfo.getString("avail_bal"));
            return acctInfo.getBigDecimal("avl_bal");
        }
        return BigDecimal.ZERO;
    }
}
ManagementJYXTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/huifu/biz/DouGongWithdrawBiz.java
New file
@@ -0,0 +1,170 @@
package com.stylefeng.guns.modular.huifu.biz;
import com.alibaba.fastjson.JSONObject;
import com.stylefeng.guns.modular.huifu.properties.HuiFuProperties;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;
import java.math.BigDecimal;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.Signature;
import java.security.spec.PKCS8EncodedKeySpec;
import java.text.SimpleDateFormat;
import java.util.Base64;
import java.util.Date;
/**
 * 斗拱提现业务
 * @author mitao
 * @date 2025/11/21
 */
@Slf4j
@Component
public class DouGongWithdrawBiz {
    @Autowired
    private HuiFuProperties huiFuProperties;
    @Autowired
    private RestTemplate restTemplate;
    @Value("${callbackPath}")
    private static String callbackPath;
    private static final String ENCASHMENT_URL = "https://api.huifu.com/v2/trade/settlement/encashment";
    /**
     * 请求参数
     * req_date    请求日期    String    8    Y    格式yyyyMMdd;示例值:20210917
     * req_seq_id    请求流水号    String    128    Y    示例值:2021091708126665001
     * cash_amt    取现金额    String    14    Y    单位元,需保留小数点后两位,示例值:1.00
     * huifu_id    取现方ID号    String    32    Y    提现发起方的汇付ID。支持已配置取现规则的商户、用户。
     * 示例值:6666000109812123
     * acct_id    账户号    String    32    N    可指定账户号,仅支持基本户、现金户,不填默认为基本户;
     * 示例值:F00598600
     * into_acct_date_type    到账日期类型    String    3    Y    D0:当日到账;当日交易资金当天可取现到账;
     * T1:次工作日到账;
     * D1:次自然日到账;
     * DM:当日到账;到账资金不包括当天的交易资金;
     * 示例值:D0
     * token_no    取现卡序列号    String    20    Y    绑定取现卡后可获取取现卡序列号;示例值:10004053462
     * enchashment_channel    取现渠道    String    2    N    00:汇付(为空默认); 10:中信e账通;示例值:00
     * remark    备注    String    100    N    示例值:备注
     * notify_url    异步通知地址    String    128    N    示例值:http://service.example.com/to/path
     */
    /**
     * 主动取现接口
     *
     * @param cashAmt 取现金额,单位元
     * @param huifuId 取现方ID号
     * @param tokenNo 取现卡序列号
     * @param type 提现类型 1:企业 2:用户/司机
     * @return 请求结果
     */
    public JSONObject encashment(String reqSeqId,BigDecimal cashAmt, String huifuId, String tokenNo, Integer type) {
        try {
            log.info("开始调用斗拱提现接口,取现方ID: {}, 取现金额: {}", huifuId, cashAmt);
            // 构建业务参数data
            JSONObject data = new JSONObject();
            SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd");
            String reqDate = dateFormat.format(new Date());
            data.put("req_date", reqDate);
            data.put("req_seq_id", reqSeqId);
            data.put("cash_amt", cashAmt.toString());
            data.put("huifu_id", huifuId);
            /**
             * D0:当日到账;当日交易资金当天可取现到账;
             * T1:次工作日到账;
             * D1:次自然日到账;
             * DM:当日到账;到账资金不包括当天的交易资金;
             * 示例值:D0
             */
            data.put("into_acct_date_type", "D1");
            data.put("token_no", tokenNo);
            String notifyUrl = type.equals(1) ? "/base/dougong/ent/encashment" : "/base/dougong/user/encashment";
            data.put("notify_url", callbackPath + notifyUrl);
            String dataStr = data.toJSONString();
            log.info("业务参数data: {}", dataStr);
            // 构建完整请求参数
            JSONObject requestJson = new JSONObject();
            requestJson.put("sys_id", huiFuProperties.getHuifuId()); // 使用配置中的huifuId作为sys_id
            requestJson.put("product_id", huiFuProperties.getProductId());
            requestJson.put("data", dataStr);
            // 生成签名 - 对整个报文进行签名
            String signData = requestJson.toJSONString();
            log.info("待签名报文: {}", signData);
            String signature = sign(signData, huiFuProperties.getRsaPrivateKey());
            if (signature == null) {
                log.error("签名生成失败");
                return createErrorResult("签名生成失败");
            }
            requestJson.put("sign", signature);
            // 发送HTTP请求 - POST JSON格式
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_JSON_UTF8);
            HttpEntity<String> requestEntity = new HttpEntity<>(requestJson.toJSONString(), headers);
            log.info("发送斗拱提现请求到: {}", ENCASHMENT_URL);
            ResponseEntity<String> response = restTemplate.exchange(
                ENCASHMENT_URL,
                HttpMethod.POST,
                requestEntity,
                String.class
            );
            log.info("斗拱提现接口响应状态: {}, 响应内容: {}", response.getStatusCode(), response.getBody());
            // 解析响应
            JSONObject result = JSONObject.parseObject(response.getBody());
            return result;
        } catch (Exception e) {
            log.error("调用斗拱提现接口异常: {}", e.getMessage(), e);
            return createErrorResult("调用接口异常: " + e.getMessage());
        }
    }
    /**
     * 创建错误结果
     */
    private JSONObject createErrorResult(String errorMsg) {
        JSONObject result = new JSONObject();
        result.put("resp_code", "9999");
        result.put("resp_desc", errorMsg);
        result.put("success", false);
        return result;
    }
    public static String sign(String data, String privateKeyBase64) {
        // Base64 --> Key
        try {
            byte[] bytes = Base64.getDecoder().decode(privateKeyBase64);
            PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(bytes);
            KeyFactory keyFactory;
            keyFactory = KeyFactory.getInstance("RSA");
            PrivateKey privateKey = keyFactory.generatePrivate(keySpec);
            // Sign
            Signature signature = Signature.getInstance("SHA256WithRSA");
            signature.initSign(privateKey);
            signature.update(data.getBytes("UTF-8"));
            return Base64.getEncoder().encodeToString(signature.sign());
        } catch (Exception e) {
            return null;
        }
    }
}
ManagementJYXTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/huifu/biz/FenZhangUtil.java
@@ -1,15 +1,15 @@
package com.stylefeng.guns.modular.huifu.biz;
import java.math.BigDecimal;
import java.util.*;
import com.huifu.bspay.sdk.opps.core.BasePay;
import com.huifu.bspay.sdk.opps.core.config.MerConfig;
import com.huifu.bspay.sdk.opps.core.net.BasePayRequest;
import com.huifu.bspay.sdk.opps.core.BasePay;
import com.stylefeng.guns.modular.huifu.properties.HuiFuProperties;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.HashMap;
import java.util.Map;
/**
 * 余额支付 - 示例
@@ -117,5 +117,43 @@
        return response;
    }
    public static Map<String, Object> payFromUser(String req_seq_id, String req_date, String ord_amt, String huifu_id) throws Exception {
        // 1. 数据初始化,填入对应的商户配置
        MerConfig merConfig = new MerConfig();
//        merConfig.setProcutId(huiFuProperties.getProductId());
//        merConfig.setSysId(huiFuProperties.getSysId());
//        merConfig.setRsaPrivateKey(huiFuProperties.getRsaPrivateKey());
//        merConfig.setRsaPublicKey(huiFuProperties.getRsaPublicKey());
        merConfig.setProcutId("KAZX");
        merConfig.setSysId("6666000182995771");
        merConfig.setRsaPrivateKey("MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCR6W3ynQJL7f2C8vFYMcQkcirpkif9ZhLq1374jIlV87nv0T9uIm6DoW8LyNEl9w2Yc5qoBv70tt/oVpemA6IZY6NXzE2USNi/sv2qUTtapcIRYxe4acCfY8K+x+p7W2e6wUWIpl9qgZA+UnFmHQ0HT6Ywzq2jJL92JdIs147Ud1aVi3aX8LYItj0z3ZKwZQkaJawZSWQk2+EdPfN059L2qFkPtnT7JIthAdUTJYZA13K4tzw6mXp/DbgwVmLhrlmwl/ccSv2Q0ABfEk7jIxF1nZmCmSy3HrEw9xWyrg1BC+DgXBdyF0OEtpNfv+UW080syUVBNN0irHVuDP81BaAjAgMBAAECggEAGlBZprZQErdxz6rWgYxADj6UpJjaI2XEJZwFZveZUOnqb2hyIv+MpKp5Z0upBErApey7SHAyjJlqWfE72hGvqxp/+7Z5izNz+2ZhPtT1ekyIajBPt89CkLwiA9vz2plKZLC0RIeUj5WcGNEvaDX3AomHtCehwtk+uiTp+XJKbOBtkkQszcdCGY1DVoQ0ppFoINnM9VLbEzaFaG7VS3eFkU4cf2CwcrnJB1RncyPFK+bGFvjkLM/eQbsh8YxkBqaGz/8UM1Na1SEidqdyUF71ltqnI0u8pLe0V+5jugVW+3lPL/p1C3i7mAbQOs4yqRWlFaGVTzOawoQUOPVwDpzeeQKBgQDs1P7F4wURqX1qZR0hSTqOigg48ychaOF66new3SuWk2CVBy8Q8b7odGSPyxJSGZvFLoznPYuSaXCtQ935WWfjB7Z5JpSWCi9BmJnkh41k/KvgMqAEGkZP6ul/zFnDWj94VwXEBz3TuRk574vK2coWoxjM6h1dlJjRBVVTs8dnrQKBgQCduKCjPDUuOHbcNn3VsaHEZX1XyiXN5gds08o61PjiHM42wYXxfUt59nBJmg2yAVRIrKYHfswJcxb5XUTDI5ZhCBnIPrdrQzj7FNadm/7mKDvSsvZdpfTiHY341XnvCq7OcNNj8g5fVsWF769strepQReSug7xgX7ojPvVcAZhDwKBgD57KwP2Er5IIuhQ6NCBS0uTqvurWqV70BDnjtBAaWF+XDq0/HvR63XUTzuIbbrvOqNY1p+jIxFrc+iiQQupxLimrkNkJEs5QKJjqiYahPkhmA68DG9Ip0gqR5QJy5y4UIplGwZOiscyzC72vcC0mJZETSSylzC7JV3vtEUy5ua5AoGAEwlDqjAMIyYBgpa5HV+xLKkrNbtaUL2gy8vMLsmhuHjNkuJMrlb3EyNhbiC/4moyqArehy0Qp1tSvIo7UGotLkzx/69CKBoW+IcNWDyJyXG1trqO7cKoCdqTViM98lIRwyzu9rMydONeN8o0HCT5id4nYDhAsXl1vc+2XY6F1pUCgYEA0dxGHBTKD/WzIvTYGYD6Xx224Y84mO6x2Mu16zFoq/NjuIdKi2O+92yrKDCMMCqaY77fXvWD3eI7QYYlbKAOqdLKVipTbhnBccDyNbtYHVg59t4xS+K6HyD+quVkL9n40UkxSZbKZBQhqt+vlQy0FUgONFii1ACZO0A8Sc/bvn4=");
        merConfig.setRsaPublicKey("MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsWrruP9JBxrUd8uEX5Z8y7pg/UIr5RNHSgDnHqNI1hbi2MfTzB5vZ275wSFFaLDD9BesgDWqsUepPS/opROlDCg9y6WYH8mkN23NmHL9F8kT48OMmH722am+Hp0XVMMwXqA0oNt4f7oW6kDemjZW8/RT4vIE7cyxoxSsVRvjqSpx9wDgFLPWh3o0pHQaoxLyeUsGBATHFrxEDlosBvsuXjMcgjPKXALrcemzKOhBmBkLgyxNVmh61ZK+FNXd+/X4PeZlnWf54NRQAUKe1308E6IIaszo+CjneKuhj1m/X4f7AIvxAqlhuCV5E/DfKRmGopxaWqdtE960Y/H4SmBh2wIDAQAB");
        BasePay.initWithMerConfig(merConfig);
}
        ord_amt=new BigDecimal(ord_amt).setScale(2, RoundingMode.HALF_UP).toString();
        // 2.组装请求参数
        Map<String, Object> paramsInfo = new HashMap<>();
        // 请求流水号
        paramsInfo.put("req_seq_id",req_seq_id);
        // 请求日期
        paramsInfo.put("req_date", req_date);
        // 出款方商户号
        paramsInfo.put("out_huifu_id", huifu_id);
        // 支付金额
        paramsInfo.put("ord_amt", ord_amt);
        // 分账对象
        paramsInfo.put("acct_split_bunch", "{\"acct_infos\":[{\"div_amt\":\"" + ord_amt + "\",\"huifu_id\":\"6666000182995771\"}]}");
        // 安全信息
        paramsInfo.put("risk_check_data", "{\"sub_product\":\"1\",\"transfer_type\":\"05\"}");
        // 手续费承担方标识余额支付手续费承担方标识;商户余额支付扣收规则为接口指定承担方时必填!枚举值:&lt;br/&gt;OUT:出款方;&lt;br/&gt;IN:分账接受方。&lt;br/&gt;&lt;font color&#x3D;&quot;green&quot;&gt;示例值:IN&lt;/font&gt;
        paramsInfo.put("trans_fee_take_flag", "OUT");
        // 核验值verify_type不为空时必填。当verify_type&#x3D;SMS时,填写用户收到的短信验证码
//        paramsInfo.put("verify_value", "test");
        // 3. 发起API调用
        Map<String, Object> response = BasePayRequest.requestBasePay("v2/trade/acctpayment/pay", paramsInfo, null, false);;
        return response;
    }
}
ManagementJYXTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/huifu/controller/DouGongNotifyController.java
New file
@@ -0,0 +1,106 @@
package com.stylefeng.guns.modular.huifu.controller;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.huifu.bspay.sdk.opps.core.utils.RsaUtils;
import com.stylefeng.guns.modular.huifu.properties.HuiFuProperties;
import com.stylefeng.guns.modular.system.model.TCompanyWithdraw;
import com.stylefeng.guns.modular.system.model.TEnterpriseWithdrawal;
import com.stylefeng.guns.modular.system.model.TPubWithdrawal;
import com.stylefeng.guns.modular.system.service.ITCompanyWithdrawService;
import com.stylefeng.guns.modular.system.service.ITEnterpriseWithdrawalService;
import com.stylefeng.guns.modular.system.service.ITPubWithdrawalService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Objects;
/**
 * @author mitao
 * @date 2025/11/21
 */
@Slf4j
@RestController
@RequestMapping("/base/dougong/")
public class DouGongNotifyController {
    @Autowired
    private HuiFuProperties huiFuProperties;
    @Autowired
    private ITCompanyWithdrawService companyWithdrawService;
    @Autowired
    private ITPubWithdrawalService pubWithdrawalService;
    /**
     * 斗拱主动取现接口企业回调
     * @param request
     * @param response
     */
    @PostMapping("/ent/encashment")
    public ResponseEntity<String> entEncashment(HttpServletRequest request, HttpServletResponse response) {
        String sign =request.getParameter("sign");
        String resp_data = request.getParameter("resp_data");
        log.info("斗拱企业提现响应内容:{}", resp_data);
        // 使用汇付公钥验签
        resp_data =  resp_data.replaceAll("& #40;", "(").replaceAll("& #41;",")");
        boolean verify = RsaUtils.verify(resp_data, huiFuProperties.getRsaPublicKey(), sign);
        if(verify){
            JSONObject respDataJson = JSONObject.parseObject(resp_data);
            String reqSeqId = respDataJson.getString("req_seq_id");
            String hfSeqId = respDataJson.getString("hf_seq_id");
            String transStat = respDataJson.getString("trans_stat");//S:成功 F:失败 P:处理中;示例值:S
            TCompanyWithdraw companyWithdraw = companyWithdrawService.selectOne(new EntityWrapper<TCompanyWithdraw>().eq("reqSeqId", reqSeqId).or().eq("hfSeqId", hfSeqId).last("limit 1"));
            if (Objects.isNull(companyWithdraw)) {
                return ResponseEntity.ok("");
            }
            if ("S".equalsIgnoreCase(transStat)) {
                companyWithdraw.setStatus(1);
            } else if ("F".equalsIgnoreCase(transStat)) {
                companyWithdraw.setStatus(2);
            }
            companyWithdrawService.updateById(companyWithdraw);
            log.info("更新企业提现记录成功,更新内容“{}", JSONObject.toJSON(companyWithdraw));
            return ResponseEntity.ok("RECV_ORD_ID_" + reqSeqId);
        }
        return null;
    }
    /**
     * 斗拱主动取现接口回调
     * @param request
     * @param response
     */
    @PostMapping("/user/encashment")
    public ResponseEntity<String> userEncashment(HttpServletRequest request, HttpServletResponse response) {
        String sign =request.getParameter("sign");
        String resp_data = request.getParameter("resp_data");
        log.info("斗拱企业提现响应内容:{}", resp_data);
        // 使用汇付公钥验签
        resp_data =  resp_data.replaceAll("& #40;", "(").replaceAll("& #41;",")");
        boolean verify = RsaUtils.verify(resp_data, huiFuProperties.getRsaPublicKey(), sign);
        if(verify){
            JSONObject respDataJson = JSONObject.parseObject(resp_data);
            String reqSeqId = respDataJson.getString("req_seq_id");
            String hfSeqId = respDataJson.getString("hf_seq_id");
            String transStat = respDataJson.getString("trans_stat");//S:成功 F:失败 P:处理中;示例值:S
            TPubWithdrawal pubWithdrawal = pubWithdrawalService.selectOne(new EntityWrapper<TPubWithdrawal>().eq("reqSeqId", reqSeqId).or().eq("hfSeqId", hfSeqId).last("limit 1"));
            if (Objects.isNull(pubWithdrawal)) {
                return ResponseEntity.ok("");
            }
            if ("S".equalsIgnoreCase(transStat)) {
                pubWithdrawal.setState(2);
            } else if ("F".equalsIgnoreCase(transStat)) {
                pubWithdrawal.setState(3);
            }
            pubWithdrawalService.updateById(pubWithdrawal);
            log.info("更新用户/司机提现记录成功,更新内容“{}", JSONObject.toJSON(pubWithdrawal));
            return ResponseEntity.ok("RECV_ORD_ID_" + reqSeqId);
        }
        return null;
    }
}
ManagementJYXTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/controller/general/TCompanyWithdrawController.java
@@ -1,22 +1,23 @@
package com.stylefeng.guns.modular.system.controller.general;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.stylefeng.guns.core.base.controller.BaseController;
import com.stylefeng.guns.core.base.tips.ErrorTip;
import com.stylefeng.guns.core.shiro.ShiroKit;
import com.stylefeng.guns.core.util.RequestSeqUtil;
import com.stylefeng.guns.core.util.ToolUtil;
import com.stylefeng.guns.modular.cloudPayment.example.BalanceAcctExample;
import com.stylefeng.guns.modular.cloudPayment.example.WithdrawalExample;
import com.stylefeng.guns.modular.cloudPayment.req.BalanceAcctReq;
import com.stylefeng.guns.modular.cloudPayment.req.WithdrawalReq;
import com.stylefeng.guns.modular.huifu.biz.DouGongBasicDataBiz;
import com.stylefeng.guns.modular.huifu.biz.DouGongWithdrawBiz;
import com.stylefeng.guns.modular.system.controller.util.Base64Util;
import com.stylefeng.guns.modular.system.model.TEnterpriseWithdrawal;
import com.stylefeng.guns.modular.system.model.User;
import com.stylefeng.guns.modular.system.service.ITEnterpriseWithdrawalService;
import com.stylefeng.guns.modular.system.service.IUserService;
import com.unionpay.upyzt.exception.UpyztException;
import com.unionpay.upyzt.resp.BalanceAcctListResp;
import com.unionpay.upyzt.resp.BalanceAcctResp;
import com.unionpay.upyzt.resp.WithdrawalResp;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
@@ -41,6 +42,7 @@
 * @author fengshuonan
 * @Date 2023-03-17 14:18:09
 */
@Slf4j
@Controller
@RequestMapping("/tCompanyWithdraw")
public class TCompanyWithdrawController extends BaseController {
@@ -53,6 +55,12 @@
    @Resource
    private ITEnterpriseWithdrawalService enterpriseWithdrawalService;
    @Autowired
    private DouGongBasicDataBiz douGongBasicDataBiz;
    @Autowired
    private DouGongWithdrawBiz douGongWithdrawBiz;
    /**
     * 跳转到首页
     */
@@ -62,14 +70,15 @@
        List<TEnterpriseWithdrawal> companyId = enterpriseWithdrawalService.selectList(new EntityWrapper<TEnterpriseWithdrawal>().eq("companyId", id));
        if(companyId.size()>0){
            try {
                BalanceAcctReq balanceAcctReq = new BalanceAcctReq();
                balanceAcctReq.setMchId(companyId.get(0).getMchId());
                BalanceAcctListResp balanceAcctListResp = BalanceAcctExample.retrieveByUserId(balanceAcctReq);
                Long settledAmount = balanceAcctListResp.getBalanceAccts().get(0).getSettledAmount();
                String money = settledAmount.toString();
                model.addAttribute("money",new BigDecimal(money).divide(new BigDecimal(100)).toString());
            } catch (UpyztException e) {
                e.printStackTrace();
                //BalanceAcctReq balanceAcctReq = new BalanceAcctReq();
                //balanceAcctReq.setMchId(companyId.get(0).getMchId());
                //BalanceAcctListResp balanceAcctListResp = BalanceAcctExample.retrieveByUserId(balanceAcctReq);
                //Long settledAmount = balanceAcctListResp.getBalanceAccts().get(0).getSettledAmount();
                //String money = settledAmount.toString();
                BigDecimal money = douGongBasicDataBiz.balanceQuery(companyId.get(0).getHuifuId());
                model.addAttribute("money",money.divide(new BigDecimal(100)).toString());
            } catch (Exception e) {
                log.error("查询企业用户汇付余额异常", e);
                model.addAttribute("money",0);
            }
@@ -137,14 +146,15 @@
        List<TEnterpriseWithdrawal> companyId = enterpriseWithdrawalService.selectList(new EntityWrapper<TEnterpriseWithdrawal>().eq("companyId", ShiroKit.getUser().getObjectId()));
        if(companyId.size()>0){
            try {
                BalanceAcctReq balanceAcctReq = new BalanceAcctReq();
                balanceAcctReq.setMchId(companyId.get(0).getMchId());
                BalanceAcctListResp balanceAcctListResp = BalanceAcctExample.retrieveByUserId(balanceAcctReq);
                Long settledAmount = balanceAcctListResp.getBalanceAccts().get(0).getSettledAmount();
                if(settledAmount<money){
                //BalanceAcctReq balanceAcctReq = new BalanceAcctReq();
                //balanceAcctReq.setMchId(companyId.get(0).getMchId());
                //BalanceAcctListResp balanceAcctListResp = BalanceAcctExample.retrieveByUserId(balanceAcctReq);
                //Long settledAmount = balanceAcctListResp.getBalanceAccts().get(0).getSettledAmount();
                BigDecimal settledAmount = douGongBasicDataBiz.balanceQuery(companyId.get(0).getHuifuId());
                if(settledAmount.compareTo(BigDecimal.valueOf(money))<0){
                    return "5001";
                }
            } catch (UpyztException e) {
            } catch (Exception e) {
                e.printStackTrace();
            }
@@ -173,14 +183,23 @@
                withdrawalReq.setPassword(Base64Util.decode(enterpriseWithdrawal.getTransactionAuthorizationCode()));
            }
            WithdrawalResp withdrawalResp = WithdrawalExample.create(withdrawalReq);
            String reqSeqId = RequestSeqUtil.extractPrefix("TX");
            JSONObject result = douGongWithdrawBiz.encashment(reqSeqId, BigDecimal.valueOf(withdrawalReq.getAmount()), companyId.get(0).getHuifuId(), companyId.get(0).getTokenNo(), 1);
            if (!result.get("resp_code").equals("00000000") || !result.getBoolean("success")) {
                return new ErrorTip(500, "操作失败,异常原因:"+result.get("resp_desc"));
            }
            tCompanyWithdraw.setReqSeqId(reqSeqId);
            String hfSeqId = (String) result.get("hf_seq_id");
            tCompanyWithdraw.setHfSeqId(hfSeqId);
            System.out.println("公司添加提现:"+withdrawalResp);
            tCompanyWithdraw.setWithdrawId(withdrawalResp.getWithdrawalId());
            //WithdrawalResp withdrawalResp = WithdrawalExample.create(withdrawalReq);
        } catch (UpyztException e) {
            e.printStackTrace();
            System.out.println("公司添加提现失败:"+e.getIssue());
            //System.out.println("公司添加提现:"+withdrawalResp);
            //tCompanyWithdraw.setWithdrawId(withdrawalResp.getWithdrawalId());
        } catch (Exception e) {
            log.error("公司添加提现异常", e);
            return new ErrorTip(500, "公司添加提现异常");
        }
        tCompanyWithdrawService.insert(tCompanyWithdraw);
        return SUCCESS_TIP;
ManagementJYXTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/controller/general/TEnterpriseWithdrawalController.java
@@ -333,7 +333,7 @@
    }
    @RequestMapping(value = "/change")
    @ResponseBody
    public Object change(@RequestParam Integer code) {
    public Object change(@RequestParam String code) {
        List<TRegion> list = new ArrayList<>();
        if (SinataUtil.isNotEmpty(code)){
            TRegion region = tRegionService.selectOne(new EntityWrapper<TRegion>().eq("code", code));
ManagementJYXTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/controller/general/TPubWithdrawalController.java
@@ -1,14 +1,18 @@
package com.stylefeng.guns.modular.system.controller.general;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.plugins.Page;
import com.stylefeng.guns.core.base.controller.BaseController;
import com.stylefeng.guns.core.base.tips.ErrorTip;
import com.stylefeng.guns.core.common.constant.factory.PageFactory;
import com.stylefeng.guns.core.shiro.ShiroKit;
import com.stylefeng.guns.core.util.RequestSeqUtil;
import com.stylefeng.guns.core.util.SinataUtil;
import com.stylefeng.guns.modular.cloudPayment.example.AllocationExample;
import com.stylefeng.guns.modular.cloudPayment.example.WithdrawalExample;
import com.stylefeng.guns.modular.cloudPayment.req.WithdrawalReq;
import com.stylefeng.guns.modular.huifu.biz.DouGongWithdrawBiz;
import com.stylefeng.guns.modular.system.model.*;
import com.stylefeng.guns.modular.system.service.*;
import com.stylefeng.guns.modular.system.util.HttpRequestUtil;
@@ -51,6 +55,8 @@
    private ITSystemNoticeService tSystemNoticeService;
    @Resource
    private IUserWithdrawalService userWithdrawalService;
    @Autowired
    private DouGongWithdrawBiz douGongWithdrawBiz;
    /**
     * 跳转到提现列表首页
@@ -134,7 +140,7 @@
     */
    @RequestMapping(value = "/immediately")
    @ResponseBody
    @Transactional(rollbackFor = UpyztException.class,propagation = Propagation.REQUIRES_NEW)
    @Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRES_NEW)
    public synchronized Object immediately(@RequestParam Integer id,@RequestParam Integer state,@RequestParam String remark) {
        TPubWithdrawal tPubWithdrawal = tPubWithdrawalService.selectById(id);
        if(tPubWithdrawal.getState()!=1){
@@ -176,12 +182,22 @@
                        System.out.println("用户:"+userWithdrawals.get(0));
                        try {
                            log.info("用户提现创建=========");
                            WithdrawalResp withdrawalResp = WithdrawalExample.create(userWithdrawalService.createInfo(userWithdrawals.get(0), tPubWithdrawal));
                            tPubWithdrawal.setWithdrawId(withdrawalResp.getWithdrawalId());
                            String reqSeqId = RequestSeqUtil.generate("TX");
                            JSONObject result = douGongWithdrawBiz.encashment(reqSeqId, tPubWithdrawal.getMoney(), userWithdrawals.get(0).getHuiFuId(), userWithdrawals.get(0).getTokenNo(), 2);
                            if (!result.get("resp_code").equals("00000000") || !result.getBoolean("success")) {
                                return new ErrorTip(500, "操作失败,异常原因:"+result.get("resp_desc"));
                            }
                            String hfSeqId = (String) result.get("hf_seq_id");
                            tPubWithdrawal.setReqSeqId(reqSeqId);
                            tPubWithdrawal.setHfSeqId(hfSeqId);
                            //WithdrawalResp withdrawalResp = WithdrawalExample.create(userWithdrawalService.createInfo(userWithdrawals.get(0), tPubWithdrawal));
                            //tPubWithdrawal.setWithdrawId(withdrawalResp.getWithdrawalId());
                            tPubWithdrawalService.updateById(tPubWithdrawal);
                            log.info("用户提现创建信息========="+withdrawalResp.toString());
                            //log.info("用户提现创建信息========="+withdrawalResp.toString());
                            log.info("用户提现创建信息:{}", result.toJSONString());
                            log.info("用户提现创建成功=========");
                        } catch (UpyztException e) {
                        } catch (Exception e) {
                            log.info("用户提现创建失败=========");
                            e.printStackTrace();
                            if(userType==1){
@@ -219,12 +235,22 @@
                    }
                    try {
                        log.info("司机提现创建=========");
                        WithdrawalResp withdrawalResp = WithdrawalExample.create(userWithdrawalService.createInfo(userWithdrawal, tPubWithdrawal));
                        tPubWithdrawal.setWithdrawId(withdrawalResp.getWithdrawalId());
                        String reqSeqId = RequestSeqUtil.generate("TX");
                        JSONObject result = douGongWithdrawBiz.encashment(reqSeqId, tPubWithdrawal.getMoney(), userWithdrawal.getHuiFuId(), userWithdrawal.getTokenNo(), 2);
                        if (!result.get("resp_code").equals("00000000") || !result.getBoolean("success")) {
                            return new ErrorTip(500, "操作失败,异常原因:"+result.get("resp_desc"));
                        }
                        String hfSeqId = (String) result.get("hf_seq_id");
                        tPubWithdrawal.setReqSeqId(reqSeqId);
                        tPubWithdrawal.setHfSeqId(hfSeqId);
                        //WithdrawalResp withdrawalResp = WithdrawalExample.create(userWithdrawalService.createInfo(userWithdrawal, tPubWithdrawal));
                        //tPubWithdrawal.setWithdrawId(withdrawalResp.getWithdrawalId());
                        tPubWithdrawalService.updateById(tPubWithdrawal);
                        log.info("司机提现创建信息========="+withdrawalResp.toString());
                        //log.info("司机提现创建信息========="+withdrawalResp.toString());
                        log.info("司机提现创建信息:{}", result.toJSONString());
                        log.info("司机提现创建成功=========");
                    } catch (UpyztException e) {
                    } catch (Exception e) {
                        log.info("司机提现创建失败=========");
                        e.printStackTrace();
                        if(userType==1){
ManagementJYXTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/controller/specialTrain/TOrderLogisticsController.java
@@ -2,14 +2,18 @@
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.plugins.Page;
import com.mysql.cj.log.Log;
import com.stylefeng.guns.core.base.controller.BaseController;
import com.stylefeng.guns.core.common.constant.factory.PageFactory;
import com.stylefeng.guns.core.shiro.ShiroKit;
import com.stylefeng.guns.core.shiro.ShiroUser;
import com.stylefeng.guns.core.util.DateUtil;
import com.stylefeng.guns.core.util.RequestSeqUtil;
import com.stylefeng.guns.core.util.SinataUtil;
import com.stylefeng.guns.core.util.ToolUtil;
import com.stylefeng.guns.modular.cloudPayment.example.AllocationExample;
import com.stylefeng.guns.modular.cloudPayment.req.AllocationReq;
import com.stylefeng.guns.modular.huifu.biz.FenZhangUtil;
import com.stylefeng.guns.modular.system.controller.util.Base64Util;
import com.stylefeng.guns.modular.system.dao.OrderCancelMapper;
import com.stylefeng.guns.modular.system.model.*;
@@ -17,6 +21,7 @@
import com.stylefeng.guns.modular.system.util.*;
import com.unionpay.upyzt.exception.UpyztException;
import com.unionpay.upyzt.resp.AllocationResp;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
@@ -39,6 +44,7 @@
 * @author fengshuonan
 * @Date 2020-09-24 14:20:41
 */
@Slf4j
@Controller
@RequestMapping("/tOrderLogistics")
public class TOrderLogisticsController extends BaseController {
@@ -304,7 +310,7 @@
        }
    }
    public String createAllocationReqUser(Integer companyId,Integer userId,int type,double money){
    public String createAllocationReqUser(Integer companyId,Integer userId,int type,double money) throws Exception {
        List<TEnterpriseWithdrawal> tEnterpriseWithdrawals = tEnterpriseWithdrawalService.selectList(new EntityWrapper<TEnterpriseWithdrawal>().eq("companyId", companyId));
        TUser tUser = userService.selectById(userId);
        List<UserWithdrawal> userWithdrawals = userWithdrawalService.selectList(new EntityWrapper<UserWithdrawal>().eq("phone", tUser.getPhone()));
@@ -313,32 +319,39 @@
        }
        AllocationReq allocationReq= new AllocationReq();
        allocationReq.setOutOrderNo(ToolUtil.getRandomString(32));
        Map<String, Object> result;
        if(type==1){
            allocationReq.setPayBalanceAcctId(tEnterpriseWithdrawals.get(0).getBalanceAcctId());
            allocationReq.setRecvBalanceAcctId(userWithdrawals.get(0).getBalanceAcctId());
            allocationReq.setPassword(Base64Util.decode(tEnterpriseWithdrawals.get(0).getTransactionAuthorizationCode()));
            //allocationReq.setPayBalanceAcctId(tEnterpriseWithdrawals.get(0).getBalanceAcctId());
            //allocationReq.setRecvBalanceAcctId(userWithdrawals.get(0).getBalanceAcctId());
            //
            //allocationReq.setPassword(Base64Util.decode(tEnterpriseWithdrawals.get(0).getTransactionAuthorizationCode()));
            result = FenZhangUtil.fenzhang(RequestSeqUtil.generate("TK"), DateUtil.formatDate(new Date(), "yyyyMMdd"), String.valueOf(money), userWithdrawals.get(0).getHuiFuId());
        }else {
            allocationReq.setRecvBalanceAcctId(tEnterpriseWithdrawals.get(0).getBalanceAcctId());
            allocationReq.setPayBalanceAcctId(userWithdrawals.get(0).getBalanceAcctId());
            allocationReq.setPassword(Base64Util.decode(userWithdrawals.get(0).getTransactionAuthorizationCode()));
            //allocationReq.setRecvBalanceAcctId(tEnterpriseWithdrawals.get(0).getBalanceAcctId());
            //allocationReq.setPayBalanceAcctId(userWithdrawals.get(0).getBalanceAcctId());
            //allocationReq.setPassword(Base64Util.decode(userWithdrawals.get(0).getTransactionAuthorizationCode()));
            result = FenZhangUtil.payFromUser(RequestSeqUtil.generate("TK"), DateUtil.formatDate(new Date(), "yyyyMMdd"), String.valueOf(money), userWithdrawals.get(0).getHuiFuId());
        }
        money=money*100;
        allocationReq.setAmount((int)money);
        allocationReq.setProductName("分账");
        allocationReq.setProductCount(1);
        allocationReq.setOrderNo(ToolUtil.getRandomString(32));
        allocationReq.setOrderAmount(1l);
        try {
            AllocationResp allocationResp = AllocationExample.create(allocationReq);
            System.out.println(allocationResp);
        if ("00000000".equals(result.get("respCode").toString())) {
            return "ok";
        } catch (UpyztException e) {
            e.printStackTrace();
            return e.getMessage();
        } else {
            return result.get("respDesc").toString();
        }
        //money=money*100;
        //allocationReq.setAmount((int)money);
        //allocationReq.setProductName("分账");
        //allocationReq.setProductCount(1);
        //allocationReq.setOrderNo(ToolUtil.getRandomString(32));
        //allocationReq.setOrderAmount(1l);
        //try {
        //    AllocationResp allocationResp = AllocationExample.create(allocationReq);
        //    System.out.println(allocationResp);
        //    return "ok";
        //} catch (UpyztException e) {
        //    e.printStackTrace();
        //    return e.getMessage();
        //}
    }
    /**
ManagementJYXTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/model/TCompanyWithdraw.java
@@ -58,7 +58,31 @@
    private String createUserName;
    private String withdrawId;
    /**
     * 请求流水号
     */
    private String reqSeqId;
    /**
     * 汇付全局流水号
     */
    private String hfSeqId;
    public String getReqSeqId() {
        return reqSeqId;
    }
    public void setReqSeqId(String reqSeqId) {
        this.reqSeqId = reqSeqId;
    }
    public String getHfSeqId() {
        return hfSeqId;
    }
    public void setHfSeqId(String hfSeqId) {
        this.hfSeqId = hfSeqId;
    }
    public String getWithdrawId() {
        return withdrawId;
ManagementJYXTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/model/TPubWithdrawal.java
@@ -86,6 +86,32 @@
    @TableField("success_time")
    private Date successTime;
    /**
     * 请求流水号
     */
    private String reqSeqId;
    /**
     * 汇付全局流水号
     */
    private String hfSeqId;
    public String getReqSeqId() {
        return reqSeqId;
    }
    public void setReqSeqId(String reqSeqId) {
        this.reqSeqId = reqSeqId;
    }
    public String getHfSeqId() {
        return hfSeqId;
    }
    public void setHfSeqId(String hfSeqId) {
        this.hfSeqId = hfSeqId;
    }
    public Date getSuccessTime() {
        return successTime;
    }
UserJYXTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/account/req/UserWithdrawalReq.java
@@ -40,7 +40,7 @@
    private String certificateExpireTime;
    @TableField("licenceIssuingAuthority")
    @ApiModelProperty(value = "发证机关")
    @ApiModelProperty(value = "【废弃】发证机关")
    private String licenceIssuingAuthority;
    @TableField("bankName")
@@ -64,7 +64,7 @@
    private String openAccountName;
    @TableField("transactionAuthorizationCode")
    @ApiModelProperty(value = "交易授权码")
    @ApiModelProperty(value = "【废弃】交易授权码")
    private String transactionAuthorizationCode;
    @TableField("phone")
@@ -72,11 +72,11 @@
    private String phone;
    @TableField("idCardFrontPicture")
    @ApiModelProperty(value = "法人身份证照片正面")
    @ApiModelProperty(value = "【废弃】法人身份证照片正面")
    private String idCardFrontPicture;
    @TableField("idCardReversePicture")
    @ApiModelProperty(value = "法人身份证照片反面")
    @ApiModelProperty(value = "【废弃】法人身份证照片反面")
    private String idCardReversePicture;
    /*@TableField("isAudit")
@@ -89,26 +89,26 @@
    @TableField("status")
    @TableLogic
    @ApiModelProperty(value = "状态")
    @ApiModelProperty(value = "【废弃】状态")
    private Boolean status;
    @TableField("createTime")
    @ApiModelProperty(value = "创建时间")
    private DateTime createTime;
    @ApiModelProperty(value = "验证码")
    @ApiModelProperty(value = "【废弃】验证码")
    private String code;
    @ApiModelProperty(value = "身份证正面id")
    @ApiModelProperty(value = "【废弃】身份证正面id")
    private String copy1;
    @ApiModelProperty(value = "身份证反面id")
    @ApiModelProperty(value = "【废弃】身份证反面id")
    private String copy2;
    @ApiModelProperty(value = "开户行所在省编码")
    @ApiModelProperty(value = "银行所在省编码")
    private String bankCardProvinceCode;
    @ApiModelProperty(value = "开户行所在市编码")
    @ApiModelProperty(value = "银行所在市编码")
    private String bankCardCityCode;
}
UserJYXTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/api/RegionController.java
New file
@@ -0,0 +1,69 @@
package com.stylefeng.guns.modular.api;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.stylefeng.guns.core.base.controller.BaseController;
import com.stylefeng.guns.modular.system.model.Region;
import com.stylefeng.guns.modular.system.service.INoticeService;
import com.stylefeng.guns.modular.system.service.IRegionService;
import com.stylefeng.guns.modular.system.util.ResultUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
/**
 * 总览信息
 *
 * @author fengshuonan
 * @Date 2017年3月4日23:05:54
 */
@Api(tags = "用户端-区域管理")
@RestController
@RequestMapping("/region")
public class RegionController extends BaseController {
    @Autowired
    private IRegionService regionService;
    /**
     * 获取省份列表
     */
    @ApiOperation("获取省份列表")
    @GetMapping("/province")
    public ResultUtil<List<Region>> blackboard() {
        List<Region> provinceList = regionService.selectList(new EntityWrapper<Region>().eq("parent_id", 0));
        return ResultUtil.success(provinceList);
    }
    /**
     * 根据区域编码获取下级列表
     * @param code
     * @return
     */
    @ApiOperation("根据区域编码获取下级列表")
    @GetMapping(value = "/change")
    @ApiImplicitParam(name = "code", value = "区域编码", required = true, dataType = "String", paramType = "query")
    public ResultUtil<List<Region>> change(@RequestParam String code) {
        List<Region> list = new ArrayList<>();
        if (StringUtils.isNotBlank(code)){
            Region region = regionService.selectOne(new EntityWrapper<Region>().eq("code", code));
            if (Objects.nonNull(region)) {
                list = regionService.selectList(new EntityWrapper<Region>().eq("parent_id", region.getId()));
            }
        }
        return ResultUtil.success(list);
    }
}
UserJYXTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/huifu/DouGongNotifyController.java
New file
@@ -0,0 +1,43 @@
package com.stylefeng.guns.modular.huifu;
import com.alibaba.fastjson.JSONObject;
import com.huifu.bspay.sdk.opps.core.utils.RsaUtils;
import com.stylefeng.guns.modular.huifu.properties.HuiFuProperties;
import lombok.extern.slf4j.Slf4j;
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.RestController;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
 * @author mitao
 * @date 2025/11/21
 */
@Slf4j
@RestController
@RequestMapping("/base/dougong/")
public class DouGongNotifyController {
    @Autowired
    private HuiFuProperties huiFuProperties;
    /**
     * 斗拱主动取现接口回调
     * @param request
     * @param response
     */
    @PostMapping("/encashment")
    public void encashment(HttpServletRequest request, HttpServletResponse response) {
        String sign =request.getParameter("sign");
        String resp_data = request.getParameter("resp_data");
        log.info("");
        resp_data =  resp_data.replaceAll("& #40;", "(").replaceAll("& #41;",")");
        boolean verify = RsaUtils.verify(resp_data, huiFuProperties.getRsaPublicKey(), sign);
        if(verify){
            JSONObject respDataJson = JSONObject.parseObject(resp_data);
        }
    }
}
UserJYXTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/huifu/biz/DouGongWithdrawBiz.java
New file
@@ -0,0 +1,168 @@
package com.stylefeng.guns.modular.huifu.biz;
import com.alibaba.fastjson.JSONObject;
import com.stylefeng.guns.core.util.RequestSeqUtil;
import com.stylefeng.guns.modular.huifu.properties.HuiFuProperties;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.*;
import org.springframework.stereotype.Component;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;
import java.math.BigDecimal;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.Signature;
import java.security.spec.PKCS8EncodedKeySpec;
import java.text.SimpleDateFormat;
import java.util.Base64;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
/**
 * 斗拱提现业务
 * @author mitao
 * @date 2025/11/21
 */
@Slf4j
@Component
public class DouGongWithdrawBiz {
    @Autowired
    private HuiFuProperties huiFuProperties;
    @Autowired
    private RestTemplate restTemplate;
    @Value("${callbackPath}")
    private static String callbackPath;
    private static final String ENCASHMENT_URL = "https://api.huifu.com/v2/trade/settlement/encashment";
    /**
     * 请求参数
     * req_date    请求日期    String    8    Y    格式yyyyMMdd;示例值:20210917
     * req_seq_id    请求流水号    String    128    Y    示例值:2021091708126665001
     * cash_amt    取现金额    String    14    Y    单位元,需保留小数点后两位,示例值:1.00
     * huifu_id    取现方ID号    String    32    Y    提现发起方的汇付ID。支持已配置取现规则的商户、用户。
     * 示例值:6666000109812123
     * acct_id    账户号    String    32    N    可指定账户号,仅支持基本户、现金户,不填默认为基本户;
     * 示例值:F00598600
     * into_acct_date_type    到账日期类型    String    3    Y    D0:当日到账;当日交易资金当天可取现到账;
     * T1:次工作日到账;
     * D1:次自然日到账;
     * DM:当日到账;到账资金不包括当天的交易资金;
     * 示例值:D0
     * token_no    取现卡序列号    String    20    Y    绑定取现卡后可获取取现卡序列号;示例值:10004053462
     * enchashment_channel    取现渠道    String    2    N    00:汇付(为空默认); 10:中信e账通;示例值:00
     * remark    备注    String    100    N    示例值:备注
     * notify_url    异步通知地址    String    128    N    示例值:http://service.example.com/to/path
     */
    /**
     * 主动取现接口
     * @param cashAmt 取现金额,单位元
     * @param huifuId 取现方ID号
     * @param tokenNo 取现卡序列号
     * @return 请求结果
     */
    public JSONObject encashment(BigDecimal cashAmt, String huifuId, String tokenNo) {
        try {
            log.info("开始调用斗拱提现接口,取现方ID: {}, 取现金额: {}", huifuId, cashAmt);
            // 构建业务参数data
            JSONObject data = new JSONObject();
            SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd");
            String reqDate = dateFormat.format(new Date());
            data.put("req_date", reqDate);
            data.put("req_seq_id", RequestSeqUtil.extractPrefix("TX"));
            data.put("cash_amt", cashAmt.toString());
            data.put("huifu_id", huifuId);
            /**
             * D0:当日到账;当日交易资金当天可取现到账;
             * T1:次工作日到账;
             * D1:次自然日到账;
             * DM:当日到账;到账资金不包括当天的交易资金;
             * 示例值:D0
             */
            data.put("into_acct_date_type", "D1");
            data.put("token_no", tokenNo);
            data.put("notify_url", callbackPath + "/base/huifu/encashment");
            String dataStr = data.toJSONString();
            log.info("业务参数data: {}", dataStr);
            // 构建完整请求参数
            JSONObject requestJson = new JSONObject();
            requestJson.put("sys_id", huiFuProperties.getHuifuId()); // 使用配置中的huifuId作为sys_id
            requestJson.put("product_id", huiFuProperties.getProductId());
            requestJson.put("data", dataStr);
            // 生成签名 - 对整个报文进行签名
            String signData = requestJson.toJSONString();
            log.info("待签名报文: {}", signData);
            String signature = sign(signData, huiFuProperties.getRsaPrivateKey());
            if (signature == null) {
                log.error("签名生成失败");
                return createErrorResult("签名生成失败");
            }
            requestJson.put("sign", signature);
            // 发送HTTP请求 - POST JSON格式
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_JSON_UTF8);
            HttpEntity<String> requestEntity = new HttpEntity<>(requestJson.toJSONString(), headers);
            log.info("发送斗拱提现请求到: {}", ENCASHMENT_URL);
            ResponseEntity<String> response = restTemplate.exchange(
                ENCASHMENT_URL,
                HttpMethod.POST,
                requestEntity,
                String.class
            );
            log.info("斗拱提现接口响应状态: {}, 响应内容: {}", response.getStatusCode(), response.getBody());
            // 解析响应
            JSONObject result = JSONObject.parseObject(response.getBody());
            return result;
        } catch (Exception e) {
            log.error("调用斗拱提现接口异常: {}", e.getMessage(), e);
            return createErrorResult("调用接口异常: " + e.getMessage());
        }
    }
    /**
     * 创建错误结果
     */
    private JSONObject createErrorResult(String errorMsg) {
        JSONObject result = new JSONObject();
        result.put("code", "9999");
        result.put("msg", errorMsg);
        result.put("success", false);
        return result;
    }
    public static String sign(String data, String privateKeyBase64) {
        // Base64 --> Key
        try {
            byte[] bytes = Base64.getDecoder().decode(privateKeyBase64);
            PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(bytes);
            KeyFactory keyFactory;
            keyFactory = KeyFactory.getInstance("RSA");
            PrivateKey privateKey = keyFactory.generatePrivate(keySpec);
            // Sign
            Signature signature = Signature.getInstance("SHA256WithRSA");
            signature.initSign(privateKey);
            signature.update(data.getBytes("UTF-8"));
            return Base64.getEncoder().encodeToString(signature.sign());
        } catch (Exception e) {
            return null;
        }
    }
}
UserJYXTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/controller/BlackboardController.java
@@ -2,6 +2,7 @@
import com.stylefeng.guns.core.base.controller.BaseController;
import com.stylefeng.guns.modular.system.service.INoticeService;
import com.stylefeng.guns.modular.system.service.IRegionService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;