Merge remote-tracking branch 'origin/master'

This commit is contained in:
Rex 2023-02-14 21:33:34 +08:00
commit 3d8d34671f
9 changed files with 382 additions and 1 deletions

View File

@ -0,0 +1,44 @@
package cn.iocoder.yudao.module.pay.controller.admin.demo;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.pay.controller.admin.demo.vo.PayDemoOrderCreateReqVO;
import cn.iocoder.yudao.module.pay.controller.admin.demo.vo.PayDemoOrderRespVO;
import cn.iocoder.yudao.module.pay.convert.demo.PayDemoOrderConvert;
import cn.iocoder.yudao.module.pay.dal.dataobject.demo.PayDemoOrderDO;
import cn.iocoder.yudao.module.pay.service.demo.PayDemoOrderService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.validation.Valid;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
@Tag(name = "管理后台 - 示例订单")
@RestController
@RequestMapping("/pay/demo-order")
@Validated
public class PayDemoOrderController {
@Resource
private PayDemoOrderService payDemoOrderService;
@PostMapping("/create")
@Operation(summary = "创建示例订单")
public CommonResult<Long> createDemoOrder(@Valid @RequestBody PayDemoOrderCreateReqVO createReqVO) {
return success(payDemoOrderService.createDemoOrder(getLoginUserId(), createReqVO));
}
@GetMapping("/page")
@Operation(summary = "获得示例订单分页")
public CommonResult<PageResult<PayDemoOrderRespVO>> getDemoOrderPage(@Valid PageParam pageVO) {
PageResult<PayDemoOrderDO> pageResult = payDemoOrderService.getDemoOrderPage(pageVO);
return success(PayDemoOrderConvert.INSTANCE.convertPage(pageResult));
}
}

View File

@ -0,0 +1,17 @@
package cn.iocoder.yudao.module.pay.controller.admin.demo.vo;
import lombok.*;
import io.swagger.v3.oas.annotations.media.Schema;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
@Schema(description = "管理后台 - 示例订单创建 Request VO")
@Data
public class PayDemoOrderCreateReqVO {
@Schema(description = "商品编号", required = true, example = "17682")
@NotNull(message = "商品编号不能为空")
private Long spuId;
}

View File

@ -0,0 +1,42 @@
package cn.iocoder.yudao.module.pay.controller.admin.demo.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*;
import java.time.LocalDateTime;
/**
* 示例订单 Base VO提供给添加修改详细的子 VO 使用
* 如果子 VO 存在差异的字段请不要添加到这里影响 Swagger 文档生成
*/
@Data
public class PayDemoOrderRespVO {
@Schema(description = "用户编号", required = true, example = "23199")
private Long userId;
@Schema(description = "商品编号", required = true, example = "17682")
private Long spuId;
@Schema(description = "商家备注", example = "李四")
private String spuName;
@Schema(description = "价格,单位:分", required = true, example = "30381")
private Integer price;
@Schema(description = "是否已支付", required = true)
private Boolean payed;
@Schema(description = "支付订单编号", example = "16863")
private Long payOrderId;
@Schema(description = "订单支付时间")
private LocalDateTime payTime;
@Schema(description = "退款金额,单位:分", required = true, example = "14039")
private Integer refundPrice;
@Schema(description = "退款时间")
private LocalDateTime refundTime;
}

View File

@ -1 +0,0 @@
package cn.iocoder.yudao.module.pay.controller.app;

View File

@ -0,0 +1,26 @@
package cn.iocoder.yudao.module.pay.convert.demo;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.pay.controller.admin.demo.vo.PayDemoOrderCreateReqVO;
import cn.iocoder.yudao.module.pay.controller.admin.demo.vo.PayDemoOrderRespVO;
import cn.iocoder.yudao.module.pay.dal.dataobject.demo.PayDemoOrderDO;
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;
/**
* 示例订单 Convert
*
* @author 芋道源码
*/
@Mapper
public interface PayDemoOrderConvert {
PayDemoOrderConvert INSTANCE = Mappers.getMapper(PayDemoOrderConvert.class);
PayDemoOrderDO convert(PayDemoOrderCreateReqVO bean);
PayDemoOrderRespVO convert(PayDemoOrderDO bean);
PageResult<PayDemoOrderRespVO> convertPage(PageResult<PayDemoOrderDO> page);
}

View File

@ -0,0 +1,86 @@
package cn.iocoder.yudao.module.pay.dal.dataobject.demo;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
import com.baomidou.mybatisplus.annotation.KeySequence;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.*;
import java.time.LocalDateTime;
import java.util.Date;
/**
* 示例订单
*
* 演示业务系统的订单如何接入 pay 系统的支付与退款
*
* @author 芋道源码
*/
@TableName("pay_demo_order")
@KeySequence("pay_demo_order_seq") // 用于 OraclePostgreSQLKingbaseDB2H2 数据库的主键自增如果是 MySQL 等数据库可不写
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class PayDemoOrderDO extends BaseDO {
/**
* 订单编号自增
*/
@TableId
private Long id;
/**
* 用户编号
*/
private Long userId;
/**
* 商品编号
*/
private Long spuId;
/**
* 商品名称
*/
private String spuName;
/**
* 价格单位
*/
private Integer price;
// ========== 支付相关字段 ==========
/**
* 是否支付
*/
private Boolean payed;
/**
* 支付订单编号
*
* 对接 pay-module-biz 支付服务的支付订单编号 PayOrderDO id 编号
*/
private Long payOrderId;
/**
* 付款时间
*/
private LocalDateTime payTime;
/**
* 支付渠道
*
* 对应 PayChannelEnum 枚举
*/
private String payChannelCode;
// ========== 退款相关字段 ==========
/**
* 退款金额
*/
private Integer refundPrice;
/**
* 退款时间
*
* 由于可以多次退款记录最后一次退款的时间
*/
private Date refundTime;
}

View File

@ -0,0 +1,23 @@
package cn.iocoder.yudao.module.pay.dal.mysql.demo;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
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.dal.dataobject.demo.PayDemoOrderDO;
import org.apache.ibatis.annotations.Mapper;
/**
* 示例订单 Mapper
*
* @author 芋道源码
*/
@Mapper
public interface PayDemoOrderMapper extends BaseMapperX<PayDemoOrderDO> {
default PageResult<PayDemoOrderDO> selectPage(PageParam reqVO) {
return selectPage(reqVO, new LambdaQueryWrapperX<PayDemoOrderDO>()
.orderByDesc(PayDemoOrderDO::getId));
}
}

View File

@ -0,0 +1,42 @@
package cn.iocoder.yudao.module.pay.service.demo;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.pay.controller.admin.demo.vo.PayDemoOrderCreateReqVO;
import cn.iocoder.yudao.module.pay.dal.dataobject.demo.PayDemoOrderDO;
import javax.validation.Valid;
/**
* 示例订单 Service 接口
*
* @author 芋道源码
*/
public interface PayDemoOrderService {
/**
* 创建示例订单
*
* @param userId 用户编号
* @param createReqVO 创建信息
* @return 编号
*/
Long createDemoOrder(Long userId, @Valid PayDemoOrderCreateReqVO createReqVO);
/**
* 获得示例订单
*
* @param id 编号
* @return 示例订单
*/
PayDemoOrderDO getDemoOrder(Long id);
/**
* 获得示例订单分页
*
* @param pageReqVO 分页查询
* @return 示例订单分页
*/
PageResult<PayDemoOrderDO> getDemoOrderPage(PageParam pageReqVO);
}

View File

@ -0,0 +1,102 @@
package cn.iocoder.yudao.module.pay.service.demo;
import cn.hutool.core.lang.Assert;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.pay.api.order.PayOrderApi;
import cn.iocoder.yudao.module.pay.api.order.dto.PayOrderCreateReqDTO;
import cn.iocoder.yudao.module.pay.controller.admin.demo.vo.PayDemoOrderCreateReqVO;
import cn.iocoder.yudao.module.pay.dal.dataobject.demo.PayDemoOrderDO;
import cn.iocoder.yudao.module.pay.dal.mysql.demo.PayDemoOrderMapper;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;
import javax.annotation.Resource;
import java.time.Duration;
import java.util.HashMap;
import java.util.Map;
import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.addTime;
import static cn.iocoder.yudao.framework.common.util.servlet.ServletUtils.getClientIP;
/**
* 示例订单 Service 实现类
*
* @author 芋道源码
*/
@Service
@Validated
public class PayDemoOrderServiceImpl implements PayDemoOrderService {
/**
* 接入的实力应用编号
*
* [支付管理 -> 应用信息] 里添加
*/
private static final Long PAY_APP_ID = 7L;
/**
* 商品信息 Map
*
* key商品编号
* value[商品名商品价格]
*/
private final Map<Long, Object[]> spuNames = new HashMap<>();
@Resource
private PayOrderApi payOrderApi;
@Resource
private PayDemoOrderMapper payDemoOrderMapper;
public PayDemoOrderServiceImpl() {
spuNames.put(1L, new Object[]{"华为手机", 1});
spuNames.put(2L, new Object[]{"小米电视", 10});
spuNames.put(3L, new Object[]{"苹果手表", 100});
spuNames.put(4L, new Object[]{"华硕笔记本", 200});
spuNames.put(5L, new Object[]{"蔚来汽车", 300});
}
@Override
public Long createDemoOrder(Long userId, PayDemoOrderCreateReqVO createReqVO) {
// 1.1 获得商品
Object[] spu = spuNames.get(createReqVO.getSpuId());
Assert.notNull(spu, "商品({}) 不存在", createReqVO.getSpuId());
String spuName = (String) spu[0];
Integer price = (Integer) spu[1];
// 1.2 插入 demo 订单
PayDemoOrderDO demoOrder = new PayDemoOrderDO().setUserId(userId)
.setSpuId(createReqVO.getSpuId()).setSpuName(spuName)
.setPayed(false).setRefundPrice(0);
payDemoOrderMapper.insert(demoOrder);
// 2.1 创建支付单
Long payOrderId = payOrderApi.createOrder(new PayOrderCreateReqDTO()
.setAppId(PAY_APP_ID).setUserIp(getClientIP()) // 支付应用
.setMerchantOrderId(demoOrder.getId().toString()) // 业务的订单编号
.setSubject(spuName).setBody("").setAmount(price) // 价格信息
.setExpireTime(addTime(Duration.ofHours(2L)))); // 支付的过期时间
// 2.2 更新支付单到 demo 订单
payDemoOrderMapper.updateById(new PayDemoOrderDO().setId(demoOrder.getId())
.setPayOrderId(payOrderId));
// 返回
return demoOrder.getId();
}
// private void validateDemoOrderExists(Long id) {
// if (demoOrderMapper.selectById(id) == null) {
// throw exception(DEMO_ORDER_NOT_EXISTS);
// }
// }
@Override
public PayDemoOrderDO getDemoOrder(Long id) {
return payDemoOrderMapper.selectById(id);
}
@Override
public PageResult<PayDemoOrderDO> getDemoOrderPage(PageParam pageReqVO) {
return payDemoOrderMapper.selectPage(pageReqVO);
}
}