diff --git a/pom.xml b/pom.xml index 1eef049..a329465 100644 --- a/pom.xml +++ b/pom.xml @@ -166,6 +166,21 @@ jaxb-api 2.3.1 + + com.stripe + stripe-java + 30.0.0 + + + org.apache.httpcomponents.client5 + httpclient5 + 5.3.1 + + + com.alibaba + fastjson + 1.2.83 + diff --git a/src/main/java/com/example/demo/DemoApplicationBank.java b/src/main/java/com/example/demo/DemoApplicationBank.java new file mode 100644 index 0000000..7de0065 --- /dev/null +++ b/src/main/java/com/example/demo/DemoApplicationBank.java @@ -0,0 +1,28 @@ +package com.example.demo; + + + +import org.mybatis.spring.annotation.MapperScan; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.scheduling.annotation.EnableScheduling; + +@EnableScheduling // 启用调度功能 +@SpringBootApplication +@MapperScan(basePackages = "com.example.demo.mapper.coin", sqlSessionTemplateRef = "mysql1SqlSessionTemplate") +@MapperScan(basePackages = "com.example.demo.mapper.bean", sqlSessionTemplateRef = "mysql2SqlSessionTemplate") +@MapperScan(basePackages = "com.example.demo.mapper.pay", sqlSessionTemplateRef = "mysql3SqlSessionTemplate") +@MapperScan(basePackages = "com.example.demo.mapper.cms", sqlSessionTemplateRef = "mysql4SqlSessionTemplate") +@MapperScan(basePackages = "com.example.demo.mapper.live", sqlSessionTemplateRef = "mysql5SqlSessionTemplate") +@MapperScan(basePackages = "com.example.demo.mapper.sqlserver", sqlSessionTemplateRef = "sqlserver1SqlSessionTemplate") +@MapperScan(basePackages = "com.example.demo.mapper.cash", sqlSessionTemplateRef = "mysql1SqlSessionTemplate") +public class DemoApplicationBank { + + public static void main(String[] args) { + System.setProperty("https.protocols", "TLSv1,TLSv1.2,TLSv1.3"); + // 设置客户端协议版本 + System.setProperty("jdk.tls.client.protocols", "TLSv1,TLSv1.2,TLSv1.3"); + SpringApplication.run(DemoApplication.class, args); + } + +} diff --git a/src/main/java/com/example/demo/bank/Server.java b/src/main/java/com/example/demo/bank/Server.java new file mode 100644 index 0000000..257e03c --- /dev/null +++ b/src/main/java/com/example/demo/bank/Server.java @@ -0,0 +1,23 @@ +package com.example.demo.bank; + +import com.stripe.Stripe; +import com.stripe.exception.StripeException; +import com.stripe.model.*; +import com.stripe.param.BalanceTransactionListParams; +import com.stripe.param.PaymentIntentSearchParams; +import com.stripe.param.ProductCreateParams; +import com.stripe.param.PriceCreateParams; + +public class Server { + public static void main(String[] args) throws StripeException { + Stripe.apiKey = "sk_test_51SKwgEQqF1eV5j2cyHz7uZ28OsPHzt9nXv1DCOmr4buFHpGhhgmskCz2XOxtCbbQMZIEkELTWIlMgZWcK6PeflZj00nRijQkLx"; + + BalanceTransactionListParams params = + BalanceTransactionListParams.builder().setLimit(3L).build(); + BalanceTransactionCollection balanceTransactions = BalanceTransaction.list(params); + System.out.println(balanceTransactions); + BalanceTransaction balanceTransaction = + BalanceTransaction.retrieve("txn_3SKxVWQqF1eV5j2c07IJegQv"); + System.out.println(balanceTransaction); + } +} \ No newline at end of file diff --git a/src/main/java/com/example/demo/config/AppConfig.java b/src/main/java/com/example/demo/config/AppConfig.java index a50aa5b..3c2f690 100644 --- a/src/main/java/com/example/demo/config/AppConfig.java +++ b/src/main/java/com/example/demo/config/AppConfig.java @@ -2,16 +2,60 @@ package com.example.demo.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.http.client.ClientHttpRequestFactory; +import org.springframework.http.client.SimpleClientHttpRequestFactory; import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; import org.springframework.web.client.RestTemplate; +import javax.net.ssl.*; +import java.security.KeyManagementException; +import java.security.NoSuchAlgorithmException; +import java.security.cert.X509Certificate; + @Configuration public class AppConfig { @Bean - public RestTemplate restTemplate() { + public RestTemplate restTemplate() throws NoSuchAlgorithmException, KeyManagementException { RestTemplate restTemplate = new RestTemplate(); + + // 配置SSL支持 + restTemplate.setRequestFactory(createSSLRequestFactory()); + restTemplate.getMessageConverters().add(new MappingJackson2HttpMessageConverter()); return restTemplate; } + + /** + * 创建支持SSL的HTTP请求工厂 + */ + private ClientHttpRequestFactory createSSLRequestFactory() throws NoSuchAlgorithmException, KeyManagementException { + TrustManager[] trustAllCerts = new TrustManager[]{ + new X509TrustManager() { + public X509Certificate[] getAcceptedIssuers() { + return new X509Certificate[0]; + } + public void checkClientTrusted(X509Certificate[] certs, String authType) { + } + public void checkServerTrusted(X509Certificate[] certs, String authType) { + } + } + }; + + SSLContext sslContext = SSLContext.getInstance("TLS"); + sslContext.init(null, trustAllCerts, new java.security.SecureRandom()); + + HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory()); + + // 创建主机名验证器,信任所有主机 + HostnameVerifier allHostsValid = (hostname, session) -> true; + HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid); + + SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory(); + factory.setConnectTimeout(30000); // 30秒连接超时 + factory.setReadTimeout(60000); // 60秒读取超时 + + return factory; + } } + 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..1535bcf --- /dev/null +++ b/src/main/java/com/example/demo/controller/cash/BankController.java @@ -0,0 +1,44 @@ +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.Bank; +import com.example.demo.domain.vo.coin.AuditRequest; +import com.example.demo.domain.vo.coin.Result; +import com.example.demo.service.cash.BankService; +import com.example.demo.service.cash.CashAuditService; +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 BankController + * @description: + * @author: Double + * @create: 2025−10-27 10:50 + * @Version 1.0 + **/ + +@RestController +@RequestMapping("/admin/bank") +@RequiredArgsConstructor +@Slf4j +@CrossOrigin +public class BankController { + + @Autowired + private BankService bankService; + + //payment银行接口 + @Log("payment银行接口") + @PostMapping("/payment") + public Result payment(@RequestBody Bank bank){ + try { + BankDTO bankDTO = bankService.payment(bank); + return Result.success(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..fb7af48 --- /dev/null +++ b/src/main/java/com/example/demo/domain/DTO/BankDTO.java @@ -0,0 +1,21 @@ +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−10-27 11:16 + * @Version 1.0 + **/ + +@Data +@NoArgsConstructor +public class BankDTO { + private List paymentDTOList; +} 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..09073dd --- /dev/null +++ b/src/main/java/com/example/demo/domain/DTO/PaymentDTO.java @@ -0,0 +1,30 @@ +package com.example.demo.domain.DTO; + +/** + * @program: gold-java + * @ClassName PaymentDTO + * @description: + * @author: Double + * @create: 2025−10-27 13:35 + * @Version 1.0 + **/ + +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@NoArgsConstructor +public class PaymentDTO { + private String type; + private String provider; + private String request_reference; + private String merchant_reference; + private String provider_reference; + private String currency; + private String order_amount; + private String charge; + private String 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/vo/cash/Bank.java b/src/main/java/com/example/demo/domain/vo/cash/Bank.java new file mode 100644 index 0000000..28bb31a --- /dev/null +++ b/src/main/java/com/example/demo/domain/vo/cash/Bank.java @@ -0,0 +1,19 @@ +package com.example.demo.domain.vo.cash; + +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @program: gold-java + * @ClassName BankDTO + * @description: + * @author: Double + * @create: 2025−10-27 11:11 + * @Version 1.0 + **/ + +@Data +@NoArgsConstructor +public class Bank { + private String time = ""; +} 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..cd5eff8 --- /dev/null +++ b/src/main/java/com/example/demo/service/cash/BankService.java @@ -0,0 +1,18 @@ +package com.example.demo.service.cash; + + +import com.example.demo.domain.DTO.BankDTO; +import com.example.demo.domain.vo.cash.Bank; + +/** + * @program: gold-java + * @ClassName BankService + * @description: + * @author: Double + * @create: 2025−10-27 11:17 + * @Version 1.0 + **/ + +public interface BankService { + BankDTO payment(Bank bank); +} 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..a531d4d --- /dev/null +++ b/src/main/java/com/example/demo/serviceImpl/cash/BankServiceImpl.java @@ -0,0 +1,137 @@ +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.vo.cash.Bank; +import com.example.demo.service.cash.BankService; +import lombok.extern.slf4j.Slf4j; +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.util.List; +import java.util.Map; +import java.util.TreeMap; + +/** + * @program: gold-java + * @ClassName BankServiceImpl + * @description: + * @author: Double + * @create: 2025−10-27 11:18 + * @Version 1.0 + **/ + +@Service +@Slf4j +public class BankServiceImpl implements BankService { + // 第三方API地址 + private static final String API_URL = "https://gateway.pa-sys.com/v1.1/reconciliation/519e26b2-8145-418c-b3e7-c1e88e52b946/settlement"; + // 签名密钥(与PHP中的$secret一致) + private static final String SECRET = "8987d1b8-1d82-4b15-af06-828d0b12076f"; + + // 注入RestTemplate用于HTTP请求(需在Spring配置类中定义) + private final RestTemplate restTemplate; + + public BankServiceImpl(RestTemplate restTemplate) { + this.restTemplate = restTemplate; + } + + @Override + public BankDTO payment(Bank bank) { + try { + // 1. 准备参数 + String settlementDate = bank.getTime(); // 从Bank对象获取time作为settlement_date + String network = "FPS"; // 固定值 + + // 2. 生成签名(复刻PHP逻辑,此处无需修改) + 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 + BankDTO bankDTO = new BankDTO(); + List paymentDTOList = transactions.toJavaList(PaymentDTO.class); + bankDTO.setPaymentDTOList(paymentDTOList); + + return bankDTO; + } else { + throw new RuntimeException("API请求失败,状态码: " + response.getStatusCodeValue()); + } + + } catch (Exception e) { + log.error("payment银行接口处理失败", e); + throw new RuntimeException("处理失败: " + e.getMessage()); + } + } + /** + * 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(); + } +}