ref 简版设备终端管理

This commit is contained in:
daxpay
2025-05-07 14:58:20 +08:00
parent df7bb4a0db
commit a9153aa61a
13 changed files with 646 additions and 71 deletions

View File

@@ -0,0 +1,85 @@
package org.dromara.daxpay.controller.assist;
import cn.bootx.platform.core.annotation.RequestGroup;
import cn.bootx.platform.core.annotation.RequestPath;
import cn.bootx.platform.core.rest.Res;
import cn.bootx.platform.core.rest.dto.LabelValue;
import cn.bootx.platform.core.rest.param.PageParam;
import cn.bootx.platform.core.rest.result.PageResult;
import cn.bootx.platform.core.rest.result.Result;
import cn.bootx.platform.core.validation.ValidationGroup;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.constraints.NotNull;
import lombok.RequiredArgsConstructor;
import org.dromara.core.trans.anno.TransMethodResult;
import org.dromara.daxpay.service.param.termina.TerminalDeviceParam;
import org.dromara.daxpay.service.param.termina.TerminalDeviceQuery;
import org.dromara.daxpay.service.result.termina.TerminalDeviceResult;
import org.dromara.daxpay.service.service.assist.TerminalDeviceService;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* 支付终端设备
* @author xxm
* @since 2025/3/9
*/
@Validated
@Tag(name = "支付终端设备管理")
@RestController
@RequestMapping("/terminal/device")
@RequestGroup(groupCode = "TerminalDevice", groupName = "支付终端设备管理", moduleCode = "PayConfig")
@RequiredArgsConstructor
public class TerminalDeviceController {
private final TerminalDeviceService terminalDeviceService;
@TransMethodResult
@RequestPath("分页查询")
@Operation(summary = "分页查询")
@GetMapping("/page")
public Result<PageResult<TerminalDeviceResult>> page(PageParam pageParam, TerminalDeviceQuery query){
return Res.ok(terminalDeviceService.page(pageParam, query));
}
@TransMethodResult
@RequestPath("根据ID查询")
@Operation(summary = "根据ID查询")
@GetMapping("/findById")
public Result<TerminalDeviceResult> findById(@NotNull(message = "支付终端设备id不能为空") Long id){
return Res.ok(terminalDeviceService.findById(id));
}
@RequestPath("新增")
@Operation(summary = "新增")
@PostMapping("/add")
public Result<Void> add(@RequestBody @Validated(ValidationGroup.add.class) TerminalDeviceParam param){
terminalDeviceService.add(param);
return Res.ok();
}
@RequestPath("修改")
@Operation(summary = "修改")
@PostMapping("/edit")
public Result<Void> edit(@RequestBody @Validated(ValidationGroup.edit.class) TerminalDeviceParam param){
terminalDeviceService.edit(param);
return Res.ok();
}
@RequestPath("删除")
@Operation(summary = "删除")
@PostMapping("/delete")
public Result<Void> delete(@NotNull(message = "支付终端设备id不能为空") Long id){
terminalDeviceService.delete(id);
return Res.ok();
}
@RequestPath("根据应用号查询下拉列表")
@Operation(summary = "根据应用号查询下拉列表")
@GetMapping("/dropdown")
public Result<List<LabelValue>> dropdown(String appId){
return Res.ok(terminalDeviceService.dropdown(appId));
}
}

View File

@@ -1,37 +1,28 @@
package org.dromara.daxpay.controller.common;
import cn.bootx.platform.core.annotation.DataPermScope;
import cn.bootx.platform.core.annotation.IgnoreAuth;
import cn.bootx.platform.core.annotation.RequestPath;
import cn.bootx.platform.core.rest.Res;
import cn.bootx.platform.core.rest.result.Result;
import cn.bootx.platform.starter.redis.delay.annotation.DelayEventListener;
import cn.bootx.platform.starter.redis.delay.annotation.DelayJobEvent;
import cn.bootx.platform.starter.redis.delay.bean.DelayJob;
import cn.bootx.platform.starter.redis.delay.service.DelayJobService;
import org.dromara.daxpay.core.result.assist.AuthResult;
import org.dromara.daxpay.service.entity.order.pay.PayOrder;
import cn.hutool.core.util.RandomUtil;
import cn.bootx.platform.starter.cache.handler.CacheClearProcessor;
import cn.bootx.platform.starter.cache.service.CacheClearService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.constraints.NotNull;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.time.LocalDateTime;
import java.util.concurrent.TimeUnit;
import java.util.List;
/**
*
* @author xxm
* @since 2024/7/4
*/
@DataPermScope("123")
@Validated
@IgnoreAuth
@Slf4j
@@ -40,49 +31,22 @@ import java.util.concurrent.TimeUnit;
@RequestMapping("/test")
@RequiredArgsConstructor
public class TestController {
private final RedisTemplate<String, Object> objectRedisTemplate;
private final DelayJobService delayJobService;
private final CacheClearProcessor cacheClearProcessor;
private final CacheClearService cacheClearService;
@Operation(summary = "测试redis")
@GetMapping("/redis")
public Result<Object> redis(){
PayOrder payOrder = new PayOrder();
payOrder.setOrderNo("123");
// redisTemplate.opsForValue().set("payOrder",new AuthResult().setStatus("123"),60000L);
objectRedisTemplate.opsForValue().set("payOrder",new AuthResult().setStatus("123"),600, TimeUnit.MILLISECONDS);
// objectRedisTemplate.opsForValue().set("payOrder",payOrder);
var payOrder1 = objectRedisTemplate.opsForValue().get("payOrder");
return Res.ok(payOrder1);
@RequestPath("查询所有缓存前缀")
@Operation(summary = "查询所有缓存前缀")
@GetMapping("/getCachePrefix")
public Result<List<String>> getCachePrefix() {
return Res.ok(cacheClearProcessor.getCachePrefix());
}
@Operation(summary = "添加测试延时任务")
@PostMapping(value = "addTest")
public Result<Void> addDefJobTest() {
for (int i = 0; i < 100; i++){
DelayJob<PayOrder> delayJob = new DelayJob<>();
delayJobService.register(delayJob, "hello", RandomUtil.randomInt(10000,90000));
delayJobService.register(delayJob, "hello", LocalDateTime.now().plusSeconds(20));
}
@RequestPath("清除指定前缀的缓存")
@Operation(summary = "清除指定前缀的缓存")
@PostMapping("/prefix")
public Result<Void> clearCacheByPrefix(List<String> prefix) {
cacheClearService.clearCacheByPrefix(prefix);
return Res.ok();
}
@DelayEventListener("hello")
public void hello(DelayJobEvent<PayOrder> event) {
if (RandomUtil.randomBoolean()){
throw new RuntimeException("测试异常");
}
log.info("接收到消息:{}",event);
}
@Operation(summary = "v1")
@PostMapping("/v1")
public void v1(@NotNull(message = "id不可为空") Long id){
log.info("v1: {}", id);
}
}

View File

@@ -0,0 +1,32 @@
package org.dromara.daxpay.core.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* 收款终端设备类型
* 字典: terminal_device_type
* @author xxm
* @since 2025/3/7
*/
@Getter
@AllArgsConstructor
public enum TerminalDeviceTypeEnum {
AUTO_COUNTER("01", "自动柜员机"),
TRADITIONAL_POS("02", "传统POS"),
MPOS("03", "mPOS"),
SMART_POS("04", "智能POS"),
FIXED_PHONE("05", "II型固定电话"),
CLOUD_SHAN_PAY("06", "云闪付终端"),
RESERVE_USE("07", "保留使用"),
PHONE_POS("08", "手机POS"),
FACE_PAY_TERMINAL("09", "刷脸付终端"),
BAR_CODE_PAY_ACCEPT_TERMINAL("10", "条码支付受理终端"),
ASSIST_ACCEPT_TERMINAL("11", "辅助受理终端"),
INDUSTRY_TERMINAL("12", "行业终端"),
MIS_TERMINAL("13", "MIS终端");
private final String code;
private final String name;
}

View File

@@ -0,0 +1,22 @@
package org.dromara.daxpay.service.convert.assist;
import org.dromara.daxpay.service.entity.assist.TerminalDevice;
import org.dromara.daxpay.service.param.termina.TerminalDeviceParam;
import org.dromara.daxpay.service.result.termina.TerminalDeviceResult;
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;
/**
* 支付终端设备转换
* @author xxm
* @since 2025/3/8
*/
@Mapper
public interface TerminalDeviceConvert {
TerminalDeviceConvert CONVERT = Mappers.getMapper(TerminalDeviceConvert.class);
TerminalDeviceResult toResult(TerminalDevice entity);
TerminalDevice toEntity(TerminalDeviceParam param);
}

View File

@@ -0,0 +1,44 @@
package org.dromara.daxpay.service.dao.assist;
import cn.bootx.platform.common.mybatisplus.impl.BaseManager;
import cn.bootx.platform.common.mybatisplus.query.generator.QueryGenerator;
import cn.bootx.platform.common.mybatisplus.util.MpUtil;
import cn.bootx.platform.core.rest.param.PageParam;
import org.dromara.daxpay.service.entity.assist.TerminalDevice;
import org.dromara.daxpay.service.param.termina.TerminalDeviceQuery;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Repository;
import java.util.Optional;
/**
* 支付终端设备管理
* @author xxm
* @since 2025/3/7
*/
@Slf4j
@Repository
@RequiredArgsConstructor
public class TerminalDeviceManager extends BaseManager<TerminalDeviceMapper, TerminalDevice> {
/**
* 分页
*/
public Page<TerminalDevice> page(PageParam pageParam, TerminalDeviceQuery query){
var mpPage = MpUtil.getMpPage(pageParam, TerminalDevice.class);
QueryWrapper<TerminalDevice> generator = QueryGenerator.generator(query);
return this.page(mpPage,generator);
}
/**
* 根据编号查询终端信息
*/
public Optional<TerminalDevice> findByNo(String terminalNo){
return this.lambdaQuery()
.eq(TerminalDevice::getTerminalNo,terminalNo)
.oneOpt();
}
}

View File

@@ -0,0 +1,14 @@
package org.dromara.daxpay.service.dao.assist;
import org.dromara.daxpay.service.entity.assist.TerminalDevice;
import com.github.yulichang.base.MPJBaseMapper;
import org.apache.ibatis.annotations.Mapper;
/**
* 支付终端设备管理
* @author xxm
* @since 2025/3/7
*/
@Mapper
public interface TerminalDeviceMapper extends MPJBaseMapper<TerminalDevice> {
}

View File

@@ -0,0 +1,97 @@
package org.dromara.daxpay.service.entity.assist;
import cn.bootx.platform.common.mybatisplus.function.ToResult;
import cn.bootx.platform.common.mybatisplus.handler.StringListTypeHandler;
import org.dromara.daxpay.core.enums.TerminalDeviceTypeEnum;
import org.dromara.daxpay.service.common.entity.MchAppBaseEntity;
import org.dromara.daxpay.service.convert.assist.TerminalDeviceConvert;
import org.dromara.daxpay.service.param.termina.TerminalDeviceParam;
import org.dromara.daxpay.service.result.termina.TerminalDeviceResult;
import com.baomidou.mybatisplus.annotation.FieldStrategy;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import java.time.LocalDate;
import java.util.List;
import java.util.Objects;
/**
* 支付终端设备管理
* @author xxm
* @since 2025/3/7
*/
@EqualsAndHashCode(callSuper = true)
@Data
@Accessors(chain = true)
@TableName(value = "pay_terminal_device",autoResultMap = true)
public class TerminalDevice extends MchAppBaseEntity implements ToResult<TerminalDeviceResult> {
/** 终端名称 */
private String name;
/** 终端编码 */
@TableField(updateStrategy = FieldStrategy.NEVER)
private String terminalNo;
/**
* 终端类型
* @see TerminalDeviceTypeEnum
*/
private String type;
/** 终端序列号 */
private String serialNum;
/** 省市区编码 */
@TableField(updateStrategy = FieldStrategy.ALWAYS, typeHandler = StringListTypeHandler.class)
private List<String> areaCode;
/** 终端发放地址 */
private String address;
/** 终端厂商名称 */
private String companyName;
/** 发放日期 */
private LocalDate putDate;
/** 支持终端定位 */
private Boolean gps;
/** 终端机具体型号 */
private String machineType;
/**
* 经度,浮点型, 小数点后最多保留6位
*/
private String longitude;
/**
* 纬度,浮点型,小数点后最多保留6位
*/
private String latitude;
/** 设备 IP 地址 */
private String ip;
/** 银行卡受理终端产品入网认证编号 */
private String networkLicense;
public Boolean getGps() {
return Objects.equals(gps, true);
}
/**
* 初始化对象
*/
public static TerminalDevice init(TerminalDeviceParam param){
return TerminalDeviceConvert.CONVERT.toEntity(param);
}
@Override
public TerminalDeviceResult toResult() {
return TerminalDeviceConvert.CONVERT.toResult(this);
}
}

View File

@@ -0,0 +1,92 @@
package org.dromara.daxpay.service.param.termina;
import cn.bootx.platform.core.validation.ValidationGroup;
import org.dromara.daxpay.core.enums.TerminalDeviceTypeEnum;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Null;
import lombok.Data;
import lombok.experimental.Accessors;
import java.time.LocalDate;
import java.util.List;
/**
* 支付终端设备参数
* @author xxm
* @since 2025/3/8
*/
@Data
@Accessors(chain = true)
@Schema(title = "支付终端设备参数")
public class TerminalDeviceParam {
/** 主键 */
@Null(message = "Id需要为空", groups = ValidationGroup.add.class)
@NotNull(message = "Id不可为空", groups = ValidationGroup.edit.class)
@Schema(description = "主键")
private Long id;
/** 终端名称 */
@Schema(description = "终端名称")
private String name;
/**
* 终端类型
* @see TerminalDeviceTypeEnum
*/
@Schema(description = "终端类型")
private String type;
/** 终端序列号 */
@Schema(description = "终端序列号")
private String serialNum;
/** 省市区编码 */
@Schema(description = "省市区编码")
private List<String> areaCode;
/** 终端发放地址 */
@Schema(description = "终端发放地址")
private String address;
/** 终端厂商名称 */
@Schema(description = "终端厂商名称")
private String companyName;
/** 发放日期 */
@Schema(description = "发放日期")
private LocalDate putDate;
/** 支持终端定位 */
@Schema(description = "支持终端定位")
private Boolean gps;
/** 终端机具型号 */
@Schema(description = "终端机具型号")
private String machineType;
/**
* 经度,浮点型, 小数点后最多保留6位
*/
@Schema(description = "经度,浮点型, 小数点后最多保留6位")
private String longitude;
/**
* 纬度,浮点型,小数点后最多保留6位
*/
@Schema(description = "纬度,浮点型,小数点后最多保留6位")
private String latitude;
/** 设备 IP 地址 */
@Schema(description = "设备 IP 地址")
private String ip;
/** 银行卡受理终端产品入网认证编号 */
@Schema(description = "银行卡受理终端产品入网认证编号")
private String networkLicense;
@NotBlank(message = "商户AppId不能为空")
@Schema(description = "商户应用AppId")
private String appId;
}

View File

@@ -0,0 +1,45 @@
package org.dromara.daxpay.service.param.termina;
import cn.bootx.platform.core.annotation.QueryParam;
import org.dromara.daxpay.core.enums.TerminalDeviceTypeEnum;
import org.dromara.daxpay.service.common.param.MchQuery;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
/**
* 支付终端查询参数
* @author xxm
* @since 2025/3/8
*/
@QueryParam(type = QueryParam.CompareTypeEnum.LIKE)
@EqualsAndHashCode(callSuper = true)
@Data
@Accessors(chain = true)
public class TerminalDeviceQuery extends MchQuery {
/** 终端名称 */
@Schema(description = "终端名称")
private String name;
/** 终端编码 */
@Schema(description = "终端编码")
private String terminalNo;
/**
* 终端类型
* @see TerminalDeviceTypeEnum
*/
@Schema(description = "终端类型")
private String type;
/** 终端序列号 */
@Schema(description = "终端序列号")
private String serialNum;
/** 终端机具型号 */
@Schema(description = "终端机具型号")
private String machineType;
}

View File

@@ -0,0 +1,85 @@
package org.dromara.daxpay.service.result.termina;
import org.dromara.daxpay.core.enums.TerminalDeviceTypeEnum;
import org.dromara.daxpay.service.common.result.MchResult;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import java.time.LocalDate;
import java.util.List;
/**
* 支付终端设备参数
* @author xxm
* @since 2025/3/8
*/
@EqualsAndHashCode(callSuper = true)
@Data
@Accessors(chain = true)
@Schema(title = "支付终端设备参数")
public class TerminalDeviceResult extends MchResult {
/** 终端名称 */
@Schema(description = "终端名称")
private String name;
/** 终端编码 */
@Schema(description = "终端编码")
private String terminalNo;
/**
* 终端类型
* @see TerminalDeviceTypeEnum
*/
@Schema(description = "终端类型")
private String type;
/** 终端序列号 */
@Schema(description = "终端序列号")
private String serialNum;
/** 省市区编码 */
@Schema(description = "省市区编码")
private List<String> areaCode;
/** 终端发放地址 */
@Schema(description = "终端发放地址")
private String address;
/** 终端厂商名称 */
@Schema(description = "终端厂商名称")
private String companyName;
/** 发放日期 */
@Schema(description = "发放日期")
private LocalDate putDate;
/** 支持终端定位 */
@Schema(description = "支持终端定位")
private Boolean gps;
/** 终端机具型号 */
@Schema(description = "终端机具型号")
private String machineType;
/**
* 经度,浮点型, 小数点后最多保留6位
*/
@Schema(description = "经度,浮点型, 小数点后最多保留6位")
private String longitude;
/**
* 纬度,浮点型,小数点后最多保留6位
*/
@Schema(description = "纬度,浮点型,小数点后最多保留6位")
private String latitude;
/** 设备 IP 地址 */
@Schema(description = "设备 IP 地址")
private String ip;
/** 银行卡受理终端产品入网认证编号 */
@Schema(description = "银行卡受理终端产品入网认证编号")
private String networkLicense;
}

View File

@@ -0,0 +1,89 @@
package org.dromara.daxpay.service.service.assist;
import cn.bootx.platform.common.mybatisplus.util.MpUtil;
import cn.bootx.platform.core.exception.DataNotExistException;
import cn.bootx.platform.core.rest.dto.LabelValue;
import cn.bootx.platform.core.rest.param.PageParam;
import cn.bootx.platform.core.rest.result.PageResult;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.core.lang.UUID;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.dromara.daxpay.service.common.entity.MchAppBaseEntity;
import org.dromara.daxpay.service.common.local.PaymentContextLocal;
import org.dromara.daxpay.service.dao.assist.TerminalDeviceManager;
import org.dromara.daxpay.service.entity.assist.TerminalDevice;
import org.dromara.daxpay.service.param.termina.TerminalDeviceParam;
import org.dromara.daxpay.service.param.termina.TerminalDeviceQuery;
import org.dromara.daxpay.service.result.termina.TerminalDeviceResult;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* 支付终端设备管理
* @author xxm
* @since 2025/3/7
*/
@Slf4j
@Service
@RequiredArgsConstructor
public class TerminalDeviceService {
private final TerminalDeviceManager terminalManager;
private final PaymentAssistService paymentAssistService;
/**
* 分页
*/
public PageResult<TerminalDeviceResult> page(PageParam pageParam, TerminalDeviceQuery query){
return MpUtil.toPageResult(terminalManager.page(pageParam, query));
}
/**
* 查询详情
*/
public TerminalDeviceResult findById(Long id){
return terminalManager.findById(id).map(TerminalDevice::toResult)
.orElseThrow(() -> new DataNotExistException("支付终端设备不存在"));
}
/**
* 添加
*/
public void add(TerminalDeviceParam param){
paymentAssistService.initMchAndApp(param.getAppId());
var mchApp = PaymentContextLocal.get().getMchAppInfo();
String uuid = UUID.fastUUID().toString(true);
TerminalDevice entity = TerminalDevice.init(param);
entity.setTerminalNo(uuid)
.setAppId(mchApp.getAppId())
.setMchNo(mchApp.getMchNo());
terminalManager.save(entity);
}
/**
* 修改
*/
public void edit(TerminalDeviceParam param){
var entity = terminalManager.findById(param.getId()).orElseThrow(() -> new DataNotExistException("支付终端设备不存在"));
BeanUtil.copyProperties(param, entity, CopyOptions.create().ignoreNullValue());
terminalManager.updateById(entity);
}
/**
* 删除
*/
public void delete(Long id){
terminalManager.deleteById(id);
}
/**
* 终端下拉列表
*/
public List<LabelValue> dropdown(String appId) {
return terminalManager.findAllByField(MchAppBaseEntity::getAppId, appId).stream()
.map(o -> new LabelValue(o.getName(), o.getTerminalNo()))
.toList();
}
}