From abe893a75716a6814bdbebdd06a135688cb5c23d Mon Sep 17 00:00:00 2001 From: sunjiabei Date: Mon, 8 Dec 2025 14:36:19 +0800 Subject: [PATCH] =?UTF-8?q?12=E6=9C=888=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 --- .../demo/controller/cash/BankController.java | 25 ++++ .../com/example/demo/domain/DTO/FirstdataDTO.java | 22 +++ .../demo/domain/DTO/FirstdataRequestDTO.java | 24 ++++ .../com/example/demo/domain/vo/cash/BankVO.java | 2 + .../com/example/demo/service/cash/BankService.java | 6 + .../demo/serviceImpl/cash/BankServiceImpl.java | 155 ++++++++++++++++++++- 6 files changed, 231 insertions(+), 3 deletions(-) create mode 100644 src/main/java/com/example/demo/domain/DTO/FirstdataDTO.java create mode 100644 src/main/java/com/example/demo/domain/DTO/FirstdataRequestDTO.java diff --git a/src/main/java/com/example/demo/controller/cash/BankController.java b/src/main/java/com/example/demo/controller/cash/BankController.java index 7610ce7..70d5a03 100644 --- a/src/main/java/com/example/demo/controller/cash/BankController.java +++ b/src/main/java/com/example/demo/controller/cash/BankController.java @@ -80,4 +80,29 @@ public class BankController { } } + //stripe银行接口(批量) + @Log("firstdata银行接口(批量)") + @PostMapping("/firstdataAuto") + public Result firstdataAuto(@RequestBody BankDTO bankDTO) { + try { + return Result.success(bankService.firstdataAuto(bankDTO)); + } catch (Exception e) { + return Result.error(e.getMessage()); + } + } + + //stripe银行接口(单个) + @Log("firstdata银行接口(单个)") + @PostMapping("/getFirstdata") + public Result getFirstdata(@RequestBody BankDTO bankDTO) { + try { + if (bankDTO.getOrderNo().isEmpty()) { + return Result.error("订单号为空"); + } + return bankService.getFirstdata(bankDTO); + } catch (Exception e) { + return Result.error(e.getMessage()); + } + } + } \ No newline at end of file diff --git a/src/main/java/com/example/demo/domain/DTO/FirstdataDTO.java b/src/main/java/com/example/demo/domain/DTO/FirstdataDTO.java new file mode 100644 index 0000000..fcb4720 --- /dev/null +++ b/src/main/java/com/example/demo/domain/DTO/FirstdataDTO.java @@ -0,0 +1,22 @@ +package com.example.demo.domain.DTO; + +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @program: gold-java + * @ClassName FirstdataDTO + * @description: + * @author: Double + * @create: 2025−12-08 10:46 + * @Version 1.0 + **/ + +@Data +@NoArgsConstructor +public class FirstdataDTO { + private String country; + private String orderId; + private String currency; + private Integer total; +} diff --git a/src/main/java/com/example/demo/domain/DTO/FirstdataRequestDTO.java b/src/main/java/com/example/demo/domain/DTO/FirstdataRequestDTO.java new file mode 100644 index 0000000..e3b6052 --- /dev/null +++ b/src/main/java/com/example/demo/domain/DTO/FirstdataRequestDTO.java @@ -0,0 +1,24 @@ +package com.example.demo.domain.DTO; + +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @program: gold-java + * @ClassName FirstdataRequestDTO + * @description: + * @author: Double + * @create: 2025−12-08 14:03 + * @Version 1.0 + **/ + +@Data +@NoArgsConstructor +public class FirstdataRequestDTO { + String key; + String secret; + long clientRequestId; + long time ; + String hmacBase64; + +} 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 index b014b03..49450a1 100644 --- a/src/main/java/com/example/demo/domain/vo/cash/BankVO.java +++ b/src/main/java/com/example/demo/domain/vo/cash/BankVO.java @@ -1,5 +1,6 @@ package com.example.demo.domain.vo.cash; +import com.example.demo.domain.DTO.FirstdataDTO; import com.example.demo.domain.DTO.PaymentDTO; import com.example.demo.domain.DTO.StripeDTO; import lombok.Data; @@ -23,5 +24,6 @@ public class BankVO { private PaymentDTO paymentDTO; private List stripeDTOList; private StripeDTO stripeDTO; + private FirstdataDTO firstdataDTO; private List message; } \ 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 index e42d599..32eb118 100644 --- a/src/main/java/com/example/demo/service/cash/BankService.java +++ b/src/main/java/com/example/demo/service/cash/BankService.java @@ -27,4 +27,10 @@ public interface BankService { //stripe银行接口(单个) Result getStripe(BankDTO bankDTO) throws StripeException; + + //firstdata银行接口(批量) + Result firstdataAuto(BankDTO bankDTO); + + //firstdata银行接口(单个) + Result getFirstdata(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 index 63eac62..f5c52d5 100644 --- a/src/main/java/com/example/demo/serviceImpl/cash/BankServiceImpl.java +++ b/src/main/java/com/example/demo/serviceImpl/cash/BankServiceImpl.java @@ -3,9 +3,7 @@ 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.domain.DTO.BankDTO; -import com.example.demo.domain.DTO.PaymentDTO; -import com.example.demo.domain.DTO.StripeDTO; +import com.example.demo.domain.DTO.*; import com.example.demo.domain.vo.cash.BankVO; import com.example.demo.domain.vo.cash.CashCollection; import com.example.demo.domain.vo.coin.Result; @@ -25,7 +23,10 @@ import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; import org.springframework.web.client.RestTemplate; +import javax.crypto.Mac; +import javax.crypto.spec.SecretKeySpec; import java.math.BigDecimal; +import java.net.http.HttpResponse; import java.nio.charset.StandardCharsets; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; @@ -516,6 +517,154 @@ public class BankServiceImpl implements BankService { } + //firstdata银行接口(批量) + @Override + public Result firstdataAuto(BankDTO bankDTO) { + return null; + } + //firstdata银行接口(单个) + @Override + public Result getFirstdata(BankDTO bankDTO) { + try { + // 获取签名参数 + FirstdataRequestDTO firstdataRequestDTO = generatePaymentAsiaSignature(); + + // 构建请求URL,使用bankDTO中的orderNo + String orderNo = bankDTO.getOrderNo(); + String url = "https://prod.api.firstdata.com/gateway/v2/payments/" + orderNo + "?storeId=4530056594"; + + // 使用RestTemplate发送GET请求 + HttpHeaders headers = new HttpHeaders(); + headers.set("accept", "application/json"); + headers.set("Client-Request-Id", String.valueOf(firstdataRequestDTO.getClientRequestId())); + headers.set("Api-Key", firstdataRequestDTO.getKey()); + headers.set("Timestamp", String.valueOf(firstdataRequestDTO.getTime())); + headers.set("Message-Signature", firstdataRequestDTO.getHmacBase64()); + headers.set("User-Agent", "Apifox/1.0.0 (https://apifox.com)"); + headers.set("Content-Type", "application/json"); + headers.set("Host", "prod.api.firstdata.com"); + headers.set("Connection", "keep-alive"); + + HttpEntity entity = new HttpEntity<>(headers); + + ResponseEntity response = restTemplate.exchange( + url, + HttpMethod.GET, + entity, + String.class + ); + + // 解析响应数据 + // API返回的是对象格式,需要先解析为JSONObject + JSONObject jsonObject = JSON.parseObject(response.getBody()); + + // 创建BankVO对象并设置数据 + BankVO bankVO = new BankVO(); + List message = new ArrayList<>(); + + // 检查jsonObject是否为空或者是否包含错误信息 + if (jsonObject != null && !jsonObject.isEmpty()) { + // 提取需要的字段 + String country = jsonObject.getString("country"); + String orderId = jsonObject.getString("orderId"); + + // 提取currency和total + JSONObject transactionAmount = jsonObject.getJSONObject("transactionAmount"); + String currency = transactionAmount != null ? transactionAmount.getString("currency") : null; + Integer total = transactionAmount != null ? transactionAmount.getInteger("total") : null; + + // 创建FirstdataDTO对象并存储数据 + FirstdataDTO firstdataDTO = new FirstdataDTO(); + firstdataDTO.setCountry(country); + firstdataDTO.setOrderId(orderId); + firstdataDTO.setCurrency(currency); + firstdataDTO.setTotal(total); + + // 将firstdataDTO存入bankVO + bankVO.setFirstdataDTO(firstdataDTO); + + // 创建一个简单的Map来存储提取的数据 + Map extractedData = new HashMap<>(); + extractedData.put("country", country); + extractedData.put("orderId", orderId); + extractedData.put("currency", currency); + extractedData.put("total", total); + extractedData.put("success", true); // 添加成功标识 + + // 将提取的数据转换为JSON字符串并添加到message列表 + message.add(JSON.toJSONString(extractedData, true)); + + // 将message存入bankVO + bankVO.setMessage(message); + + return Result.success(bankVO); + } else { + // 没有数据时也添加失败标识 + Map emptyData = new HashMap<>(); + emptyData.put("success", false); + emptyData.put("message", "No data found"); + message.add(JSON.toJSONString(emptyData, true)); + + // 将message存入bankVO + bankVO.setMessage(message); + + return Result.error("No data found"); + } + } catch (Exception e) { + log.error("Firstdata银行接口调用失败", e); + + // 在异常情况下也构建包含错误信息的message + BankVO bankVO = new BankVO(); + List message = new ArrayList<>(); + Map errorData = new HashMap<>(); + errorData.put("success", false); + errorData.put("error", e.getMessage()); + message.add(JSON.toJSONString(errorData, true)); + bankVO.setMessage(message); + + return Result.error("Firstdata银行接口调用失败: " + e.getMessage()); + } + } + /** + * 生成PaymentAsia API所需的签名 + * @return 签名字符串 + */ + public FirstdataRequestDTO generatePaymentAsiaSignature() { + try { + String key = "3E04ZUCKFmQKrW0uoBa89QKIJWYoU9OX"; + String secret = "ZLtBPgfMIT4HXg25SoVuCyUQZ6GtSv9UFmDmYaoVSKS"; + + // 生成ClientRequestId(1-10000000的随机数) + long clientRequestId = new Random().nextInt(10000000) + 1; + + // 获取当前时间戳(毫秒) + long time = System.currentTimeMillis(); + + // 构造原始签名数据 + String rawSignature = key + clientRequestId + time; + + // 计算HMAC-SHA256 + Mac sha256Hmac = Mac.getInstance("HmacSHA256"); + SecretKeySpec secretKey = new SecretKeySpec(secret.getBytes(StandardCharsets.UTF_8), "HmacSHA256"); + sha256Hmac.init(secretKey); + byte[] hmacBytes = sha256Hmac.doFinal(rawSignature.getBytes(StandardCharsets.UTF_8)); + // 转换为Base64编码 + String hmacBase64 = Base64.getEncoder().encodeToString(hmacBytes); + // 赋值给DTO + FirstdataRequestDTO firstdataRequestDTO = new FirstdataRequestDTO(); + firstdataRequestDTO.setKey(key); + firstdataRequestDTO.setSecret(secret); + firstdataRequestDTO.setClientRequestId(clientRequestId); + firstdataRequestDTO.setTime(time); + firstdataRequestDTO.setHmacBase64(hmacBase64); + + // Base64编码并返回签名 + return firstdataRequestDTO; + } catch (Exception e) { + throw new RuntimeException("生成PaymentAsia签名失败", e); + } + } + /** * http_build_query的查询字符串(key=value&key=value) */