commit
602bd5f93c
@ -19,6 +19,7 @@ public enum BrokerageWithdrawTypeEnum implements IntArrayValuable {
|
||||
BANK(2, "银行卡"),
|
||||
WECHAT(3, "微信"),
|
||||
ALIPAY(4, "支付宝"),
|
||||
ALIPAY_SMALL(5, "微信零钱"),
|
||||
;
|
||||
|
||||
public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(BrokerageWithdrawTypeEnum::getType).toArray();
|
||||
|
@ -44,7 +44,7 @@ public class BrokerageRecordController {
|
||||
@Operation(summary = "获得佣金记录")
|
||||
@Parameter(name = "id", description = "编号", required = true, example = "1024")
|
||||
@PreAuthorize("@ss.hasPermission('trade:brokerage-record:query')")
|
||||
public CommonResult<BrokerageRecordRespVO> getBrokerageRecord(@RequestParam("id") Integer id) {
|
||||
public CommonResult<BrokerageRecordRespVO> getBrokerageRecord(@RequestParam("id") Long id) {
|
||||
BrokerageRecordDO brokerageRecord = brokerageRecordService.getBrokerageRecord(id);
|
||||
return success(BrokerageRecordConvert.INSTANCE.convert(brokerageRecord));
|
||||
}
|
||||
|
@ -4,6 +4,7 @@ import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.module.member.api.user.MemberUserApi;
|
||||
import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO;
|
||||
import cn.iocoder.yudao.module.pay.api.notify.dto.PayTransferNotifyReqDTO;
|
||||
import cn.iocoder.yudao.module.trade.controller.admin.brokerage.vo.withdraw.BrokerageWithdrawRejectReqVO;
|
||||
import cn.iocoder.yudao.module.trade.controller.admin.brokerage.vo.withdraw.BrokerageWithdrawPageReqVO;
|
||||
import cn.iocoder.yudao.module.trade.controller.admin.brokerage.vo.withdraw.BrokerageWithdrawRespVO;
|
||||
@ -14,6 +15,8 @@ import cn.iocoder.yudao.module.trade.service.brokerage.BrokerageWithdrawService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.annotation.security.PermitAll;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
@ -24,11 +27,13 @@ import java.util.Map;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
||||
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
|
||||
import static cn.iocoder.yudao.framework.common.util.servlet.ServletUtils.getClientIP;
|
||||
|
||||
@Tag(name = "管理后台 - 佣金提现")
|
||||
@RestController
|
||||
@RequestMapping("/trade/brokerage-withdraw")
|
||||
@Validated
|
||||
@Slf4j
|
||||
public class BrokerageWithdrawController {
|
||||
|
||||
@Resource
|
||||
@ -40,8 +45,8 @@ public class BrokerageWithdrawController {
|
||||
@PutMapping("/approve")
|
||||
@Operation(summary = "通过申请")
|
||||
@PreAuthorize("@ss.hasPermission('trade:brokerage-withdraw:audit')")
|
||||
public CommonResult<Boolean> approveBrokerageWithdraw(@RequestParam("id") Integer id) {
|
||||
brokerageWithdrawService.auditBrokerageWithdraw(id, BrokerageWithdrawStatusEnum.AUDIT_SUCCESS, "");
|
||||
public CommonResult<Boolean> approveBrokerageWithdraw(@RequestParam("id") Long id) {
|
||||
brokerageWithdrawService.auditBrokerageWithdraw(id, BrokerageWithdrawStatusEnum.AUDIT_SUCCESS, "", getClientIP());
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@ -49,7 +54,7 @@ public class BrokerageWithdrawController {
|
||||
@Operation(summary = "驳回申请")
|
||||
@PreAuthorize("@ss.hasPermission('trade:brokerage-withdraw:audit')")
|
||||
public CommonResult<Boolean> rejectBrokerageWithdraw(@Valid @RequestBody BrokerageWithdrawRejectReqVO reqVO) {
|
||||
brokerageWithdrawService.auditBrokerageWithdraw(reqVO.getId(), BrokerageWithdrawStatusEnum.AUDIT_FAIL, reqVO.getAuditReason());
|
||||
brokerageWithdrawService.auditBrokerageWithdraw(reqVO.getId(), BrokerageWithdrawStatusEnum.AUDIT_FAIL, reqVO.getAuditReason(), getClientIP());
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@ -57,7 +62,7 @@ public class BrokerageWithdrawController {
|
||||
@Operation(summary = "获得佣金提现")
|
||||
@Parameter(name = "id", description = "编号", required = true, example = "1024")
|
||||
@PreAuthorize("@ss.hasPermission('trade:brokerage-withdraw:query')")
|
||||
public CommonResult<BrokerageWithdrawRespVO> getBrokerageWithdraw(@RequestParam("id") Integer id) {
|
||||
public CommonResult<BrokerageWithdrawRespVO> getBrokerageWithdraw(@RequestParam("id") Long id) {
|
||||
BrokerageWithdrawDO brokerageWithdraw = brokerageWithdrawService.getBrokerageWithdraw(id);
|
||||
return success(BrokerageWithdrawConvert.INSTANCE.convert(brokerageWithdraw));
|
||||
}
|
||||
@ -75,4 +80,15 @@ public class BrokerageWithdrawController {
|
||||
return success(BrokerageWithdrawConvert.INSTANCE.convertPage(pageResult, userMap));
|
||||
}
|
||||
|
||||
@PostMapping("/update-transfer")
|
||||
@Operation(summary = "更新转账订单为转账成功") // 由 pay-module 支付服务,进行回调,可见 PayNotifyJob
|
||||
@PermitAll // 无需登录,安全由 PayDemoOrderService 内部校验实现
|
||||
public CommonResult<Boolean> updateAfterRefund(@RequestBody PayTransferNotifyReqDTO notifyReqDTO) {
|
||||
// 目前业务逻辑,不需要做任何事情
|
||||
// 当然,退款会有小概率会失败的情况,可以监控失败状态,进行告警
|
||||
log.info("[updateAfterRefund][notifyReqDTO({})]", notifyReqDTO);
|
||||
brokerageWithdrawService.updateTransfer(Long.parseLong(notifyReqDTO.getMerchantTransferId()), notifyReqDTO.getPayTransferId());
|
||||
return success(true);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -14,7 +14,7 @@ import java.time.LocalDateTime;
|
||||
public class BrokerageRecordRespVO extends BrokerageRecordBaseVO {
|
||||
|
||||
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "28896")
|
||||
private Integer id;
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private LocalDateTime createTime;
|
||||
|
@ -14,7 +14,7 @@ public class BrokerageWithdrawRejectReqVO {
|
||||
|
||||
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "7161")
|
||||
@NotNull(message = "编号不能为空")
|
||||
private Integer id;
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "审核驳回原因", example = "不对")
|
||||
@NotEmpty(message = "审核驳回原因不能为空")
|
||||
|
@ -14,7 +14,7 @@ import java.time.LocalDateTime;
|
||||
public class BrokerageWithdrawRespVO extends BrokerageWithdrawBaseVO {
|
||||
|
||||
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "7161")
|
||||
private Integer id;
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private LocalDateTime createTime;
|
||||
|
@ -35,7 +35,7 @@ public interface BrokerageWithdrawMapper extends BaseMapperX<BrokerageWithdrawDO
|
||||
.orderByAsc(BrokerageWithdrawDO::getStatus).orderByDesc(BrokerageWithdrawDO::getId));
|
||||
}
|
||||
|
||||
default int updateByIdAndStatus(Integer id, Integer status, BrokerageWithdrawDO updateObj) {
|
||||
default int updateByIdAndStatus(Long id, Integer status, BrokerageWithdrawDO updateObj) {
|
||||
return update(updateObj, new LambdaUpdateWrapper<BrokerageWithdrawDO>()
|
||||
.eq(BrokerageWithdrawDO::getId, id)
|
||||
.eq(BrokerageWithdrawDO::getStatus, status));
|
||||
|
@ -21,7 +21,7 @@ public class TradeOrderAutoCommentJob implements JobHandler {
|
||||
@Override
|
||||
@TenantJob
|
||||
public String execute(String param) {
|
||||
int count = tradeOrderUpdateService.createOrderItemCommentBySystem();
|
||||
int count = tradeOrderUpdateService.createOrderItemCommentBySystem();
|
||||
return String.format("评论订单 %s 个", count);
|
||||
}
|
||||
|
||||
|
@ -32,7 +32,7 @@ public interface BrokerageRecordService {
|
||||
* @param id 编号
|
||||
* @return 佣金记录
|
||||
*/
|
||||
BrokerageRecordDO getBrokerageRecord(Integer id);
|
||||
BrokerageRecordDO getBrokerageRecord(Long id);
|
||||
|
||||
/**
|
||||
* 获得佣金记录分页
|
||||
|
@ -64,7 +64,7 @@ public class BrokerageRecordServiceImpl implements BrokerageRecordService {
|
||||
private ProductSkuApi productSkuApi;
|
||||
|
||||
@Override
|
||||
public BrokerageRecordDO getBrokerageRecord(Integer id) {
|
||||
public BrokerageRecordDO getBrokerageRecord(Long id) {
|
||||
return brokerageRecordMapper.selectById(id);
|
||||
}
|
||||
|
||||
|
@ -28,7 +28,7 @@ public interface BrokerageWithdrawService {
|
||||
* @param status 审核状态
|
||||
* @param auditReason 驳回原因
|
||||
*/
|
||||
void auditBrokerageWithdraw(Integer id, BrokerageWithdrawStatusEnum status, String auditReason);
|
||||
void auditBrokerageWithdraw(Long id, BrokerageWithdrawStatusEnum status, String auditReason, String userIp);
|
||||
|
||||
/**
|
||||
* 获得佣金提现
|
||||
@ -36,7 +36,7 @@ public interface BrokerageWithdrawService {
|
||||
* @param id 编号
|
||||
* @return 佣金提现
|
||||
*/
|
||||
BrokerageWithdrawDO getBrokerageWithdraw(Integer id);
|
||||
BrokerageWithdrawDO getBrokerageWithdraw(Long id);
|
||||
|
||||
/**
|
||||
* 获得佣金提现分页
|
||||
@ -77,4 +77,10 @@ public interface BrokerageWithdrawService {
|
||||
return convertMap(getWithdrawSummaryListByUserId(userIds, status), BrokerageWithdrawSummaryRespBO::getUserId);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param merchantTransferId 提现编号
|
||||
* @param payTransferId 转账订单编号
|
||||
*/
|
||||
void updateTransfer(Long merchantTransferId, Long payTransferId);
|
||||
}
|
||||
|
@ -4,20 +4,35 @@ import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.date.LocalDateTimeUtil;
|
||||
import cn.hutool.core.map.MapUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.common.util.number.MoneyUtils;
|
||||
import cn.iocoder.yudao.module.pay.api.transfer.PayTransferApi;
|
||||
import cn.iocoder.yudao.module.pay.api.transfer.dto.PayTransferCreateReqDTO;
|
||||
import cn.iocoder.yudao.module.pay.api.transfer.dto.PayTransferRespDTO;
|
||||
import cn.iocoder.yudao.module.pay.api.wallet.PayWalletApi;
|
||||
import cn.iocoder.yudao.module.pay.api.wallet.dto.PayWalletCreateReqDto;
|
||||
import cn.iocoder.yudao.module.pay.api.wallet.dto.PayWalletRespDTO;
|
||||
import cn.iocoder.yudao.module.pay.enums.transfer.PayTransferStatusEnum;
|
||||
import cn.iocoder.yudao.module.pay.enums.transfer.PayTransferTypeEnum;
|
||||
import cn.iocoder.yudao.module.pay.enums.wallet.PayWalletBizTypeEnum;
|
||||
import cn.iocoder.yudao.module.system.api.notify.NotifyMessageSendApi;
|
||||
import cn.iocoder.yudao.module.system.api.notify.dto.NotifySendSingleToUserReqDTO;
|
||||
import cn.iocoder.yudao.module.system.api.social.SocialUserApi;
|
||||
import cn.iocoder.yudao.module.system.api.social.dto.SocialUserRespDTO;
|
||||
import cn.iocoder.yudao.module.system.enums.social.SocialTypeEnum;
|
||||
import cn.iocoder.yudao.module.trade.controller.admin.brokerage.vo.withdraw.BrokerageWithdrawPageReqVO;
|
||||
import cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.withdraw.AppBrokerageWithdrawCreateReqVO;
|
||||
import cn.iocoder.yudao.module.trade.convert.brokerage.BrokerageWithdrawConvert;
|
||||
import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.BrokerageWithdrawDO;
|
||||
import cn.iocoder.yudao.module.trade.dal.dataobject.config.TradeConfigDO;
|
||||
import cn.iocoder.yudao.module.trade.dal.mysql.brokerage.BrokerageWithdrawMapper;
|
||||
import cn.iocoder.yudao.module.trade.dal.redis.no.TradeNoRedisDAO;
|
||||
import cn.iocoder.yudao.module.trade.enums.MessageTemplateConstants;
|
||||
import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageRecordBizTypeEnum;
|
||||
import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageWithdrawStatusEnum;
|
||||
import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageWithdrawTypeEnum;
|
||||
import cn.iocoder.yudao.module.trade.framework.order.config.TradeOrderProperties;
|
||||
import cn.iocoder.yudao.module.trade.service.brokerage.bo.BrokerageWithdrawSummaryRespBO;
|
||||
import cn.iocoder.yudao.module.trade.service.config.TradeConfigService;
|
||||
import org.springframework.stereotype.Service;
|
||||
@ -27,10 +42,7 @@ import org.springframework.validation.annotation.Validated;
|
||||
import jakarta.annotation.Resource;
|
||||
import jakarta.validation.Validator;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.*;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||
import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.*;
|
||||
@ -46,6 +58,8 @@ public class BrokerageWithdrawServiceImpl implements BrokerageWithdrawService {
|
||||
|
||||
@Resource
|
||||
private BrokerageWithdrawMapper brokerageWithdrawMapper;
|
||||
@Resource
|
||||
private TradeNoRedisDAO tradeNoRedisDAO;
|
||||
|
||||
@Resource
|
||||
private BrokerageRecordService brokerageRecordService;
|
||||
@ -54,15 +68,25 @@ public class BrokerageWithdrawServiceImpl implements BrokerageWithdrawService {
|
||||
|
||||
@Resource
|
||||
private NotifyMessageSendApi notifyMessageSendApi;
|
||||
@Resource
|
||||
private PayTransferApi payTransferApi;
|
||||
@Resource
|
||||
private SocialUserApi socialUserApi;
|
||||
@Resource
|
||||
private PayWalletApi payWalletApi;
|
||||
|
||||
@Resource
|
||||
private Validator validator;
|
||||
|
||||
@Resource
|
||||
private TradeOrderProperties tradeOrderProperties;
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void auditBrokerageWithdraw(Integer id, BrokerageWithdrawStatusEnum status, String auditReason) {
|
||||
public void auditBrokerageWithdraw(Long id, BrokerageWithdrawStatusEnum status, String auditReason, String userIp) {
|
||||
// 1.1 校验存在
|
||||
BrokerageWithdrawDO withdraw = validateBrokerageWithdrawExists(id);
|
||||
|
||||
// 1.2 校验状态为审核中
|
||||
if (ObjectUtil.notEqual(BrokerageWithdrawStatusEnum.AUDITING.getStatus(), withdraw.getStatus())) {
|
||||
throw exception(BROKERAGE_WITHDRAW_STATUS_NOT_AUDITING);
|
||||
@ -80,9 +104,25 @@ public class BrokerageWithdrawServiceImpl implements BrokerageWithdrawService {
|
||||
templateCode = MessageTemplateConstants.SMS_BROKERAGE_WITHDRAW_AUDIT_APPROVE;
|
||||
// 3.1 通过时佣金转余额
|
||||
if (BrokerageWithdrawTypeEnum.WALLET.getType().equals(withdraw.getType())) {
|
||||
// todo 疯狂:
|
||||
PayWalletRespDTO wallet = payWalletApi.getWalletByUserId(withdraw.getUserId());
|
||||
payWalletApi.addWallet(new PayWalletCreateReqDto()
|
||||
.setWalletId(wallet.getId())
|
||||
.setBizType(PayWalletBizTypeEnum.WITHDRAW)
|
||||
.setBizId(withdraw.getId().toString())
|
||||
.setPrice(withdraw.getPrice())
|
||||
.setTitle("分佣提现"));
|
||||
rows = brokerageWithdrawMapper.updateByIdAndStatus(id, BrokerageWithdrawStatusEnum.AUDIT_SUCCESS.getStatus(),
|
||||
new BrokerageWithdrawDO().setStatus(BrokerageWithdrawStatusEnum.WITHDRAW_SUCCESS.getStatus()).setAuditReason(auditReason).setAuditTime(LocalDateTime.now()));
|
||||
if (rows == 0) {
|
||||
throw exception(BROKERAGE_WITHDRAW_STATUS_NOT_AUDITING);
|
||||
}
|
||||
}else if (BrokerageWithdrawTypeEnum.ALIPAY_SMALL.getType().equals(withdraw.getType())){
|
||||
//获取openid
|
||||
SocialUserRespDTO socialUser = socialUserApi.getSocialUserByUserId(UserTypeEnum.MEMBER.getValue(), withdraw.getUserId(), SocialTypeEnum.WECHAT_MINI_APP.getType());
|
||||
// 微信提现
|
||||
PayTransferCreateReqDTO payTransferCreateReqDTO = getPayTransferCreateReqDTO(userIp, withdraw, socialUser);
|
||||
payTransferApi.createTransfer(payTransferCreateReqDTO);
|
||||
}
|
||||
// TODO 疯狂:调用转账接口
|
||||
} else if (BrokerageWithdrawStatusEnum.AUDIT_FAIL.equals(status)) {
|
||||
templateCode = MessageTemplateConstants.SMS_BROKERAGE_WITHDRAW_AUDIT_REJECT;
|
||||
// 3.2 驳回时需要退还用户佣金
|
||||
@ -93,16 +133,29 @@ public class BrokerageWithdrawServiceImpl implements BrokerageWithdrawService {
|
||||
}
|
||||
|
||||
// 4. 通知用户
|
||||
Map<String, Object> templateParams = MapUtil.<String, Object>builder()
|
||||
.put("createTime", LocalDateTimeUtil.formatNormal(withdraw.getCreateTime()))
|
||||
.put("price", MoneyUtils.fenToYuanStr(withdraw.getPrice()))
|
||||
.put("reason", auditReason)
|
||||
.build();
|
||||
notifyMessageSendApi.sendSingleMessageToMember(new NotifySendSingleToUserReqDTO()
|
||||
.setUserId(withdraw.getUserId()).setTemplateCode(templateCode).setTemplateParams(templateParams));
|
||||
// Map<String, Object> templateParams = MapUtil.<String, Object>builder()
|
||||
// .put("createTime", LocalDateTimeUtil.formatNormal(withdraw.getCreateTime()))
|
||||
// .put("price", MoneyUtils.fenToYuanStr(withdraw.getPrice()))
|
||||
// .put("reason", auditReason)
|
||||
// .build();
|
||||
// notifyMessageSendApi.sendSingleMessageToMember(new NotifySendSingleToUserReqDTO()
|
||||
// .setUserId(withdraw.getUserId()).setTemplateCode(templateCode).setTemplateParams(templateParams));
|
||||
}
|
||||
|
||||
private BrokerageWithdrawDO validateBrokerageWithdrawExists(Integer id) {
|
||||
private PayTransferCreateReqDTO getPayTransferCreateReqDTO(String userIp, BrokerageWithdrawDO withdraw, SocialUserRespDTO socialUser) {
|
||||
PayTransferCreateReqDTO payTransferCreateReqDTO = new PayTransferCreateReqDTO();
|
||||
payTransferCreateReqDTO.setAppKey(tradeOrderProperties.getPayAppKey());
|
||||
payTransferCreateReqDTO.setChannelCode("wx_lite");
|
||||
payTransferCreateReqDTO.setUserIp(userIp);
|
||||
payTransferCreateReqDTO.setType(PayTransferTypeEnum.WX_BALANCE.getType());
|
||||
payTransferCreateReqDTO.setMerchantTransferId(withdraw.getId().toString());
|
||||
payTransferCreateReqDTO.setPrice(withdraw.getPrice());
|
||||
payTransferCreateReqDTO.setSubject("佣金提现");
|
||||
payTransferCreateReqDTO.setOpenid(socialUser.getOpenid());
|
||||
return payTransferCreateReqDTO;
|
||||
}
|
||||
|
||||
private BrokerageWithdrawDO validateBrokerageWithdrawExists(Long id) {
|
||||
BrokerageWithdrawDO withdraw = brokerageWithdrawMapper.selectById(id);
|
||||
if (withdraw == null) {
|
||||
throw exception(BROKERAGE_WITHDRAW_NOT_EXISTS);
|
||||
@ -111,7 +164,7 @@ public class BrokerageWithdrawServiceImpl implements BrokerageWithdrawService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public BrokerageWithdrawDO getBrokerageWithdraw(Integer id) {
|
||||
public BrokerageWithdrawDO getBrokerageWithdraw(Long id) {
|
||||
return brokerageWithdrawMapper.selectById(id);
|
||||
}
|
||||
|
||||
@ -150,6 +203,23 @@ public class BrokerageWithdrawServiceImpl implements BrokerageWithdrawService {
|
||||
return brokerageWithdrawMapper.selectCountAndSumPriceByUserIdAndStatus(userIds, status.getStatus());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateTransfer(Long id, Long payTransferId) {
|
||||
BrokerageWithdrawDO withdraw = validateBrokerageWithdrawExists(id);
|
||||
PayTransferRespDTO transfer = payTransferApi.getTransfer(payTransferId);
|
||||
if(PayTransferStatusEnum.isSuccess(transfer.getStatus())){
|
||||
withdraw.setStatus(BrokerageWithdrawStatusEnum.WITHDRAW_SUCCESS.getStatus());
|
||||
}else if(PayTransferStatusEnum.isPendingStatus(transfer.getStatus())){
|
||||
withdraw.setStatus(BrokerageWithdrawStatusEnum.AUDIT_SUCCESS.getStatus());
|
||||
}else{
|
||||
withdraw.setStatus(BrokerageWithdrawStatusEnum.WITHDRAW_FAIL.getStatus());
|
||||
// 3.2 驳回时需要退还用户佣金
|
||||
brokerageRecordService.addBrokerage(withdraw.getUserId(), BrokerageRecordBizTypeEnum.WITHDRAW_REJECT,
|
||||
String.valueOf(withdraw.getId()), withdraw.getPrice(), BrokerageRecordBizTypeEnum.WITHDRAW_REJECT.getTitle());
|
||||
}
|
||||
brokerageWithdrawMapper.updateById(withdraw);
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算提现手续费
|
||||
*
|
||||
|
@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.pay.api.transfer;
|
||||
|
||||
import cn.iocoder.yudao.module.pay.api.transfer.dto.PayTransferCreateReqDTO;
|
||||
|
||||
import cn.iocoder.yudao.module.pay.api.transfer.dto.PayTransferRespDTO;
|
||||
import jakarta.validation.Valid;
|
||||
|
||||
/**
|
||||
@ -19,4 +20,10 @@ public interface PayTransferApi {
|
||||
*/
|
||||
Long createTransfer(@Valid PayTransferCreateReqDTO reqDTO);
|
||||
|
||||
/**
|
||||
* 获取转账单详细
|
||||
* @param id 转账单编号
|
||||
* @return 转账单详细
|
||||
*/
|
||||
PayTransferRespDTO getTransfer(Long id);
|
||||
}
|
||||
|
@ -0,0 +1,32 @@
|
||||
package cn.iocoder.yudao.module.pay.api.transfer.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class PayTransferRespDTO {
|
||||
|
||||
/**
|
||||
* 编号
|
||||
*/
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 转账单号
|
||||
*
|
||||
*/
|
||||
private String no;
|
||||
|
||||
/**
|
||||
* 转账金额,单位:分
|
||||
*/
|
||||
private Integer price;
|
||||
|
||||
/**
|
||||
* 转账状态
|
||||
*
|
||||
* 枚举 {@link PayTransferStatusRespEnum}
|
||||
*/
|
||||
private Integer status;
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
package cn.iocoder.yudao.module.pay.api.wallet;
|
||||
|
||||
import cn.iocoder.yudao.module.pay.api.wallet.dto.PayWalletCreateReqDto;
|
||||
import cn.iocoder.yudao.module.pay.api.wallet.dto.PayWalletRespDTO;
|
||||
|
||||
/**
|
||||
* 钱包 API 接口
|
||||
*
|
||||
* @author liurulin
|
||||
*/
|
||||
public interface PayWalletApi {
|
||||
|
||||
/**
|
||||
* 添加钱包
|
||||
* @param reqDTO 创建请求
|
||||
*/
|
||||
void addWallet(PayWalletCreateReqDto reqDTO);
|
||||
|
||||
/**
|
||||
* 根据用户id获取钱包信息
|
||||
* @param userId 用户id
|
||||
* @return 钱包信息
|
||||
*/
|
||||
PayWalletRespDTO getWalletByUserId(Long userId);
|
||||
}
|
@ -0,0 +1,42 @@
|
||||
package cn.iocoder.yudao.module.pay.api.wallet.dto;
|
||||
|
||||
import cn.iocoder.yudao.module.pay.enums.wallet.PayWalletBizTypeEnum;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class PayWalletCreateReqDto {
|
||||
|
||||
/**
|
||||
* 钱包编号
|
||||
*/
|
||||
@NotNull(message = "钱包编号不能为空")
|
||||
private Long walletId;
|
||||
|
||||
/**
|
||||
* 关联业务分类
|
||||
*/
|
||||
@NotNull(message = "关联业务分类不能为空")
|
||||
private PayWalletBizTypeEnum bizType;
|
||||
|
||||
/**
|
||||
* 关联业务编号
|
||||
*/
|
||||
@NotNull(message = "关联业务编号不能为空")
|
||||
private String bizId;
|
||||
|
||||
/**
|
||||
* 流水说明
|
||||
*/
|
||||
@NotNull(message = "流水说明不能为空")
|
||||
private String title;
|
||||
|
||||
/**
|
||||
* 交易金额,单位分
|
||||
*
|
||||
* 正值表示余额增加,负值表示余额减少
|
||||
*/
|
||||
@NotNull(message = "交易金额不能为空")
|
||||
private Integer price;
|
||||
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
package cn.iocoder.yudao.module.pay.api.wallet.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class PayWalletRespDTO {
|
||||
|
||||
/**
|
||||
* 编号
|
||||
*/
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 余额,单位分
|
||||
*/
|
||||
private Integer balance;
|
||||
|
||||
}
|
@ -19,7 +19,8 @@ public enum PayWalletBizTypeEnum implements IntArrayValuable {
|
||||
RECHARGE_REFUND(2, "充值退款"),
|
||||
PAYMENT(3, "支付"),
|
||||
PAYMENT_REFUND(4, "支付退款"),
|
||||
UPDATE_BALANCE(5, "更新余额");
|
||||
UPDATE_BALANCE(5, "更新余额"),
|
||||
WITHDRAW(6, "分佣提现");
|
||||
|
||||
/**
|
||||
* 业务分类
|
||||
@ -36,4 +37,5 @@ public enum PayWalletBizTypeEnum implements IntArrayValuable {
|
||||
public int[] array() {
|
||||
return ARRAYS;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,6 +1,9 @@
|
||||
package cn.iocoder.yudao.module.pay.api.transfer;
|
||||
|
||||
import cn.iocoder.yudao.module.pay.api.transfer.dto.PayTransferCreateReqDTO;
|
||||
import cn.iocoder.yudao.module.pay.api.transfer.dto.PayTransferRespDTO;
|
||||
import cn.iocoder.yudao.module.pay.convert.transfer.PayTransferConvert;
|
||||
import cn.iocoder.yudao.module.pay.dal.dataobject.transfer.PayTransferDO;
|
||||
import cn.iocoder.yudao.module.pay.service.transfer.PayTransferService;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
@ -24,4 +27,10 @@ public class PayTransferApiImpl implements PayTransferApi {
|
||||
return payTransferService.createTransfer(reqDTO);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PayTransferRespDTO getTransfer(Long id) {
|
||||
PayTransferDO transfer = payTransferService.getTransfer(id);
|
||||
return PayTransferConvert.INSTANCE.convert3(transfer);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,34 @@
|
||||
package cn.iocoder.yudao.module.pay.api.wallet;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
|
||||
import cn.iocoder.yudao.module.pay.api.wallet.dto.PayWalletCreateReqDto;
|
||||
import cn.iocoder.yudao.module.pay.api.wallet.dto.PayWalletRespDTO;
|
||||
import cn.iocoder.yudao.module.pay.convert.wallet.PayWalletConvert;
|
||||
import cn.iocoder.yudao.module.pay.dal.dataobject.wallet.PayWalletDO;
|
||||
import cn.iocoder.yudao.module.pay.service.wallet.PayWalletService;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* 钱包 API 实现类
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Service
|
||||
public class PayWalletApiImpl implements PayWalletApi {
|
||||
|
||||
@Resource
|
||||
private PayWalletService payWalletService;
|
||||
|
||||
@Override
|
||||
public void addWallet(PayWalletCreateReqDto reqDTO) {
|
||||
//添加钱包金额
|
||||
payWalletService.addWalletBalance(reqDTO.getWalletId(), reqDTO.getBizId(), reqDTO.getBizType(), reqDTO.getPrice());
|
||||
}
|
||||
|
||||
@Override
|
||||
public PayWalletRespDTO getWalletByUserId(Long userId) {
|
||||
PayWalletDO orCreateWallet = payWalletService.getOrCreateWallet(userId, UserTypeEnum.MEMBER.getValue());
|
||||
return PayWalletConvert.INSTANCE.convert03(orCreateWallet);
|
||||
}
|
||||
}
|
@ -40,4 +40,9 @@ public class PayAppBaseVO {
|
||||
@URL(message = "退款结果的回调地址必须为 URL 格式")
|
||||
private String refundNotifyUrl;
|
||||
|
||||
@Schema(description = "转账结果的回调地址", requiredMode = Schema.RequiredMode.REQUIRED, example = "http://127.0.0.1:48080/refund-callback")
|
||||
@NotNull(message = "转账结果的回调地址不能为空")
|
||||
@URL(message = "转账结果的回调地址必须为 URL 格式")
|
||||
private String transferNotifyUrl;
|
||||
|
||||
}
|
||||
|
@ -6,6 +6,7 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.pay.core.client.PayClient;
|
||||
import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderRespDTO;
|
||||
import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundRespDTO;
|
||||
import cn.iocoder.yudao.framework.pay.core.client.dto.transfer.PayTransferRespDTO;
|
||||
import cn.iocoder.yudao.module.pay.controller.admin.notify.vo.PayNotifyTaskDetailRespVO;
|
||||
import cn.iocoder.yudao.module.pay.controller.admin.notify.vo.PayNotifyTaskPageReqVO;
|
||||
import cn.iocoder.yudao.module.pay.controller.admin.notify.vo.PayNotifyTaskRespVO;
|
||||
@ -18,6 +19,7 @@ import cn.iocoder.yudao.module.pay.service.channel.PayChannelService;
|
||||
import cn.iocoder.yudao.module.pay.service.notify.PayNotifyService;
|
||||
import cn.iocoder.yudao.module.pay.service.order.PayOrderService;
|
||||
import cn.iocoder.yudao.module.pay.service.refund.PayRefundService;
|
||||
import cn.iocoder.yudao.module.pay.service.transfer.PayTransferService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
@ -49,6 +51,8 @@ public class PayNotifyController {
|
||||
@Resource
|
||||
private PayRefundService refundService;
|
||||
@Resource
|
||||
private PayTransferService payTransferService;
|
||||
@Resource
|
||||
private PayNotifyService notifyService;
|
||||
@Resource
|
||||
private PayAppService appService;
|
||||
@ -95,6 +99,26 @@ public class PayNotifyController {
|
||||
return "success";
|
||||
}
|
||||
|
||||
@PostMapping(value = "/transfer/{channelId}")
|
||||
@Operation(summary = "支付渠道的统一【转账】回调")
|
||||
@PermitAll
|
||||
public String notifyTransfer(@PathVariable("channelId") Long channelId,
|
||||
@RequestParam(required = false) Map<String, String> params,
|
||||
@RequestBody(required = false) String body) {
|
||||
log.info("[notifyRefund][channelId({}) 回调数据({}/{})]", channelId, params, body);
|
||||
// 1. 校验支付渠道是否存在
|
||||
PayClient payClient = channelService.getPayClient(channelId);
|
||||
if (payClient == null) {
|
||||
log.error("[notifyCallback][渠道编号({}) 找不到对应的支付客户端]", channelId);
|
||||
throw exception(CHANNEL_NOT_FOUND);
|
||||
}
|
||||
|
||||
// 2. 解析通知数据
|
||||
PayTransferRespDTO notify = payClient.parseTransferNotify(params, body);
|
||||
payTransferService.notifyTransfer(channelId, notify);
|
||||
return "success";
|
||||
}
|
||||
|
||||
@GetMapping("/get-detail")
|
||||
@Operation(summary = "获得回调通知的明细")
|
||||
@Parameter(name = "id", description = "编号", required = true, example = "1024")
|
||||
|
@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.pay.convert.transfer;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.pay.core.client.dto.transfer.PayTransferUnifiedReqDTO;
|
||||
import cn.iocoder.yudao.module.pay.api.transfer.dto.PayTransferCreateReqDTO;
|
||||
import cn.iocoder.yudao.module.pay.api.transfer.dto.PayTransferRespDTO;
|
||||
import cn.iocoder.yudao.module.pay.controller.admin.demo.vo.transfer.PayDemoTransferCreateReqVO;
|
||||
import cn.iocoder.yudao.module.pay.controller.admin.transfer.vo.PayTransferCreateReqVO;
|
||||
import cn.iocoder.yudao.module.pay.controller.admin.transfer.vo.PayTransferPageItemRespVO;
|
||||
@ -24,7 +25,9 @@ public interface PayTransferConvert {
|
||||
|
||||
PayTransferCreateReqDTO convert(PayDemoTransferCreateReqVO vo);
|
||||
|
||||
PayTransferRespVO convert(PayTransferDO bean);
|
||||
PayTransferRespVO convert(PayTransferDO bean);
|
||||
|
||||
PayTransferRespDTO convert3(PayTransferDO bean);
|
||||
|
||||
PageResult<PayTransferPageItemRespVO> convertPage(PageResult<PayTransferDO> pageResult);
|
||||
}
|
||||
|
@ -1,6 +1,8 @@
|
||||
package cn.iocoder.yudao.module.pay.convert.wallet;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.module.pay.api.wallet.dto.PayWalletCreateReqDto;
|
||||
import cn.iocoder.yudao.module.pay.api.wallet.dto.PayWalletRespDTO;
|
||||
import cn.iocoder.yudao.module.pay.controller.admin.wallet.vo.wallet.PayWalletRespVO;
|
||||
import cn.iocoder.yudao.module.pay.controller.app.wallet.vo.wallet.AppPayWalletRespVO;
|
||||
import cn.iocoder.yudao.module.pay.dal.dataobject.wallet.PayWalletDO;
|
||||
@ -18,4 +20,6 @@ public interface PayWalletConvert {
|
||||
|
||||
PageResult<PayWalletRespVO> convertPage(PageResult<PayWalletDO> page);
|
||||
|
||||
PayWalletRespDTO convert03(PayWalletDO orCreateWallet);
|
||||
|
||||
}
|
||||
|
@ -4,6 +4,7 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
|
||||
import cn.iocoder.yudao.module.pay.controller.admin.transfer.vo.PayTransferPageReqVO;
|
||||
import cn.iocoder.yudao.module.pay.dal.dataobject.refund.PayRefundDO;
|
||||
import cn.iocoder.yudao.module.pay.dal.dataobject.transfer.PayTransferDO;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
@ -44,6 +45,12 @@ public interface PayTransferMapper extends BaseMapperX<PayTransferDO> {
|
||||
default List<PayTransferDO> selectListByStatus(Integer status){
|
||||
return selectList(PayTransferDO::getStatus, status);
|
||||
}
|
||||
|
||||
default PayTransferDO selectByAppIdAndNo(Long appId, String no){
|
||||
return selectOne(new LambdaQueryWrapperX<PayTransferDO>()
|
||||
.eq(PayTransferDO::getAppId, appId)
|
||||
.eq(PayTransferDO::getNo, no));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -39,6 +39,15 @@ public class PayProperties {
|
||||
@URL(message = "支付回调地址的格式必须是 URL")
|
||||
private String refundNotifyUrl;
|
||||
|
||||
/**
|
||||
* 转账回调地址
|
||||
*
|
||||
* 实际上,对应的 PayNotifyController 的 notifyTransfer 方法的 URL
|
||||
*
|
||||
* 回调顺序:支付渠道(支付宝支付、微信支付) => yudao-module-pay 的 transferNotifyUrl 地址 => 业务的 PayAppDO.transferNotifyUrl 地址
|
||||
*/
|
||||
private String transferNotifyUrl;
|
||||
|
||||
/**
|
||||
* 支付订单 no 的前缀
|
||||
*/
|
||||
|
@ -177,6 +177,11 @@ public class WalletPayClient extends AbstractPayClient<NonePayClientConfig> {
|
||||
throw new IllegalStateException(String.format("支付退款单[%s] 状态不正确", outRefundNo));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected PayTransferRespDTO doParseTransferNotify(Map<String, String> params, String body) throws Throwable {
|
||||
throw new UnsupportedOperationException("未实现");
|
||||
}
|
||||
|
||||
@Override
|
||||
public PayTransferRespDTO doUnifiedTransfer(PayTransferUnifiedReqDTO reqDTO) {
|
||||
throw new UnsupportedOperationException("待实现");
|
||||
|
@ -78,5 +78,4 @@ public interface PayRefundService {
|
||||
* @return 同步到状态的退款数量,包括退款成功、退款失败
|
||||
*/
|
||||
int syncRefund();
|
||||
|
||||
}
|
||||
|
@ -193,6 +193,8 @@ public class PayRefundServiceImpl implements PayRefundService {
|
||||
TenantUtils.execute(channel.getTenantId(), () -> getSelf().notifyRefund(channel, notify));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 通知并更新订单的退款结果
|
||||
*
|
||||
|
@ -1,6 +1,7 @@
|
||||
package cn.iocoder.yudao.module.pay.service.transfer;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.pay.core.client.dto.transfer.PayTransferRespDTO;
|
||||
import cn.iocoder.yudao.module.pay.api.transfer.dto.PayTransferCreateReqDTO;
|
||||
import cn.iocoder.yudao.module.pay.controller.admin.transfer.vo.PayTransferCreateReqVO;
|
||||
import cn.iocoder.yudao.module.pay.controller.admin.transfer.vo.PayTransferPageReqVO;
|
||||
@ -54,4 +55,12 @@ public interface PayTransferService {
|
||||
* @return 同步到状态的转账数量,包括转账成功、转账失败、转账中的
|
||||
*/
|
||||
int syncTransfer();
|
||||
|
||||
/**
|
||||
* 渠道的转账通知
|
||||
*
|
||||
* @param channelId 渠道编号
|
||||
* @param notify 通知
|
||||
*/
|
||||
void notifyTransfer(Long channelId, PayTransferRespDTO notify);
|
||||
}
|
||||
|
@ -21,6 +21,7 @@ import cn.iocoder.yudao.module.pay.dal.mysql.transfer.PayTransferMapper;
|
||||
import cn.iocoder.yudao.module.pay.dal.redis.no.PayNoRedisDAO;
|
||||
import cn.iocoder.yudao.module.pay.enums.notify.PayNotifyTypeEnum;
|
||||
import cn.iocoder.yudao.module.pay.enums.transfer.PayTransferStatusEnum;
|
||||
import cn.iocoder.yudao.module.pay.framework.pay.config.PayProperties;
|
||||
import cn.iocoder.yudao.module.pay.service.app.PayAppService;
|
||||
import cn.iocoder.yudao.module.pay.service.channel.PayChannelService;
|
||||
import cn.iocoder.yudao.module.pay.service.notify.PayNotifyService;
|
||||
@ -28,6 +29,7 @@ import jakarta.annotation.Resource;
|
||||
import jakarta.validation.Validator;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Propagation;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.List;
|
||||
@ -50,6 +52,9 @@ public class PayTransferServiceImpl implements PayTransferService {
|
||||
|
||||
private static final String TRANSFER_NO_PREFIX = "T";
|
||||
|
||||
@Resource
|
||||
private PayProperties payProperties;
|
||||
|
||||
@Resource
|
||||
private PayTransferMapper transferMapper;
|
||||
@Resource
|
||||
@ -96,13 +101,15 @@ public class PayTransferServiceImpl implements PayTransferService {
|
||||
transfer = INSTANCE.convert(reqDTO)
|
||||
.setChannelId(channel.getId())
|
||||
.setNo(no).setStatus(WAITING.getStatus())
|
||||
.setNotifyUrl(payApp.getTransferNotifyUrl());
|
||||
.setNotifyUrl(payApp.getTransferNotifyUrl())
|
||||
.setAppId(channel.getAppId());
|
||||
transferMapper.insert(transfer);
|
||||
}
|
||||
try {
|
||||
// 3. 调用三方渠道发起转账
|
||||
PayTransferUnifiedReqDTO transferUnifiedReq = INSTANCE.convert2(transfer)
|
||||
.setOutTransferNo(transfer.getNo());
|
||||
transferUnifiedReq.setNotifyUrl(genChannelTransferNotifyUrl(channel));
|
||||
PayTransferRespDTO unifiedTransferResp = client.unifiedTransfer(transferUnifiedReq);
|
||||
// 4. 通知转账结果
|
||||
getSelf().notifyTransfer(channel, unifiedTransferResp);
|
||||
@ -116,6 +123,16 @@ public class PayTransferServiceImpl implements PayTransferService {
|
||||
return transfer.getId();
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据支付渠道的编码,生成支付渠道的回调地址
|
||||
*
|
||||
* @param channel 支付渠道
|
||||
* @return 支付渠道的回调地址 配置地址 + "/" + channel id
|
||||
*/
|
||||
private String genChannelTransferNotifyUrl(PayChannelDO channel) {
|
||||
return payProperties.getTransferNotifyUrl() + "/" + channel.getId();
|
||||
}
|
||||
|
||||
private PayTransferDO validateTransferCanCreate(PayTransferCreateReqDTO dto, Long appId) {
|
||||
PayTransferDO transfer = transferMapper.selectByAppIdAndMerchantTransferId(appId, dto.getMerchantTransferId());
|
||||
if (transfer != null) {
|
||||
@ -154,7 +171,8 @@ public class PayTransferServiceImpl implements PayTransferService {
|
||||
|
||||
private void notifyTransferInProgress(PayChannelDO channel, PayTransferRespDTO notify) {
|
||||
// 1.校验
|
||||
PayTransferDO transfer = transferMapper.selectByNo(notify.getOutTransferNo());
|
||||
PayTransferDO transfer = transferMapper.selectByAppIdAndNo(
|
||||
channel.getAppId(), notify.getOutTransferNo());
|
||||
if (transfer == null) {
|
||||
throw exception(PAY_TRANSFER_NOT_FOUND);
|
||||
}
|
||||
@ -172,16 +190,13 @@ public class PayTransferServiceImpl implements PayTransferService {
|
||||
throw exception(PAY_TRANSFER_STATUS_IS_NOT_WAITING);
|
||||
}
|
||||
log.info("[notifyTransferInProgress][transfer({}) 更新为转账进行中状态]", transfer.getId());
|
||||
|
||||
// 3. 插入转账通知记录
|
||||
notifyService.createPayNotifyTask(PayNotifyTypeEnum.TRANSFER.getType(),
|
||||
transfer.getId());
|
||||
}
|
||||
|
||||
|
||||
private void notifyTransferSuccess(PayChannelDO channel, PayTransferRespDTO notify) {
|
||||
// 1.校验
|
||||
PayTransferDO transfer = transferMapper.selectByNo(notify.getOutTransferNo());
|
||||
PayTransferDO transfer = transferMapper.selectByAppIdAndNo(
|
||||
channel.getAppId(), notify.getOutTransferNo());
|
||||
if (transfer == null) {
|
||||
throw exception(PAY_TRANSFER_NOT_FOUND);
|
||||
}
|
||||
@ -210,7 +225,8 @@ public class PayTransferServiceImpl implements PayTransferService {
|
||||
|
||||
private void notifyTransferClosed(PayChannelDO channel, PayTransferRespDTO notify) {
|
||||
// 1.校验
|
||||
PayTransferDO transfer = transferMapper.selectByNo(notify.getOutTransferNo());
|
||||
PayTransferDO transfer = transferMapper.selectByAppIdAndNo(
|
||||
channel.getAppId(), notify.getOutTransferNo());
|
||||
if (transfer == null) {
|
||||
throw exception(PAY_TRANSFER_NOT_FOUND);
|
||||
}
|
||||
@ -283,7 +299,7 @@ public class PayTransferServiceImpl implements PayTransferService {
|
||||
}
|
||||
}
|
||||
|
||||
private void notifyTransfer(Long channelId, PayTransferRespDTO notify) {
|
||||
public void notifyTransfer(Long channelId, PayTransferRespDTO notify) {
|
||||
// 校验渠道是否有效
|
||||
PayChannelDO channel = channelService.validPayChannel(channelId);
|
||||
// 通知转账结果给对应的业务
|
||||
|
@ -200,6 +200,9 @@ public class PayWalletServiceImpl implements PayWalletService {
|
||||
case UPDATE_BALANCE: // 更新余额
|
||||
walletMapper.updateWhenRecharge(payWallet.getId(), price);
|
||||
break;
|
||||
case WITHDRAW:
|
||||
walletMapper.updateWhenRecharge(payWallet.getId(), price);
|
||||
break;
|
||||
default: {
|
||||
// TODO 其它类型待实现
|
||||
throw new UnsupportedOperationException("待实现");
|
||||
|
@ -64,6 +64,10 @@
|
||||
<groupId>com.github.binarywang</groupId>
|
||||
<artifactId>weixin-java-pay</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.github.binarywang</groupId>
|
||||
<artifactId>wx-java-miniapp-spring-boot-starter</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- Test 测试相关 -->
|
||||
<dependency>
|
||||
@ -71,6 +75,7 @@
|
||||
<artifactId>yudao-spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
|
@ -79,6 +79,8 @@ public interface PayClient {
|
||||
*/
|
||||
PayRefundRespDTO getRefund(String outTradeNo, String outRefundNo);
|
||||
|
||||
// ============ 转账相关 ==========
|
||||
|
||||
/**
|
||||
* 调用渠道,进行转账
|
||||
*
|
||||
@ -95,4 +97,13 @@ public interface PayClient {
|
||||
* @return 转账信息
|
||||
*/
|
||||
PayTransferRespDTO getTransfer(String outTradeNo, PayTransferTypeEnum type);
|
||||
|
||||
/**
|
||||
* 解析 transfer 回调数据
|
||||
*
|
||||
* @param params HTTP 回调接口 content type 为 application/x-www-form-urlencoded 的所有参数
|
||||
* @param body HTTP 回调接口的 request body
|
||||
* @return 转账信息
|
||||
*/
|
||||
PayTransferRespDTO parseTransferNotify(Map<String, String> params, String body);
|
||||
}
|
||||
|
@ -9,6 +9,8 @@ import jakarta.validation.constraints.Min;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import org.hibernate.validator.constraints.URL;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import static cn.iocoder.yudao.framework.pay.core.enums.transfer.PayTransferTypeEnum.*;
|
||||
@ -75,4 +77,11 @@ public class PayTransferUnifiedReqDTO {
|
||||
* 支付渠道的额外参数
|
||||
*/
|
||||
private Map<String, String> channelExtras;
|
||||
|
||||
/**
|
||||
* 转账结果的 notify 回调地址
|
||||
*/
|
||||
@NotEmpty(message = "转账结果的回调地址不能为空")
|
||||
@URL(message = "转账结果的 notify 回调地址必须是 URL 格式")
|
||||
private String notifyUrl;
|
||||
}
|
||||
|
@ -0,0 +1,128 @@
|
||||
package cn.iocoder.yudao.framework.pay.core.client.dto.transfer;
|
||||
|
||||
import com.github.binarywang.wxpay.bean.notify.OriginNotifyResponse;
|
||||
import com.github.binarywang.wxpay.bean.notify.WxPayBaseNotifyV3Result;
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
@NoArgsConstructor
|
||||
public class WxPayTransferPartnerNotifyV3Result implements Serializable, WxPayBaseNotifyV3Result<WxPayTransferPartnerNotifyV3Result.TransferNotifyResult> {
|
||||
|
||||
private static final long serialVersionUID = -1L;
|
||||
|
||||
/**
|
||||
* 源数据
|
||||
*/
|
||||
private OriginNotifyResponse rawData;
|
||||
|
||||
/**
|
||||
* 解密后的数据
|
||||
*/
|
||||
private TransferNotifyResult result;
|
||||
|
||||
@Override
|
||||
public void setRawData(OriginNotifyResponse rawData) {
|
||||
this.rawData = rawData;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setResult(TransferNotifyResult data) {
|
||||
this.result = data;
|
||||
}
|
||||
|
||||
public TransferNotifyResult getResult() {
|
||||
return result;
|
||||
}
|
||||
|
||||
public OriginNotifyResponse getRawData() {
|
||||
return rawData;
|
||||
}
|
||||
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
public static class TransferNotifyResult implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/*********************** 公共字段 ********************
|
||||
|
||||
/**
|
||||
* 商家批次单号
|
||||
*/
|
||||
@SerializedName(value = "out_batch_no")
|
||||
protected String outBatchNo;
|
||||
|
||||
/**
|
||||
* 微信批次单号
|
||||
*/
|
||||
@SerializedName(value = "batch_id")
|
||||
protected String batchId;
|
||||
|
||||
/**
|
||||
* 批次状态
|
||||
*/
|
||||
@SerializedName(value = "batch_status")
|
||||
protected String batchStatus;
|
||||
|
||||
/**
|
||||
* 批次总笔数
|
||||
*/
|
||||
@SerializedName(value = "total_num")
|
||||
protected Integer totalNum;
|
||||
|
||||
/**
|
||||
* 批次总金额
|
||||
*/
|
||||
@SerializedName(value = "total_amount")
|
||||
protected Integer totalAmount;
|
||||
|
||||
/**
|
||||
* 批次更新时间
|
||||
*/
|
||||
@SerializedName(value = "update_time")
|
||||
private String updateTime;
|
||||
|
||||
/*********************** FINISHED ********************
|
||||
|
||||
/**
|
||||
* 转账成功金额
|
||||
*/
|
||||
@SerializedName(value = "success_amount")
|
||||
protected Integer successAmount;
|
||||
|
||||
/**
|
||||
* 转账成功笔数
|
||||
*/
|
||||
@SerializedName(value = "success_num")
|
||||
protected Integer successNum;
|
||||
|
||||
/**
|
||||
* 转账失败金额
|
||||
*/
|
||||
@SerializedName(value = "fail_amount")
|
||||
protected Integer failAmount;
|
||||
|
||||
/**
|
||||
* 转账失败笔数
|
||||
*/
|
||||
@SerializedName(value = "fail_num")
|
||||
protected Integer failNum;
|
||||
|
||||
/*********************** CLOSED ********************
|
||||
|
||||
/**
|
||||
* 商户号
|
||||
*/
|
||||
@SerializedName(value = "mchid")
|
||||
protected String mchId;
|
||||
|
||||
/**
|
||||
* 批次关闭原因
|
||||
*/
|
||||
@SerializedName(value = "close_reason")
|
||||
protected String closeReason;
|
||||
|
||||
}
|
||||
}
|
@ -219,6 +219,22 @@ public abstract class AbstractPayClient<Config extends PayClientConfig> implemen
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public final PayTransferRespDTO parseTransferNotify(Map<String, String> params, String body) {
|
||||
try {
|
||||
return doParseTransferNotify(params, body);
|
||||
} catch (ServiceException ex) { // 业务异常,都是实现类已经翻译,所以直接抛出即可
|
||||
throw ex;
|
||||
} catch (Throwable ex) {
|
||||
log.error("[doParseTransferNotify][客户端({}) params({}) body({}) 解析失败]",
|
||||
getId(), params, body, ex);
|
||||
throw buildPayException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract PayTransferRespDTO doParseTransferNotify(Map<String, String> params, String body)
|
||||
throws Throwable;
|
||||
|
||||
@Override
|
||||
public final PayTransferRespDTO getTransfer(String outTradeNo, PayTransferTypeEnum type) {
|
||||
try {
|
||||
|
@ -325,6 +325,11 @@ public abstract class AbstractAlipayPayClient extends AbstractPayClient<AlipayPa
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected PayTransferRespDTO doParseTransferNotify(Map<String, String> params, String body) throws Throwable {
|
||||
throw new UnsupportedOperationException("未实现");
|
||||
}
|
||||
|
||||
// ========== 各种工具方法 ==========
|
||||
|
||||
protected String formatAmount(Integer amount) {
|
||||
|
@ -2,6 +2,7 @@ package cn.iocoder.yudao.framework.pay.core.client.impl.alipay;
|
||||
|
||||
import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderRespDTO;
|
||||
import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedReqDTO;
|
||||
import cn.iocoder.yudao.framework.pay.core.client.dto.transfer.PayTransferRespDTO;
|
||||
import cn.iocoder.yudao.framework.pay.core.enums.channel.PayChannelEnum;
|
||||
import cn.iocoder.yudao.framework.pay.core.enums.order.PayOrderDisplayModeEnum;
|
||||
import com.alipay.api.AlipayApiException;
|
||||
@ -56,4 +57,5 @@ public class AlipayAppPayClient extends AbstractAlipayPayClient {
|
||||
return PayOrderRespDTO.waitingOf(displayMode, response.getBody(),
|
||||
reqDTO.getOutTradeNo(), response);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ import cn.hutool.core.map.MapUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderRespDTO;
|
||||
import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedReqDTO;
|
||||
import cn.iocoder.yudao.framework.pay.core.client.dto.transfer.PayTransferRespDTO;
|
||||
import cn.iocoder.yudao.framework.pay.core.enums.channel.PayChannelEnum;
|
||||
import cn.iocoder.yudao.framework.pay.core.enums.order.PayOrderDisplayModeEnum;
|
||||
import com.alipay.api.AlipayApiException;
|
||||
@ -82,4 +83,5 @@ public class AlipayBarPayClient extends AbstractAlipayPayClient {
|
||||
return PayOrderRespDTO.waitingOf(displayMode, "",
|
||||
reqDTO.getOutTradeNo(), response);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -4,6 +4,7 @@ import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.http.Method;
|
||||
import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderRespDTO;
|
||||
import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedReqDTO;
|
||||
import cn.iocoder.yudao.framework.pay.core.client.dto.transfer.PayTransferRespDTO;
|
||||
import cn.iocoder.yudao.framework.pay.core.enums.channel.PayChannelEnum;
|
||||
import cn.iocoder.yudao.framework.pay.core.enums.order.PayOrderDisplayModeEnum;
|
||||
import com.alipay.api.AlipayApiException;
|
||||
@ -66,4 +67,5 @@ public class AlipayPcPayClient extends AbstractAlipayPayClient {
|
||||
return PayOrderRespDTO.waitingOf(displayMode, response.getBody(),
|
||||
reqDTO.getOutTradeNo(), response);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -57,6 +57,11 @@ public class MockPayClient extends AbstractPayClient<NonePayClientConfig> {
|
||||
outRefundNo, MOCK_RESP_SUCCESS_DATA);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected PayTransferRespDTO doParseTransferNotify(Map<String, String> params, String body) throws Throwable {
|
||||
throw new UnsupportedOperationException("未实现");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected PayRefundRespDTO doParseRefundNotify(Map<String, String> params, String body) {
|
||||
throw new UnsupportedOperationException("模拟支付无退款回调");
|
||||
|
@ -14,23 +14,26 @@ import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundRespDTO;
|
||||
import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundUnifiedReqDTO;
|
||||
import cn.iocoder.yudao.framework.pay.core.client.dto.transfer.PayTransferRespDTO;
|
||||
import cn.iocoder.yudao.framework.pay.core.client.dto.transfer.PayTransferUnifiedReqDTO;
|
||||
import cn.iocoder.yudao.framework.pay.core.client.dto.transfer.WxPayTransferPartnerNotifyV3Result;
|
||||
import cn.iocoder.yudao.framework.pay.core.client.impl.AbstractPayClient;
|
||||
import cn.iocoder.yudao.framework.pay.core.enums.order.PayOrderStatusRespEnum;
|
||||
import cn.iocoder.yudao.framework.pay.core.enums.transfer.PayTransferTypeEnum;
|
||||
import com.github.binarywang.wxpay.bean.notify.WxPayNotifyV3Result;
|
||||
import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult;
|
||||
import com.github.binarywang.wxpay.bean.notify.WxPayRefundNotifyResult;
|
||||
import com.github.binarywang.wxpay.bean.notify.WxPayRefundNotifyV3Result;
|
||||
import com.github.binarywang.wxpay.bean.notify.*;
|
||||
import com.github.binarywang.wxpay.bean.request.*;
|
||||
import com.github.binarywang.wxpay.bean.result.*;
|
||||
import com.github.binarywang.wxpay.bean.transfer.TransferBatchesRequest;
|
||||
import com.github.binarywang.wxpay.bean.transfer.TransferBatchesResult;
|
||||
import com.github.binarywang.wxpay.config.WxPayConfig;
|
||||
import com.github.binarywang.wxpay.exception.WxPayException;
|
||||
import com.github.binarywang.wxpay.service.TransferService;
|
||||
import com.github.binarywang.wxpay.service.WxPayService;
|
||||
import com.github.binarywang.wxpay.service.impl.WxPayServiceImpl;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZoneId;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
@ -348,6 +351,29 @@ public abstract class AbstractWxPayClient extends AbstractPayClient<WxPayClientC
|
||||
return PayRefundRespDTO.failureOf(result.getOutRefundNo(), response);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PayTransferRespDTO doParseTransferNotify(Map<String, String> params, String body) throws WxPayException {
|
||||
switch (config.getApiVersion()) {
|
||||
case API_VERSION_V3:
|
||||
return parseTransferNotifyV3(body);
|
||||
default:
|
||||
throw new IllegalArgumentException(String.format("未知的 API 版本(%s)", config.getApiVersion()));
|
||||
}
|
||||
}
|
||||
|
||||
private PayTransferRespDTO parseTransferNotifyV3(String body) throws WxPayException {
|
||||
WxPayTransferPartnerNotifyV3Result response = client.baseParseOrderNotifyV3Result(body, null, WxPayTransferPartnerNotifyV3Result.class, WxPayTransferPartnerNotifyV3Result.TransferNotifyResult.class);
|
||||
WxPayTransferPartnerNotifyV3Result.TransferNotifyResult result = response.getResult();
|
||||
// 2. 构建结果
|
||||
if (Objects.equals("FINISHED", result.getBatchStatus())) {
|
||||
if(result.getFailNum() <= 0){
|
||||
return PayTransferRespDTO.successOf(result.getBatchId(), parseDateV3(result.getUpdateTime()),
|
||||
result.getOutBatchNo(), response);
|
||||
}
|
||||
}
|
||||
return PayTransferRespDTO.closedOf(result.getBatchStatus(), result.getCloseReason(), result.getOutBatchNo(), response);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected PayRefundRespDTO doGetRefund(String outTradeNo, String outRefundNo) throws WxPayException {
|
||||
try {
|
||||
@ -426,8 +452,26 @@ public abstract class AbstractWxPayClient extends AbstractPayClient<WxPayClientC
|
||||
}
|
||||
|
||||
@Override
|
||||
protected PayTransferRespDTO doUnifiedTransfer(PayTransferUnifiedReqDTO reqDTO) {
|
||||
throw new UnsupportedOperationException("待实现");
|
||||
protected PayTransferRespDTO doUnifiedTransfer(PayTransferUnifiedReqDTO reqDTO) throws WxPayException {
|
||||
TransferService transferService = client.getTransferService();
|
||||
List<TransferBatchesRequest.TransferDetail> transferDetailList = new ArrayList<>();
|
||||
transferDetailList.add(TransferBatchesRequest.TransferDetail.newBuilder()
|
||||
.outDetailNo(reqDTO.getOutTransferNo())
|
||||
.transferAmount(reqDTO.getPrice())
|
||||
.transferRemark(reqDTO.getSubject())
|
||||
.openid(reqDTO.getOpenid())
|
||||
.build());
|
||||
TransferBatchesRequest transferBatches = TransferBatchesRequest.newBuilder()
|
||||
.appid(this.config.getAppId())
|
||||
.outBatchNo(reqDTO.getOutTransferNo())
|
||||
.batchName(reqDTO.getSubject())
|
||||
.batchRemark(reqDTO.getSubject())
|
||||
.totalAmount(reqDTO.getPrice())
|
||||
.totalNum(1)
|
||||
.transferDetailList(transferDetailList).build();
|
||||
transferBatches.setNotifyUrl(reqDTO.getNotifyUrl());
|
||||
TransferBatchesResult transferBatchesResult = transferService.transferBatches(transferBatches);
|
||||
return PayTransferRespDTO.dealingOf(transferBatchesResult.getBatchId(), reqDTO.getOutTransferNo(), transferBatchesResult);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -0,0 +1,118 @@
|
||||
package com.github.binarywang.wxpay.bean.transfer;
|
||||
|
||||
import com.github.binarywang.wxpay.v3.SpecEncrypt;
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 发起商家转账API参数
|
||||
*
|
||||
* @author zhongjun
|
||||
* created on 2022/6/17
|
||||
**/
|
||||
@Data
|
||||
@Builder(builderMethodName = "newBuilder")
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class TransferBatchesRequest implements Serializable {
|
||||
private static final long serialVersionUID = -2175582517588397426L;
|
||||
|
||||
/**
|
||||
* 直连商户的appid
|
||||
*/
|
||||
@SerializedName("appid")
|
||||
private String appid;
|
||||
|
||||
/**
|
||||
* 商家批次单号
|
||||
*/
|
||||
@SerializedName("out_batch_no")
|
||||
private String outBatchNo;
|
||||
|
||||
/**
|
||||
* 批次名称
|
||||
*/
|
||||
@SerializedName("batch_name")
|
||||
private String batchName;
|
||||
|
||||
/**
|
||||
* 批次备注
|
||||
*/
|
||||
@SerializedName("batch_remark")
|
||||
private String batchRemark;
|
||||
|
||||
/**
|
||||
* 转账总金额
|
||||
*/
|
||||
@SerializedName("total_amount")
|
||||
private Integer totalAmount;
|
||||
|
||||
/**
|
||||
* 转账总笔数
|
||||
*/
|
||||
@SerializedName("total_num")
|
||||
private Integer totalNum;
|
||||
|
||||
/**
|
||||
* 转账明细列表
|
||||
*/
|
||||
@SpecEncrypt
|
||||
@SerializedName("transfer_detail_list")
|
||||
private List<TransferDetail> transferDetailList;
|
||||
|
||||
/**
|
||||
* 转账场景ID
|
||||
*/
|
||||
@SerializedName("transfer_scene_id")
|
||||
private String transferSceneId;
|
||||
|
||||
/**
|
||||
* 通知地址 说明:异步接收微信支付结果通知的回调地址,通知url必须为公网可访问的url,必须为https,不能携带参数。
|
||||
*/
|
||||
@SerializedName("notify_url")
|
||||
private String notifyUrl;
|
||||
|
||||
@Data
|
||||
@Builder(builderMethodName = "newBuilder")
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public static class TransferDetail {
|
||||
|
||||
/**
|
||||
* 商家明细单号
|
||||
*/
|
||||
@SerializedName("out_detail_no")
|
||||
private String outDetailNo;
|
||||
|
||||
/**
|
||||
* 转账金额
|
||||
*/
|
||||
@SerializedName("transfer_amount")
|
||||
private Integer transferAmount;
|
||||
|
||||
/**
|
||||
* 转账备注
|
||||
*/
|
||||
@SerializedName("transfer_remark")
|
||||
private String transferRemark;
|
||||
|
||||
/**
|
||||
* 用户在直连商户应用下的用户标示
|
||||
*/
|
||||
@SerializedName("openid")
|
||||
private String openid;
|
||||
|
||||
/**
|
||||
* 收款用户姓名
|
||||
*/
|
||||
@SpecEncrypt
|
||||
@SerializedName("user_name")
|
||||
private String userName;
|
||||
}
|
||||
}
|
@ -165,7 +165,8 @@ yudao:
|
||||
pay:
|
||||
order-notify-url: http://yunai.natapp1.cc/admin-api/pay/notify/order # 支付渠道的【支付】回调地址
|
||||
refund-notify-url: http://yunai.natapp1.cc/admin-api/pay/notify/refund # 支付渠道的【退款】回调地址
|
||||
demo: true # 开启演示模式
|
||||
transfer-notify-url: https://yunai.natapp1.cc/admin-api/pay/notify/transfer # 支付渠道的【转账】回调地址
|
||||
demo: false # 开启演示模式
|
||||
tencent-lbs-key: TVDBZ-TDILD-4ON4B-PFDZA-RNLKH-VVF6E # QQ 地图的密钥 https://lbs.qq.com/service/staticV2/staticGuide/staticDoc
|
||||
|
||||
justauth:
|
||||
|
@ -218,6 +218,7 @@ yudao:
|
||||
pay:
|
||||
order-notify-url: http://yunai.natapp1.cc/admin-api/pay/notify/order # 支付渠道的【支付】回调地址
|
||||
refund-notify-url: http://yunai.natapp1.cc/admin-api/pay/notify/refund # 支付渠道的【退款】回调地址
|
||||
transfer-notify-url: http://yunai.natapp1.cc/admin-api/pay/notify/transfer # 支付渠道的【转账】回调地址
|
||||
access-log: # 访问日志的配置项
|
||||
enable: false
|
||||
demo: false # 关闭演示模式
|
||||
|
Loading…
x
Reference in New Issue
Block a user