|
|
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.*;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 com.stripe.Stripe;import com.stripe.exception.StripeException;import com.stripe.model.BalanceTransaction;import com.stripe.model.Charge;import com.stripe.model.ChargeCollection;import com.stripe.param.ChargeListParams;import lombok.extern.slf4j.Slf4j;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.http.*;import org.springframework.scheduling.annotation.Scheduled;import org.springframework.stereotype.Service;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;import java.text.SimpleDateFormat;import java.time.LocalDate;import java.time.ZoneId;import java.time.format.DateTimeFormatter;import java.util.*;
/** * @program: gold-java * @ClassName BankServiceImpl * @description: * @author: Double * @create: 2025−11-21 10:46 * @Version 1.0 **/
@Service@Slf4jpublic 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<String, String> 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<String, String> 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<MultiValueMap<String, String>> requestEntity = new HttpEntity<>(formData, headers);
// 调用第三方API(使用配置好SSL协议的RestTemplate)
ResponseEntity<String> 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<PaymentDTO> paymentDTOList; try { paymentDTOList = transactions.toJavaList(PaymentDTO.class); } catch (Exception e) { log.error("解析JSON响应时发生错误: {}", e.getMessage(), e); return Result.error("payment当天无数据请切换日期"); } 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().multiply(BigDecimal.valueOf(100))); paymentDTO.setCharge(paymentDTO.getCharge().multiply(BigDecimal.valueOf(100))); paymentDTO.setNet_amount(paymentDTO.getNet_amount().multiply(BigDecimal.valueOf(100))); paymentDTO.setCurrency("港币HKD"); 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.updateByGoldCoinOrderCodeByPayment(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<String, String> 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<String, String> 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<MultiValueMap<String, String>> requestEntity = new HttpEntity<>(formData, headers);
// 调用第三方API(使用配置好SSL协议的RestTemplate)
ResponseEntity<String> 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");
// 创建BankVO并设置paymentDTOList
BankVO bankVO = new BankVO(); List<PaymentDTO> paymentDTOList; try { paymentDTOList = transactions.toJavaList(PaymentDTO.class); } catch (Exception e) { log.error("解析JSON响应时发生错误: {}", e.getMessage(), e); return Result.error("payment当天无数据请切换日期"); } bankVO.setPaymentDTOList(paymentDTOList); // 收集处理信息
List<String> messages = new ArrayList<>(); // 对paymentDTOList中的每个元素进行处理
List<PaymentDTO> processedPayments = new ArrayList<>(); for (PaymentDTO paymentDTO : paymentDTOList) { try {
// 格式化时间
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd"); paymentDTO.setTime(sdf.parse(settlementDate)); // 金额转换(假设原始数据是元为单位,需要转为分为单位)
paymentDTO.setOrder_amount(paymentDTO.getOrder_amount().multiply(BigDecimal.valueOf(100))); paymentDTO.setCharge(paymentDTO.getCharge().multiply(BigDecimal.valueOf(100))); paymentDTO.setNet_amount(paymentDTO.getNet_amount().multiply(BigDecimal.valueOf(100))); // 设置货币代码
paymentDTO.setCurrency("港币HKD");
// 获取订单号
String orderNo = paymentDTO.getMerchant_reference();
List<String> orderNoList = cashCollectionMapper.selectStripeList(); // 检查当前订单号是否在列表中
if (orderNoList.contains(orderNo)) { cashCollectionMapper.updateByGoldCoinOrderCodeByPayment(paymentDTO); processedPayments.add(paymentDTO); log.info("成功处理订单: {}", orderNo); messages.add("成功处理订单: " + orderNo); } else { log.warn("金币系统中未找到订单: {}", orderNo); messages.add("金币系统中未找到订单: " + orderNo); } } catch (Exception e) { messages.add("处理单个支付记录时发生错误: " + paymentDTO.getMerchant_reference() + ",错误信息: " + e.getMessage()); log.error("处理单个支付记录时发生错误: {}", paymentDTO.getMerchant_reference(), e); } }
// 设置处理成功的支付列表
bankVO.setPaymentDTOList(processedPayments); bankVO.setMessage(messages);
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) { try { // 设置Stripe API密钥
Stripe.apiKey = "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"; if (bankDTO.getSum() <= 0) { return Result.error("最大条数不能小于等于0"); } // 收集处理信息
List<String> messages = new ArrayList<>(); // 从Stripe获取最近的收费记录(最多200条)
List<Charge> allCharges = new ArrayList<>(); String startingAfter = null; int totalLimit = bankDTO.getSum(); // 目标获取条数
int pageSize = 100; // 单次最大获取条数
do { // 计算当前页需查询的条数(最后一页可能不足100条)
int currentPageSize = Math.min(pageSize, totalLimit - allCharges.size()); if (currentPageSize <= 0) { break; // 已获取足够条数,停止
} Long startTime = LocalDate.parse(bankDTO.getStartTime(), DateTimeFormatter.ofPattern("yyyyMMdd")).atStartOfDay(ZoneId.of("Asia/Shanghai")).toEpochSecond(); Long endTime = LocalDate.parse(bankDTO.getEndTime(), DateTimeFormatter.ofPattern("yyyyMMdd")).atStartOfDay(ZoneId.of("Asia/Shanghai")).toEpochSecond(); ChargeListParams.Created createdCondition = ChargeListParams.Created.builder() .setGte(startTime) // 大于等于开始时间
.setLt(endTime) // 小于结束时间
.build(); ChargeListParams params = ChargeListParams.builder() .setLimit((long) currentPageSize) .setStartingAfter(startingAfter) .setCreated(createdCondition) // 加入时间筛选
.build();
try { // 执行分页查询
ChargeCollection charges = Charge.list(params); List<Charge> 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) { log.error("Stripe 分页查询失败:" + e.getMessage()); break; // 异常时停止查询,返回已获取的数据
}
} while (startingAfter != null);
// 创建StripeDTO列表用于存储所有处理后的数据
List<StripeDTO> stripeDTOList = new ArrayList<>();
// 处理每一条Stripe数据
for (Charge charge : allCharges) { try { // 获取charge对应的余额交易ID
String balanceTransactionId = charge.getBalanceTransaction();
// 通过余额交易ID获取详细信息
BalanceTransaction balanceTransaction = BalanceTransaction.retrieve(balanceTransactionId);
// 创建StripeDTO对象并填充所需数据点
StripeDTO stripeDTO = new StripeDTO();
// 从metadata中获取订单号
if (charge.getMetadata() != null) { stripeDTO.setOrderNo(charge.getMetadata().get("order_no")); }
// 设置余额交易ID
stripeDTO.setBalanceTransaction(charge.getBalanceTransaction());
// 设置付款币种和金额(来自charge)
stripeDTO.setCurrency(charge.getCurrency().toUpperCase()); stripeDTO.setAmount(String.valueOf(balanceTransaction.getAmount()));
// 设置收款币种(来自charge)
stripeDTO.setChargeCurrency(charge.getCurrency().toUpperCase());
// 设置到账金额和手续费(来自balanceTransaction)
stripeDTO.setNet(String.valueOf(balanceTransaction.getNet())); stripeDTO.setFee(String.valueOf(balanceTransaction.getFee()));
// 设置到账币种(来自balanceTransaction)
stripeDTO.setCurrency(balanceTransaction.getCurrency().toUpperCase());
// 设置available_on日期
if (balanceTransaction.getAvailableOn() != null) { long availableOnInSeconds = balanceTransaction.getAvailableOn(); // 将Unix时间戳转换为Date对象
Date availableOnDate = new Date(availableOnInSeconds * 1000L); stripeDTO.setAvailableOn(availableOnDate); }
// 添加到列表中
stripeDTOList.add(stripeDTO);
// 如果订单号存在,且在selectStripeList返回的列表中,则更新数据库中的记录
if (stripeDTO.getOrderNo() != null && !stripeDTO.getOrderNo().isEmpty()) { // 获取需要处理的订单号列表
List<String> orderNoList = cashCollectionMapper.selectStripeList(); // 检查当前订单号是否在列表中
if (orderNoList.contains(stripeDTO.getOrderNo())) { cashCollectionMapper.updateByGoldCoinOrderCodeByStripe(stripeDTO); } } messages.add("成功处理订单: " + stripeDTO.getOrderNo()); } catch (Exception e) { log.error("处理Stripe数据失败,chargeId: " + charge.getId(), e); // 继续处理其他数据,不中断整个流程
} }
// 创建响应VO对象
BankVO bankVO = new BankVO(); bankVO.setStripeDTOList(stripeDTOList); bankVO.setMessage(messages);
return Result.success(bankVO); } catch (Exception e) { log.error("stripe银行接口处理失败", e); throw new RuntimeException("处理失败: " + e.getMessage()); } }
//stripe银行接口(单个)
@Override public Result getStripe(BankDTO bankDTO) throws StripeException { try { // 设置Stripe API密钥
Stripe.apiKey = "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"; // 方式一:通过订单号查找最近数据
String orderNo = bankDTO.getOrderNo();
if (bankDTO.getSum() <= 0) { return Result.error("最大条数不能小于等于0"); }
// 从Stripe获取最近的收费记录(最多200条)
List<Charge> allCharges = new ArrayList<>(); String startingAfter = null; int totalLimit = bankDTO.getSum(); // 目标获取条数
int pageSize = 100; // 单次最大获取条数
do { // 计算当前页需查询的条数(最后一页可能不足100条)
int currentPageSize = Math.min(pageSize, totalLimit - allCharges.size()); if (currentPageSize <= 0) { break; // 已获取足够条数,停止
} Long startTime = LocalDate.parse(bankDTO.getStartTime(), DateTimeFormatter.ofPattern("yyyyMMdd")).atStartOfDay(ZoneId.of("Asia/Shanghai")).toEpochSecond(); Long endTime = LocalDate.parse(bankDTO.getEndTime(), DateTimeFormatter.ofPattern("yyyyMMdd")).atStartOfDay(ZoneId.of("Asia/Shanghai")).toEpochSecond(); ChargeListParams.Created createdCondition = ChargeListParams.Created.builder() .setGte(startTime) // 大于等于开始时间
.setLt(endTime) // 小于结束时间
.build(); ChargeListParams params = ChargeListParams.builder() .setLimit((long) currentPageSize) .setStartingAfter(startingAfter) .setCreated(createdCondition) // 加入时间筛选
.build();
try { // 执行分页查询
ChargeCollection charges = Charge.list(params); List<Charge> 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) { log.error("Stripe 分页查询失败:" + e.getMessage()); break; // 异常时停止查询,返回已获取的数据
}
} while (startingAfter != null);
// 在获取的所有记录中查找匹配订单号的记录
Charge matchedCharge = null; System.out.println(allCharges); for (Charge charge : allCharges) { // 从metadata中获取订单号进行匹配
if (charge.getMetadata() != null) { String chargeOrderNo = charge.getMetadata().get("order_no"); if (chargeOrderNo != null && orderNo.equals(chargeOrderNo)) { matchedCharge = charge; break; } } }
// 如果未找到匹配的订单,返回错误信息
if (matchedCharge == null) { return Result.error("未找到订单号 " + orderNo + " 的支付记录"); }
// 获取匹配到的charge对应的余额交易ID
String balanceTransactionId = matchedCharge.getBalanceTransaction();
// 通过余额交易ID获取详细信息
BalanceTransaction balanceTransaction = BalanceTransaction.retrieve(balanceTransactionId);
// 创建StripeDTO对象并填充所需数据点
StripeDTO stripeDTO = new StripeDTO(); // 设置订单号
stripeDTO.setOrderNo(matchedCharge.getMetadata().get("order_no")); // 设置余额交易ID
stripeDTO.setBalanceTransaction(matchedCharge.getBalanceTransaction());
// 设置付款币种和金额(来自charge和来自balanceTransaction)
stripeDTO.setCurrency(matchedCharge.getCurrency().toUpperCase()); stripeDTO.setAmount(String.valueOf(balanceTransaction.getAmount()));
// 设置收款币种(来自charge)
stripeDTO.setChargeCurrency(matchedCharge.getCurrency().toUpperCase());
// 设置到账金额和手续费(来自balanceTransaction)
stripeDTO.setNet(String.valueOf(balanceTransaction.getNet())); stripeDTO.setFee(String.valueOf(balanceTransaction.getFee()));
// 设置到账币种(来自balanceTransaction)
stripeDTO.setCurrency(balanceTransaction.getCurrency().toUpperCase());
// 设置available_on日期
if (balanceTransaction.getAvailableOn() != null) { long availableOnInSeconds = balanceTransaction.getAvailableOn(); // 将Unix时间戳转换为Date对象
Date availableOnDate = new Date(availableOnInSeconds * 1000L); stripeDTO.setAvailableOn(availableOnDate); }
// 创建响应VO对象
BankVO bankVO = new BankVO(); bankVO.setStripeDTO(stripeDTO); CashCollection cashCollection = cashCollectionMapper.selectByGoldCoinOrderCode(orderNo); if (cashCollection == null) { return Result.error("金币系统当前日期 " + " 该订单号 " + orderNo + " 未查到"); } else { cashCollectionMapper.updateByGoldCoinOrderCodeByStripe(bankVO.getStripeDTO()); } return Result.success(bankVO); } catch (Exception e) { log.error("stripe银行接口处理失败", e); throw new RuntimeException("处理失败: " + e.getMessage()); } }
//firstdata银行接口(批量)
@Override public Result firstdataAuto(BankDTO bankDTO) { // 获取需要处理的订单号列表
List<String> orderNoList = cashCollectionMapper.selectFirstdataList();
// 存储处理结果的列表
List<Result> results = new ArrayList<>();
// 对每个订单执行getFirstdata方法
for (String orderNo : orderNoList) { // 创建一个新的BankDTO实例,设置订单号
BankDTO dto = new BankDTO(); dto.setOrderNo(orderNo);
// 调用getFirstdata方法处理单个订单
Result result = getFirstdata(dto); results.add(result); }
// 返回处理结果列表
return Result.success(results); }
//firstdata银行接口(单个)
@Override public Result getFirstdata(BankDTO bankDTO) { try { CashCollection cashCollection = cashCollectionMapper.selectByBankCode(bankDTO.getOrderNo()); if (cashCollection == null) { return Result.error("金币系统当前日期 " + " 该银行订单号 " + bankDTO.getOrderNo() + " 未查到"); } // 获取签名参数
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<String> entity = new HttpEntity<>(headers);
ResponseEntity<String> response = restTemplate.exchange( url, HttpMethod.GET, entity, String.class );
// 解析响应数据
// API返回的是对象格式,需要先解析为JSONObject
JSONObject jsonObject = JSON.parseObject(response.getBody());
// 创建BankVO对象并设置数据
BankVO bankVO = new BankVO(); List<String> 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);
// 根据要求设置amount为永久金币×100
Integer amount = cashCollection.getPermanentGold(); firstdataDTO.setAmount(amount);
// 根据国家计算fee
double feeValue; if ("Singapore".equals(country)) { // 新加坡:amount的值×百分之2.8加上20保留整数四舍五入
feeValue = Math.round(amount * 0.028 + 20); } else { // 其他国家:amount的值×百分之3加20
feeValue = Math.round(amount * 0.03 + 20); } firstdataDTO.setFee((int) feeValue);
// net的值为amount减去fee
firstdataDTO.setNet(amount - (int) feeValue);
// 将firstdataDTO存入bankVO
bankVO.setFirstdataDTO(firstdataDTO);
// 创建一个简单的Map来存储提取的数据
Map<String, Object> extractedData = new HashMap<>(); extractedData.put("country", country); extractedData.put("orderId", orderId); extractedData.put("currency", currency); extractedData.put("total", total); extractedData.put("amount", amount); extractedData.put("fee", (int) feeValue); extractedData.put("net", amount - (int) feeValue); extractedData.put("success", true); // 添加成功标识
// 将提取的数据转换为JSON字符串并添加到message列表
message.add(JSON.toJSONString(extractedData, true));
// 将message存入bankVO
bankVO.setMessage(message);
cashCollectionMapper.updateByGoldCoinOrderCodeByFirstdata(bankVO.getFirstdataDTO());
return Result.success(bankVO); } else { // 没有数据时也添加失败标识
Map<String, Object> 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<String> message = new ArrayList<>(); Map<String, Object> 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()); } }
//IPAY银行接口(批量)
@Override public Result ipayAuto(BankDTO bankDTO) { // 获取需要处理的订单号列表
List<CashCollection> cashCollections = cashCollectionMapper.selectIpayList(); BankVO bankVO = new BankVO(); List<String> message = new ArrayList<>(); // 对每个订单执行getFirstdata方法
for (CashCollection cashCollection : cashCollections) { // 创建一个新的BankDTO实例,设置订单号
Ipay88DTO ipay88DTO = new Ipay88DTO(); ipay88DTO.setOrderNo(cashCollection.getOrderCode());
// 将double先转为int再转为string
double amountDouble = cashCollection.getPermanentGold() * 3.18; int amountInt = (int) amountDouble; ipay88DTO.setAmount(String.valueOf(amountInt));
double feeDouble = cashCollection.getPermanentGold() * 3.18 * 0.0085; int feeInt = (int) feeDouble; ipay88DTO.setFee(String.valueOf(feeInt));
double netDouble = cashCollection.getPermanentGold() * 3.18 - cashCollection.getPermanentGold() * 3.18 * 0.0085; int netInt = (int) netDouble; ipay88DTO.setNet(String.valueOf(netInt)); cashCollectionMapper.updateByGoldCoinOrderCodeByIpay88(ipay88DTO); // 构建成功消息
Map<String, Object> successData = new HashMap<>(); successData.put("success", true); successData.put("orderNo", ipay88DTO.getOrderNo()); successData.put("amount", ipay88DTO.getAmount()); successData.put("fee", ipay88DTO.getFee()); successData.put("net", ipay88DTO.getNet()); message.add(JSON.toJSONString(successData, true)); }
// 将message存入bankVO
bankVO.setMessage(message);
// 返回处理结果列表
return Result.success(bankVO); }
// 银行自动处理接口(每天早上6点执行)
@Scheduled(cron = "0 53 10 * * ?") @Override public Result bankAuto() { try { // 生成昨天的日期,格式为yyyyMMdd
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd"); LocalDate sevenDayAgo = LocalDate.now().minusDays(7); String sevenDayAgoStr = sevenDayAgo.format(formatter); LocalDate sixDayAgo = LocalDate.now().minusDays(6); String sixDayAgoStr = sixDayAgo.format(formatter); LocalDate fiveDayAgo = LocalDate.now().minusDays(5); String fiveDayAgoStr = fiveDayAgo.format(formatter); LocalDate fourDayAgo = LocalDate.now().minusDays(4); String fourDayAgoStr = fourDayAgo.format(formatter); LocalDate threeDayAgo = LocalDate.now().minusDays(3); String threeDayAgoStr = threeDayAgo.format(formatter); LocalDate twoDayAgo = LocalDate.now().minusDays(2); String twoDayAgoStr = twoDayAgo.format(formatter); LocalDate oneDayAgo = LocalDate.now().minusDays(1); String oneDayAgoStr = oneDayAgo.format(formatter); LocalDate today = LocalDate.now(); String todayStr = today.format(formatter); // 创建BankDTO实例并设置时间
BankDTO dto = new BankDTO();
dto.setStartTime(fiveDayAgoStr); dto.setEndTime(todayStr); dto.setTime(sixDayAgoStr); dto.setSum(1000);
// 依次调用各个自动处理方法
Result paymentResult = paymentAuto(dto); Result stripeResult = stripeAuto(dto); Result firstdataResult = firstdataAuto(dto); Result ipayResult = ipayAuto(dto);
// 创建响应VO对象并收集处理结果
BankVO bankVO = new BankVO(); List<String> messages = new ArrayList<>();
// 收集各方法的处理结果信息
messages.add("Payment Auto Result: " + (paymentResult != null ? paymentResult.toString() : "null")); messages.add("Stripe Auto Result: " + (stripeResult != null ? stripeResult.toString() : "null")); messages.add("Firstdata Auto Result: " + (firstdataResult != null ? firstdataResult.toString() : "null")); messages.add("Ipay Auto Result: " + (ipayResult != null ? ipayResult.toString() : "null"));
bankVO.setMessage(messages);
return Result.success(bankVO); } catch (Exception e) { log.error("bankAuto执行失败", e); return Result.error("bankAuto执行失败: " + 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) */ private String buildQueryString(Map<String, String> params) { StringBuilder sb = new StringBuilder(); for (Map.Entry<String, String> 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(); }
}
|