mirror of
				https://gitee.com/hhyykk/ipms-sjy.git
				synced 2025-11-04 20:28:44 +08:00 
			
		
		
		
	转账 - 动态收款人字段修改
This commit is contained in:
		@@ -1,14 +1,15 @@
 | 
			
		||||
package cn.iocoder.yudao.module.pay.controller.admin.demo.vo.transfer;
 | 
			
		||||
 | 
			
		||||
import cn.iocoder.yudao.framework.common.util.validation.ValidationUtils;
 | 
			
		||||
import cn.iocoder.yudao.framework.common.validation.InEnum;
 | 
			
		||||
import cn.iocoder.yudao.framework.pay.core.enums.transfer.PayTransferTypeEnum;
 | 
			
		||||
import io.swagger.v3.oas.annotations.media.Schema;
 | 
			
		||||
import lombok.Data;
 | 
			
		||||
 | 
			
		||||
import javax.validation.Validator;
 | 
			
		||||
import javax.validation.constraints.Min;
 | 
			
		||||
import javax.validation.constraints.NotEmpty;
 | 
			
		||||
import javax.validation.constraints.NotBlank;
 | 
			
		||||
import javax.validation.constraints.NotNull;
 | 
			
		||||
import java.util.Map;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @author jason
 | 
			
		||||
@@ -22,13 +23,50 @@ public class PayDemoTransferCreateReqVO {
 | 
			
		||||
    @InEnum(PayTransferTypeEnum.class)
 | 
			
		||||
    private Integer type;
 | 
			
		||||
 | 
			
		||||
    @Schema(description = "转账金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "100")
 | 
			
		||||
    @NotNull(message = "转账金额不能为空")
 | 
			
		||||
    @Min(value = 1, message = "转账金额必须大于零")
 | 
			
		||||
    private Integer price;
 | 
			
		||||
 | 
			
		||||
    // TODO @jason:感觉这个动态字段,晚点改;可能要讨论下怎么搞好;
 | 
			
		||||
    @Schema(description = "收款方信息", requiredMode = Schema.RequiredMode.REQUIRED, example = "{'ALIPAY_LOGON_ID':'xxxx'}")
 | 
			
		||||
    @NotEmpty(message = "收款方信息不能为空")
 | 
			
		||||
    private Map<String, String> payeeInfo;
 | 
			
		||||
    // ========== 支付宝,微信转账相关字段 ==========
 | 
			
		||||
    @Schema(description = "支付宝登录号,支持邮箱和手机号格式", example = "test1@@sandbox.com")
 | 
			
		||||
    @NotBlank(message = "支付宝登录号不能为空", groups = {Alipay.class})
 | 
			
		||||
    private String alipayLogonId;
 | 
			
		||||
 | 
			
		||||
    @Schema(description = "支付宝账号名称", example = "test1")
 | 
			
		||||
    @NotBlank(message = "支付宝登录号不能为空", groups = {Alipay.class})
 | 
			
		||||
    private String alipayAccountName;
 | 
			
		||||
 | 
			
		||||
    // ========== 微信转账相关字段 ==========
 | 
			
		||||
    @Schema(description = "微信 openId", example = "oLefc4g5Gxx")
 | 
			
		||||
    @NotBlank(message = "微信 openId 不能为空", groups = {WxPay.class})
 | 
			
		||||
    private String openid;
 | 
			
		||||
 | 
			
		||||
    @Schema(description = "微信账号名称", example = "oLefc4g5Gjxxxxxx")
 | 
			
		||||
    private String wxAccountName;
 | 
			
		||||
 | 
			
		||||
    // ========== 转账到银行卡和钱包相关字段 待补充 ==========
 | 
			
		||||
    public interface WxPay {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public interface Alipay {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void validate(Validator validator) {
 | 
			
		||||
        PayTransferTypeEnum transferType = PayTransferTypeEnum.typeOf(type);
 | 
			
		||||
        switch (transferType) {
 | 
			
		||||
            case ALIPAY_BALANCE: {
 | 
			
		||||
                ValidationUtils.validate(validator, this, Alipay.class);
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
            case WX_BALANCE: {
 | 
			
		||||
                ValidationUtils.validate(validator, this, WxPay.class);
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
            default: {
 | 
			
		||||
                throw new UnsupportedOperationException("待实现");
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,17 @@
 | 
			
		||||
package cn.iocoder.yudao.module.pay.convert.demo;
 | 
			
		||||
 | 
			
		||||
import cn.iocoder.yudao.module.pay.controller.admin.demo.vo.transfer.PayDemoTransferCreateReqVO;
 | 
			
		||||
import cn.iocoder.yudao.module.pay.dal.dataobject.demo.PayDemoTransferDO;
 | 
			
		||||
import org.mapstruct.Mapper;
 | 
			
		||||
import org.mapstruct.factory.Mappers;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @author jason
 | 
			
		||||
 */
 | 
			
		||||
@Mapper
 | 
			
		||||
public interface PayDemoTransferConvert {
 | 
			
		||||
 | 
			
		||||
    PayDemoTransferConvert INSTANCE = Mappers.getMapper(PayDemoTransferConvert.class);
 | 
			
		||||
 | 
			
		||||
    PayDemoTransferDO convert(PayDemoTransferCreateReqVO bean);
 | 
			
		||||
}
 | 
			
		||||
@@ -1,15 +1,13 @@
 | 
			
		||||
package cn.iocoder.yudao.module.pay.dal.dataobject.demo;
 | 
			
		||||
 | 
			
		||||
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
 | 
			
		||||
import cn.iocoder.yudao.framework.pay.core.enums.transfer.PayTransferTypeEnum;
 | 
			
		||||
import com.baomidou.mybatisplus.annotation.KeySequence;
 | 
			
		||||
import com.baomidou.mybatisplus.annotation.TableField;
 | 
			
		||||
import com.baomidou.mybatisplus.annotation.TableId;
 | 
			
		||||
import com.baomidou.mybatisplus.annotation.TableName;
 | 
			
		||||
import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
 | 
			
		||||
import lombok.Data;
 | 
			
		||||
 | 
			
		||||
import java.time.LocalDateTime;
 | 
			
		||||
import java.util.Map;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 示例转账订单
 | 
			
		||||
@@ -39,15 +37,30 @@ public class PayDemoTransferDO extends BaseDO {
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 转账类型
 | 
			
		||||
     * <p>
 | 
			
		||||
     * 枚举 {@link PayTransferTypeEnum}
 | 
			
		||||
     */
 | 
			
		||||
    private Integer type;
 | 
			
		||||
 | 
			
		||||
    // TODO @jason:要不字段还是弄成正确的平铺开?
 | 
			
		||||
    /**
 | 
			
		||||
     * 收款人信息,不同类型和渠道不同
 | 
			
		||||
     * 支付宝登录号
 | 
			
		||||
     */
 | 
			
		||||
    @TableField(typeHandler = JacksonTypeHandler.class)
 | 
			
		||||
    private Map<String, String> payeeInfo;
 | 
			
		||||
    private String alipayLogonId;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 支付宝账号名称
 | 
			
		||||
     */
 | 
			
		||||
    private String alipayAccountName;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 微信 openId
 | 
			
		||||
     */
 | 
			
		||||
    private String openid;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 微信账号名称
 | 
			
		||||
     */
 | 
			
		||||
    private String wxAccountName;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 转账状态
 | 
			
		||||
 
 | 
			
		||||
@@ -31,33 +31,35 @@ public class PayTransferDO extends BaseDO {
 | 
			
		||||
     */
 | 
			
		||||
    @TableId
 | 
			
		||||
    private Long id;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 转账单号
 | 
			
		||||
     *
 | 
			
		||||
     */
 | 
			
		||||
    private String no;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 应用编号
 | 
			
		||||
     *
 | 
			
		||||
     * 关联 {@link PayAppDO#getId()}
 | 
			
		||||
     */
 | 
			
		||||
    private Long appId;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 转账渠道编号
 | 
			
		||||
     *
 | 
			
		||||
     * 关联 {@link PayChannelDO#getId()}
 | 
			
		||||
     */
 | 
			
		||||
    private Long channelId;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 转账渠道编码
 | 
			
		||||
     *
 | 
			
		||||
     * 枚举 {@link PayChannelEnum}
 | 
			
		||||
     */
 | 
			
		||||
    private String channelCode;
 | 
			
		||||
    /**
 | 
			
		||||
     * 类型
 | 
			
		||||
     *
 | 
			
		||||
     * 枚举 {@link PayTransferTypeEnum}
 | 
			
		||||
     */
 | 
			
		||||
    private Integer type;
 | 
			
		||||
 | 
			
		||||
    // ========== 商户相关字段 ==========
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 商户订单编号
 | 
			
		||||
     *
 | 
			
		||||
@@ -65,12 +67,20 @@ public class PayTransferDO extends BaseDO {
 | 
			
		||||
     */
 | 
			
		||||
    private String merchantOrderId;
 | 
			
		||||
 | 
			
		||||
    // ========== 转账相关字段 ==========
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 类型
 | 
			
		||||
     *
 | 
			
		||||
     * 枚举 {@link PayTransferTypeEnum}
 | 
			
		||||
     */
 | 
			
		||||
    private Integer type;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 转账标题
 | 
			
		||||
     */
 | 
			
		||||
    private String subject;
 | 
			
		||||
 | 
			
		||||
    // ========== 转账相关字段 ==========
 | 
			
		||||
    /**
 | 
			
		||||
     * 转账金额,单位:分
 | 
			
		||||
     */
 | 
			
		||||
@@ -81,26 +91,70 @@ public class PayTransferDO extends BaseDO {
 | 
			
		||||
     * 枚举 {@link PayTransferStatusRespEnum}
 | 
			
		||||
     */
 | 
			
		||||
    private Integer status;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 订单转账成功时间
 | 
			
		||||
     */
 | 
			
		||||
    private LocalDateTime successTime;
 | 
			
		||||
 | 
			
		||||
    // ========== 支付宝转账相关字段 ==========
 | 
			
		||||
    /**
 | 
			
		||||
     * 转账成功的转账拓展单编号
 | 
			
		||||
     *
 | 
			
		||||
     * 关联 {@link PayTransferExtensionDO#getId()}
 | 
			
		||||
     * 支付宝登录号
 | 
			
		||||
     */
 | 
			
		||||
    private Long extensionId;
 | 
			
		||||
    private String alipayLogonId;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 转账成功的转账拓展单号
 | 
			
		||||
     *
 | 
			
		||||
     * 关联 {@link PayTransferExtensionDO#getNo()}
 | 
			
		||||
     * 支付宝账号名称
 | 
			
		||||
     */
 | 
			
		||||
    private String no;
 | 
			
		||||
    private String alipayAccountName;
 | 
			
		||||
 | 
			
		||||
    // ========== 微信转账相关字段 ==========
 | 
			
		||||
    /**
 | 
			
		||||
     * 收款人信息,不同类型和渠道不同
 | 
			
		||||
     * 微信 openId
 | 
			
		||||
     */
 | 
			
		||||
    private String openid;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 微信账号名称
 | 
			
		||||
     */
 | 
			
		||||
    private String wxAccountName;
 | 
			
		||||
 | 
			
		||||
    // ========== 其它字段 ==========
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 异步通知地址
 | 
			
		||||
     */
 | 
			
		||||
    private String notifyUrl;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 用户 IP
 | 
			
		||||
     */
 | 
			
		||||
    private String userIp;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 渠道的额外参数
 | 
			
		||||
     */
 | 
			
		||||
    @TableField(typeHandler = JacksonTypeHandler.class)
 | 
			
		||||
    private Map<String, String> payeeInfo;
 | 
			
		||||
    private Map<String, String> channelExtras;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 渠道转账单号
 | 
			
		||||
     */
 | 
			
		||||
    private String channelTransferNo;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 调用渠道的错误码
 | 
			
		||||
     */
 | 
			
		||||
    private String channelErrorCode;
 | 
			
		||||
    /**
 | 
			
		||||
     * 调用渠道的错误提示
 | 
			
		||||
     */
 | 
			
		||||
    private String channelErrorMsg;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 渠道的同步/异步通知的内容
 | 
			
		||||
     *
 | 
			
		||||
     */
 | 
			
		||||
    private String channelNotifyData;
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -1,10 +1,7 @@
 | 
			
		||||
package cn.iocoder.yudao.module.pay.service.demo;
 | 
			
		||||
 | 
			
		||||
import cn.hutool.core.map.MapUtil;
 | 
			
		||||
import cn.hutool.core.util.StrUtil;
 | 
			
		||||
import cn.iocoder.yudao.framework.pay.core.enums.transfer.PayTransferTypeEnum;
 | 
			
		||||
import cn.iocoder.yudao.module.pay.controller.admin.demo.vo.transfer.PayDemoTransferCreateReqVO;
 | 
			
		||||
import cn.iocoder.yudao.module.pay.convert.transfer.PayTransferConvert;
 | 
			
		||||
import cn.iocoder.yudao.module.pay.convert.demo.PayDemoTransferConvert;
 | 
			
		||||
import cn.iocoder.yudao.module.pay.dal.dataobject.demo.PayDemoTransferDO;
 | 
			
		||||
import cn.iocoder.yudao.module.pay.dal.mysql.demo.PayDemoTransferMapper;
 | 
			
		||||
import cn.iocoder.yudao.module.pay.service.transfer.PayTransferService;
 | 
			
		||||
@@ -14,12 +11,8 @@ import org.springframework.validation.annotation.Validated;
 | 
			
		||||
 | 
			
		||||
import javax.annotation.Resource;
 | 
			
		||||
import javax.validation.Valid;
 | 
			
		||||
import java.util.Map;
 | 
			
		||||
import javax.validation.Validator;
 | 
			
		||||
 | 
			
		||||
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
 | 
			
		||||
import static cn.iocoder.yudao.framework.pay.core.enums.transfer.PayTransferTypeEnum.*;
 | 
			
		||||
import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.PAY_TRANSFER_ALIPAY_ACCOUNT_NAME_IS_EMPTY;
 | 
			
		||||
import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.PAY_TRANSFER_ALIPAY_LOGIN_ID_IS_EMPTY;
 | 
			
		||||
import static cn.iocoder.yudao.module.pay.enums.transfer.PayTransferStatusEnum.WAITING;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
@@ -41,49 +34,18 @@ public class PayDemoTransferServiceImpl implements PayDemoTransferService {
 | 
			
		||||
    private PayDemoTransferMapper demoTransferMapper;
 | 
			
		||||
    @Resource
 | 
			
		||||
    private PayTransferService transferService;
 | 
			
		||||
    @Resource
 | 
			
		||||
    private Validator validator;
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    @Transactional(rollbackFor = Exception.class)
 | 
			
		||||
    public Long createDemoTransfer(Long userId, @Valid PayDemoTransferCreateReqVO vo) {
 | 
			
		||||
        // 1 校验收款账号
 | 
			
		||||
        validatePayeeInfo(vo.getType(), vo.getPayeeInfo());
 | 
			
		||||
 | 
			
		||||
        // 1 校验参数
 | 
			
		||||
        vo.validate(validator);
 | 
			
		||||
        // 2 保存示例转账业务表
 | 
			
		||||
        PayDemoTransferDO demoTransfer = new PayDemoTransferDO().setUserId(userId).setType(vo.getType())
 | 
			
		||||
                .setPrice(vo.getPrice()).setPayeeInfo(vo.getPayeeInfo())
 | 
			
		||||
                .setTransferStatus(WAITING.getStatus());
 | 
			
		||||
        PayDemoTransferDO demoTransfer = PayDemoTransferConvert.INSTANCE.convert(vo)
 | 
			
		||||
                .setUserId(userId).setTransferStatus(WAITING.getStatus());
 | 
			
		||||
        demoTransferMapper.insert(demoTransfer);
 | 
			
		||||
 | 
			
		||||
        // 3.1 创建转账单
 | 
			
		||||
        Long transferId = transferService.createTransfer(PayTransferConvert.INSTANCE.convert(vo)
 | 
			
		||||
                .setAppId(TRANSFER_APP_ID).setTitle("示例转账")
 | 
			
		||||
                .setMerchantOrderId(String.valueOf(demoTransfer.getId())));
 | 
			
		||||
        // 3.2 更新转账单编号
 | 
			
		||||
        demoTransferMapper.updateById(new PayDemoTransferDO().setId(demoTransfer.getId())
 | 
			
		||||
                .setPayTransferId(transferId));
 | 
			
		||||
        return demoTransfer.getId();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // TODO @jason:可以参考 AppBrokerageWithdrawCreateReqVO 搞下字段哈,进行校验
 | 
			
		||||
    // @jason payeeinfo 字段确定改一下
 | 
			
		||||
    private void validatePayeeInfo(Integer transferType, Map<String, String> payeeInfo) {
 | 
			
		||||
        PayTransferTypeEnum transferTypeEnum = typeOf(transferType);
 | 
			
		||||
        switch (transferTypeEnum) {
 | 
			
		||||
            case ALIPAY_BALANCE: {
 | 
			
		||||
                if (StrUtil.isEmpty(MapUtil.getStr(payeeInfo, ALIPAY_LOGON_ID))) {
 | 
			
		||||
                    throw exception(PAY_TRANSFER_ALIPAY_LOGIN_ID_IS_EMPTY);
 | 
			
		||||
                }
 | 
			
		||||
                if (StrUtil.isEmpty(MapUtil.getStr(payeeInfo, ALIPAY_ACCOUNT_NAME))) {
 | 
			
		||||
                    throw exception(PAY_TRANSFER_ALIPAY_ACCOUNT_NAME_IS_EMPTY);
 | 
			
		||||
                }
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
            case WX_BALANCE:
 | 
			
		||||
            case BANK_CARD:
 | 
			
		||||
            case WALLET_BALANCE: {
 | 
			
		||||
                throw new UnsupportedOperationException("待实现");
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -28,7 +28,6 @@ import org.springframework.stereotype.Service;
 | 
			
		||||
import org.springframework.transaction.annotation.Transactional;
 | 
			
		||||
 | 
			
		||||
import javax.annotation.Resource;
 | 
			
		||||
import java.util.Objects;
 | 
			
		||||
 | 
			
		||||
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
 | 
			
		||||
import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.*;
 | 
			
		||||
@@ -80,7 +79,7 @@ public class PayTransferServiceImpl implements PayTransferService {
 | 
			
		||||
        PayTransferUnifiedReqDTO transferUnifiedReq = new PayTransferUnifiedReqDTO()
 | 
			
		||||
                .setOutTransferNo(transferExtension.getNo()).setPrice(transfer.getPrice())
 | 
			
		||||
                .setType(transfer.getType()).setTitle(transfer.getSubject())
 | 
			
		||||
                .setPayeeInfo(transfer.getPayeeInfo()).setUserIp(userIp)
 | 
			
		||||
                .setUserIp(userIp)
 | 
			
		||||
                .setChannelExtras(reqVO.getChannelExtras());
 | 
			
		||||
        PayTransferRespDTO unifiedTransferResp = client.unifiedTransfer(transferUnifiedReq);
 | 
			
		||||
 | 
			
		||||
@@ -139,10 +138,7 @@ public class PayTransferServiceImpl implements PayTransferService {
 | 
			
		||||
        if (transfer == null) {
 | 
			
		||||
            throw exception(PAY_TRANSFER_NOT_FOUND);
 | 
			
		||||
        }
 | 
			
		||||
        if (isSuccess(transfer.getStatus()) && Objects.equals(transfer.getExtensionId(), transferExtension.getId())) {
 | 
			
		||||
            log.info("[updateTransferSuccess][transfer({}) 已经是已转账,无需更新]", transfer.getId());
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (!isPendingStatus(transfer.getStatus())) {
 | 
			
		||||
            throw exception(PAY_TRANSFER_STATUS_IS_NOT_PENDING);
 | 
			
		||||
        }
 | 
			
		||||
@@ -151,7 +147,7 @@ public class PayTransferServiceImpl implements PayTransferService {
 | 
			
		||||
                CollUtil.newArrayList(WAITING.getStatus(), IN_PROGRESS.getStatus()),
 | 
			
		||||
                new PayTransferDO().setStatus(SUCCESS.getStatus()).setSuccessTime(notify.getSuccessTime())
 | 
			
		||||
                        .setChannelId(channel.getId()).setChannelCode(channel.getCode())
 | 
			
		||||
                        .setExtensionId(transferExtension.getId()).setNo(transferExtension.getNo()));
 | 
			
		||||
                        .setNo(transferExtension.getNo()));
 | 
			
		||||
        if (updateCounts == 0) {
 | 
			
		||||
            throw exception(PAY_TRANSFER_STATUS_IS_NOT_PENDING);
 | 
			
		||||
        }
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user