瀏覽代碼

对接台州银行接口

xdd 3 月之前
父節點
當前提交
6ac62e7dab
共有 29 個文件被更改,包括 1398 次插入45 次删除
  1. 1 1
      fs-admin/src/main/java/com/fs/qw/config/SocketConfig.java
  2. 44 0
      fs-admin/src/main/java/com/fs/store/controller/FsStorePaymentController.java
  3. 9 0
      fs-common/src/main/java/com/fs/common/core/redis/RedisCache.java
  4. 8 0
      fs-service-system/pom.xml
  5. 36 0
      fs-service-system/src/main/java/com/fs/common/DeviceUtils.java
  6. 96 0
      fs-service-system/src/main/java/com/fs/huifuPay/dto/QueryOrderInfoDTO.java
  7. 11 0
      fs-service-system/src/main/java/com/fs/huifuPay/dto/QueryOrderRestDTO.java
  8. 26 0
      fs-service-system/src/main/java/com/fs/huifuPay/dto/RefundParam.java
  9. 40 0
      fs-service-system/src/main/java/com/fs/huifuPay/dto/RefundResult.java
  10. 66 0
      fs-service-system/src/main/java/com/fs/huifuPay/dto/ReqTokenResultDTO.java
  11. 24 0
      fs-service-system/src/main/java/com/fs/huifuPay/dto/RequestDTO.java
  12. 32 0
      fs-service-system/src/main/java/com/fs/huifuPay/dto/TzMiniProgramCodeReqDTO.java
  13. 69 0
      fs-service-system/src/main/java/com/fs/huifuPay/dto/TzMiniProgramCodeRespDTO.java
  14. 97 0
      fs-service-system/src/main/java/com/fs/huifuPay/dto/TzPayCreateOrderReqBodyDTO.java
  15. 46 0
      fs-service-system/src/main/java/com/fs/huifuPay/dto/TzPayCreateOrderRspDTO.java
  16. 44 0
      fs-service-system/src/main/java/com/fs/huifuPay/dto/TzPayRefundDTO.java
  17. 71 0
      fs-service-system/src/main/java/com/fs/huifuPay/dto/TzRefundNotifyDTO.java
  18. 72 0
      fs-service-system/src/main/java/com/fs/huifuPay/dto/TzReqHeaderDTO.java
  19. 54 0
      fs-service-system/src/main/java/com/fs/huifuPay/dto/TzReqResultDTO.java
  20. 13 0
      fs-service-system/src/main/java/com/fs/store/config/TzBankConfig.java
  21. 1 0
      fs-service-system/src/main/java/com/fs/store/domain/FsPayConfig.java
  22. 102 0
      fs-service-system/src/main/java/com/fs/store/domain/TzConfigInfoDTO.java
  23. 40 6
      fs-service-system/src/main/java/com/fs/store/service/impl/FsStoreAfterSalesServiceImpl.java
  24. 43 1
      fs-service-system/src/main/java/com/fs/store/service/impl/FsStoreOrderServiceImpl.java
  25. 36 7
      fs-service-system/src/main/java/com/fs/store/service/impl/FsStorePaymentServiceImpl.java
  26. 46 0
      fs-service-system/src/main/java/com/fs/tzBank/TzBankService.java
  27. 148 0
      fs-service-system/src/main/java/com/fs/tzBank/impl/TzBankServiceImpl.java
  28. 23 0
      fs-service-system/src/main/java/com/fs/tzBank/utils/TzConfigUtils.java
  29. 100 30
      fs-user-app/src/main/java/com/fs/app/controller/StoreOrderController.java

+ 1 - 1
fs-admin/src/main/java/com/fs/qw/config/SocketConfig.java

@@ -5,7 +5,7 @@ import org.springframework.context.annotation.Configuration;
 
 @Configuration
 public class SocketConfig {
-    @Value("${socket.url}")
+//    @Value("${socket.url}")
     private String socketUrl;
 
     public String getSocketUrl() {

+ 44 - 0
fs-admin/src/main/java/com/fs/store/controller/FsStorePaymentController.java

@@ -18,6 +18,7 @@ import com.fs.common.utils.StringUtils;
 import com.fs.company.service.ICompanyService;
 import com.fs.huifuPay.domain.HuiFuQueryOrderResult;
 import com.fs.huifuPay.domain.HuiFuRefundResult;
+import com.fs.huifuPay.dto.*;
 import com.fs.huifuPay.sdk.opps.core.request.V2TradePaymentScanpayQueryRequest;
 import com.fs.huifuPay.sdk.opps.core.request.V2TradePaymentScanpayRefundRequest;
 import com.fs.huifuPay.service.HuiFuService;
@@ -26,10 +27,14 @@ import com.fs.pay.pay.domain.OrderResult;
 import com.fs.pay.pay.domain.RefundResult;
 import com.fs.pay.pay.dto.OrderQueryDTO;
 import com.fs.pay.pay.service.PayService;
+import com.fs.store.domain.TzConfigInfoDTO;
 import com.fs.store.param.FsStorePaymentParam;
 import com.fs.store.service.IFsStoreOrderService;
 import com.fs.store.vo.FsStorePaymentVO;
 import com.fs.pay.service.IPayService;
+import com.fs.tzBank.TzBankService;
+import com.fs.tzBank.utils.TzConfigUtils;
+import com.hc.openapi.tool.fastjson.JSON;
 import com.ijpay.alipay.AliPayApi;
 import com.ijpay.alipay.AliPayApiConfig;
 import com.ijpay.alipay.AliPayApiConfigKit;
@@ -69,6 +74,8 @@ public class FsStorePaymentController extends BaseController
     @Autowired
     HuiFuService huiFuService;
     @Autowired
+    TzBankService tzBankService;
+    @Autowired
     private ICompanyService companyService;
 
     @Autowired
@@ -270,6 +277,43 @@ public class FsStorePaymentController extends BaseController
                     return R.error(refund.getResp_desc());
                 }
 
+            }else if (payment.getPayMode()!=null&&payment.getPayMode().equals("tzbk")){
+                TzConfigInfoDTO tzConfigInfoDTO = TzConfigUtils.getConfig();
+
+                RequestDTO<TzPayRefundDTO> requestDTO = new RequestDTO<TzPayRefundDTO>();
+                TzPayRefundDTO tzPayRefundDTO = new TzPayRefundDTO();
+                tzPayRefundDTO.setOldPayOutOrderNo(payment.getPayCode());
+                tzPayRefundDTO.setRefundOrderNo(payment.getTradeNo());
+                tzPayRefundDTO.setPlatMerCstNo(tzConfigInfoDTO.getPlatMerCstNo());
+                SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
+                tzPayRefundDTO.setTrxSendTime(sdf.format(new Date()));
+                tzPayRefundDTO.setRefundOrdTransAmt(payment.getPayMoney());
+                tzPayRefundDTO.setNotifyURL(tzConfigInfoDTO.getRefundNotifyUrl());
+                requestDTO.setReqBody(tzPayRefundDTO);
+                requestDTO.setReqHeader(TzReqHeaderDTO.getInstance(payment.getPayCode()));
+
+                TzReqResultDTO<TzRefundNotifyDTO> resultDTO;
+
+                try {
+                    resultDTO = tzBankService.payRefund(requestDTO);
+                    TzRefundNotifyDTO body = resultDTO.getBody();
+                    String refundOrdStatus = body.getRefundOrdStatus();
+                    if("90".equals(refundOrdStatus) || "50".equals(refundOrdStatus)){
+                        payment.setRefundMoney(fsStorePayment.getRefundMoney());
+                        payment.setStatus(-1);
+                        payment.setRefundTime(new Date());
+                        fsStorePaymentService.updateFsStorePayment(payment);
+                        //收款 减去所有
+                        if(payment.getCompanyId()!=null&&payment.getCompanyId()>0){
+                            companyService.subCompanyPaymentMoney(payment);
+                        }
+                    } else {
+                        TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
+                        return R.error(resultDTO.getRetMsg());
+                    }
+                } catch (Exception e) {
+                    throw new RuntimeException("退款请求失败"+e);
+                }
             }
             //易宝退款
 

+ 9 - 0
fs-common/src/main/java/com/fs/common/core/redis/RedisCache.java

@@ -24,6 +24,15 @@ public class RedisCache
     @Autowired
     public RedisTemplate redisTemplate;
 
+    /**
+     * 获取Key到期时间
+     * @param key
+     * @return
+     */
+    public Long getExpire(String key){
+        return redisTemplate.getExpire(key,TimeUnit.MILLISECONDS);
+    }
+
     public boolean  hasKey(final String key){
         return redisTemplate.hasKey(key);
     }

+ 8 - 0
fs-service-system/pom.xml

@@ -158,6 +158,14 @@
             <version>2.5.1</version>
         </dependency>
 
+        <dependency>
+            <groupId>com.tzbank</groupId>
+            <artifactId>tzbClient</artifactId>
+            <version>1.0-SNAPSHOT</version>
+            <scope>system</scope>
+            <systemPath>${basedir}/src/main/resources/lib/tzbClient-1.0-SNAPSHOT.jar</systemPath>
+        </dependency>
+
 
     </dependencies>
 </project>

+ 36 - 0
fs-service-system/src/main/java/com/fs/common/DeviceUtils.java

@@ -0,0 +1,36 @@
+package com.fs.common;
+
+import java.net.NetworkInterface;
+import java.net.SocketException;
+import java.util.Enumeration;
+
+public class DeviceUtils {
+    public static String getMacAddress() {
+        try {
+            Enumeration<NetworkInterface> networkInterfaces = NetworkInterface.getNetworkInterfaces();
+            StringBuilder sb = new StringBuilder();
+            while (networkInterfaces.hasMoreElements()) {
+                NetworkInterface networkInterface = networkInterfaces.nextElement();
+                byte[] mac = networkInterface.getHardwareAddress();
+                if (mac != null) {
+
+                    for (int i = 0; i < mac.length; i++) {
+                        sb.append(String.format("%02X%s", mac[i], (i < mac.length - 1) ? "-" : ""));
+                    }
+                    return sb.toString(); //返回第一个不为空的mac地址
+                }
+            }
+        } catch (SocketException e) {
+            e.printStackTrace();
+        }
+        return null;
+    }
+     public static void main(String[] args) {
+        String macAddress = getMacAddress();
+        if (macAddress != null) {
+            System.out.println("MAC Address: " + macAddress);
+        } else {
+            System.out.println("Could not retrieve MAC Address.");
+        }
+    }
+}

+ 96 - 0
fs-service-system/src/main/java/com/fs/huifuPay/dto/QueryOrderInfoDTO.java

@@ -0,0 +1,96 @@
+package com.fs.huifuPay.dto;
+
+import lombok.Data;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+
+/**
+ * 订单信息 DTO
+ *
+ * <p>此类用于封装订单的详细信息,包括订单状态、支付信息、商户信息等。</p>
+ *
+ * @author xdd
+ * @version 1.0
+ * @since 2025-02-27
+ */
+@Data
+public class QueryOrderInfoDTO implements Serializable {
+
+    /**
+     * 订单状态
+     * <p>
+     * 订单状态:
+     * <ul>
+     *     <li>10 - 初始状态</li>
+     *     <li>60 - 交易中</li>
+     *     <li>70 - 交易失败</li>
+     *     <li>80 - 订单关闭</li>
+     *     <li>90 - 交易成功</li>
+     * </ul>
+     */
+    private String status;
+
+    /**
+     * 成功时间 (YYYYMMDDHHmmss)
+     * <p>使用 {@link java.time.LocalDateTime} 类型,方便进行时间处理。</p>
+     */
+    private String succTime;
+     /**
+     *  转换SuccTime,格式为YYYYMMDDHHmmss
+     */
+     public LocalDateTime getFormatSuccTime() {
+        if(this.succTime !=null && !this.succTime.isEmpty()){
+           DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMddHHmmss");
+           return   LocalDateTime.parse(this.succTime,formatter);
+        }
+        return  null;
+
+    }
+    /**
+     * 支付成功金额(订单状态为成功时返回)
+     */
+    private BigDecimal succTrxAmt;
+
+    /**
+     * 支付方式(具体枚举值见《线上收银台支付方式》)
+     */
+    private String payType;
+
+    /**
+     * 白条支付订单号(支付方式为白条支付时返回,表示在支付平台在白条系统的订单号)
+     */
+    private String loanPayOrder;
+
+    /**
+     * 商户手续费(订单状态为成功时返回,现阶段为 0)
+     */
+    private BigDecimal fee;
+
+    /**
+     * 支付来源:
+     * <ul>
+     *     <li>00 - PC</li>
+     *     <li>01 - APP</li>
+     *     <li>02 - H5</li>
+     * </ul>
+     */
+    private String trxPaySource;
+
+    /**
+     * 第三方客户号
+     */
+    private String payCstNo;
+
+    /**
+     * 预下单传了返回地址,此字段会返回相应数据
+     */
+    private String payReturnUrl;
+
+    /**
+     * 渠道交易流水号
+     */
+    private String chlTrxId;
+}

+ 11 - 0
fs-service-system/src/main/java/com/fs/huifuPay/dto/QueryOrderRestDTO.java

@@ -0,0 +1,11 @@
+package com.fs.huifuPay.dto;
+
+import lombok.Data;
+
+import java.io.Serializable;
+
+@Data
+public class QueryOrderRestDTO implements Serializable {
+    private String orderFlowNo;
+    private String platMerCstNo;
+}

+ 26 - 0
fs-service-system/src/main/java/com/fs/huifuPay/dto/RefundParam.java

@@ -0,0 +1,26 @@
+package com.fs.huifuPay.dto;
+
+import lombok.Data;
+
+import java.math.BigDecimal;
+import java.util.List;
+
+@Data
+public class RefundParam {
+    private String oldPayOutOrderNo;   // 商户原支付订单号
+    private String refundOrderNo;      // 商户退款订单号 对接平台系统里自己生成的退款订单号
+    private String trxSendTime;        // 交易发送时间 yyyyMMddHHmmss
+    private String platMerCstNo;       // 平台商户号
+    private Double refundOrdTransAmt;  // 退款金额
+    private String notifyURL; //由企业提供,退款申请后通知业务系统退款结果信息,一般为后端接口地址。因部分网络运营商存在域名解析失败的问题,建议上送IP加端口的形式,该地址需台行开通网络防火墙
+    private List<sharers> sharers;
+
+    @Data
+    public static class sharers {
+        private BigDecimal shareAmt;    // 分账金额
+        private String sharerCstNo;     // 分账方支付平台客户号
+        private String sharerCstName;   // 核心企业客户号
+    }
+
+}
+

+ 40 - 0
fs-service-system/src/main/java/com/fs/huifuPay/dto/RefundResult.java

@@ -0,0 +1,40 @@
+package com.fs.huifuPay.dto;
+
+import lombok.Data;
+
+@Data
+public class RefundResult {
+
+    // 订单状态 (50-退款拒绝, 60-退款中, 70-退款失败, 90-退款成功)
+    private String refundOrdStatus;
+
+    // 商户退款订单号 (对接平台系统里自己生成的退款订单号,同输入)
+    private String refundOrderNo;
+
+    // 退款订单流水号 (行方返回的退款订单流水号)
+    private String refundOrderFlowNo;
+
+    // 退款金额
+    private double refundOrdTransAmt;
+
+    // 商户名称
+    private String refundOrdMerName;
+
+    // 退还手续费
+    private double refundOrdFeeAmt;
+
+    // 订单流水号 (原支付订单流水号)
+    private String refundOrdPayOrdFlowNo;
+
+    // 备注
+    private String refundOrdRemark;
+
+    // 交易类型退款 (2002-退款)
+    private String refundOrdTransType;
+
+    // 商户后台通知地址 (冗余字段,可忽略,同输入字段)
+    private String notifyURL;
+
+    // 币种 (冗余字段,可忽略,均为人民币CNY)
+    private String refundOrdCurrencyNo;
+}

+ 66 - 0
fs-service-system/src/main/java/com/fs/huifuPay/dto/ReqTokenResultDTO.java

@@ -0,0 +1,66 @@
+package com.fs.huifuPay.dto;
+
+import lombok.Data;
+import java.io.Serializable;
+
+/**
+ * 响应结果DTO
+ *
+ * <p>
+ *     此类用于封装服务响应结果。
+ *     包含返回类型、返回码、返回消息、令牌以及随机安全码等信息。
+ * </p>
+ *
+ * @author xdd
+ * @since 2025-02-27
+ */
+@Data
+public class ReqTokenResultDTO implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 返回类型
+     * <p>
+     *     示例值: "S"
+     *     通常表示成功或失败,"S" 可能代表 Success。
+     * </p>
+     */
+    private String retType;
+
+    /**
+     * 返回码
+     * <p>
+     *     示例值: "00000000"
+     *     通常 "00000000" 或类似的编码表示成功。
+     * </p>
+     */
+    private String retCode;
+
+    /**
+     * 返回消息
+     * <p>
+     *     示例值: "success"
+     *     对返回码的文字描述。
+     * </p>
+     */
+    private String retMsg;
+
+    /**
+     * 令牌
+     * <p>
+     *     示例值: "94383736-6870-4bed-8bda-4a23977c9d90"
+     *     用于后续请求的身份验证或授权。
+     * </p>
+     */
+    private String token;
+
+    /**
+     * 随机安全码
+     * <p>
+     *     示例值: "68954728665455B127D943947B6BACF1"
+     *     用于增强安全性,例如防止重放攻击。
+     * </p>
+     */
+    private String randomSec;
+}

+ 24 - 0
fs-service-system/src/main/java/com/fs/huifuPay/dto/RequestDTO.java

@@ -0,0 +1,24 @@
+package com.fs.huifuPay.dto;
+
+import lombok.Data;
+
+/**
+ * 请求DTO
+ * <p>
+ * @author xdd
+ * @date 2025-02-27
+ */
+@Data
+public class RequestDTO<T> {
+
+    /**
+     * 请求头
+     */
+    private TzReqHeaderDTO reqHeader;
+
+    /**
+     * 请求体
+     */
+    private T reqBody;
+
+}

+ 32 - 0
fs-service-system/src/main/java/com/fs/huifuPay/dto/TzMiniProgramCodeReqDTO.java

@@ -0,0 +1,32 @@
+package com.fs.huifuPay.dto;
+
+import lombok.Data;
+
+import java.io.Serializable;
+
+@Data
+public class TzMiniProgramCodeReqDTO implements Serializable {
+    /**
+     * 平台商户客户号
+     * <p>
+     *  示例值:"8197833247112040502"
+     * </p>
+     */
+    private String platMerCstNo;
+
+    /**
+     * 业务客户号
+     * <p>
+     *     示例值:"123456789"
+     * </p>
+     */
+    private String businessCstNo;
+
+    /**
+     * 订单号
+     * <p>
+     *     示例值:"1551965705501422168"
+     * </p>
+     */
+    private String orderNo;
+}

+ 69 - 0
fs-service-system/src/main/java/com/fs/huifuPay/dto/TzMiniProgramCodeRespDTO.java

@@ -0,0 +1,69 @@
+package com.fs.huifuPay.dto;
+
+import lombok.Data;
+import java.io.Serializable;
+
+/**
+ *  请求数据DTO
+ *
+ * <p>
+ *  此类用于封装请求数据。
+ *  包含了平台商户客户号、订单号、平台商户名称、业务客户号、订单金额以及许可证代码等信息。
+ * </p>
+ *
+ * @author xdd
+ * @since 2025-02-27
+ */
+@Data
+public class TzMiniProgramCodeRespDTO implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 平台商户客户号
+     * <p>
+     * 示例值: "8197833247112040502"
+     * </p>
+     */
+    private String platMerCstNo;
+
+    /**
+     * 订单号
+     * <p>
+     * 示例值: "1551965705501422168"
+     * </p>
+     */
+    private String orderNo;
+
+    /**
+     * 平台商户名称
+     * <p>
+     * 示例值: "平台商户一勿动"
+     * </p>
+     */
+    private String platMerCstName;
+
+    /**
+     * 业务客户号
+     * <p>
+     * 示例值: "123456789"
+     * </p>
+     */
+    private String businessCstNo;
+
+    /**
+     * 订单金额
+     * <p>
+     * 示例值: "0.01"
+     * </p>
+     */
+    private String orderAmt;
+
+    /**
+     * 许可证代码
+     * <p>
+     * 示例值: "8wpwx8idtc"
+     * </p>
+     */
+    private String licenseCode;
+}

+ 97 - 0
fs-service-system/src/main/java/com/fs/huifuPay/dto/TzPayCreateOrderReqBodyDTO.java

@@ -0,0 +1,97 @@
+package com.fs.huifuPay.dto;
+
+import lombok.Data;
+
+import java.math.BigDecimal;
+
+/**
+ * 创建订单请求体DTO
+ * <p>
+ * @author xdd
+ * @date 2025-02-27
+ */
+@Data
+public class TzPayCreateOrderReqBodyDTO {
+
+    /**
+     * 订单号
+     */
+    private String orderNo;
+
+     /**
+     * 订单来源
+     */
+    private String orderSource;
+    /**
+     * 交易金额 (单位:元)
+     */
+    private BigDecimal trxAmt;
+
+    /**
+     * 币种
+     * <p>
+     * 示例值: CNY
+     */
+    private String currency;
+
+    /**
+     * 交易类型
+     */
+    private String transType;
+    /**
+     * 商户号
+     */
+    private String tradeMerCstNo;
+
+    /**
+     * 平台商户号
+     */
+    private String platMerCstNo;
+
+    /**
+     * 业务客户号
+     */
+      private String businessCstNo;
+
+
+    /**
+     * 商品信息
+     * <p>
+     * 示例值:Product A - Qty 2, Product B - Qty 1
+     */
+    private String goodsInfo;
+
+    /**
+     * 支付结果通知URL
+     */
+    private String payNotifyUrl;
+
+    /**
+     * 付款人姓名
+     */
+    private String payerName;
+
+    /**
+     * 付款人手机号
+     */
+    private String payerMobileNo;
+
+    /**
+     * 是否需要分账
+     * <p>
+     * "00": 不需要, "01":需要
+     */
+    private String needLedger;
+
+    /**
+     * 订单过期时间
+     * <p>
+     * 时间戳(毫秒)
+     */
+    private String expiredTime;
+
+    /**
+     * 客户端IP
+     */
+    private String clientIp;
+}

+ 46 - 0
fs-service-system/src/main/java/com/fs/huifuPay/dto/TzPayCreateOrderRspDTO.java

@@ -0,0 +1,46 @@
+package com.fs.huifuPay.dto;
+
+import lombok.Data;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+
+/**
+ * payCreateOrder
+ * tzbank创建订单
+ */
+@Data
+public class TzPayCreateOrderRspDTO implements Serializable {
+    /**
+     * 订单流水号.
+     * <p>
+     *     唯一标识一笔订单的流水号。
+     * </p>
+     */
+    private String orderFlowNo;
+
+    /**
+     * 订单号.
+     * <p>
+     *     商户生成的订单号。
+     * </p>
+     */
+    private String orderNo;
+
+    /**
+     * 平台商户客户号.
+     * <p>
+     *     平台分配给商户的客户号。
+     * </p>
+     */
+    private String platMerCstNo;
+
+    /**
+     * 交易金额.
+     * <p>
+     *      单位:元。
+     * </p>
+     * <p>注意:这里使用BigDecimal来处理金额,以避免精度问题</p>
+     */
+    private BigDecimal trxAmt;
+}

+ 44 - 0
fs-service-system/src/main/java/com/fs/huifuPay/dto/TzPayRefundDTO.java

@@ -0,0 +1,44 @@
+package com.fs.huifuPay.dto;
+
+import lombok.Data;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+
+@Data
+public class TzPayRefundDTO implements Serializable {
+    /**
+     * 商户原支付订单号
+     * 即对接平台系统里支付时的那个订单号,对应支付申请接口里的 orderNO
+     */
+    private String oldPayOutOrderNo;
+
+    /**
+     * 商户退款订单号
+     * 对接平台系统里自己生成的退款订单号
+     */
+    private String refundOrderNo;
+
+    /**
+     * 交易发送时间
+     * yyyyMMddHHmmss
+     */
+    private String trxSendTime;
+
+    /**
+     * 平台商户号
+     */
+    private String platMerCstNo;
+
+    /**
+     * 退款金额
+     */
+    private BigDecimal refundOrdTransAmt;
+
+    /**
+     * 退款结果异步通知地址
+     * 由企业提供,退款申请后通知业务系统退款结果信息,一般为后端接口地址。
+     * 因部分网络运营商存在域名解析失败的问题,建议上送 IP 加端口的形式,该地址需台行开通网络防火墙
+     */
+    private String notifyURL;
+}

+ 71 - 0
fs-service-system/src/main/java/com/fs/huifuPay/dto/TzRefundNotifyDTO.java

@@ -0,0 +1,71 @@
+package com.fs.huifuPay.dto;
+
+import lombok.Data;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+
+@Data
+public class TzRefundNotifyDTO implements Serializable {
+    /**
+     * 订单状态
+     * 50-退款拒绝,60-退款中,70-退款失败,90-退款成功
+     */
+    private String refundOrdStatus;
+
+    /**
+     * 商户退款订单号
+     * 对接平台系统里自己生成的退款订单号,同输入
+     */
+    private String refundOrderNo;
+
+    /**
+     * 退款订单流水号
+     * 行方返回的退款订单流水号
+     */
+    private String refundOrderFlowNo;
+
+    /**
+     * 退款金额
+     */
+    private BigDecimal refundOrdTransAmt;
+
+    /**
+     * 商户名称
+     */
+    private String refundOrdMerName;
+
+    /**
+     * 退还手续费
+     */
+    private BigDecimal refundOrdFeeAmt;
+
+    /**
+     * 订单流水号
+     * 订单流水号(原支付订单流水号)
+     */
+    private String refundOrdPayOrdFlowNo;
+
+    /**
+     * 备注
+     */
+    private String refundOrdRemark;
+
+    /**
+     * 交易类型退款
+     * 2002-退款
+     */
+    private String refundOrdTransType;
+
+    /**
+     * 商户后台通知地址
+     * 冗余字段,可忽略,同输入字段
+     */
+    private String notifyURL;
+
+    /**
+     * 币种
+     * 冗余字段,可忽略,均为人民币 CNY
+     */
+    private String refundOrdCurrencyNo;
+}

+ 72 - 0
fs-service-system/src/main/java/com/fs/huifuPay/dto/TzReqHeaderDTO.java

@@ -0,0 +1,72 @@
+package com.fs.huifuPay.dto;
+
+import com.fs.common.DeviceUtils;
+import lombok.Data;
+
+import java.time.LocalDate;
+import java.time.LocalTime;
+import java.time.format.DateTimeFormatter;
+
+/**
+ * 请求头DTO
+ * <p>
+ * @author xdd
+ * @date 2025-02-27
+ */
+@Data
+public class TzReqHeaderDTO {
+
+    /**
+     * 终端类型
+     * <p>
+     * 示例值:WEB
+     */
+    private String cutType;
+
+    /**
+     * 终端号
+     */
+    private String terminalNo;
+
+    /**
+     * 交易日期
+     * <p>
+     * 格式:YYYYMMDD
+     * 示例值:20250312
+     */
+    private String tranDate;
+
+    /**
+     * 交易流水号
+     */
+    private String tranSeq;
+
+    /**
+     * 交易时间
+     *
+     */
+    private String tranTime;
+
+
+    public static TzReqHeaderDTO getInstance(String tranSeq){
+        if(tranSeq == null || tranSeq.trim().isEmpty()){
+            throw new IllegalArgumentException("tranSeq 不能为空");
+        }
+        // 使用当前日期和时间
+        DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("yyyyMMdd");
+        DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern("HHmmssSSS");
+
+        String macAddress = DeviceUtils.getMacAddress();
+        if(macAddress == null || macAddress.trim().isEmpty()){
+            throw new IllegalArgumentException("macAddress 不能为空");
+        }
+        TzReqHeaderDTO reqHeader = new TzReqHeaderDTO();
+        reqHeader.setCutType("WEB");
+        reqHeader.setTerminalNo(macAddress);
+        reqHeader.setTranDate(LocalDate.now().format(dateFormatter));
+        reqHeader.setTranSeq(tranSeq);
+        reqHeader.setTranTime(LocalTime.now().format(timeFormatter));
+
+        return reqHeader;
+    }
+}

+ 54 - 0
fs-service-system/src/main/java/com/fs/huifuPay/dto/TzReqResultDTO.java

@@ -0,0 +1,54 @@
+package com.fs.huifuPay.dto;
+
+import lombok.Data;
+
+import java.io.Serializable;
+
+/**
+ * 交易结果 DTO.
+ *
+ * <p>此类用于封装交易接口返回的数据。</p>
+ *
+ * @author xdd
+ * @version 1.0
+ * @since 2025-02-27
+ */
+@Data
+public class TzReqResultDTO<T> implements Serializable {
+
+    /**
+     * 返回码.
+     * <ul>
+     *     <li>00000000 表示成功</li>
+     *     <li>其他值表示失败,具体含义参考接口文档</li>
+     * </ul>
+     */
+    private String retCode;
+
+    /**
+     * 返回信息.
+     * <ul>
+     *     <li>通常情况下,成功时为 "success"</li>
+     *     <li>失败时为具体的错误信息</li>
+     * </ul>
+     */
+    private String retMsg;
+
+    /**
+     * 返回类型.
+     * <ul>
+     *  <li>S: 成功</li>
+     *  <li>F: 失败</li>
+     *  <li>P: 处理中(可选)</li>
+     * </ul>
+     */
+    private String retType;
+
+    /**
+     * 响应体.
+     */
+    private T body;
+
+
+
+}

+ 13 - 0
fs-service-system/src/main/java/com/fs/store/config/TzBankConfig.java

@@ -0,0 +1,13 @@
+package com.fs.store.config;
+
+import com.tzbank.util.TZBClient;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+public class TzBankConfig {
+    @Bean
+    public TZBClient tzbClient(){
+        return new TZBClient();
+    }
+}

+ 1 - 0
fs-service-system/src/main/java/com/fs/store/domain/FsPayConfig.java

@@ -22,4 +22,5 @@ public class FsPayConfig {
     private String hfPayOnlineNotifyUrl;
     private String hfRefundNotifyUrl;
     private String hfOnlineRefundNotifyUrl;
+
 }

+ 102 - 0
fs-service-system/src/main/java/com/fs/store/domain/TzConfigInfoDTO.java

@@ -0,0 +1,102 @@
+package com.fs.store.domain;
+
+import lombok.Data;
+import java.io.Serializable;
+
+/**
+ * 配置信息DTO
+ *
+ * <p>
+ *  此类用于封装配置信息。
+ *  包含类型、appKey、appSecret、私钥、公钥、UUID 以及 appid 等配置项。
+ * </p>
+ *
+ * @author xdd
+ * @since 2025-02-27
+ */
+@Data
+public class TzConfigInfoDTO implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 类型
+     * <p>
+     * 示例值: "tzbk"
+     * </p>
+     */
+    private String type;
+
+    /**
+     * 应用 Key
+     * <p>
+     * 示例值: "1ef7bb04-a987-45c8-bfa9-1276188b085a"
+     * </p>
+     */
+    private String appKey;
+
+    /**
+     * 应用 Secret
+     * <p>
+     * 示例值: "141B81F09FB32DA2F490BEEBA2135316"
+     * </p>
+     */
+    private String appSecret;
+
+    /**
+     * 私钥
+     * <p>
+     * 示例值: "2AA510FB7AB3637F5044472785A9D1D6EEAEDA1A73EF242570A25C3F23C513AD"
+     * </p>
+     */
+    private String privateKey;
+
+    /**
+     * 公钥
+     * <p>
+     * 示例值: "0452469B7E7BBB00A06A59398967A7A2BA0C727317DC42FF72D146F8069131828DACC6587669FBBDA6637787E23E046C71139E17A16BD489569DA10C9126E3C6BB"
+     * </p>
+     */
+    private String publicKey;
+
+    /**
+     * UUID
+     * <p>
+     * 示例值: "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCB"
+     * </p>
+     */
+    private String uuid;
+
+    /**
+     * 应用 ID
+     * <p>
+     * 示例值: "wx19c8813ffc33d1cb"
+     * </p>
+     */
+    private String appid;
+
+    /**
+     * 平台商户号
+     */
+    private String platMerCstNo;
+
+    /**
+     * 交易商户号
+     */
+    private String tradeMerCstNo;
+
+    /**
+     * 业务平台客户号
+     */
+    private String businessCstNo;
+
+    /**
+     * 支付回调url
+     */
+    private String payNotifyUrl;
+
+    /**
+     * 退款回调url
+     */
+    private String refundNotifyUrl;
+}

+ 40 - 6
fs-service-system/src/main/java/com/fs/store/service/impl/FsStoreAfterSalesServiceImpl.java

@@ -23,14 +23,12 @@ import com.fs.erp.dto.BaseResponse;
 import com.fs.erp.dto.ErpRefundUpdateRequest;
 import com.fs.erp.service.IErpOrderService;
 import com.fs.huifuPay.domain.HuiFuRefundResult;
+import com.fs.huifuPay.dto.*;
 import com.fs.huifuPay.sdk.opps.core.request.V2TradePaymentScanpayRefundRequest;
 import com.fs.huifuPay.service.HuiFuService;
-import com.fs.pay.pay.domain.QueryRefundResult;
+import com.fs.tzBank.TzBankService;
 import com.fs.pay.pay.domain.RefundResult;
-import com.fs.pay.pay.dto.RefundOrderDTO;
 import com.fs.pay.pay.service.PayService;
-import com.fs.pay.pay.service.impl.PayApiServiceImpl;
-import com.fs.pay.service.impl.PayServiceImpl;
 import com.fs.store.config.StoreConfig;
 import com.fs.store.domain.*;
 import com.fs.store.dto.StoreOrderProductDTO;
@@ -44,9 +42,9 @@ import com.fs.store.vo.FsStoreAfterSalesQueryVO;
 import com.fs.store.vo.FsStoreAfterSalesVO;
 import com.fs.store.vo.FsStoreOrderItemVO;
 import com.fs.pay.service.IPayService;
-import com.fs.pay.service.dto.RefundDTO;
 import com.fs.system.service.ISysConfigService;
-import com.hc.openapi.tool.util.Ids;
+import com.fs.tzBank.utils.TzConfigUtils;
+import com.hc.openapi.tool.fastjson.JSON;
 import lombok.Synchronized;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -100,6 +98,9 @@ public class FsStoreAfterSalesServiceImpl implements IFsStoreAfterSalesService
     @Autowired
     PayService ybPayService;
 
+    @Autowired
+    TzBankService tzBankService;
+
 
     /**
      * 查询售后记录
@@ -608,6 +609,39 @@ public class FsStoreAfterSalesServiceImpl implements IFsStoreAfterSalesService
                             return R.error(refund.getResp_desc());
                         }
 
+                    } else if(payment.getPayMode() != null && payment.getPayMode().equals("tzbk")){
+
+                        TzConfigInfoDTO tzConfigInfoDTO = TzConfigUtils.getConfig();
+
+                        RequestDTO<TzPayRefundDTO> requestDTO = new RequestDTO<TzPayRefundDTO>();
+                        TzPayRefundDTO tzPayRefundDTO = new TzPayRefundDTO();
+                        tzPayRefundDTO.setOldPayOutOrderNo(order.getOrderCode());
+                        tzPayRefundDTO.setRefundOrderNo(payment.getTradeNo());
+                        tzPayRefundDTO.setPlatMerCstNo(tzConfigInfoDTO.getPlatMerCstNo());
+                        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
+                        tzPayRefundDTO.setTrxSendTime(sdf.format(new Date()));
+                        tzPayRefundDTO.setRefundOrdTransAmt(order.getPayMoney());
+                        tzPayRefundDTO.setNotifyURL(tzConfigInfoDTO.getRefundNotifyUrl());
+                        requestDTO.setReqBody(tzPayRefundDTO);
+                        requestDTO.setReqHeader(TzReqHeaderDTO.getInstance(order.getOrderCode()));
+
+                        TzReqResultDTO<TzRefundNotifyDTO> resultDTO;
+
+                        try {
+                            resultDTO = tzBankService.payRefund(requestDTO);
+                            TzRefundNotifyDTO body = resultDTO.getBody();
+                            String refundOrdStatus = body.getRefundOrdStatus();
+                            if("90".equals(refundOrdStatus) || "50".equals(refundOrdStatus)){
+                                payment.setRefundMoney(payment.getPayMoney());
+                                payment.setStatus(-1);
+                                payment.setRefundTime(new Date());
+                                paymentService.updateFsStorePayment(payment);
+                            } else {
+                                throw new RuntimeException("退款请求失败:"+ JSON.toJSONString(resultDTO));
+                            }
+                        } catch (Exception e) {
+                            throw new RuntimeException("退款请求失败"+e);
+                        }
                     }
                 }
             }

+ 43 - 1
fs-service-system/src/main/java/com/fs/store/service/impl/FsStoreOrderServiceImpl.java

@@ -44,6 +44,7 @@ import com.fs.erp.domain.*;
 import com.fs.erp.dto.*;
 import com.fs.erp.service.IErpOrderService;
 import com.fs.huifuPay.domain.HuiFuRefundResult;
+import com.fs.huifuPay.dto.*;
 import com.fs.huifuPay.sdk.opps.core.request.V2TradePaymentScanpayRefundRequest;
 import com.fs.huifuPay.service.HuiFuService;
 import com.fs.pay.pay.domain.RefundResult;
@@ -64,6 +65,8 @@ import com.fs.pay.service.IPayService;
 import com.fs.pay.service.dto.RefundDTO;
 import com.fs.system.domain.SysConfig;
 import com.fs.system.service.ISysConfigService;
+import com.fs.tzBank.TzBankService;
+import com.fs.tzBank.utils.TzConfigUtils;
 import com.hc.openapi.tool.util.Ids;
 import lombok.Synchronized;
 import org.slf4j.Logger;
@@ -178,6 +181,9 @@ public class FsStoreOrderServiceImpl implements IFsStoreOrderService
     @Autowired
     HuiFuService huiFuService;
 
+    @Autowired
+    TzBankService tzBankService;
+
     /**
      * 查询订单
      *
@@ -1882,7 +1888,43 @@ public class FsStoreOrderServiceImpl implements IFsStoreOrderService
                             return R.error(refund.getResp_desc());
                         }
 
-                    }else {
+                    }else if (payment.getPayMode()!=null&&payment.getPayMode().equals("tzbk")){
+                        TzConfigInfoDTO tzConfigInfoDTO = TzConfigUtils.getConfig();
+
+                        RequestDTO<TzPayRefundDTO> requestDTO = new RequestDTO<TzPayRefundDTO>();
+                        TzPayRefundDTO tzPayRefundDTO = new TzPayRefundDTO();
+                        tzPayRefundDTO.setOldPayOutOrderNo(payment.getPayCode());
+                        tzPayRefundDTO.setRefundOrderNo(payment.getTradeNo());
+                        tzPayRefundDTO.setPlatMerCstNo(tzConfigInfoDTO.getPlatMerCstNo());
+                        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
+                        tzPayRefundDTO.setTrxSendTime(sdf.format(new Date()));
+                        tzPayRefundDTO.setRefundOrdTransAmt(payment.getPayMoney());
+                        tzPayRefundDTO.setNotifyURL(tzConfigInfoDTO.getRefundNotifyUrl());
+                        requestDTO.setReqBody(tzPayRefundDTO);
+                        requestDTO.setReqHeader(TzReqHeaderDTO.getInstance(payment.getPayCode()));
+
+                        TzReqResultDTO<TzRefundNotifyDTO> resultDTO;
+
+                        try {
+                            resultDTO = tzBankService.payRefund(requestDTO);
+
+                            TzRefundNotifyDTO body = resultDTO.getBody();
+                            String refundOrdStatus = body.getRefundOrdStatus();
+                            if("90".equals(refundOrdStatus) || "50".equals(refundOrdStatus)){
+                                payment.setRefundMoney(payment.getPayMoney());
+                                payment.setStatus(-1);
+                                payment.setRefundTime(new Date());
+                                paymentService.updateFsStorePayment(payment);
+                            } else {
+                                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
+                                return R.error(resultDTO.getRetMsg());
+                            }
+                        } catch (Exception e) {
+                            throw new RuntimeException("退款请求失败"+e);
+                        }
+
+                    }
+                    else {
                         TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                         return R.error("支付类型异常");
                     }

+ 36 - 7
fs-service-system/src/main/java/com/fs/store/service/impl/FsStorePaymentServiceImpl.java

@@ -1,17 +1,14 @@
 package com.fs.store.service.impl;
 
 import java.math.BigDecimal;
-import java.util.ArrayList;
 import java.util.Date;
 import java.util.List;
 import java.util.Map;
-import java.util.concurrent.TimeUnit;
 
 import cn.hutool.core.util.IdUtil;
 import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONObject;
 import com.fs.common.annotation.DataScope;
-import com.fs.common.config.FSConfig;
 import com.fs.common.config.FSSysConfig;
 import com.fs.common.core.controller.BaseController;
 import com.fs.common.core.domain.R;
@@ -23,12 +20,17 @@ import com.fs.company.service.ICompanyService;
 import com.fs.company.service.ICompanyUserService;
 import com.fs.huifuPay.domain.HuiFuCreateOrder;
 import com.fs.huifuPay.domain.HuifuCreateOrderResult;
+import com.fs.huifuPay.dto.RequestDTO;
+import com.fs.huifuPay.dto.TzPayCreateOrderReqBodyDTO;
+import com.fs.huifuPay.dto.TzPayCreateOrderRspDTO;
+import com.fs.huifuPay.dto.TzReqResultDTO;
 import com.fs.huifuPay.service.HuiFuService;
-import com.fs.pay.pay.config.PayConfig;
+import com.fs.tzBank.TzBankService;
 import com.fs.pay.pay.domain.CreateWxOrderResult;
 import com.fs.pay.pay.dto.WxJspayDTO;
 import com.fs.pay.pay.service.PayService;
 import com.fs.store.domain.FsPayConfig;
+import com.fs.store.domain.TzConfigInfoDTO;
 import com.fs.store.param.FsStoreStatisticsParam;
 import com.fs.store.vo.FsStorePaymentStatisticsVO;
 import com.fs.system.service.ISysConfigService;
@@ -40,9 +42,6 @@ import com.fs.store.param.FsStorePaymentParam;
 import com.fs.store.service.IFsUserService;
 import com.fs.store.vo.FsStorePaymentVO;
 import com.fs.pay.service.IPayService;
-import com.fs.pay.service.dto.CreatePayDTO;
-import com.fs.pay.service.dto.PayDTO;
-import com.fs.pay.service.dto.TradeOrder;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -85,6 +84,8 @@ public class FsStorePaymentServiceImpl implements IFsStorePaymentService
     private ISysConfigService configService;
     @Autowired
     HuiFuService huiFuService;
+    @Autowired
+    TzBankService tzBankService;
     /**
      * 查询支付明细
      *
@@ -252,6 +253,34 @@ public class FsStorePaymentServiceImpl implements IFsStorePaymentService
             else{
                 return R.error(wxOrder.getMessage());
             }
+        } else if(fsPayConfig.getType().equals("tzbank")){
+            TzConfigInfoDTO tzConfigInfoDTO = JSON.parseObject(json, TzConfigInfoDTO.class);
+
+            TzPayCreateOrderReqBodyDTO reqBodyDTO = new TzPayCreateOrderReqBodyDTO();
+            RequestDTO<TzPayCreateOrderReqBodyDTO> requestDTO = new RequestDTO<>();
+            reqBodyDTO.setOrderNo(orderSn);
+            reqBodyDTO.setOrderSource("02");
+            reqBodyDTO.setTrxAmt(storePayment.getPayMoney());
+            reqBodyDTO.setCurrency("CNY");
+            reqBodyDTO.setTransType("2001");
+            reqBodyDTO.setTradeMerCstNo(tzConfigInfoDTO.getTradeMerCstNo());
+            reqBodyDTO.setPlatMerCstNo(tzConfigInfoDTO.getPlatMerCstNo());
+            reqBodyDTO.setBusinessCstNo(tzConfigInfoDTO.getBusinessCstNo());
+            reqBodyDTO.setPayNotifyUrl(tzConfigInfoDTO.getPayNotifyUrl());
+            reqBodyDTO.setPayerName(user.getUsername());
+            reqBodyDTO.setPayerMobileNo(user.getPhone());
+            // 不需要分账
+            reqBodyDTO.setNeedLedger("00");
+            reqBodyDTO.setClientIp(IPUtils.getIpAddr(ServletUtils.getRequest()));
+            reqBodyDTO.setExpiredTime("");
+            try {
+                TzReqResultDTO<TzPayCreateOrderRspDTO> payCreateOrder = tzBankService.payCreateOrder(requestDTO);
+            } catch (Exception e) {
+                throw new RuntimeException(e);
+            }
+//            if()
+//            return R.ok().put("result",wxOrder.getPay_info());
+
         }
 
         //小雨点支付

+ 46 - 0
fs-service-system/src/main/java/com/fs/tzBank/TzBankService.java

@@ -0,0 +1,46 @@
+package com.fs.tzBank;
+
+import com.fs.huifuPay.dto.*;
+
+/**
+ * 台州银行服务类
+ */
+public interface TzBankService {
+
+
+    /**
+     * 获取token
+     * @return ReqTokenResultDTO
+     */
+    ReqTokenResultDTO getToken() throws Exception;
+    /**
+     * 支付创建订单
+     * @param requestDTO 请求体
+     * @return TzPayCreateOrderResultDTO
+     */
+    TzReqResultDTO<TzPayCreateOrderRspDTO> payCreateOrder(RequestDTO<TzPayCreateOrderReqBodyDTO> requestDTO) throws Exception;
+
+    /**
+     * 支付创建订单
+     * @param requestDTO 请求体
+     * @return TzPayCreateOrderResultDTO
+     */
+    TzReqResultDTO<TzMiniProgramCodeRespDTO> miniProgramCode(RequestDTO<TzMiniProgramCodeReqDTO> requestDTO) throws Exception;
+
+    /**
+     * 查询支付订单
+     * @param requestDTO 请求DTO
+     * @return TzReqResultDTO<QueryOrderInfoDTO>
+     * @throws Exception 异常信息
+     */
+    TzReqResultDTO<QueryOrderInfoDTO> payQueryOrder(RequestDTO<QueryOrderRestDTO> requestDTO) throws Exception;
+
+    /**
+     * 申请退款
+     * @param requestDTO 请求DTO
+     * @return TzReqResultDTO<TzRefundNotifyDTO>
+     */
+    TzReqResultDTO<TzRefundNotifyDTO> payRefund(RequestDTO<TzPayRefundDTO> requestDTO) throws Exception;
+
+
+}

+ 148 - 0
fs-service-system/src/main/java/com/fs/tzBank/impl/TzBankServiceImpl.java

@@ -0,0 +1,148 @@
+package com.fs.tzBank.impl;
+
+import cn.hutool.core.util.ObjectUtil;
+import com.alibaba.fastjson.JSONObject;
+import com.alibaba.fastjson.TypeReference;
+import com.fs.huifuPay.dto.*;
+import com.fs.tzBank.TzBankService;
+import com.fs.store.domain.TzConfigInfoDTO;
+import com.fs.system.domain.SysConfig;
+import com.fs.system.mapper.SysConfigMapper;
+import com.google.gson.Gson;
+import com.tzbank.util.TZBClient;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+/**
+ * tzBank服务实现类
+ */
+@Service
+@Slf4j
+@RequiredArgsConstructor
+public class TzBankServiceImpl implements TzBankService {
+
+    private static final String urlBase = "https://open.tzbank.com/ApiGateWay/";
+    private static final String getTokenUrl = urlBase+"auth/getToken";
+    private static final String payCreateOrderUrl = urlBase+"apihandle/prod/1.0/payCreateOrder";
+    private static final String miniProgramCodeUrl = urlBase+"apihandle/prod/1.0/miniProgramCode";
+    private static final String payQueryOrderUrl = urlBase+"apihandle/prod/1.0/payQueryOrder";
+    private static final String payRefund = urlBase+"apihandle/prod/1.0/payRefund";
+
+
+    /**
+     * tzbank配置
+     */
+    private static TzConfigInfoDTO tzConfigInfoDTO;
+    @Autowired
+    public void setTzConfig(SysConfigMapper sysConfigMapper){
+        SysConfig sysConfig = sysConfigMapper.selectConfigByConfigKey("store.pay");
+        tzConfigInfoDTO =
+                new Gson().fromJson(sysConfig.getConfigValue(), TzConfigInfoDTO.class);
+    }
+
+    /**
+     * tzbank客户端
+     */
+    private final TZBClient tzbClient;
+
+
+    @Override
+    public ReqTokenResultDTO getToken() {
+        String result = null;
+        try {
+            result = tzbClient.tokenRequest(
+                    getTokenUrl,
+                    tzConfigInfoDTO.getAppKey(),
+                    tzConfigInfoDTO.getAppSecret(), tzConfigInfoDTO.getUuid(),
+                    tzConfigInfoDTO.getPublicKey(),
+                    tzConfigInfoDTO.getPrivateKey());
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+
+        ReqTokenResultDTO reqTokenResultDTO = JSONObject.parseObject(result, ReqTokenResultDTO.class);
+
+        if(ObjectUtil.notEqual(reqTokenResultDTO.getRetCode(),"00000000")){
+            throw new RuntimeException("获取token失败");
+        }
+
+        return reqTokenResultDTO;
+    }
+
+    @Override
+    public TzReqResultDTO<TzPayCreateOrderRspDTO> payCreateOrder(RequestDTO<TzPayCreateOrderReqBodyDTO> requestDTO) throws Exception {
+
+        ReqTokenResultDTO token = this.getToken();
+
+
+        String result = tzbClient.clientRequest(payCreateOrderUrl,
+                tzConfigInfoDTO.getAppKey(),
+                token.getRandomSec(),
+                JSONObject.toJSONString(requestDTO),
+                tzConfigInfoDTO.getPublicKey(),
+                tzConfigInfoDTO.getPrivateKey(),
+                token.getToken()
+        );
+
+        log.info(result);
+        TypeReference<TzReqResultDTO<TzPayCreateOrderRspDTO>> typeReference = new TypeReference<TzReqResultDTO<TzPayCreateOrderRspDTO>>(){};
+
+        return JSONObject.parseObject(result, typeReference);
+    }
+
+    @Override
+    public TzReqResultDTO<TzMiniProgramCodeRespDTO> miniProgramCode(RequestDTO<TzMiniProgramCodeReqDTO> requestDTO) throws Exception {
+        ReqTokenResultDTO token = this.getToken();
+        String result = tzbClient.clientRequest(miniProgramCodeUrl,
+                tzConfigInfoDTO.getAppKey(),
+                token.getRandomSec(),
+                JSONObject.toJSONString(requestDTO),
+                tzConfigInfoDTO.getPublicKey(),
+                tzConfigInfoDTO.getPrivateKey(),
+                token.getToken()
+        );
+        log.info(result);
+
+        TypeReference<TzReqResultDTO<TzMiniProgramCodeRespDTO>> typeReference = new TypeReference<TzReqResultDTO<TzMiniProgramCodeRespDTO>>(){};
+
+        return JSONObject.parseObject(result, typeReference);
+    }
+
+    @Override
+    public TzReqResultDTO<QueryOrderInfoDTO> payQueryOrder(RequestDTO<QueryOrderRestDTO> requestDTO) throws Exception {
+        ReqTokenResultDTO token = this.getToken();
+        String result = tzbClient.clientRequest(payQueryOrderUrl,
+                tzConfigInfoDTO.getAppKey(),
+                token.getRandomSec(),
+                JSONObject.toJSONString(requestDTO),
+                tzConfigInfoDTO.getPublicKey(),
+                tzConfigInfoDTO.getPrivateKey(),
+                token.getToken()
+        );
+        log.info(result);
+
+        TypeReference<TzReqResultDTO<QueryOrderInfoDTO>> typeReference = new TypeReference<TzReqResultDTO<QueryOrderInfoDTO>>(){};
+
+        return JSONObject.parseObject(result, typeReference);
+    }
+
+    @Override
+    public TzReqResultDTO<TzRefundNotifyDTO> payRefund(RequestDTO<TzPayRefundDTO> requestDTO) throws Exception {
+        ReqTokenResultDTO token = this.getToken();
+        String result = tzbClient.clientRequest(payRefund,
+                tzConfigInfoDTO.getAppKey(),
+                token.getRandomSec(),
+                JSONObject.toJSONString(requestDTO),
+                tzConfigInfoDTO.getPublicKey(),
+                tzConfigInfoDTO.getPrivateKey(),
+                token.getToken()
+        );
+        log.info(result);
+
+        TypeReference<TzReqResultDTO<TzRefundNotifyDTO>> typeReference = new TypeReference<TzReqResultDTO<TzRefundNotifyDTO>>(){};
+
+        return JSONObject.parseObject(result, typeReference);
+    }
+}

+ 23 - 0
fs-service-system/src/main/java/com/fs/tzBank/utils/TzConfigUtils.java

@@ -0,0 +1,23 @@
+package com.fs.tzBank.utils;
+
+import cn.hutool.core.bean.BeanUtil;
+import cn.hutool.extra.spring.SpringUtil;
+import com.fs.common.utils.spring.SpringUtils;
+import com.fs.store.domain.TzConfigInfoDTO;
+import com.fs.system.domain.SysConfig;
+import com.fs.system.mapper.SysConfigMapper;
+import com.google.gson.Gson;
+import org.springframework.beans.factory.annotation.Autowired;
+
+/**
+ * 台州银行配置获取
+ */
+public class TzConfigUtils {
+
+    public static TzConfigInfoDTO getConfig(){
+
+        SysConfigMapper sysConfigMapper = SpringUtils.getBean(SysConfigMapper.class);
+        SysConfig sysConfig = sysConfigMapper.selectConfigByConfigKey("store.pay");
+        return new Gson().fromJson(sysConfig.getConfigValue(), TzConfigInfoDTO.class);
+    }
+}

+ 100 - 30
fs-user-app/src/main/java/com/fs/app/controller/StoreOrderController.java

@@ -5,32 +5,30 @@ import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
 
 import cn.hutool.core.util.IdUtil;
 import cn.hutool.core.util.ObjectUtil;
+import cn.hutool.core.util.StrUtil;
 import cn.hutool.json.JSONUtil;
 import com.alibaba.fastjson.JSON;
 import com.fs.app.annotation.Login;
-import com.fs.common.annotation.Log;
 import com.fs.common.annotation.RepeatSubmit;
 
 import com.fs.common.config.FSSysConfig;
 import com.fs.common.core.domain.R;
-import com.fs.common.enums.BusinessType;
 import com.fs.common.exception.CustomException;
-import com.fs.common.utils.IPUtils;
-import com.fs.common.utils.IpUtil;
-import com.fs.common.utils.ParseUtils;
-import com.fs.common.utils.StringUtils;
+import com.fs.common.utils.*;
 import com.fs.huifuPay.domain.HuiFuCreateOrder;
 import com.fs.huifuPay.domain.HuifuCreateOrderResult;
+import com.fs.huifuPay.dto.*;
 import com.fs.huifuPay.service.HuiFuService;
-import com.fs.pay.pay.config.PayConfig;
+import com.fs.tzBank.TzBankService;
 import com.fs.pay.pay.domain.CreateWxOrderResult;
-import com.fs.pay.pay.domain.OrderResult;
 import com.fs.pay.pay.dto.OrderQueryDTO;
 import com.fs.pay.pay.dto.WxJspayDTO;
 import com.fs.pay.pay.service.PayService;
-import com.fs.pay.pay.service.impl.PayApiServiceImpl;
-import com.fs.pay.service.dto.PayQueryDTO;
+import com.fs.store.constants.StoreConstants;
 import com.fs.store.domain.*;
+import com.fs.system.domain.SysConfig;
+import com.fs.system.mapper.SysConfigMapper;
+import com.fs.tzBank.utils.TzConfigUtils;
 import com.fs.wx.miniapp.config.WxMaConfiguration;
 import com.fs.wx.miniapp.config.WxMaProperties;
 import com.fs.wx.pay.config.WxPayProperties;
@@ -45,24 +43,14 @@ import com.fs.store.service.*;
 import com.fs.store.vo.FsMyStoreOrderListQueryVO;
 import com.fs.store.vo.FsStoreOrderItemVO;
 import com.fs.pay.service.IPayService;
-import com.fs.pay.service.dto.CreatePayDTO;
-import com.fs.pay.service.dto.PayDTO;
-import com.fs.pay.service.dto.TradeOrder;
 import com.fs.system.service.ISysConfigService;
-import com.github.binarywang.wxpay.bean.entpay.EntPayResult;
-import com.github.binarywang.wxpay.bean.order.WxPayMpOrderResult;
-import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest;
-import com.github.binarywang.wxpay.config.WxPayConfig;
-import com.github.binarywang.wxpay.exception.WxPayException;
-import com.github.binarywang.wxpay.service.EntPayService;
 import com.github.binarywang.wxpay.service.WxPayService;
 import com.github.pagehelper.PageHelper;
 import com.github.pagehelper.PageInfo;
+import com.google.gson.Gson;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
-import lombok.Synchronized;
 import me.chanjar.weixin.common.error.WxErrorException;
-import org.apache.catalina.servlets.DefaultServlet;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -119,6 +107,10 @@ public class StoreOrderController extends  AppBaseController {
     private IFsStoreProductPackageService productPackageService;
     @Autowired
     PayService ybPayService;
+    @Autowired
+    TzBankService tzBankService;
+
+
 
     @Login
     @ApiOperation("获取我的订单列表")
@@ -294,8 +286,7 @@ public class StoreOrderController extends  AppBaseController {
             String payCode = IdUtil.getSnowflake(0, 0).nextIdStr();
 //            order.setOrderCode(orderCode);
 
-
-            //汇付支付
+            // 台州银行支付
             if(order.getPayType().equals("1")||order.getPayType().equals("2")){
                 String json = configService.selectConfigByKey("store.pay");
                 FsPayConfig fsPayConfig = JSON.parseObject(json, FsPayConfig.class);
@@ -335,8 +326,70 @@ public class StoreOrderController extends  AppBaseController {
                     else{
                         return R.error(result.getResp_desc());
                     }
-                }
-                if (fsPayConfig.getType().equals("yb")){
+                } else if(fsPayConfig.getType().equals("tzbk")){
+                    TzConfigInfoDTO tzConfigInfoDTO = JSON.parseObject(json, TzConfigInfoDTO.class);
+
+                    TzPayCreateOrderReqBodyDTO reqBodyDTO = new TzPayCreateOrderReqBodyDTO();
+                    RequestDTO<TzPayCreateOrderReqBodyDTO> requestDTO = new RequestDTO<>();
+                    reqBodyDTO.setOrderNo(order.getOrderCode());
+                    reqBodyDTO.setOrderSource("02");
+                    reqBodyDTO.setTrxAmt(storePayment.getPayMoney());
+                    reqBodyDTO.setCurrency("CNY");
+                    reqBodyDTO.setTransType("2001");
+                    reqBodyDTO.setTradeMerCstNo(tzConfigInfoDTO.getPlatMerCstNo());
+                    reqBodyDTO.setPlatMerCstNo(tzConfigInfoDTO.getPlatMerCstNo());
+                    reqBodyDTO.setBusinessCstNo(user.getUserId().toString());
+                    reqBodyDTO.setPayNotifyUrl(tzConfigInfoDTO.getPayNotifyUrl());
+                    reqBodyDTO.setPayerName(user.getUsername());
+                    reqBodyDTO.setPayerMobileNo(user.getPhone());
+                    //TODO 商品信息必须获取
+                    reqBodyDTO.setGoodsInfo("测试");
+                    // 不需要分账
+                    reqBodyDTO.setNeedLedger("00");
+                    reqBodyDTO.setClientIp(IPUtils.getIpAddr(ServletUtils.getRequest()));
+                    // 获取订单到期时间
+                    String redisKey = String.valueOf(StrUtil.format("{}{}",
+                            StoreConstants.REDIS_ORDER_OUTTIME_UNPAY, order.getId()));
+                    Long expire = redisCache.getExpire(redisKey);
+                    Long currentTimeMillis = System.currentTimeMillis();
+
+                    reqBodyDTO.setExpiredTime(String.valueOf(currentTimeMillis+expire));
+
+
+
+                    requestDTO.setReqHeader(TzReqHeaderDTO.getInstance(payCode));
+                    requestDTO.setReqBody(reqBodyDTO);
+                    try {
+                        // 创建订单
+                        TzReqResultDTO<TzPayCreateOrderRspDTO> payCreateOrder = tzBankService.payCreateOrder(requestDTO);
+                        // 获得小程序请求码
+                        if("00000000".equals(payCreateOrder.getRetCode())){
+                            TzPayCreateOrderRspDTO body = payCreateOrder.getBody();
+
+                            RequestDTO<TzMiniProgramCodeReqDTO> reqDTORequestDTO = new RequestDTO<>();
+                            TzMiniProgramCodeReqDTO tzMiniProgramCodeReqDTO = new TzMiniProgramCodeReqDTO();
+                            tzMiniProgramCodeReqDTO.setOrderNo(body.getOrderFlowNo());
+                            tzMiniProgramCodeReqDTO.setPlatMerCstNo(tzConfigInfoDTO.getPlatMerCstNo());
+                            tzMiniProgramCodeReqDTO.setBusinessCstNo(user.getUserId().toString());
+                            reqDTORequestDTO.setReqHeader(TzReqHeaderDTO.getInstance(payCode));
+                            reqDTORequestDTO.setReqBody(tzMiniProgramCodeReqDTO);
+                            TzReqResultDTO<TzMiniProgramCodeRespDTO> miniProgramCode = tzBankService.miniProgramCode(reqDTORequestDTO);
+                            if("00000000".equals(miniProgramCode.getRetCode())){
+                                FsStorePayment mt=new FsStorePayment();
+                                mt.setPaymentId(storePayment.getPaymentId());
+                                mt.setTradeNo(miniProgramCode.getBody().getOrderNo());
+                                fsStorePaymentMapper.updateFsStorePayment(mt);
+                                redisCache.setCacheObject("isPaying:"+order.getId(),order.getId().toString(),1, TimeUnit.MINUTES);
+                                return R.ok().put("payType",param.getPayType()).put("result",miniProgramCode.getBody());
+                            } else {
+                                return R.error(miniProgramCode.getRetMsg());
+                            }
+                        }
+                    } catch (Exception e) {
+                        logger.error("系统异常",e);
+                        return R.error("系统异常,请联系管理员!");
+                    }
+                } else if (fsPayConfig.getType().equals("yb")){
                     WxJspayDTO p = new WxJspayDTO();
                     p.setPayMoney(order.getPayMoney().toString());
                     p.setLowOrderId("store-"+payCode);
@@ -506,12 +559,29 @@ public class StoreOrderController extends  AppBaseController {
             for(FsStorePayment payment : payments){
                 OrderQueryDTO orderQueryDTO = new OrderQueryDTO();
                 orderQueryDTO.setLowOrderId("store-"+payment.getPayCode());
-                OrderResult orderResult = ybPayService.getOrder(orderQueryDTO);
-                if(orderResult.getStatus()!= null&&orderResult.getStatus().equals("100")){
-                    if(orderResult.getState()!=null&&orderResult.getState().equals("0")){
-                        return R.error("订单已支付");
-                    }
+                RequestDTO<QueryOrderRestDTO> requestDTO = new RequestDTO<>();
 
+                QueryOrderRestDTO queryOrderRestDTO = new QueryOrderRestDTO();
+
+                queryOrderRestDTO.setOrderFlowNo(payment.getTradeNo());
+                TzConfigInfoDTO tzConfigInfoDTO = TzConfigUtils.getConfig();
+
+                queryOrderRestDTO.setPlatMerCstNo(tzConfigInfoDTO.getPlatMerCstNo());
+
+                requestDTO.setReqBody(queryOrderRestDTO);
+                requestDTO.setReqHeader(TzReqHeaderDTO.getInstance(payment.getPayCode()));
+                try {
+                    TzReqResultDTO<QueryOrderInfoDTO> resultDTO = tzBankService.payQueryOrder(requestDTO);
+                    if(ObjectUtil.isNotNull(resultDTO)){
+                        QueryOrderInfoDTO body = resultDTO.getBody();
+                        if(ObjectUtil.isNotNull(body)){
+                            if("80".equals(body.getStatus()) || "90".equals(body.getStatus())){
+                                return R.error("订单已支付");
+                            }
+                        }
+                    }
+                } catch (Exception e) {
+                    throw new RuntimeException(e);
                 }
             }
         }