[fix]修改提现逻辑

This commit is contained in:
wangqx 2025-09-26 09:54:02 +08:00
parent 28ea7a5c3b
commit 94e891a510
6 changed files with 123 additions and 29 deletions

View File

@ -24,6 +24,7 @@ import com.wzj.soopin.transaction.convert.ChargeConvert;
import com.wzj.soopin.transaction.convert.WithdrawConvert;
import com.wzj.soopin.transaction.domain.bo.ChargeBO;
import com.wzj.soopin.transaction.domain.bo.WithdrawBO;
import com.wzj.soopin.transaction.domain.entity.InitiateBatchTransferResponseNew;
import com.wzj.soopin.transaction.domain.po.Withdraw;
import com.wzj.soopin.transaction.enums.WithdrawType;
import com.wzj.soopin.transaction.service.IAccountBillService;
@ -204,14 +205,8 @@ public class AppMemberController {
bo.setMemberId(memberId);
bo.setType(WithdrawType.WALLET.getCode());
Withdraw withdraw=withdrawConvert.toPo(bo);
withdrawService.withdraw(withdraw);
//检查提现金额是否小于1元 一元以下自动审批
if(withdraw.getMoney().compareTo(BigDecimal.ONE)<0){
//自动审批
bo.setId(withdraw.getId());
withdrawService.audit(bo);
}
return R.ok();
InitiateBatchTransferResponseNew responseNew= withdrawService.withdraw(withdraw);
return R.ok(responseNew);
}

View File

@ -1,5 +1,7 @@
package com.wzj.soopin.transaction.controller;
import com.wzj.soopin.member.domain.po.Member;
import com.wzj.soopin.member.service.IMemberService;
import com.wzj.soopin.transaction.domain.entity.*;
import com.wzj.soopin.transaction.service.impl.WxAuthService;
import com.wzj.soopin.transaction.service.impl.WxPayService;
@ -13,9 +15,11 @@ import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.domain.R;
import org.dromara.common.core.domain.model.LoginUser;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.log.annotation.Log;
import org.dromara.common.log.enums.BusinessType;
import org.dromara.common.satoken.utils.LoginHelper;
import org.mapstruct.Context;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
@ -40,6 +44,12 @@ public class WxPayController {
@Autowired
private WxAuthService wxAuthService;
@Autowired
private IMemberService memberService;
@Autowired
private WechatPayConfig wechatPayConfig;
/**
*商家转账 - 发起转账
* @return
@ -180,7 +190,44 @@ public class WxPayController {
}
}
/**
* 获取用户的openid
*
* @return 包含openid的响应对象
*/
@Operation(summary = "拉取用户授权")
@GetMapping("/pullConfirm")
@Parameters({
@Parameter(name = "code", description = "授权码", required = true, in = ParameterIn.QUERY)
})
public R<InitiateBatchTransferResponseNew> pullComfirm() {
try {
InitiateBatchTransferRequestNew request = new InitiateBatchTransferRequestNew();
//商户AppID
request.setAppid(wechatPayConfig.getAppId());
LoginUser user = LoginHelper.getLoginUser();
Member member = memberService.getById(user.getUserId());
//用户的openId
request.setOpenid(member.getOpenId());
//收款用户姓名
//转账场景ID
// /** 转账场景ID 说明:该批次转账使用的转账场景,如不填写则使用商家的默认场景,如无默认场景可为空,可前往“商家转账到零钱-前往功能”中申请。 如1001-现金营销 */
request.setTransferSceneId("1005");
//转账备注 单条转账备注微信用户会收到该备注UTF8编码最多允许32个字符
InitiateBatchTransferResponseNew response =null;
try{
response = wxPayService.pullConfirm(request);
}catch (ServiceException e){
e.printStackTrace();
}
return R.ok(response);
} catch (Exception e) {
log.error("获取openid时发生异常: {}", e.getMessage());
return R.fail("发起面确认收款授权时发生异常: " + e.getMessage());
}
}

View File

@ -58,7 +58,7 @@ public class InitiateBatchTransferRequestNew {
/** 转账场景报备信息 Y 说明:各转账场景下需报备的内容,可通过 产品文档 了解 */
@SerializedName("transfer_scene_report_infos")
private List<TransferSceneReportInfoNew> transferSceneReportInfos = new ArrayList<>();
private List<TransferSceneReportInfoNew> transferSceneReportInfos ;
public InitiateBatchTransferRequestNew() {
super();

View File

@ -2,6 +2,7 @@ package com.wzj.soopin.transaction.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.wzj.soopin.transaction.domain.bo.WithdrawBO;
import com.wzj.soopin.transaction.domain.entity.InitiateBatchTransferResponseNew;
import com.wzj.soopin.transaction.domain.po.Withdraw;
public interface IWithdrawService extends IService<Withdraw> {
@ -9,6 +10,6 @@ public interface IWithdrawService extends IService<Withdraw> {
boolean withdrawCallback(WithdrawBO withdraw);
boolean withdraw (Withdraw withdraw);
InitiateBatchTransferResponseNew withdraw (Withdraw withdraw);
}

View File

@ -1,5 +1,7 @@
package com.wzj.soopin.transaction.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.wzj.soopin.content.domain.po.Comment;
import com.wzj.soopin.member.domain.po.Member;
@ -7,6 +9,7 @@ import com.wzj.soopin.transaction.domain.bo.WithdrawBO;
import com.wzj.soopin.member.domain.po.MemberAccount;
import com.wzj.soopin.member.domain.po.AccountBill;
import com.wzj.soopin.transaction.domain.entity.InitiateBatchTransferRequestNew;
import com.wzj.soopin.transaction.domain.entity.InitiateBatchTransferResponseNew;
import com.wzj.soopin.transaction.domain.entity.TransferSceneReportInfoNew;
import com.wzj.soopin.transaction.domain.po.Withdraw;
import com.wzj.soopin.member.enums.AccountBillChangeTypeEnum;
@ -30,9 +33,11 @@ import org.dromara.common.mq.domain.MQMessage;
import org.dromara.common.mq.enums.MessageActionEnum;
import org.dromara.common.mq.utils.MqUtil;
import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.common.translation.annotation.Translation;
import org.dromara.system.domain.SysTenantAccount;
import org.dromara.system.service.ISysTenantAccountService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.math.BigDecimal;
import java.time.LocalDateTime;
@ -76,22 +81,7 @@ public class WithdrawServiceImpl extends ServiceImpl<WithdrawMapper, Withdraw> i
}
//发起提现
try{
wxPayService.initiateBatchTransferNew(buildWechatPayParam(withdraw));
}catch (ServiceException e){
log.error(e.getMessage());
throw new ServiceException(e.getMessage());
}
withdraw = Withdraw.builder().id(bo.getId())
.auditReason(bo.getAuditReason())
.auditTime(LocalDateTime.now())
.auditStatus(bo.getAuditStatus())
.auditBy(LoginHelper.getUserId())
.build();
this.updateById(withdraw);
//发送成功通知
MqUtil.sendIMMessage(buildMessage(withdraw, MessageActionEnum.ORDER_WITHDRAW_AUDIT));
return true;
}
@ -188,7 +178,9 @@ public class WithdrawServiceImpl extends ServiceImpl<WithdrawMapper, Withdraw> i
public boolean withdraw (Withdraw withdraw) {
@Override
@Transactional
public InitiateBatchTransferResponseNew withdraw (Withdraw withdraw) {
MemberAccount memberAccount = memberAccountService.getMemberAccount(withdraw.getMemberId());
if (memberAccount == null) {
throw new RuntimeException("用户不存在");
@ -198,6 +190,16 @@ public class WithdrawServiceImpl extends ServiceImpl<WithdrawMapper, Withdraw> i
if (balance==null||balance.compareTo(withdraw.getMoney()) < 0) {
throw new RuntimeException("用户余额不足");
}
//检查提现次数是否超过限制
long count = this.count(new LambdaQueryWrapper<Withdraw>()
.eq(Withdraw::getMemberId, withdraw.getMemberId())
.eq(Withdraw::getStatus, WithdrawStatus.SUCCESS.getCode())
.between(Withdraw::getCreateTime, LocalDateTime.now().minusDays(1), LocalDateTime.now())
);
if (count >= 3) {
throw new RuntimeException("提现次数超过限制");
}
//生成费用
BigDecimal fee = withdraw.getMoney().multiply(new BigDecimal("0.00"));
withdraw.setFee(fee);
@ -220,6 +222,23 @@ public class WithdrawServiceImpl extends ServiceImpl<WithdrawMapper, Withdraw> i
.source(AccountBillSourceEnum.WITHDRAW.getCode())
.build();
accountBillService.save(memberAccountChangeRecord);
return true;
InitiateBatchTransferResponseNew response = null;
try{
response = wxPayService.initiateBatchTransferNew(buildWechatPayParam(withdraw));
}catch (ServiceException e){
log.error(e.getMessage());
throw new ServiceException(e.getMessage());
}
withdraw = Withdraw.builder().id(withdraw.getId())
.auditReason(withdraw.getAuditReason())
.auditTime(LocalDateTime.now())
.auditStatus(withdraw.getAuditStatus())
.build();
this.updateById(withdraw);
//发送成功通知
MqUtil.sendIMMessage(buildMessage(withdraw, MessageActionEnum.ORDER_WITHDRAW_AUDIT));
return response;
}
}

View File

@ -3,6 +3,7 @@ package com.wzj.soopin.transaction.service.impl;
import cn.hutool.core.io.IoUtil;
import com.alibaba.fastjson.JSON;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.wechat.pay.java.core.Config;
import com.wechat.pay.java.core.RSAAutoCertificateConfig;
import com.wechat.pay.java.core.cipher.PrivacyDecryptor;
@ -58,7 +59,38 @@ public class WxPayService {
request.setUserName(encryptName);
}
String requestPath = "https://api.mch.weixin.qq.com/v3/fund-app/mch-transfer/transfer-bills/transfer";
String requestPath = "https://api.mch.weixin.qq.com/v3/fund-app/mch-transfer/transfer-bills";
HttpHeaders headers = new HttpHeaders();
headers.addHeader("Accept", MediaType.APPLICATION_JSON.getValue());
headers.addHeader("Content-Type", MediaType.APPLICATION_JSON.getValue());
headers.addHeader("Wechatpay-Serial", config.createEncryptor().getWechatpaySerial());
HttpRequest httpRequest =
new HttpRequest.Builder()
.httpMethod(HttpMethod.POST)
.url(requestPath)
.headers(headers)
.body(createRequestBody(request))
.build();
HttpClient httpClient = new DefaultHttpClientBuilder().config(config).build();
HttpResponse<InitiateBatchTransferResponseNew> httpResponse = httpClient.execute(httpRequest, InitiateBatchTransferResponseNew.class);
logger.info("WxPayService.initiateBatchTransferNew response:{}", httpResponse.getServiceResponse());
return httpResponse.getServiceResponse();
}
/**
* 商家转账 - 发起转账 - 2025年1月15号之后商户转账零线必须用户确认收款
*
* @param request 请求体
* @return
*/
public InitiateBatchTransferResponseNew pullConfirm(InitiateBatchTransferRequestNew request) {
logger.info("WxPayService.initiateBatchTransferNew request:{}", request.toString());
if(request.getUserName() != null && !request.getUserName().isEmpty()){
String encryptName = config.createEncryptor().encrypt(request.getUserName());
request.setUserName(encryptName);
}
String requestPath = "https://api.mch.weixin.qq.com/v3/fund-app/mch-transfer/user-confirm-authorization";
HttpHeaders headers = new HttpHeaders();
headers.addHeader("Accept", MediaType.APPLICATION_JSON.getValue());
headers.addHeader("Content-Type", MediaType.APPLICATION_JSON.getValue());
@ -109,7 +141,7 @@ public class WxPayService {
* @return
*/
private static RequestBody createRequestBody(Object request) {
return new JsonRequestBody.Builder().body(new Gson().toJson(request)).build();
return new JsonRequestBody.Builder().body(new GsonBuilder().create().toJson(request)).build();
}
/**