Merge branch 'master' of http://120.76.84.145:10101/gitblit/r/java/JiaYiXing2025
| | |
| | | <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> |
| | |
| | | private String certificateExpireTime; |
| | | |
| | | @TableField("licenceIssuingAuthority") |
| | | @ApiModelProperty(value = "发证机关") |
| | | @ApiModelProperty(value = "【废弃】发证机关") |
| | | private String licenceIssuingAuthority; |
| | | |
| | | @TableField("bankName") |
| | |
| | | private String bankCardCode; |
| | | |
| | | @TableField("bankCode") |
| | | @ApiModelProperty(value = "开户银行编码") |
| | | @ApiModelProperty(value = "【废弃】开户银行编码") |
| | | private String bankCode; |
| | | |
| | | @TableField("bankBranchCode") |
| | | @ApiModelProperty(value = "开户银行联行号") |
| | | @ApiModelProperty(value = "【废弃】开户银行联行号") |
| | | private String bankBranchCode; |
| | | |
| | | @TableField("openAccountName") |
| | |
| | | private String openAccountName; |
| | | |
| | | @TableField("transactionAuthorizationCode") |
| | | @ApiModelProperty(value = "交易授权码") |
| | | @ApiModelProperty(value = "【废弃】交易授权码") |
| | | private String transactionAuthorizationCode; |
| | | |
| | | @TableField("phone") |
| | |
| | | private String phone; |
| | | |
| | | @TableField("idCardFrontPicture") |
| | | @ApiModelProperty(value = "法人身份证照片正面") |
| | | @ApiModelProperty(value = "【废弃】法人身份证照片正面") |
| | | private String idCardFrontPicture; |
| | | |
| | | @TableField("idCardReversePicture") |
| | | @ApiModelProperty(value = "法人身份证照片反面") |
| | | @ApiModelProperty(value = "【废弃】法人身份证照片反面") |
| | | private String idCardReversePicture; |
| | | |
| | | /*@TableField("isAudit") |
| | |
| | | |
| | | @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; |
| | | |
| | | } |
| New file |
| | |
| | | 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); |
| | | } |
| | | } |
| | |
| | | @ApiModelProperty(value = "验证码") |
| | | private String code; |
| | | |
| | | @ApiModelProperty(value = "开户行所在省编码") |
| | | @ApiModelProperty(value = "银行所在省编码") |
| | | private String bankCardProvinceCode; |
| | | |
| | | @ApiModelProperty(value = "开户行所在市编码") |
| | | @ApiModelProperty(value = "银行所在市编码") |
| | | private String bankCardCityCode; |
| | | |
| | | @ApiModelProperty(value = "进件类型 0-江苏银行;1-汇付") |
| New file |
| | |
| | | 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> { |
| | | } |
| New file |
| | |
| | | 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 { |
| | | } |
| New file |
| | |
| | | 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 |
| | |
| | | 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; |
| | |
| | | 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; |
| | |
| | | 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; |
| | | } |
| | | } |
| New file |
| | |
| | | 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; |
| | | } |
| | | } |
| | | } |
| | |
| | | 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; |
| | | |
| | | /** |
| | | * 余额支付 - 示例 |
| | |
| | | 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\"}"); |
| | | // 手续费承担方标识余额支付手续费承担方标识;商户余额支付扣收规则为接口指定承担方时必填!枚举值:<br/>OUT:出款方;<br/>IN:分账接受方。<br/><font color="green">示例值:IN</font> |
| | | paramsInfo.put("trans_fee_take_flag", "OUT"); |
| | | // 核验值verify_type不为空时必填。当verify_type=SMS时,填写用户收到的短信验证码 |
| | | // paramsInfo.put("verify_value", "test"); |
| | | // 3. 发起API调用 |
| | | Map<String, Object> response = BasePayRequest.requestBasePay("v2/trade/acctpayment/pay", paramsInfo, null, false);; |
| | | return response; |
| | | } |
| | | } |
| | | |
| | | |
| New file |
| | |
| | | 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; |
| | | } |
| | | } |
| | |
| | | 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; |
| | |
| | | * @author fengshuonan |
| | | * @Date 2023-03-17 14:18:09 |
| | | */ |
| | | @Slf4j |
| | | @Controller |
| | | @RequestMapping("/tCompanyWithdraw") |
| | | public class TCompanyWithdrawController extends BaseController { |
| | |
| | | @Resource |
| | | private ITEnterpriseWithdrawalService enterpriseWithdrawalService; |
| | | |
| | | @Autowired |
| | | private DouGongBasicDataBiz douGongBasicDataBiz; |
| | | |
| | | @Autowired |
| | | private DouGongWithdrawBiz douGongWithdrawBiz; |
| | | |
| | | /** |
| | | * 跳转到首页 |
| | | */ |
| | |
| | | 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); |
| | | } |
| | | |
| | |
| | | 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(); |
| | | } |
| | | |
| | |
| | | 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; |
| | |
| | | } |
| | | @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)); |
| | |
| | | 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; |
| | |
| | | private ITSystemNoticeService tSystemNoticeService; |
| | | @Resource |
| | | private IUserWithdrawalService userWithdrawalService; |
| | | @Autowired |
| | | private DouGongWithdrawBiz douGongWithdrawBiz; |
| | | |
| | | /** |
| | | * 跳转到提现列表首页 |
| | |
| | | */ |
| | | @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){ |
| | |
| | | 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){ |
| | |
| | | } |
| | | 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){ |
| | |
| | | |
| | | 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.*; |
| | |
| | | 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.*; |
| | |
| | | * @author fengshuonan |
| | | * @Date 2020-09-24 14:20:41 |
| | | */ |
| | | @Slf4j |
| | | @Controller |
| | | @RequestMapping("/tOrderLogistics") |
| | | public class TOrderLogisticsController extends BaseController { |
| | |
| | | } |
| | | |
| | | } |
| | | 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())); |
| | |
| | | } |
| | | 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(); |
| | | //} |
| | | } |
| | | |
| | | /** |
| | |
| | | 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; |
| | |
| | | @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; |
| | | } |
| | |
| | | private String certificateExpireTime; |
| | | |
| | | @TableField("licenceIssuingAuthority") |
| | | @ApiModelProperty(value = "发证机关") |
| | | @ApiModelProperty(value = "【废弃】发证机关") |
| | | private String licenceIssuingAuthority; |
| | | |
| | | @TableField("bankName") |
| | |
| | | private String openAccountName; |
| | | |
| | | @TableField("transactionAuthorizationCode") |
| | | @ApiModelProperty(value = "交易授权码") |
| | | @ApiModelProperty(value = "【废弃】交易授权码") |
| | | private String transactionAuthorizationCode; |
| | | |
| | | @TableField("phone") |
| | |
| | | private String phone; |
| | | |
| | | @TableField("idCardFrontPicture") |
| | | @ApiModelProperty(value = "法人身份证照片正面") |
| | | @ApiModelProperty(value = "【废弃】法人身份证照片正面") |
| | | private String idCardFrontPicture; |
| | | |
| | | @TableField("idCardReversePicture") |
| | | @ApiModelProperty(value = "法人身份证照片反面") |
| | | @ApiModelProperty(value = "【废弃】法人身份证照片反面") |
| | | private String idCardReversePicture; |
| | | |
| | | /*@TableField("isAudit") |
| | |
| | | |
| | | @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; |
| | | |
| | | } |
| New file |
| | |
| | | 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); |
| | | } |
| | | } |
| New file |
| | |
| | | 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); |
| | | |
| | | } |
| | | } |
| | | } |
| New file |
| | |
| | | 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; |
| | | } |
| | | } |
| | | } |
| | |
| | | |
| | | 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; |