Commit ce6f7ab1b165fe36a197aaa996965ac7f470a650

Authored by jason
1 parent aa2f6511

Pay: 新增转账示例单

sql/mysql/pay_wallet.sql
@@ -73,3 +73,81 @@ CREATE TABLE `pay_wallet_recharge` @@ -73,3 +73,81 @@ CREATE TABLE `pay_wallet_recharge`
73 PRIMARY KEY (`id`) USING BTREE 73 PRIMARY KEY (`id`) USING BTREE
74 ) ENGINE=InnoDB COMMENT='会员钱包充值'; 74 ) ENGINE=InnoDB COMMENT='会员钱包充值';
75 75
  76 +-- ----------------------------
  77 +-- 转账单表
  78 +-- ----------------------------
  79 +DROP TABLE IF EXISTS `pay_transfer`;
  80 +CREATE TABLE `pay_transfer`
  81 +(
  82 + `id` bigint NOT NULL AUTO_INCREMENT COMMENT '编号',
  83 + `type` int NOT NULL COMMENT '类型',
  84 + `app_id` bigint NOT NULL COMMENT '应用编号',
  85 + `merchant_order_id` varchar(64) NOT NULL COMMENT '商户订单编号',
  86 + `price` int NOT NULL COMMENT '转账金额,单位:分',
  87 + `title` varchar(512) NOT NULL COMMENT '转账标题',
  88 + `payee_info` varchar(512) NOT NULL COMMENT '收款人信息,不同类型和渠道不同',
  89 + `status` tinyint NOT NULL COMMENT '转账状态',
  90 + `success_time` datetime NULL COMMENT '转账成功时间',
  91 + `extension_id` bigint NULL COMMENT '转账渠道编号',
  92 + `no` varchar(64) NULL COMMENT '转账单号',
  93 + `channel_id` bigint NULL COMMENT '转账渠道编号',
  94 + `channel_code` varchar(32) NULL COMMENT '转账渠道编码',
  95 + `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '创建者',
  96 + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  97 + `updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '更新者',
  98 + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
  99 + `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
  100 + `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
  101 + PRIMARY KEY (`id`) USING BTREE
  102 +) ENGINE=InnoDB COMMENT='转账单表';
  103 +
  104 +-- ----------------------------
  105 +-- 转账扩展单
  106 +-- ----------------------------
  107 +DROP TABLE IF EXISTS `pay_transfer_extension`;
  108 +CREATE TABLE `pay_transfer_extension`
  109 +(
  110 + `id` bigint NOT NULL AUTO_INCREMENT COMMENT '编号',
  111 + `no` varchar(64) NOT NULL COMMENT '转账单号',
  112 + `transfer_id` bigint NOT NULL COMMENT '转账单编号',
  113 + `channel_id` bigint NOT NULL COMMENT '转账渠道编号',
  114 + `channel_code` varchar(32) NOT NULL COMMENT '转账渠道编码',
  115 + `channel_extras` varchar(512) NULL DEFAULT NULL COMMENT '支付渠道的额外参数',
  116 + `status` tinyint NOT NULL COMMENT '转账状态',
  117 + `channel_notify_data` varchar(4096) NULL DEFAULT NULL COMMENT '支付渠道异步通知的内容',
  118 + `creator` varchar(64) NULL DEFAULT '' COMMENT '创建者',
  119 + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  120 + `updater` varchar(64) NULL DEFAULT '' COMMENT '更新者',
  121 + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
  122 + `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
  123 + `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
  124 + PRIMARY KEY (`id`) USING BTREE
  125 +) ENGINE=InnoDB COMMENT='转账拓展单表';
  126 +
  127 +-- ----------------------------
  128 +-- Table structure for pay_demo_transfer
  129 +-- ----------------------------
  130 +DROP TABLE IF EXISTS `pay_demo_transfer`;
  131 +CREATE TABLE `pay_demo_transfer` (
  132 + `id` bigint NOT NULL AUTO_INCREMENT COMMENT '订单编号',
  133 + `user_id` bigint UNSIGNED NOT NULL COMMENT '用户编号',
  134 + `price` int NOT NULL COMMENT '转账金额,单位:分',
  135 + `type` int NOT NULL COMMENT '转账类型',
  136 + `payee_info` varchar(512) NOT NULL COMMENT '收款人信息,不同类型和渠道不同',
  137 + `transfer_status` tinyint NOT NULL DEFAULT 0 COMMENT '转账状态',
  138 + `pay_transfer_id` bigint NULL DEFAULT NULL COMMENT '转账订单编号',
  139 + `pay_channel_code` varchar(16) NULL DEFAULT NULL COMMENT '转账支付成功渠道',
  140 + `transfer_time` datetime NULL DEFAULT NULL COMMENT '转账支付时间',
  141 + `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT '' COMMENT '创建者',
  142 + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  143 + `updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT '' COMMENT '更新者',
  144 + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
  145 + `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
  146 + `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
  147 + PRIMARY KEY (`id`) USING BTREE
  148 +) ENGINE = InnoDB COMMENT = '示例业务转账订单\n';
  149 +
  150 +
  151 +ALTER TABLE `pay_channel`
  152 + MODIFY COLUMN `config` text CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '支付渠道配置' AFTER `app_id`;
  153 +
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/demo/PayDemoTransferController.java 0 → 100644
  1 +package cn.iocoder.yudao.module.pay.controller.admin.demo;
  2 +
  3 +import cn.iocoder.yudao.framework.common.pojo.CommonResult;
  4 +import cn.iocoder.yudao.module.pay.controller.admin.demo.vo.transfer.PayDemoTransferCreateReqVO;
  5 +import cn.iocoder.yudao.module.pay.service.demo.PayDemoTransferService;
  6 +import io.swagger.v3.oas.annotations.Operation;
  7 +import io.swagger.v3.oas.annotations.tags.Tag;
  8 +import org.springframework.validation.annotation.Validated;
  9 +import org.springframework.web.bind.annotation.PostMapping;
  10 +import org.springframework.web.bind.annotation.RequestBody;
  11 +import org.springframework.web.bind.annotation.RequestMapping;
  12 +import org.springframework.web.bind.annotation.RestController;
  13 +
  14 +import javax.annotation.Resource;
  15 +import javax.validation.Valid;
  16 +
  17 +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
  18 +import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
  19 +
  20 +@Tag(name = "管理后台 - 示例转账单")
  21 +@RestController
  22 +@RequestMapping("/pay/demo-transfer")
  23 +@Validated
  24 +public class PayDemoTransferController {
  25 + @Resource
  26 + private PayDemoTransferService demoTransferService;
  27 +
  28 + @PostMapping("/create")
  29 + @Operation(summary = "创建示例转账订单")
  30 + public CommonResult<Long> createDemoOrder(@Valid @RequestBody PayDemoTransferCreateReqVO createReqVO) {
  31 + return success(demoTransferService.createDemoTransfer(getLoginUserId(), createReqVO));
  32 + }
  33 +}
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/demo/vo/transfer/PayDemoTransferCreateReqVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.pay.controller.admin.demo.vo.transfer;
  2 +
  3 +import cn.iocoder.yudao.framework.common.validation.InEnum;
  4 +import cn.iocoder.yudao.framework.pay.core.enums.transfer.PayTransferTypeEnum;
  5 +import io.swagger.v3.oas.annotations.media.Schema;
  6 +import lombok.Data;
  7 +
  8 +import javax.validation.constraints.Min;
  9 +import javax.validation.constraints.NotEmpty;
  10 +import javax.validation.constraints.NotNull;
  11 +import java.util.Map;
  12 +
  13 +/**
  14 + * @author jason
  15 + */
  16 +@Schema(description = "管理后台 - 示例转账单创建 Request VO")
  17 +@Data
  18 +public class PayDemoTransferCreateReqVO {
  19 +
  20 + @Schema(description = "转账类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
  21 + @NotNull(message = "转账类型不能为空")
  22 + @InEnum(PayTransferTypeEnum.class)
  23 + private Integer transferType;
  24 +
  25 + @NotNull(message = "转账金额不能为空")
  26 + @Min(value = 1, message = "转账金额必须大于零")
  27 + private Integer price;
  28 +
  29 + @Schema(description = "收款方信息", requiredMode = Schema.RequiredMode.REQUIRED, example = "{'ALIPAY_LOGON_ID':'xxxx'}")
  30 + @NotEmpty(message = "收款方信息不能为空")
  31 + private Map<String, String> payeeInfo;
  32 +}
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/demo/PayDemoTransferDO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.pay.dal.dataobject.demo;
  2 +
  3 +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
  4 +import com.baomidou.mybatisplus.annotation.KeySequence;
  5 +import com.baomidou.mybatisplus.annotation.TableField;
  6 +import com.baomidou.mybatisplus.annotation.TableId;
  7 +import com.baomidou.mybatisplus.annotation.TableName;
  8 +import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
  9 +import lombok.Data;
  10 +
  11 +import java.time.LocalDateTime;
  12 +import java.util.Map;
  13 +
  14 +/**
  15 + * 示例转账订单
  16 + *
  17 + * 演示业务系统的转账业务
  18 + */
  19 +@TableName(value ="pay_demo_transfer", autoResultMap = true)
  20 +@KeySequence("pay_demo_transfer_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
  21 +@Data
  22 +public class PayDemoTransferDO extends BaseDO {
  23 + /**
  24 + * 订单编号
  25 + */
  26 + @TableId
  27 + private Long id;
  28 +
  29 + /**
  30 + * 用户编号
  31 + */
  32 + private Long userId;
  33 +
  34 + /**
  35 + * 转账金额,单位:分
  36 + */
  37 + private Integer price;
  38 +
  39 + /**
  40 + * 转账类型
  41 + */
  42 + private Integer type;
  43 +
  44 + /**
  45 + * 收款人信息,不同类型和渠道不同
  46 + */
  47 + @TableField(typeHandler = JacksonTypeHandler.class)
  48 + private Map<String, String> payeeInfo;
  49 +
  50 + /**
  51 + * 转账状态
  52 + */
  53 + private Integer transferStatus;
  54 +
  55 + /**
  56 + * 转账订单编号
  57 + */
  58 + private Long payTransferId;
  59 +
  60 + /**
  61 + * 转账支付成功渠道
  62 + */
  63 + private String payChannelCode;
  64 +
  65 + /**
  66 + * 转账支付时间
  67 + */
  68 + private LocalDateTime transferTime;
  69 +}
0 \ No newline at end of file 70 \ No newline at end of file
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/mysql/demo/PayDemoTransferMapper.java 0 → 100644
  1 +package cn.iocoder.yudao.module.pay.dal.mysql.demo;
  2 +
  3 +import cn.iocoder.yudao.module.pay.dal.dataobject.demo.PayDemoTransferDO;
  4 +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
  5 +import org.apache.ibatis.annotations.Mapper;
  6 +
  7 +@Mapper
  8 +public interface PayDemoTransferMapper extends BaseMapperX<PayDemoTransferDO> {
  9 +
  10 +}
  11 +
  12 +
  13 +
  14 +
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/demo/PayDemoTransferService.java 0 → 100644
  1 +package cn.iocoder.yudao.module.pay.service.demo;
  2 +
  3 +import cn.iocoder.yudao.module.pay.controller.admin.demo.vo.transfer.PayDemoTransferCreateReqVO;
  4 +
  5 +import javax.validation.Valid;
  6 +
  7 +/**
  8 + * 示例转账业务 Service 接口
  9 + *
  10 + * @author jason
  11 + */
  12 +public interface PayDemoTransferService {
  13 +
  14 + /**
  15 + * 创建转账单
  16 + *
  17 + * @param userId 用户编号
  18 + * @param createReqVO 创建信息
  19 + * @return 编号
  20 + */
  21 + Long createDemoTransfer(Long userId, @Valid PayDemoTransferCreateReqVO createReqVO);
  22 +}
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/demo/PayDemoTransferServiceImpl.java 0 → 100644
  1 +package cn.iocoder.yudao.module.pay.service.demo;
  2 +
  3 +import cn.hutool.core.map.MapUtil;
  4 +import cn.hutool.core.util.StrUtil;
  5 +import cn.iocoder.yudao.framework.pay.core.enums.transfer.PayTransferTypeEnum;
  6 +import cn.iocoder.yudao.module.pay.controller.admin.demo.vo.transfer.PayDemoTransferCreateReqVO;
  7 +import cn.iocoder.yudao.module.pay.convert.transfer.PayTransferConvert;
  8 +import cn.iocoder.yudao.module.pay.dal.dataobject.demo.PayDemoTransferDO;
  9 +import cn.iocoder.yudao.module.pay.dal.mysql.demo.PayDemoTransferMapper;
  10 +import cn.iocoder.yudao.module.pay.service.transfer.PayTransferService;
  11 +import org.springframework.stereotype.Service;
  12 +import org.springframework.transaction.annotation.Transactional;
  13 +import org.springframework.validation.annotation.Validated;
  14 +
  15 +import javax.annotation.Resource;
  16 +import javax.validation.Valid;
  17 +import java.util.Map;
  18 +
  19 +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
  20 +import static cn.iocoder.yudao.framework.pay.core.enums.transfer.PayTransferTypeEnum.*;
  21 +import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.PAY_TRANSFER_ALIPAY_ACCOUNT_NAME_IS_EMPTY;
  22 +import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.PAY_TRANSFER_ALIPAY_LOGIN_ID_IS_EMPTY;
  23 +import static cn.iocoder.yudao.module.pay.enums.transfer.PayTransferStatusEnum.WAITING;
  24 +
  25 +/**
  26 + * 示例转账业务 Service 实现类
  27 + *
  28 + * @author jason
  29 + */
  30 +@Service
  31 +@Validated
  32 +public class PayDemoTransferServiceImpl implements PayDemoTransferService {
  33 +
  34 + /**
  35 + * 接入的实力应用编号
  36 +
  37 + * 从 [支付管理 -> 应用信息] 里添加
  38 + */
  39 + private static final Long TRANSFER_APP_ID = 8L;
  40 + @Resource
  41 + private PayDemoTransferMapper demoTransferMapper;
  42 + @Resource
  43 + private PayTransferService transferService;
  44 +
  45 + @Override
  46 + @Transactional(rollbackFor = Exception.class)
  47 + public Long createDemoTransfer(Long userId, @Valid PayDemoTransferCreateReqVO vo) {
  48 + // 1 校验收款账号
  49 + validatePayeeInfo(vo.getTransferType(), vo.getPayeeInfo());
  50 +
  51 + // 2 保存示例转账业务表
  52 + PayDemoTransferDO demoTransfer = new PayDemoTransferDO().setUserId(userId).setType(vo.getTransferType())
  53 + .setPrice(vo.getPrice()).setPayeeInfo(vo.getPayeeInfo())
  54 + .setTransferStatus(WAITING.getStatus());
  55 + demoTransferMapper.insert(demoTransfer);
  56 +
  57 + // 3.1 创建转账单
  58 + Long transferId = transferService.createTransfer(PayTransferConvert.INSTANCE.convert(vo)
  59 + .setAppId(TRANSFER_APP_ID).setTitle("示例转账")
  60 + .setMerchantOrderId(String.valueOf(demoTransfer.getId())));
  61 + // 3.2 更新转账单编号
  62 + demoTransferMapper.updateById(new PayDemoTransferDO().setId(demoTransfer.getId())
  63 + .setPayTransferId(transferId));
  64 + return demoTransfer.getId();
  65 + }
  66 +
  67 + private void validatePayeeInfo(Integer transferType, Map<String, String> payeeInfo) {
  68 + PayTransferTypeEnum transferTypeEnum = ofType(transferType);
  69 + switch (transferTypeEnum) {
  70 + case ALIPAY_BALANCE: {
  71 + if (StrUtil.isEmpty(MapUtil.getStr(payeeInfo, ALIPAY_LOGON_ID))) {
  72 + throw exception(PAY_TRANSFER_ALIPAY_LOGIN_ID_IS_EMPTY);
  73 + }
  74 + if (StrUtil.isEmpty(MapUtil.getStr(payeeInfo, ALIPAY_ACCOUNT_NAME))) {
  75 + throw exception(PAY_TRANSFER_ALIPAY_ACCOUNT_NAME_IS_EMPTY);
  76 + }
  77 + break;
  78 + }
  79 + case WX_BALANCE:
  80 + case BANK_CARD:
  81 + case WALLET_BALANCE: {
  82 + throw new UnsupportedOperationException("待实现");
  83 + }
  84 + }
  85 + }
  86 +}