Browse Source

11月23日银行接口

sunjiabei/feature-20251021102635-银行接口
sunjiabei 2 days ago
parent
commit
2eff7c71ad
  1. 106
      src/main/java/com/example/demo/controller/cash/Bank.java
  2. 4
      src/main/java/com/example/demo/controller/cash/BankController.java
  3. 2
      src/main/java/com/example/demo/domain/DTO/BankDTO.java
  4. 7
      src/main/java/com/example/demo/domain/DTO/PaymentDTO.java
  5. 6
      src/main/java/com/example/demo/domain/DTO/StripeDTO.java
  6. 1
      src/main/java/com/example/demo/domain/vo/cash/BankVO.java
  7. 5
      src/main/java/com/example/demo/mapper/cash/CashCollectionMapper.java
  8. 3
      src/main/java/com/example/demo/service/cash/BankService.java
  9. 235
      src/main/java/com/example/demo/serviceImpl/cash/BankServiceImpl.java
  10. 15
      src/main/resources/cashMapper/CashCollectionMapper.xml

106
src/main/java/com/example/demo/controller/cash/Bank.java

@ -24,63 +24,65 @@ public class Bank {
public static void main(String[] args) throws StripeException {
Stripe.apiKey = "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";
// List<Charge> 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<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) {
// System.err.println("Stripe 分页查询失败:" + e.getMessage());
// break; // 异常时停止查询返回已获取的数据
// }
//
// } while (startingAfter != null);
// System.out.println(allCharges);
//
// // 3. 封装DTO
// List<StripeDTO> 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());
List<Charge> 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<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) {
System.err.println("Stripe 分页查询失败:" + e.getMessage());
break; // 异常时停止查询返回已获取的数据
}
} while (startingAfter != null);
System.out.println(allCharges);
// 3. 封装DTO
List<StripeDTO> 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");
BalanceTransaction.retrieve("txn_3SVl0sJHMNYcqBc01M0HJM72");
System.out.println(balanceTransaction);
}
}

4
src/main/java/com/example/demo/controller/cash/BankController.java

@ -55,7 +55,7 @@ public class BankController {
}
}
//payment银行接口(批量)
//stripe银行接口(批量)
@Log("stripe银行接口(批量)")
@PostMapping("/stripeAuto")
public Result stripeAuto(@RequestBody BankDTO bankDTO) {
@ -66,7 +66,7 @@ public class BankController {
}
}
//payment银行接口(单个)
//stripe银行接口(单个)
@Log("stripe银行接口(单个)")
@PostMapping("/getStripe")
public Result getStripe(@RequestBody BankDTO bankDTO) {

2
src/main/java/com/example/demo/domain/DTO/BankDTO.java

@ -21,4 +21,6 @@ public class BankDTO {
private String time = "";
//订单号
private String orderNo = "";
//交易ID
private String transactionId = "";
}

7
src/main/java/com/example/demo/domain/DTO/PaymentDTO.java

@ -13,6 +13,7 @@ import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.math.BigDecimal;
import java.util.Date;
@Data
@ -27,9 +28,9 @@ public class PaymentDTO {
private String merchant_reference;
private String provider_reference;
private String currency;
private Double order_amount;
private Double charge;
private Double net_amount;
private BigDecimal order_amount;
private BigDecimal charge;
private BigDecimal net_amount;
private String status;
private String created_time;
private String completed_time;

6
src/main/java/com/example/demo/domain/DTO/StripeDTO.java

@ -10,9 +10,12 @@ package com.example.demo.domain.DTO;
**/
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Date;
@Data
@NoArgsConstructor
public class StripeDTO {
@ -22,4 +25,7 @@ public class StripeDTO {
private String amount;//金额
private String fee;//手续费
private String net;//净额
private String chargeCurrency;//收款币种
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "Asia/Shanghai")
private Date availableOn;
}

1
src/main/java/com/example/demo/domain/vo/cash/BankVO.java

@ -23,4 +23,5 @@ public class BankVO {
private PaymentDTO paymentDTO;
private List<StripeDTO> stripeDTOList;
private StripeDTO stripeDTO;
private List<String> message;
}

5
src/main/java/com/example/demo/mapper/cash/CashCollectionMapper.java

@ -1,6 +1,8 @@
package com.example.demo.mapper.cash;
//import com.example.demo.domain.DTO.PaymentDTO;
import com.example.demo.domain.DTO.PaymentDTO;
import com.example.demo.domain.DTO.StripeDTO;
import com.example.demo.domain.entity.CashRecord;
import com.example.demo.domain.entity.GOrder;
import com.example.demo.domain.entity.RechargeActivity;
@ -61,5 +63,6 @@ public interface CashCollectionMapper {
//根据glodcoin订单号查询收款订单
CashCollection selectByGoldCoinOrderCode(String orderNo);
// void updateByGoldCoinOrderCode(PaymentDTO paymentDTO);
void updateByGoldCoinOrderCodeByPayment(PaymentDTO paymentDTO);
void updateByGoldCoinOrderCodeByStripe(StripeDTO stripeDTO);
}

3
src/main/java/com/example/demo/service/cash/BankService.java

@ -4,6 +4,7 @@ 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;
import com.stripe.exception.StripeException;
/**
* @program: gold-java
@ -25,5 +26,5 @@ public interface BankService {
Result stripeAuto(BankDTO bankDTO);
//stripe银行接口(单个)
Result getStripe(BankDTO bankDTO);
Result getStripe(BankDTO bankDTO) throws StripeException;
}

235
src/main/java/com/example/demo/serviceImpl/cash/BankServiceImpl.java

@ -6,11 +6,18 @@ 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.DTO.StripeDTO;
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.*;
@ -19,14 +26,12 @@ import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;
import java.math.BigDecimal;
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;
import java.util.*;
/**
* @program: gold-java
@ -113,9 +118,9 @@ public class BankServiceImpl implements BankService {
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.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("2");
bankVO.setPaymentDTO(paymentDTO);
found = true;
@ -133,9 +138,8 @@ public class BankServiceImpl implements BankService {
CashCollection cashCollection = cashCollectionMapper.selectByGoldCoinOrderCode(orderNo);
if (cashCollection == null) {
return Result.error("金币系统当前日期 " + settlementDate + " 该订单号 " + orderNo + " 未查到");
}
else {
cashCollectionMapper.updateByGoldCoinOrderCode(bankVO.getPaymentDTO());
} else {
cashCollectionMapper.updateByGoldCoinOrderCodeByPayment(bankVO.getPaymentDTO());
}
return Result.success(bankVO);
} else {
@ -191,10 +195,50 @@ public class BankServiceImpl implements BankService {
JSONObject jsonObject = JSON.parseObject(responseBody);
JSONArray transactions = jsonObject.getJSONObject("payload").getJSONArray("transactions");
// 创建BankDTO并设置paymentDTOList
// 创建BankVO并设置paymentDTOList
BankVO bankVO = new BankVO();
List<PaymentDTO> paymentDTOList = transactions.toJavaList(PaymentDTO.class);
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("2");
// 获取订单号
String orderNo = paymentDTO.getMerchant_reference();
// 查询金币系统中的订单
CashCollection cashCollection = cashCollectionMapper.selectByGoldCoinOrderCode(orderNo);
if (cashCollection != null) {
// 更新金币系统中的订单信息
cashCollectionMapper.updateByGoldCoinOrderCodeByPayment(paymentDTO);
processedPayments.add(paymentDTO);
log.info("成功处理订单: {}", orderNo);
messages.add("成功处理订单: " + orderNo);
} else {
log.warn("金币系统中未找到订单: {}", orderNo);
messages.add("金币系统中未找到订单: " + orderNo);
}
} catch (Exception e) {
log.error("处理单个支付记录时发生错误: {}", paymentDTO.getMerchant_reference(), e);
}
}
// 设置处理成功的支付列表
bankVO.setPaymentDTOList(processedPayments);
bankVO.setMessage(messages);
return Result.success(bankVO);
} else {
@ -210,44 +254,157 @@ public class BankServiceImpl implements BankService {
//stripe银行接口(批量)
@Override
public Result stripeAuto(BankDTO bankDTO) {
return Result.success(bankDTO);
return Result.success(bankDTO);
}
//stripe银行接口(单个)
@Override
public Result getStripe(BankDTO bankDTO) {
return Result.success(bankDTO);
}
public Result getStripe(BankDTO bankDTO) throws StripeException {
try {
// 设置Stripe API密钥
Stripe.apiKey = "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";
// 方式一通过订单号查找最近数据
String orderNo = bankDTO.getOrderNo();
/**
* 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("&");
if (orderNo == null || orderNo.isEmpty()) {
return Result.error("订单号为空");
}
// 从Stripe获取最近的收费记录最多200条
List<Charge> 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<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;
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 + " 的支付记录");
}
sb.append(entry.getKey()).append("=").append(entry.getValue());
// 获取匹配到的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
stripeDTO.setCurrency(matchedCharge.getCurrency().toUpperCase());
stripeDTO.setAmount(String.valueOf(matchedCharge.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());
}
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);
* 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');
}
return hexStr.toString();
hexStr.append(hex);
}
return hexStr.toString();
}
}

15
src/main/resources/cashMapper/CashCollectionMapper.xml

@ -278,7 +278,7 @@
</select>
<!--根据glodcoin订单号更新收款订单-->
<update id="updateByGoldCoinOrderCode">
<update id="updateByGoldCoinOrderCodeByPayment">
update cash_record_collection
SET
received_time=#{time},
@ -290,4 +290,17 @@
order_no_status=0
where order_no=#{merchant_reference}
</update>
<!--根据glodcoin订单号更新收款订单-->
<update id="updateByGoldCoinOrderCodeByStripe">
update cash_record_collection
SET
received_time=#{availableOn},
payment_currency=#{chargeCurrency},
received_currency=#{currency},
payment_amount=#{amount},
received_amount=#{net},
handling_charge=#{fee},
order_no_status=0
where order_no=#{orderNo}
</update>
</mapper>
Loading…
Cancel
Save