|
|
@@ -2,10 +2,14 @@ package io.renren.modules.qyh.service.impl;
|
|
|
|
|
|
import cn.hutool.core.lang.Snowflake;
|
|
|
import cn.hutool.core.map.MapUtil;
|
|
|
+import cn.hutool.json.JSONUtil;
|
|
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
|
|
import com.baomidou.mybatisplus.core.metadata.IPage;
|
|
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
|
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
|
|
+import com.wechat.pay.java.service.transferbatch.model.InitiateBatchTransferRequest;
|
|
|
+import com.wechat.pay.java.service.transferbatch.model.InitiateBatchTransferResponse;
|
|
|
+import com.wechat.pay.java.service.transferbatch.model.TransferDetailInput;
|
|
|
import io.renren.common.enums.WithdrawAuditStateEnum;
|
|
|
import io.renren.common.enums.WithdrawTypeEnum;
|
|
|
import io.renren.common.exception.RRException;
|
|
|
@@ -14,6 +18,7 @@ import io.renren.common.utils.LocalDateTimeUtils;
|
|
|
import io.renren.common.utils.PageUtils;
|
|
|
import io.renren.modules.qmgj.entity.MemberInfoEntity;
|
|
|
import io.renren.modules.qmgj.service.MemberInfoService;
|
|
|
+import io.renren.modules.qmgj.wxpayutil.NewWxPayUtil;
|
|
|
import io.renren.modules.qmjz.utils.BeanCopyUtils;
|
|
|
import io.renren.modules.qyh.entity.MemberWalletEntity;
|
|
|
import io.renren.modules.qyh.entity.WithdrawConfigEntity;
|
|
|
@@ -24,12 +29,16 @@ import io.renren.modules.qyh.model.vo.WithdrawInfoVO;
|
|
|
import io.renren.modules.qyh.service.MemberWalletService;
|
|
|
import io.renren.modules.qyh.service.WithdrawConfigService;
|
|
|
import io.renren.modules.qyh.service.WithdrawInfoService;
|
|
|
+import io.renren.modules.wechat.enums.BatchStatusEnum;
|
|
|
+import lombok.extern.slf4j.Slf4j;
|
|
|
+import org.apache.commons.lang.StringUtils;
|
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
|
import org.springframework.stereotype.Service;
|
|
|
import org.springframework.transaction.annotation.Transactional;
|
|
|
|
|
|
import java.math.BigDecimal;
|
|
|
import java.time.LocalDateTime;
|
|
|
+import java.util.ArrayList;
|
|
|
import java.util.List;
|
|
|
import java.util.Map;
|
|
|
|
|
|
@@ -39,6 +48,7 @@ import java.util.Map;
|
|
|
* @author qingyunhui
|
|
|
* @date 2026-04-24
|
|
|
*/
|
|
|
+@Slf4j
|
|
|
@Service("withdrawInfoService")
|
|
|
public class WithdrawInfoServiceImpl extends ServiceImpl<WithdrawInfoMapper, WithdrawInfoEntity>
|
|
|
implements WithdrawInfoService {
|
|
|
@@ -52,6 +62,9 @@ public class WithdrawInfoServiceImpl extends ServiceImpl<WithdrawInfoMapper, Wit
|
|
|
@Autowired
|
|
|
private MemberInfoService memberInfoService;
|
|
|
|
|
|
+ @Autowired
|
|
|
+ private NewWxPayUtil wxPayUtil;
|
|
|
+
|
|
|
@Override
|
|
|
public PageUtils queryPage(Map<String, Object> params) {
|
|
|
Integer page = MapUtil.getInt(params, Constant.PAGE);
|
|
|
@@ -127,18 +140,67 @@ public class WithdrawInfoServiceImpl extends ServiceImpl<WithdrawInfoMapper, Wit
|
|
|
entity.setAuditExplain(dto.getAuditExplain());
|
|
|
entity.setAuditPer(dto.getAuditPer());
|
|
|
entity.setAuditTime(LocalDateTime.now());
|
|
|
+ baseMapper.updateById(entity);
|
|
|
// 审核通过
|
|
|
if (auditState.equals(WithdrawAuditStateEnum.AUDIT_PASS.value())) {
|
|
|
- // TODO: 这里调用微信接口进行打款
|
|
|
+ // 这里调用微信接口进行打款
|
|
|
+ wxTransfer(entity);
|
|
|
} else if (auditState.equals(WithdrawAuditStateEnum.AUDIT_REFUSE.value())) {
|
|
|
// 拒绝后需要解冻并退回钱包余额
|
|
|
memberWalletService.unfreezeAndRefund(entity.getMemberId(), entity.getMoney());
|
|
|
} else {
|
|
|
throw new RRException("审核状态不正确");
|
|
|
}
|
|
|
- baseMapper.updateById(entity);
|
|
|
}
|
|
|
|
|
|
+ private void wxTransfer(WithdrawInfoEntity entity) {
|
|
|
+ // 1. 获取会员信息(需要 openid)
|
|
|
+ MemberInfoEntity memberInfo = memberInfoService.getById(entity.getMemberId());
|
|
|
+ if (memberInfo == null || StringUtils.isBlank(memberInfo.getOpenid())) {
|
|
|
+ throw new RRException("会员信息不存在或未绑定微信");
|
|
|
+ }
|
|
|
+ // 2. 构建转账请求
|
|
|
+ InitiateBatchTransferRequest request = new InitiateBatchTransferRequest();
|
|
|
+ // 商户系统内部的批次单号(使用提现记录的业务单号)
|
|
|
+ request.setOutBatchNo(entity.getBusinessCode());
|
|
|
+ String remark = "提现" + entity.getMoney() + "元";
|
|
|
+ // 批次名称
|
|
|
+ request.setBatchName(remark);
|
|
|
+ // 批次备注
|
|
|
+ request.setBatchRemark(remark);
|
|
|
+ // 转账总金额(单位:分)
|
|
|
+ BigDecimal moneyInFen = entity.getMoney().multiply(new BigDecimal("100"));
|
|
|
+ request.setTotalAmount(moneyInFen.longValue());
|
|
|
+ // 转账总笔数
|
|
|
+ request.setTotalNum(1);
|
|
|
+ // 转账明细列表
|
|
|
+ List<TransferDetailInput> detailList = new ArrayList<>();
|
|
|
+ TransferDetailInput detail = new TransferDetailInput();
|
|
|
+ // 商户系统内部的明细单号
|
|
|
+ detail.setOutDetailNo(entity.getBusinessCode() + "_01");
|
|
|
+ // 转账金额(单位:分)
|
|
|
+ detail.setTransferAmount(moneyInFen.longValue());
|
|
|
+ // 转账备注
|
|
|
+ detail.setTransferRemark(remark);
|
|
|
+ // 收款用户openid
|
|
|
+ detail.setOpenid(memberInfo.getOpenid());
|
|
|
+ detailList.add(detail);
|
|
|
+ request.setTransferDetailList(detailList);
|
|
|
+ log.info("发起微信转账,提现单号:{},金额:{}元,openid:{}",
|
|
|
+ entity.getBusinessCode(), entity.getMoney(), memberInfo.getOpenid());
|
|
|
+ // 3. 调用微信转账接口
|
|
|
+ InitiateBatchTransferResponse response = wxPayUtil.transferSingle(request);
|
|
|
+ log.info("微信转账响应:{}", JSONUtil.toJsonStr(response));
|
|
|
+ // 4. 处理转账结果
|
|
|
+ if (response != null) {
|
|
|
+ handleTransferStatus(entity, response.getBatchStatus(), response.getBatchId());
|
|
|
+ } else {
|
|
|
+ throw new RRException("微信转账失败");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
@Override
|
|
|
public Map<String, BigDecimal> getWithdrawStatistics(Map<String, Object> params) {
|
|
|
return baseMapper.getWithdrawStatistics(params);
|
|
|
@@ -161,4 +223,25 @@ public class WithdrawInfoServiceImpl extends ServiceImpl<WithdrawInfoMapper, Wit
|
|
|
withdrawInfoVO.setAvailableAmount(myWallet.getAvailableAmount());
|
|
|
return withdrawInfoVO;
|
|
|
}
|
|
|
+
|
|
|
+ @Transactional(rollbackFor = Exception.class)
|
|
|
+ @Override
|
|
|
+ public void handleTransferStatus(WithdrawInfoEntity entity, String batchStatus, String batchId) {
|
|
|
+ // FINISHED(已完成)表示成功
|
|
|
+ if (BatchStatusEnum.FINISHED.value().equals(batchStatus)) {
|
|
|
+ // 保存微信批次单号
|
|
|
+ entity.setThirdTransactionNo(batchId);
|
|
|
+ entity.setRemitTime(LocalDateTime.now());
|
|
|
+ entity.setAuditState(WithdrawAuditStateEnum.REMIT_SUCCESS.value());
|
|
|
+ //扣余额
|
|
|
+ memberWalletService.deductBalance(entity.getMemberId(), entity.getMoney());
|
|
|
+ } else if (BatchStatusEnum.CLOSED.value().equals(batchStatus)) {
|
|
|
+ // 转账失败,退回余额
|
|
|
+ memberWalletService.unfreezeAndRefund(entity.getMemberId(), entity.getMoney());
|
|
|
+ entity.setAuditState(WithdrawAuditStateEnum.AUDIT_REFUSE.value());
|
|
|
+ entity.setAuditExplain("打款失败:" + batchStatus);
|
|
|
+ entity.setThirdTransactionNo(batchId);
|
|
|
+ }
|
|
|
+ baseMapper.updateById(entity);
|
|
|
+ }
|
|
|
}
|