完成支付模块支付应用信息和微信类型的支付渠道配置。

This commit is contained in:
aquan
2021-11-09 16:36:07 +08:00
parent 6265e4a736
commit e46a27b937
56 changed files with 3373 additions and 28 deletions

View File

@ -0,0 +1,175 @@
package cn.iocoder.yudao.adminserver.modules.pay.controller.app;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.adminserver.modules.pay.controller.app.vo.*;
import cn.iocoder.yudao.adminserver.modules.pay.convert.app.PayAppConvert;
import cn.iocoder.yudao.adminserver.modules.pay.service.app.PayAppService;
import cn.iocoder.yudao.adminserver.modules.pay.service.channel.PayChannelService;
import cn.iocoder.yudao.adminserver.modules.pay.service.merchant.PayMerchantService;
import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayAppDO;
import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayChannelDO;
import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayMerchantDO;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT;
/**
* 支付应用信息 controller 组件
*
* @author aquan
*/
@Slf4j
@Api(tags = "支付应用信息")
@RestController
@RequestMapping("/pay/app")
@Validated
public class PayAppController {
@Resource
private PayAppService appService;
@Resource
private PayChannelService channelService;
@Resource
private PayMerchantService merchantService;
@PostMapping("/create")
@ApiOperation("创建支付应用信息")
@PreAuthorize("@ss.hasPermission('pay:app:create')")
public CommonResult<Long> createApp(@Valid @RequestBody PayAppCreateReqVO createReqVO) {
return success(appService.createApp(createReqVO));
}
@PutMapping("/update")
@ApiOperation("更新支付应用信息")
@PreAuthorize("@ss.hasPermission('pay:app:update')")
public CommonResult<Boolean> updateApp(@Valid @RequestBody PayAppUpdateReqVO updateReqVO) {
appService.updateApp(updateReqVO);
return success(true);
}
@PutMapping("/update-status")
@ApiOperation("更新支付应用状态")
@PreAuthorize("@ss.hasPermission('pay:app:update')")
public CommonResult<Boolean> updateAppStatus(@Valid @RequestBody PayAppUpdateStatusReqVO updateReqVO) {
appService.updateAppStatus(updateReqVO.getId(), updateReqVO.getStatus());
return success(true);
}
@DeleteMapping("/delete")
@ApiOperation("删除支付应用信息")
@ApiImplicitParam(name = "id", value = "编号", required = true)
@PreAuthorize("@ss.hasPermission('pay:app:delete')")
public CommonResult<Boolean> deleteApp(@RequestParam("id") Long id) {
appService.deleteApp(id);
return success(true);
}
@GetMapping("/get")
@ApiOperation("获得支付应用信息")
@ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class)
@PreAuthorize("@ss.hasPermission('pay:app:query')")
public CommonResult<PayAppRespVO> getApp(@RequestParam("id") Long id) {
PayAppDO app = appService.getApp(id);
return success(PayAppConvert.INSTANCE.convert(app));
}
@GetMapping("/list")
@ApiOperation("获得支付应用信息列表")
@ApiImplicitParam(name = "ids", value = "编号列表", required = true, example = "1024,2048", dataTypeClass = List.class)
@PreAuthorize("@ss.hasPermission('pay:app:query')")
public CommonResult<List<PayAppRespVO>> getAppList(@RequestParam("ids") Collection<Long> ids) {
List<PayAppDO> list = appService.getAppList(ids);
return success(PayAppConvert.INSTANCE.convertList(list));
}
@GetMapping("/page")
@ApiOperation("获得支付应用信息分页")
@PreAuthorize("@ss.hasPermission('pay:app:query')")
public CommonResult<PageResult<PayAppPageItemRespVO>> getAppPage(@Valid PayAppPageReqVO pageVO) {
// 得到应用分页列表
PageResult<PayAppDO> pageResult = appService.getAppPage(pageVO);
if (CollUtil.isEmpty(pageResult.getList())) {
return success(new PageResult<>(pageResult.getTotal()));
}
// 得到所有的应用编号,查出所有的通道
Collection<Long> payAppIds = CollectionUtils.convertList(pageResult.getList(), PayAppDO::getId);
List<PayChannelDO> channels = channelService.getSimpleChannels(payAppIds);
// 得到所有的商户信息
Collection<Long> merchantIds = CollectionUtils.convertList(pageResult.getList(), PayAppDO::getMerchantId);
Map<Long, PayMerchantDO> deptMap = merchantService.getMerchantMap(merchantIds);
// 利用反射将通道数据复制到返回的数据结构中去
List<PayAppPageItemRespVO> appList = new ArrayList<>(pageResult.getList().size());
pageResult.getList().forEach(app -> {
// 写入应用信息的数据
PayAppPageItemRespVO respVO = PayAppConvert.INSTANCE.pageConvert(app);
// 写入商户的数据
respVO.setPayMerchant(PayAppConvert.INSTANCE.convert(deptMap.get(app.getMerchantId())));
// 写入支付渠道信息的数据
PayAppPageItemRespVO.PayChannel payChannel = new PayAppPageItemRespVO.PayChannel();
channels.forEach(c -> {
if (c.getAppId().equals(app.getId())) {
// 获取 set 方法
String methodName = StrUtil.toCamelCase("set_" + c.getCode());
try {
// 根据 set 方法将值写入
payChannel.getClass().getMethod(methodName, Integer.class)
.invoke(payChannel, CommonStatusEnum.ENABLE.getStatus());
} catch (IllegalAccessException | NoSuchMethodException | InvocationTargetException e) {
log.error("[getAppPage]调用方法[{}]设置参数[{}]异常", c.getCode(), methodName);
}
}
});
respVO.setPayChannel(payChannel);
appList.add(respVO);
});
return success(new PageResult<>(appList, pageResult.getTotal()));
}
@GetMapping("/export-excel")
@ApiOperation("导出支付应用信息 Excel")
@PreAuthorize("@ss.hasPermission('pay:app:export')")
@OperateLog(type = EXPORT)
public void exportAppExcel(@Valid PayAppExportReqVO exportReqVO,
HttpServletResponse response) throws IOException {
List<PayAppDO> list = appService.getAppList(exportReqVO);
// 导出 Excel
List<PayAppExcelVO> datas = PayAppConvert.INSTANCE.convertList02(list);
ExcelUtils.write(response, "支付应用信息.xls", "数据", PayAppExcelVO.class, datas);
}
}

View File

@ -0,0 +1,37 @@
package cn.iocoder.yudao.adminserver.modules.pay.controller.app.vo;
import lombok.*;
import io.swagger.annotations.*;
import javax.validation.constraints.*;
/**
* 支付应用信息 Base VO提供给添加、修改、详细的子 VO 使用
* 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成
*/
@Data
public class PayAppBaseVO {
@ApiModelProperty(value = "应用名", required = true)
@NotNull(message = "应用名不能为空")
private String name;
@ApiModelProperty(value = "开启状态", required = true)
@NotNull(message = "开启状态不能为空")
private Integer status;
@ApiModelProperty(value = "备注")
private String remark;
@ApiModelProperty(value = "支付结果的回调地址", required = true)
@NotNull(message = "支付结果的回调地址不能为空")
private String payNotifyUrl;
@ApiModelProperty(value = "退款结果的回调地址", required = true)
@NotNull(message = "退款结果的回调地址不能为空")
private String refundNotifyUrl;
@ApiModelProperty(value = "商户编号", required = true)
@NotNull(message = "商户编号不能为空")
private Long merchantId;
}

View File

@ -0,0 +1,14 @@
package cn.iocoder.yudao.adminserver.modules.pay.controller.app.vo;
import lombok.*;
import java.util.*;
import io.swagger.annotations.*;
import javax.validation.constraints.*;
@ApiModel("支付应用信息创建 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class PayAppCreateReqVO extends PayAppBaseVO {
}

View File

@ -0,0 +1,41 @@
package cn.iocoder.yudao.adminserver.modules.pay.controller.app.vo;
import lombok.*;
import java.util.*;
import io.swagger.annotations.*;
import com.alibaba.excel.annotation.ExcelProperty;
/**
* 支付应用信息 Excel VO
*
* @author 芋艿
*/
@Data
public class PayAppExcelVO {
@ExcelProperty("应用编号")
private Long id;
@ExcelProperty("应用名")
private String name;
@ExcelProperty("开启状态")
private Integer status;
@ExcelProperty("备注")
private String remark;
@ExcelProperty("支付结果的回调地址")
private String payNotifyUrl;
@ExcelProperty("退款结果的回调地址")
private String refundNotifyUrl;
@ExcelProperty("商户编号")
private Long merchantId;
@ExcelProperty("创建时间")
private Date createTime;
}

View File

@ -0,0 +1,41 @@
package cn.iocoder.yudao.adminserver.modules.pay.controller.app.vo;
import lombok.*;
import java.util.*;
import io.swagger.annotations.*;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import org.springframework.format.annotation.DateTimeFormat;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@ApiModel(value = "支付应用信息 Excel 导出 Request VO", description = "参数和 PayAppPageReqVO 是一致的")
@Data
public class PayAppExportReqVO {
@ApiModelProperty(value = "应用名")
private String name;
@ApiModelProperty(value = "开启状态")
private Integer status;
@ApiModelProperty(value = "备注")
private String remark;
@ApiModelProperty(value = "支付结果的回调地址")
private String payNotifyUrl;
@ApiModelProperty(value = "退款结果的回调地址")
private String refundNotifyUrl;
@ApiModelProperty(value = "商户编号")
private Long merchantId;
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
@ApiModelProperty(value = "开始创建时间")
private Date beginCreateTime;
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
@ApiModelProperty(value = "结束创建时间")
private Date endCreateTime;
}

View File

@ -0,0 +1,75 @@
package cn.iocoder.yudao.adminserver.modules.pay.controller.app.vo;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import java.util.Date;
@ApiModel(value = "支付应用信息分页查询 Response VO", description = "相比于支付信息,还会多出应用渠道的开关信息")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class PayAppPageItemRespVO extends PayAppBaseVO {
@ApiModelProperty(value = "应用编号", required = true)
private Long id;
@ApiModelProperty(value = "创建时间", required = true)
private Date createTime;
/**
* 所属商户
*/
private PayMerchant payMerchant;
@ApiModel("商户")
@Data
public static class PayMerchant {
@ApiModelProperty(value = "商户编号", required = true, example = "1")
private Long id;
@ApiModelProperty(value = "商户名称", required = true, example = "研发部")
private String name;
}
/**
* 支付渠道
*/
private PayChannel payChannel;
/**
* 支付渠道开通情况
* 1默认为未开通当前支付渠道0为已开通支付渠道
*/
@Data
@ApiModel("支付渠道")
public static class PayChannel {
@ApiModelProperty(value = "微信 JSAPI 支付", required = true, example = "1")
private Integer wxPub = CommonStatusEnum.DISABLE.getStatus();
@ApiModelProperty(value = "微信小程序支付", required = true, example = "1")
private Integer wxLite = CommonStatusEnum.DISABLE.getStatus();
@ApiModelProperty(value = "微信 App 支付", required = true, example = "1")
private Integer wxApp = CommonStatusEnum.DISABLE.getStatus();
@ApiModelProperty(value = "支付宝 PC 网站支付", required = true, example = "1")
private Integer alipayPc = CommonStatusEnum.DISABLE.getStatus();
@ApiModelProperty(value = "支付宝 Wap 网站支付", required = true, example = "1")
private Integer alipayWap = CommonStatusEnum.DISABLE.getStatus();
@ApiModelProperty(value = "支付宝App 支付", required = true, example = "1")
private Integer alipayApp = CommonStatusEnum.DISABLE.getStatus();
@ApiModelProperty(value = "支付宝扫码支付", required = true, example = "1")
private Integer alipayQr = CommonStatusEnum.DISABLE.getStatus();
}
}

View File

@ -0,0 +1,43 @@
package cn.iocoder.yudao.adminserver.modules.pay.controller.app.vo;
import lombok.*;
import java.util.*;
import io.swagger.annotations.*;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import org.springframework.format.annotation.DateTimeFormat;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@ApiModel("支付应用信息分页 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class PayAppPageReqVO extends PageParam {
@ApiModelProperty(value = "应用名")
private String name;
@ApiModelProperty(value = "开启状态")
private Integer status;
@ApiModelProperty(value = "备注")
private String remark;
@ApiModelProperty(value = "支付结果的回调地址")
private String payNotifyUrl;
@ApiModelProperty(value = "退款结果的回调地址")
private String refundNotifyUrl;
@ApiModelProperty(value = "商户名称")
private String merchantName;
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
@ApiModelProperty(value = "开始创建时间")
private Date beginCreateTime;
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
@ApiModelProperty(value = "结束创建时间")
private Date endCreateTime;
}

View File

@ -0,0 +1,19 @@
package cn.iocoder.yudao.adminserver.modules.pay.controller.app.vo;
import lombok.*;
import java.util.*;
import io.swagger.annotations.*;
@ApiModel("支付应用信息 Response VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class PayAppRespVO extends PayAppBaseVO {
@ApiModelProperty(value = "应用编号", required = true)
private Long id;
@ApiModelProperty(value = "创建时间", required = true)
private Date createTime;
}

View File

@ -0,0 +1,18 @@
package cn.iocoder.yudao.adminserver.modules.pay.controller.app.vo;
import lombok.*;
import java.util.*;
import io.swagger.annotations.*;
import javax.validation.constraints.*;
@ApiModel("支付应用信息更新 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class PayAppUpdateReqVO extends PayAppBaseVO {
@ApiModelProperty(value = "应用编号", required = true)
@NotNull(message = "应用编号不能为空")
private Long id;
}

View File

@ -0,0 +1,21 @@
package cn.iocoder.yudao.adminserver.modules.pay.controller.app.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotNull;
@ApiModel("应用更新状态 Request VO")
@Data
public class PayAppUpdateStatusReqVO {
@ApiModelProperty(value = "商户编号", required = true, example = "1024")
@NotNull(message = "商户编号不能为空")
private Long id;
@ApiModelProperty(value = "状态", required = true, example = "1", notes = "见 SysCommonStatusEnum 枚举")
@NotNull(message = "状态不能为空")
private Integer status;
}

View File

@ -0,0 +1,190 @@
package cn.iocoder.yudao.adminserver.modules.pay.controller.channel;
import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayChannelDO;
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
import cn.iocoder.yudao.framework.pay.core.client.impl.wx.WXPayClientConfig;
import cn.iocoder.yudao.framework.pay.core.client.impl.wx.WXPubPayClient;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import org.springframework.validation.annotation.Validated;
import org.springframework.security.access.prepost.PreAuthorize;
import io.swagger.annotations.*;
import javax.validation.*;
import javax.servlet.http.*;
import java.util.*;
import java.io.IOException;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.*;
import cn.iocoder.yudao.adminserver.modules.pay.controller.channel.vo.*;
import cn.iocoder.yudao.adminserver.modules.pay.convert.channel.PayChannelConvert;
import cn.iocoder.yudao.adminserver.modules.pay.service.channel.PayChannelService;
import org.springframework.web.multipart.MultipartFile;
@Api(tags = "支付渠道")
@RestController
@RequestMapping("/pay/channel")
@Validated
public class PayChannelController {
@Resource
private PayChannelService channelService;
// todo 芋艿 这几个生成的方法是没用到的 您看要不删除了把? -----start
@PostMapping("/create")
@ApiOperation("创建支付渠道 ")
@PreAuthorize("@ss.hasPermission('pay:channel:create')")
public CommonResult<Long> createChannel(@Valid @RequestBody PayChannelCreateReqVO createReqVO) {
return success(channelService.createChannel(createReqVO));
}
@PutMapping("/update")
@ApiOperation("更新支付渠道 ")
@PreAuthorize("@ss.hasPermission('pay:channel:update')")
public CommonResult<Boolean> updateChannel(@Valid @RequestBody PayChannelUpdateReqVO updateReqVO) {
channelService.updateChannel(updateReqVO);
return success(true);
}
@DeleteMapping("/delete")
@ApiOperation("删除支付渠道 ")
@ApiImplicitParam(name = "id", value = "编号", required = true)
@PreAuthorize("@ss.hasPermission('pay:channel:delete')")
public CommonResult<Boolean> deleteChannel(@RequestParam("id") Long id) {
channelService.deleteChannel(id);
return success(true);
}
@GetMapping("/get")
@ApiOperation("获得支付渠道 ")
@ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class)
@PreAuthorize("@ss.hasPermission('pay:channel:query')")
public CommonResult<PayChannelRespVO> getChannel(@RequestParam("id") Long id) {
PayChannelDO channel = channelService.getChannel(id);
return success(PayChannelConvert.INSTANCE.convert(channel));
}
@GetMapping("/list")
@ApiOperation("获得支付渠道列表")
@ApiImplicitParam(name = "ids", value = "编号列表",
required = true, example = "1024,2048", dataTypeClass = List.class)
@PreAuthorize("@ss.hasPermission('pay:channel:query')")
public CommonResult<List<PayChannelRespVO>> getChannelList(@RequestParam("ids") Collection<Long> ids) {
List<PayChannelDO> list = channelService.getChannelList(ids);
return success(PayChannelConvert.INSTANCE.convertList(list));
}
@GetMapping("/page")
@ApiOperation("获得支付渠道分页")
@PreAuthorize("@ss.hasPermission('pay:channel:query')")
public CommonResult<PageResult<PayChannelRespVO>> getChannelPage(@Valid PayChannelPageReqVO pageVO) {
PageResult<PayChannelDO> pageResult = channelService.getChannelPage(pageVO);
return success(PayChannelConvert.INSTANCE.convertPage(pageResult));
}
@GetMapping("/export-excel")
@ApiOperation("导出支付渠道Excel")
@PreAuthorize("@ss.hasPermission('pay:channel:export')")
@OperateLog(type = EXPORT)
public void exportChannelExcel(@Valid PayChannelExportReqVO exportReqVO,
HttpServletResponse response) throws IOException {
List<PayChannelDO> list = channelService.getChannelList(exportReqVO);
// 导出 Excel
List<PayChannelExcelVO> datas = PayChannelConvert.INSTANCE.convertList02(list);
ExcelUtils.write(response, "支付渠道.xls", "数据", PayChannelExcelVO.class, datas);
}
// todo 芋艿 这几个生成的方法是没用到的 您看要不删除了把? -----end
@PostMapping("/parsing-pem")
@ApiOperation("解析pem证书转换为字符串")
@PreAuthorize("@ss.hasPermission('pay:channel:parsing')")
@ApiImplicitParam(name = "file", value = "pem文件", required = true, dataTypeClass = MultipartFile.class)
public CommonResult<String> parsingPemFile(@RequestParam("file") MultipartFile file) {
return success(channelService.parsingPemFile(file));
}
@PostMapping("/create-wechat")
@ApiOperation("创建支付渠道 ")
@PreAuthorize("@ss.hasPermission('pay:channel:create')")
public CommonResult<Long> createWechatChannel(@Valid @RequestBody PayWechatChannelCreateReqVO reqVO) {
// 针对于 V2 或者 V3 版本的参数校验
this.paramAdvanceCheck(reqVO.getWeChatConfig().getApiVersion(),reqVO.getWeChatConfig().getMchKey(),
reqVO.getWeChatConfig().getPrivateKeyContent(),reqVO.getWeChatConfig().getPrivateCertContent());
return success(channelService.createWechatChannel(reqVO));
}
@GetMapping("/get-wechat")
@ApiOperation("根据条件查询微信支付渠道")
@ApiImplicitParams({
@ApiImplicitParam(name = "merchantId", value = "商户编号",
required = true, example = "1", dataTypeClass = Long.class),
@ApiImplicitParam(name = "appId", value = "应用编号",
required = true, example = "1", dataTypeClass = Long.class),
@ApiImplicitParam(name = "code", value = "支付渠道编码",
required = true, example = "wx_pub", dataTypeClass = String.class)
})
@PreAuthorize("@ss.hasPermission('pay:channel:query')")
public CommonResult<PayWeChatChannelRespVO> getWeChatChannel(
@RequestParam Long merchantId, @RequestParam Long appId, @RequestParam String code) {
// 獲取渠道
PayChannelDO channel = channelService.getChannelByConditions(merchantId, appId, code);
if (channel == null) {
return success(new PayWeChatChannelRespVO());
}
// 拼凑数据
PayWeChatChannelRespVO respVo = PayChannelConvert.INSTANCE.convert2(channel);
WXPayClientConfig config = (WXPayClientConfig) channel.getConfig();
respVo.setWeChatConfig(PayChannelConvert.INSTANCE.configConvert(config));
return success(respVo);
}
@PutMapping("/update-wechat")
@ApiOperation("更新微信支付渠道 ")
@PreAuthorize("@ss.hasPermission('pay:channel:update')")
public CommonResult<Boolean> updateWechatChannel(@Valid @RequestBody PayWechatChannelUpdateReqVO updateReqVO) {
// 针对于 V2 或者 V3 版本的参数校验
this.paramAdvanceCheck(updateReqVO.getWeChatConfig().getApiVersion(),updateReqVO.getWeChatConfig().getMchKey(),
updateReqVO.getWeChatConfig().getPrivateKeyContent(),updateReqVO.getWeChatConfig().getPrivateCertContent());
channelService.updateWechatChannel(updateReqVO);
return success(true);
}
/**
* 预检测微信秘钥参数
* @param version 版本
* @param mchKey v2版本秘钥
* @param privateKeyContent v3版本apiclient_key
* @param privateCertContent v3版本中apiclient_cert
*/
private void paramAdvanceCheck(String version, String mchKey, String privateKeyContent, String privateCertContent) {
// 针对于 V2 或者 V3 版本的参数校验
if (version.equals(WXPayClientConfig.API_VERSION_V2)) {
Assert.notNull(mchKey, "v2版本中商户密钥不可为空");
}
if (version.equals(WXPayClientConfig.API_VERSION_V3)) {
Assert.notNull(privateKeyContent, "v3版本apiclient_key.pem不可为空");
Assert.notNull(privateCertContent, "v3版本中apiclient_cert.pem不可为空");
}
}
}

View File

@ -0,0 +1,39 @@
package cn.iocoder.yudao.adminserver.modules.pay.controller.channel.vo;
import lombok.*;
import java.util.*;
import io.swagger.annotations.*;
import javax.validation.constraints.*;
/**
* 支付渠道
Base VO提供给添加、修改、详细的子 VO 使用
* 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成
*/
@Data
public class PayChannelBaseVO {
@ApiModelProperty(value = "渠道编码", required = true)
@NotNull(message = "渠道编码不能为空")
private String code;
@ApiModelProperty(value = "开启状态", required = true)
@NotNull(message = "开启状态不能为空")
private Integer status;
@ApiModelProperty(value = "备注")
private String remark;
@ApiModelProperty(value = "渠道费率,单位:百分比", required = true)
@NotNull(message = "渠道费率,单位:百分比不能为空")
private Double feeRate;
@ApiModelProperty(value = "商户编号", required = true)
@NotNull(message = "商户编号不能为空")
private Long merchantId;
@ApiModelProperty(value = "应用编号", required = true)
@NotNull(message = "应用编号不能为空")
private Long appId;
}

View File

@ -0,0 +1,16 @@
package cn.iocoder.yudao.adminserver.modules.pay.controller.channel.vo;
import io.swagger.annotations.ApiModel;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
@ApiModel("支付渠道 创建 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class PayChannelCreateReqVO extends PayChannelBaseVO {
}

View File

@ -0,0 +1,50 @@
package cn.iocoder.yudao.adminserver.modules.pay.controller.channel.vo;
import lombok.*;
import java.util.*;
import io.swagger.annotations.*;
import com.alibaba.excel.annotation.ExcelProperty;
/**
* 支付渠道
Excel VO
*
* @author 芋艿
*/
@Data
public class PayChannelExcelVO {
@ExcelProperty("商户编号")
private Long id;
@ExcelProperty("渠道编码")
private String code;
@ExcelProperty("开启状态")
private Integer status;
@ExcelProperty("备注")
private String remark;
@ExcelProperty("渠道费率,单位:百分比")
private Double feeRate;
@ExcelProperty("商户编号")
private Long merchantId;
@ExcelProperty("应用编号")
private Long appId;
/**
* todo @芋艿 mapStruct 存在转换问题
* java: Can't map property "PayClientConfig payChannelDO.config" to "String payChannelExcelVO.config".
* Consider to declare/implement a mapping method: "String map(PayClientConfig value)".
*/
/// @ExcelProperty("支付渠道配置")
/// private String config;
@ExcelProperty("创建时间")
private Date createTime;
}

View File

@ -0,0 +1,44 @@
package cn.iocoder.yudao.adminserver.modules.pay.controller.channel.vo;
import lombok.*;
import java.util.*;
import io.swagger.annotations.*;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import org.springframework.format.annotation.DateTimeFormat;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@ApiModel(value = "支付渠道 Excel 导出 Request VO", description = "参数和 PayChannelPageReqVO 是一致的")
@Data
public class PayChannelExportReqVO {
@ApiModelProperty(value = "渠道编码")
private String code;
@ApiModelProperty(value = "开启状态")
private Integer status;
@ApiModelProperty(value = "备注")
private String remark;
@ApiModelProperty(value = "渠道费率,单位:百分比")
private Double feeRate;
@ApiModelProperty(value = "商户编号")
private Long merchantId;
@ApiModelProperty(value = "应用编号")
private Long appId;
@ApiModelProperty(value = "支付渠道配置")
private String config;
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
@ApiModelProperty(value = "开始创建时间")
private Date beginCreateTime;
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
@ApiModelProperty(value = "结束创建时间")
private Date endCreateTime;
}

View File

@ -0,0 +1,46 @@
package cn.iocoder.yudao.adminserver.modules.pay.controller.channel.vo;
import lombok.*;
import java.util.*;
import io.swagger.annotations.*;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import org.springframework.format.annotation.DateTimeFormat;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@ApiModel("支付渠道 分页 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class PayChannelPageReqVO extends PageParam {
@ApiModelProperty(value = "渠道编码")
private String code;
@ApiModelProperty(value = "开启状态")
private Integer status;
@ApiModelProperty(value = "备注")
private String remark;
@ApiModelProperty(value = "渠道费率,单位:百分比")
private Double feeRate;
@ApiModelProperty(value = "商户编号")
private Long merchantId;
@ApiModelProperty(value = "应用编号")
private Long appId;
@ApiModelProperty(value = "支付渠道配置")
private String config;
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
@ApiModelProperty(value = "开始创建时间")
private Date beginCreateTime;
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
@ApiModelProperty(value = "结束创建时间")
private Date endCreateTime;
}

View File

@ -0,0 +1,19 @@
package cn.iocoder.yudao.adminserver.modules.pay.controller.channel.vo;
import lombok.*;
import java.util.*;
import io.swagger.annotations.*;
@ApiModel("支付渠道 Response VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class PayChannelRespVO extends PayChannelBaseVO {
@ApiModelProperty(value = "商户编号", required = true)
private Long id;
@ApiModelProperty(value = "创建时间", required = true)
private Date createTime;
}

View File

@ -0,0 +1,18 @@
package cn.iocoder.yudao.adminserver.modules.pay.controller.channel.vo;
import lombok.*;
import java.util.*;
import io.swagger.annotations.*;
import javax.validation.constraints.*;
@ApiModel("支付渠道 更新 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class PayChannelUpdateReqVO extends PayChannelBaseVO {
@ApiModelProperty(value = "商户编号", required = true)
@NotNull(message = "商户编号不能为空")
private Long id;
}

View File

@ -0,0 +1,65 @@
package cn.iocoder.yudao.adminserver.modules.pay.controller.channel.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import javax.validation.Valid;
import java.util.Date;
@ApiModel("支付微信渠道 Response VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class PayWeChatChannelRespVO extends PayChannelBaseVO {
@ApiModelProperty(value = "商户编号", required = true)
private Long id;
@ApiModelProperty(value = "创建时间", required = true)
private Date createTime;
/**
* 微信配置类
*/
@Valid
private WeChatConfig weChatConfig;
/**
* 微信配置类
*/
@Data
@ApiModel("微信配置类")
public static class WeChatConfig {
@ApiModelProperty(value = "公众号或者小程序的 appid", required = true, example = "wx041349c6f39b261b")
private String appId;
@ApiModelProperty(value = "商户号", required = true, example = "1545083881")
private String mchId;
@ApiModelProperty(value = "API 版本", required = true, example = "v2")
private String apiVersion;
// ========== V2 版本的参数 ==========
@ApiModelProperty(value = "商户密钥", required = true, example = "0alL64UDQdaCwiKZ73ib7ypaIjMns06p")
private String mchKey;
/// todo @aquan 暂不支持 .p12上传 后期优化
/// apiclient_cert.p12 证书文件的绝对路径或者以 classpath: 开头的类路径. 对应的字符串
/// private String keyContent;
// ========== V3 版本的参数 ==========
@ApiModelProperty(value = "apiclient_key.pem 证书对应的字符串", required = true, example = "-----BEGIN PRIVATE KEY-----")
private String privateKeyContent;
@ApiModelProperty(value = "apiclient_cert.pem 证书对应的字符串", required = true, example = "-----BEGIN CERTIFICATE-----")
private String privateCertContent;
}
}

View File

@ -0,0 +1,68 @@
package cn.iocoder.yudao.adminserver.modules.pay.controller.channel.vo;
import com.fasterxml.jackson.annotation.JsonClassDescription;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import javax.validation.Valid;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
/**
* 支付渠道微信创建Request VO
* @author aquan
*/
@ApiModel("支付渠道微信创建Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class PayWechatChannelCreateReqVO extends PayChannelBaseVO {
/**
* 微信配置类
*/
@Valid
private WeChatConfig weChatConfig;
/**
* 微信配置类
*/
@Data
@ApiModel("微信配置类")
public static class WeChatConfig {
@NotBlank(message = "公众号或者小程序的 appid不能为空")
@ApiModelProperty(value = "公众号或者小程序的 appid", required = true, example = "wx041349c6f39b261b")
private String appId;
@NotBlank(message = "商户号不能为空")
@ApiModelProperty(value = "商户号", required = true, example = "1545083881")
private String mchId;
@NotNull(message = "API 版本不能为空")
@ApiModelProperty(value = "API 版本", required = true, example = "v2")
private String apiVersion;
// ========== V2 版本的参数 ==========
@ApiModelProperty(value = "商户密钥", required = true, example = "0alL64UDQdaCwiKZ73ib7ypaIjMns06p")
private String mchKey;
/// todo @aquan 暂不支持 .p12上传 后期优化
/// apiclient_cert.p12 证书文件的绝对路径或者以 classpath: 开头的类路径. 对应的字符串
/// private String keyContent;
// ========== V3 版本的参数 ==========
@ApiModelProperty(value = "apiclient_key.pem 证书对应的字符串", required = true, example = "-----BEGIN PRIVATE KEY-----")
private String privateKeyContent;
@ApiModelProperty(value = "apiclient_cert.pem 证书对应的字符串", required = true, example = "-----BEGIN CERTIFICATE-----")
private String privateCertContent;
}
}

View File

@ -0,0 +1,66 @@
package cn.iocoder.yudao.adminserver.modules.pay.controller.channel.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import javax.validation.Valid;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
@ApiModel("支付渠道 更新 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class PayWechatChannelUpdateReqVO extends PayChannelBaseVO {
@ApiModelProperty(value = "商户编号", required = true)
@NotNull(message = "商户编号不能为空")
private Long id;
/**
* 微信配置类
*/
@Valid
private PayWechatChannelCreateReqVO.WeChatConfig weChatConfig;
/**
* 微信配置类
*/
@Data
@ApiModel("微信配置类")
public static class WeChatConfig {
@NotBlank(message = "公众号或者小程序的 appid不能为空")
@ApiModelProperty(value = "公众号或者小程序的 appid", required = true, example = "wx041349c6f39b261b")
private String appId;
@NotBlank(message = "商户号不能为空")
@ApiModelProperty(value = "商户号", required = true, example = "1545083881")
private String mchId;
@NotNull(message = "API 版本不能为空")
@ApiModelProperty(value = "API 版本", required = true, example = "v2")
private String apiVersion;
// ========== V2 版本的参数 ==========
@ApiModelProperty(value = "商户密钥", required = true, example = "0alL64UDQdaCwiKZ73ib7ypaIjMns06p")
private String mchKey;
/// todo @aquan 暂不支持 .p12上传 后期优化
/// apiclient_cert.p12 证书文件的绝对路径或者以 classpath: 开头的类路径. 对应的字符串
/// private String keyContent;
// ========== V3 版本的参数 ==========
@ApiModelProperty(value = "apiclient_key.pem 证书对应的字符串", required = true, example = "-----BEGIN PRIVATE KEY-----")
private String privateKeyContent;
@ApiModelProperty(value = "apiclient_cert.pem 证书对应的字符串", required = true, example = "-----BEGIN CERTIFICATE-----")
private String privateCertContent;
}
}

View File

@ -3,7 +3,6 @@ package cn.iocoder.yudao.adminserver.modules.pay.controller.merchant;
import cn.iocoder.yudao.adminserver.modules.pay.controller.merchant.vo.*;
import cn.iocoder.yudao.adminserver.modules.pay.convert.merchant.PayMerchantConvert;
import cn.iocoder.yudao.adminserver.modules.pay.service.merchant.PayMerchantService;
import cn.iocoder.yudao.adminserver.modules.system.controller.user.vo.user.SysUserUpdateStatusReqVO;
import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayMerchantDO;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
@ -76,6 +75,15 @@ public class PayMerchantController {
return success(PayMerchantConvert.INSTANCE.convert(merchant));
}
@GetMapping("/list-name")
@ApiOperation("根据商户名称获得支付商户信息列表")
@ApiImplicitParam(name = "name", value = "商户名称", required = true, example = "芋道", dataTypeClass = Long.class)
@PreAuthorize("@ss.hasPermission('pay:merchant:query')")
public CommonResult<List<PayMerchantRespVO>> getMerchantListByName(@RequestParam("name") String name) {
List<PayMerchantDO> merchantListDO = merchantService.getMerchantListByNameLimit(name);
return success(PayMerchantConvert.INSTANCE.convertList(merchantListDO));
}
@GetMapping("/list")
@ApiOperation("获得支付商户信息列表")
@ApiImplicitParam(name = "ids", value = "编号列表", required = true, example = "1024,2048", dataTypeClass = List.class)

View File

@ -12,10 +12,6 @@ import javax.validation.constraints.NotNull;
@Data
public class PayMerchantBaseVO {
// TODO @aquanno 应该不允许修改。啊哈哈,我的原型没画对
@ApiModelProperty(value = "商户号")
private String no;
@ApiModelProperty(value = "商户全称", required = true)
@NotNull(message = "商户全称不能为空")
private String name;

View File

@ -0,0 +1,41 @@
package cn.iocoder.yudao.adminserver.modules.pay.convert.app;
import java.util.*;
import cn.iocoder.yudao.adminserver.modules.system.controller.user.vo.user.SysUserPageItemRespVO;
import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.dept.SysDeptDO;
import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayAppDO;
import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayMerchantDO;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;
import cn.iocoder.yudao.adminserver.modules.pay.controller.app.vo.*;
/**
* 支付应用信息 Convert
*
* @author 芋艿
*/
@Mapper
public interface PayAppConvert {
PayAppConvert INSTANCE = Mappers.getMapper(PayAppConvert.class);
PayAppPageItemRespVO pageConvert (PayAppDO bean);
PayAppPageItemRespVO.PayMerchant convert(PayMerchantDO bean);
PayAppDO convert(PayAppCreateReqVO bean);
PayAppDO convert(PayAppUpdateReqVO bean);
PayAppRespVO convert(PayAppDO bean);
List<PayAppRespVO> convertList(List<PayAppDO> list);
PageResult<PayAppRespVO> convertPage(PageResult<PayAppDO> page);
List<PayAppExcelVO> convertList02(List<PayAppDO> list);
}

View File

@ -0,0 +1,51 @@
package cn.iocoder.yudao.adminserver.modules.pay.convert.channel;
import java.util.*;
import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayChannelDO;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.pay.core.client.impl.wx.WXPayClientConfig;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.factory.Mappers;
import cn.iocoder.yudao.adminserver.modules.pay.controller.channel.vo.*;
/**
* 支付渠道
Convert
*
* @author 芋艿
*/
@Mapper
public interface PayChannelConvert {
PayChannelConvert INSTANCE = Mappers.getMapper(PayChannelConvert.class);
@Mapping(target = "config",ignore = true)
PayChannelDO convert(PayWechatChannelCreateReqVO bean);
@Mapping(target = "config",ignore = true)
PayChannelDO convert(PayWechatChannelUpdateReqVO bean);
PayChannelDO convert(PayChannelCreateReqVO bean);
PayChannelDO convert(PayChannelUpdateReqVO bean);
PayChannelRespVO convert(PayChannelDO bean);
List<PayChannelRespVO> convertList(List<PayChannelDO> list);
PageResult<PayChannelRespVO> convertPage(PageResult<PayChannelDO> page);
List<PayChannelExcelVO> convertList02(List<PayChannelDO> list);
WXPayClientConfig configConvert(PayWechatChannelCreateReqVO.WeChatConfig bean);
WXPayClientConfig configConvert(PayWechatChannelUpdateReqVO.WeChatConfig bean);
@Mapping(target = "weChatConfig",ignore = true)
PayWeChatChannelRespVO convert2(PayChannelDO bean);
PayWeChatChannelRespVO.WeChatConfig configConvert(WXPayClientConfig bean);
}

View File

@ -0,0 +1,44 @@
package cn.iocoder.yudao.adminserver.modules.pay.dal.mysql.app;
import java.util.*;
import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayAppDO;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.mybatis.core.query.QueryWrapperX;
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import org.apache.ibatis.annotations.Mapper;
import cn.iocoder.yudao.adminserver.modules.pay.controller.app.vo.*;
/**
* 支付应用信息 Mapper
*
* @author 芋艿
*/
@Mapper
public interface PayAppMapper extends BaseMapperX<PayAppDO> {
default PageResult<PayAppDO> selectPage(PayAppPageReqVO reqVO,Collection<Long> merchantIds) {
return selectPage(reqVO, new QueryWrapperX<PayAppDO>()
.likeIfPresent("name", reqVO.getName())
.eqIfPresent("status", reqVO.getStatus())
.eqIfPresent("remark", reqVO.getRemark())
.eqIfPresent("pay_notify_url", reqVO.getPayNotifyUrl())
.eqIfPresent("refund_notify_url", reqVO.getRefundNotifyUrl())
.inIfPresent("merchant_id", merchantIds)
.betweenIfPresent("create_time", reqVO.getBeginCreateTime(), reqVO.getEndCreateTime())
.orderByDesc("id"));
}
default List<PayAppDO> selectList(PayAppExportReqVO reqVO) {
return selectList(new QueryWrapperX<PayAppDO>()
.likeIfPresent("name", reqVO.getName())
.eqIfPresent("status", reqVO.getStatus())
.eqIfPresent("remark", reqVO.getRemark())
.eqIfPresent("pay_notify_url", reqVO.getPayNotifyUrl())
.eqIfPresent("refund_notify_url", reqVO.getRefundNotifyUrl())
.eqIfPresent("merchant_id", reqVO.getMerchantId())
.betweenIfPresent("create_time", reqVO.getBeginCreateTime(), reqVO.getEndCreateTime())
.orderByDesc("id") );
}
}

View File

@ -0,0 +1,47 @@
package cn.iocoder.yudao.adminserver.modules.pay.dal.mysql.channel;
import java.util.*;
import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayChannelDO;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.mybatis.core.query.QueryWrapperX;
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import org.apache.ibatis.annotations.Mapper;
import cn.iocoder.yudao.adminserver.modules.pay.controller.channel.vo.*;
/**
* 支付渠道
Mapper
*
* @author 芋艿
*/
@Mapper
public interface PayChannelMapper extends BaseMapperX<PayChannelDO> {
default PageResult<PayChannelDO> selectPage(PayChannelPageReqVO reqVO) {
return selectPage(reqVO, new QueryWrapperX<PayChannelDO>()
.eqIfPresent("code", reqVO.getCode())
.eqIfPresent("status", reqVO.getStatus())
.eqIfPresent("remark", reqVO.getRemark())
.eqIfPresent("fee_rate", reqVO.getFeeRate())
.eqIfPresent("merchant_id", reqVO.getMerchantId())
.eqIfPresent("app_id", reqVO.getAppId())
.eqIfPresent("config", reqVO.getConfig())
.betweenIfPresent("create_time", reqVO.getBeginCreateTime(), reqVO.getEndCreateTime())
.orderByDesc("id") );
}
default List<PayChannelDO> selectList(PayChannelExportReqVO reqVO) {
return selectList(new QueryWrapperX<PayChannelDO>()
.eqIfPresent("code", reqVO.getCode())
.eqIfPresent("status", reqVO.getStatus())
.eqIfPresent("remark", reqVO.getRemark())
.eqIfPresent("fee_rate", reqVO.getFeeRate())
.eqIfPresent("merchant_id", reqVO.getMerchantId())
.eqIfPresent("app_id", reqVO.getAppId())
.eqIfPresent("config", reqVO.getConfig())
.betweenIfPresent("create_time", reqVO.getBeginCreateTime(), reqVO.getEndCreateTime())
.orderByDesc("id") );
}
}

View File

@ -0,0 +1,81 @@
package cn.iocoder.yudao.adminserver.modules.pay.service.app;
import java.util.*;
import javax.validation.*;
import cn.iocoder.yudao.adminserver.modules.pay.controller.app.vo.*;
import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayAppDO;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import org.springframework.web.multipart.MultipartFile;
/**
* 支付应用信息 Service 接口
*
* @author 芋艿
*/
public interface PayAppService {
/**
* 创建支付应用信息
*
* @param createReqVO 创建信息
* @return 编号
*/
Long createApp(@Valid PayAppCreateReqVO createReqVO);
/**
* 更新支付应用信息
*
* @param updateReqVO 更新信息
*/
void updateApp(@Valid PayAppUpdateReqVO updateReqVO);
/**
* 删除支付应用信息
*
* @param id 编号
*/
void deleteApp(Long id);
/**
* 获得支付应用信息
*
* @param id 编号
* @return 支付应用信息
*/
PayAppDO getApp(Long id);
/**
* 获得支付应用信息列表
*
* @param ids 编号
* @return 支付应用信息列表
*/
List<PayAppDO> getAppList(Collection<Long> ids);
/**
* 获得支付应用信息分页
*
* @param pageReqVO 分页查询
* @return 支付应用信息分页
*/
PageResult<PayAppDO> getAppPage(PayAppPageReqVO pageReqVO);
/**
* 获得支付应用信息列表, 用于 Excel 导出
*
* @param exportReqVO 查询条件
* @return 支付应用信息列表
*/
List<PayAppDO> getAppList(PayAppExportReqVO exportReqVO);
/**
* 修改应用信息状态
*
* @param id 应用编号
* @param status 状态{@link cn.iocoder.yudao.framework.common.enums.CommonStatusEnum}
*/
void updateAppStatus(Long id, Integer status);
}

View File

@ -0,0 +1,140 @@
package cn.iocoder.yudao.adminserver.modules.pay.service.app.impl;
import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.adminserver.modules.pay.service.merchant.PayMerchantService;
import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayAppDO;
import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayMerchantDO;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
import com.google.common.annotations.VisibleForTesting;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import org.springframework.validation.annotation.Validated;
import java.util.*;
import cn.iocoder.yudao.adminserver.modules.pay.controller.app.vo.*;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.adminserver.modules.pay.convert.app.PayAppConvert;
import cn.iocoder.yudao.adminserver.modules.pay.dal.mysql.app.PayAppMapper;
import cn.iocoder.yudao.adminserver.modules.pay.service.app.PayAppService;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.coreservice.modules.pay.enums.PayErrorCodeCoreConstants.*;
/**
* 支付应用信息 Service 实现类
*
* @author aquan
*/
@Service
@Validated
public class PayAppServiceImpl implements PayAppService {
@Resource
private PayAppMapper appMapper;
/**
* 商户 service 组件
*/
@Resource
private PayMerchantService merchantService;
@Override
public Long createApp(PayAppCreateReqVO createReqVO) {
// 插入
PayAppDO app = PayAppConvert.INSTANCE.convert(createReqVO);
appMapper.insert(app);
// 返回
return app.getId();
}
@Override
public void updateApp(PayAppUpdateReqVO updateReqVO) {
// 校验存在
this.validateAppExists(updateReqVO.getId());
// 更新
PayAppDO updateObj = PayAppConvert.INSTANCE.convert(updateReqVO);
appMapper.updateById(updateObj);
}
@Override
public void deleteApp(Long id) {
// 校验存在
this.validateAppExists(id);
// 删除
appMapper.deleteById(id);
}
private void validateAppExists(Long id) {
if (appMapper.selectById(id) == null) {
throw exception(APP_NOT_EXISTS);
}
}
@Override
public PayAppDO getApp(Long id) {
return appMapper.selectById(id);
}
@Override
public List<PayAppDO> getAppList(Collection<Long> ids) {
return appMapper.selectBatchIds(ids);
}
@Override
public PageResult<PayAppDO> getAppPage(PayAppPageReqVO pageReqVO) {
return appMapper.selectPage(pageReqVO,this.getMerchantCondition(pageReqVO.getMerchantName()));
}
@Override
public List<PayAppDO> getAppList(PayAppExportReqVO exportReqVO) {
return appMapper.selectList(exportReqVO);
}
/**
* 获取商户编号集合,根据商户名称模糊查询得到所有的商户编号集合
* @param merchantName 商户名称
* @return 商户编号集合
*/
private Set<Long> getMerchantCondition(String merchantName) {
if (StrUtil.isBlank(merchantName)) {
return Collections.emptySet();
}
return CollectionUtils.convertSet(merchantService.getMerchantListByName(merchantName), PayMerchantDO::getId);
}
/**
* 修改应用信息状态
*
* @param id 应用编号
* @param status 状态{@link CommonStatusEnum}
*/
@Override
public void updateAppStatus(Long id, Integer status) {
// 校验商户存在
this.checkAppExists(id);
// 更新状态
PayAppDO app = new PayAppDO();
app.setId(id);
app.setStatus(status);
appMapper.updateById(app);
}
/**
* 检查商户是否存在
* @param id 商户编号
*/
@VisibleForTesting
public void checkAppExists(Long id) {
if (id == null) {
return;
}
PayAppDO payApp = appMapper.selectById(id);
if (payApp == null) {
throw exception(APP_NOT_EXISTS);
}
}
}

View File

@ -0,0 +1,130 @@
package cn.iocoder.yudao.adminserver.modules.pay.service.channel;
import java.util.*;
import javax.validation.*;
import cn.iocoder.yudao.adminserver.modules.pay.controller.channel.vo.*;
import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayChannelDO;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import org.springframework.web.multipart.MultipartFile;
/**
* 支付渠道
* Service 接口
*
* @author 芋艿
*/
public interface PayChannelService {
/**
* 创建支付渠道
*
* @param createReqVO 创建信息
* @return 编号
*/
Long createChannel(@Valid PayChannelCreateReqVO createReqVO);
/**
* 更新支付渠道
*
* @param updateReqVO 更新信息
*/
void updateChannel(@Valid PayChannelUpdateReqVO updateReqVO);
/**
* 删除支付渠道
*
* @param id 编号
*/
void deleteChannel(Long id);
/**
* 获得支付渠道
*
* @param id 编号
* @return 支付渠道
*/
PayChannelDO getChannel(Long id);
/**
* 获得支付渠道
* 列表
*
* @param ids 编号
* @return 支付渠道
* 列表
*/
List<PayChannelDO> getChannelList(Collection<Long> ids);
/**
* 获得支付渠道
* 分页
*
* @param pageReqVO 分页查询
* @return 支付渠道
* 分页
*/
PageResult<PayChannelDO> getChannelPage(PayChannelPageReqVO pageReqVO);
/**
* 获得支付渠道
* 列表, 用于 Excel 导出
*
* @param exportReqVO 查询条件
* @return 支付渠道
* 列表
*/
List<PayChannelDO> getChannelList(PayChannelExportReqVO exportReqVO);
/**
* 根据支付应用ID集合获取所有的支付渠道
*
* @param payIds 支付应用编号集合
* @return 支付渠道
*/
List<PayChannelDO> getSimpleChannels(Collection<Long> payIds);
/**
* 解析pem文件获取公钥私钥字符串
*
* @param file pem公私钥文件
* @return 解析后的字符串
*/
String parsingPemFile(MultipartFile file);
/**
* 创建微信的渠道配置
*
* @param reqVO 创建信息
* @return 创建结果
*/
Long createWechatChannel(PayWechatChannelCreateReqVO reqVO);
/**
* 根据条件获取通道数量
*
* @param merchantId 商户编号
* @param appid 应用编号
* @param code 通道编码
* @return 数量
*/
Integer getChannelCountByConditions(Long merchantId, Long appid, String code);
/**
* 根据条件获取通道
*
* @param merchantId 商户编号
* @param appid 应用编号
* @param code 通道编码
* @return 数量
*/
PayChannelDO getChannelByConditions(Long merchantId, Long appid, String code);
/**
* 更新微信支付渠道
*
* @param updateReqVO 更新信息
*/
void updateWechatChannel(PayWechatChannelUpdateReqVO updateReqVO);
}

View File

@ -0,0 +1,196 @@
package cn.iocoder.yudao.adminserver.modules.pay.service.channel.impl;
import cn.hutool.core.io.IoUtil;
import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayChannelDO;
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
import cn.iocoder.yudao.framework.pay.core.client.impl.wx.WXPayClientConfig;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.databind.json.JsonMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import org.springframework.util.Assert;
import org.springframework.validation.annotation.Validated;
import java.io.IOException;
import java.util.*;
import cn.iocoder.yudao.adminserver.modules.pay.controller.channel.vo.*;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.adminserver.modules.pay.convert.channel.PayChannelConvert;
import cn.iocoder.yudao.adminserver.modules.pay.dal.mysql.channel.PayChannelMapper;
import cn.iocoder.yudao.adminserver.modules.pay.service.channel.PayChannelService;
import org.springframework.web.multipart.MultipartFile;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.coreservice.modules.pay.enums.PayErrorCodeCoreConstants.*;
/**
* 支付渠道
* Service 实现类
*
* @author 芋艿
*/
@Slf4j
@Service
@Validated
public class PayChannelServiceImpl implements PayChannelService {
@Resource
private PayChannelMapper channelMapper;
@Override
public Long createChannel(PayChannelCreateReqVO createReqVO) {
// 插入
PayChannelDO channel = PayChannelConvert.INSTANCE.convert(createReqVO);
channelMapper.insert(channel);
// 返回
return channel.getId();
}
@Override
public void updateChannel(PayChannelUpdateReqVO updateReqVO) {
// 校验存在
this.validateChannelExists(updateReqVO.getId());
// 更新
PayChannelDO updateObj = PayChannelConvert.INSTANCE.convert(updateReqVO);
channelMapper.updateById(updateObj);
}
@Override
public void deleteChannel(Long id) {
// 校验存在
this.validateChannelExists(id);
// 删除
channelMapper.deleteById(id);
}
private void validateChannelExists(Long id) {
if (channelMapper.selectById(id) == null) {
throw exception(CHANNEL_NOT_EXISTS);
}
}
@Override
public PayChannelDO getChannel(Long id) {
return channelMapper.selectById(id);
}
@Override
public List<PayChannelDO> getChannelList(Collection<Long> ids) {
return channelMapper.selectBatchIds(ids);
}
@Override
public PageResult<PayChannelDO> getChannelPage(PayChannelPageReqVO pageReqVO) {
return channelMapper.selectPage(pageReqVO);
}
@Override
public List<PayChannelDO> getChannelList(PayChannelExportReqVO exportReqVO) {
return channelMapper.selectList(exportReqVO);
}
/**
* 根据支付应用ID集合获取所有的支付渠道
*
* @param payIds 支付应用编号集合
* @return 支付渠道
*/
@Override
public List<PayChannelDO> getSimpleChannels(Collection<Long> payIds) {
return channelMapper.selectList(new QueryWrapper<PayChannelDO>().lambda().in(PayChannelDO::getAppId, payIds));
}
/**
* 解析pem文件获取公钥私钥字符串
*
* @param file pem公私钥文件
* @return 解析后的字符串
*/
@Override
public String parsingPemFile(MultipartFile file) {
try {
return IoUtil.readUtf8(file.getInputStream());
} catch (IOException e) {
log.error("[parsingPemToString]读取pem[{}]文件错误", file.getOriginalFilename());
throw exception(CHANNEL_KEY_READ_ERROR);
}
}
/**
* 创建微信的渠道配置
*
* @param reqVO 创建信息
* @return 创建结果
*/
@Override
public Long createWechatChannel(PayWechatChannelCreateReqVO reqVO) {
// 判断是否有重复的有责无法新增
Integer channelCount = this.getChannelCountByConditions(reqVO.getMerchantId(), reqVO.getAppId(), reqVO.getCode());
if (channelCount > 0) {
throw exception(EXIST_SAME_CHANNEL_ERROR);
}
PayChannelDO channel = PayChannelConvert.INSTANCE.convert(reqVO);
WXPayClientConfig config = PayChannelConvert.INSTANCE.configConvert(reqVO.getWeChatConfig());
channel.setConfig(config);
channelMapper.insert(channel);
return channel.getId();
}
/**
* 根据条件获取通道数量
*
* @param merchantId 商户编号
* @param appid 应用编号
* @param code 通道编码
* @return 数量
*/
@Override
public Integer getChannelCountByConditions(Long merchantId, Long appid, String code) {
return this.channelMapper.selectCount(new QueryWrapper<PayChannelDO>().lambda()
.eq(PayChannelDO::getMerchantId, merchantId)
.eq(PayChannelDO::getAppId, appid)
.eq(PayChannelDO::getCode, code)
);
}
/**
* 根据条件获取通道
*
* @param merchantId 商户编号
* @param appid 应用编号
* @param code 通道编码
* @return 数量
*/
@Override
public PayChannelDO getChannelByConditions(Long merchantId, Long appid, String code) {
return this.channelMapper.selectOne((new QueryWrapper<PayChannelDO>().lambda()
.eq(PayChannelDO::getMerchantId, merchantId)
.eq(PayChannelDO::getAppId, appid)
.eq(PayChannelDO::getCode, code)
));
}
/**
* 更新微信支付渠道
*
* @param updateReqVO 更新信息
*/
@Override
public void updateWechatChannel(PayWechatChannelUpdateReqVO updateReqVO) {
// 校验存在
this.validateChannelExists(updateReqVO.getId());
PayChannelDO channel = PayChannelConvert.INSTANCE.convert(updateReqVO);
WXPayClientConfig config = PayChannelConvert.INSTANCE.configConvert(updateReqVO.getWeChatConfig());
channel.setConfig(config);
this.channelMapper.updateById(channel);
}
}

View File

@ -2,9 +2,13 @@ package cn.iocoder.yudao.adminserver.modules.pay.service.merchant;
import java.util.*;
import javax.validation.*;
import cn.hutool.core.collection.CollUtil;
import cn.iocoder.yudao.adminserver.modules.pay.controller.merchant.vo.*;
import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.dept.SysDeptDO;
import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayMerchantDO;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
/**
* 支付商户信息 Service 接口
@ -69,9 +73,46 @@ public interface PayMerchantService {
/**
* 修改商户状态
* @param id 商户编号
*
* @param id 商户编号
* @param status 状态
*/
void updateMerchantStatus(Long id, Integer status);
/**
* 根据商户名称模糊查询商户集合
*
* @param merchantName 商户名称
* @return 商户集合
*/
List<PayMerchantDO> getMerchantListByName(String merchantName);
/**
* 根据商户名称模糊查询一定数量的商户集合
* @param merchantName 商户名称
* @return 商户集合
*/
List<PayMerchantDO> getMerchantListByNameLimit(String merchantName);
/**
* 获得指定编号的商户列表
*
* @param merchantIds 商户编号数组
* @return 商户列表
*/
List<PayMerchantDO> getSimpleMerchants(Collection<Long> merchantIds);
/**
* 获得指定编号的商户 Map
*
* @param merchantIds 商户编号数组
* @return 商户 Map
*/
default Map<Long, PayMerchantDO> getMerchantMap(Collection<Long> merchantIds){
if (CollUtil.isEmpty(merchantIds)) {
return Collections.emptyMap();
}
List<PayMerchantDO> list = getSimpleMerchants(merchantIds);
return CollectionUtils.convertMap(list, PayMerchantDO::getId);
}
}

View File

@ -10,6 +10,8 @@ import cn.iocoder.yudao.adminserver.modules.pay.dal.mysql.merchant.PayMerchantMa
import cn.iocoder.yudao.adminserver.modules.pay.service.merchant.PayMerchantService;
import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayMerchantDO;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.google.common.annotations.VisibleForTesting;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;
@ -24,7 +26,7 @@ import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionU
/**
* 支付商户信息 Service 实现类
*
* @author 芋艿
* @author aquan
*/
@Service
@Validated
@ -37,10 +39,7 @@ public class PayMerchantServiceImpl implements PayMerchantService {
public Long createMerchant(PayMerchantCreateReqVO createReqVO) {
// 插入
PayMerchantDO merchant = PayMerchantConvert.INSTANCE.convert(createReqVO);
// 根据 年月日时分秒毫秒 生成时间戳
// TODO @aquan生成 no 可以单独一个小方法
String merchantNo = "M" + DateUtil.format(LocalDateTime.now(),"yyyyMMddHHmmssSSS");
merchant.setNo(merchantNo);
merchant.setNo(this.generateMerchantNo());
merchantMapper.insert(merchant);
// 返回
return merchant.getId();
@ -106,6 +105,35 @@ public class PayMerchantServiceImpl implements PayMerchantService {
merchantMapper.updateById(merchant);
}
/**
* 根据商户名称模糊查询商户集合
*
* @param merchantName 商户名称
* @return 商户集合
*/
@Override
public List<PayMerchantDO> getMerchantListByName(String merchantName) {
return this.merchantMapper.selectList(new QueryWrapper<PayMerchantDO>()
.lambda().likeRight(PayMerchantDO::getName, merchantName));
}
/**
* 根据商户名称模糊查询一定数量的商户集合
*
* @param merchantName 商户名称
* @return 商户集合
*/
@Override
public List<PayMerchantDO> getMerchantListByNameLimit(String merchantName) {
LambdaQueryWrapper<PayMerchantDO> queryWrapper = new QueryWrapper<PayMerchantDO>().lambda()
.select(PayMerchantDO::getId, PayMerchantDO::getName)
.likeRight(PayMerchantDO::getName, merchantName)
.last("limit 200");
return this.merchantMapper.selectList(queryWrapper);
}
/**
* 检查商户是否存在
* @param id 商户编号
@ -121,5 +149,24 @@ public class PayMerchantServiceImpl implements PayMerchantService {
}
}
/**
* 获得指定编号的商户列表
*
* @param merchantIds 商户编号数组
* @return 商户列表
*/
@Override
public List<PayMerchantDO> getSimpleMerchants(Collection<Long> merchantIds) {
return merchantMapper.selectBatchIds(merchantIds);
}
/**
* 根据年月日时分秒毫秒生成商户号
* @return 商户号
*/
private String generateMerchantNo(){
return "M" + DateUtil.format(LocalDateTime.now(),"yyyyMMddHHmmssSSS");
}
}

View File

@ -44,16 +44,16 @@ spring:
datasource:
master:
name: ruoyi-vue-pro
url: jdbc:mysql://127.0.0.1:3306/${spring.datasource.dynamic.datasource.master.name}?useSSL=false&allowPublicKeyRetrieval=true&useUnicode=true&characterEncoding=UTF-8&serverTimezone=CTT
url: jdbc:mysql://rm-j6cxl87683w973f78ho.mysql.rds.aliyuncs.com:3306/${spring.datasource.dynamic.datasource.master.name}?useSSL=false&allowPublicKeyRetrieval=true&useUnicode=true&characterEncoding=UTF-8&serverTimezone=CTT
driver-class-name: com.mysql.jdbc.Driver
username: root
password: 123456
username: chenquan
password: Miraclequan@990429
slave: # 模拟从库,可根据自己需要修改
name: ruoyi-vue-pro
url: jdbc:mysql://127.0.0.1:3306/${spring.datasource.dynamic.datasource.slave.name}?useSSL=false&allowPublicKeyRetrieval=true&useUnicode=true&characterEncoding=UTF-8&serverTimezone=CTT
url: jdbc:mysql://rm-j6cxl87683w973f78ho.mysql.rds.aliyuncs.com:3306/${spring.datasource.dynamic.datasource.slave.name}?useSSL=false&allowPublicKeyRetrieval=true&useUnicode=true&characterEncoding=UTF-8&serverTimezone=CTT
driver-class-name: com.mysql.jdbc.Driver
username: root
password: 123456
username: chenquan
password: Miraclequan@990429
# Redis 配置。Redisson 默认的配置足够使用,一般不需要进行调优
redis:

View File

@ -60,5 +60,6 @@ yudao:
constants-class-list:
- cn.iocoder.yudao.adminserver.modules.infra.enums.InfErrorCodeConstants
- cn.iocoder.yudao.adminserver.modules.system.enums.SysErrorCodeConstants
pay:
payReturnUrl: http://127.0.0.1
debug: false

View File

@ -0,0 +1,196 @@
package cn.iocoder.yudao.adminserver.modules.pay.app.service;
import javax.annotation.Resource;
import cn.iocoder.yudao.adminserver.BaseDbUnitTest;
import cn.iocoder.yudao.adminserver.modules.pay.controller.app.vo.PayAppCreateReqVO;
import cn.iocoder.yudao.adminserver.modules.pay.controller.app.vo.PayAppExportReqVO;
import cn.iocoder.yudao.adminserver.modules.pay.controller.app.vo.PayAppPageReqVO;
import cn.iocoder.yudao.adminserver.modules.pay.controller.app.vo.PayAppUpdateReqVO;
import cn.iocoder.yudao.adminserver.modules.pay.dal.mysql.app.PayAppMapper;
import cn.iocoder.yudao.adminserver.modules.pay.service.app.impl.PayAppServiceImpl;
import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayAppDO;
import cn.iocoder.yudao.framework.common.util.object.ObjectUtils;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import org.junit.jupiter.api.Test;
import org.springframework.context.annotation.Import;
import java.util.*;
import static cn.iocoder.yudao.coreservice.modules.pay.enums.PayErrorCodeCoreConstants.*;
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals;
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.buildTime;
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.*;
/**
* {@link PayAppServiceImpl} 的单元测试类
*
* @author 芋艿
*/
@Import(PayAppServiceImpl.class)
public class PayAppServiceTest extends BaseDbUnitTest {
@Resource
private PayAppServiceImpl appService;
@Resource
private PayAppMapper appMapper;
@Test
public void testCreateApp_success() {
// 准备参数
PayAppCreateReqVO reqVO = randomPojo(PayAppCreateReqVO.class);
// 调用
Long appId = appService.createApp(reqVO);
// 断言
assertNotNull(appId);
// 校验记录的属性是否正确
PayAppDO app = appMapper.selectById(appId);
assertPojoEquals(reqVO, app);
}
@Test
public void testUpdateApp_success() {
// mock 数据
PayAppDO dbApp = randomPojo(PayAppDO.class);
appMapper.insert(dbApp);// @Sql: 先插入出一条存在的数据
// 准备参数
PayAppUpdateReqVO reqVO = randomPojo(PayAppUpdateReqVO.class, o -> {
o.setId(dbApp.getId()); // 设置更新的 ID
});
// 调用
appService.updateApp(reqVO);
// 校验是否更新正确
PayAppDO app = appMapper.selectById(reqVO.getId()); // 获取最新的
assertPojoEquals(reqVO, app);
}
@Test
public void testUpdateApp_notExists() {
// 准备参数
PayAppUpdateReqVO reqVO = randomPojo(PayAppUpdateReqVO.class);
// 调用, 并断言异常
assertServiceException(() -> appService.updateApp(reqVO), APP_NOT_EXISTS);
}
@Test
public void testDeleteApp_success() {
// mock 数据
PayAppDO dbApp = randomPojo(PayAppDO.class);
appMapper.insert(dbApp);// @Sql: 先插入出一条存在的数据
// 准备参数
Long id = dbApp.getId();
// 调用
appService.deleteApp(id);
// 校验数据不存在了
assertNull(appMapper.selectById(id));
}
@Test
public void testDeleteApp_notExists() {
// 准备参数
Long id = randomLongId();
// 调用, 并断言异常
assertServiceException(() -> appService.deleteApp(id), APP_NOT_EXISTS);
}
@Test // TODO 请修改 null 为需要的值
public void testGetAppPage() {
// mock 数据
PayAppDO dbApp = randomPojo(PayAppDO.class, o -> { // 等会查询到
o.setName(null);
o.setStatus(null);
o.setRemark(null);
o.setPayNotifyUrl(null);
o.setRefundNotifyUrl(null);
o.setMerchantId(null);
o.setCreateTime(null);
});
appMapper.insert(dbApp);
// 测试 name 不匹配
appMapper.insert(ObjectUtils.clone(dbApp, o -> o.setName(null)));
// 测试 status 不匹配
appMapper.insert(ObjectUtils.clone(dbApp, o -> o.setStatus(null)));
// 测试 remark 不匹配
appMapper.insert(ObjectUtils.clone(dbApp, o -> o.setRemark(null)));
// 测试 payNotifyUrl 不匹配
appMapper.insert(ObjectUtils.clone(dbApp, o -> o.setPayNotifyUrl(null)));
// 测试 refundNotifyUrl 不匹配
appMapper.insert(ObjectUtils.clone(dbApp, o -> o.setRefundNotifyUrl(null)));
// 测试 merchantId 不匹配
appMapper.insert(ObjectUtils.clone(dbApp, o -> o.setMerchantId(null)));
// 测试 createTime 不匹配
appMapper.insert(ObjectUtils.clone(dbApp, o -> o.setCreateTime(null)));
// 准备参数
PayAppPageReqVO reqVO = new PayAppPageReqVO();
reqVO.setName(null);
reqVO.setStatus(null);
reqVO.setRemark(null);
reqVO.setPayNotifyUrl(null);
reqVO.setRefundNotifyUrl(null);
reqVO.setBeginCreateTime(null);
reqVO.setEndCreateTime(null);
// 调用
PageResult<PayAppDO> pageResult = appService.getAppPage(reqVO);
// 断言
assertEquals(1, pageResult.getTotal());
assertEquals(1, pageResult.getList().size());
assertPojoEquals(dbApp, pageResult.getList().get(0));
}
@Test // TODO 请修改 null 为需要的值
public void testGetAppList() {
// mock 数据
PayAppDO dbApp = randomPojo(PayAppDO.class, o -> { // 等会查询到
o.setName(null);
o.setStatus(null);
o.setRemark(null);
o.setPayNotifyUrl(null);
o.setRefundNotifyUrl(null);
o.setMerchantId(null);
o.setCreateTime(null);
});
appMapper.insert(dbApp);
// 测试 name 不匹配
appMapper.insert(ObjectUtils.clone(dbApp, o -> o.setName(null)));
// 测试 status 不匹配
appMapper.insert(ObjectUtils.clone(dbApp, o -> o.setStatus(null)));
// 测试 remark 不匹配
appMapper.insert(ObjectUtils.clone(dbApp, o -> o.setRemark(null)));
// 测试 payNotifyUrl 不匹配
appMapper.insert(ObjectUtils.clone(dbApp, o -> o.setPayNotifyUrl(null)));
// 测试 refundNotifyUrl 不匹配
appMapper.insert(ObjectUtils.clone(dbApp, o -> o.setRefundNotifyUrl(null)));
// 测试 merchantId 不匹配
appMapper.insert(ObjectUtils.clone(dbApp, o -> o.setMerchantId(null)));
// 测试 createTime 不匹配
appMapper.insert(ObjectUtils.clone(dbApp, o -> o.setCreateTime(null)));
// 准备参数
PayAppExportReqVO reqVO = new PayAppExportReqVO();
reqVO.setName(null);
reqVO.setStatus(null);
reqVO.setRemark(null);
reqVO.setPayNotifyUrl(null);
reqVO.setRefundNotifyUrl(null);
reqVO.setMerchantId(null);
reqVO.setBeginCreateTime(null);
reqVO.setEndCreateTime(null);
// 调用
List<PayAppDO> list = appService.getAppList(reqVO);
// 断言
assertEquals(1, list.size());
assertPojoEquals(dbApp, list.get(0));
}
}

View File

@ -0,0 +1,204 @@
package cn.iocoder.yudao.adminserver.modules.pay.channel;
import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayChannelDO;
import org.junit.jupiter.api.Test;
import javax.annotation.Resource;
import cn.iocoder.yudao.adminserver.BaseDbUnitTest;
import cn.iocoder.yudao.adminserver.modules.pay.service.channel.impl.PayChannelServiceImpl;
import cn.iocoder.yudao.adminserver.modules.pay.controller.channel.vo.*;
import cn.iocoder.yudao.adminserver.modules.pay.dal.mysql.channel.PayChannelMapper;
import cn.iocoder.yudao.framework.common.util.object.ObjectUtils;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import org.junit.jupiter.api.Test;
import org.springframework.context.annotation.Import;
import java.util.*;
import static cn.iocoder.yudao.coreservice.modules.pay.enums.PayErrorCodeCoreConstants.*;
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals;
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.buildTime;
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.*;
/**
* {@link PayChannelServiceImpl} 的单元测试类
*
* @author 芋艿
*/
@Import(PayChannelServiceImpl.class)
public class PayChannelServiceTest extends BaseDbUnitTest {
@Resource
private PayChannelServiceImpl channelService;
@Resource
private PayChannelMapper channelMapper;
@Test
public void testCreateChannel_success() {
// 准备参数
PayChannelCreateReqVO reqVO = randomPojo(PayChannelCreateReqVO.class);
// 调用
Long channelId = channelService.createChannel(reqVO);
// 断言
assertNotNull(channelId);
// 校验记录的属性是否正确
PayChannelDO channel = channelMapper.selectById(channelId);
assertPojoEquals(reqVO, channel);
}
@Test
public void testUpdateChannel_success() {
// mock 数据
PayChannelDO dbChannel = randomPojo(PayChannelDO.class);
channelMapper.insert(dbChannel);// @Sql: 先插入出一条存在的数据
// 准备参数
PayChannelUpdateReqVO reqVO = randomPojo(PayChannelUpdateReqVO.class, o -> {
o.setId(dbChannel.getId()); // 设置更新的 ID
});
// 调用
channelService.updateChannel(reqVO);
// 校验是否更新正确
PayChannelDO channel = channelMapper.selectById(reqVO.getId()); // 获取最新的
assertPojoEquals(reqVO, channel);
}
@Test
public void testUpdateChannel_notExists() {
// 准备参数
PayChannelUpdateReqVO reqVO = randomPojo(PayChannelUpdateReqVO.class);
// 调用, 并断言异常
assertServiceException(() -> channelService.updateChannel(reqVO), CHANNEL_NOT_EXISTS);
}
@Test
public void testDeleteChannel_success() {
// mock 数据
PayChannelDO dbChannel = randomPojo(PayChannelDO.class);
channelMapper.insert(dbChannel);// @Sql: 先插入出一条存在的数据
// 准备参数
Long id = dbChannel.getId();
// 调用
channelService.deleteChannel(id);
// 校验数据不存在了
assertNull(channelMapper.selectById(id));
}
@Test
public void testDeleteChannel_notExists() {
// 准备参数
Long id = randomLongId();
// 调用, 并断言异常
assertServiceException(() -> channelService.deleteChannel(id), CHANNEL_NOT_EXISTS);
}
@Test // TODO 请修改 null 为需要的值
public void testGetChannelPage() {
// mock 数据
PayChannelDO dbChannel = randomPojo(PayChannelDO.class, o -> { // 等会查询到
o.setCode(null);
o.setStatus(null);
o.setRemark(null);
o.setFeeRate(null);
o.setMerchantId(null);
o.setAppId(null);
o.setConfig(null);
o.setCreateTime(null);
});
channelMapper.insert(dbChannel);
// 测试 code 不匹配
channelMapper.insert(ObjectUtils.clone(dbChannel, o -> o.setCode(null)));
// 测试 status 不匹配
channelMapper.insert(ObjectUtils.clone(dbChannel, o -> o.setStatus(null)));
// 测试 remark 不匹配
channelMapper.insert(ObjectUtils.clone(dbChannel, o -> o.setRemark(null)));
// 测试 feeRate 不匹配
channelMapper.insert(ObjectUtils.clone(dbChannel, o -> o.setFeeRate(null)));
// 测试 merchantId 不匹配
channelMapper.insert(ObjectUtils.clone(dbChannel, o -> o.setMerchantId(null)));
// 测试 appId 不匹配
channelMapper.insert(ObjectUtils.clone(dbChannel, o -> o.setAppId(null)));
// 测试 config 不匹配
channelMapper.insert(ObjectUtils.clone(dbChannel, o -> o.setConfig(null)));
// 测试 createTime 不匹配
channelMapper.insert(ObjectUtils.clone(dbChannel, o -> o.setCreateTime(null)));
// 准备参数
PayChannelPageReqVO reqVO = new PayChannelPageReqVO();
reqVO.setCode(null);
reqVO.setStatus(null);
reqVO.setRemark(null);
reqVO.setFeeRate(null);
reqVO.setMerchantId(null);
reqVO.setAppId(null);
reqVO.setConfig(null);
reqVO.setBeginCreateTime(null);
reqVO.setEndCreateTime(null);
// 调用
PageResult<PayChannelDO> pageResult = channelService.getChannelPage(reqVO);
// 断言
assertEquals(1, pageResult.getTotal());
assertEquals(1, pageResult.getList().size());
assertPojoEquals(dbChannel, pageResult.getList().get(0));
}
@Test // TODO 请修改 null 为需要的值
public void testGetChannelList() {
// mock 数据
PayChannelDO dbChannel = randomPojo(PayChannelDO.class, o -> { // 等会查询到
o.setCode(null);
o.setStatus(null);
o.setRemark(null);
o.setFeeRate(null);
o.setMerchantId(null);
o.setAppId(null);
o.setConfig(null);
o.setCreateTime(null);
});
channelMapper.insert(dbChannel);
// 测试 code 不匹配
channelMapper.insert(ObjectUtils.clone(dbChannel, o -> o.setCode(null)));
// 测试 status 不匹配
channelMapper.insert(ObjectUtils.clone(dbChannel, o -> o.setStatus(null)));
// 测试 remark 不匹配
channelMapper.insert(ObjectUtils.clone(dbChannel, o -> o.setRemark(null)));
// 测试 feeRate 不匹配
channelMapper.insert(ObjectUtils.clone(dbChannel, o -> o.setFeeRate(null)));
// 测试 merchantId 不匹配
channelMapper.insert(ObjectUtils.clone(dbChannel, o -> o.setMerchantId(null)));
// 测试 appId 不匹配
channelMapper.insert(ObjectUtils.clone(dbChannel, o -> o.setAppId(null)));
// 测试 config 不匹配
channelMapper.insert(ObjectUtils.clone(dbChannel, o -> o.setConfig(null)));
// 测试 createTime 不匹配
channelMapper.insert(ObjectUtils.clone(dbChannel, o -> o.setCreateTime(null)));
// 准备参数
PayChannelExportReqVO reqVO = new PayChannelExportReqVO();
reqVO.setCode(null);
reqVO.setStatus(null);
reqVO.setRemark(null);
reqVO.setFeeRate(null);
reqVO.setMerchantId(null);
reqVO.setAppId(null);
reqVO.setConfig(null);
reqVO.setBeginCreateTime(null);
reqVO.setEndCreateTime(null);
// 调用
List<PayChannelDO> list = channelService.getChannelList(reqVO);
// 断言
assertEquals(1, list.size());
assertPojoEquals(dbChannel, list.get(0));
}
}

View File

@ -1,6 +1,9 @@
package cn.iocoder.yudao.adminserver.modules.pay.merchant.service;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import cn.iocoder.yudao.adminserver.BaseDbUnitTest;
import cn.iocoder.yudao.adminserver.modules.pay.controller.merchant.vo.PayMerchantCreateReqVO;
import cn.iocoder.yudao.adminserver.modules.pay.controller.merchant.vo.PayMerchantExportReqVO;
@ -28,7 +31,7 @@ import static org.junit.jupiter.api.Assertions.*;
/**
* {@link PayMerchantServiceImpl} 的单元测试类
*
* @author 芋艿 // TODO @aquan修改成自己的。。。
* @author aquan
*/
@Import(PayMerchantServiceImpl.class)
public class PayMerchantServiceTest extends BaseDbUnitTest {