feat: 支付宝提现

master
yang 2025-02-06 17:27:00 +08:00
parent 61ac03de38
commit 2672fc9e33
8 changed files with 147 additions and 20 deletions

View File

@ -6,6 +6,7 @@ import cn.hutool.json.JSONUtil;
import com.alipay.easysdk.factory.Factory; import com.alipay.easysdk.factory.Factory;
import com.mcwl.common.annotation.Anonymous; import com.mcwl.common.annotation.Anonymous;
import com.mcwl.common.core.controller.BaseController; import com.mcwl.common.core.controller.BaseController;
import com.mcwl.common.core.domain.AjaxResult;
import com.mcwl.common.core.redis.RedisCache; import com.mcwl.common.core.redis.RedisCache;
import com.mcwl.common.utils.SecurityUtils; import com.mcwl.common.utils.SecurityUtils;
import com.mcwl.common.utils.ShareCodeUtils; import com.mcwl.common.utils.ShareCodeUtils;
@ -13,6 +14,7 @@ import com.mcwl.pay.domain.OrderTrade;
import com.mcwl.pay.domain.OrderTradeDto; import com.mcwl.pay.domain.OrderTradeDto;
import com.mcwl.pay.service.AliPayService; import com.mcwl.pay.service.AliPayService;
import com.mcwl.pay.service.OrderTradeService; import com.mcwl.pay.service.OrderTradeService;
import org.checkerframework.checker.units.qual.min;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller; import org.springframework.stereotype.Controller;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
@ -20,6 +22,10 @@ import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.net.URLEncoder; import java.net.URLEncoder;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
@ -51,6 +57,7 @@ public class AliPayController extends BaseController {
/** /**
* *
*
* @param response * @param response
* @throws Exception * @throws Exception
*/ */
@ -71,6 +78,7 @@ public class AliPayController extends BaseController {
/** /**
* *
*
* @param authCode * @param authCode
*/ */
@GetMapping("/callback") @GetMapping("/callback")
@ -113,13 +121,17 @@ public class AliPayController extends BaseController {
* *
*/ */
@Anonymous @Anonymous
@PostMapping("/withdraw") @PostMapping("/fetch")
public void withdraw(@RequestBody OrderTradeDto orderTradeDto, HttpServletResponse response) throws Exception { @ResponseBody
public AjaxResult fetch(@Valid
@NotNull(message = "提现金额不能为空")
Double amount) throws Exception {
if (amount < 0.01) {
return AjaxResult.error("提现金额最小为0.01");
}
String outBizNo = UUID.fastUUID().toString(true); String outBizNo = UUID.fastUUID().toString(true);
String payerUserId = "2088102167258880";
String payeeUserId = "2088102167258880"; return aliPayService.fetch(outBizNo, amount.toString());
String amount = "100";
aliPayService.transfer(outBizNo, payerUserId, payeeUserId, amount);
} }

View File

@ -11,5 +11,5 @@ public interface AliPayService {
String pointsPay(Double paymentAmount) throws Exception; String pointsPay(Double paymentAmount) throws Exception;
String transfer(String outBizNo, String payerUserId, String payeeUserId, String amount) throws AlipayApiException; AjaxResult fetch(String outBizNo, String amount) throws AlipayApiException;
} }

View File

@ -22,6 +22,7 @@ import com.alipay.easysdk.factory.Factory;
import com.alipay.easysdk.kernel.Config; import com.alipay.easysdk.kernel.Config;
import com.alipay.easysdk.payment.facetoface.models.AlipayTradePrecreateResponse; import com.alipay.easysdk.payment.facetoface.models.AlipayTradePrecreateResponse;
import com.mcwl.common.core.domain.AjaxResult; import com.mcwl.common.core.domain.AjaxResult;
import com.mcwl.common.core.domain.entity.SysUser;
import com.mcwl.common.core.redis.RedisCache; import com.mcwl.common.core.redis.RedisCache;
import com.mcwl.common.exception.BusinessException; import com.mcwl.common.exception.BusinessException;
import com.mcwl.common.exception.ServiceException; import com.mcwl.common.exception.ServiceException;
@ -34,11 +35,16 @@ import com.mcwl.pay.domain.OrderTrade;
import com.mcwl.pay.domain.OrderTradeDto; import com.mcwl.pay.domain.OrderTradeDto;
import com.mcwl.pay.service.AliPayService; import com.mcwl.pay.service.AliPayService;
import com.mcwl.system.domain.SysUserPayAccount; import com.mcwl.system.domain.SysUserPayAccount;
import com.mcwl.system.domain.SysUserPayAccountLog;
import com.mcwl.system.service.ISysUserPayAccountLogService;
import com.mcwl.system.service.ISysUserPayAccountService; import com.mcwl.system.service.ISysUserPayAccountService;
import com.mcwl.system.service.ISysUserService;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import java.math.BigDecimal;
import java.util.Objects; import java.util.Objects;
import java.util.Optional; import java.util.Optional;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
@ -64,6 +70,12 @@ public class AliPayServiceImpl implements AliPayService {
@Autowired @Autowired
private ISysUserPayAccountService sysUserPayAccountService; private ISysUserPayAccountService sysUserPayAccountService;
@Autowired
private ISysUserService sysUserService;
@Autowired
private ISysUserPayAccountLogService sysUserPayAccountLogService;
public AliPayServiceImpl(Config config) { public AliPayServiceImpl(Config config) {
Factory.setOptions(config); Factory.setOptions(config);
@ -194,13 +206,17 @@ public class AliPayServiceImpl implements AliPayService {
* *
* *
* @param outBizNo * @param outBizNo
* @param payerUserId ID
* @param payeeUserId ID
* @param amount * @param amount
* @return * @return
*/ */
@Override @Override
public String transfer(String outBizNo, String payerUserId, String payeeUserId, String amount) throws AlipayApiException { @Transactional(rollbackFor = Exception.class)
public AjaxResult fetch(String outBizNo, String amount) throws AlipayApiException {
Long userId = SecurityUtils.getUserId();
SysUser sysUser = sysUserService.selectUserById(userId);
if (sysUser.getWallet() < Double.parseDouble(amount)) {
return AjaxResult.error("钱包余额不足");
}
// 初始化SDK // 初始化SDK
AlipayClient alipayClient = new DefaultAlipayClient(getAlipayConfig()); AlipayClient alipayClient = new DefaultAlipayClient(getAlipayConfig());
@ -222,22 +238,29 @@ public class AliPayServiceImpl implements AliPayService {
model.setProductCode("TRANS_ACCOUNT_NO_PWD"); model.setProductCode("TRANS_ACCOUNT_NO_PWD");
// 设置转账业务的标题 // 设置转账业务的标题
model.setOrderTitle("测试"); model.setOrderTitle("提现");
// 设置收款方信息 // 设置收款方信息
SysUserPayAccount sysUserPayAccount = sysUserPayAccountService
.lambdaQuery()
.eq(SysUserPayAccount::getUserId, userId)
.eq(SysUserPayAccount::getType, 0)
.one();
if ( Objects.isNull(sysUserPayAccount)) {
return AjaxResult.error("请先绑定支付宝账号");
}
Participant payeeInfo = new Participant(); Participant payeeInfo = new Participant();
payeeInfo.setCertType("IDENTITY_CARD"); payeeInfo.setIdentity(sysUserPayAccount.getOpenId());
payeeInfo.setCertNo("1201152******72917");
payeeInfo.setIdentity("2088123412341234");
payeeInfo.setName("黄龙国际有限公司");
payeeInfo.setIdentityType("ALIPAY_USER_ID"); payeeInfo.setIdentityType("ALIPAY_USER_ID");
model.setPayeeInfo(payeeInfo); model.setPayeeInfo(payeeInfo);
// 设置业务备注 // 设置业务备注
model.setRemark("201905代发"); // model.setRemark("201905代发");
// 设置转账业务请求的扩展参数 // 设置转账业务请求的扩展参数
model.setBusinessParams("{\"payer_show_name_use_alias\":\"true\"}"); // model.setBusinessParams("{\"payer_show_name_use_alias\":\"true\"}");
request.setBizModel(model); request.setBizModel(model);
AlipayFundTransUniTransferResponse response = alipayClient.certificateExecute(request); AlipayFundTransUniTransferResponse response = alipayClient.certificateExecute(request);
@ -245,13 +268,26 @@ public class AliPayServiceImpl implements AliPayService {
if (response.isSuccess()) { if (response.isSuccess()) {
System.out.println("调用成功"); System.out.println("调用成功");
BigDecimal wallet = new BigDecimal(sysUser.getWallet().toString());
BigDecimal amountBigDecimal = new BigDecimal(amount);
sysUser.setWallet(wallet.subtract(amountBigDecimal).doubleValue());
sysUserService.updateUser(sysUser);
// 添加记录
SysUserPayAccountLog sysUserPayAccountLog = new SysUserPayAccountLog();
sysUserPayAccountLog.setUserId(userId);
sysUserPayAccountLog.setAmount(Double.valueOf(amount));
sysUserPayAccountLog.setAccount("支付宝");
sysUserPayAccountLogService.save(sysUserPayAccountLog);
// response.getBody()
return AjaxResult.success("转账成功");
} else { } else {
System.out.println("调用失败"); System.out.println("调用失败");
// sdk版本是"4.38.0.ALL"及以上,可以参考下面的示例获取诊断链接 // sdk版本是"4.38.0.ALL"及以上,可以参考下面的示例获取诊断链接
String diagnosisUrl = DiagnosisUtils.getDiagnosisUrl(response); String diagnosisUrl = DiagnosisUtils.getDiagnosisUrl(response);
System.out.println(diagnosisUrl); System.out.println(diagnosisUrl);
return AjaxResult.error("转账失败:" + response.getMsg());
} }
return response.getBody();
} }
private AlipayConfig getAlipayConfig() { private AlipayConfig getAlipayConfig() {
@ -286,7 +322,6 @@ public class AliPayServiceImpl implements AliPayService {
// 判断是否已经绑定过 // 判断是否已经绑定过
SysUserPayAccount sysUserPayAccount = sysUserPayAccountService.lambdaQuery() SysUserPayAccount sysUserPayAccount = sysUserPayAccountService.lambdaQuery()
.eq(SysUserPayAccount::getUserId, userId) .eq(SysUserPayAccount::getUserId, userId)
.eq(SysUserPayAccount::getOpenId, openId)
.eq(SysUserPayAccount::getType, 0) .eq(SysUserPayAccount::getType, 0)
.one(); .one();
if (Objects.nonNull(sysUserPayAccount)) { if (Objects.nonNull(sysUserPayAccount)) {

View File

@ -7,7 +7,7 @@ import lombok.Data;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
/** /**
* *
*/ */
@Data @Data
@EqualsAndHashCode(callSuper = true) @EqualsAndHashCode(callSuper = true)

View File

@ -0,0 +1,32 @@
package com.mcwl.system.domain;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.mcwl.common.core.domain.BaseEntity;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
*
*/
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("sys_user_pay_account_log")
public class SysUserPayAccountLog extends BaseEntity {
@TableId
private Long id;
/**
*
*/
private Long userId;
/**
*
*/
private Double amount;
/**
*
*/
private String account;
}

View File

@ -0,0 +1,14 @@
package com.mcwl.system.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.mcwl.system.domain.SysUserPayAccount;
import com.mcwl.system.domain.SysUserPayAccountLog;
import org.apache.ibatis.annotations.Mapper;
/**
*
*/
@Mapper
public interface SysUserPayAccountLogMapper extends BaseMapper<SysUserPayAccountLog> {
}

View File

@ -0,0 +1,15 @@
package com.mcwl.system.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.mcwl.system.domain.SysUserPayAccount;
import com.mcwl.system.domain.SysUserPayAccountLog;
/**
*
*
* @author mcwl
*/
public interface ISysUserPayAccountLogService extends IService<SysUserPayAccountLog> {
}

View File

@ -0,0 +1,19 @@
package com.mcwl.system.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.mcwl.system.domain.SysUserPayAccount;
import com.mcwl.system.domain.SysUserPayAccountLog;
import com.mcwl.system.mapper.SysUserPayAccountLogMapper;
import com.mcwl.system.mapper.SysUserPayAccountMapper;
import com.mcwl.system.service.ISysUserPayAccountLogService;
import com.mcwl.system.service.ISysUserPayAccountService;
import org.springframework.stereotype.Service;
/**
*
*/
@Service
public class SysUserPayAccountLogServiceImpl extends ServiceImpl<SysUserPayAccountLogMapper, SysUserPayAccountLog> implements ISysUserPayAccountLogService {
}