Prechádzať zdrojové kódy

feat:新增退款单,拒绝接单金额原路返回

wrj 10 mesiacov pred
rodič
commit
77afc65533

+ 2 - 61
nightFragrance-admin/src/main/java/com/ylx/web/controller/massage/PayController.java

@@ -337,67 +337,8 @@ public class PayController {
 
     @RequestMapping("/refund")
     @ResponseBody
-    public String refund(@RequestParam(required = false) String outRefundNo, @RequestParam(required = false) String transactionId, @RequestParam(required = false) String outTradeNo) {
-        try {
-            log.info("商户退款单号: {}", outRefundNo);
-            //退款商品
-            List<RefundGoodsDetail> list = new ArrayList<>();
-            RefundGoodsDetail refundGoodsDetail = new RefundGoodsDetail()
-                    //商户侧商品编码
-                    .setMerchant_goods_id("123")
-                    //商品名称
-                    .setGoods_name("IJPay 测试")
-                    //商品单价
-                    .setUnit_price(1)
-                    //商品退款金额
-                    .setRefund_amount(1)
-                    //商品退货数量
-                    .setRefund_quantity(1);
-            list.add(refundGoodsDetail);
-
-            RefundModel refundModel = new RefundModel()
-                    //商户退款单号
-                    .setOut_refund_no(outRefundNo)
-                    //退款原因
-                    .setReason("IJPay 测试退款")
-                    //回调地址
-                    .setNotify_url(wxPayProperties.getRefundNotify())
-                    //金额信息
-                    .setAmount(new RefundAmount().setRefund(1).setTotal(1).setCurrency("CNY"))
-                    //退款商品
-                    .setGoods_detail(list);
-
-            //商户订单号
-            if (StrUtil.isNotEmpty(transactionId)) {
-                refundModel.setTransaction_id(transactionId);
-            }
-            if (StrUtil.isNotEmpty(outTradeNo)) {
-                refundModel.setOut_trade_no(outTradeNo);
-            }
-            log.info("退款参数 {}", JSONUtil.toJsonStr(refundModel));
-            IJPayHttpResponse response = WxPayApi.v3(
-                    RequestMethodEnum.POST,
-                    WxDomainEnum.CHINA.toString(),
-                    BasePayApiEnum.REFUND.toString(),
-                    wxPayProperties.getMchId(),
-                    getSerialNumber(),
-                    null,
-                    wxPayProperties.getCertKeyPath(),
-                    JSONUtil.toJsonStr(refundModel)
-            );
-            // 根据证书序列号查询对应的证书来验证签名结果
-            boolean verifySignature = WxPayKit.verifySignature(response, wxPayProperties.getPlatFormPath());
-            log.info("verifySignature: {}", verifySignature);
-            log.info("退款响应 {}", response);
-
-            if (verifySignature) {
-                return response.getBody();
-            }
-        } catch (Exception e) {
-            log.error("系统异常", e);
-            return e.getMessage();
-        }
-        return null;
+    public String refund(@RequestParam(required = false) String outRefundNo, BigDecimal amount,@RequestParam(required = false) String transactionId, @RequestParam(required = false) String outTradeNo) {
+        return rechargeService.refund(outRefundNo,transactionId,outTradeNo,amount);
     }
 
     /**

+ 85 - 0
nightFragrance-admin/src/main/java/com/ylx/web/controller/massage/RefundVoucherController.java

@@ -0,0 +1,85 @@
+package com.ylx.web.controller.massage;
+
+
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ylx.massage.domain.RefundVoucher;
+import com.ylx.massage.service.RefundVoucherService;
+import org.springframework.web.bind.annotation.*;
+import com.ylx.common.core.domain.R;
+import javax.annotation.Resource;
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * 退款单(RefundVoucher)表控制层
+ *
+ * @author makejava
+ * @since 2024-07-02 17:42:09
+ */
+@RestController
+@RequestMapping("refundVoucher")
+public class RefundVoucherController  {
+    /**
+     * 服务对象
+     */
+    @Resource
+    private RefundVoucherService refundVoucherService;
+
+    /**
+     * 分页查询所有数据
+     *
+     * @param page          分页对象
+     * @param refundVoucher 查询实体
+     * @return 所有数据
+     */
+    @GetMapping
+    public R selectAll(Page<RefundVoucher> page, RefundVoucher refundVoucher) {
+        return R.ok(this.refundVoucherService.page(page, new QueryWrapper<>(refundVoucher)));
+    }
+
+    /**
+     * 通过主键查询单条数据
+     *
+     * @param id 主键
+     * @return 单条数据
+     */
+    @GetMapping("{id}")
+    public R selectOne(@PathVariable Serializable id) {
+        return R.ok(this.refundVoucherService.getById(id));
+    }
+
+    /**
+     * 新增数据
+     *
+     * @param refundVoucher 实体对象
+     * @return 新增结果
+     */
+    @PostMapping
+    public R insert(@RequestBody RefundVoucher refundVoucher) {
+        return R.ok(this.refundVoucherService.save(refundVoucher));
+    }
+
+    /**
+     * 修改数据
+     *
+     * @param refundVoucher 实体对象
+     * @return 修改结果
+     */
+    @PutMapping
+    public R update(@RequestBody RefundVoucher refundVoucher) {
+        return R.ok(this.refundVoucherService.updateById(refundVoucher));
+    }
+
+    /**
+     * 删除数据
+     *
+     * @param idList 主键结合
+     * @return 删除结果
+     */
+    @DeleteMapping
+    public R delete(@RequestParam("idList") List<Long> idList) {
+        return R.ok(this.refundVoucherService.removeByIds(idList));
+    }
+}
+

+ 130 - 0
nightFragrance-massage/src/main/java/com/ylx/massage/domain/RefundVoucher.java

@@ -0,0 +1,130 @@
+package com.ylx.massage.domain;
+
+
+import com.baomidou.mybatisplus.extension.activerecord.Model;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.util.Date;
+
+/**
+ * 退款单(RefundVoucher)表实体类
+ *
+ * @author makejava
+ * @since 2024-07-02 17:42:09
+ */
+@SuppressWarnings("serial")
+public class RefundVoucher extends Model<RefundVoucher> {
+
+    private String id;
+    //退款单号
+    private String refundNo;
+    //用户openid
+    private String openId;
+    //退款金额
+    private BigDecimal money;
+    //订单号
+    private String orderNo;
+    //退款原因
+    private String reason;
+    //退款状态 0待退款 1已退款
+    private Integer reStatus;
+    //是否删除0否1是
+    private Integer isDelete;
+    //系统创建时间
+    private Date createTime;
+    //系统修改时间
+    private Date updateTime;
+
+
+    public String getId() {
+        return id;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    public String getRefundNo() {
+        return refundNo;
+    }
+
+    public void setRefundNo(String refundNo) {
+        this.refundNo = refundNo;
+    }
+
+    public String getOpenId() {
+        return openId;
+    }
+
+    public void setOpenId(String openId) {
+        this.openId = openId;
+    }
+
+    public BigDecimal getMoney() {
+        return money;
+    }
+
+    public void setMoney(BigDecimal money) {
+        this.money = money;
+    }
+
+    public String getOrderNo() {
+        return orderNo;
+    }
+
+    public void setOrderNo(String orderNo) {
+        this.orderNo = orderNo;
+    }
+
+    public String getReason() {
+        return reason;
+    }
+
+    public void setReason(String reason) {
+        this.reason = reason;
+    }
+
+    public Integer getReStatus() {
+        return reStatus;
+    }
+
+    public void setReStatus(Integer reStatus) {
+        this.reStatus = reStatus;
+    }
+
+    public Integer getIsDelete() {
+        return isDelete;
+    }
+
+    public void setIsDelete(Integer isDelete) {
+        this.isDelete = isDelete;
+    }
+
+    public Date getCreateTime() {
+        return createTime;
+    }
+
+    public void setCreateTime(Date createTime) {
+        this.createTime = createTime;
+    }
+
+    public Date getUpdateTime() {
+        return updateTime;
+    }
+
+    public void setUpdateTime(Date updateTime) {
+        this.updateTime = updateTime;
+    }
+
+    /**
+     * 获取主键值
+     *
+     * @return 主键值
+     */
+    @Override
+    public Serializable pkVal() {
+        return this.id;
+    }
+}
+

+ 1 - 1
nightFragrance-massage/src/main/java/com/ylx/massage/domain/TJs.java

@@ -181,7 +181,7 @@ public class TJs implements Serializable {
 
 
     /**
-     * 服务状态	0 可服务	1 服务中
+     * 服务状态	0 可服务	1 服务中 2不可服务
      */
     @TableField("n_status")
     @ApiModelProperty("服务状态\t0 可服务\t1 服务中")

+ 35 - 0
nightFragrance-massage/src/main/java/com/ylx/massage/mapper/RefundVoucherMapper.java

@@ -0,0 +1,35 @@
+package com.ylx.massage.mapper;
+
+import java.util.List;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.apache.ibatis.annotations.Param;
+import com.ylx.massage.domain.RefundVoucher;
+
+/**
+ * 退款单(RefundVoucher)表数据库访问层
+ *
+ * @author makejava
+ * @since 2024-07-02 17:42:09
+ */
+public interface RefundVoucherMapper extends BaseMapper<RefundVoucher> {
+
+    /**
+     * 批量新增数据(MyBatis原生foreach方法)
+     *
+     * @param entities List<RefundVoucher> 实例对象列表
+     * @return 影响行数
+     */
+    int insertBatch(@Param("entities") List<RefundVoucher> entities);
+
+    /**
+     * 批量新增或按主键更新数据(MyBatis原生foreach方法)
+     *
+     * @param entities List<RefundVoucher> 实例对象列表
+     * @return 影响行数
+     * @throws org.springframework.jdbc.BadSqlGrammarException 入参是空List的时候会抛SQL语句错误的异常,请自行校验入参
+     */
+    int insertOrUpdateBatch(@Param("entities") List<RefundVoucher> entities);
+
+}
+

+ 15 - 0
nightFragrance-massage/src/main/java/com/ylx/massage/service/RefundVoucherService.java

@@ -0,0 +1,15 @@
+package com.ylx.massage.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.ylx.massage.domain.RefundVoucher;
+
+/**
+ * 退款单(RefundVoucher)表服务接口
+ *
+ * @author makejava
+ * @since 2024-07-02 17:42:09
+ */
+public interface RefundVoucherService extends IService<RefundVoucher> {
+
+}
+

+ 11 - 0
nightFragrance-massage/src/main/java/com/ylx/massage/service/TRechargeService.java

@@ -17,4 +17,15 @@ public interface TRechargeService extends IService<TRecharge> {
     TRecharge increaseAmount(String rechargeNo);
 
     R getPay(String setOutTradeNo, BigDecimal amount, String openId,String description,String attach) throws Exception;
+
+    /**
+     * 退款接口
+     * 此方法根据给定的退款编号、交易ID和原始交易订单号处理退款请求。
+     *
+     * @param outRefundNo 商户系统内部的退款单号,对同一个退款单号多次提交退款请求,只退一次。
+     * @param transactionId 支付交易号,通过此交易号可以追溯交易支付时的信息。
+     * @param outTradeNo 商户系统内部的订单号,与transactionId不能同时为空。
+     * @return 如果退款成功,返回退款成功的标识字符串;如果失败,返回错误信息字符串。
+     */
+    String refund(String outRefundNo, String transactionId, String outTradeNo, BigDecimal amount);
 }

+ 19 - 0
nightFragrance-massage/src/main/java/com/ylx/massage/service/impl/RefundVoucherServiceImpl.java

@@ -0,0 +1,19 @@
+package com.ylx.massage.service.impl;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.ylx.massage.mapper.RefundVoucherMapper;
+import com.ylx.massage.domain.RefundVoucher;
+import com.ylx.massage.service.RefundVoucherService;
+import org.springframework.stereotype.Service;
+
+/**
+ * 退款单(RefundVoucher)表服务实现类
+ *
+ * @author makejava
+ * @since 2024-07-02 17:42:10
+ */
+@Service("refundVoucherService")
+public class RefundVoucherServiceImpl extends ServiceImpl<RefundVoucherMapper, RefundVoucher> implements RefundVoucherService {
+
+}
+

+ 23 - 3
nightFragrance-massage/src/main/java/com/ylx/massage/service/impl/TOrderServiceImpl.java

@@ -81,6 +81,9 @@ public class TOrderServiceImpl extends ServiceImpl<TOrderMapper, TOrder> impleme
     @Resource
     private WeChatUtil weChatUtil;
 
+    @Resource
+    private RefundVoucherService refundVoucherService;
+
 
     public Boolean isFree(String jsId, BigDecimal distance) {
         TJs js = jsService.getById(jsId);
@@ -322,14 +325,31 @@ public class TOrderServiceImpl extends ServiceImpl<TOrderMapper, TOrder> impleme
      */
     @Override
     public Boolean jujue(TOrder order) {
+
         TOrder orderNew = getById(order.getcId());
 
-        TWxUser user = wxUserService.getById(orderNew.getcOpenId());
+        TWxUser user = wxUserService.getByOpenId(orderNew.getcOpenId());
         // 更新用户金额 及下单此时
         TWxUser paramUser = new TWxUser();
         paramUser.setcOpenid(user.getcOpenid());
-        // 金额归还对应账户
-        paramUser.setdBalance(user.getdBalance().add(orderNew.getdTotalMoney()));
+        if (orderNew.getPayType() == 2) {
+            // 金额归还对应账户
+            paramUser.setdBalance(user.getdBalance().add(orderNew.getdTotalMoney()));
+        } else {
+            // 微信支付
+            // 生成退款单退款
+            RefundVoucher refundVoucher = new RefundVoucher();
+            refundVoucher.setRefundNo(generator.generateNextOrderNumber(OrderNumberGenerator.KEY_PREFIX_REFUND));
+            refundVoucher.setOrderNo(orderNew.getOrderNo());
+            refundVoucher.setMoney(orderNew.getTotalPrice());
+            refundVoucher.setOpenId(orderNew.getcOpenId());
+            refundVoucher.setReStatus(MassageConstants.INTEGER_ZERO);
+            refundVoucher.setReason("技师拒绝接单");
+            refundVoucherService.save(refundVoucher);
+            // 微信退款原路返回
+            rechargeService.refund(refundVoucher.getRefundNo(), null, orderNew.getOrderNo(), orderNew.getTotalPrice());
+        }
+
         // 消费金额对应减少
         paramUser.setdMoney(user.getdMoney().subtract(orderNew.getdTotalMoney()));
         // 下单次数减一

+ 70 - 3
nightFragrance-massage/src/main/java/com/ylx/massage/service/impl/TRechargeServiceImpl.java

@@ -17,9 +17,7 @@ import com.ijpay.core.utils.DateTimeZoneUtil;
 import com.ijpay.wxpay.WxPayApi;
 import com.ijpay.wxpay.enums.WxDomainEnum;
 import com.ijpay.wxpay.enums.v3.BasePayApiEnum;
-import com.ijpay.wxpay.model.v3.Amount;
-import com.ijpay.wxpay.model.v3.Payer;
-import com.ijpay.wxpay.model.v3.UnifiedOrderModel;
+import com.ijpay.wxpay.model.v3.*;
 import com.ylx.common.config.WechatAccountConfig;
 import com.ylx.common.config.WxPayConfig;
 import com.ylx.common.core.domain.R;
@@ -43,6 +41,8 @@ import javax.annotation.Resource;
 import java.math.BigDecimal;
 import java.security.cert.X509Certificate;
 import java.time.LocalDateTime;
+import java.util.ArrayList;
+import java.util.List;
 import java.util.Map;
 
 import static com.ylx.common.constant.HttpStatus.SUCCESS;
@@ -174,6 +174,73 @@ public class TRechargeServiceImpl extends ServiceImpl<TRechargeMapper, TRecharge
         return R.ok(JSONUtil.toJsonStr(response));
     }
 
+    @Override
+    public String refund(String outRefundNo, String transactionId, String outTradeNo, BigDecimal amount) {
+        try {
+
+            int i = amount.multiply(new BigDecimal(100)).intValue();
+
+            log.info("商户退款单号: {}", outRefundNo);
+            //退款商品
+            List<RefundGoodsDetail> list = new ArrayList<>();
+            RefundGoodsDetail refundGoodsDetail = new RefundGoodsDetail()
+                    //商户侧商品编码
+                    .setMerchant_goods_id("123")
+                    //商品名称
+                    .setGoods_name("IJPay 测试")
+                    //商品单价
+                    .setUnit_price(1)
+                    //商品退款金额
+                    .setRefund_amount(1)
+                    //商品退货数量
+                    .setRefund_quantity(1);
+            list.add(refundGoodsDetail);
+
+            RefundModel refundModel = new RefundModel()
+                    //商户退款单号
+                    .setOut_refund_no(outRefundNo)
+                    //退款原因
+                    //.setReason("IJPay 测试退款")
+                    //回调地址
+                    .setNotify_url(wxPayProperties.getRefundNotify())
+                    //金额信息
+                    .setAmount(new RefundAmount().setRefund(i).setTotal(i).setCurrency("CNY"));
+                    //退款商品
+                    //.setGoods_detail(list);
+
+            //商户订单号
+            if (StrUtil.isNotEmpty(transactionId)) {
+                refundModel.setTransaction_id(transactionId);
+            }
+            if (StrUtil.isNotEmpty(outTradeNo)) {
+                refundModel.setOut_trade_no(outTradeNo);
+            }
+            log.info("退款参数 {}", JSONUtil.toJsonStr(refundModel));
+            IJPayHttpResponse response = WxPayApi.v3(
+                    RequestMethodEnum.POST,
+                    WxDomainEnum.CHINA.toString(),
+                    BasePayApiEnum.REFUND.toString(),
+                    wxPayProperties.getMchId(),
+                    getSerialNumber(),
+                    null,
+                    wxPayProperties.getCertKeyPath(),
+                    JSONUtil.toJsonStr(refundModel)
+            );
+            // 根据证书序列号查询对应的证书来验证签名结果
+            boolean verifySignature = WxPayKit.verifySignature(response, wxPayProperties.getPlatFormPath());
+            log.info("verifySignature: {}", verifySignature);
+            log.info("退款响应 {}", response);
+
+            if (verifySignature) {
+                return response.getBody();
+            }
+        } catch (Exception e) {
+            log.error("系统异常", e);
+            return e.getMessage();
+        }
+        return null;
+    }
+
     private String getSerialNumber() {
         if (StrUtil.isEmpty(serialNo)) {
             // 获取证书序列号

+ 3 - 0
nightFragrance-massage/src/main/java/com/ylx/massage/utils/OrderNumberGenerator.java

@@ -17,6 +17,9 @@ public class OrderNumberGenerator {
     public static final String KEY_PREFIX_RECHAR = "RECHAR";
 
     public static final String KEY_PREFIX_CASH = "CASH";
+
+    public static final String KEY_PREFIX_REFUND = "REFUND";
+
     private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyyMMdd");
 
     private final StringRedisTemplate stringRedisTemplate;

+ 40 - 0
nightFragrance-massage/src/main/resources/mapper/massage/RefundVoucherMapper.xml

@@ -0,0 +1,40 @@
+<?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.ylx.massage.mapper.RefundVoucherMapper">
+
+    <resultMap type="com.ylx.massage.domain.RefundVoucher" id="RefundVoucherMap">
+        <result property="id" column="id" jdbcType="VARCHAR"/>
+        <result property="refundNo" column="refund_no" jdbcType="VARCHAR"/>
+        <result property="openId" column="open_id" jdbcType="VARCHAR"/>
+        <result property="money" column="money" jdbcType="NUMERIC"/>
+        <result property="orderNo" column="order_no" jdbcType="VARCHAR"/>
+        <result property="reason" column="reason" jdbcType="VARCHAR"/>
+        <result property="reStatus" column="re_status" jdbcType="INTEGER"/>
+        <result property="isDelete" column="is_delete" jdbcType="INTEGER"/>
+        <result property="createTime" column="create_time" jdbcType="TIMESTAMP"/>
+        <result property="updateTime" column="update_time" jdbcType="TIMESTAMP"/>
+    </resultMap>
+
+    <!-- 批量插入 -->
+    <insert id="insertBatch" keyProperty="id" useGeneratedKeys="true">
+        insert into ry-vue.refund_voucher(refund_noopen_idmoneyorder_noreasonre_statusis_deletecreate_timeupdate_time)
+        values
+        <foreach collection="entities" item="entity" separator=",">
+            (#{entity.refundNo}#{entity.openId}#{entity.money}#{entity.orderNo}#{entity.reason}#{entity.reStatus}#{entity.isDelete}#{entity.createTime}#{entity.updateTime})
+        </foreach>
+    </insert>
+    <!-- 批量插入或按主键更新 -->
+    <insert id="insertOrUpdateBatch" keyProperty="id" useGeneratedKeys="true">
+        insert into ry-vue.refund_voucher(refund_noopen_idmoneyorder_noreasonre_statusis_deletecreate_timeupdate_time)
+        values
+        <foreach collection="entities" item="entity" separator=",">
+            (#{entity.refundNo}#{entity.openId}#{entity.money}#{entity.orderNo}#{entity.reason}#{entity.reStatus}#{entity.isDelete}#{entity.createTime}#{entity.updateTime})
+        </foreach>
+        on duplicate key update
+        refund_no = values(refund_no) open_id = values(open_id) money = values(money) order_no = values(order_no) reason
+        = values(reason) re_status = values(re_status) is_delete = values(is_delete) create_time = values(create_time)
+        update_time = values(update_time)
+    </insert>
+
+</mapper>
+