skyfffire 1 hafta önce
ebeveyn
işleme
f0f42d9e3b
26 değiştirilmiş dosya ile 1484 ekleme ve 1207 silme
  1. 0 501
      src/main/java/common/utils/tl/AllinpaySDK.java
  2. 0 122
      src/main/java/common/utils/tl/HttpConnectionUtil.java
  3. 0 59
      src/main/java/common/utils/tl/SSLUtil.java
  4. 0 152
      src/main/java/common/utils/tl/SmUtil.java
  5. 0 20
      src/main/java/common/utils/tl/SybConstants.java
  6. 0 125
      src/main/java/common/utils/tl/SybPayService.java
  7. 0 228
      src/main/java/common/utils/tl/SybUtil.java
  8. 17 0
      src/main/java/common/utils/tl/annotation/IgnoreField.java
  9. 26 0
      src/main/java/common/utils/tl/constant/TestConstants.java
  10. 54 0
      src/main/java/common/utils/tl/main/H5UnionPayMain.java
  11. 31 0
      src/main/java/common/utils/tl/main/ScanqrPayMain.java
  12. 77 0
      src/main/java/common/utils/tl/main/SignMain.java
  13. 76 0
      src/main/java/common/utils/tl/restservice/ClientTlService.java
  14. 57 0
      src/main/java/common/utils/tl/restservice/ClientTlUrlService.java
  15. 82 0
      src/main/java/common/utils/tl/restservice/TlHttpService.java
  16. 114 0
      src/main/java/common/utils/tl/util/ASCIIUtils.java
  17. 70 0
      src/main/java/common/utils/tl/util/JacksonUtils.java
  18. 93 0
      src/main/java/common/utils/tl/util/RSAUtils.java
  19. 39 0
      src/main/java/common/utils/tl/util/SignUtils.java
  20. 48 0
      src/main/java/common/utils/tl/util/URLUtils.java
  21. 269 0
      src/main/java/common/utils/tl/vo/AsyncNoticeRequestVO.java
  22. 58 0
      src/main/java/common/utils/tl/vo/TlH5UnionPayRequestVO.java
  23. 142 0
      src/main/java/common/utils/tl/vo/TlScanqrPayRequestVO.java
  24. 129 0
      src/main/java/common/utils/tl/vo/TlScanqrPayResponseVO.java
  25. 63 0
      src/main/java/common/utils/tl/vo/basevo/TlBaseRequestVO.java
  26. 39 0
      src/main/java/common/utils/tl/vo/basevo/TlBaseResponseVO.java

+ 0 - 501
src/main/java/common/utils/tl/AllinpaySDK.java

@@ -1,501 +0,0 @@
-package common.utils.tl;
-
-import java.util.*;
-
-/**
- * 通联支付SDK - 使用现有工具类实现
- * 支持H5收银台支付功能
- * 
- * @author skyff
- * @date 2024
- */
-public class AllinpaySDK {
-    
-    /**
-     * H5收银台支付 - 使用现有工具类实现
-     * 
-     * @param trxamt 交易金额(分)
-     * @param reqsn 商户订单号
-     * @param body 订单标题
-     * @param remark 订单备注信息
-     * @param notify_url 服务器异步通知页面路径
-     * @param returl 页面跳转同步通知页面路径
-     * @param charset 参数字符编码集
-     * @param validtime 有效时间(分钟)
-     * @param limit_pay 支付限制
-     * @param truename 付款人真实姓名
-     * @param idno 证件号
-     * @return 支付结果
-     */
-    public static PaymentResult h5Pay(Long trxamt, String reqsn, String body, String remark, 
-                                     String notify_url, String returl, String charset, 
-                                     Integer validtime, String limit_pay, String truename, String idno) {
-        try {
-            // 使用HttpConnectionUtil发送H5支付请求
-            HttpConnectionUtil http = new HttpConnectionUtil(SybConstants.SYB_APIURL + "/h5unionpay/unionorder");
-            http.init();
-            
-            // 构建请求参数 - 使用与测试代码相同的逻辑
-            TreeMap<String, String> params = new TreeMap<>();
-            if (!SybUtil.isEmpty(SybConstants.SYB_ORGID)) {
-                params.put("orgid", SybConstants.SYB_ORGID);
-            }
-            params.put("cusid", SybConstants.SYB_CUSID);
-            params.put("appid", SybConstants.SYB_APPID);
-            params.put("version", SybConstants.VERSION);
-            params.put("trxamt", String.valueOf(trxamt));
-            params.put("charset", charset);
-            params.put("returl", returl);
-            params.put("notify_url", notify_url);
-            params.put("body", body);
-            params.put("remark", remark);
-            params.put("randomstr", SybUtil.getValidatecode(8));
-            params.put("signtype", SybConstants.SIGN_TYPE);
-            params.put("reqsn", reqsn);
-
-            // 添加可选参数
-            if (validtime != null) params.put("validtime", String.valueOf(validtime));
-            if (!SybUtil.isEmpty(limit_pay)) params.put("limit_pay", limit_pay);
-            if (!SybUtil.isEmpty(truename)) params.put("truename", truename);
-            if (!SybUtil.isEmpty(idno)) params.put("idno", idno);
-
-            // 生成签名 - 使用与测试代码相同的逻辑
-            String appkey = "MD5".equals(SybConstants.SIGN_TYPE) ? SybConstants.SYB_MD5_APPKEY : 
-                           "RSA".equals(SybConstants.SIGN_TYPE) ? SybConstants.SYB_RSACUSPRIKEY : 
-                           SybConstants.SYB_SM2PPRIVATEKEY;
-            
-            params.put("sign", SybUtil.unionSign(params, appkey, SybConstants.SIGN_TYPE));
-
-            // 发送请求 - 使用与测试代码相同的逻辑
-            byte[] response = http.postParams(params, true);
-            String responseStr = new String(response, "UTF-8");
-            
-            http.destory();
-
-            // 处理响应
-            Map<String, String> resultMap = SybPayService.handleResult(responseStr);
-            
-            if ("SUCCESS".equals(resultMap.get("retcode"))) {
-                String payUrl = resultMap.get("payinfo");
-                return PaymentResult.success(payUrl, "H5支付链接生成成功");
-            } else {
-                return PaymentResult.error("H5支付失败: " + resultMap.get("retmsg"));
-            }
-
-        } catch (Exception e) {
-            e.printStackTrace();
-            return PaymentResult.error("H5支付请求失败: " + e.getMessage());
-        }
-    }
-    
-    /**
-     * 查询支付结果 - 使用现有工具类实现
-     * 
-     * @param reqsn 商户交易单号
-     * @return 查询结果
-     */
-    public static QueryResult queryPayment(String reqsn) {
-        try {
-            // 直接使用SybPayService的query方法
-            SybPayService payService = new SybPayService();
-            Map<String, String> resultMap = payService.query(reqsn, null);
-            
-            if ("SUCCESS".equals(resultMap.get("retcode"))) {
-                String trxstatus = resultMap.get("trxstatus");
-                String trxid = resultMap.get("trxid");
-                String trxamt = resultMap.get("trxamt");
-                return QueryResult.success(trxstatus, trxid, trxamt, "查询成功");
-            } else {
-                return QueryResult.error("查询失败: " + resultMap.get("retmsg"));
-            }
-            
-        } catch (Exception e) {
-            e.printStackTrace();
-            return QueryResult.error("查询失败: " + e.getMessage());
-        }
-    }
-    
-    /**
-     * 处理异步通知 - 使用现有工具类实现
-     * 
-     * @param notifyParams 通知参数
-     * @return 处理结果
-     */
-    public static NotifyResult handleNotify(Map<String, String> notifyParams) {
-        try {
-            System.out.println("收到异步通知: " + notifyParams);
-            
-            // 验证签名
-            String sign = notifyParams.get("sign");
-            if (SybUtil.isEmpty(sign)) {
-                return NotifyResult.error("签名为空");
-            }
-            
-            // 构建验签参数
-            TreeMap<String, String> verifyParams = new TreeMap<>();
-            for (Map.Entry<String, String> entry : notifyParams.entrySet()) {
-                if (!"sign".equals(entry.getKey()) && !SybUtil.isEmpty(entry.getValue())) {
-                    verifyParams.put(entry.getKey(), entry.getValue());
-                }
-            }
-            
-            // 使用SybUtil进行签名验证
-            String appkey = getAppKey();
-            boolean verifyResult = SybUtil.validSign(verifyParams, appkey, SybConstants.SIGN_TYPE);
-            
-            if (!verifyResult) {
-                return NotifyResult.error("签名验证失败");
-            }
-            
-            // 解析通知内容
-            String reqsn = notifyParams.get("reqsn");
-            String trxstatus = notifyParams.get("trxstatus");
-            String trxid = notifyParams.get("trxid");
-            String trxamt = notifyParams.get("trxamt");
-            
-            return NotifyResult.success(reqsn, trxstatus, trxid, trxamt, "通知处理成功");
-            
-        } catch (Exception e) {
-            e.printStackTrace();
-            return NotifyResult.error("通知处理失败: " + e.getMessage());
-        }
-    }
-    
-    /**
-     * 获取签名密钥
-     */
-    private static String getAppKey() {
-        if ("RSA".equals(SybConstants.SIGN_TYPE)) {
-            return SybConstants.SYB_RSACUSPRIKEY;
-        } else if ("SM2".equals(SybConstants.SIGN_TYPE)) {
-            return SybConstants.SYB_SM2PPRIVATEKEY;
-        } else {
-            return SybConstants.SYB_MD5_APPKEY;
-        }
-    }
-    
-    /**
-     * 支付结果类
-     */
-    public static class PaymentResult {
-        private boolean success;
-        private String payUrl;
-        private String message;
-        private String errorCode;
-        
-        private PaymentResult(boolean success, String payUrl, String message, String errorCode) {
-            this.success = success;
-            this.payUrl = payUrl;
-            this.message = message;
-            this.errorCode = errorCode;
-        }
-        
-        public static PaymentResult success(String payUrl, String message) {
-            return new PaymentResult(true, payUrl, message, null);
-        }
-        
-        public static PaymentResult error(String message) {
-            return new PaymentResult(false, null, message, "ERROR");
-        }
-        
-        // Getters
-        public boolean isSuccess() { return success; }
-        public String getPayUrl() { return payUrl; }
-        public String getMessage() { return message; }
-        public String getErrorCode() { return errorCode; }
-        
-        @Override
-        public String toString() {
-            return "PaymentResult{" +
-                    "success=" + success +
-                    ", payUrl='" + payUrl + '\'' +
-                    ", message='" + message + '\'' +
-                    ", errorCode='" + errorCode + '\'' +
-                    '}';
-        }
-    }
-    
-    /**
-     * 查询结果类
-     */
-    public static class QueryResult {
-        private boolean success;
-        private String trxstatus;
-        private String trxid;
-        private String trxamt;
-        private String message;
-        private String errorCode;
-        
-        private QueryResult(boolean success, String trxstatus, String trxid, String trxamt, String message, String errorCode) {
-            this.success = success;
-            this.trxstatus = trxstatus;
-            this.trxid = trxid;
-            this.trxamt = trxamt;
-            this.message = message;
-            this.errorCode = errorCode;
-        }
-        
-        public static QueryResult success(String trxstatus, String trxid, String trxamt, String message) {
-            return new QueryResult(true, trxstatus, trxid, trxamt, message, null);
-        }
-        
-        public static QueryResult error(String message) {
-            return new QueryResult(false, null, null, null, message, "ERROR");
-        }
-        
-        // Getters
-        public boolean isSuccess() { return success; }
-        public String getTrxstatus() { return trxstatus; }
-        public String getTrxid() { return trxid; }
-        public String getTrxamt() { return trxamt; }
-        public String getMessage() { return message; }
-        public String getErrorCode() { return errorCode; }
-        
-        @Override
-        public String toString() {
-            return "QueryResult{" +
-                    "success=" + success +
-                    ", trxstatus='" + trxstatus + '\'' +
-                    ", trxid='" + trxid + '\'' +
-                    ", trxamt='" + trxamt + '\'' +
-                    ", message='" + message + '\'' +
-                    ", errorCode='" + errorCode + '\'' +
-                    '}';
-        }
-    }
-    
-    /**
-     * 通知结果类
-     */
-    public static class NotifyResult {
-        private boolean success;
-        private String reqsn;
-        private String trxstatus;
-        private String trxid;
-        private String trxamt;
-        private String message;
-        private String errorCode;
-        
-        private NotifyResult(boolean success, String reqsn, String trxstatus, String trxid, String trxamt, String message, String errorCode) {
-            this.success = success;
-            this.reqsn = reqsn;
-            this.trxstatus = trxstatus;
-            this.trxid = trxid;
-            this.trxamt = trxamt;
-            this.message = message;
-            this.errorCode = errorCode;
-        }
-        
-        public static NotifyResult success(String reqsn, String trxstatus, String trxid, String trxamt, String message) {
-            return new NotifyResult(true, reqsn, trxstatus, trxid, trxamt, message, null);
-        }
-        
-        public static NotifyResult error(String message) {
-            return new NotifyResult(false, null, null, null, null, message, "ERROR");
-        }
-        
-        // Getters
-        public boolean isSuccess() { return success; }
-        public String getReqsn() { return reqsn; }
-        public String getTrxstatus() { return trxstatus; }
-        public String getTrxid() { return trxid; }
-        public String getTrxamt() { return trxamt; }
-        public String getMessage() { return message; }
-        public String getErrorCode() { return errorCode; }
-        
-        @Override
-        public String toString() {
-            return "NotifyResult{" +
-                    "success=" + success +
-                    ", reqsn='" + reqsn + '\'' +
-                    ", trxstatus='" + trxstatus + '\'' +
-                    ", trxid='" + trxid + '\'' +
-                    ", trxamt='" + trxamt + '\'' +
-                    ", message='" + message + '\'' +
-                    ", errorCode='" + errorCode + '\'' +
-                    '}';
-        }
-    }
-    
-    /**
-     * 测试主方法 - 专门测试H5收银台支付
-     */
-    public static void main(String[] args) {
-        System.out.println("=== 通联支付H5收银台测试 ===");
-        
-        // 测试参数
-        String reqsn = "H5" + System.currentTimeMillis(); // 商户订单号
-        Long trxamt = 100L; // 1元(分为单位)
-        String body = "鲁迅的茶";
-        String remark = "鲁迅的书";
-        String notify_url = "https://dlsh-nft.com.cn/api/notify/allinpay";
-        String returl = "https://dlsh-nft.com.cn";
-        String charset = "UTF-8";
-        Integer validtime = 30; // 30分钟有效期
-        
-        System.out.println("测试订单号: " + reqsn);
-        System.out.println("交易金额: " + trxamt + "分 (1元)");
-        System.out.println("商品名称: " + body);
-        System.out.println("订单备注: " + remark);
-        System.out.println("异步通知地址: " + notify_url);
-        System.out.println("同步跳转地址: " + returl);
-        System.out.println("有效时间: " + validtime + "分钟");
-        System.out.println("商户ID: " + SybConstants.SYB_CUSID);
-        System.out.println("应用ID: " + SybConstants.SYB_APPID);
-        System.out.println("API地址: " + SybConstants.SYB_APIURL);
-        System.out.println("签名类型: " + SybConstants.SIGN_TYPE);
-        
-        try {
-            // 测试H5收银台支付
-            System.out.println("\n=== 开始H5收银台支付测试 ===");
-            PaymentResult payResult = h5Pay(trxamt, reqsn, body, remark, notify_url, 
-                                           returl, charset, validtime, null, null, null);
-            
-            System.out.println("支付结果: " + payResult);
-            
-            if (payResult.isSuccess()) {
-                System.out.println("\n✅ H5支付链接生成成功!");
-                System.out.println("支付链接: " + payResult.getPayUrl());
-                System.out.println("消息: " + payResult.getMessage());
-                System.out.println("\n请复制上述链接到浏览器中打开完成支付测试");
-                
-                // 等待一段时间后查询支付结果
-                System.out.println("\n=== 等待5秒后查询支付结果 ===");
-                try {
-                    Thread.sleep(5000); // 等待5秒
-                } catch (InterruptedException e) {
-                    Thread.currentThread().interrupt();
-                }
-                
-                QueryResult queryResult = queryPayment(reqsn);
-                System.out.println("查询结果: " + queryResult);
-                
-                if (queryResult.isSuccess()) {
-                    System.out.println("✅ 查询成功!");
-                    System.out.println("交易状态: " + queryResult.getTrxstatus());
-                    System.out.println("交易ID: " + queryResult.getTrxid());
-                    System.out.println("交易金额: " + queryResult.getTrxamt());
-                } else {
-                    System.out.println("❌ 查询失败: " + queryResult.getMessage());
-                }
-                
-            } else {
-                System.out.println("\n❌ H5支付失败!");
-                System.out.println("错误信息: " + payResult.getMessage());
-                System.out.println("错误代码: " + payResult.getErrorCode());
-            }
-            
-            // 测试异步通知处理
-            System.out.println("\n=== 测试异步通知处理 ===");
-            Map<String, String> notifyParams = new HashMap<>();
-            notifyParams.put("reqsn", reqsn);
-            notifyParams.put("trxstatus", "0000"); // 成功状态
-            notifyParams.put("trxid", "TL" + System.currentTimeMillis());
-            notifyParams.put("trxamt", String.valueOf(trxamt));
-            notifyParams.put("cusid", SybConstants.SYB_CUSID);
-            notifyParams.put("appid", SybConstants.SYB_APPID);
-            
-            // 生成模拟签名
-            TreeMap<String, String> signParams = new TreeMap<>(notifyParams);
-            String appkey = getAppKey();
-            String sign = SybUtil.unionSign(signParams, appkey, SybConstants.SIGN_TYPE);
-            notifyParams.put("sign", sign);
-            
-            NotifyResult notifyResult = handleNotify(notifyParams);
-            System.out.println("通知处理结果: " + notifyResult);
-            
-            if (notifyResult.isSuccess()) {
-                System.out.println("✅ 异步通知处理成功!");
-                System.out.println("订单号: " + notifyResult.getReqsn());
-                System.out.println("交易状态: " + notifyResult.getTrxstatus());
-                System.out.println("交易ID: " + notifyResult.getTrxid());
-            } else {
-                System.out.println("❌ 异步通知处理失败: " + notifyResult.getMessage());
-            }
-            
-        } catch (Exception e) {
-            System.out.println("\n❌ 测试过程中发生异常: " + e.getMessage());
-            e.printStackTrace();
-        }
-        
-        System.out.println("\n=== H5收银台测试完成 ===");
-        System.out.println("注意事项:");
-        System.out.println("1. 如果支付链接生成成功,请在浏览器中打开进行实际支付测试");
-        System.out.println("2. 支付完成后可以再次运行查询方法验证支付状态");
-        System.out.println("3. 异步通知需要配置真实的回调地址才能接收到通联的通知");
-        System.out.println("4. 生产环境使用时请确保配置正确的商户信息和密钥");
-        
-        /*
-        // ========== 以下为其他测试代码,暂时注释 ==========
-        
-        // 测试2: 退款操作 (需要有原始交易)
-        System.out.println("\n=== 测试退款操作 ===");
-        String refundReqsn = "REFUND" + System.currentTimeMillis();
-        String oldTrxId = "TL" + (System.currentTimeMillis() - 1000); // 模拟原交易ID
-        String oldReqsn = "OLD" + (System.currentTimeMillis() - 1000); // 模拟原订单号
-        
-        try {
-            Map<String, String> refundResult = payService.refund(trxamt, refundReqsn, oldTrxId, oldReqsn);
-            System.out.println("退款结果: " + refundResult);
-            
-            if ("SUCCESS".equals(refundResult.get("retcode"))) {
-                System.out.println("退款成功!");
-                System.out.println("退款交易ID: " + refundResult.get("trxid"));
-            } else {
-                System.out.println("退款失败: " + refundResult.get("retmsg"));
-            }
-        } catch (Exception e) {
-            System.out.println("退款异常: " + e.getMessage());
-        }
-        
-        // 测试3: 撤销操作
-        System.out.println("\n=== 测试撤销操作 ===");
-        String cancelReqsn = "CANCEL" + System.currentTimeMillis();
-        
-        try {
-            Map<String, String> cancelResult = payService.cancel(trxamt, cancelReqsn, oldTrxId, oldReqsn);
-            System.out.println("撤销结果: " + cancelResult);
-            
-            if ("SUCCESS".equals(cancelResult.get("retcode"))) {
-                System.out.println("撤销成功!");
-                System.out.println("撤销交易ID: " + cancelResult.get("trxid"));
-            } else {
-                System.out.println("撤销失败: " + cancelResult.get("retmsg"));
-            }
-        } catch (Exception e) {
-            System.out.println("撤销异常: " + e.getMessage());
-        }
-        
-        // 测试5: HTTP连接工具测试
-        System.out.println("\n=== 测试HTTP连接工具 ===");
-        try {
-            HttpConnectionUtil httpUtil = new HttpConnectionUtil(SybConstants.SYB_APIURL + "/unitorder/query");
-            httpUtil.init();
-            
-            TreeMap<String, String> httpParams = new TreeMap<>();
-            httpParams.put("appid", SybConstants.SYB_APPID);
-            httpParams.put("cusid", SybConstants.SYB_CUSID);
-            httpParams.put("version", "11");
-            httpParams.put("reqsn", reqsn);
-            httpParams.put("randomstr", SybUtil.getValidatecode(8));
-            httpParams.put("signtype", SybConstants.SIGN_TYPE);
-            
-            String appkey = "MD5".equals(SybConstants.SIGN_TYPE) ? SybConstants.SYB_MD5_APPKEY : 
-                           "RSA".equals(SybConstants.SIGN_TYPE) ? SybConstants.SYB_RSACUSPRIKEY : 
-                           SybConstants.SYB_SM2PPRIVATEKEY;
-            
-            httpParams.put("sign", SybUtil.unionSign(httpParams, appkey, SybConstants.SIGN_TYPE));
-            
-            byte[] response = httpUtil.postParams(httpParams, true);
-            String responseStr = new String(response, "UTF-8");
-            System.out.println("HTTP请求响应: " + responseStr);
-            
-            httpUtil.destory();
-            
-        } catch (Exception e) {
-            System.out.println("HTTP连接测试异常: " + e.getMessage());
-        }
-
-        */
-    }
-}

+ 0 - 122
src/main/java/common/utils/tl/HttpConnectionUtil.java

@@ -1,122 +0,0 @@
-package common.utils.tl;
-
-import java.io.ByteArrayOutputStream;
-import java.io.DataOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.HttpURLConnection;
-import java.net.URL;
-import java.net.URLConnection;
-import java.net.URLEncoder;
-import java.util.Map;
-
-import javax.net.ssl.HostnameVerifier;
-import javax.net.ssl.HttpsURLConnection;
-import javax.net.ssl.SSLSession;
-
-public class HttpConnectionUtil {
-    private HttpURLConnection conn;
-    private String connectUrl;
-
-    public HttpConnectionUtil(String connectUrl) {
-        this.connectUrl = connectUrl;
-    }
-
-    public void init() throws Exception {
-        URL url = new URL(connectUrl);
-        System.setProperty("java.protocol.handler.pkgs", "javax.net.ssl");
-        HostnameVerifier hv = new HostnameVerifier() {
-            public boolean verify(String urlHostName, SSLSession session) {
-                return urlHostName.equals(session.getPeerHost());
-            }
-        };
-        HttpsURLConnection.setDefaultHostnameVerifier(hv);
-        URLConnection conn = url.openConnection();
-        conn.setDoInput(true);
-        conn.setDoOutput(true);
-        conn.setReadTimeout(60000);
-        conn.setConnectTimeout(30000);
-        if (conn instanceof HttpsURLConnection) {
-            HttpsURLConnection httpsConn = (HttpsURLConnection) conn;
-            httpsConn.setSSLSocketFactory(SSLUtil.getInstance().getSSLSocketFactory());
-        } else if (conn instanceof HttpURLConnection) {
-            // HttpURLConnection httpConn = (HttpURLConnection) conn;
-        } else {
-            throw new Exception("不是http/https协议的url");
-        }
-        this.conn = (HttpURLConnection) conn;
-        initDefaultPost();
-    }
-
-    public void destory() {
-        try {
-            if (this.conn != null) {
-                this.conn.disconnect();
-            }
-        } catch (Exception e) {
-
-        }
-    }
-
-    private void initDefaultPost() throws Exception {
-        conn.setDoOutput(true);
-        conn.setDoInput(true);
-        conn.setRequestMethod("POST");
-        conn.setUseCaches(false);
-        conn.setInstanceFollowRedirects(true);
-        conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
-    }
-
-    public byte[] postParams(Map<String, String> params, boolean readreturn) throws IOException {
-        StringBuilder outBuf = new StringBuilder();
-        boolean isNotFirst = false;
-        for (Map.Entry<String, String> entry : params.entrySet()) {
-            if (isNotFirst)
-                outBuf.append('&');
-            isNotFirst = true;
-            outBuf
-                    .append(entry.getKey())
-                    .append('=')
-                    .append(URLEncoder.encode(entry.getValue(), "UTF-8"));
-        }
-        System.out.println("参数:" + outBuf.toString());
-        return postParams(outBuf.toString(), readreturn);
-    }
-
-    public byte[] postParams(String message, boolean readreturn) throws IOException {
-        DataOutputStream out = new DataOutputStream(conn.getOutputStream());
-        out.write(message.getBytes("UTF-8"));
-        out.close();
-        if (readreturn) {
-            return readBytesFromStream(conn.getInputStream());
-        } else {
-            return null;
-        }
-    }
-
-    public byte[] postParams(byte[] message, boolean readreturn) throws IOException {
-        DataOutputStream out = new DataOutputStream(conn.getOutputStream());
-        out.write(message);
-        out.close();
-        if (readreturn) {
-            return readBytesFromStream(conn.getInputStream());
-        } else {
-            return null;
-        }
-    }
-
-    private byte[] readBytesFromStream(InputStream is) throws IOException {
-        ByteArrayOutputStream baos = new ByteArrayOutputStream();
-        int readLen;
-        byte[] tmpBuf = new byte[4096];
-        while ((readLen = is.read(tmpBuf)) > 0)
-            baos.write(tmpBuf, 0, readLen);
-        is.close();
-        return baos.toByteArray();
-    }
-
-    public HttpURLConnection getConn() {
-        return conn;
-    }
-
-}

+ 0 - 59
src/main/java/common/utils/tl/SSLUtil.java

@@ -1,59 +0,0 @@
-package common.utils.tl;
-
-import java.security.KeyManagementException;
-import java.security.NoSuchAlgorithmException;
-import java.security.cert.CertificateException;
-import java.security.cert.X509Certificate;
-
-import javax.net.ssl.SSLContext;
-import javax.net.ssl.SSLSocketFactory;
-import javax.net.ssl.TrustManager;
-import javax.net.ssl.X509TrustManager;
-
-/**
- * SSL管理助手类
- *
- * @author Administrator
- *
- */
-public class SSLUtil implements X509TrustManager {
-    private SSLSocketFactory sslFactory = null;
-
-    private SSLUtil() {
-    }
-
-    public void checkClientTrusted(X509Certificate[] arg0, String arg1)
-            throws CertificateException {
-    }
-
-    public void checkServerTrusted(X509Certificate[] arg0, String arg1)
-            throws CertificateException {
-    }
-
-    public X509Certificate[] getAcceptedIssuers() {
-        return null;
-    }
-
-    /**
-     * 获取SSL Socket工厂
-     */
-    public SSLSocketFactory getSSLSocketFactory() {
-        return sslFactory;
-    }
-
-    private static SSLUtil _instance = null;
-
-    /**
-     * 获取SSL管理助手类实例
-     */
-    synchronized public static SSLUtil getInstance() throws NoSuchAlgorithmException, KeyManagementException {
-        if (_instance == null) {
-            _instance = new SSLUtil();
-            SSLContext sc = SSLContext.getInstance("SSLv3");
-            sc.init(null, new TrustManager[]{new SSLUtil()}, null);
-            _instance.sslFactory = sc.getSocketFactory();
-        }
-        return _instance;
-    }
-
-}

+ 0 - 152
src/main/java/common/utils/tl/SmUtil.java

@@ -1,152 +0,0 @@
-package common.utils.tl;
-
-import java.io.IOException;
-import java.math.BigInteger;
-import java.security.KeyFactory;
-import java.security.PrivateKey;
-import java.security.PublicKey;
-import java.security.SecureRandom;
-import java.security.Security;
-import java.security.Signature;
-import java.security.spec.PKCS8EncodedKeySpec;
-import java.security.spec.X509EncodedKeySpec;
-import java.util.Arrays;
-
-import org.apache.commons.codec.binary.Base64;
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Integer;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.jcajce.spec.SM2ParameterSpec;
-import org.bouncycastle.jce.provider.BouncyCastleProvider;
-import org.bouncycastle.util.encoders.Hex;
-
-public class SmUtil {
-    static {
-        Security.addProvider(new BouncyCastleProvider());
-    }
-
-    /**
-     * 算法常量:SM3withSM2
-     */
-    public static final String ALGORITHM_SM3SM2_BCPROV = "SM3withSM2";
-    private final static int SM3withSM2_RS_LEN = 32;
-
-    public static void main(String[] args) throws Exception {
-        /**商户平台分配的appid,也是签名的certid**/
-        String appid = "00000156";
-        /**商户sm2私钥,用于向通联发起请求前进行签名**/
-        String cusPrivateKey = "MIGTAgEAMBMGByqGSM49AgEGCCqBHM9VAYItBHkwdwIBAQQgjj4Rk+b0YjwO+UwXofnHf4bK+kaaY5Btkd8nMP2VimmgCgYIKoEcz1UBgi2hRANCAAQqlALW4qGC3bP1x3wo5QsKxaCMEZJ2ODTTwOQ+d8UGU7GoK/y/WMBQWf5upMnFU06p5FxGooXYYoBtldgm03hq";
-        /**商户sm2公钥,需要配置到通联商户平台**/
-        // String cusPubKey = "MFkwEwYHKoZIzj0CAQYIKoEcz1UBgi0DQgAEKpQC1uKhgt2z9cd8KOULCsWgjBGSdjg008DkPnfFBlOxqCv8v1jAUFn+bqTJxVNOqeRcRqKF2GKAbZXYJtN4ag==";
-
-        /**通联平台sm2公钥,用于请求返回或者通联通知的验签**/
-        String tlPubKey = "MFkwEwYHKoZIzj0CAQYIKoEcz1UBgi0DQgAE/BnA8BawehBtH0ksPyayo4pmzL/u1FQ2sZcqwOp6bjVqQX4tjo930QAvHZPJ2eez8sCz/RYghcqv4LvMq+kloQ==";
-
-        String blankStr = "请求待签名数据";
-        PrivateKey privkey = privKeySM2FromBase64Str(cusPrivateKey);
-        String sign = signSM3SM2RetBase64(privkey, appid, blankStr.getBytes("UTF-8"));//签名
-        System.out.println(sign);
-
-        String rspBlankStr = "返回待验签数据";//通联返回的明文
-        String rspSign = "AovBKQGUe0xuJ0ox7FgIIX+yB3DzbudgUsnNvJmDV0IdHZtU2Y8vdeUY1pd2vmPUf08hNgdkoz+4WP/D/ktOcA==";//通联返回的签名
-        PublicKey publicKey = pubKeySM2FromBase64Str(tlPubKey);
-        boolean isOk = verifySM3SM2(publicKey, "Allinpay", Base64.decodeBase64(rspSign), rspBlankStr.getBytes("UTF-8"));
-        System.out.println("验签结果:" + isOk);
-
-
-    }
-
-    /**
-     * 签名并BASE64编码-SM3WithSM2
-     */
-    public static String signSM3SM2RetBase64(final PrivateKey privateKey, String certid, final byte[] data) throws Exception {
-        return Base64.encodeBase64String(signSM3SM2(privateKey, certid, data));
-    }
-
-    /**
-     * 签名-SM3WithSM2
-     */
-    public static byte[] signSM3SM2(final PrivateKey privateKey, String certid, final byte[] data) throws Exception {
-        SM2ParameterSpec parameterSpec = new SM2ParameterSpec(certid.getBytes());
-        Signature signer = Signature.getInstance(ALGORITHM_SM3SM2_BCPROV, "BC");
-        signer.setParameter(parameterSpec);
-        signer.initSign(privateKey, new SecureRandom());
-        signer.update(data);
-        return byteAsn12BytePlain(signer.sign());
-    }
-
-    /**
-     * 验证签名-SM3WithSM2
-     */
-    public static boolean verifySM3SM2(final PublicKey publicKey, String certid, final byte[] signData, final byte[] srcData) throws Exception {
-        SM2ParameterSpec parameterSpec = new SM2ParameterSpec(certid.getBytes());
-        Signature verifier = Signature.getInstance(ALGORITHM_SM3SM2_BCPROV, "BC");
-        verifier.setParameter(parameterSpec);
-        verifier.initVerify(publicKey);
-        verifier.update(srcData);
-        return verifier.verify(bytePlain2ByteAsn1(signData));
-    }
-
-    /**
-     * 从字符串读取私钥-目前支持PKCS8(keystr为BASE64格式)
-     */
-    public static PrivateKey privKeySM2FromBase64Str(String keystr) throws Exception {
-        KeyFactory keyFactory = KeyFactory.getInstance("EC");
-        return keyFactory.generatePrivate(new PKCS8EncodedKeySpec(Base64.decodeBase64(keystr)));
-    }
-
-    /**
-     * 从字符串读取RSA公钥(keystr为BASE64格式)
-     */
-    public static PublicKey pubKeySM2FromBase64Str(String keystr) throws Exception {
-        KeyFactory keyFactory = KeyFactory.getInstance("EC");
-        return keyFactory.generatePublic(new X509EncodedKeySpec(Base64.decodeBase64(keystr)));
-    }
-
-    /**
-     * 将普通字节数组转换为ASN1字节数组 适用于SM3withSM2验签时验签明文转换
-     */
-    private static byte[] bytePlain2ByteAsn1(byte[] data) {
-        if (data.length != SM3withSM2_RS_LEN * 2) throw new RuntimeException("err data. ");
-        BigInteger r = new BigInteger(1, Arrays.copyOfRange(data, 0, SM3withSM2_RS_LEN));
-        BigInteger s = new BigInteger(1, Arrays.copyOfRange(data, SM3withSM2_RS_LEN, SM3withSM2_RS_LEN * 2));
-        ASN1EncodableVector v = new ASN1EncodableVector();
-        v.add(new ASN1Integer(r));
-        v.add(new ASN1Integer(s));
-        try {
-            return new DERSequence(v).getEncoded("DER");
-        } catch (IOException e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    /**
-     * 将ASN1字节数组转换为普通字节数组 适用于SM3withSM2签名时签名结果转换
-     */
-    private static byte[] byteAsn12BytePlain(byte[] dataAsn1) {
-        ASN1Sequence seq = ASN1Sequence.getInstance(dataAsn1);
-        byte[] r = bigIntToFixexLengthBytes(ASN1Integer.getInstance(seq.getObjectAt(0)).getValue());
-        byte[] s = bigIntToFixexLengthBytes(ASN1Integer.getInstance(seq.getObjectAt(1)).getValue());
-        byte[] result = new byte[SM3withSM2_RS_LEN * 2];
-        System.arraycopy(r, 0, result, 0, r.length);
-        System.arraycopy(s, 0, result, SM3withSM2_RS_LEN, s.length);
-        return result;
-    }
-
-    private static byte[] bigIntToFixexLengthBytes(BigInteger rOrS) {
-        byte[] rs = rOrS.toByteArray();
-        if (rs.length == SM3withSM2_RS_LEN) return rs;
-        else if (rs.length == SM3withSM2_RS_LEN + 1 && rs[0] == 0)
-            return Arrays.copyOfRange(rs, 1, SM3withSM2_RS_LEN + 1);
-        else if (rs.length < SM3withSM2_RS_LEN) {
-            byte[] result = new byte[SM3withSM2_RS_LEN];
-            Arrays.fill(result, (byte) 0);
-            System.arraycopy(rs, 0, result, SM3withSM2_RS_LEN - rs.length, rs.length);
-            return result;
-        } else {
-            throw new RuntimeException("err rs: " + Hex.toHexString(rs));
-        }
-    }
-
-}

+ 0 - 20
src/main/java/common/utils/tl/SybConstants.java

@@ -1,20 +0,0 @@
-package common.utils.tl;
-
-public class SybConstants {
-    //	正式环境测试参数
-    public static final String SYB_ORGID = "";
-    public static final String SYB_CUSID = "660222053994DLK";
-    public static final String SYB_APPID = "00375513";
-    public static final String SYB_MD5_APPKEY = "";
-    public static final String SYB_APIURL = "https://syb.allinpay.com/apiweb";
-    public static final String SYB_RSACUSPRIKEY = "";
-    public static final String SYB_RSATLPUBKEY = "";
-    
-    //生产环境
-    public static final String VERSION = "12";
-    public static final String SIGN_TYPE = "SM2";
-    //	/**商户sm2私钥,用于向通联发起请求前进行签名**/
-    public static final String SYB_SM2PPRIVATEKEY = System.getenv("TL_SM2_PRIVATE_KEY");
-    //	/**通联平台sm2公钥,用于请求返回或者通联通知的验签**/
-    public static final String SYB_SM2TLPUBKEY = System.getenv("TL_SM2_PUBLIC_KEY");
-}

+ 0 - 125
src/main/java/common/utils/tl/SybPayService.java

@@ -1,125 +0,0 @@
-package common.utils.tl;
-
-import java.util.Map;
-import java.util.TreeMap;
-
-public class SybPayService {
-
-    public Map<String, String> cancel(long trxamt, String reqsn, String oldtrxid, String oldreqsn) throws Exception {
-        HttpConnectionUtil http = new HttpConnectionUtil(SybConstants.SYB_APIURL + "/unitorder/cancel");
-        http.init();
-        TreeMap<String, String> params = new TreeMap<String, String>();
-        if (!SybUtil.isEmpty(SybConstants.SYB_ORGID))
-            params.put("orgid", SybConstants.SYB_ORGID);
-        params.put("cusid", SybConstants.SYB_CUSID);
-        params.put("appid", SybConstants.SYB_APPID);
-        params.put("version", "11");
-        params.put("trxamt", String.valueOf(trxamt));
-        params.put("reqsn", reqsn);
-        params.put("oldtrxid", oldtrxid);
-        params.put("oldreqsn", oldreqsn);
-        params.put("randomstr", SybUtil.getValidatecode(8));
-        params.put("signtype", SybConstants.SIGN_TYPE);
-        String appkey = "";
-        if (SybConstants.SIGN_TYPE.equals("RSA"))
-            appkey = SybConstants.SYB_RSACUSPRIKEY;
-        else if (SybConstants.SIGN_TYPE.equals("SM2"))
-            appkey = SybConstants.SYB_SM2PPRIVATEKEY;
-        else
-            appkey = SybConstants.SYB_MD5_APPKEY;
-        params.put("sign", SybUtil.unionSign(params, appkey, SybConstants.SIGN_TYPE));
-        byte[] bys = http.postParams(params, true);
-        String result = new String(bys, "UTF-8");
-        Map<String, String> map = handleResult(result);
-        return map;
-    }
-
-    public Map<String, String> refund(long trxamt, String reqsn, String oldtrxid, String oldreqsn) throws Exception {
-        HttpConnectionUtil http = new HttpConnectionUtil(SybConstants.SYB_APIURL + "/unitorder/refund");
-        http.init();
-        TreeMap<String, String> params = new TreeMap<String, String>();
-        if (!SybUtil.isEmpty(SybConstants.SYB_ORGID))
-            params.put("orgid", SybConstants.SYB_ORGID);
-        params.put("cusid", SybConstants.SYB_CUSID);
-        params.put("appid", SybConstants.SYB_APPID);
-        params.put("version", "11");
-        params.put("trxamt", String.valueOf(trxamt));
-        params.put("reqsn", reqsn);
-        params.put("oldreqsn", oldreqsn);
-        params.put("oldtrxid", oldtrxid);
-        params.put("randomstr", SybUtil.getValidatecode(8));
-        params.put("signtype", SybConstants.SIGN_TYPE);
-        String appkey = "";
-        if (SybConstants.SIGN_TYPE.equals("RSA"))
-            appkey = SybConstants.SYB_RSACUSPRIKEY;
-        else if (SybConstants.SIGN_TYPE.equals("SM2"))
-            appkey = SybConstants.SYB_SM2PPRIVATEKEY;
-        else
-            appkey = SybConstants.SYB_MD5_APPKEY;
-        params.put("sign", SybUtil.unionSign(params, appkey, SybConstants.SIGN_TYPE));
-        byte[] bys = http.postParams(params, true);
-        String result = new String(bys, "UTF-8");
-        Map<String, String> map = handleResult(result);
-        return map;
-    }
-
-    public Map<String, String> query(String reqsn, String trxid) throws Exception {
-        HttpConnectionUtil http = new HttpConnectionUtil(SybConstants.SYB_APIURL + "/unitorder/query");
-        http.init();
-        TreeMap<String, String> params = new TreeMap<String, String>();
-        if (!SybUtil.isEmpty(SybConstants.SYB_ORGID))
-            params.put("orgid", SybConstants.SYB_ORGID);
-        params.put("cusid", SybConstants.SYB_CUSID);
-        params.put("appid", SybConstants.SYB_APPID);
-        params.put("version", "11");
-        params.put("reqsn", reqsn);
-        params.put("trxid", trxid);
-        params.put("randomstr", SybUtil.getValidatecode(8));
-        params.put("signtype", SybConstants.SIGN_TYPE);
-        String appkey = "";
-        if (SybConstants.SIGN_TYPE.equals("RSA"))
-            appkey = SybConstants.SYB_RSACUSPRIKEY;
-        else if (SybConstants.SIGN_TYPE.equals("SM2"))
-            appkey = SybConstants.SYB_SM2PPRIVATEKEY;
-        else
-            appkey = SybConstants.SYB_MD5_APPKEY;
-        params.put("sign", SybUtil.unionSign(params, appkey, SybConstants.SIGN_TYPE));
-        byte[] bys = http.postParams(params, true);
-        String result = new String(bys, "UTF-8");
-        Map<String, String> map = handleResult(result);
-        return map;
-    }
-
-
-    public static Map<String, String> handleResult(String result) throws Exception {
-        System.out.println("ret:" + result);
-        @SuppressWarnings("unchecked")
-        Map<String, String> map = SybUtil.json2Obj(result, Map.class);
-        if (map == null) {
-            throw new Exception("返回数据错误");
-        }
-        if ("SUCCESS".equals(map.get("retcode"))) {
-            TreeMap<String, String> tmap = new TreeMap<>();
-            tmap.putAll(map);
-            String appkey;
-            if (SybConstants.SIGN_TYPE.equals("RSA")) {
-                appkey = SybConstants.SYB_RSATLPUBKEY;
-            } else if (SybConstants.SIGN_TYPE.equals("SM2")) {
-                appkey = SybConstants.SYB_SM2TLPUBKEY;
-            } else {
-                appkey = SybConstants.SYB_MD5_APPKEY;
-            }
-            if (SybUtil.validSign(tmap, appkey, SybConstants.SIGN_TYPE)) {
-                System.out.println("签名成功");
-                return map;
-            } else {
-                throw new Exception("验证签名失败");
-            }
-        } else {
-            Object retmsg = map.get("retmsg");
-            throw new Exception(retmsg != null ? retmsg.toString() : "未知错误");
-        }
-    }
-
-
-}

+ 0 - 228
src/main/java/common/utils/tl/SybUtil.java

@@ -1,228 +0,0 @@
-package common.utils.tl;
-
-import java.security.KeyFactory;
-import java.security.MessageDigest;
-import java.security.NoSuchAlgorithmException;
-import java.security.PrivateKey;
-import java.security.PublicKey;
-import java.security.spec.PKCS8EncodedKeySpec;
-import java.security.spec.X509EncodedKeySpec;
-import java.util.Map;
-import java.util.Random;
-import java.util.TreeMap;
-
-import org.apache.commons.codec.binary.Base64;
-import cn.hutool.json.JSONUtil;
-
-public class SybUtil {
-    /**
-     * js转化为实体
-     *
-     * @param <T>
-     * @param jsonstr
-     * @param cls
-     * @return
-     */
-    public static <T> T json2Obj(String jsonstr, Class<T> cls) {
-        return JSONUtil.toBean(jsonstr, cls);
-    }
-
-    /**
-     * md5
-     *
-     * @param b
-     * @return
-     */
-    public static String md5(byte[] b) {
-        try {
-            MessageDigest md = MessageDigest.getInstance("MD5");
-            md.reset();
-            md.update(b);
-            byte[] hash = md.digest();
-            StringBuffer outStrBuf = new StringBuffer(32);
-            for (int i = 0; i < hash.length; i++) {
-                int v = hash[i] & 0xFF;
-                if (v < 16) {
-                    outStrBuf.append('0');
-                }
-                outStrBuf.append(Integer.toString(v, 16).toLowerCase());
-            }
-            return outStrBuf.toString();
-        } catch (NoSuchAlgorithmException e) {
-            e.printStackTrace();
-            return new String(b);
-        }
-    }
-
-    /**
-     * 判断字符串是否为空
-     *
-     * @param s
-     * @return
-     */
-    public static boolean isEmpty(String s) {
-        if (s == null || "".equals(s.trim()))
-            return true;
-        return false;
-    }
-
-    /**
-     * 生成随机码
-     *
-     * @param n
-     * @return
-     */
-    public static String getValidatecode(int n) {
-        Random random = new Random();
-        String sRand = "";
-        n = n == 0 ? 4 : n;// default 4
-        for (int i = 0; i < n; i++) {
-            String rand = String.valueOf(random.nextInt(10));
-            sRand += rand;
-        }
-        return sRand;
-    }
-
-
-    public static boolean validSign(TreeMap<String, String> param,
-                                    String appkey, String signType) throws Exception {
-        if (param != null && !param.isEmpty()) {
-            if (!param.containsKey("sign"))
-                return false;
-            String sign = param.remove("sign");
-            if ("MD5".equals(signType)) {// 如果是md5则需要把md5的key加入到排序
-                param.put("key", appkey);
-            }
-            StringBuilder sb = new StringBuilder();
-            for (Map.Entry<String, String> entry : param.entrySet()) {
-                if (entry.getValue() != null && entry.getValue().length() > 0) {
-                    sb.append(entry.getKey()).append("=")
-                            .append(entry.getValue()).append("&");
-                }
-            }
-            if (sb.length() > 0) {
-                sb.deleteCharAt(sb.length() - 1);
-            }
-            if ("MD5".equals(signType)) {
-                return sign.toLowerCase().equals(
-                        md5(sb.toString().getBytes("UTF-8")).toLowerCase());
-            } else if ("SM2".equals(signType)) {
-                PublicKey publicKey = SmUtil.pubKeySM2FromBase64Str(appkey);
-                return SmUtil.verifySM3SM2(publicKey, "Allinpay", Base64.decodeBase64(sign), sb.toString().getBytes("UTF-8"));
-            } else {
-                return rsaVerifyPublickey(sb.toString(), sign, appkey, "UTF-8");
-            }
-        }
-        return false;
-    }
-
-    public static boolean rsaVerifyPublickey(String content, String sign,
-                                             String publicKey, String charset) throws Exception {
-        try {
-            PublicKey pubKey = getPublicKeyFromX509("RSA",
-                    Base64.decodeBase64(publicKey.getBytes()));
-            return rsaVerifyPublickey(content, sign, pubKey, charset);
-        } catch (Exception e) {
-            e.printStackTrace();
-            throw new Exception("RSAcontent = " + content + ",sign=" + sign
-                    + ",charset = " + charset, e);
-        }
-    }
-
-    public static boolean rsaVerifyPublickey(String content, String sign,
-                                             PublicKey pubKey, String charset) throws Exception {
-        try {
-            java.security.Signature signature = java.security.Signature
-                    .getInstance("SHA1WithRSA");
-
-            signature.initVerify(pubKey);
-
-            if (charset == null || "".equals(charset)) {
-                signature.update(content.getBytes());
-            } else {
-                signature.update(content.getBytes(charset));
-            }
-
-            return signature.verify(Base64.decodeBase64(sign.getBytes()));
-        } catch (Exception e) {
-            throw e;
-        }
-    }
-
-    public static String unionSign(TreeMap<String, String> params, String appkey,
-                                   String signType) throws Exception {
-        // TODO Auto-generated method stub
-
-        params.remove("sign");
-        if ("MD5".equals(signType)) {// 如果是md5则需要把md5的key加入到排序
-            params.put("key", appkey);
-        }
-        StringBuilder sb = new StringBuilder();
-        for (Map.Entry<String, String> entry : params.entrySet()) {
-            if (entry.getValue() != null && entry.getValue().length() > 0) {
-                sb.append(entry.getKey()).append("=").append(entry.getValue())
-                        .append("&");
-            }
-        }
-        if (sb.length() > 0) {
-            sb.deleteCharAt(sb.length() - 1);
-        }
-        String sign = "";
-        if ("MD5".equals(signType)) {
-            System.out.println(sb.toString());
-            sign = md5(sb.toString().getBytes("UTF-8"));// 记得是md5编码的加签
-            params.remove("key");
-        } else if ("SM2".equals(signType)) {
-            System.out.println(sb.toString());
-            PrivateKey privkey = SmUtil.privKeySM2FromBase64Str(appkey);
-            sign = SmUtil.signSM3SM2RetBase64(privkey, params.get("appid"), sb.toString().getBytes("UTF-8"));//签名
-        } else {
-            System.out.println(sb.toString());
-            sign = rsaSign(sb.toString(), appkey, "UTF-8");
-        }
-        return sign;
-    }
-
-    public static String rsaSign(String content, String privateKey,
-                                 String charset) throws Exception {
-        PrivateKey priKey = getPrivateKeyFromPKCS8("RSA",
-                Base64.decodeBase64(privateKey.getBytes()));
-        return rsaSign(content, priKey, charset);
-    }
-
-    public static String rsaSign(String content, byte[] privateKey,
-                                 String charset) throws Exception {
-        PrivateKey priKey = getPrivateKeyFromPKCS8("RSA", privateKey);
-        return rsaSign(content, priKey, charset);
-    }
-
-    public static String rsaSign(String content, PrivateKey priKey,
-                                 String charset) throws Exception {
-        java.security.Signature signature = java.security.Signature
-                .getInstance("SHA1WithRSA");
-        signature.initSign(priKey);
-        if (charset == null || "".equals(charset)) {
-            signature.update(content.getBytes());
-        } else {
-            signature.update(content.getBytes(charset));
-        }
-        byte[] signed = signature.sign();
-
-        return new String(Base64.encodeBase64(signed));
-    }
-
-    public static PrivateKey getPrivateKeyFromPKCS8(String algorithm,
-                                                    byte[] encodedKey) throws Exception {
-
-        KeyFactory keyFactory = KeyFactory.getInstance(algorithm);
-
-        return keyFactory.generatePrivate(new PKCS8EncodedKeySpec(encodedKey));
-    }
-
-    public static PublicKey getPublicKeyFromX509(String algorithm,
-                                                 byte[] encodedKey) throws Exception {
-        KeyFactory keyFactory = KeyFactory.getInstance(algorithm);
-
-        return keyFactory.generatePublic(new X509EncodedKeySpec(encodedKey));
-    }
-}

+ 17 - 0
src/main/java/common/utils/tl/annotation/IgnoreField.java

@@ -0,0 +1,17 @@
+package common.utils.tl.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * @ClassName: IgnoreField
+ * @Description: 反射忽略字段注解
+ * @Auther: wang hong wei
+ * @Date: 2024/05/15
+ */
+@Target(ElementType.FIELD)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface IgnoreField {
+}

+ 26 - 0
src/main/java/common/utils/tl/constant/TestConstants.java

@@ -0,0 +1,26 @@
+package common.utils.tl.constant;
+
+/**
+ * @ClassName: TestConstants
+ * @Description: TestConstants
+ * @Auther: wang hong wei
+ * @Date: 2024/12/02
+ */
+public class TestConstants {
+
+    private TestConstants(){}
+
+    //测试数据
+    public static final String TRXAMT = "1";//金额 元转换为分,乘以100
+    public static final String REQSN = "12345";//流水号
+    public static final String NOTIFY_URL = null;//回调通知
+    public static final String AUTH_CODE = "";//支付码编号
+    public static final String MER_ID_CHANNEL = "990440148166000";
+    public static final String TERM_INFO = "{\"termno\":\"10001008\",\"devicetype\":\"11\"}";//根据接口文档拼接
+    public static final String ORGID = null;
+    public static final String  CUSID = null;
+    public static final String  APPID = "00000003";
+    public static final String  VERSION = "11";
+    public static final String  SIGN_TYPE = "RSA";
+    public static final String  PRIVATE_KEY = "MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDrjRCrziqLp6P/a2xMxm1G+JGOersAPq8JqSuVdXfkDOhDGYAnFV+bb+ypJCLqAydfeamt24nTN4SX2Z1mcmlfkYRugBlKIu7T/uXQKt7Hx/IwLv63TPfUwtzqRzxJ50KL6fniGZePL60RpBC+3cQ5z4LfUDZv40zm+k5VFSHwEg7+zXXFhcuzE7ZDxaCqmTBgQp6LAQ5nnZqM2ya7B6ERHuMmqMPOYTTB6giLlQmUrEqVXf0d0DfxMyXuVrJmX5F0YuMUo/AR/6rndaep3p58/t6R+Q7BplM76CfRKNHh6BZb40T3TtSz2wIpcpMeflup+TXp0FSIzz4IlOG/vZMHAgMBAAECggEASDtk7lp1f4fz6YKGnnCG2CmncRq/t46BXKQM4nM4Ra2Tl+f8/X83Z1IGL8QOFNbMvyFu4AqflC7FMU+hTeYt3Amio8QSfUKDHG1hCdnroTX2VcJDh/BJW2w6FHmtyjfpl0AzyZrxeA41s2AtZmpZHyU8S8CsQNliHr6JQNwPIS/B3/4CWlzOMVa9ONSTOWPKZXExzlB9AmypkU9lm4E6GlCbDb8tve3ikF34JD+xpHQ/DclKc6KJAmnyxeaOku5JAR621eWk8bjYVwQRvKyt/mqwI245//nvHj3f/tp1FsWxaYSiGTFU+G7cxF0OvUI4P6+1ZYNRiAdyCoKSDFgLqQKBgQD2S8K03N/J+UjJvLRUhLJEz4n+aDXzgnGgKEJl6NdpxP2fhlFBwOnz4tPJuuz8RWhOtu8E4ZLW7+D8ro+6L+GSTwMJwGr1HroSCHriW/jDWpvXsdP8l4S5n2tWca2GPs6dAkdM+brpGujelcaCL1xKiEpY+YheYFzwYWkI3MPN+wKBgQD01O1ZbnYhIujJtPDDapye8SRZeHRDtaZQ6UqKpYsBnJNUiceME4ItMAtSfip0XCUzrLL2l9CjJIRl9h7h+nv1mZN2+25a/eXx8DwR6krcj016vauoUfOm7udog/IEMsBN2+uwevroH3atdxb9TOzT0t9K7ihOd7d71GJY0VG9ZQKBgQDvhSHnLd3c17c3qXJdt2Z+kK6MYOAG3laOAFkCLnw++joEB2XCYk+ixHZeepC5jO4xjqnHv29D46iTU1enI6Vk2b4En8Hke2tM2j5XIEY+BUIFc4TK4rdKpYSHXqn4IeBgxLR+YWaqB2dr/5A7Tr+cJArZmGJMFb6Mbs7stXUePQKBgQDQnfqcoK4RsDBRZ1db/CT2nh1OC4BuDYNpIFA+8a4Psn4ro7cf2aOro2uSYCUGv1mHvZlE27mQudYDF4PbJFepv7HSyY2QBRaBYCWfUld1trnbY3C4XRRTYvBVs1BuWVxZO5KJ71CKp/y09GvnbDvEhsNzkplPu1ziK+edLMcMrQKBgHGUpj9HVgU6RBZlmMK+73lSWuBZE6HV8dpmBx5jw/SAtKP9BLHJxS3mx3/H/3lHv13KtkS2zAbKhg2G5EkTvrNp3xph15sX5GQv39ESBef0CqUDCDEXOEk86XPGUGy8wpVqno9IVY+gV54MmOTvM1j607B8YWGWQ7mkKcpYk2sH";
+}

+ 54 - 0
src/main/java/common/utils/tl/main/H5UnionPayMain.java

@@ -0,0 +1,54 @@
+package common.utils.tl.main;
+
+import common.utils.tl.restservice.ClientTlService;
+import common.utils.tl.restservice.ClientTlUrlService;
+import common.utils.tl.util.ASCIIUtils;
+import common.utils.tl.util.SignUtils;
+import common.utils.tl.vo.TlH5UnionPayRequestVO;
+
+/**
+ * @ClassName: H5UnionPayMain
+ * @Description: H5UnionPayMain
+ * @Auther: wang hong wei
+ * @Date: 2025/04/29
+ */
+public class H5UnionPayMain {
+
+    //私钥:
+    public static final String PRIVATE_KEY = "MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDrjRCrziqLp6P/a2xMxm1G+JGOersAPq8JqSuVdXfkDOhDGYAnFV+bb+ypJCLqAydfeamt24nTN4SX2Z1mcmlfkYRugBlKIu7T/uXQKt7Hx/IwLv63TPfUwtzqRzxJ50KL6fniGZePL60RpBC+3cQ5z4LfUDZv40zm+k5VFSHwEg7+zXXFhcuzE7ZDxaCqmTBgQp6LAQ5nnZqM2ya7B6ERHuMmqMPOYTTB6giLlQmUrEqVXf0d0DfxMyXuVrJmX5F0YuMUo/AR/6rndaep3p58/t6R+Q7BplM76CfRKNHh6BZb40T3TtSz2wIpcpMeflup+TXp0FSIzz4IlOG/vZMHAgMBAAECggEASDtk7lp1f4fz6YKGnnCG2CmncRq/t46BXKQM4nM4Ra2Tl+f8/X83Z1IGL8QOFNbMvyFu4AqflC7FMU+hTeYt3Amio8QSfUKDHG1hCdnroTX2VcJDh/BJW2w6FHmtyjfpl0AzyZrxeA41s2AtZmpZHyU8S8CsQNliHr6JQNwPIS/B3/4CWlzOMVa9ONSTOWPKZXExzlB9AmypkU9lm4E6GlCbDb8tve3ikF34JD+xpHQ/DclKc6KJAmnyxeaOku5JAR621eWk8bjYVwQRvKyt/mqwI245//nvHj3f/tp1FsWxaYSiGTFU+G7cxF0OvUI4P6+1ZYNRiAdyCoKSDFgLqQKBgQD2S8K03N/J+UjJvLRUhLJEz4n+aDXzgnGgKEJl6NdpxP2fhlFBwOnz4tPJuuz8RWhOtu8E4ZLW7+D8ro+6L+GSTwMJwGr1HroSCHriW/jDWpvXsdP8l4S5n2tWca2GPs6dAkdM+brpGujelcaCL1xKiEpY+YheYFzwYWkI3MPN+wKBgQD01O1ZbnYhIujJtPDDapye8SRZeHRDtaZQ6UqKpYsBnJNUiceME4ItMAtSfip0XCUzrLL2l9CjJIRl9h7h+nv1mZN2+25a/eXx8DwR6krcj016vauoUfOm7udog/IEMsBN2+uwevroH3atdxb9TOzT0t9K7ihOd7d71GJY0VG9ZQKBgQDvhSHnLd3c17c3qXJdt2Z+kK6MYOAG3laOAFkCLnw++joEB2XCYk+ixHZeepC5jO4xjqnHv29D46iTU1enI6Vk2b4En8Hke2tM2j5XIEY+BUIFc4TK4rdKpYSHXqn4IeBgxLR+YWaqB2dr/5A7Tr+cJArZmGJMFb6Mbs7stXUePQKBgQDQnfqcoK4RsDBRZ1db/CT2nh1OC4BuDYNpIFA+8a4Psn4ro7cf2aOro2uSYCUGv1mHvZlE27mQudYDF4PbJFepv7HSyY2QBRaBYCWfUld1trnbY3C4XRRTYvBVs1BuWVxZO5KJ71CKp/y09GvnbDvEhsNzkplPu1ziK+edLMcMrQKBgHGUpj9HVgU6RBZlmMK+73lSWuBZE6HV8dpmBx5jw/SAtKP9BLHJxS3mx3/H/3lHv13KtkS2zAbKhg2G5EkTvrNp3xph15sX5GQv39ESBef0CqUDCDEXOEk86XPGUGy8wpVqno9IVY+gV54MmOTvM1j607B8YWGWQ7mkKcpYk2sH";
+
+    public static void main(String[] args) {
+
+        //'cusid' => '990440148166000',
+        //'appid' => '00000003',
+        //'version' => '12',
+        //'trxamt' => '100',
+        //'reqsn'   => '1745909424337',
+        //'charset' => 'UTF-8',
+        //'returl'  => 'https://21fa-124-93-32-110.ngrok-free.app/user/login.html',
+        //'notify_url' => 'https://21fa-124-93-32-110.ngrok-free.app/user/login.html',
+        //'body'      => 'qiyangtest',
+        //'randomstr' => 'u8InIGlHjw0T11f9gr7S7Ow42r6bEpOZ',
+        //'signtype'  => 'RSA',
+
+        TlH5UnionPayRequestVO tlH5UnionPayRequestVO = TlH5UnionPayRequestVO.builder()
+                .appid("00000003")
+                .body("qiyangtest")
+                .charset("UTF-8")
+                .cusid("990440148166000")
+                .reqsn("1745909424337")
+                .notifyUrl("https://21fa-124-93-32-110.ngrok-free.app/user/login.html")
+                .randomstr("u8InIGlHjw0T11f9gr7S7Ow42r6bEpOZ")
+                .returl("https://21fa-124-93-32-110.ngrok-free.app/user/login.html")
+                .trxamt("100")
+                .signtype("RSA")
+                .version("12")
+                .build();
+
+        String url = new ClientTlUrlService().tlH5UnionPayClient(tlH5UnionPayRequestVO, PRIVATE_KEY);
+
+        System.out.println("url:" + url);
+
+    }
+
+}

+ 31 - 0
src/main/java/common/utils/tl/main/ScanqrPayMain.java

@@ -0,0 +1,31 @@
+package common.utils.tl.main;
+
+import common.utils.tl.constant.TestConstants;
+import common.utils.tl.restservice.ClientTlService;
+import common.utils.tl.vo.TlScanqrPayRequestVO;
+import common.utils.tl.vo.TlScanqrPayResponseVO;
+
+/**
+ * @ClassName: ScanqrPayMain
+ * @Description: ScanqrPayMain
+ * @Auther: wang hong wei
+ * @Date: 2024/12/02
+ */
+public class ScanqrPayMain {
+
+    public static void main(String[] args) {
+        TlScanqrPayRequestVO tlScanqrPayRequestVO = TlScanqrPayRequestVO.builder()
+                //元转换为分,乘以100
+                .trxamt(TestConstants.TRXAMT)
+                .reqsn(TestConstants.REQSN)
+                .notifyUrl(TestConstants.NOTIFY_URL)
+                .authcode(TestConstants.AUTH_CODE)
+                .terminfo(TestConstants.TERM_INFO)
+                .build();
+
+        TlScanqrPayResponseVO tlScanqrPayResponseVO = new ClientTlService().tlScanqrPayClient(TestConstants.MER_ID_CHANNEL, tlScanqrPayRequestVO);
+
+        System.out.println(tlScanqrPayResponseVO);
+    }
+
+}

+ 77 - 0
src/main/java/common/utils/tl/main/SignMain.java

@@ -0,0 +1,77 @@
+package common.utils.tl.main;
+
+import common.utils.tl.util.SignUtils;
+import common.utils.tl.vo.AsyncNoticeRequestVO;
+
+/**
+ * @ClassName: sign
+ * @Description: sign
+ * @Auther: wang hong wei
+ * @Date: 2025/04/15
+ */
+public class SignMain {
+
+    public static final String PUBLIC_KEY = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCm9OV6zH5DYH/ZnAVYHscEELdCNfNTHGuBv1nYYEY9FrOzE0/4kLl9f7Y9dkWHlc2ocDwbrFSm0Vqz0q2rJPxXUYBCQl5yW3jzuKSXif7q1yOwkFVtJXvuhf5WRy+1X5FOFoMvS7538No0RpnLzmNi3ktmiqmhpcY/1pmt20FHQQIDAQAB";
+
+    public static void main(String[] args) {
+
+//        AsyncNoticeRequestVO asyncNoticeRequestVO = AsyncNoticeRequestVO.builder()
+//                .acct("opn0buEbCyvEhBWYGlu-mv69i-Vk")
+//                .accttype("99")
+//                .amount("1")
+//                .appid("00289873")
+//                .bankcode("OTHERS")
+//                .bizseq("10432023110700002")
+//                .chnltrxid("4200002039202311070419796704")
+//                .cusid("56122208249KFA5")
+//                .fee("0")
+//                .paytime("20231107171224")
+//                .randomstr("121448")
+//                .sign("Pfq+Z0wVyoNNIeECwib6lRHDJc6Z9KHB8+3BYHMEkfgCb+lxfkoqsC9hpaup4TZ7KcfWsrKRMtGSNNM/F2GB8VAlzM+y8lQNTWb0TW1kcN9Kk+v1f/hFELgiggGgIrDKT36LaksnWxfkmuUlEJwwBIfeOgzKdCjLnM+AyE6ozzo=")
+//                .signtype("RSA")
+//                .termauthno("OTHERS")
+//                .termid("100BTSZEJ6Ml")
+//                .termrefnum("4200002039202311070419796704")
+//                .timestamp("20231107171224")
+//                .traceno("0")
+//                .trxcode("VSP501")
+//                .trxday("20231107")
+//                .trxid("231107118683137719")
+//                .trxreserve("05|缴费金额(元)#0.01|缴费年份#2024|年级#2022级|专业#城轨|姓名#赵阳|性别#男|身份证#220182200802132126")
+//                .trxstatus("0000")
+//                .build();
+
+        AsyncNoticeRequestVO asyncNoticeRequestVO = AsyncNoticeRequestVO.builder()
+                .acct("oCYH14lnx7_yH6-t2tPCQpqyTles")
+                .accttype("99")
+                .appid("00348104")
+                .bankcode("OTHERS")
+                .chnlid("205299480")
+                .chnltrxid("4200002691202504154889658464")
+                .cmid("761771195")
+                .cusid("660222048163EKM")
+                .cusorderid("202504157113000014")
+                .fee("0")
+                .feecycle("2")
+                .initamt("1")
+                .outtrxid("202504157113000014")
+                .paytime("20250415103629")
+                .sign("Ov9iEyxYSS96FkEhPK5sIuUPeYgWCB5/pCqBiounzPwmkE61UR1pQ/Q5mQwhdGuREssWL9ex9GrqCdAD6UBuUL7BJXlZnL0wWxUXwCxyjNt495CTuKchike26dNRXIcLE+K0lC77W4hZzU/l7O4+IUhkVqtLFDkxS47qgXkXs9M=")
+                .signtype("RSA")
+                .termauthno("OTHERS")
+                .termrefnum("4200002691202504154889658464")
+                .termtraceno("0")
+                .tlopenid("oCYH14lnx7_yH6-t2tPCQpqyTles")
+                .trxamt("1")
+                .trxcode("VSP501")
+                .trxdate("20250415")
+                .trxid("250415124424664637")
+                .trxreserved("备注写什么我也不知道")
+                .trxstatus("0000")
+                .build();
+
+        boolean verifySign = SignUtils.verifySign(asyncNoticeRequestVO.getSign(), asyncNoticeRequestVO, PUBLIC_KEY);
+
+        System.out.println("验签结果:" + verifySign);
+    }
+}

+ 76 - 0
src/main/java/common/utils/tl/restservice/ClientTlService.java

@@ -0,0 +1,76 @@
+package common.utils.tl.restservice;
+
+import common.utils.tl.constant.TestConstants;
+import org.springframework.util.StringUtils;
+import common.utils.tl.util.SignUtils;
+import common.utils.tl.vo.TlH5UnionPayRequestVO;
+import common.utils.tl.vo.TlScanqrPayRequestVO;
+import common.utils.tl.vo.TlScanqrPayResponseVO;
+import common.utils.tl.vo.basevo.TlBaseRequestVO;
+
+import java.util.UUID;
+
+/**
+ * @ClassName: ClientTlService
+ * @Description: Tl相关ClientService
+ * @Auther: wang hong wei
+ * @Date: 2024/05/15
+ */
+public class ClientTlService {
+
+    public static final String SCANQR_PAY_URL = "https://vsp.allinpay.com/apiweb/unitorder/scanqrpay";
+    public static final String H5UNION_PAY_URL = "https://syb.allinpay.com/apiweb/h5unionpay/unionorder";
+
+    /**
+     * 统一扫码接口
+     * @param cusid
+     * @param tlScanqrPayRequestVO
+     * @return
+     */
+    public TlScanqrPayResponseVO tlScanqrPayClient(String cusid, TlScanqrPayRequestVO tlScanqrPayRequestVO){
+
+        //封装公共字段
+        getTlBaseRequestVO(cusid, tlScanqrPayRequestVO);
+
+        //发送接口
+        TlScanqrPayResponseVO responseVO = new TlHttpService().exchange(SCANQR_PAY_URL, tlScanqrPayRequestVO, TlScanqrPayResponseVO.class);
+
+        //转换为实体类
+        return responseVO;
+    }
+
+    /**
+     * H5收银台
+     * @param tlH5UnionPayRequestVO
+     * @return
+     */
+    public String tlH5UnionPayClient(TlH5UnionPayRequestVO tlH5UnionPayRequestVO){
+
+        //发送接口
+        String responseVO = new TlHttpService().exchange(H5UNION_PAY_URL, tlH5UnionPayRequestVO, String.class);
+
+        //转换为实体类
+        return responseVO;
+    }
+
+    /**
+     * 获取Tl公共字段
+     * @param merIdChannel
+     * @param tlBaseRequestVO
+     */
+    private void getTlBaseRequestVO(String merIdChannel, TlBaseRequestVO tlBaseRequestVO){
+
+        tlBaseRequestVO.setOrgid(TestConstants.ORGID);
+        tlBaseRequestVO.setAppid(TestConstants.APPID);
+        tlBaseRequestVO.setVersion(TestConstants.VERSION);
+        tlBaseRequestVO.setSigntype(TestConstants.SIGN_TYPE);
+
+        //渠道商户号存在,则赋值渠道商户号;不存在,则赋值通联分配的商户号
+        tlBaseRequestVO.setCusid(StringUtils.hasLength(merIdChannel) ? merIdChannel : TestConstants.CUSID);
+        tlBaseRequestVO.setRandomstr(UUID.randomUUID().toString().replace("-", ""));
+
+        //生成签名
+        tlBaseRequestVO.setSign(SignUtils.generateTlSign(tlBaseRequestVO, TestConstants.PRIVATE_KEY));
+    }
+
+}

+ 57 - 0
src/main/java/common/utils/tl/restservice/ClientTlUrlService.java

@@ -0,0 +1,57 @@
+package common.utils.tl.restservice;
+
+import org.springframework.stereotype.Service;
+import common.utils.tl.util.ASCIIUtils;
+import common.utils.tl.util.SignUtils;
+import common.utils.tl.util.URLUtils;
+import common.utils.tl.vo.TlH5UnionPayRequestVO;
+
+import java.lang.reflect.Field;
+import java.util.Comparator;
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * @ClassName: ClientTlUrlService
+ * @Description: 获取Tl Url Service
+ * @Auther: wang hong wei
+ * @Date: 2024/05/15
+ */
+@Service
+public class ClientTlUrlService {
+
+    public static final String H5UNION_PAY_URL = "https://syb.allinpay.com/apiweb/h5unionpay/unionorder";
+
+    /**
+     * H5收银台
+     * @param tlH5UnionPayRequestVO
+     * @return
+     */
+    public String tlH5UnionPayClient(TlH5UnionPayRequestVO tlH5UnionPayRequestVO, String privateKey){
+
+        tlH5UnionPayRequestVO.setSign(SignUtils.generateTlSign(tlH5UnionPayRequestVO, privateKey));
+
+        //生成url参数
+        String paramString = getParamString(tlH5UnionPayRequestVO);
+
+        //转换为实体类
+        return H5UNION_PAY_URL + "?" + paramString;
+    }
+
+    /**
+     * 拼接路径
+     * @param object
+     * @return
+     */
+    private String getParamString(Object object){
+        //获取属性集合
+        List<Field> fieldList = ASCIIUtils.getFieldList(object);
+
+        return fieldList.stream()
+                .filter(c -> ASCIIUtils.getValue(c, object) != null)
+                .sorted(Comparator.comparing(ASCIIUtils::getJsonPropertyName))
+                .map(c -> ASCIIUtils.getJsonPropertyName(c) + "=" + URLUtils.encode(ASCIIUtils.getValue(c, object).toString()))
+                .collect(Collectors.joining("&"));
+    }
+
+}

+ 82 - 0
src/main/java/common/utils/tl/restservice/TlHttpService.java

@@ -0,0 +1,82 @@
+package common.utils.tl.restservice;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.core.io.FileSystemResource;
+import org.springframework.http.HttpEntity;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.util.LinkedMultiValueMap;
+import org.springframework.util.MultiValueMap;
+import org.springframework.web.client.RestTemplate;
+import common.utils.tl.util.ASCIIUtils;
+import common.utils.tl.util.JacksonUtils;
+
+import java.io.File;
+import java.lang.reflect.Field;
+import java.util.List;
+
+/**
+ * @ClassName: TlHttpService
+ * @Description: 发送Tl请求Service
+ * @Auther: wang hong wei
+ * @Date: 2024/09/27
+ */
+@Slf4j
+public class TlHttpService {
+
+    /**
+     * 发送Tl请求,处理返回报文
+     * @param url
+     * @param object
+     * @return
+     */
+    public <T> T exchange(String url, Object object, Class<T> responseType){
+        log.info("请求Tl url-[{}]",url);
+        log.info("请求Tl 报文-[{}]", JacksonUtils.obj2String(object));
+        try {
+            HttpEntity<?> requestEntity = new HttpEntity<>(getRequestBody(object));
+            ResponseEntity<T> exchange = new RestTemplate().exchange(url, HttpMethod.POST, requestEntity, responseType);
+            HttpStatus statusCode = exchange.getStatusCode();
+            log.info("Tl响应码-[{}]",statusCode);
+            if(!HttpStatus.OK.equals(statusCode)){
+                log.error("请求Tl接口失败,抛出异常!");
+            }
+            T t = exchange.getBody();
+            log.info("Tl响应报文-[{}]", JacksonUtils.obj2String(t));
+            return t;
+        }catch (Exception e){
+            log.error(e.getMessage(),e);
+            return null;
+        }
+    }
+
+    /**
+     * 获取tl requestBody
+     * @param object
+     * @return
+     */
+    private MultiValueMap<String, Object> getRequestBody(Object object){
+        MultiValueMap<String, Object> requestBody = new LinkedMultiValueMap<>();
+
+        //利用反射获取类信息
+        List<Field> fieldList = ASCIIUtils.getFieldList(object);
+        for (Field field : fieldList) {
+            //获取属性名
+            String propertyName = ASCIIUtils.getJsonPropertyName(field);
+            //获取属性值
+            Object value = ASCIIUtils.getValue(field, object);
+
+            if (value instanceof File) {
+                // 添加文件
+                FileSystemResource fileResource = new FileSystemResource( (File) value);
+                requestBody.add(propertyName, fileResource);
+            }else {
+                requestBody.add(propertyName, value);
+            }
+        }
+
+        return requestBody;
+    }
+
+}

+ 114 - 0
src/main/java/common/utils/tl/util/ASCIIUtils.java

@@ -0,0 +1,114 @@
+package common.utils.tl.util;
+
+import common.utils.tl.annotation.IgnoreField;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import org.springframework.util.ReflectionUtils;
+
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * @ClassName: ASCIIUtils
+ * @Description: ASCII工具类
+ * @Auther: wang hong wei
+ * @Date: 2024/05/15
+ */
+public class ASCIIUtils {
+
+    private ASCIIUtils(){}
+
+    /**
+     * 实体类属性名按照ASCII排序后转换为字符串
+     * @param object
+     * @return
+     */
+    public static String getASCIIString(Object object) {
+        //获取属性集合
+        List<Field> fieldList = getFieldList(object);
+
+        /*
+         *  处理属性list:fieldList
+         *      1.过滤掉IgnoreField注解字段
+         *      2.过滤掉属性值为null的字段
+         *      3.按照属性名(优先注解中的名称)进行排序,sort方法默认ASCII
+         *      4.拼接sign字符串:每对使用'='拼接,每对之间使用'&'相连
+         *          属性名(优先注解中的名称)=属性值&属性名(优先注解中的名称)=属性值
+         *          例:key=value&key=value
+         */
+        return fieldList.stream()
+                .filter(c -> !c.isAnnotationPresent(IgnoreField.class))
+                .filter(c -> getValue(c, object) != null)
+                .sorted(Comparator.comparing(ASCIIUtils::getJsonPropertyName))
+                .map(c -> getJsonPropertyName(c) + "=" + getValue(c, object))
+                .collect(Collectors.joining("&"));
+    }
+
+    /**
+     * 获取属性集合
+     * @param object
+     * @return
+     */
+    public static List<Field> getFieldList(Object object){
+        //ASCII转换对象为null直接抛出异常
+        if(object != null){
+            //属性list:存放本类+父类属性
+            List<Field> fieldList = new ArrayList<>();
+            Class<?> clazz = object.getClass();
+            //获取本类属性
+            fieldList.addAll(Arrays.asList(clazz.getDeclaredFields()));
+            //获取父类属性
+            fieldList.addAll(Arrays.asList(clazz.getSuperclass().getDeclaredFields()));
+            return fieldList;
+        }
+
+        return null;
+    }
+
+    /**
+     * 获取属性值
+     * @param field
+     * @param object
+     * @return
+     */
+    public static Object getValue(Field field, Object object) {
+        try {
+            // 允许访问私有字段
+            ReflectionUtils.makeAccessible(field);
+            return field.get(object);
+        }catch (IllegalAccessException e){
+            return null;
+        }
+    }
+
+    /**
+     * 获取属性值
+     * @param field
+     * @param object
+     * @return
+     */
+    public static void setValue(Field field, Object object, String value) {
+        // 允许访问私有字段
+        ReflectionUtils.makeAccessible(field);
+        ReflectionUtils.setField(field, object, value);
+    }
+
+    /**
+     * 获取属性名(优先注解中的名称)
+     * @param field
+     * @return
+     */
+    public static String getJsonPropertyName(Field field) {
+        JsonProperty jsonProperty = field.getAnnotation(JsonProperty.class);
+        if (jsonProperty != null) {
+            //存在注解名则返回注解名
+            return jsonProperty.value();
+        }
+        //不存在注解名则返回属性名
+        return field.getName();
+    }
+
+}

+ 70 - 0
src/main/java/common/utils/tl/util/JacksonUtils.java

@@ -0,0 +1,70 @@
+package common.utils.tl.util;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.DeserializationFeature;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.SerializationFeature;
+import lombok.extern.slf4j.Slf4j;
+
+/**
+ * @ClassName: JsonMapper
+ * @Description: JsonMapper
+ * @Auther: wang hong wei
+ * @Date: 2024/05/20
+ */
+@Slf4j
+public class JacksonUtils {
+
+    private JacksonUtils(){}
+
+    private static ObjectMapper objectMapper = new ObjectMapper();
+
+    static {
+        //config
+        //属性为null的转换
+        objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
+        //设置在反序列化时忽略在JSON字符串中存在,而在Java中不存在的属性
+        objectMapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
+        //象为空对象(即没有任何属性)不抛出异常,而是返回一个空的JSON字符串
+        objectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
+    }
+
+    /**
+     * 对象转String
+     * @param t
+     * @param <T>
+     * @return
+     */
+    public static <T> String obj2String(T t){
+        if (null == t){
+            return null;
+        }
+        try {
+            return t instanceof String ? (String) t : objectMapper.writeValueAsString(t);
+        } catch (Exception e) {
+            log.error(e.getMessage(),e);
+            return null;
+        }
+    }
+
+    /**
+     * json字符串转换对象
+     * @param src
+     * @param typeReference
+     * @param <T>
+     * @return
+     */
+    public static <T> T string2Obj(String src, TypeReference<T> typeReference){
+        if(null == src || null == typeReference){
+            return null;
+        }
+        try {
+            return (T) (typeReference.getType().equals(String.class) ? src : objectMapper.readValue(src, typeReference));
+        } catch (Exception e){
+            log.error(e.getMessage(),e);
+            return null;
+        }
+    }
+
+}

+ 93 - 0
src/main/java/common/utils/tl/util/RSAUtils.java

@@ -0,0 +1,93 @@
+package common.utils.tl.util;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.util.Base64Utils;
+
+import java.nio.charset.StandardCharsets;
+import java.security.*;
+import java.security.spec.InvalidKeySpecException;
+import java.security.spec.PKCS8EncodedKeySpec;
+import java.security.spec.X509EncodedKeySpec;
+
+/**
+ * @ClassName: RSAUtils
+ * @Description: RSA工具类
+ * @Auther: wang hong wei
+ * @Date: 2024/05/15
+ */
+@Slf4j
+@SuppressWarnings("squid:S5542")
+public class RSAUtils {
+
+    private RSAUtils(){}
+
+    /*  ----------------- 加密 -----------------  */
+
+    /**
+     * RSA加密:通过私钥对sign字符串进行分段加密
+     * @param signData
+     * @param privateKey
+     * @return
+     */
+    public static String encryptSignByPrivateKey(String signData, String privateKey) {
+        try{
+            Signature signature = Signature.getInstance("SHA1WithRSA");
+            signature.initSign(getPrivateKey(privateKey));
+            signature.update(signData.getBytes(StandardCharsets.UTF_8));
+            byte[] signed = signature.sign();
+            return Base64Utils.encodeToString(signed);
+        }catch (Exception e){
+            log.error(e.getMessage(),e);
+            return null;
+        }
+    }
+
+    /**
+     * RSA验签:通过公钥对sign字符串进行验证
+     * @param sign
+     * @param publicKey
+     * @return
+     */
+    public static boolean verifySignByPublicKey(String sign, String signData, String publicKey) {
+        try{
+            Signature signature = Signature.getInstance("SHA1WithRSA");
+            signature.initVerify(getPublicKey(publicKey));
+            signature.update(signData.getBytes(StandardCharsets.UTF_8));
+
+            //验签
+            return signature.verify(Base64Utils.decodeFromString(sign));
+        }catch (Exception e){
+            log.error(e.getMessage(),e);
+            return false;
+        }
+    }
+
+    /**
+     * 根据公钥字符串生成公钥
+     * @param publicKey
+     * @return
+     * @throws NoSuchAlgorithmException
+     * @throws InvalidKeySpecException
+     */
+    public static PublicKey getPublicKey(String publicKey) throws NoSuchAlgorithmException, InvalidKeySpecException {
+        byte[] keyBytes = Base64Utils.decodeFromString(publicKey);
+        X509EncodedKeySpec spec = new X509EncodedKeySpec(keyBytes);
+        KeyFactory kf = KeyFactory.getInstance("RSA");
+        return kf.generatePublic(spec);
+    }
+
+    /**
+     * 根据私钥字符串生成密钥
+     * @param privateKey
+     * @return
+     * @throws NoSuchAlgorithmException
+     * @throws InvalidKeySpecException
+     */
+    public static PrivateKey getPrivateKey(String privateKey) throws NoSuchAlgorithmException, InvalidKeySpecException {
+        byte[] keyBytes = Base64Utils.decodeFromString(privateKey);
+        PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(keyBytes);
+        KeyFactory kf = KeyFactory.getInstance("RSA");
+        return kf.generatePrivate(spec);
+    }
+
+}

+ 39 - 0
src/main/java/common/utils/tl/util/SignUtils.java

@@ -0,0 +1,39 @@
+package common.utils.tl.util;
+
+import lombok.extern.slf4j.Slf4j;
+
+/**
+ * @ClassName: SignUtils
+ * @Description: Sign工具类
+ * @Auther: wang hong wei
+ * @Date: 2024/05/15
+ */
+@Slf4j
+public class SignUtils {
+
+    private SignUtils(){}
+
+    /**
+     * 生成Tl签名
+     * @param object
+     * @param tlKey
+     * @return
+     */
+    public static String generateTlSign(Object object, String tlKey){
+        String signData = ASCIIUtils.getASCIIString(object);
+        return RSAUtils.encryptSignByPrivateKey(signData, tlKey);
+    }
+
+    /**
+     * 验证Tl签名
+     * @param object
+     * @param tlPublicKey
+     * @return
+     */
+    public static boolean verifySign(String sign, Object object, String tlPublicKey){
+        String signData = ASCIIUtils.getASCIIString(object);
+        log.info("signData-[{}]", signData);
+        return RSAUtils.verifySignByPublicKey(sign, signData, tlPublicKey);
+    }
+
+}

+ 48 - 0
src/main/java/common/utils/tl/util/URLUtils.java

@@ -0,0 +1,48 @@
+package common.utils.tl.util;
+
+import lombok.extern.slf4j.Slf4j;
+
+import java.net.URLDecoder;
+import java.net.URLEncoder;
+import java.nio.charset.StandardCharsets;
+
+/**
+ * @ClassName: RSAUtils
+ * @Description: RSA工具类
+ * @Auther: wang hong wei
+ * @Date: 2024/05/15
+ */
+@Slf4j
+public class URLUtils {
+
+    private URLUtils(){}
+
+    /**
+     * URL转换
+     * @param url
+     * @return
+     */
+    public static String encode(String url) {
+        try {
+            return URLEncoder.encode(url, StandardCharsets.UTF_8.name());
+        }catch (Exception e){
+            log.error(e.getMessage(),e);
+            return null;
+        }
+    }
+
+    /**
+     * URL转换
+     * @param url
+     * @return
+     */
+    public static String decode(String url) {
+        try {
+            return URLDecoder.decode(url, StandardCharsets.UTF_8.name());
+        }catch (Exception e){
+            log.error(e.getMessage(),e);
+            return null;
+        }
+    }
+
+}

+ 269 - 0
src/main/java/common/utils/tl/vo/AsyncNoticeRequestVO.java

@@ -0,0 +1,269 @@
+package common.utils.tl.vo;
+
+import common.utils.tl.annotation.IgnoreField;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * @ClassName: AsyncNoticeRequestVO
+ * @Description: 异步通知接口Request
+ * @Auther: wang hong wei
+ * @Date: 2024/10/09
+ */
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class AsyncNoticeRequestVO {
+
+    /**
+     * outtrxid:第三方交易号
+     */
+    @JsonProperty("outtrxid")
+    private String outtrxid;
+
+    /**
+     * appid:平台分配的机构APPID
+     */
+    @JsonProperty("appid")
+    private String appid;
+
+    /**
+     * trxcode:交易类型
+     */
+    @JsonProperty("trxcode")
+    private String trxcode;
+
+    /**
+     * trxid:收银宝交易单号
+     */
+    @JsonProperty("trxid")
+    private String trxid;
+
+    /**
+     * initamt:原始下单金额
+     */
+    @JsonProperty("initamt")
+    private String initamt;
+
+    /**
+     * trxamt:交易金额
+     */
+    @JsonProperty("trxamt")
+    private String trxamt;
+
+    /**
+     * trxdate:交易请求日期 yyyymmdd
+     */
+    @JsonProperty("trxdate")
+    private String trxdate;
+
+    /**
+     * paytime:交易完成时间 yyyymmddhhmmss
+     */
+    @JsonProperty("paytime")
+    private String paytime;
+
+    /**
+     * chnltrxid:渠道流水号
+     */
+    @JsonProperty("chnltrxid")
+    private String chnltrxid;
+
+    /**
+     * trxstatus:交易结果码
+     */
+    @JsonProperty("trxstatus")
+    private String trxstatus;
+
+    /**
+     * cusid:渠道商户号
+     */
+    @JsonProperty("cusid")
+    private String cusid;
+
+    /**
+     * termno:终端编号
+     */
+    @JsonProperty("termno")
+    private String termno;
+
+    /**
+     * termbatchid:终端批次号
+     */
+    @JsonProperty("termbatchid")
+    private String termbatchid;
+
+    /**
+     * termtraceno:终端流水号
+     */
+    @JsonProperty("termtraceno")
+    private String termtraceno;
+
+    /**
+     * termauthno:终端授权码
+     */
+    @JsonProperty("termauthno")
+    private String termauthno;
+
+    /**
+     * termrefnum:终端参考号
+     */
+    @JsonProperty("termrefnum")
+    private String termrefnum;
+
+    /**
+     * trxreserved:业务关联内容
+     */
+    @JsonProperty("trxreserved")
+    private String trxreserved;
+
+    /**
+     * srctrxid:原交易流水
+     */
+    @JsonProperty("srctrxid")
+    private String srctrxid;
+
+    /**
+     * cusorderid:业务流水
+     */
+    @JsonProperty("cusorderid")
+    private String cusorderid;
+
+    /**
+     * acct:交易账号
+     */
+    @JsonProperty("acct")
+    private String acct;
+
+    /**
+     * fee:手续费
+     */
+    @JsonProperty("fee")
+    private String fee;
+
+    /**
+     * signtype:签名类型
+     */
+    @JsonProperty("signtype")
+    private String signtype;
+
+    /**
+     * cmid:渠道子商户号
+     */
+    @JsonProperty("cmid")
+    private String cmid;
+
+    /**
+     * chnlid:渠道号
+     */
+    @JsonProperty("chnlid")
+    private String chnlid;
+
+    /**
+     * chnldata:渠道信息
+     */
+    @JsonProperty("chnldata")
+    private String chnldata;
+
+    /**
+     * accttype:借贷标识
+     */
+    @JsonProperty("accttype")
+    private String accttype;
+
+    /**
+     * bankcode:发卡行
+     */
+    @JsonProperty("bankcode")
+    private String bankcode;
+
+    /**
+     * logonid:支付宝买家账号
+     */
+    @JsonProperty("logonid")
+    private String logonid;
+
+
+
+
+    /**
+     * amount:交易金额
+     */
+    @JsonProperty("amount")
+    private String amount;
+
+    /**
+     * bizseq:支付宝买家账号
+     */
+    @JsonProperty("bizseq")
+    private String bizseq;
+
+    /**
+     * randomstr:支付宝买家账号
+     */
+    @JsonProperty("randomstr")
+    private String randomstr;
+
+    /**
+     * termid:支付宝买家账号
+     */
+    @JsonProperty("termid")
+    private String termid;
+
+    /**
+     * timestamp:支付宝买家账号
+     */
+    @JsonProperty("timestamp")
+    private String timestamp;
+
+    /**
+     * traceno:支付宝买家账号
+     */
+    @JsonProperty("traceno")
+    private String traceno;
+
+    /**
+     * trxday:支付宝买家账号
+     */
+    @JsonProperty("trxday")
+    private String trxday;
+
+    /**
+     * trxreserve:支付宝买家账号
+     */
+    @JsonProperty("trxreserve")
+    private String trxreserve;
+
+
+
+    /**
+     * feecycle:支付宝买家账号
+     */
+    @JsonProperty("feecycle")
+    private String feecycle;
+
+    /**
+     * tlopenid:支付宝买家账号
+     */
+    @JsonProperty("tlopenid")
+    private String tlopenid;
+
+
+
+
+
+
+
+
+    /**
+     * sign:签名
+     */
+    @IgnoreField
+    @JsonProperty("sign")
+    private String sign;
+
+}

+ 58 - 0
src/main/java/common/utils/tl/vo/TlH5UnionPayRequestVO.java

@@ -0,0 +1,58 @@
+package common.utils.tl.vo;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import lombok.experimental.SuperBuilder;
+import vo.basevo.TlBaseRequestVO;
+
+/**
+ * @ClassName: TlScanqrPayRequestVO
+ * @Description: TlScanqrPayRequestVO
+ * @Auther: wang hong wei
+ * @Date: 2024/09/25
+ */
+@Data
+@SuperBuilder
+@NoArgsConstructor
+@AllArgsConstructor
+public class TlH5UnionPayRequestVO extends TlBaseRequestVO {
+
+    /**
+     * trxamt:交易金额 单位为分
+     */
+    @JsonProperty("trxamt")
+    private String trxamt;
+
+    /**
+     * reqsn:商户订单号
+     */
+    @JsonProperty("reqsn")
+    private String reqsn;
+
+    /**
+     * charset:charset
+     */
+    @JsonProperty("charset")
+    private String charset;
+
+    /**
+     * body:订单标题
+     */
+    @JsonProperty("body")
+    private String body;
+
+    /**
+     * notify_url:交易结果通知地址
+     */
+    @JsonProperty("notify_url")
+    private String notifyUrl;
+
+    /**
+     * returl:returl
+     */
+    @JsonProperty("returl")
+    private String returl;
+
+}

+ 142 - 0
src/main/java/common/utils/tl/vo/TlScanqrPayRequestVO.java

@@ -0,0 +1,142 @@
+package common.utils.tl.vo;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import lombok.experimental.SuperBuilder;
+import vo.basevo.TlBaseRequestVO;
+
+/**
+ * @ClassName: TlScanqrPayRequestVO
+ * @Description: TlScanqrPayRequestVO
+ * @Auther: wang hong wei
+ * @Date: 2024/09/25
+ */
+@Data
+@SuperBuilder
+@NoArgsConstructor
+@AllArgsConstructor
+public class TlScanqrPayRequestVO extends TlBaseRequestVO {
+
+    /**
+     * trxamt:交易金额 单位为分
+     */
+    @JsonProperty("trxamt")
+    private String trxamt;
+
+    /**
+     * reqsn:商户订单号
+     */
+    @JsonProperty("reqsn")
+    private String reqsn;
+
+    /**
+     * body:订单标题
+     */
+    @JsonProperty("body")
+    private String body;
+
+    /**
+     * remark:备注
+     */
+    @JsonProperty("remark")
+    private String remark;
+
+    /**
+     * authcode:支付授权码
+     */
+    @JsonProperty("authcode")
+    private String authcode;
+
+    /**
+     * limit_pay:支付限制
+     */
+    @JsonProperty("limit_pay")
+    private String limitPay;
+
+    /**
+     * goods_tag:订单优惠标识
+     */
+    @JsonProperty("goods_tag")
+    private String goodsTag;
+
+    /**
+     * benefitdetail:优惠信息
+     */
+    @JsonProperty("benefitdetail")
+    private String benefitdetail;
+
+    /**
+     * sub_appid:微信子appid
+     */
+    @JsonProperty("sub_appid")
+    private String subAppid;
+
+    /**
+     * chnlstoreid:渠道门店编号
+     */
+    @JsonProperty("chnlstoreid")
+    private String chnlstoreid;
+
+    /**
+     * subbranch:门店号
+     */
+    @JsonProperty("subbranch")
+    private String subbranch;
+
+    /**
+     * idno:证件号
+     */
+    @JsonProperty("idno")
+    private String idno;
+
+    /**
+     * extendparams:拓展参数
+     */
+    @JsonProperty("extendparams")
+    private String extendparams;
+
+    /**
+     * truename:付款人真实姓名
+     */
+    @JsonProperty("truename")
+    private String truename;
+
+    /**
+     * asinfo:分账信息
+     */
+    @JsonProperty("asinfo")
+    private String asinfo;
+
+    /**
+     * fqnum:分期
+     */
+    @JsonProperty("fqnum")
+    private String fqnum;
+
+    /**
+     * notify_url:交易结果通知地址
+     */
+    @JsonProperty("notify_url")
+    private String notifyUrl;
+
+    /**
+     * unpid:银联pid
+     */
+    @JsonProperty("unpid")
+    private String unpid;
+
+    /**
+     * terminfo:终端信息
+     */
+    @JsonProperty("terminfo")
+    private String terminfo;
+
+    /**
+     * operatorid:收银员号
+     */
+    @JsonProperty("operatorid")
+    private String operatorid;
+
+}

+ 129 - 0
src/main/java/common/utils/tl/vo/TlScanqrPayResponseVO.java

@@ -0,0 +1,129 @@
+package common.utils.tl.vo;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import lombok.experimental.SuperBuilder;
+import vo.basevo.TlBaseResponseVO;
+
+/**
+ * @ClassName: TlScanqrPayResponseVO
+ * @Description: TlScanqrPayResponseVO
+ * @Auther: wang hong wei
+ * @Date: 2024/09/25
+ */
+@Data
+@SuperBuilder
+@NoArgsConstructor
+@AllArgsConstructor
+public class TlScanqrPayResponseVO extends TlBaseResponseVO {
+
+    /**
+     * cusid:渠道商户号
+     */
+    @JsonProperty("cusid")
+    private String cusid;
+
+    /**
+     * appid:应用ID
+     */
+    @JsonProperty("appid")
+    private String appid;
+
+    /**
+     * trxid:交易单号
+     */
+    @JsonProperty("trxid")
+    private String trxid;
+
+    /**
+     * chnltrxid:支付渠道交易单号
+     */
+    @JsonProperty("chnltrxid")
+    private String chnltrxid;
+
+    /**
+     * reqsn:商户订单号
+     */
+    @JsonProperty("reqsn")
+    private String reqsn;
+    /**
+     * trxstatus:交易状态码
+     */
+    @JsonProperty("trxstatus")
+    private String trxstatus;
+
+    /**
+     * acct:支付平台用户标识
+     */
+    @JsonProperty("acct")
+    private String acct;
+
+    /**
+     * trxcode:交易类型
+     */
+    @JsonProperty("trxcode")
+    private String trxcode;
+
+    /**
+     * fintime:交易完成时间
+     */
+    @JsonProperty("fintime")
+    private String fintime;
+
+    /**
+     * errmsg:错误信息
+     */
+    @JsonProperty("errmsg")
+    private String errmsg;
+
+    /**
+     * randomstr:随机字符串
+     */
+    @JsonProperty("randomstr")
+    private String randomstr;
+
+    /**
+     * initamt:原交易金额
+     */
+    @JsonProperty("initamt")
+    private String initamt;
+
+    /**
+     * trxamt:实际交易金额
+     */
+    @JsonProperty("trxamt")
+    private String trxamt;
+
+    /**
+     * fee:手续费
+     */
+    @JsonProperty("fee")
+    private String fee;
+
+    /**
+     * cmid:渠道子商户号
+     */
+    @JsonProperty("cmid")
+    private String cmid;
+
+    /**
+     * chnlid:渠道号
+     */
+    @JsonProperty("chnlid")
+    private String chnlid;
+
+    /**
+     * chnldata:渠道信息
+     */
+    @JsonProperty("chnldata")
+    private String chnldata;
+
+    /**
+     * accttype:借贷标识
+     */
+    @JsonProperty("accttype")
+    private String accttype;
+
+}

+ 63 - 0
src/main/java/common/utils/tl/vo/basevo/TlBaseRequestVO.java

@@ -0,0 +1,63 @@
+package common.utils.tl.vo.basevo;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import lombok.experimental.SuperBuilder;
+
+/**
+ * @ClassName: TlBaseRequestVO
+ * @Description: TlBaseRequestVO
+ * @Auther: wang hong wei
+ * @Date: 2024/09/25
+ */
+@Data
+@SuperBuilder
+@NoArgsConstructor
+@AllArgsConstructor
+public class TlBaseRequestVO {
+
+    /**
+     * cusid:渠道商户号
+     */
+    @JsonProperty("cusid")
+    private String cusid;
+
+    /**
+     * orgid:代理商号
+     */
+    @JsonProperty("orgid")
+    private String orgid;
+
+    /**
+     * appid:平台分配的机构APPID
+     */
+    @JsonProperty("appid")
+    private String appid;
+
+    /**
+     * version:接口版本号
+     */
+    @JsonProperty("version")
+    private String version;
+
+    /**
+     * randomstr:随机字符串
+     */
+    @JsonProperty("randomstr")
+    private String randomstr;
+
+    /**
+     * signtype:签名类型
+     */
+    @JsonProperty("signtype")
+    private String signtype;
+
+    /**
+     * sign:签名
+     */
+    @JsonProperty("sign")
+    private String sign;
+
+}

+ 39 - 0
src/main/java/common/utils/tl/vo/basevo/TlBaseResponseVO.java

@@ -0,0 +1,39 @@
+package common.utils.tl.vo.basevo;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import lombok.experimental.SuperBuilder;
+
+/**
+ * @ClassName: TlBaseResponseVO
+ * @Description: TlBaseResponseVO
+ * @Auther: wang hong wei
+ * @Date: 2024/09/25
+ */
+@Data
+@SuperBuilder
+@NoArgsConstructor
+@AllArgsConstructor
+public class TlBaseResponseVO {
+
+    /**
+     * retcode:响应码
+     */
+    @JsonProperty("retcode")
+    private String retcode;
+
+    /**
+     * retmsg:响应描述
+     */
+    @JsonProperty("retmsg")
+    private String retmsg;
+
+    /**
+     * sign:签名
+     */
+    @JsonProperty("sign")
+    private String sign;
+
+}