Sfoglia il codice sorgente

完善对接企业微信-获取收款记录接口

cgp 6 giorni fa
parent
commit
f21c665545

+ 99 - 0
fs-service/src/main/java/com/fs/qw/domain/FsCompanyExternalPayRefund.java

@@ -0,0 +1,99 @@
+package com.fs.qw.domain;
+
+import com.baomidou.mybatisplus.annotation.*;
+import com.fs.common.core.domain.BaseEntity;
+import lombok.Data;
+import java.math.BigDecimal;
+import java.util.Date;
+
+/**
+ * 企业对外退款记录实体类
+ * 表名:fs_company_external_pay_refund
+ */
+@Data
+@TableName("fs_company_external_pay_refund")
+public class FsCompanyExternalPayRefund extends BaseEntity {
+
+    /**
+     * 主键ID,自增长
+     */
+    @TableId(type = IdType.AUTO)
+    private Long id;
+
+    /**
+     * 交易单号(企业微信唯一标识,对应原收款单的transaction_id)
+     */
+    private String transactionId;
+
+    /**
+     * 原收款商户单号
+     */
+    private String outTradeNo;
+
+    /**
+     * 退款单号(唯一)
+     */
+    private String outRefundNo;
+
+    /**
+     * 退款发起人的企业微信 userid
+     */
+    private String refundUserid;
+
+    /**
+     * 退款备注
+     */
+    private String refundComment;
+
+    /**
+     * 退款发起时间(秒级时间戳)
+     */
+    private Long refundReqtime;
+
+    /**
+     * 退款状态:0-已申请,1-处理中,2-成功,3-关闭,4-异常,5-审批中,6-审批失败,7-审批取消
+     */
+    private Integer refundStatus;
+
+    /**
+     * 退款金额,单位:元
+     */
+    private BigDecimal refundFee;
+
+    /**
+     * 付款人的企业微信 external_userid
+     */
+    private String externalUserid;
+
+    /**
+     * 原收款成员(退款记录中该字段为退款发起人,与refundUserid相同)
+     */
+    private String payeeUserid;
+
+    /**
+     * 原收款方式:0-聊天中,1-收款码,2-直播间,3-产品图册,14-转账,15-小程序
+     */
+    private Integer paymentType;
+
+    /**
+     * 收款商户号id
+     */
+    private String mchId;
+
+    /**
+     * 原交易时间(秒级时间戳)
+     */
+    private Long payTime;
+
+    /**
+     * 本地创建时间(自动填充)
+     */
+    @TableField(fill = FieldFill.INSERT)
+    private Date createTime;
+
+    /**
+     * 本地更新时间(自动填充)
+     */
+    @TableField(fill = FieldFill.INSERT_UPDATE)
+    private Date updateTime;
+}

+ 54 - 13
fs-service/src/main/java/com/fs/qw/dto/ReceiptDto.java

@@ -3,37 +3,78 @@ package com.fs.qw.dto;
 import lombok.Data;
 
 /**
- * 企业微信对外收款记录 DTO(仅收款记录)
- * 用于接收接口返回的原始数据
+ * 企业微信对外收款/退款记录 DTO
+ * 用于接收企业微信 get_bill_list 接口返回的原始数据
  */
 @Data
 public class ReceiptDto {
-    /** 交易单号 */
+
+    // ========== 通用字段 ==========
+
+    /** 交易单号(企业微信唯一标识) */
     private String transactionId;
-    /** 交易状态:1-已完成,3-已完成有退款 */
+
+    /** 交易类型:0-收款记录,1-退款记录 */
+    private Integer billType;
+
+    /** 交易状态(仅收款记录有):1-已完成,3-已完成有退款 */
     private Integer tradeState;
+
     /** 交易时间(秒级时间戳) */
     private Long payTime;
-    /** 商户单号 */
+
+    /** 商户单号(退款记录时对应原收款记录的商户单号) */
     private String outTradeNo;
+
     /** 付款人的 external_userid */
     private String externalUserid;
-    /** 收款总金额(分) */
+
+    /** 收款总金额(单位:分),退款记录中为原收款金额 */
     private Integer totalFee;
-    /** 收款成员 userid */
+
+    /** 企业内账号userid(收款记录为收款成员,退款记录为退款成员) */
     private String payeeUserid;
-    /** 收款方式:0聊天中,1收款码,2直播间,3产品图册,14转账,15小程序 */
+
+    /** 收款方式:0-聊天中,1-收款码,2-直播间,3-产品图册,14-转账,15-小程序 */
     private Integer paymentType;
+
     /** 收款商户号id */
     private String mchId;
-    /** 备注 */
+
+    /** 备注(收款记录为收款备注,退款记录为退款备注) */
     private String remark;
-    /** 退款总金额(分) */
+
+    // ========== 收款记录特有字段 ==========
+
+    /** 退款总金额(单位:分),仅收款记录有 */
     private Integer totalRefundFee;
-    /** 商品信息 JSON 字符串 */
+
+    /** 商品信息 JSON 数组,格式:[{"description":"手机","amount":1}],仅收款记录有 */
     private String commodityList;
-    /** 联系人信息 JSON 字符串 */
+
+    /** 联系人信息 JSON 对象,格式:{"name":"张三","phone":"138...","address":"..."},第三方不可获取 */
     private String contactInfo;
-    /** 小程序信息 JSON 字符串 */
+
+    /** 小程序信息 JSON 对象,收款方式为小程序时返回,格式:{"appid":"wx...","name":"XX小程序"} */
     private String miniprogramInfo;
+
+    // ========== 退款记录特有字段 ==========
+
+    /** 退款单号(仅退款记录有) */
+    private String outRefundNo;
+
+    /** 退款发起人ID(仅退款记录有) */
+    private String refundUserid;
+
+    /** 退款备注(仅退款记录有) */
+    private String refundComment;
+
+    /** 退款发起时间(秒级时间戳,仅退款记录有) */
+    private Long refundReqtime;
+
+    /** 退款状态(仅退款记录有):0-已申请,1-处理中,2-成功,3-关闭,4-异常,5-审批中,6-审批失败,7-审批取消 */
+    private Integer refundStatus;
+
+    /** 退款金额(单位:分,仅退款记录有) */
+    private Integer refundFee;
 }

+ 18 - 0
fs-service/src/main/java/com/fs/qw/mapper/FsCompanyExternalPayRefundMapper.java

@@ -0,0 +1,18 @@
+package com.fs.qw.mapper;
+
+import com.fs.qw.domain.FsCompanyExternalPayRefund;
+import org.apache.ibatis.annotations.Param;
+import java.util.List;
+
+public interface FsCompanyExternalPayRefundMapper {
+
+    int insertRefund(FsCompanyExternalPayRefund refund);
+
+    int updateRefund(FsCompanyExternalPayRefund refund);
+
+    FsCompanyExternalPayRefund selectByTransactionId(@Param("transactionId") String transactionId);
+
+    FsCompanyExternalPayRefund selectByOutRefundNo(@Param("outRefundNo") String outRefundNo);
+
+    List<FsCompanyExternalPayRefund> selectRefundList(FsCompanyExternalPayRefund refund);
+}

+ 39 - 16
fs-service/src/main/java/com/fs/qw/service/impl/FsCompanyExternalPayReceiptServiceImpl.java

@@ -1,8 +1,10 @@
 package com.fs.qw.service.impl;
 
 import com.fs.qw.domain.FsCompanyExternalPayReceipt;
+import com.fs.qw.domain.FsCompanyExternalPayRefund;
 import com.fs.qw.dto.ReceiptDto;
 import com.fs.qw.mapper.FsCompanyExternalPayReceiptMapper;
+import com.fs.qw.mapper.FsCompanyExternalPayRefundMapper;
 import com.fs.qw.service.IFsCompanyExternalPayReceiptService;
 import com.fs.qw.utils.MoneyUtils;
 import lombok.extern.slf4j.Slf4j;
@@ -25,31 +27,52 @@ public class FsCompanyExternalPayReceiptServiceImpl implements IFsCompanyExterna
     @Autowired
     private FsCompanyExternalPayReceiptMapper receiptMapper;
 
-    // 同步收款记录(定时任务同步或手动同步)
+    @Autowired
+    private FsCompanyExternalPayRefundMapper refundMapper;
+
+    // 同步收、退款记录(定时任务同步或手动同步)
     @Override
     @Transactional(rollbackFor = Exception.class)
-    public void syncReceipts(Long beginTime, Long endTime, String payeeUserid,String corpId) {
-        List<ReceiptDto> receiptList = weWorkPayService.fetchAllReceipts(beginTime, endTime, payeeUserid,corpId);
+    public void syncReceipts(Long beginTime, Long endTime, String payeeUserid, String corpId) {
+        List<ReceiptDto> receiptList = weWorkPayService.fetchAllReceipts(beginTime, endTime, payeeUserid, corpId);
         if (CollectionUtils.isEmpty(receiptList)) {
-            log.info("没有需要同步的收款记录");
+            log.info("没有需要同步的记录");
             return;
         }
 
         for (ReceiptDto dto : receiptList) {
-            FsCompanyExternalPayReceipt entity = new FsCompanyExternalPayReceipt();
-            BeanUtils.copyProperties(dto, entity);
-            // 同步时转换一下金额单位,微信官方返回的是分,数据库中存储的是元
-            entity.setTotalFee(MoneyUtils.centToYuan(dto.getTotalFee()));
-            entity.setTotalRefundFee(MoneyUtils.centToYuan(dto.getTotalRefundFee()));
-            FsCompanyExternalPayReceipt exist = receiptMapper.selectByTransactionId(dto.getTransactionId());
-            if (exist == null) {
-                receiptMapper.insertFsCompanyExternalPayReceipt(entity);
-            } else {
-                entity.setId(exist.getId());
-                receiptMapper.updateFsCompanyExternalPayReceipt(entity);
+            if (dto.getBillType() == 0) {
+                // 收款记录
+                FsCompanyExternalPayReceipt entity = new FsCompanyExternalPayReceipt();
+                BeanUtils.copyProperties(dto, entity);
+                entity.setTotalFee(MoneyUtils.centToYuan(dto.getTotalFee()));
+                entity.setTotalRefundFee(MoneyUtils.centToYuan(dto.getTotalRefundFee()));
+
+                FsCompanyExternalPayReceipt exist = receiptMapper.selectByTransactionId(dto.getTransactionId());
+                if (exist == null) {
+                    receiptMapper.insertFsCompanyExternalPayReceipt(entity);
+                } else {
+                    entity.setId(exist.getId());
+                    receiptMapper.updateFsCompanyExternalPayReceipt(entity);
+                }
+            } else if (dto.getBillType() == 1) {
+                // 退款记录
+                FsCompanyExternalPayRefund refund = new FsCompanyExternalPayRefund();
+                // 复制同名同类型字段
+                BeanUtils.copyProperties(dto, refund);
+                // 单独处理金额(分转元)
+                refund.setRefundFee(MoneyUtils.centToYuan(dto.getRefundFee()));
+
+                FsCompanyExternalPayRefund existRefund = refundMapper.selectByTransactionId(dto.getTransactionId());
+                if (existRefund == null) {
+                    refundMapper.insertRefund(refund);
+                } else {
+                    refund.setId(existRefund.getId());
+                    refundMapper.updateRefund(refund);
+                }
             }
         }
-        log.info("同步收款记录完成,共处理 {} 条", receiptList.size());
+        log.info("同步完成,共处理 {} 条记录", receiptList.size());
     }
 
     @Override

+ 15 - 11
fs-service/src/main/java/com/fs/qw/service/impl/WeWorkExternalPayService.java

@@ -76,7 +76,7 @@ public class WeWorkExternalPayService {
             if (billList != null && !billList.isEmpty()) {
                 for (Object obj : billList) {
                     JSONObject item = (JSONObject) obj;
-                    // 只处理收款记录(bill_type=0)
+                    // 只处理收款记录(bill_type=0),如果要处理退款记录,后续完善
                     Integer billType = item.getInt("bill_type");
                     if (billType != null && billType == 0) {
                         ReceiptDto dto = convertToReceiptDto(item);
@@ -96,6 +96,7 @@ public class WeWorkExternalPayService {
     private ReceiptDto convertToReceiptDto(JSONObject item) {
         ReceiptDto dto = new ReceiptDto();
         dto.setTransactionId(item.getStr("transaction_id"));
+        dto.setBillType(item.getInt("bill_type"));
         dto.setTradeState(item.getInt("trade_state"));
         dto.setPayTime(item.getLong("pay_time"));
         dto.setOutTradeNo(item.getStr("out_trade_no"));
@@ -107,19 +108,22 @@ public class WeWorkExternalPayService {
         dto.setRemark(item.getStr("remark"));
         dto.setTotalRefundFee(item.getInt("total_refund_fee"));
 
-        // 嵌套对象转 JSON 字符串
+        // 嵌套对象(仅收款记录有)
         Object commodityListObj = item.get("commodity_list");
-        if (commodityListObj != null) {
-            dto.setCommodityList(JSONUtil.toJsonStr(commodityListObj));
-        }
+        if (commodityListObj != null) dto.setCommodityList(JSONUtil.toJsonStr(commodityListObj));
         Object contactInfoObj = item.get("contact_info");
-        if (contactInfoObj != null) {
-            dto.setContactInfo(JSONUtil.toJsonStr(contactInfoObj));
-        }
+        if (contactInfoObj != null) dto.setContactInfo(JSONUtil.toJsonStr(contactInfoObj));
         Object miniprogramInfoObj = item.get("miniprogram_info");
-        if (miniprogramInfoObj != null) {
-            dto.setMiniprogramInfo(JSONUtil.toJsonStr(miniprogramInfoObj));
-        }
+        if (miniprogramInfoObj != null) dto.setMiniprogramInfo(JSONUtil.toJsonStr(miniprogramInfoObj));
+
+        // 退款记录特有字段
+        dto.setOutRefundNo(item.getStr("out_refund_no"));
+        dto.setRefundUserid(item.getStr("refund_userid"));
+        dto.setRefundComment(item.getStr("refund_comment"));
+        dto.setRefundReqtime(item.getLong("refund_reqtime"));
+        dto.setRefundStatus(item.getInt("refund_status"));
+        dto.setRefundFee(item.getInt("refund_fee"));
+
         return dto;
     }
 }

+ 83 - 0
fs-service/src/main/resources/mapper/qw/FsCompanyExternalPayRefundMapper.xml

@@ -0,0 +1,83 @@
+<?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.fs.qw.mapper.FsCompanyExternalPayRefundMapper">
+
+    <resultMap type="com.fs.qw.domain.FsCompanyExternalPayRefund" id="FsCompanyExternalPayRefundResult">
+        <result property="id"               column="id"               />
+        <result property="transactionId"    column="transaction_id"   />
+        <result property="outTradeNo"       column="out_trade_no"      />
+        <result property="outRefundNo"      column="out_refund_no"     />
+        <result property="refundUserid"     column="refund_userid"     />
+        <result property="refundComment"    column="refund_comment"    />
+        <result property="refundReqtime"    column="refund_reqtime"    />
+        <result property="refundStatus"     column="refund_status"     />
+        <result property="refundFee"        column="refund_fee"        />
+        <result property="externalUserid"   column="external_userid"   />
+        <result property="payeeUserid"      column="payee_userid"      />
+        <result property="paymentType"      column="payment_type"      />
+        <result property="mchId"            column="mch_id"            />
+        <result property="payTime"          column="pay_time"          />
+        <result property="createTime"       column="create_time"       />
+        <result property="updateTime"       column="update_time"       />
+    </resultMap>
+
+    <sql id="Base_Column_List">
+        id, transaction_id, out_trade_no, out_refund_no, refund_userid, refund_comment,
+        refund_reqtime, refund_status, refund_fee, external_userid, payee_userid,
+        payment_type, mch_id, pay_time, create_time, update_time
+    </sql>
+
+    <insert id="insertRefund" parameterType="com.fs.qw.domain.FsCompanyExternalPayRefund" useGeneratedKeys="true" keyProperty="id">
+        insert into fs_company_external_pay_refund
+        <trim prefix="(" suffix=")" suffixOverrides=",">
+            transaction_id, out_trade_no, out_refund_no, refund_userid, refund_comment,
+            refund_reqtime, refund_status, refund_fee, external_userid, payee_userid,
+            payment_type, mch_id, pay_time, create_time, update_time
+        </trim>
+        <trim prefix="values (" suffix=")" suffixOverrides=",">
+            #{transactionId}, #{outTradeNo}, #{outRefundNo}, #{refundUserid}, #{refundComment},
+            #{refundReqtime}, #{refundStatus}, #{refundFee}, #{externalUserid}, #{payeeUserid},
+            #{paymentType}, #{mchId}, #{payTime}, sysdate(), sysdate()
+        </trim>
+    </insert>
+
+    <update id="updateRefund" parameterType="com.fs.qw.domain.FsCompanyExternalPayRefund">
+        update fs_company_external_pay_refund
+        <set>
+            <if test="outTradeNo != null">out_trade_no = #{outTradeNo},</if>
+            <if test="outRefundNo != null">out_refund_no = #{outRefundNo},</if>
+            <if test="refundUserid != null">refund_userid = #{refundUserid},</if>
+            <if test="refundComment != null">refund_comment = #{refundComment},</if>
+            <if test="refundReqtime != null">refund_reqtime = #{refundReqtime},</if>
+            <if test="refundStatus != null">refund_status = #{refundStatus},</if>
+            <if test="refundFee != null">refund_fee = #{refundFee},</if>
+            <if test="externalUserid != null">external_userid = #{externalUserid},</if>
+            <if test="payeeUserid != null">payee_userid = #{payeeUserid},</if>
+            <if test="paymentType != null">payment_type = #{paymentType},</if>
+            <if test="mchId != null">mch_id = #{mchId},</if>
+            <if test="payTime != null">pay_time = #{payTime},</if>
+            update_time = sysdate()
+        </set>
+        where id = #{id}
+    </update>
+
+    <select id="selectByTransactionId" resultMap="FsCompanyExternalPayRefundResult">
+        select <include refid="Base_Column_List"/> from fs_company_external_pay_refund where transaction_id = #{transactionId}
+    </select>
+
+    <select id="selectByOutRefundNo" resultMap="FsCompanyExternalPayRefundResult">
+        select <include refid="Base_Column_List"/> from fs_company_external_pay_refund where out_refund_no = #{outRefundNo}
+    </select>
+
+    <select id="selectRefundList" parameterType="com.fs.qw.domain.FsCompanyExternalPayRefund" resultMap="FsCompanyExternalPayRefundResult">
+        select <include refid="Base_Column_List"/> from fs_company_external_pay_refund
+        <where>
+            <if test="transactionId != null and transactionId != ''">and transaction_id = #{transactionId}</if>
+            <if test="outTradeNo != null and outTradeNo != ''">and out_trade_no = #{outTradeNo}</if>
+            <if test="outRefundNo != null and outRefundNo != ''">and out_refund_no = #{outRefundNo}</if>
+            <if test="refundUserid != null and refundUserid != ''">and refund_userid = #{refundUserid}</if>
+            <if test="refundStatus != null">and refund_status = #{refundStatus}</if>
+        </where>
+        order by refund_reqtime desc
+    </select>
+</mapper>