From 3f17034c768ba4fc330e01f014b4f880e6a1569c Mon Sep 17 00:00:00 2001
From: Administrator <zhubaomin>
Date: 星期二, 12 三月 2024 16:03:30 +0800
Subject: [PATCH] 2024-03-12 朱宝民 增加已挂失,未补卡接口

---
 pipIrr-platform/pipIrr-web/pipIrr-web-sell/src/main/java/com/dy/pipIrrSell/virtualCard/VirtualCardCtrl.java           |  162 +++++
 pipIrr-platform/pipIrr-web/pipIrr-web-sell/src/main/java/com/dy/pipIrrSell/config/RestTemplateConfig.java             |    1 
 pipIrr-platform/pipIrr-global/src/main/resources/mapper/SeVcRefundItemMapper.xml                                      |  168 +++++
 pipIrr-platform/pipIrr-web/pipIrr-web-sell/src/main/java/com/dy/pipIrrSell/virtualCard/enums/RefundStateENUM.java     |   22 
 pipIrr-platform/pipIrr-global/src/main/java/com/dy/pipIrrGlobal/daoSe/SeVcRefundMapper.java                           |   37 +
 pipIrr-platform/pipIrr-web/pipIrr-web-sell/src/main/java/com/dy/pipIrrSell/wechatpay/dto/ToRefund.java                |   35 +
 pipIrr-platform/pipIrr-global/src/main/java/com/dy/pipIrrGlobal/daoSe/SeVcRechargeMapper.java                         |   18 
 pipIrr-platform/pipIrr-web/pipIrr-web-sell/src/main/java/com/dy/pipIrrSell/virtualCard/dto/DtoRefund.java             |   34 +
 pipIrr-platform/pipIrr-global/src/main/resources/mapper/SeVcRechargeMapper.xml                                        |   28 
 pipIrr-platform/pipIrr-global/src/main/java/com/dy/pipIrrGlobal/voSe/VoOrders.java                                    |   44 +
 pipIrr-platform/pipIrr-global/src/main/java/com/dy/pipIrrGlobal/pojoSe/SeVcRefundItem.java                            |   88 ++
 pipIrr-platform/pipIrr-global/src/main/resources/mapper/SeClientCardMapper.xml                                        |   36 +
 pipIrr-platform/pipIrr-web/pipIrr-web-sell/src/main/java/com/dy/pipIrrSell/virtualCard/enums/RefundItemStateENUM.java |   21 
 pipIrr-platform/pipIrr-web/pipIrr-web-sell/src/main/java/com/dy/pipIrrSell/virtualCard/enums/LastOperateENUM.java     |    3 
 pipIrr-platform/pipIrr-web/pipIrr-web-sell/src/main/java/com/dy/pipIrrSell/clientCard/ClientCardCtrl.java             |   30 +
 pipIrr-platform/pipIrr-web/pipIrr-web-sell/src/main/java/com/dy/pipIrrSell/virtualCard/dto/DtoAudit.java              |   40 +
 pipIrr-platform/pipIrr-web/pipIrr-web-sell/src/main/java/com/dy/pipIrrSell/wallet/WalletSv.java                       |    2 
 pipIrr-platform/pipIrr-web/pipIrr-web-sell/src/main/java/com/dy/pipIrrSell/wechatpay/dto/Orders.java                  |   44 +
 pipIrr-platform/pipIrr-web/pipIrr-web-sell/src/main/java/com/dy/pipIrrSell/clientCard/ClientCardSv.java               |   19 
 pipIrr-platform/pipIrr-global/src/main/java/com/dy/pipIrrGlobal/pojoSe/SeVcRefund.java                                |  116 +++
 pipIrr-platform/pipIrr-web/pipIrr-web-sell/src/main/java/com/dy/pipIrrSell/virtualCard/VirtualCardSv.java             |  126 ++++
 pipIrr-platform/pipIrr-web/pipIrr-web-sell/src/main/java/com/dy/pipIrrSell/wechatpay/PayInfo.java                     |    2 
 pipIrr-platform/pipIrr-web/pipIrr-web-sell/src/main/java/com/dy/pipIrrSell/wechatpay/dto/Refund.java                  |    2 
 pipIrr-platform/pipIrr-global/src/main/java/com/dy/pipIrrGlobal/daoSe/SeClientCardMapper.java                         |   12 
 pipIrr-platform/pipIrr-global/src/main/resources/mapper/SeVcRefundMapper.xml                                          |  211 +++++++
 pipIrr-platform/pipIrr-web/pipIrr-web-sell/src/main/java/com/dy/pipIrrSell/util/PayHelper.java                        |  172 +++++
 pipIrr-platform/pipIrr-web/pipIrr-web-sell/src/main/java/com/dy/pipIrrSell/result/SellResultCode.java                 |    1 
 pipIrr-platform/pipIrr-web/pipIrr-web-sell/src/main/java/com/dy/pipIrrSell/wechatpay/PaymentCtrl.java                 |  239 +++----
 pipIrr-platform/pipIrr-global/src/main/java/com/dy/pipIrrGlobal/daoSe/SeVcRefundItemMapper.java                       |   49 +
 29 files changed, 1,615 insertions(+), 147 deletions(-)

diff --git a/pipIrr-platform/pipIrr-global/src/main/java/com/dy/pipIrrGlobal/daoSe/SeClientCardMapper.java b/pipIrr-platform/pipIrr-global/src/main/java/com/dy/pipIrrGlobal/daoSe/SeClientCardMapper.java
index b329fa7..b75f7ce 100644
--- a/pipIrr-platform/pipIrr-global/src/main/java/com/dy/pipIrrGlobal/daoSe/SeClientCardMapper.java
+++ b/pipIrr-platform/pipIrr-global/src/main/java/com/dy/pipIrrGlobal/daoSe/SeClientCardMapper.java
@@ -107,4 +107,16 @@
      * @return
      */
     List<VoCards> getCards(Map<?, ?> params);
+
+    /**
+     * 鑾峰彇宸叉寕澶憋紝鏈ˉ鍗$殑璁板綍鏁伴噺锛屽簲鐢ㄧ▼搴忎娇鐢�
+     * @return
+     */
+    Long getUnreplacedRecordCount();
+
+    /**
+     * 鑾峰彇宸叉寕澶憋紝鏈ˉ鍗$殑璁板綍锛屽簲鐢ㄧ▼搴忎娇鐢�
+     * @return
+     */
+    List<VoCards> getUnreplaced(Map<?, ?> params);
 }
\ No newline at end of file
diff --git a/pipIrr-platform/pipIrr-global/src/main/java/com/dy/pipIrrGlobal/daoSe/SeVcRechargeMapper.java b/pipIrr-platform/pipIrr-global/src/main/java/com/dy/pipIrrGlobal/daoSe/SeVcRechargeMapper.java
index dcf8965..4c96274 100644
--- a/pipIrr-platform/pipIrr-global/src/main/java/com/dy/pipIrrGlobal/daoSe/SeVcRechargeMapper.java
+++ b/pipIrr-platform/pipIrr-global/src/main/java/com/dy/pipIrrGlobal/daoSe/SeVcRechargeMapper.java
@@ -2,7 +2,11 @@
 
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.dy.pipIrrGlobal.pojoSe.SeVcRecharge;
+import com.dy.pipIrrGlobal.voSe.VoOrders;
 import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
 
 /**
  * @author ZhuBaoMin
@@ -31,4 +35,18 @@
      * @return
      */
     SeVcRecharge getVCRechargeByorderNumber(String orderNumber);
+
+    /**
+     * 鏍规嵁铏氭嫙鍗″彿鑾峰彇璁㈠崟鍒楄〃
+     * @param virtualId
+     * @return
+     */
+    List<VoOrders> getOrders(@Param("virtualId") Long virtualId);
+
+    /**
+     * 鏍规嵁璁㈠崟鍙疯幏鍙栧厖鍊奸噾棰�
+     * @param orderNumber
+     * @return
+     */
+    Integer getRechargeAmountByOrderNumber(@Param("orderNumber") String orderNumber);
 }
\ No newline at end of file
diff --git a/pipIrr-platform/pipIrr-global/src/main/java/com/dy/pipIrrGlobal/daoSe/SeVcRefundItemMapper.java b/pipIrr-platform/pipIrr-global/src/main/java/com/dy/pipIrrGlobal/daoSe/SeVcRefundItemMapper.java
new file mode 100644
index 0000000..d86ef0d
--- /dev/null
+++ b/pipIrr-platform/pipIrr-global/src/main/java/com/dy/pipIrrGlobal/daoSe/SeVcRefundItemMapper.java
@@ -0,0 +1,49 @@
+package com.dy.pipIrrGlobal.daoSe;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.dy.pipIrrGlobal.pojoSe.SeVcRefundItem;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+
+/**
+ * @author ZhuBaoMin
+ * @date 2024-03-10 21:05
+ * @LastEditTime 2024-03-10 21:05
+ * @Description
+ */
+
+@Mapper
+public interface SeVcRefundItemMapper extends BaseMapper<SeVcRefundItem> {
+    int deleteByPrimaryKey(Long id);
+
+    int insert(SeVcRefundItem record);
+
+    int insertSelective(SeVcRefundItem record);
+
+    SeVcRefundItem selectByPrimaryKey(Long id);
+
+    int updateByPrimaryKeySelective(SeVcRefundItem record);
+
+    int updateByPrimaryKey(SeVcRefundItem record);
+
+    /**
+     * 鏍规嵁璁㈠崟鍙疯幏鍙栨渶鍚庝竴涓��鍗曞彿
+     * @param orderNumber
+     * @return
+     */
+    String getLastRefundNumber(@Param("orderNumber") String orderNumber);
+
+    /**
+     * 鏍规嵁閫�娆鹃�氱煡鎺ュ彛杩斿洖鐨勯��娆惧崟鍙峰弽鏌ラ��娆綢D锛屾煡璇㈣閫�娆綢D涓嬫湭閫�娆捐褰曟暟閲�
+     * @param refundNumber
+     * @return
+     */
+    Integer getNoRefundedCount(String refundNumber);
+
+    /**
+     * 鏍规嵁閫�娆惧崟鍙疯幏鍙栭��娆綢D锛岄��娆鹃�氱煡鍚庢洿鏂伴��娆捐〃鎵�闇�
+     * @param refundNumber
+     * @return
+     */
+    Long getRefundIdByRefundNumber(String refundNumber);
+}
\ No newline at end of file
diff --git a/pipIrr-platform/pipIrr-global/src/main/java/com/dy/pipIrrGlobal/daoSe/SeVcRefundMapper.java b/pipIrr-platform/pipIrr-global/src/main/java/com/dy/pipIrrGlobal/daoSe/SeVcRefundMapper.java
new file mode 100644
index 0000000..7e632ad
--- /dev/null
+++ b/pipIrr-platform/pipIrr-global/src/main/java/com/dy/pipIrrGlobal/daoSe/SeVcRefundMapper.java
@@ -0,0 +1,37 @@
+package com.dy.pipIrrGlobal.daoSe;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.dy.pipIrrGlobal.pojoSe.SeVcRefund;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+/**
+ * @author ZhuBaoMin
+ * @date 2024-03-08 11:06
+ * @LastEditTime 2024-03-08 11:06
+ * @Description
+ */
+
+@Mapper
+public interface SeVcRefundMapper extends BaseMapper<SeVcRefund> {
+    int deleteByPrimaryKey(Long id);
+
+    int insert(SeVcRefund record);
+
+    int insertSelective(SeVcRefund record);
+
+    SeVcRefund selectByPrimaryKey(Long id);
+
+    int updateByPrimaryKeySelective(SeVcRefund record);
+
+    int updateByPrimaryKey(SeVcRefund record);
+
+    /**
+     * 鏍规嵁璁㈠崟鍙疯幏鍙栧叾鍚勭瑪閫�娆鹃噾棰�
+     * @param orderNumber
+     * @return
+     */
+    List<Integer> getRefundAmount(@Param("orderNumber") String orderNumber);
+}
\ No newline at end of file
diff --git a/pipIrr-platform/pipIrr-global/src/main/java/com/dy/pipIrrGlobal/pojoSe/SeVcRefund.java b/pipIrr-platform/pipIrr-global/src/main/java/com/dy/pipIrrGlobal/pojoSe/SeVcRefund.java
new file mode 100644
index 0000000..2c15c12
--- /dev/null
+++ b/pipIrr-platform/pipIrr-global/src/main/java/com/dy/pipIrrGlobal/pojoSe/SeVcRefund.java
@@ -0,0 +1,116 @@
+package com.dy.pipIrrGlobal.pojoSe;
+
+import com.alibaba.fastjson2.annotation.JSONField;
+import com.alibaba.fastjson2.writer.ObjectWriterImplToString;
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.dy.common.po.BaseEntity;
+import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.constraints.NotNull;
+import lombok.*;
+
+import java.util.Date;
+
+/**
+ * @author ZhuBaoMin
+ * @date 2024-03-08 11:06
+ * @LastEditTime 2024-03-08 11:06
+ * @Description
+ */
+
+@TableName(value="se_vc_refund", autoResultMap = true)
+@Data
+@Builder
+@ToString
+@NoArgsConstructor
+@AllArgsConstructor
+@Schema(name = "铏氭嫙鍗¢��娆惧疄浣�")
+public class SeVcRefund implements BaseEntity {
+    public static final long serialVersionUID = 202403081109001L;
+
+    /**
+    * 涓婚敭
+    */
+    @JSONField(serializeUsing= ObjectWriterImplToString.class)
+    @TableId(type = IdType.INPUT)
+    @Schema(description = "瀹炰綋id", requiredMode = Schema.RequiredMode.NOT_REQUIRED)
+    private Long id;
+
+    /**
+    * 铏氭嫙鍗D
+    */
+    @Schema(description = "铏氭嫙鍗D", requiredMode = Schema.RequiredMode.NOT_REQUIRED)
+    @NotNull(message = "铏氭嫙鍗D涓嶈兘涓虹┖")
+    private Long vcId;
+
+    /**
+    * 鍐滄埛ID
+    */
+    @Schema(description = "鍐滄埛ID", requiredMode = Schema.RequiredMode.NOT_REQUIRED)
+    @NotNull(message = "鍐滄埛ID涓嶈兘涓虹┖")
+    private Long clientId;
+
+    /**
+    * 铏氭嫙鍗′綑棰濓紝閫�娆鹃�氱煡鍚庢洿鏂颁綑棰�
+    */
+    @Schema(description = "铏氭嫙鍗′綑棰�", requiredMode = Schema.RequiredMode.NOT_REQUIRED)
+    private Double money;
+
+    /**
+    * 閫�娆鹃噾棰�
+    */
+    @Schema(description = "閫�娆鹃噾棰�", requiredMode = Schema.RequiredMode.NOT_REQUIRED)
+    @NotNull(message = "閫�娆鹃噾棰濅笉鑳戒负绌�")
+    private Integer refundAmount;
+
+    /**
+    * 閫�娆惧悗浣欓
+    */
+    @Schema(description = "閫�娆惧悗浣欓", requiredMode = Schema.RequiredMode.NOT_REQUIRED)
+    private Double afterRefund;
+
+    /**
+    * 鐢宠鏃堕棿
+    */
+    @Schema(description = "鐢宠鏃堕棿", requiredMode = Schema.RequiredMode.NOT_REQUIRED)
+    @NotNull(message = "鐢宠鏃堕棿涓嶈兘涓虹┖")
+    private Date applicationTime;
+
+    /**
+    * 瀹℃牳浜�
+    */
+    @Schema(description = "瀹℃牳浜�", requiredMode = Schema.RequiredMode.NOT_REQUIRED)
+    private Long auditor;
+
+    /**
+    * 瀹℃牳鏃堕棿
+    */
+    @Schema(description = "瀹℃牳鏃堕棿", requiredMode = Schema.RequiredMode.NOT_REQUIRED)
+    private Date auditTime;
+
+    /**
+    * 瀹℃牳澶囨敞
+    */
+    @Schema(description = "瀹℃牳澶囨敞", requiredMode = Schema.RequiredMode.NOT_REQUIRED)
+    private String remarks;
+
+    /**
+    * 閫�娆惧崟鍙�;12浣嶅啘鎴峰彿+17浣嶆椂闂存埑+2浣嶆暟閲�
+    */
+    @Schema(description = "閫�娆惧崟鍙�", requiredMode = Schema.RequiredMode.NOT_REQUIRED)
+    private String refundNumber;
+
+    /**
+    * 閫�娆惧畬鎴愭椂闂�
+    */
+    @Schema(description = "閫�娆惧畬鎴愭椂闂�", requiredMode = Schema.RequiredMode.NOT_REQUIRED)
+    private Date refundTime;
+
+    /**
+    * 閫�娆剧姸鎬�;1-寰呭鏍革紝2-寰呴��娆撅紝3-宸查��娆�
+    */
+    @Schema(description = "閫�娆剧姸鎬�", requiredMode = Schema.RequiredMode.NOT_REQUIRED)
+    private Byte refundStatus;
+
+}
\ No newline at end of file
diff --git a/pipIrr-platform/pipIrr-global/src/main/java/com/dy/pipIrrGlobal/pojoSe/SeVcRefundItem.java b/pipIrr-platform/pipIrr-global/src/main/java/com/dy/pipIrrGlobal/pojoSe/SeVcRefundItem.java
new file mode 100644
index 0000000..ee8ba08
--- /dev/null
+++ b/pipIrr-platform/pipIrr-global/src/main/java/com/dy/pipIrrGlobal/pojoSe/SeVcRefundItem.java
@@ -0,0 +1,88 @@
+package com.dy.pipIrrGlobal.pojoSe;
+
+import com.alibaba.fastjson2.annotation.JSONField;
+import com.alibaba.fastjson2.writer.ObjectWriterImplToString;
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.dy.common.po.BaseEntity;
+import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotNull;
+import lombok.*;
+
+import java.util.Date;
+
+/**
+ * @author ZhuBaoMin
+ * @date 2024-03-10 21:05
+ * @LastEditTime 2024-03-10 21:05
+ * @Description
+ */
+
+@TableName(value="se_vc_refund_item", autoResultMap = true)
+@Data
+@Builder
+@ToString
+@NoArgsConstructor
+@AllArgsConstructor
+@Schema(name = "铏氭嫙鍗¢��娆惧垎椤瑰疄浣�")
+public class SeVcRefundItem implements BaseEntity {
+    public static final long serialVersionUID = 202403102108001L;
+
+    /**
+     * 涓婚敭
+     */
+    @JSONField(serializeUsing= ObjectWriterImplToString.class)
+    @TableId(type = IdType.INPUT)
+    @Schema(description = "瀹炰綋id", requiredMode = Schema.RequiredMode.NOT_REQUIRED)
+    private Long id;
+
+    /**
+     * 閫�娆綢D
+     */
+    @Schema(description = "閫�娆綢D", requiredMode = Schema.RequiredMode.NOT_REQUIRED)
+    @NotNull(message = "閫�娆綢D涓嶈兘涓虹┖")
+    private Long refundId;
+
+    /**
+     * 璁㈠崟鍙�;12浣嶅啘鎴峰ソ+17浣嶆椂闂存埑
+     */
+    @Schema(description = "璁㈠崟鍙�", requiredMode = Schema.RequiredMode.NOT_REQUIRED)
+    @NotBlank(message = "璁㈠崟鍙蜂笉鑳戒负绌�")
+    private String orderNumber;
+
+    /**
+     * 閫�娆惧崟鍙�;12浣嶅啘鎴峰彿+17浣嶆椂闂存埑+2浣嶆暟閲�
+     */
+    @Schema(description = "閫�娆惧崟鍙�", requiredMode = Schema.RequiredMode.NOT_REQUIRED)
+    @NotBlank(message = "閫�娆惧崟鍙蜂笉鑳戒负绌�")
+    private String refundNumber;
+
+    /**
+     * 閫�娆鹃噾棰�;涓庤鍗曞搴旂殑閫�娆鹃噾棰�
+     */
+    @Schema(description = "閫�娆鹃噾棰�", requiredMode = Schema.RequiredMode.NOT_REQUIRED)
+    @NotNull(message = "閫�娆鹃噾棰濅笉鑳戒负绌�")
+    private Integer refundAmount;
+
+    /**
+     * 閫�娆惧崟鍒涘缓鏃堕棿
+     */
+    @Schema(description = "閫�娆惧崟鍒涘缓鏃堕棿", requiredMode = Schema.RequiredMode.NOT_REQUIRED)
+    @NotNull(message = "閫�娆惧崟鍒涘缓鏃堕棿涓嶈兘涓虹┖")
+    private Date createTime;
+
+    /**
+     * 閫�娆惧畬鎴愭椂闂�
+     */
+    @Schema(description = "閫�娆惧畬鎴愭椂闂�", requiredMode = Schema.RequiredMode.NOT_REQUIRED)
+    private Date refundTime;
+
+    /**
+     * 閫�娆剧姸鎬�;1-鏈��娆撅紝2-宸查��娆�
+     */
+    @Schema(description = "閫�娆剧姸鎬�", requiredMode = Schema.RequiredMode.NOT_REQUIRED)
+    private Byte refundStatus;
+
+}
\ No newline at end of file
diff --git a/pipIrr-platform/pipIrr-global/src/main/java/com/dy/pipIrrGlobal/voSe/VoOrders.java b/pipIrr-platform/pipIrr-global/src/main/java/com/dy/pipIrrGlobal/voSe/VoOrders.java
new file mode 100644
index 0000000..9a3ea4e
--- /dev/null
+++ b/pipIrr-platform/pipIrr-global/src/main/java/com/dy/pipIrrGlobal/voSe/VoOrders.java
@@ -0,0 +1,44 @@
+package com.dy.pipIrrGlobal.voSe;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotNull;
+import jakarta.validation.constraints.Positive;
+import lombok.Data;
+
+import java.util.Date;
+
+/**
+ * @author ZhuBaoMin
+ * @date 2024-03-08 9:36
+ * @LastEditTime 2024-03-08 9:36
+ * @Description
+ */
+
+@Data
+@Schema(title = "璁㈠崟瑙嗗浘瀵硅薄")
+public class VoOrders {
+    public static final long serialVersionUID = 202403072157001L;
+
+    /**
+     * 璁㈠崟鍙�
+     */
+    @Schema(description = "璁㈠崟鍙�", requiredMode = Schema.RequiredMode.NOT_REQUIRED)
+    @NotBlank(message = "璁㈠崟鍙蜂笉鑳戒负绌�")
+    private String orderNumber;
+
+    /**
+     * 鍏呭�奸噾棰�
+     */
+    @Schema(description = "鍏呭�奸噾棰�", requiredMode = Schema.RequiredMode.NOT_REQUIRED)
+    @NotNull(message = "鍏呭�奸噾棰濅笉鑳戒负绌�")
+    @Positive(message = "鍏呭�奸噾棰濆繀椤讳负澶т簬0鐨勬暣鏁�")
+    private Integer rechargeAmount;
+
+    /**
+     * 鍏呭�煎畬鎴愭椂闂�
+     */
+    @Schema(description = "鍏呭�煎畬鎴愭椂闂�", requiredMode = Schema.RequiredMode.NOT_REQUIRED)
+    @NotNull(message = "鍏呭�煎畬鎴愭椂闂翠笉鑳戒负绌�")
+    private Date rechargeTime;
+}
diff --git a/pipIrr-platform/pipIrr-global/src/main/resources/mapper/SeClientCardMapper.xml b/pipIrr-platform/pipIrr-global/src/main/resources/mapper/SeClientCardMapper.xml
index 8fb2f81..f2d8c83 100644
--- a/pipIrr-platform/pipIrr-global/src/main/resources/mapper/SeClientCardMapper.xml
+++ b/pipIrr-platform/pipIrr-global/src/main/resources/mapper/SeClientCardMapper.xml
@@ -387,4 +387,40 @@
       </if>
     </trim>
   </select>
+
+  <!--鑾峰彇宸叉寕澶辨湭琛ュ崱鐨勮褰曟暟閲�-->
+  <select id="getUnreplacedRecordCount" resultType="java.lang.Long">
+    SELECT
+        COUNT(*) AS recordCount
+    FROM se_client_card card
+        INNER JOIN se_client cli ON card.clientId = cli.id
+    WHERE card.state = 3 AND NOT EXISTS (SELECT * FROM se_client_card card2 WHERE card.clientId = card2.clientId AND card2.state = 1)
+  </select>
+
+  <!--鑾峰彇宸叉寕澶辨湭琛ュ崱鐨勮褰�-->
+  <select id="getUnreplaced" resultType="com.dy.pipIrrGlobal.voSe.VoCards">
+    SELECT
+        cli.clientNum,
+        cli.name AS clientName,
+        card.cardNum,
+        cli.phone,
+        cli.idCard,
+        card.state AS cardState,
+        (CASE
+            WHEN card.state = 1 THEN '姝e父'
+            WHEN card.state = 2 THEN '宸叉敞閿�'
+            WHEN card.state = 3 THEN '宸叉寕澶�'
+        End) AS stateName,
+        '鍐滄埛鍗�' AS cardType,
+        FORMAT(card.money,2) AS money
+    FROM se_client_card card
+        INNER JOIN se_client cli ON card.clientId = cli.id
+    WHERE card.state = 3 AND NOT EXISTS (SELECT * FROM se_client_card card2 WHERE card.clientId = card2.clientId AND card2.state = 1)
+    ORDER BY card.id
+    <trim prefix="limit " >
+      <if test="start != null and count != null">
+        #{start,javaType=Integer,jdbcType=INTEGER}, #{count,javaType=Integer,jdbcType=INTEGER}
+      </if>
+    </trim>
+  </select>
 </mapper>
\ No newline at end of file
diff --git a/pipIrr-platform/pipIrr-global/src/main/resources/mapper/SeVcRechargeMapper.xml b/pipIrr-platform/pipIrr-global/src/main/resources/mapper/SeVcRechargeMapper.xml
index 95b5342..de16e7a 100644
--- a/pipIrr-platform/pipIrr-global/src/main/resources/mapper/SeVcRechargeMapper.xml
+++ b/pipIrr-platform/pipIrr-global/src/main/resources/mapper/SeVcRechargeMapper.xml
@@ -168,4 +168,32 @@
     WHERE order_number = #{orderNumber}
     LIMIT 0,1
   </select>
+
+  <!--鏍规嵁铏氭嫙鍗″彿鑾峰彇璁㈠崟鍒楄〃-->
+  <select id="getOrders" resultType="com.dy.pipIrrGlobal.voSe.VoOrders">
+    SELECT
+      order_number AS orderNumber,
+      recharge_amount AS rechargeAmount,
+      recharge_time AS rechargeTime
+    FROM se_vc_recharge
+    <where>
+      AND order_state = 2
+      <if test = "virtualId != null and virtualId > 0">
+        AND vc_id = ${virtualId}
+      </if>
+    </where>
+    ORDER BY order_number
+  </select>
+
+<!--鏍规嵁璁㈠崟鍙疯幏鍙栧厖鍊奸噾棰�-->
+  <select id="getRechargeAmountByOrderNumber" resultType="java.lang.Integer">
+    SELECT
+        recharge_amount AS rechargeAmount
+    FROM se_vc_recharge
+    <where>
+      <if test = "orderNumber != null and orderNumber !=''">
+        AND order_number = #{orderNumber}
+      </if>
+    </where>
+  </select>
 </mapper>
\ No newline at end of file
diff --git a/pipIrr-platform/pipIrr-global/src/main/resources/mapper/SeVcRefundItemMapper.xml b/pipIrr-platform/pipIrr-global/src/main/resources/mapper/SeVcRefundItemMapper.xml
new file mode 100644
index 0000000..f381ebe
--- /dev/null
+++ b/pipIrr-platform/pipIrr-global/src/main/resources/mapper/SeVcRefundItemMapper.xml
@@ -0,0 +1,168 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.dy.pipIrrGlobal.daoSe.SeVcRefundItemMapper">
+  <resultMap id="BaseResultMap" type="com.dy.pipIrrGlobal.pojoSe.SeVcRefundItem">
+    <!--@mbg.generated-->
+    <!--@Table se_vc_refund_item-->
+    <id column="id" jdbcType="BIGINT" property="id" />
+    <result column="refund_id" jdbcType="BIGINT" property="refundId" />
+    <result column="order_number" jdbcType="VARCHAR" property="orderNumber" />
+    <result column="refund_number" jdbcType="VARCHAR" property="refundNumber" />
+    <result column="refund_amount" jdbcType="INTEGER" property="refundAmount" />
+    <result column="create_time" jdbcType="TIMESTAMP" property="createTime" />
+    <result column="refund_time" jdbcType="TIMESTAMP" property="refundTime" />
+    <result column="refund_status" jdbcType="TINYINT" property="refundStatus" />
+  </resultMap>
+  <sql id="Base_Column_List">
+    <!--@mbg.generated-->
+    id, refund_id, order_number, refund_number, refund_amount, create_time, refund_time, 
+    refund_status
+  </sql>
+  <select id="selectByPrimaryKey" parameterType="java.lang.Long" resultMap="BaseResultMap">
+    <!--@mbg.generated-->
+    select 
+    <include refid="Base_Column_List" />
+    from se_vc_refund_item
+    where id = #{id,jdbcType=BIGINT}
+  </select>
+  <delete id="deleteByPrimaryKey" parameterType="java.lang.Long">
+    <!--@mbg.generated-->
+    delete from se_vc_refund_item
+    where id = #{id,jdbcType=BIGINT}
+  </delete>
+  <insert id="insert" parameterType="com.dy.pipIrrGlobal.pojoSe.SeVcRefundItem">
+    <!--@mbg.generated-->
+    insert into se_vc_refund_item (id, refund_id, order_number, 
+      refund_number, refund_amount, create_time, 
+      refund_time, refund_status)
+    values (#{id,jdbcType=BIGINT}, #{refundId,jdbcType=BIGINT}, #{orderNumber,jdbcType=VARCHAR}, 
+      #{refundNumber,jdbcType=VARCHAR}, #{refundAmount,jdbcType=INTEGER}, #{createTime,jdbcType=TIMESTAMP}, 
+      #{refundTime,jdbcType=TIMESTAMP}, #{refundStatus,jdbcType=TINYINT})
+  </insert>
+  <insert id="insertSelective" parameterType="com.dy.pipIrrGlobal.pojoSe.SeVcRefundItem">
+    <!--@mbg.generated-->
+    insert into se_vc_refund_item
+    <trim prefix="(" suffix=")" suffixOverrides=",">
+      <if test="id != null">
+        id,
+      </if>
+      <if test="refundId != null">
+        refund_id,
+      </if>
+      <if test="orderNumber != null">
+        order_number,
+      </if>
+      <if test="refundNumber != null">
+        refund_number,
+      </if>
+      <if test="refundAmount != null">
+        refund_amount,
+      </if>
+      <if test="createTime != null">
+        create_time,
+      </if>
+      <if test="refundTime != null">
+        refund_time,
+      </if>
+      <if test="refundStatus != null">
+        refund_status,
+      </if>
+    </trim>
+    <trim prefix="values (" suffix=")" suffixOverrides=",">
+      <if test="id != null">
+        #{id,jdbcType=BIGINT},
+      </if>
+      <if test="refundId != null">
+        #{refundId,jdbcType=BIGINT},
+      </if>
+      <if test="orderNumber != null">
+        #{orderNumber,jdbcType=VARCHAR},
+      </if>
+      <if test="refundNumber != null">
+        #{refundNumber,jdbcType=VARCHAR},
+      </if>
+      <if test="refundAmount != null">
+        #{refundAmount,jdbcType=INTEGER},
+      </if>
+      <if test="createTime != null">
+        #{createTime,jdbcType=TIMESTAMP},
+      </if>
+      <if test="refundTime != null">
+        #{refundTime,jdbcType=TIMESTAMP},
+      </if>
+      <if test="refundStatus != null">
+        #{refundStatus,jdbcType=TINYINT},
+      </if>
+    </trim>
+  </insert>
+  <update id="updateByPrimaryKeySelective" parameterType="com.dy.pipIrrGlobal.pojoSe.SeVcRefundItem">
+    <!--@mbg.generated-->
+    update se_vc_refund_item
+    <set>
+      <if test="refundId != null">
+        refund_id = #{refundId,jdbcType=BIGINT},
+      </if>
+      <if test="orderNumber != null">
+        order_number = #{orderNumber,jdbcType=VARCHAR},
+      </if>
+      <if test="refundNumber != null">
+        refund_number = #{refundNumber,jdbcType=VARCHAR},
+      </if>
+      <if test="refundAmount != null">
+        refund_amount = #{refundAmount,jdbcType=INTEGER},
+      </if>
+      <if test="createTime != null">
+        create_time = #{createTime,jdbcType=TIMESTAMP},
+      </if>
+      <if test="refundTime != null">
+        refund_time = #{refundTime,jdbcType=TIMESTAMP},
+      </if>
+      <if test="refundStatus != null">
+        refund_status = #{refundStatus,jdbcType=TINYINT},
+      </if>
+    </set>
+    where id = #{id,jdbcType=BIGINT}
+  </update>
+  <update id="updateByPrimaryKey" parameterType="com.dy.pipIrrGlobal.pojoSe.SeVcRefundItem">
+    <!--@mbg.generated-->
+    update se_vc_refund_item
+    set refund_id = #{refundId,jdbcType=BIGINT},
+      order_number = #{orderNumber,jdbcType=VARCHAR},
+      refund_number = #{refundNumber,jdbcType=VARCHAR},
+      refund_amount = #{refundAmount,jdbcType=INTEGER},
+      create_time = #{createTime,jdbcType=TIMESTAMP},
+      refund_time = #{refundTime,jdbcType=TIMESTAMP},
+      refund_status = #{refundStatus,jdbcType=TINYINT}
+    where id = #{id,jdbcType=BIGINT}
+  </update>
+
+  <!--鏍规嵁璁㈠崟鍙疯幏鍙栨渶鍚庝竴涓��鍗曞彿-->
+  <select id="getLastRefundNumber" resultType="java.lang.String">
+    SELECT
+        refund_number AS refundNumber
+    FROM se_vc_refund_item
+    <where>
+      <if test = "orderNumber != null">
+        AND order_number = #{orderNumber}
+      </if>
+    </where>
+    ORDER BY refund_number DESC
+    LIMIT 0,1
+  </select>
+
+  <!--鏍规嵁閫�娆鹃�氱煡鎺ュ彛杩斿洖鐨勯��娆惧崟鍙峰弽鏌ラ��娆綢D锛屾煡璇㈣閫�娆綢D涓嬫湭閫�娆捐褰曟暟閲�-->
+  <select id="getNoRefundedCount" resultType="java.lang.Integer">
+    SELECT
+      COUNT(*) AS recordCount
+    FROM se_vc_refund_item
+    WHERE refund_id = (SELECT refund_id FROM se_vc_refund_item WHERE refund_number = #{refundNumber}) AND refund_status = 1
+  </select>
+
+  <!--鏍规嵁閫�娆惧崟鍙疯幏鍙栭��娆綢D锛岄��娆鹃�氱煡鍚庢洿鏂伴��娆捐〃鎵�闇�-->
+  <select id="getRefundIdByRefundNumber" resultType="java.lang.Long">
+    SELECT
+        refund_id AS refundId
+    FROM se_vc_refund_item
+    WHERE refund_number = #{refundNumber}
+  </select>
+</mapper>
\ No newline at end of file
diff --git a/pipIrr-platform/pipIrr-global/src/main/resources/mapper/SeVcRefundMapper.xml b/pipIrr-platform/pipIrr-global/src/main/resources/mapper/SeVcRefundMapper.xml
new file mode 100644
index 0000000..011458f
--- /dev/null
+++ b/pipIrr-platform/pipIrr-global/src/main/resources/mapper/SeVcRefundMapper.xml
@@ -0,0 +1,211 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.dy.pipIrrGlobal.daoSe.SeVcRefundMapper">
+  <resultMap id="BaseResultMap" type="com.dy.pipIrrGlobal.pojoSe.SeVcRefund">
+    <!--@mbg.generated-->
+    <!--@Table se_vc_refund-->
+    <id column="id" jdbcType="BIGINT" property="id" />
+    <result column="vc_id" jdbcType="BIGINT" property="vcId" />
+    <result column="client_id" jdbcType="BIGINT" property="clientId" />
+    <result column="money" jdbcType="FLOAT" property="money" />
+    <result column="refund_amount" jdbcType="FLOAT" property="refundAmount" />
+    <result column="after_refund" jdbcType="FLOAT" property="afterRefund" />
+    <result column="application_time" jdbcType="TIMESTAMP" property="applicationTime" />
+    <result column="auditor" jdbcType="BIGINT" property="auditor" />
+    <result column="audit_time" jdbcType="TIMESTAMP" property="auditTime" />
+    <result column="remarks" jdbcType="VARCHAR" property="remarks" />
+    <result column="refund_number" jdbcType="VARCHAR" property="refundNumber" />
+    <result column="refund_time" jdbcType="TIMESTAMP" property="refundTime" />
+    <result column="refund_status" jdbcType="TINYINT" property="refundStatus" />
+  </resultMap>
+  <sql id="Base_Column_List">
+    <!--@mbg.generated-->
+    id, vc_id, client_id, money, refund_amount, after_refund, application_time, auditor, 
+    audit_time, remarks, refund_number, refund_time, refund_status
+  </sql>
+  <select id="selectByPrimaryKey" parameterType="java.lang.Long" resultMap="BaseResultMap">
+    <!--@mbg.generated-->
+    select 
+    <include refid="Base_Column_List" />
+    from se_vc_refund
+    where id = #{id,jdbcType=BIGINT}
+  </select>
+  <delete id="deleteByPrimaryKey" parameterType="java.lang.Long">
+    <!--@mbg.generated-->
+    delete from se_vc_refund
+    where id = #{id,jdbcType=BIGINT}
+  </delete>
+  <insert id="insert" parameterType="com.dy.pipIrrGlobal.pojoSe.SeVcRefund">
+    <!--@mbg.generated-->
+    insert into se_vc_refund (id, vc_id, client_id, 
+      money, refund_amount, after_refund, 
+      application_time, auditor, audit_time, 
+      remarks, refund_number, refund_time, 
+      refund_status)
+    values (#{id,jdbcType=BIGINT}, #{vcId,jdbcType=BIGINT}, #{clientId,jdbcType=BIGINT}, 
+      #{money,jdbcType=FLOAT}, #{refundAmount,jdbcType=FLOAT}, #{afterRefund,jdbcType=FLOAT}, 
+      #{applicationTime,jdbcType=TIMESTAMP}, #{auditor,jdbcType=BIGINT}, #{auditTime,jdbcType=TIMESTAMP}, 
+      #{remarks,jdbcType=VARCHAR}, #{refundNumber,jdbcType=VARCHAR}, #{refundTime,jdbcType=TIMESTAMP}, 
+      #{refundStatus,jdbcType=TINYINT})
+  </insert>
+  <insert id="insertSelective" parameterType="com.dy.pipIrrGlobal.pojoSe.SeVcRefund">
+    <!--@mbg.generated-->
+    insert into se_vc_refund
+    <trim prefix="(" suffix=")" suffixOverrides=",">
+      <if test="id != null">
+        id,
+      </if>
+      <if test="vcId != null">
+        vc_id,
+      </if>
+      <if test="clientId != null">
+        client_id,
+      </if>
+      <if test="money != null">
+        money,
+      </if>
+      <if test="refundAmount != null">
+        refund_amount,
+      </if>
+      <if test="afterRefund != null">
+        after_refund,
+      </if>
+      <if test="applicationTime != null">
+        application_time,
+      </if>
+      <if test="auditor != null">
+        auditor,
+      </if>
+      <if test="auditTime != null">
+        audit_time,
+      </if>
+      <if test="remarks != null">
+        remarks,
+      </if>
+      <if test="refundNumber != null">
+        refund_number,
+      </if>
+      <if test="refundTime != null">
+        refund_time,
+      </if>
+      <if test="refundStatus != null">
+        refund_status,
+      </if>
+    </trim>
+    <trim prefix="values (" suffix=")" suffixOverrides=",">
+      <if test="id != null">
+        #{id,jdbcType=BIGINT},
+      </if>
+      <if test="vcId != null">
+        #{vcId,jdbcType=BIGINT},
+      </if>
+      <if test="clientId != null">
+        #{clientId,jdbcType=BIGINT},
+      </if>
+      <if test="money != null">
+        #{money,jdbcType=FLOAT},
+      </if>
+      <if test="refundAmount != null">
+        #{refundAmount,jdbcType=FLOAT},
+      </if>
+      <if test="afterRefund != null">
+        #{afterRefund,jdbcType=FLOAT},
+      </if>
+      <if test="applicationTime != null">
+        #{applicationTime,jdbcType=TIMESTAMP},
+      </if>
+      <if test="auditor != null">
+        #{auditor,jdbcType=BIGINT},
+      </if>
+      <if test="auditTime != null">
+        #{auditTime,jdbcType=TIMESTAMP},
+      </if>
+      <if test="remarks != null">
+        #{remarks,jdbcType=VARCHAR},
+      </if>
+      <if test="refundNumber != null">
+        #{refundNumber,jdbcType=VARCHAR},
+      </if>
+      <if test="refundTime != null">
+        #{refundTime,jdbcType=TIMESTAMP},
+      </if>
+      <if test="refundStatus != null">
+        #{refundStatus,jdbcType=TINYINT},
+      </if>
+    </trim>
+  </insert>
+  <update id="updateByPrimaryKeySelective" parameterType="com.dy.pipIrrGlobal.pojoSe.SeVcRefund">
+    <!--@mbg.generated-->
+    update se_vc_refund
+    <set>
+      <if test="vcId != null">
+        vc_id = #{vcId,jdbcType=BIGINT},
+      </if>
+      <if test="clientId != null">
+        client_id = #{clientId,jdbcType=BIGINT},
+      </if>
+      <if test="money != null">
+        money = #{money,jdbcType=FLOAT},
+      </if>
+      <if test="refundAmount != null">
+        refund_amount = #{refundAmount,jdbcType=FLOAT},
+      </if>
+      <if test="afterRefund != null">
+        after_refund = #{afterRefund,jdbcType=FLOAT},
+      </if>
+      <if test="applicationTime != null">
+        application_time = #{applicationTime,jdbcType=TIMESTAMP},
+      </if>
+      <if test="auditor != null">
+        auditor = #{auditor,jdbcType=BIGINT},
+      </if>
+      <if test="auditTime != null">
+        audit_time = #{auditTime,jdbcType=TIMESTAMP},
+      </if>
+      <if test="remarks != null">
+        remarks = #{remarks,jdbcType=VARCHAR},
+      </if>
+      <if test="refundNumber != null">
+        refund_number = #{refundNumber,jdbcType=VARCHAR},
+      </if>
+      <if test="refundTime != null">
+        refund_time = #{refundTime,jdbcType=TIMESTAMP},
+      </if>
+      <if test="refundStatus != null">
+        refund_status = #{refundStatus,jdbcType=TINYINT},
+      </if>
+    </set>
+    where id = #{id,jdbcType=BIGINT}
+  </update>
+  <update id="updateByPrimaryKey" parameterType="com.dy.pipIrrGlobal.pojoSe.SeVcRefund">
+    <!--@mbg.generated-->
+    update se_vc_refund
+    set vc_id = #{vcId,jdbcType=BIGINT},
+      client_id = #{clientId,jdbcType=BIGINT},
+      money = #{money,jdbcType=FLOAT},
+      refund_amount = #{refundAmount,jdbcType=FLOAT},
+      after_refund = #{afterRefund,jdbcType=FLOAT},
+      application_time = #{applicationTime,jdbcType=TIMESTAMP},
+      auditor = #{auditor,jdbcType=BIGINT},
+      audit_time = #{auditTime,jdbcType=TIMESTAMP},
+      remarks = #{remarks,jdbcType=VARCHAR},
+      refund_number = #{refundNumber,jdbcType=VARCHAR},
+      refund_time = #{refundTime,jdbcType=TIMESTAMP},
+      refund_status = #{refundStatus,jdbcType=TINYINT}
+    where id = #{id,jdbcType=BIGINT}
+  </update>
+
+  <!--鏍规嵁璁㈠崟鍙疯幏鍙栧叾鍚勭瑪閫�娆鹃噾棰�-->
+  <select id="getRefundAmount" resultType="java.lang.Integer">
+    SELECT
+        refund_amount AS refundAmount
+    FROM se_vc_refund
+    <where>
+      AND refund_status = 3
+      <if test = "orderNumber != null">
+        AND refund_amount LIKE CONCAT(#{orderNumber},'%')
+      </if>
+    </where>
+  </select>
+
+</mapper>
\ No newline at end of file
diff --git a/pipIrr-platform/pipIrr-web/pipIrr-web-sell/src/main/java/com/dy/pipIrrSell/clientCard/ClientCardCtrl.java b/pipIrr-platform/pipIrr-web/pipIrr-web-sell/src/main/java/com/dy/pipIrrSell/clientCard/ClientCardCtrl.java
index 01b56eb..93901fd 100644
--- a/pipIrr-platform/pipIrr-web/pipIrr-web-sell/src/main/java/com/dy/pipIrrSell/clientCard/ClientCardCtrl.java
+++ b/pipIrr-platform/pipIrr-web/pipIrr-web-sell/src/main/java/com/dy/pipIrrSell/clientCard/ClientCardCtrl.java
@@ -146,4 +146,34 @@
             return BaseResponseUtils.buildException(e.getMessage()) ;
         }
     }
+
+    /**
+     * 鑾峰緱涓�椤靛凡鎸傚け锛屾湭琛ュ崱鐨勬按鍗¤褰�
+     * @param vo
+     * @return
+     */
+    @Operation(summary = "鑾峰緱涓�椤靛凡鎸傚け锛屾湭琛ュ崱鐨勬按鍗¤褰�", description = "杩斿洖涓�椤靛凡鎸傚け锛屾湭琛ュ崱鐨勬按鍗℃暟鎹�")
+    @ApiResponses(value = {
+            @ApiResponse(
+                    responseCode = ResultCodeMsg.RsCode.SUCCESS_CODE,
+                    description = "杩斿洖涓�椤靛啘鎴锋暟鎹紙BaseResponse.content:QueryResultVo[{}]锛�",
+                    content = {@Content(mediaType = MediaType.APPLICATION_JSON_VALUE,
+                            schema = @Schema(implementation = BaClient.class))}
+            )
+    })
+    @GetMapping(path = "getUnreplaced")
+    @SsoAop()
+    public BaseResponse<QueryResultVo<List<VoCards>>> getUnreplaced(QoCards vo){
+        try {
+            QueryResultVo<List<VoCards>> res = clientCardSv.getUnreplaced(vo);
+            if(res.itemTotal != null && res.itemTotal > 0) {
+                return BaseResponseUtils.buildSuccess(res);
+            }else {
+                return BaseResponseUtils.buildFail(SellResultCode.THE_CARD_NOT_EXIST.getMessage());
+            }
+        } catch (Exception e) {
+            log.error("鏌ヨ鍐滄埛寮傚父", e);
+            return BaseResponseUtils.buildException(e.getMessage()) ;
+        }
+    }
 }
diff --git a/pipIrr-platform/pipIrr-web/pipIrr-web-sell/src/main/java/com/dy/pipIrrSell/clientCard/ClientCardSv.java b/pipIrr-platform/pipIrr-web/pipIrr-web-sell/src/main/java/com/dy/pipIrrSell/clientCard/ClientCardSv.java
index d195dc2..6f7e24c 100644
--- a/pipIrr-platform/pipIrr-web/pipIrr-web-sell/src/main/java/com/dy/pipIrrSell/clientCard/ClientCardSv.java
+++ b/pipIrr-platform/pipIrr-web/pipIrr-web-sell/src/main/java/com/dy/pipIrrSell/clientCard/ClientCardSv.java
@@ -130,4 +130,23 @@
 
         return rsVo ;
     }
+
+    /**
+     * 鑾峰彇宸叉寕澶憋紝鏈ˉ鍗$殑璁板綍锛屽簲鐢ㄧ▼搴忎娇鐢�
+     * @param queryVo
+     * @return
+     */
+    public QueryResultVo<List<VoCards>> getUnreplaced(QoCards queryVo){
+        Map<String, Object> params = (Map<String, Object>) PojoUtils.generalize(queryVo) ;
+        Long itemTotal = seClientCardMapper.getUnreplacedRecordCount();
+
+        QueryResultVo<List<VoCards>> rsVo = new QueryResultVo<>() ;
+        rsVo.pageSize = queryVo.pageSize ;
+        rsVo.pageCurr = queryVo.pageCurr ;
+
+        rsVo.calculateAndSet(itemTotal, params);
+        rsVo.obj = seClientCardMapper.getUnreplaced(params);
+
+        return rsVo ;
+    }
 }
diff --git a/pipIrr-platform/pipIrr-web/pipIrr-web-sell/src/main/java/com/dy/pipIrrSell/config/RestTemplateConfig.java b/pipIrr-platform/pipIrr-web/pipIrr-web-sell/src/main/java/com/dy/pipIrrSell/config/RestTemplateConfig.java
index 3ba853d..ae8753d 100644
--- a/pipIrr-platform/pipIrr-web/pipIrr-web-sell/src/main/java/com/dy/pipIrrSell/config/RestTemplateConfig.java
+++ b/pipIrr-platform/pipIrr-web/pipIrr-web-sell/src/main/java/com/dy/pipIrrSell/config/RestTemplateConfig.java
@@ -58,6 +58,7 @@
     //@Bean(name = "wechatRestTemplate")
     @Bean()
     public RestTemplate restTemplate() throws Exception {
+        //RestTemplate restTemplate = new RestTemplate(restTemplateWechatCertConfig.wechatHttpRequestFactory());
         RestTemplate restTemplate = new RestTemplate(restTemplateWechatCertConfig.wechatHttpRequestFactory());
         // 娣诲姞鎷︽埅鍣�
         //List<ClientHttpRequestInterceptor> interceptors = new ArrayList<>();
diff --git a/pipIrr-platform/pipIrr-web/pipIrr-web-sell/src/main/java/com/dy/pipIrrSell/result/SellResultCode.java b/pipIrr-platform/pipIrr-web/pipIrr-web-sell/src/main/java/com/dy/pipIrrSell/result/SellResultCode.java
index db843e7..6209612 100644
--- a/pipIrr-platform/pipIrr-web/pipIrr-web-sell/src/main/java/com/dy/pipIrrSell/result/SellResultCode.java
+++ b/pipIrr-platform/pipIrr-web/pipIrr-web-sell/src/main/java/com/dy/pipIrrSell/result/SellResultCode.java
@@ -104,6 +104,7 @@
     CONSUME_FAIL(90008, "娑堣垂澶辫触"),
     REFUND_AMOUNT_CANNOT_GREATER_THAN_MONEY(90009, "鐢宠閫�娆惧け璐ワ紝閫�娆鹃噾棰濅笉鑳藉ぇ浜庝綑棰�"),
     APPLICATION_REFUND_FAIL(900010, "鐢宠閫�娆惧け璐�"),
+    NOT_SUFFICIENT_FUNDS(900010, "閫�娆惧け璐ワ紝浣欓涓嶈冻"),
     NO_TO_AUDIT_REFUND(900011, "璇ョ數瀛愰挶鍖呮病鏈夊緟瀹℃牳鐨勯��娆剧敵璇�"),
     AUDIT_REFUND_FAIL(900012, "瀹℃牳閫�娆剧敵璇峰け璐�"),
     No_WALLER_RECHARGES(900013, "娌℃湁绗﹀悎鏉′欢鐨勫厖鍊兼暟鎹�"),
diff --git a/pipIrr-platform/pipIrr-web/pipIrr-web-sell/src/main/java/com/dy/pipIrrSell/util/PayHelper.java b/pipIrr-platform/pipIrr-web/pipIrr-web-sell/src/main/java/com/dy/pipIrrSell/util/PayHelper.java
index 032a5d6..e90474a 100644
--- a/pipIrr-platform/pipIrr-web/pipIrr-web-sell/src/main/java/com/dy/pipIrrSell/util/PayHelper.java
+++ b/pipIrr-platform/pipIrr-web/pipIrr-web-sell/src/main/java/com/dy/pipIrrSell/util/PayHelper.java
@@ -1,9 +1,19 @@
 package com.dy.pipIrrSell.util;
 
+import com.alibaba.fastjson2.JSON;
 import com.alibaba.fastjson2.JSONArray;
 import com.alibaba.fastjson2.JSONObject;
-
+import com.dy.common.webUtil.BaseResponse;
+import com.dy.common.webUtil.BaseResponseUtils;
+import com.dy.pipIrrGlobal.pojoSe.SeVirtualCard;
+import com.dy.pipIrrGlobal.voSe.VoOrders;
+import com.dy.pipIrrSell.result.SellResultCode;
+import com.dy.pipIrrSell.virtualCard.VirtualCardSv;
 import com.dy.pipIrrSell.wechatpay.PayInfo;
+import com.dy.pipIrrSell.wechatpay.dto.Refund;
+import com.dy.pipIrrSell.wechatpay.dto.RefundRequest;
+import com.dy.pipIrrSell.wechatpay.dto.RefundResponse;
+import com.dy.pipIrrSell.wechatpay.dto.ToRefund;
 import lombok.RequiredArgsConstructor;
 import org.springframework.stereotype.Component;
 
@@ -19,10 +29,7 @@
 import java.security.cert.CertificateFactory;
 import java.security.spec.InvalidKeySpecException;
 import java.security.spec.PKCS8EncodedKeySpec;
-import java.util.Base64;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Random;
+import java.util.*;
 
 /**
  * @author ZhuBaoMin
@@ -33,6 +40,7 @@
 @Component
 @RequiredArgsConstructor
 public class PayHelper {
+    private final VirtualCardSv virtualCardSv;
     private final RestTemplateUtil restTemplateUtil;
 
     private static final String CHARACTERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
@@ -40,6 +48,10 @@
     private String checkSessionUrl = PayInfo.checkSessionUrl;
     private String tokenUrl = PayInfo.tokenUrl;
     private String resetUserSessionKeyUrl = PayInfo.resetUserSessionKeyUrl;
+    private String notifyUrl = PayInfo.notifyUrl;
+    private String schema = PayInfo.schema;
+    private String privateCertFileName = PayInfo.privateCertFileName;
+    private String refundUrl = PayInfo.refundUrl;
 
     // 骞冲彴璇佷功鍏挜
     public Map<String, Certificate> CERTIFICATE_MAP = new HashMap();
@@ -341,4 +353,154 @@
         boolean valid = signature.verify(Base64.getDecoder().decode(wechatpaySignature));
         return valid;
     }
+
+
+    /**
+     * 鑾峰彇寰呴��娆惧璞″垪琛�
+     *      寰呴��娆惧璞″寘鍚鍗曞彿鍜屽彲閫�娆鹃噾棰�
+     *      璁㈠崟瀵硅薄鍖呭惈璁㈠崟鍙枫�佸厖鍊奸噾棰濄�佸厖鍊煎畬鎴愭椂闂�
+     *      1. 鏍规嵁铏氭嫙鍗″彿鍒拌櫄鎷熷崱琛ㄤ腑鍙栧嚭璇ュ崱浣欓
+     *      2. 鏍规嵁铏氭嫙鍗″彿鍒板厖鍊艰〃鍙栧嚭璁㈠崟瀵硅薄鍒楄〃
+     * @param virtualId
+     * @param refundAmount
+     * @return
+     */
+    public List<ToRefund> getToRefunds(Long virtualId, Integer refundAmount) {
+        ToRefund toRefund = new ToRefund();
+        List<ToRefund> list = new ArrayList<>();
+        Double money = 0d;
+
+        // 鏍规嵁铏氭嫙鍗″彿鑾峰彇褰撳墠铏氭嫙鍗′綑棰�
+        SeVirtualCard seVirtualCard = virtualCardSv.selectVirtuCardById(virtualId);
+        if(seVirtualCard != null) {
+            money = seVirtualCard.getMoney();
+        }
+
+        // 瑕侀��閲戦澶т簬璇ュ崱浣欓锛岃繑鍥炵┖鍒楄〃
+        if(refundAmount > money) {
+            return list;
+        }
+
+        // 鏍规嵁铏氭嫙鍗″彿鑾峰彇璁㈠崟鍒楄〃锛堜粎闄愬厖鍊兼垚鍔熺殑锛�
+        List<VoOrders> list_Orders = virtualCardSv.selectOrders(virtualId);
+        // 閬嶅巻璁㈠崟鍒楄〃锛岃幏鍙�
+        if(list_Orders != null && list_Orders.size() > 0) {
+            JSONArray array_Orders = (JSONArray) JSON.toJSON(list_Orders);
+            for(int i = 0; i < array_Orders.size(); i++) {
+                JSONObject job_order = array_Orders.getJSONObject(i);
+                String orderNumber = job_order.getString("orderNumber");
+                Integer rechargeAmount = job_order.getInteger("rechargeAmount");
+                Date rechargeTime = job_order.getDate("rechargeTime");
+
+                // 璁$畻鍏呭�艰嚦浠婃椂闂村樊锛堝垎閽燂級
+                Long timestamp_Recharge = rechargeTime.getTime() / 1000;
+                Long timestamp_Current = System.currentTimeMillis() / 1000;
+                Long timeDiff_Minute = (timestamp_Current - timestamp_Recharge)/60;
+
+                // 鑾峰彇璇ヨ鍗曞凡閫�娆剧瑪鏁�
+                Integer refundCount = 0;
+                List<Integer> list_RefundAmount = virtualCardSv.selectRefundAmount(orderNumber);
+                if(list_RefundAmount != null && list_RefundAmount.size() > 0) {
+                    refundCount = list_RefundAmount.size();
+                }
+
+                // 鍏呭�艰嚦浠婃湭瓒呰繃涓�骞翠笖璇ヨ鍗曢��娆炬�绘鏁版湭瓒呰繃50娆�
+                if(timeDiff_Minute/(365*24*60) >= 1 && (refundCount + 1) > 50)
+                    return list;
+
+                /**
+                 * 1. 濡傛灉瑕侀��閲戦灏忎簬褰撳墠璁㈠崟鐨勫厖鍊奸噾棰濓紝瑕侀��閲戦鍗充负搴旈��閲戦骞惰繑鍥�
+                 * 2. 濡傛灉瑕佹帹閲戦澶т簬褰撳墠璁㈠崟鍏呭�奸噾棰濓紝褰撳墠璁㈠崟鍏呭�奸噾棰濆嵆涓哄簲閫�閲戦
+                 *      a. 鐢熸垚搴旈��娆惧璞�
+                 *      b. 璁$畻鏂扮殑浣欓
+                 *      c. 閲戣挏鏂扮殑瑕侀��娆鹃噾棰�
+                 *      d. 濡傛灉瑕侀��閲戦澶т簬0锛岄亶鍘嗕笅涓�涓鍗�
+                 */
+                if(refundAmount <= rechargeAmount) {
+                    toRefund = new ToRefund();
+                    toRefund.setOrderNumber(orderNumber);
+                    toRefund.setRefundAmount(refundAmount);
+                    list.add(toRefund);
+                    // 璁$畻鏂扮殑浣欓鍜屾柊鐨勮閫�閲戦
+                    money = money - refundAmount;
+                    refundAmount = refundAmount - refundAmount;
+                    return list;
+                }else {
+                    toRefund = new ToRefund();
+                    toRefund.setOrderNumber(orderNumber);
+                    toRefund.setRefundAmount(rechargeAmount);
+                    list.add(toRefund);
+                    // 璁$畻鏂扮殑浣欓鍜屾柊鐨勮閫�閲戦
+                    money = money - rechargeAmount;
+                    refundAmount = refundAmount - rechargeAmount;
+                    if(refundAmount > 0) {
+                        continue;
+                    }else {
+                        return list;
+                    }
+                }
+            }
+        }
+        return list;
+    }
+
+    /**
+     * 閫�娆剧敵璇凤紝璋冪敤寰俊鏀粯閫�娆剧敵璇锋帴鍙�
+     * @param po 閫�娆捐姹傚璞★紝鍖呭惈璁㈠崟鍙枫�侀��娆惧崟鍙枫�侀��娆鹃噾棰�
+     * @return
+     * @throws NoSuchPaddingException
+     * @throws NoSuchAlgorithmException
+     * @throws InvalidKeySpecException
+     * @throws IOException
+     * @throws SignatureException
+     * @throws InvalidKeyException
+     */
+    public BaseResponse<Boolean> refunds(Refund po) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeySpecException, IOException, SignatureException, InvalidKeyException {
+        String tradeNo = po.getTradeNo();
+        String refundNo = po.getRefundNo();
+        Integer refund = po.getRefund();
+
+        // 鐢熸垚body
+        Integer total = virtualCardSv.getRechargeAmountByOrderNumber(tradeNo);
+        RefundRequest.Amount amount = new RefundRequest.Amount();
+        amount.setRefund(refund);
+        amount.setTotal(total);
+        amount.setCurrency("CNY");
+
+        RefundRequest refundRequest = new RefundRequest();
+        refundRequest.setOut_trade_no(tradeNo);
+        refundRequest.setOut_refund_no(refundNo);
+        refundRequest.setNotify_url(notifyUrl);
+        refundRequest.setAmount(amount);
+
+        // 鐢熸垚header
+        String nonceStr = generateRandomString();
+        Long timestamp = System.currentTimeMillis() / 1000;
+
+        String method = "POST";
+        String httpUrl = "/v3/refund/domestic/refunds";
+
+        String body = JSONObject.toJSONString(refundRequest);
+        String header = schema + " " + getToken(method, httpUrl, body, nonceStr, timestamp, privateCertFileName);
+
+        Map<String, String> headers = new HashMap<>();
+        headers.put("Authorization", header);
+        headers.put("Accept", "application/json");
+        headers.put("Content-Type", "application/json");
+
+        JSONObject job_refundResponse = restTemplateUtil.post(PayInfo.refundUrl, body, headers);
+        RefundResponse refundResponse = JSON.parseObject(job_refundResponse.toJSONString(), RefundResponse.class);
+
+        String status = refundResponse.getStatus();
+        if(status != null && status.equals("SUCCESS")) {
+            // 閫�娆剧敵璇峰凡鍙楃悊
+            return BaseResponseUtils.buildSuccess(true) ;
+        } else if(status != null && status.equals("PROCESSING")) {
+            // 閫�娆惧鐞嗕腑
+            return BaseResponseUtils.buildFail(SellResultCode.PROCESSING.getMessage());
+        } else {
+            // 閫�娆惧紓甯�
+            return BaseResponseUtils.buildError(SellResultCode.ABNORMAL.getMessage());
+        }
+    }
 }
diff --git a/pipIrr-platform/pipIrr-web/pipIrr-web-sell/src/main/java/com/dy/pipIrrSell/virtualCard/VirtualCardCtrl.java b/pipIrr-platform/pipIrr-web/pipIrr-web-sell/src/main/java/com/dy/pipIrrSell/virtualCard/VirtualCardCtrl.java
index 8593e8d..5a30b15 100644
--- a/pipIrr-platform/pipIrr-web/pipIrr-web-sell/src/main/java/com/dy/pipIrrSell/virtualCard/VirtualCardCtrl.java
+++ b/pipIrr-platform/pipIrr-web/pipIrr-web-sell/src/main/java/com/dy/pipIrrSell/virtualCard/VirtualCardCtrl.java
@@ -1,29 +1,49 @@
 package com.dy.pipIrrSell.virtualCard;
 
+import com.alibaba.fastjson2.JSON;
+import com.alibaba.fastjson2.JSONArray;
+import com.alibaba.fastjson2.JSONObject;
 import com.dy.common.aop.SsoAop;
 import com.dy.common.webUtil.BaseResponse;
 import com.dy.common.webUtil.BaseResponseUtils;
 import com.dy.common.webUtil.ResultCodeMsg;
+import com.dy.pipIrrGlobal.pojoSe.SeVcRefund;
+import com.dy.pipIrrGlobal.pojoSe.SeVcRefundItem;
 import com.dy.pipIrrGlobal.pojoSe.SeVirtualCard;
 import com.dy.pipIrrSell.result.SellResultCode;
+import com.dy.pipIrrSell.util.PayHelper;
+import com.dy.pipIrrSell.virtualCard.dto.DtoAudit;
+import com.dy.pipIrrSell.virtualCard.dto.DtoRefund;
 import com.dy.pipIrrSell.virtualCard.enums.LastOperateENUM;
+import com.dy.pipIrrSell.virtualCard.enums.RefundItemStateENUM;
+import com.dy.pipIrrSell.virtualCard.enums.RefundStateENUM;
+import com.dy.pipIrrSell.wechatpay.dto.Refund;
+import com.dy.pipIrrSell.wechatpay.dto.ToRefund;
 import io.swagger.v3.oas.annotations.Operation;
 import io.swagger.v3.oas.annotations.media.Content;
 import io.swagger.v3.oas.annotations.media.Schema;
 import io.swagger.v3.oas.annotations.responses.ApiResponse;
 import io.swagger.v3.oas.annotations.responses.ApiResponses;
 import io.swagger.v3.oas.annotations.tags.Tag;
+import jakarta.validation.Valid;
 import jakarta.validation.constraints.NotNull;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.http.MediaType;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.validation.BindingResult;
 import org.springframework.validation.annotation.Validated;
-import org.springframework.web.bind.annotation.PostMapping;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestParam;
-import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.bind.annotation.*;
 
+import javax.crypto.NoSuchPaddingException;
+import java.io.IOException;
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+import java.security.SignatureException;
+import java.security.spec.InvalidKeySpecException;
 import java.util.Date;
+import java.util.List;
+import java.util.Objects;
 
 /**
  * @author ZhuBaoMin
@@ -40,7 +60,13 @@
 @Validated
 public class VirtualCardCtrl {
     private final VirtualCardSv virtualCardSv;
+    private final PayHelper payHelper;
 
+    /**
+     * 铏氭嫙鍗¤处鍙锋敞鍐�
+     * @param clientId
+     * @return
+     */
     @Operation(summary = "娉ㄥ唽铏氭嫙鍗�", description = "娉ㄥ唽铏氭嫙鍗�")
     @ApiResponses(value = {
             @ApiResponse(
@@ -71,4 +97,132 @@
     }
 
 
+    /**
+     * 鐢ㄦ埛鐢宠閫�娆�
+     * @param po
+     * @param bindingResult
+     * @return
+     */
+    @Operation(summary = "铏氭嫙鍗$敵璇烽��娆�", description = "铏氭嫙鍗$敵璇烽��娆�")
+    @ApiResponses(value = {
+            @ApiResponse(
+                    responseCode = ResultCodeMsg.RsCode.SUCCESS_CODE,
+                    description = "鎿嶄綔缁撴灉锛歵rue锛氭垚鍔燂紝false锛氬け璐ワ紙BaseResponse.content锛�",
+                    content = {@Content(mediaType = MediaType.APPLICATION_JSON_VALUE,
+                            schema = @Schema(implementation = Boolean.class))}
+            )
+    })
+    @PostMapping(path = "add_refund", consumes = MediaType.APPLICATION_JSON_VALUE)
+    @Transactional(rollbackFor = Exception.class)
+    @SsoAop()
+    public BaseResponse<Boolean> addRefund(@RequestBody @Valid DtoRefund po, BindingResult bindingResult){
+        if(bindingResult != null && bindingResult.hasErrors()){
+            return BaseResponseUtils.buildFail(Objects.requireNonNull(bindingResult.getFieldError()).getDefaultMessage());
+        }
+
+        Long virtualId = po.getVirtualId();
+        Integer refundAmount = po.getRefundAmount();
+
+        // 鏍规嵁铏氭嫙鍗D鑾峰彇铏氭嫙鍗″璞�
+        SeVirtualCard seVirtualCard = virtualCardSv.selectVirtuCardById(virtualId);
+        if(seVirtualCard == null) {
+            return BaseResponseUtils.buildFail(SellResultCode.VIRTUAL_CARD_NOT_EXIST.getMessage());
+        }
+        Long clientId = seVirtualCard.getClientId();
+        Double money = seVirtualCard.getMoney();
+
+        // 楠岃瘉閫�娆鹃噾棰濇槸鍚﹀ぇ浜庝綑棰�
+        if(refundAmount > money) {
+            return BaseResponseUtils.buildFail(SellResultCode.REFUND_AMOUNT_CANNOT_GREATER_THAN_MONEY.getMessage());
+        }
+
+        // 璁$畻娑堣垂鍚庝綑棰�
+        Double afterRefund = money - refundAmount;
+
+        SeVcRefund seVcRefund = new SeVcRefund();
+        seVcRefund.setVcId(virtualId);
+        seVcRefund.setClientId(clientId);
+        seVcRefund.setMoney(money);
+        seVcRefund.setRefundAmount(refundAmount);
+        seVcRefund.setAfterRefund(afterRefund);
+        seVcRefund.setApplicationTime(new Date());
+        seVcRefund.setRefundStatus(RefundStateENUM.TO_AUDIT.getCode());
+
+        Long rec = virtualCardSv.addRefund(seVcRefund);
+        if(rec == 0) {
+            return BaseResponseUtils.buildFail(SellResultCode.APPLICATION_REFUND_FAIL.getMessage());
+        }
+        return BaseResponseUtils.buildSuccess(true) ;
+    }
+
+    /**
+     * 瀹℃牳閫�娆剧敵璇�
+     * @param po
+     * @param bindingResult
+     * @return
+     */
+    @Operation(summary = "瀹℃牳閫�娆剧敵璇�", description = "瀹℃牳閫�娆剧敵璇�")
+    @ApiResponses(value = {
+            @ApiResponse(
+                    responseCode = ResultCodeMsg.RsCode.SUCCESS_CODE,
+                    description = "鎿嶄綔缁撴灉锛歵rue锛氭垚鍔燂紝false锛氬け璐ワ紙BaseResponse.content锛�",
+                    content = {@Content(mediaType = MediaType.APPLICATION_JSON_VALUE,
+                            schema = @Schema(implementation = Boolean.class))}
+            )
+    })
+    @PostMapping(path = "audit_refund", consumes = MediaType.APPLICATION_JSON_VALUE)
+    @Transactional(rollbackFor = Exception.class)
+    @SsoAop()
+    public BaseResponse<Boolean> auditRefund(@RequestBody @Valid DtoAudit po, BindingResult bindingResult) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeySpecException, IOException, SignatureException, InvalidKeyException {
+        if(bindingResult != null && bindingResult.hasErrors()){
+            return BaseResponseUtils.buildFail(Objects.requireNonNull(bindingResult.getFieldError()).getDefaultMessage());
+        }
+
+        // 鏍规嵁閫�娆綢D鑾峰彇閫�娆惧璞★紝骞舵洿鏂板鏍镐汉銆佸鏍告椂闂淬�佸鏍稿娉ㄣ�侀��娆剧姸鎬佸瓧娈�
+        SeVcRefund seVcRefund = virtualCardSv.selectRefundByRefundId(po.getRefundId());
+        Long virtualId = seVcRefund.getVcId();
+        Integer refundAmount = seVcRefund.getRefundAmount();
+        seVcRefund.setAuditor(po.getAuditor());
+        seVcRefund.setAuditTime(new Date());
+        seVcRefund.setRemarks(po.getRemarks());
+        seVcRefund.setRefundStatus(RefundStateENUM.TO_REFUND.getCode());
+        Integer rec = virtualCardSv.updateRefund(seVcRefund);
+        if(rec == 0) {
+            return BaseResponseUtils.buildFail(SellResultCode.AUDIT_REFUND_FAIL.getMessage());
+        }
+
+        // 瀹屾垚瀹℃牳鍚庤幏鍙栧緟閫�娆捐鍗曞垪琛�
+        List<ToRefund> list_ToRefund = payHelper.getToRefunds(virtualId, refundAmount);
+        if(list_ToRefund == null || list_ToRefund.size() <=0)
+            return BaseResponseUtils.buildFail(SellResultCode.NOT_SUFFICIENT_FUNDS.getMessage());
+
+        //閬嶅巻寰呴��娆惧垪琛�
+        JSONArray array_ToRefund = (JSONArray) JSON.toJSON(list_ToRefund);
+        for(int i = 0; i < array_ToRefund.size(); i++) {
+            JSONObject job_ToRefund = array_ToRefund.getJSONObject(i);
+            String orderNumber_ToRefund = job_ToRefund.getString("orderNumber");
+            Integer refundAmount_ToRefund = job_ToRefund.getInteger("refundAmount");
+
+            // 鐢熸垚閫�娆惧垎椤硅褰�
+            SeVcRefundItem seVcRefundItem = new SeVcRefundItem();
+            seVcRefundItem.setRefundId(po.getRefundId());
+            seVcRefundItem.setOrderNumber(orderNumber_ToRefund);
+            String refundNumber = virtualCardSv.generateRefundNumber(orderNumber_ToRefund);
+            seVcRefundItem.setRefundNumber(refundNumber);
+            seVcRefundItem.setRefundAmount(refundAmount_ToRefund);
+            seVcRefundItem.setCreateTime(new Date());
+            seVcRefundItem.setRefundStatus(RefundItemStateENUM.NO_REFUND.getCode());
+            Long refundItemId = virtualCardSv.addRefundItem(seVcRefundItem);
+
+            // 璋冪敤寰俊閫�娆剧敵璇锋帴鍙�
+            Refund refund = new Refund();
+            refund.setTradeNo(orderNumber_ToRefund);
+            refund.setRefundNo(refundNumber);
+            refund.setRefund(refundAmount_ToRefund);
+            BaseResponse rep = payHelper.refunds(refund);
+        }
+
+        return BaseResponseUtils.buildSuccess(true) ;
+    }
+
 }
diff --git a/pipIrr-platform/pipIrr-web/pipIrr-web-sell/src/main/java/com/dy/pipIrrSell/virtualCard/VirtualCardSv.java b/pipIrr-platform/pipIrr-web/pipIrr-web-sell/src/main/java/com/dy/pipIrrSell/virtualCard/VirtualCardSv.java
index 10caf9c..1765f7b 100644
--- a/pipIrr-platform/pipIrr-web/pipIrr-web-sell/src/main/java/com/dy/pipIrrSell/virtualCard/VirtualCardSv.java
+++ b/pipIrr-platform/pipIrr-web/pipIrr-web-sell/src/main/java/com/dy/pipIrrSell/virtualCard/VirtualCardSv.java
@@ -3,9 +3,14 @@
 import com.dy.common.webUtil.BaseResponse;
 import com.dy.common.webUtil.BaseResponseUtils;
 import com.dy.pipIrrGlobal.daoSe.SeVcRechargeMapper;
+import com.dy.pipIrrGlobal.daoSe.SeVcRefundItemMapper;
+import com.dy.pipIrrGlobal.daoSe.SeVcRefundMapper;
 import com.dy.pipIrrGlobal.daoSe.SeVirtualCardMapper;
 import com.dy.pipIrrGlobal.pojoSe.SeVcRecharge;
+import com.dy.pipIrrGlobal.pojoSe.SeVcRefund;
+import com.dy.pipIrrGlobal.pojoSe.SeVcRefundItem;
 import com.dy.pipIrrGlobal.pojoSe.SeVirtualCard;
+import com.dy.pipIrrGlobal.voSe.VoOrders;
 import com.dy.pipIrrSell.result.SellResultCode;
 import com.dy.pipIrrSell.virtualCard.dto.DtoVirtualCard;
 import com.dy.pipIrrSell.virtualCard.enums.LastOperateENUM;
@@ -16,6 +21,7 @@
 import org.springframework.transaction.annotation.Transactional;
 
 import java.util.Date;
+import java.util.List;
 
 /**
  * @author ZhuBaoMin
@@ -32,6 +38,12 @@
 
     @Autowired
     private SeVcRechargeMapper seVcRechargeMapper;
+
+    @Autowired
+    private SeVcRefundMapper seVcRefundMapper;
+
+    @Autowired
+    private SeVcRefundItemMapper seVcRefundItemMapper;
 
     /**
      * 娉ㄥ唽铏氭嫙鍗�
@@ -61,6 +73,7 @@
     public SeVirtualCard selectVirtuCardById(Long virtualId) {
         return seVirtualCardMapper.selectByPrimaryKey(virtualId);
     }
+
     /**
      * 娣诲姞铏氭嫙鍗″厖鍊艰褰�
      * JSAPI涓嬪崟鍚庣敓鎴愰儴鍒嗗厖鍊艰褰�
@@ -139,7 +152,7 @@
     }
 
     /**
-     * 淇敼铏氭嫙鍗″厖鍊艰褰�
+     * 淇敼铏氭嫙鍗″厖鍊艰褰曪紙搴熷純锛�
      * 寰俊灏忕▼搴忔敮浠橀�氱煡鍚庝慨鏀癸細浣欓銆佸厖鍊煎悗浣欓銆佸厖鍊煎畬鎴愭椂闂�
      * @param po
      * @return
@@ -147,4 +160,115 @@
     public Integer updateVCRecharge(SeVcRecharge po) {
         return seVcRechargeMapper.updateByPrimaryKeySelective(po);
     }
+
+    /**
+     * 鏍规嵁铏氭嫙鍗″彿鑾峰彇璁㈠崟鍒楄〃
+     * @param virtualId
+     * @return
+     */
+    public List<VoOrders> selectOrders(Long virtualId) {
+        List<VoOrders> rsVo = seVcRechargeMapper.getOrders(virtualId);
+        return rsVo ;
+    }
+
+    /**
+     * 鏍规嵁閫�娆綢D鑾峰彇閫�娆惧璞�
+     * @param refundId
+     * @return
+     */
+    public SeVcRefund selectRefundByRefundId(Long refundId) {
+        return seVcRefundMapper.selectByPrimaryKey(refundId);
+    }
+
+    /**
+     * 娣诲姞閫�娆剧敵璇�
+     * @param po
+     * @return
+     */
+    public Long addRefund(SeVcRefund po) {
+        seVcRefundMapper.insert(po);
+        return po.getId();
+    }
+
+    /**
+     * 淇敼閫�娆捐褰�
+     * @param po
+     * @return
+     */
+    public Integer updateRefund(SeVcRefund po) {
+        return seVcRefundMapper.updateByPrimaryKeySelective(po);
+    }
+
+    /**
+     * 鏍规嵁璁㈠崟鍙疯幏鍙栧叾鍚勭瑪閫�娆鹃噾棰�
+     * @param orderNumber
+     * @return
+     */
+    public List<Integer> selectRefundAmount(String orderNumber) {
+        List<Integer> rsVo = seVcRefundMapper.getRefundAmount(orderNumber);
+        return rsVo;
+    }
+
+    /**
+     * 娣诲姞閫�娆惧垎椤�
+     * @param po
+     * @return
+     */
+    public Long addRefundItem(SeVcRefundItem po) {
+        seVcRefundItemMapper.insert(po);
+        return po.getRefundId();
+    }
+
+    /**
+     * 缂栬緫閫�娆惧垎椤�
+     * @param po
+     * @return
+     */
+    public Integer updateRefundItem(SeVcRefundItem po) {
+        return seVcRefundItemMapper.updateByPrimaryKeySelective(po);
+    }
+
+    /**
+     * 鏍规嵁璁㈠崟鍙风敓鎴愰��娆惧崟鍙�
+     * @param orderNumber
+     * @return
+     */
+    public String generateRefundNumber(String orderNumber) {
+        String refundNumber = seVcRefundItemMapper.getLastRefundNumber(orderNumber);
+        if(refundNumber == null) {
+            refundNumber = orderNumber + "01";
+            return refundNumber;
+        }
+
+        String a = String.format("%02d", (Integer.parseInt(refundNumber.substring(29,30).trim()) + 1));
+        return  a;
+    }
+
+    /**
+     * 鏍规嵁璁㈠崟鍙疯幏鍙栧厖鍊奸噾棰濓紝璋冪敤閫�娆剧敵璇锋帴鍙d娇鐢�
+     * @param orderNumber
+     * @return
+     */
+    public Integer getRechargeAmountByOrderNumber(String orderNumber) {
+        return seVcRechargeMapper.getRechargeAmountByOrderNumber(orderNumber);
+
+    }
+
+    /**
+     * 鏍规嵁閫�娆鹃�氱煡鎺ュ彛杩斿洖鐨勯��娆惧崟鍙峰弽鏌ラ��娆綢D锛屾煡璇㈣閫�娆綢D涓嬫湭閫�娆捐褰曟暟閲�
+     * @param refundNumber
+     * @return
+     */
+    public Integer getNoRefundedCount(String refundNumber) {
+        return seVcRefundItemMapper.getNoRefundedCount(refundNumber);
+    }
+
+    /**
+     * 鏍规嵁閫�娆惧崟鍙疯幏鍙栭��娆綢D锛岄��娆鹃�氱煡鍚庢洿鏂伴��娆捐〃鎵�闇�
+     * @param refundNumber
+     * @return
+     */
+    public Long getRefundIdByRefundNumber(String refundNumber) {
+        return seVcRefundItemMapper.getRefundIdByRefundNumber(refundNumber);
+    }
 }
diff --git a/pipIrr-platform/pipIrr-web/pipIrr-web-sell/src/main/java/com/dy/pipIrrSell/virtualCard/dto/DtoAudit.java b/pipIrr-platform/pipIrr-web/pipIrr-web-sell/src/main/java/com/dy/pipIrrSell/virtualCard/dto/DtoAudit.java
new file mode 100644
index 0000000..4ac150c
--- /dev/null
+++ b/pipIrr-platform/pipIrr-web/pipIrr-web-sell/src/main/java/com/dy/pipIrrSell/virtualCard/dto/DtoAudit.java
@@ -0,0 +1,40 @@
+package com.dy.pipIrrSell.virtualCard.dto;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.constraints.NotNull;
+import lombok.Data;
+import org.hibernate.validator.constraints.Length;
+
+/**
+ * @author ZhuBaoMin
+ * @date 2024-03-08 21:09
+ * @LastEditTime 2024-03-08 21:09
+ * @Description
+ */
+
+@Data
+@Schema(name = "閫�娆惧鏍镐紶鍏ュ璞�")
+public class DtoAudit {
+    public static final long serialVersionUID = 202403082109001L;
+
+    /**
+     * 铏氭嫙鍗¢��娆綢D
+     */
+    @Schema(description = "铏氭嫙鍗¢��娆綢D", requiredMode = Schema.RequiredMode.NOT_REQUIRED)
+    @NotNull(message = "铏氭嫙鍗¢��娆綢D涓嶈兘涓虹┖")
+    private Long refundId;
+
+    /**
+     * 瀹℃牳浜篒D
+     */
+    @Schema(description = "瀹℃牳浜篒D", requiredMode = Schema.RequiredMode.NOT_REQUIRED)
+    @NotNull(message = "瀹℃牳ID涓嶈兘涓虹┖")
+    private Long auditor;
+
+    /**
+     * 瀹℃牳澶囨敞
+     */
+    @Schema(description = "瀹℃牳澶囨敞", requiredMode = Schema.RequiredMode.NOT_REQUIRED)
+    @Length(max = 200)
+    private String remarks;
+}
diff --git a/pipIrr-platform/pipIrr-web/pipIrr-web-sell/src/main/java/com/dy/pipIrrSell/virtualCard/dto/DtoRefund.java b/pipIrr-platform/pipIrr-web/pipIrr-web-sell/src/main/java/com/dy/pipIrrSell/virtualCard/dto/DtoRefund.java
new file mode 100644
index 0000000..1bff55b
--- /dev/null
+++ b/pipIrr-platform/pipIrr-web/pipIrr-web-sell/src/main/java/com/dy/pipIrrSell/virtualCard/dto/DtoRefund.java
@@ -0,0 +1,34 @@
+package com.dy.pipIrrSell.virtualCard.dto;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.constraints.NotNull;
+import jakarta.validation.constraints.Positive;
+import lombok.Data;
+
+/**
+ * @author ZhuBaoMin
+ * @date 2024-03-08 20:17
+ * @LastEditTime 2024-03-08 20:17
+ * @Description
+ */
+
+@Data
+@Schema(name = "鐢ㄦ埛閫�娆句紶鍏ュ璞�")
+public class DtoRefund {
+    public static final long serialVersionUID = 202403080858001L;
+
+    /**
+     * 铏氭嫙鍗$紪鍙�
+     */
+    @Schema(description = "铏氭嫙鍗$紪鍙�", requiredMode = Schema.RequiredMode.NOT_REQUIRED)
+    @NotNull(message = "铏氭嫙鍗$紪鍙蜂笉鑳戒负绌�")
+    private Long virtualId;
+
+    /**
+     * 閫�娆鹃噾棰�
+     */
+    @Schema(description = "閫�娆鹃噾棰�", requiredMode = Schema.RequiredMode.NOT_REQUIRED)
+    @NotNull(message = "閫�娆鹃噾棰濅笉鑳戒负绌�")
+    @Positive(message = "鍏呭�奸噾棰濆繀椤讳负澶т簬0鐨勬暣鏁�")
+    private Integer refundAmount;
+}
diff --git a/pipIrr-platform/pipIrr-web/pipIrr-web-sell/src/main/java/com/dy/pipIrrSell/virtualCard/enums/LastOperateENUM.java b/pipIrr-platform/pipIrr-web/pipIrr-web-sell/src/main/java/com/dy/pipIrrSell/virtualCard/enums/LastOperateENUM.java
index b9ac164..b29688d 100644
--- a/pipIrr-platform/pipIrr-web/pipIrr-web-sell/src/main/java/com/dy/pipIrrSell/virtualCard/enums/LastOperateENUM.java
+++ b/pipIrr-platform/pipIrr-web/pipIrr-web-sell/src/main/java/com/dy/pipIrrSell/virtualCard/enums/LastOperateENUM.java
@@ -17,7 +17,8 @@
     RECHARGE((byte)2, "鍏呭��"),
     CONSUME((byte)3, "娑堣垂"),
     APPLY_REFUND((byte)4, "鐢宠閫�娆�"),
-    AUDIT_REFUND((byte)5, "閫�娆惧鏍�");
+    AUDIT_REFUND((byte)5, "閫�娆惧鏍�"),
+    REFUND((byte)6, "閫�娆�");
 
     private final Byte code;
     private final String message;
diff --git a/pipIrr-platform/pipIrr-web/pipIrr-web-sell/src/main/java/com/dy/pipIrrSell/virtualCard/enums/RefundItemStateENUM.java b/pipIrr-platform/pipIrr-web/pipIrr-web-sell/src/main/java/com/dy/pipIrrSell/virtualCard/enums/RefundItemStateENUM.java
new file mode 100644
index 0000000..6eca897
--- /dev/null
+++ b/pipIrr-platform/pipIrr-web/pipIrr-web-sell/src/main/java/com/dy/pipIrrSell/virtualCard/enums/RefundItemStateENUM.java
@@ -0,0 +1,21 @@
+package com.dy.pipIrrSell.virtualCard.enums;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+/**
+ * @author ZhuBaoMin
+ * @date 2024-03-11 8:49
+ * @LastEditTime 2024-03-11 8:49
+ * @Description 閫�娆惧垎椤圭殑閫�娆剧姸鎬侊紝鍗冲井淇¢��娆剧姸鎬�
+ */
+
+@Getter
+@AllArgsConstructor
+public enum RefundItemStateENUM {
+    NO_REFUND((byte)1, "鏈��娆�"),
+    REFUNDED((byte)2, "宸查��娆�");
+
+    private final Byte code;
+    private final String message;
+}
diff --git a/pipIrr-platform/pipIrr-web/pipIrr-web-sell/src/main/java/com/dy/pipIrrSell/virtualCard/enums/RefundStateENUM.java b/pipIrr-platform/pipIrr-web/pipIrr-web-sell/src/main/java/com/dy/pipIrrSell/virtualCard/enums/RefundStateENUM.java
new file mode 100644
index 0000000..0a5c69a
--- /dev/null
+++ b/pipIrr-platform/pipIrr-web/pipIrr-web-sell/src/main/java/com/dy/pipIrrSell/virtualCard/enums/RefundStateENUM.java
@@ -0,0 +1,22 @@
+package com.dy.pipIrrSell.virtualCard.enums;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+/**
+ * @author ZhuBaoMin
+ * @date 2024-03-08 20:45
+ * @LastEditTime 2024-03-08 20:45
+ * @Description
+ */
+
+@Getter
+@AllArgsConstructor
+public enum RefundStateENUM {
+    TO_AUDIT((byte)1, "寰呭鏍�"),
+    TO_REFUND((byte)2, "寰呴��娆�"),
+    REFUNDED((byte)3, "宸查��娆�");
+
+    private final Byte code;
+    private final String message;
+}
diff --git a/pipIrr-platform/pipIrr-web/pipIrr-web-sell/src/main/java/com/dy/pipIrrSell/wallet/WalletSv.java b/pipIrr-platform/pipIrr-web/pipIrr-web-sell/src/main/java/com/dy/pipIrrSell/wallet/WalletSv.java
index 3fafbb3..c253f27 100644
--- a/pipIrr-platform/pipIrr-web/pipIrr-web-sell/src/main/java/com/dy/pipIrrSell/wallet/WalletSv.java
+++ b/pipIrr-platform/pipIrr-web/pipIrr-web-sell/src/main/java/com/dy/pipIrrSell/wallet/WalletSv.java
@@ -13,8 +13,8 @@
 import com.dy.pipIrrGlobal.voSe.VoWalletConsume;
 import com.dy.pipIrrGlobal.voSe.VoWalletRecharge;
 import com.dy.pipIrrGlobal.voSe.VoWalletRefund;
-import com.dy.pipIrrSell.wallet.qo.QueryVo;
 import com.dy.pipIrrSell.wallet.qo.QoWalletRecharge;
+import com.dy.pipIrrSell.wallet.qo.QueryVo;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.dubbo.common.utils.PojoUtils;
 import org.springframework.beans.factory.annotation.Autowired;
diff --git a/pipIrr-platform/pipIrr-web/pipIrr-web-sell/src/main/java/com/dy/pipIrrSell/wechatpay/PayInfo.java b/pipIrr-platform/pipIrr-web/pipIrr-web-sell/src/main/java/com/dy/pipIrrSell/wechatpay/PayInfo.java
index 4952e7a..eb0827c 100644
--- a/pipIrr-platform/pipIrr-web/pipIrr-web-sell/src/main/java/com/dy/pipIrrSell/wechatpay/PayInfo.java
+++ b/pipIrr-platform/pipIrr-web/pipIrr-web-sell/src/main/java/com/dy/pipIrrSell/wechatpay/PayInfo.java
@@ -52,7 +52,7 @@
     /**
      * 鐢宠閫�娆続PI
      */
-    public static String refundUrl = "https://api.mch.weixin.qq.co/v3/refund/domestic/refunds";
+    public static String refundUrl = "https://api.mch.weixin.qq.com/v3/refund/domestic/refunds";
 
     /*
      * 閫�娆鹃�氱煡API
diff --git a/pipIrr-platform/pipIrr-web/pipIrr-web-sell/src/main/java/com/dy/pipIrrSell/wechatpay/PaymentCtrl.java b/pipIrr-platform/pipIrr-web/pipIrr-web-sell/src/main/java/com/dy/pipIrrSell/wechatpay/PaymentCtrl.java
index 5258444..4aad549 100644
--- a/pipIrr-platform/pipIrr-web/pipIrr-web-sell/src/main/java/com/dy/pipIrrSell/wechatpay/PaymentCtrl.java
+++ b/pipIrr-platform/pipIrr-web/pipIrr-web-sell/src/main/java/com/dy/pipIrrSell/wechatpay/PaymentCtrl.java
@@ -1,11 +1,12 @@
 package com.dy.pipIrrSell.wechatpay;
 
-import com.alibaba.fastjson2.JSON;
 import com.alibaba.fastjson2.JSONObject;
 import com.dy.common.aop.SsoAop;
 import com.dy.common.webUtil.BaseResponse;
 import com.dy.common.webUtil.BaseResponseUtils;
 import com.dy.common.webUtil.ResultCodeMsg;
+import com.dy.pipIrrGlobal.pojoSe.SeVcRefund;
+import com.dy.pipIrrGlobal.pojoSe.SeVcRefundItem;
 import com.dy.pipIrrGlobal.pojoSe.SeVirtualCard;
 import com.dy.pipIrrGlobal.pojoSe.SeWebchatLogonState;
 import com.dy.pipIrrGlobal.voSe.VoClient;
@@ -16,7 +17,12 @@
 import com.dy.pipIrrSell.util.RestTemplateUtil;
 import com.dy.pipIrrSell.virtualCard.VirtualCardSv;
 import com.dy.pipIrrSell.virtualCard.dto.DtoVirtualCard;
-import com.dy.pipIrrSell.wechatpay.dto.*;
+import com.dy.pipIrrSell.virtualCard.enums.LastOperateENUM;
+import com.dy.pipIrrSell.virtualCard.enums.RefundItemStateENUM;
+import com.dy.pipIrrSell.wallet.enums.RefundStatusENUM;
+import com.dy.pipIrrSell.wechatpay.dto.Code2Session;
+import com.dy.pipIrrSell.wechatpay.dto.DtoOrder;
+import com.dy.pipIrrSell.wechatpay.dto.OrderNotify;
 import io.swagger.v3.oas.annotations.Operation;
 import io.swagger.v3.oas.annotations.media.Content;
 import io.swagger.v3.oas.annotations.media.Schema;
@@ -65,25 +71,23 @@
     private final VirtualCardSv virtualCardSv;
     private final ClientSv clientSv;
 
-    private String privateCertFileName = PayInfo.privateCertFileName;
-    private String appid = PayInfo.appid;
-    private String mchid = PayInfo.mchid;
-    private String schema = PayInfo.schema;
-    private String signType = PayInfo.signType;
-    private String description = PayInfo.description;
-    private String loginUrl = PayInfo.loginUrl;
-    private String notifyUrl = PayInfo.notifyUrl;
-    private String grantType = PayInfo.grantType;
-    private String refundUrl = PayInfo.refundUrl;
+    private final String privateCertFileName = PayInfo.privateCertFileName;
+    private final String appid = PayInfo.appid;
+    private final String mchid = PayInfo.mchid;
+    private final String schema = PayInfo.schema;
+    private final String signType = PayInfo.signType;
+    private final String description = PayInfo.description;
+    private final String loginUrl = PayInfo.loginUrl;
+    private final String notifyUrl = PayInfo.notifyUrl;
+    private final String grantType = PayInfo.grantType;
 
     // 骞冲彴璇佷功鍏挜
-    private Map CERTIFICATE_MAP = new HashMap();
+    private final Map CERTIFICATE_MAP = new HashMap();
 
     /**
      * 鐧诲綍鍑瘉鏍¢獙
-     * @param appid 灏忕▼搴� appId
-     * @param secret 灏忕▼搴� appSecret
-     * @param js_code 涓存椂鐧诲綍鍑瘉code
+     * @param code2Session 鐧诲綍鍑瘉鏍¢獙浼犲叆瀵硅薄
+     * @param bindingResult
      * @return
      * @throws Exception
      */
@@ -99,11 +103,15 @@
     @PostMapping(path = "getSessionId")
     @Transactional(rollbackFor = Exception.class)
     @SsoAop()
-    public BaseResponse<Boolean> getSessionId(@RequestParam("appid")  String appid, @RequestParam("secret") String secret, @RequestParam("js_code") String js_code) throws Exception {
+    public BaseResponse<Boolean> getSessionId(@RequestBody @Valid Code2Session code2Session, BindingResult bindingResult) throws Exception {
+        if(bindingResult != null && bindingResult.hasErrors()){
+            return BaseResponseUtils.buildFail(Objects.requireNonNull(bindingResult.getFieldError()).getDefaultMessage());
+        }
+
         Map<String, Object> queryParams = new HashMap<>();
         queryParams.put("appid", appid);
-        queryParams.put("secret", secret);
-        queryParams.put("js_code", js_code);
+        queryParams.put("secret", code2Session.getSecret());
+        queryParams.put("js_code", code2Session.getJs_code());
         queryParams.put("grant_type", grantType);
         Map<String, String> headerParams = new HashMap<>();
         JSONObject job = restTemplateUtil.get(loginUrl, queryParams, headerParams);
@@ -116,20 +124,20 @@
         String sessionKey = job.getString("session_key");
 
         // 妫�楠岀櫥褰曟��
-        JSONObject checkSessionKey = payHelper.checkSessionKey(appid, secret, openid, sessionKey);
-        if(checkSessionKey != null) {
-            Integer errcode = checkSessionKey.getInteger("errcode");
-            String errmsg = checkSessionKey.getString("errmsg");
-        }
+        //JSONObject checkSessionKey = payHelper.checkSessionKey(appid, secret, openid, sessionKey);
+        //if(checkSessionKey != null) {
+        //    Integer errcode = checkSessionKey.getInteger("errcode");
+        //    String errmsg = checkSessionKey.getString("errmsg");
+        //}
 
         // 閲嶇疆鐧诲綍鎬�
-        JSONObject resetUserSessionKey = payHelper.resetUserSessionKey(appid, secret, openid, sessionKey);
-        if(resetUserSessionKey != null) {
-            Integer errcode = checkSessionKey.getInteger("errcode");
-            String errmsg = checkSessionKey.getString("errmsg");
-            String openid_New = checkSessionKey.getString("openid");
-            String sessionKey_New = checkSessionKey.getString("session_key");
-        }
+        //JSONObject resetUserSessionKey = payHelper.resetUserSessionKey(appid, secret, openid, sessionKey);
+        //if(resetUserSessionKey != null) {
+        //    Integer errcode = checkSessionKey.getInteger("errcode");
+        //    String errmsg = checkSessionKey.getString("errmsg");
+        //    String openid_New = checkSessionKey.getString("openid");
+        //    String sessionKey_New = checkSessionKey.getString("session_key");
+        //}
 
         // 娣诲姞鐧诲綍鎬佽褰�
         SeWebchatLogonState po = new SeWebchatLogonState();
@@ -277,110 +285,14 @@
         headers.put("Accept", "application/json");
         headers.put("Content-Type", "application/json");
 
-        JSONObject job_result = restTemplateUtil.post(PayInfo.orderUrl, body, headers);
-        if(job_result != null) {
-            System.out.println(job_result.toString());
-            prepayId = job_result.getString("prepay_id");
-        }
+        // 鏆傛椂娉ㄩ噴鎺夛紝璁よ瘉閫氳繃鍚庡啀鏀惧紑
+        //JSONObject job_result = restTemplateUtil.post(PayInfo.orderUrl, body, headers);
+        //if(job_result != null) {
+        //    System.out.println(job_result.toString());
+        //    prepayId = job_result.getString("prepay_id");
+        //}
 
         return BaseResponseUtils.buildSuccess(prepayId) ;
-    }
-
-    /**
-     * 鐢宠閫�娆�
-     * @param po 閫�娆捐姹傚璞�
-     * @param bindingResult
-     * @return
-     * @throws NoSuchPaddingException
-     * @throws NoSuchAlgorithmException
-     * @throws InvalidKeySpecException
-     * @throws IOException
-     * @throws SignatureException
-     * @throws InvalidKeyException
-     */
-    @Operation(summary = "鐢宠閫�娆�", description = "鐢宠閫�娆�")
-    @ApiResponses(value = {
-            @ApiResponse(
-                    responseCode = ResultCodeMsg.RsCode.SUCCESS_CODE,
-                    description = "鎿嶄綔缁撴灉锛歵rue锛氭垚鍔燂紝false锛氬け璐ワ紙BaseResponse.content锛�",
-                    content = {@Content(mediaType = MediaType.APPLICATION_JSON_VALUE,
-                            schema = @Schema(implementation = Boolean.class))}
-            )
-    })
-    @PostMapping(path = "refunds")
-    @Transactional(rollbackFor = Exception.class)
-    @SsoAop()
-    public BaseResponse<Boolean> refunds(@RequestBody @Valid Refund po, BindingResult bindingResult) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeySpecException, IOException, SignatureException, InvalidKeyException {
-        if(bindingResult != null && bindingResult.hasErrors()){
-            return BaseResponseUtils.buildFail(Objects.requireNonNull(bindingResult.getFieldError()).getDefaultMessage());
-        }
-
-        /**
-         * 1. 鍒ゆ柇浜ゆ槗鏃堕棿鏄惁瓒呰繃涓�骞�
-         * 2. 鍒ゆ柇閫�娆炬�婚噾棰濇槸鍚﹁秴杩囪鍗曢噾棰�
-         * 3. 鍒ゆ柇褰撳墠璁㈠崟閫�娆炬鏁版槸鍚﹁秴杩�50娆�
-         * 4. 鍒ゆ柇涓庤璁㈠崟涓婃閫�娆炬槸鍚︾浉闅�1鍒嗛挓
-         */
-
-        String tradeNo = po.getTradeNo();
-        String refundNo = po.getRefundNo();
-        Integer refund = po.getRefund();
-        if(refundNo == null || refundNo.length() <= 0) {
-            // 鏂版彁閫�娆剧敵璇凤紝鐢熸垚閫�娆惧崟鍙�
-            //refundNo = generateRefundNo(tradeNo);
-        }
-
-        // 鏍规嵁璁㈠崟鍙疯幏鍙栨�绘敮浠橀噾棰濆拰鎬婚��娆鹃噾棰�
-        Integer totalTradeAmount = 0;
-        Integer totalRefundAmount = 0;
-        //Integer totalTradeAmount = getTotalTradeAmount(tradeNo);
-        //Integer totalRefundAmount = getTotalRefundAmount(tradeNo);
-        if(totalRefundAmount > totalTradeAmount) {
-            return BaseResponseUtils.buildFail(SellResultCode.TOTAL_REFUND_EXCEED_TRADE.getMessage());
-        }
-
-        // 鐢熸垚body
-        RefundRequest.Amount amount = new RefundRequest.Amount();
-        amount.setRefund(refund);
-        amount.setTotal(totalTradeAmount);
-        amount.setCurrency("CNY");
-
-        RefundRequest refundRequest = new RefundRequest();
-        refundRequest.setOut_trade_no(tradeNo);
-        refundRequest.setOut_refund_no(refundNo);
-        refundRequest.setNotify_url(notifyUrl);
-        refundRequest.setAmount(amount);
-
-        // 鐢熸垚header
-        String nonceStr = payHelper.generateRandomString();
-        Long timestamp = System.currentTimeMillis() / 1000;
-
-        String method = "POST";
-        String httpUrl = "/v3/refund/domestic/refunds";
-
-        String body = JSONObject.toJSONString(refundRequest);
-        String header = schema + " " + payHelper.getToken(method, httpUrl, body, nonceStr, timestamp, privateCertFileName);
-
-        Map<String, String> headers = new HashMap<>();
-        headers.put("Authorization", header);
-        headers.put("Accept", "application/json");
-        headers.put("Content-Type", "application/json");
-
-        JSONObject job_refundResponse = restTemplateUtil.post(PayInfo.orderUrl, body, headers);
-        RefundResponse refundResponse = JSON.parseObject(job_refundResponse.toJSONString(), RefundResponse.class);
-
-        String status = refundResponse.getStatus();
-        if(status != null && status.equals("SUCCESS")) {
-            // 閫�娆剧敵璇峰凡鍙楃悊
-            return BaseResponseUtils.buildSuccess(true) ;
-        } else if(status != null && status.equals("PROCESSING")) {
-            // 閫�娆惧鐞嗕腑
-            return BaseResponseUtils.buildFail(SellResultCode.PROCESSING.getMessage());
-        } else {
-            // 閫�娆惧紓甯�
-            return BaseResponseUtils.buildError(SellResultCode.ABNORMAL.getMessage());
-        }
-
     }
 
     /**
@@ -491,7 +403,68 @@
             }
         } else if(eventType != null && eventType.equals("REFUND.SUCCESS")) {
             // 閫�娆炬垚鍔熷悗鍥炶皟
+            /**
+             * 閫�娆炬垚鍔熺殑鍥炶皟
+             * 鍙栧嚭閫氱煡鏁版嵁瀵硅薄锛岀户鑰屽彇鍑鸿В瀵嗘墍闇�鐨刟ssociatedData鍜宯once锛屼互鍙婂瘑鏂嘽iphertext
+             * 瑙e瘑ciphertext寰楀埌
+             */
+            OrderNotify.NotifyResource notifyResource = orderNotify.getResource();
+            String associatedData = notifyResource.getAssociated_data();
+            String nonce = notifyResource.getNonce();
+            String ciphertext = notifyResource.getCiphertext();
 
+            String resource = AesUtil.decryptToString(PayInfo.key.getBytes("utf-8"), associatedData.getBytes("utf-8"), nonce.getBytes("utf-8"), ciphertext);
+            JSONObject job_resource = JSONObject.parseObject(resource);
+
+            // 瑙e瘑鍚庡彇鍑猴細鍟嗘埛璁㈠崟鍛樸�佸井淇℃敮浠樿鍗曞彿銆佷氦鏄撶姸鎬併�佹敮浠樺畬鎴愭椂闂�
+            String out_trade_no = job_resource.getString("out_trade_no");
+            String transaction_id = job_resource.getString("transaction_id");
+            String out_refund_no = job_resource.getString("out_refund_no");
+            String refund_status = job_resource.getString("refund_status");
+            Date success_time = job_resource.getDate("success_time");
+            if(!refund_status.equals("SUCCESS")) {
+                response.setStatus(500);
+                result.put("code", "FAIL");
+                result.put("message", "澶辫触");
+                return result;
+            }
+
+            // 鏇存柊铏氭嫙鍗¤〃鍙婂厖鍊艰〃鍝嶅簲瀛楁
+            SeVcRefundItem seVcRefundItem = new SeVcRefundItem();
+            seVcRefundItem.setRefundTime(success_time);
+            seVcRefundItem.setRefundStatus(RefundItemStateENUM.REFUNDED.getCode());
+            Integer rec = virtualCardSv.updateRefundItem(seVcRefundItem);
+            if(rec == null && rec <= 0) {
+                response.setStatus(500);
+                result.put("code", "FAIL");
+                result.put("message", "澶辫触");
+                return result;
+            }
+
+            // 鏍规嵁閫�娆惧崟鍙峰弽鏌ラ��娆綢D锛屾牴鎹��娆綢D鑾峰彇閫�娆剧姸鎬佹槸鏈��娆剧殑璁板綍鏁伴噺锛屽鏋滄槸0鍒欒鏄庡叏閮ㄩ��娆惧畬鎴愶紝鏇存柊閫�娆捐〃鐘舵�佷负宸查��娆撅紝灏嗛��娆惧悗閲戦鏇存柊鍒拌櫄鎷熷崱琛�
+            /**
+             * 鏍规嵁閫�娆鹃�氱煡鎺ュ彛杩斿洖鐨勯��娆惧崟鍙峰弽鏌ラ��娆綢D锛屾煡璇㈣閫�娆綢D涓嬫湭閫�娆捐褰曟暟閲�
+             *      濡傛灉缁撴灉涓�0锛屽垯璇ラ��娆惧凡缁忓畬鎴�
+             *      1. 鏇存柊閫�娆捐〃鐘舵�佷负宸查��娆�
+             *      2. 灏嗛��娆惧悗浣欓鏇存柊鍒拌櫄鎷熷崱琛ㄤ腑
+             */
+            Integer noRefundedCount = virtualCardSv.getNoRefundedCount(out_refund_no);
+            if(noRefundedCount != null && noRefundedCount == 0) {
+                // 鑾峰彇閫�娆惧璞″苟淇敼閫�娆剧姸鎬�
+                Long refundId = virtualCardSv.getRefundIdByRefundNumber(out_refund_no);
+                SeVcRefund seVcRefund = virtualCardSv.selectRefundByRefundId(refundId);
+                seVcRefund.setRefundStatus(RefundStatusENUM.REFUNDED.getCode());
+                virtualCardSv.updateRefund(seVcRefund);
+
+                // 鑾峰彇铏氭嫙鍗″璞″苟淇敼浣欓銆佹渶鍚庢搷浣溿�佹渶鍚庢搷浣滄椂闂�
+                Long vcId = seVcRefund.getVcId();
+                Double afterRefund = seVcRefund.getAfterRefund();
+                SeVirtualCard seVirtualCard = virtualCardSv.selectVirtuCardById(vcId);
+                seVirtualCard.setMoney(afterRefund);
+                seVirtualCard.setLastOperate(LastOperateENUM.REFUND.getCode());
+                seVirtualCard.setLastOperateTime(new Date());
+                virtualCardSv.updateVirtualCard(seVirtualCard);
+            }
         }
 
         // 閫氱煡搴旂瓟
diff --git a/pipIrr-platform/pipIrr-web/pipIrr-web-sell/src/main/java/com/dy/pipIrrSell/wechatpay/dto/Orders.java b/pipIrr-platform/pipIrr-web/pipIrr-web-sell/src/main/java/com/dy/pipIrrSell/wechatpay/dto/Orders.java
new file mode 100644
index 0000000..4c8e63e
--- /dev/null
+++ b/pipIrr-platform/pipIrr-web/pipIrr-web-sell/src/main/java/com/dy/pipIrrSell/wechatpay/dto/Orders.java
@@ -0,0 +1,44 @@
+package com.dy.pipIrrSell.wechatpay.dto;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotNull;
+import jakarta.validation.constraints.Positive;
+import lombok.Data;
+
+import java.util.Date;
+
+/**
+ * @author ZhuBaoMin
+ * @date 2024-03-07 21:56
+ * @LastEditTime 2024-03-07 21:56
+ * @Description 璁㈠崟瀵硅薄锛屼粠鍏呭�艰〃涓彇鍑虹殑璁㈠崟淇℃伅
+ */
+
+@Data
+@Schema(name = "璁㈠崟瀵硅薄")
+public class Orders {
+    public static final long serialVersionUID = 202403072157001L;
+
+    /**
+     * 璁㈠崟鍙�
+     */
+    @Schema(description = "璁㈠崟鍙�", requiredMode = Schema.RequiredMode.NOT_REQUIRED)
+    @NotBlank(message = "璁㈠崟鍙蜂笉鑳戒负绌�")
+    private String orderNumber;
+
+    /**
+     * 鍏呭�奸噾棰�
+     */
+    @Schema(description = "鍏呭�奸噾棰�", requiredMode = Schema.RequiredMode.NOT_REQUIRED)
+    @NotNull(message = "鍏呭�奸噾棰濅笉鑳戒负绌�")
+    @Positive(message = "鍏呭�奸噾棰濆繀椤讳负澶т簬0鐨勬暣鏁�")
+    private Integer rechargeAmount;
+
+    /**
+     * 鍏呭�煎畬鎴愭椂闂�
+     */
+    @Schema(description = "鍏呭�煎畬鎴愭椂闂�", requiredMode = Schema.RequiredMode.NOT_REQUIRED)
+    @NotNull(message = "鍏呭�煎畬鎴愭椂闂翠笉鑳戒负绌�")
+    private Date rechargeTime;
+}
diff --git a/pipIrr-platform/pipIrr-web/pipIrr-web-sell/src/main/java/com/dy/pipIrrSell/wechatpay/dto/Refund.java b/pipIrr-platform/pipIrr-web/pipIrr-web-sell/src/main/java/com/dy/pipIrrSell/wechatpay/dto/Refund.java
index ebc7fc9..57be610 100644
--- a/pipIrr-platform/pipIrr-web/pipIrr-web-sell/src/main/java/com/dy/pipIrrSell/wechatpay/dto/Refund.java
+++ b/pipIrr-platform/pipIrr-web/pipIrr-web-sell/src/main/java/com/dy/pipIrrSell/wechatpay/dto/Refund.java
@@ -25,7 +25,7 @@
     private String tradeNo;
 
     /**
-     * 閫�娆惧崟鍙凤紝閫�娆惧崟鍙锋棤鍊硷細鏂版彁浜ら��娆剧敵璇枫�傞��娆惧崟鍙锋湁鍊硷細閲嶆柊鎻愪氦閫�娆�
+     * 閫�娆惧崟鍙�
      */
     @Schema(description = "閫�娆惧崟鍙�", requiredMode = Schema.RequiredMode.NOT_REQUIRED)
     private String refundNo;
diff --git a/pipIrr-platform/pipIrr-web/pipIrr-web-sell/src/main/java/com/dy/pipIrrSell/wechatpay/dto/ToRefund.java b/pipIrr-platform/pipIrr-web/pipIrr-web-sell/src/main/java/com/dy/pipIrrSell/wechatpay/dto/ToRefund.java
new file mode 100644
index 0000000..24eb95f
--- /dev/null
+++ b/pipIrr-platform/pipIrr-web/pipIrr-web-sell/src/main/java/com/dy/pipIrrSell/wechatpay/dto/ToRefund.java
@@ -0,0 +1,35 @@
+package com.dy.pipIrrSell.wechatpay.dto;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotNull;
+import jakarta.validation.constraints.Positive;
+import lombok.Data;
+
+/**
+ * @author ZhuBaoMin
+ * @date 2024-03-07 21:43
+ * @LastEditTime 2024-03-07 21:43
+ * @Description 寰呴��娆惧璞★紝鐢ㄦ埛閫夋嫨涓�涓櫄鎷熷崱閫�娆炬椂锛岀郴缁熼亶鍘嗗嚭涓�涓��娆惧璞″垪琛紝鐢卞涓鍗曞叡鍚屽畬鎴愰��娆�
+ */
+
+@Data
+@Schema(name = "寰呴��娆惧璞�")
+public class ToRefund {
+    public static final long serialVersionUID = 202403072144001L;
+
+    /**
+     * 璁㈠崟鍙�
+     */
+    @Schema(description = "璁㈠崟鍙�", requiredMode = Schema.RequiredMode.NOT_REQUIRED)
+    @NotBlank(message = "璁㈠崟鍙蜂笉鑳戒负绌�")
+    private String orderNumber;
+
+    /**
+     * 閫�娆鹃噾棰�
+     */
+    @Schema(description = "閫�娆鹃噾棰�", requiredMode = Schema.RequiredMode.NOT_REQUIRED)
+    @NotNull(message = "閫�娆鹃噾棰濅笉鑳戒负绌�")
+    @Positive(message = "閫�娆鹃噾棰濆繀椤讳负澶т簬0鐨勬暣鏁�")
+    private Integer refundAmount;
+}

--
Gitblit v1.8.0