From a2154cf643aa9023ac9dae0206e15a7caa8bda1d Mon Sep 17 00:00:00 2001 From: sunjiabei Date: Fri, 21 Nov 2025 19:23:56 +0800 Subject: [PATCH] =?UTF-8?q?11=E6=9C=8821=E6=97=A5=E9=93=B6=E8=A1=8C?= =?UTF-8?q?=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/example/demo/Util/DateConvertUtil.java | 186 +++++++++++++++ .../com/example/demo/controller/cash/Bank.java | 74 +++++- .../demo/controller/cash/BankController.java | 83 +++++++ .../java/com/example/demo/domain/DTO/BankDTO.java | 24 ++ .../com/example/demo/domain/DTO/PaymentDTO.java | 36 +++ .../com/example/demo/domain/DTO/StripeDTO.java | 25 ++ .../com/example/demo/domain/vo/cash/BankVO.java | 26 +++ .../com/example/demo/service/cash/BankService.java | 29 +++ .../demo/serviceImpl/cash/BankServiceImpl.java | 253 +++++++++++++++++++++ 9 files changed, 735 insertions(+), 1 deletion(-) create mode 100644 src/main/java/com/example/demo/Util/DateConvertUtil.java create mode 100644 src/main/java/com/example/demo/controller/cash/BankController.java create mode 100644 src/main/java/com/example/demo/domain/DTO/BankDTO.java create mode 100644 src/main/java/com/example/demo/domain/DTO/PaymentDTO.java create mode 100644 src/main/java/com/example/demo/domain/DTO/StripeDTO.java create mode 100644 src/main/java/com/example/demo/domain/vo/cash/BankVO.java create mode 100644 src/main/java/com/example/demo/service/cash/BankService.java create mode 100644 src/main/java/com/example/demo/serviceImpl/cash/BankServiceImpl.java diff --git a/src/main/java/com/example/demo/Util/DateConvertUtil.java b/src/main/java/com/example/demo/Util/DateConvertUtil.java new file mode 100644 index 0000000..a0b8666 --- /dev/null +++ b/src/main/java/com/example/demo/Util/DateConvertUtil.java @@ -0,0 +1,186 @@ +package com.example.demo.Util; + +/** + * @program: gold-java + * @ClassName DateConvertUtil + * @description: + * @author: Double + * @create: 2025−11-21 17:45 + * @Version 1.0 + **/ +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.time.LocalDate; +import java.time.format.DateTimeFormatter; +import java.time.format.DateTimeParseException; +import java.util.Date; +import java.util.TimeZone; + +public class DateConvertUtil { + + // 定义支持的日期格式(可根据需求扩展) + private static final DateTimeFormatter FORMATTER_YYYYMMDD = DateTimeFormatter.ofPattern("yyyyMMdd"); + private static final DateTimeFormatter FORMATTER_YYYY_MM_DD = DateTimeFormatter.ofPattern("yyyy-MM-dd"); + private static final DateTimeFormatter FORMATTER_YYYY_SLASH_MM_SLASH_DD = DateTimeFormatter.ofPattern("yyyy/MM/dd"); + + private static final SimpleDateFormat SDF_YYYYMMDD = new SimpleDateFormat("yyyyMMdd"); + private static final SimpleDateFormat SDF_YYYY_MM_DD = new SimpleDateFormat("yyyy-MM-dd"); + private static final SimpleDateFormat SDF_YYYY_SLASH_MM_SLASH_DD = new SimpleDateFormat("yyyy/MM/dd"); + + // 默认时区(可改为 UTC:TimeZone.getTimeZone("UTC")) + private static final TimeZone DEFAULT_TIME_ZONE = TimeZone.getTimeZone("Asia/Shanghai"); + + static { + // 统一设置SimpleDateFormat时区 + SDF_YYYYMMDD.setTimeZone(DEFAULT_TIME_ZONE); + SDF_YYYY_MM_DD.setTimeZone(DEFAULT_TIME_ZONE); + SDF_YYYY_SLASH_MM_SLASH_DD.setTimeZone(DEFAULT_TIME_ZONE); + } + + // -------------------------- String → LocalDate(Java 8+ 推荐)-------------------------- + /** + * 字符串转LocalDate(自动匹配支持的格式) + */ + public static LocalDate stringToLocalDate(String dateStr) { + if (dateStr == null || dateStr.trim().isEmpty()) { + throw new IllegalArgumentException("日期字符串不能为空"); + } + dateStr = dateStr.trim(); + // 依次尝试三种格式 + try { + return LocalDate.parse(dateStr, FORMATTER_YYYYMMDD); + } catch (DateTimeParseException e1) { + try { + return LocalDate.parse(dateStr, FORMATTER_YYYY_MM_DD); + } catch (DateTimeParseException e2) { + try { + return LocalDate.parse(dateStr, FORMATTER_YYYY_SLASH_MM_SLASH_DD); + } catch (DateTimeParseException e3) { + throw new IllegalArgumentException( + String.format("日期格式错误!支持格式:yyyyMMdd、yyyy-MM-dd、yyyy/MM/dd,当前输入:%s", dateStr), + e3 + ); + } + } + } + } + + /** + * 字符串转LocalDate(指定格式) + */ + public static LocalDate stringToLocalDate(String dateStr, String pattern) { + if (dateStr == null || dateStr.trim().isEmpty()) { + throw new IllegalArgumentException("日期字符串不能为空"); + } + if (pattern == null || pattern.trim().isEmpty()) { + throw new IllegalArgumentException("格式模板不能为空"); + } + try { + DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern); + return LocalDate.parse(dateStr.trim(), formatter); + } catch (DateTimeParseException e) { + throw new IllegalArgumentException( + String.format("日期格式错误!指定格式:%s,当前输入:%s", pattern, dateStr), + e + ); + } + } + + // -------------------------- String → Date(兼容旧代码)-------------------------- + /** + * 字符串转Date(自动匹配支持的格式) + */ + public static Date stringToDate(String dateStr) { + if (dateStr == null || dateStr.trim().isEmpty()) { + throw new IllegalArgumentException("日期字符串不能为空"); + } + dateStr = dateStr.trim(); + try { + return SDF_YYYYMMDD.parse(dateStr); + } catch (ParseException e1) { + try { + return SDF_YYYY_MM_DD.parse(dateStr); + } catch (ParseException e2) { + try { + return SDF_YYYY_SLASH_MM_SLASH_DD.parse(dateStr); + } catch (ParseException e3) { + throw new IllegalArgumentException( + String.format("日期格式错误!支持格式:yyyyMMdd、yyyy-MM-dd、yyyy/MM/dd,当前输入:%s", dateStr), + e3 + ); + } + } + } + } + + /** + * 字符串转Date(指定格式) + */ + public static Date stringToDate(String dateStr, String pattern) { + if (dateStr == null || dateStr.trim().isEmpty()) { + throw new IllegalArgumentException("日期字符串不能为空"); + } + if (pattern == null || pattern.trim().isEmpty()) { + throw new IllegalArgumentException("格式模板不能为空"); + } + try { + SimpleDateFormat sdf = new SimpleDateFormat(pattern); + sdf.setTimeZone(DEFAULT_TIME_ZONE); + return sdf.parse(dateStr.trim()); + } catch (ParseException e) { + throw new IllegalArgumentException( + String.format("日期格式错误!指定格式:%s,当前输入:%s", pattern, dateStr), + e + ); + } + } + + // -------------------------- Date ↔ LocalDate 互转 -------------------------- + /** + * Date转LocalDate + */ + public static LocalDate dateToLocalDate(Date date) { + if (date == null) { + throw new IllegalArgumentException("Date对象不能为空"); + } + return date.toInstant() + .atZone(DEFAULT_TIME_ZONE.toZoneId()) + .toLocalDate(); + } + + /** + * LocalDate转Date + */ + public static Date localDateToDate(LocalDate localDate) { + if (localDate == null) { + throw new IllegalArgumentException("LocalDate对象不能为空"); + } + return Date.from( + localDate.atStartOfDay(DEFAULT_TIME_ZONE.toZoneId()) + .toInstant() + ); + } + + // -------------------------- 测试方法 -------------------------- + public static void main(String[] args) { + // 测试1:String→LocalDate(yyyyMMdd格式) + LocalDate localDate1 = stringToLocalDate("20250911"); + System.out.println("String→LocalDate(yyyyMMdd):" + localDate1); // 输出:2025-09-11 + + // 测试2:String→Date(yyyy-MM-dd格式) + Date date1 = stringToDate("2025-09-11"); + System.out.println("String→Date(yyyy-MM-dd):" + date1); // 输出:Wed Sep 11 00:00:00 CST 2025 + + // 测试3:Date→LocalDate + LocalDate localDate2 = dateToLocalDate(date1); + System.out.println("Date→LocalDate:" + localDate2); // 输出:2025-09-11 + + // 测试4:LocalDate→Date + Date date2 = localDateToDate(localDate2); + System.out.println("LocalDate→Date:" + date2); // 输出:Wed Sep 11 00:00:00 CST 2025 + + // 测试5:指定格式转换(yyyy/MM/dd) + LocalDate localDate3 = stringToLocalDate("2025/09/11", "yyyy/MM/dd"); + System.out.println("指定格式(yyyy/MM/dd)→LocalDate:" + localDate3); // 输出:2025-09-11 + } +} diff --git a/src/main/java/com/example/demo/controller/cash/Bank.java b/src/main/java/com/example/demo/controller/cash/Bank.java index 7b95437..7e55783 100644 --- a/src/main/java/com/example/demo/controller/cash/Bank.java +++ b/src/main/java/com/example/demo/controller/cash/Bank.java @@ -9,6 +9,78 @@ package com.example.demo.controller.cash; * @Version 1.0 **/ +import com.example.demo.domain.DTO.BankDTO; +import com.example.demo.domain.DTO.StripeDTO; +import com.example.demo.domain.vo.cash.BankVO; +import com.stripe.Stripe; +import com.stripe.exception.StripeException; +import com.stripe.model.*; +import com.stripe.param.*; + +import java.util.ArrayList; +import java.util.List; + public class Bank { + public static void main(String[] args) throws StripeException { + Stripe.apiKey = "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"; + +// List allCharges = new ArrayList<>(); +// String startingAfter = null; +// int totalLimit = 200; // 目标获取 +// int pageSize = 100; // 单次最大 +// +// do { +// // 计算当前页需查询的条数(最后一页可能不足 100 条) +// int currentPageSize = Math.min(pageSize, totalLimit - allCharges.size()); +// if (currentPageSize <= 0) { +// break; // 已获取够,停止 +// } +// +// // 构建分页参数 +// ChargeListParams params = ChargeListParams.builder() +// .setLimit((long) currentPageSize) +// .setStartingAfter(startingAfter) +// .build(); +// +// try { +// ChargeCollection charges = Charge.list(params); +// List currentPageData = charges.getData(); +// allCharges.addAll(currentPageData); +// +// // 更新分页游标:若有下一页且未达 200 条,继续 +// boolean hasMore = charges.getHasMore() && allCharges.size() < totalLimit; +// startingAfter = hasMore ? currentPageData.get(currentPageData.size() - 1).getId() : null; +// +// } catch (StripeException e) { +// System.err.println("Stripe 分页查询失败:" + e.getMessage()); +// break; // 异常时停止查询,返回已获取的数据 +// } +// +// } while (startingAfter != null); +// System.out.println(allCharges); +// +// // 3. 封装DTO +// List stripeDTOList = new ArrayList<>(); +// for (Charge charge : allCharges) { +// StripeDTO stripeDTO = new StripeDTO(); +// stripeDTO.setOrderNo(charge.getMetadata().get("order_no")); +// stripeDTO.setBalanceTransaction(charge.getBalanceTransaction()); +// stripeDTOList.add(stripeDTO); +// } +// +// BankVO bankVO = new BankVO(); +// bankVO.setStripeDTOList(stripeDTOList); +// +// // 4. 输出结果 +// System.out.println("最终BankDTO数据:"); +// System.out.println("stripeDTOList size:" + bankVO.getStripeDTOList().size()); +// System.out.println("stripeDTOList:" + bankVO.getStripeDTOList()); +// System.out.println("orderNo:" + bankVO.getStripeDTOList().get(199).getOrderNo()); +// System.out.println("balanceTransaction:" + bankVO.getStripeDTOList().get(199).getBalanceTransaction()); + -} + BalanceTransaction balanceTransaction = + BalanceTransaction.retrieve("txn_3SVnLrJHMNYcqBc01CAgovvJ"); + System.out.println(balanceTransaction); + } +} \ No newline at end of file diff --git a/src/main/java/com/example/demo/controller/cash/BankController.java b/src/main/java/com/example/demo/controller/cash/BankController.java new file mode 100644 index 0000000..af89502 --- /dev/null +++ b/src/main/java/com/example/demo/controller/cash/BankController.java @@ -0,0 +1,83 @@ +package com.example.demo.controller.cash; + +import com.example.demo.config.interfac.Log; +import com.example.demo.domain.DTO.BankDTO; +import com.example.demo.domain.vo.cash.BankVO; +import com.example.demo.domain.vo.coin.Result; +import com.example.demo.service.cash.BankService; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +/** + * @program: gold-java + * @ClassName Bank + * @description: + * @author: Double + * @create: 2025−11-17 13:31 + * @Version 1.0 + **/ + + +@RestController +@RequestMapping("/bank") +@RequiredArgsConstructor +@Slf4j +@CrossOrigin +public class BankController { + + @Autowired + private BankService bankService; + + //payment银行接口(批量) + @Log("payment银行接口(批量)") + @PostMapping("/paymentAuto") + public Result paymentAuto(@RequestBody BankDTO bankDTO) { + try { + return Result.success(bankService.paymentAuto(bankDTO)); + } catch (Exception e) { + return Result.error(e.getMessage()); + } + } + + //payment银行接口(单个) + @Log("payment银行接口(单个)") + @PostMapping("/getPayment") + public Result getPayment(@RequestBody BankDTO bankDTO) { + try { + if(bankDTO.getTime().isEmpty() || bankDTO.getOrderNo().isEmpty()){ + return Result.error("时间或订单号为空"); + } + return bankService.getPayment(bankDTO); + } catch (Exception e) { + return Result.error(e.getMessage()); + } + } + + //payment银行接口(批量) + @Log("stripe银行接口(批量)") + @PostMapping("/stripeAuto") + public Result stripeAuto(@RequestBody BankDTO bankDTO) { + try { + return Result.success(bankService.stripeAuto(bankDTO)); + } catch (Exception e) { + return Result.error(e.getMessage()); + } + } + + //payment银行接口(单个) + @Log("stripe银行接口(单个)") + @PostMapping("/getStripe") + public Result getStripe(@RequestBody BankDTO bankDTO) { + try { + if(bankDTO.getTime().isEmpty() || bankDTO.getOrderNo().isEmpty()){ + return Result.error("时间或订单号为空"); + } + return bankService.getStripe(bankDTO); + } catch (Exception e) { + return Result.error(e.getMessage()); + } + } + +} diff --git a/src/main/java/com/example/demo/domain/DTO/BankDTO.java b/src/main/java/com/example/demo/domain/DTO/BankDTO.java new file mode 100644 index 0000000..cf504e5 --- /dev/null +++ b/src/main/java/com/example/demo/domain/DTO/BankDTO.java @@ -0,0 +1,24 @@ +package com.example.demo.domain.DTO; + +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.List; + +/** + * @program: gold-java + * @ClassName BankDTO + * @description: + * @author: Double + * @create: 2025−11-21 10:32 + * @Version 1.0 + **/ + +@Data +@NoArgsConstructor +public class BankDTO { + //时间格式yyyyMMdd + private String time = ""; + //订单号 + private String orderNo = ""; +} diff --git a/src/main/java/com/example/demo/domain/DTO/PaymentDTO.java b/src/main/java/com/example/demo/domain/DTO/PaymentDTO.java new file mode 100644 index 0000000..c36abb4 --- /dev/null +++ b/src/main/java/com/example/demo/domain/DTO/PaymentDTO.java @@ -0,0 +1,36 @@ +package com.example.demo.domain.DTO; + +/** + * @program: gold-java + * @ClassName PaymentDTO + * @description: + * @author: Double + * @create: 2025−11-21 10:42 + * @Version 1.0 + **/ + +import com.fasterxml.jackson.annotation.JsonFormat; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.Date; + +@Data +@NoArgsConstructor +public class PaymentDTO { + + @JsonFormat(pattern = "yyyy-MM-dd", timezone = "Asia/Shanghai") + private Date time; + private String type; + private String provider; + private String request_reference; + private String merchant_reference; + private String provider_reference; + private String currency; + private Double order_amount; + private Double charge; + private Double net_amount; + private String status; + private String created_time; + private String completed_time; +} \ No newline at end of file diff --git a/src/main/java/com/example/demo/domain/DTO/StripeDTO.java b/src/main/java/com/example/demo/domain/DTO/StripeDTO.java new file mode 100644 index 0000000..72af3f2 --- /dev/null +++ b/src/main/java/com/example/demo/domain/DTO/StripeDTO.java @@ -0,0 +1,25 @@ +package com.example.demo.domain.DTO; + +/** + * @program: gold-java + * @ClassName StripeDTO + * @description: + * @author: Double + * @create: 2025−11-21 15:26 + * @Version 1.0 + **/ + + +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@NoArgsConstructor +public class StripeDTO { + private String orderNo;//订单号 + private String balanceTransaction;//余额交易ID + private String currency;//货币 + private String amount;//金额 + private String fee;//手续费 + private String net;//净额 +} diff --git a/src/main/java/com/example/demo/domain/vo/cash/BankVO.java b/src/main/java/com/example/demo/domain/vo/cash/BankVO.java new file mode 100644 index 0000000..e5855fe --- /dev/null +++ b/src/main/java/com/example/demo/domain/vo/cash/BankVO.java @@ -0,0 +1,26 @@ +package com.example.demo.domain.vo.cash; + +import com.example.demo.domain.DTO.PaymentDTO; +import com.example.demo.domain.DTO.StripeDTO; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.List; + +/** + * @program: gold-java + * @ClassName BankVO + * @description: + * @author: Double + * @create: 2025−11-21 10:44 + * @Version 1.0 + **/ + +@Data +@NoArgsConstructor +public class BankVO { + private List paymentDTOList; + private PaymentDTO paymentDTO; + private List stripeDTOList; + private StripeDTO stripeDTO; +} \ No newline at end of file diff --git a/src/main/java/com/example/demo/service/cash/BankService.java b/src/main/java/com/example/demo/service/cash/BankService.java new file mode 100644 index 0000000..8eb32f0 --- /dev/null +++ b/src/main/java/com/example/demo/service/cash/BankService.java @@ -0,0 +1,29 @@ +package com.example.demo.service.cash; + + +import com.example.demo.domain.DTO.BankDTO; +import com.example.demo.domain.vo.cash.BankVO; +import com.example.demo.domain.vo.coin.Result; + +/** + * @program: gold-java + * @ClassName BankService + * @description: + * @author: Double + * @create: 2025−11-21 10:43 + * @Version 1.0 + **/ + +public interface BankService { + //payment银行接口(批量) + Result paymentAuto(BankDTO bankDTO); + + //payment银行接口(单个) + Result getPayment(BankDTO bankDTO); + + //stripe银行接口(批量) + Result stripeAuto(BankDTO bankDTO); + + //stripe银行接口(单个) + Result getStripe(BankDTO bankDTO); +} \ No newline at end of file diff --git a/src/main/java/com/example/demo/serviceImpl/cash/BankServiceImpl.java b/src/main/java/com/example/demo/serviceImpl/cash/BankServiceImpl.java new file mode 100644 index 0000000..d79ea3a --- /dev/null +++ b/src/main/java/com/example/demo/serviceImpl/cash/BankServiceImpl.java @@ -0,0 +1,253 @@ +package com.example.demo.serviceImpl.cash; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.example.demo.Util.DateConvertUtil; +import com.example.demo.domain.DTO.BankDTO; +import com.example.demo.domain.DTO.PaymentDTO; +import com.example.demo.domain.vo.cash.BankVO; +import com.example.demo.domain.vo.cash.CashCollection; +import com.example.demo.domain.vo.coin.Result; +import com.example.demo.mapper.cash.CashCollectionMapper; +import com.example.demo.service.cash.BankService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.*; +import org.springframework.stereotype.Service; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; +import org.springframework.web.client.RestTemplate; + +import java.nio.charset.StandardCharsets; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.List; +import java.util.Map; +import java.util.TreeMap; + +/** + * @program: gold-java + * @ClassName BankServiceImpl + * @description: + * @author: Double + * @create: 2025−11-21 10:46 + * @Version 1.0 + **/ + +@Service +@Slf4j +public class BankServiceImpl implements BankService { + + @Autowired + private CashCollectionMapper cashCollectionMapper; + + // 第三方API地址 + private static final String API_URL = "https://gateway.pa-sys.com/v1.1/reconciliation/519e26b2-8145-418c-b3e7-c1e88e52b946/settlement"; + // 签名密钥 + private static final String SECRET = "8987d1b8-1d82-4b15-af06-828d0b12076f"; + + // 注入RestTemplate用于HTTP请求(需在Spring配置类中定义) + private final RestTemplate restTemplate; + + public BankServiceImpl(RestTemplate restTemplate) { + this.restTemplate = restTemplate; + } + + //payment银行接口(单个) + @Override + public Result getPayment(BankDTO bankDTO) { + try { + // 1. 准备参数 + String settlementDate = bankDTO.getTime(); // 从BankDTO对象获取time作为settlement_date + String network = "FPS"; // 固定值 + // 2. 生成签名 + Map params = new TreeMap<>(); // 按key升序排序 + params.put("settlement_date", settlementDate); + params.put("network", network); + + String signSource = buildQueryString(params) + SECRET; + String sign = sha512(signSource); + + // 3. 构建form-data请求参数 + MultiValueMap formData = new LinkedMultiValueMap<>(); + formData.add("settlement_date", settlementDate); + formData.add("network", network); + formData.add("sign", sign); + + // 4. 发送HTTP POST请求(优化:显式设置multipart/form-data的字符集) + HttpHeaders headers = new HttpHeaders(); + // 补充charset=UTF-8,避免部分服务器对编码敏感 + headers.setContentType(new MediaType("multipart", "form-data", StandardCharsets.UTF_8)); + HttpEntity> requestEntity = new HttpEntity<>(formData, headers); + + // 调用第三方API(使用配置好SSL协议的RestTemplate) + ResponseEntity response = restTemplate.exchange( + API_URL, + HttpMethod.POST, + requestEntity, + String.class + ); + + if (response.getStatusCode().is2xxSuccessful()) { + String responseBody = response.getBody(); + log.info("第三方API响应: {}", responseBody); + + // 解析JSON获取payload.transactions数组 + JSONObject jsonObject = JSON.parseObject(responseBody); + JSONArray transactions = jsonObject.getJSONObject("payload").getJSONArray("transactions"); + + // 创建BankDTO并设置paymentDTOList + BankVO bankVO = new BankVO(); + List paymentDTOList = transactions.toJavaList(PaymentDTO.class); + bankVO.setPaymentDTOList(paymentDTOList); + // 获取订单号 + String orderNo = bankDTO.getOrderNo(); + + // 如果订单号不为空,则进行匹配查找 + if (orderNo != null && !orderNo.isEmpty()) { + boolean found = false; + for (PaymentDTO paymentDTO : paymentDTOList) { + if (orderNo.equals(paymentDTO.getMerchant_reference())) { + SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd"); + paymentDTO.setTime(sdf.parse(bankDTO.getTime())); + paymentDTO.setOrder_amount(paymentDTO.getOrder_amount()*100); + paymentDTO.setCharge(paymentDTO.getCharge()*100); + paymentDTO.setNet_amount(paymentDTO.getNet_amount()*100); + paymentDTO.setCurrency("2"); + bankVO.setPaymentDTO(paymentDTO); + found = true; + break; + } + } + // 如果没有找到匹配的订单号,返回提示信息 + if (!found) { + log.info("当前日期 {} 该订单号 {} 未查到", settlementDate, orderNo); + // 可以根据业务需求进行相应处理,比如抛出异常或设置特定标识 + return Result.error("payment当前日期 " + settlementDate + " 该订单号 " + orderNo + " 未查到"); + } + } + + CashCollection cashCollection = cashCollectionMapper.selectByGoldCoinOrderCode(orderNo); + if (cashCollection == null) { + return Result.error("金币系统当前日期 " + settlementDate + " 该订单号 " + orderNo + " 未查到"); + } + else { + cashCollectionMapper.updateByGoldCoinOrderCode(bankVO.getPaymentDTO()); + } + return Result.success(bankVO); + } else { + throw new RuntimeException("API请求失败,状态码: " + response.getStatusCodeValue()); + } + + } catch (Exception e) { + log.error("payment银行接口处理失败", e); + throw new RuntimeException("处理失败: " + e.getMessage()); + } + } + + //payment银行接口(批量) + @Override + public Result paymentAuto(BankDTO bankDTO) { + try { + // 1. 准备参数 + String settlementDate = bankDTO.getTime(); // 从BankDTO对象获取time作为settlement_date + String network = "FPS"; // 固定值 + // 2. 生成签名 + Map params = new TreeMap<>(); // 按key升序排序 + params.put("settlement_date", settlementDate); + params.put("network", network); + + String signSource = buildQueryString(params) + SECRET; + String sign = sha512(signSource); + + // 3. 构建form-data请求参数 + MultiValueMap formData = new LinkedMultiValueMap<>(); + formData.add("settlement_date", settlementDate); + formData.add("network", network); + formData.add("sign", sign); + + // 4. 发送HTTP POST请求(优化:显式设置multipart/form-data的字符集) + HttpHeaders headers = new HttpHeaders(); + // 补充charset=UTF-8,避免部分服务器对编码敏感 + headers.setContentType(new MediaType("multipart", "form-data", StandardCharsets.UTF_8)); + HttpEntity> requestEntity = new HttpEntity<>(formData, headers); + + // 调用第三方API(使用配置好SSL协议的RestTemplate) + ResponseEntity response = restTemplate.exchange( + API_URL, + HttpMethod.POST, + requestEntity, + String.class + ); + + if (response.getStatusCode().is2xxSuccessful()) { + String responseBody = response.getBody(); + log.info("第三方API响应: {}", responseBody); + + // 解析JSON获取payload.transactions数组 + JSONObject jsonObject = JSON.parseObject(responseBody); + JSONArray transactions = jsonObject.getJSONObject("payload").getJSONArray("transactions"); + + // 创建BankDTO并设置paymentDTOList + BankVO bankVO = new BankVO(); + List paymentDTOList = transactions.toJavaList(PaymentDTO.class); + bankVO.setPaymentDTOList(paymentDTOList); + + return Result.success(bankVO); + } else { + throw new RuntimeException("API请求失败,状态码: " + response.getStatusCodeValue()); + } + + } catch (Exception e) { + log.error("payment银行接口处理失败", e); + throw new RuntimeException("处理失败: " + e.getMessage()); + } + } + + //stripe银行接口(批量) + @Override + public Result stripeAuto(BankDTO bankDTO) { + return Result.success(bankDTO); + } + + //stripe银行接口(单个) + @Override + public Result getStripe(BankDTO bankDTO) { + return Result.success(bankDTO); + } + + /** + * http_build_query的查询字符串(key=value&key=value) + */ + private String buildQueryString(Map params) { + StringBuilder sb = new StringBuilder(); + for (Map.Entry entry : params.entrySet()) { + if (sb.length() > 0) { + sb.append("&"); + } + sb.append(entry.getKey()).append("=").append(entry.getValue()); + } + return sb.toString(); + } + + /** + * SHA512加密 + */ + private String sha512(String content) throws NoSuchAlgorithmException { + MessageDigest md = MessageDigest.getInstance("SHA-512"); + byte[] bytes = md.digest(content.getBytes(StandardCharsets.UTF_8)); + // 转换为十六进制字符串 + StringBuilder hexStr = new StringBuilder(); + for (byte b : bytes) { + String hex = Integer.toHexString(0xff & b); + if (hex.length() == 1) { + hexStr.append('0'); + } + hexStr.append(hex); + } + return hexStr.toString(); + } +} \ No newline at end of file