diff --git a/sql/pay-app-menu.sql b/sql/pay-app-menu.sql new file mode 100644 index 000000000..2b6f9cf77 --- /dev/null +++ b/sql/pay-app-menu.sql @@ -0,0 +1,64 @@ +-- 菜单 SQL +INSERT INTO `sys_menu`( + `name`, `permission`, `menu_type`, `sort`, `parent_id`, + `path`, `icon`, `component`, `status` +) +VALUES ( + '支付应用信息管理', '', 2, 0, 1117, + 'app', '', 'pay/app/index', 0 + ); + +-- 按钮父菜单ID +SELECT @parentId := LAST_INSERT_ID(); + +-- 按钮 SQL +INSERT INTO `sys_menu`( + `name`, `permission`, `menu_type`, `sort`, `parent_id`, + `path`, `icon`, `component`, `status` +) +VALUES ( + '支付应用信息查询', 'pay:app:query', 3, 1, @parentId, + '', '', '', 0 + ); +INSERT INTO `sys_menu`( + `name`, `permission`, `menu_type`, `sort`, `parent_id`, + `path`, `icon`, `component`, `status` +) +VALUES ( + '支付应用信息创建', 'pay:app:create', 3, 2, @parentId, + '', '', '', 0 + ); +INSERT INTO `sys_menu`( + `name`, `permission`, `menu_type`, `sort`, `parent_id`, + `path`, `icon`, `component`, `status` +) +VALUES ( + '支付应用信息更新', 'pay:app:update', 3, 3, @parentId, + '', '', '', 0 + ); +INSERT INTO `sys_menu`( + `name`, `permission`, `menu_type`, `sort`, `parent_id`, + `path`, `icon`, `component`, `status` +) +VALUES ( + '支付应用信息删除', 'pay:app:delete', 3, 4, @parentId, + '', '', '', 0 + ); +INSERT INTO `sys_menu`( + `name`, `permission`, `menu_type`, `sort`, `parent_id`, + `path`, `icon`, `component`, `status` +) +VALUES ( + '支付应用信息导出', 'pay:app:export', 3, 5, @parentId, + '', '', '', 0 + ); + + +INSERT INTO `sys_menu` ( + `name`, `permission`, `menu_type`, `sort`, `parent_id`, + `path`, `icon`, `component`, `status`, `creator`, `create_time`, + `updater`, `update_time`, `deleted` +) VALUES ( + '秘钥解析', 'pay:channel:parsing', 3, 6, 1129, '', '', '', 0, '1', + '2021-11-08 15:15:47', '1', '2021-11-08 15:15:47', b'0' + ); diff --git a/sql/pay-dict.sql b/sql/pay-dict.sql new file mode 100644 index 000000000..3b769568c --- /dev/null +++ b/sql/pay-dict.sql @@ -0,0 +1,24 @@ + +-- 商户状态 status +INSERT INTO `sys_dict_type` ( `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES ( '商户状态', 'pay_merchant_status', 0, '商户的启用于停用状态', '1', '2021-11-03 11:29:04', '1', '2021-11-03 11:29:04', b'0'); + +INSERT INTO `sys_dict_data` ( `sort`, `label`, `value`, `dict_type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES ( 1, '启用', '0', 'pay_merchant_status', 0, '商户启用', '1', '2021-11-03 11:30:52', '1', '2021-11-03 11:31:15', b'0'); +INSERT INTO `sys_dict_data` ( `sort`, `label`, `value`, `dict_type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES ( 2, '停用', '1', 'pay_merchant_status', 0, '商户停用', '1', '2021-11-03 11:31:05', '1', '2021-11-03 11:31:05', b'0'); + +-- 支付应用状态 status +INSERT INTO `sys_dict_type` ( `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES ('支付应用状态', 'pay_app_status', 0, '支付应用的启停状态', '1', '2021-11-06 19:41:50', '1', '2021-11-06 19:41:50', b'0'); + +INSERT INTO `sys_dict_data` ( `sort`, `label`, `value`, `dict_type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES ( 1, '开启', '0', 'pay_app_status', 0, NULL, '1', '2021-11-06 19:42:10', '1', '2021-11-06 19:42:10', b'0'); +INSERT INTO `sys_dict_data` ( `sort`, `label`, `value`, `dict_type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES ( 2, '关闭', '1', 'pay_app_status', 0, NULL, '1', '2021-11-06 19:42:17', '1', '2021-11-06 19:42:17', b'0'); + +-- 支付渠道状态 status +INSERT INTO `sys_dict_type` ( `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES ( '支付渠道状态', 'pay_channel_status', 0, '支付渠道的启停状态', '1', '2021-11-08 16:47:21', '1', '2021-11-08 16:47:21', b'0'); + +INSERT INTO `sys_dict_data` ( `sort`, `label`, `value`, `dict_type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES ( 1, '开启', '0', 'pay_channel_status', 0, '开启', '1', '2021-11-08 16:47:45', '1', '2021-11-08 16:47:45', b'0'); +INSERT INTO `sys_dict_data` ( `sort`, `label`, `value`, `dict_type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES ( 2, '关闭', '1', 'pay_channel_status', 0, '关闭', '1', '2021-11-08 16:47:52', '1', '2021-11-08 16:47:52', b'0'); + +-- 微信渠道版本控制 +INSERT INTO `sys_dict_type` (`name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES ('支付渠道微信版本', 'pay_channel_wechat_version', 0, '支付渠道微信版本', '1', '2021-11-08 17:00:26', '1', '2021-11-08 17:00:26', b'0'); + +INSERT INTO `sys_dict_data` (`sort`, `label`, `value`, `dict_type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1, 'v2', 'v2', 'pay_channel_wechat_version', 0, 'v2版本', '1', '2021-11-08 17:00:58', '1', '2021-11-08 17:00:58', b'0'); +INSERT INTO `sys_dict_data` (`sort`, `label`, `value`, `dict_type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2, 'v3', 'v3', 'pay_channel_wechat_version', 0, 'v3版本', '1', '2021-11-08 17:01:07', '1', '2021-11-08 17:01:07', b'0'); diff --git a/sql/pay-merchant-menu.sql b/sql/pay-merchant-menu.sql index cc4a4e761..65b4ceb9b 100644 --- a/sql/pay-merchant-menu.sql +++ b/sql/pay-merchant-menu.sql @@ -1,9 +1,4 @@ -- 支付模块-商户中心-菜单SQL --- 菜单 SQL -INSERT INTO `sys_menu` ( - `name`, `permission`,`menu_type`,`sort`, `parent_id`, `path`, `icon`, `component`, - `status`, `creator`,`create_time`, `updater`, `update_time`, `deleted` -) VALUES ('支付管理', '', 1, 4,0, '/pay','pay', NULL, 0, '1', '2021-11-03 10:35:04', '1', '2021-11-03 10:35:04', b'0'); INSERT INTO `sys_menu`( `name`, `permission`, `menu_type`, `sort`, `parent_id`, diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/app/PayAppController.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/app/PayAppController.java new file mode 100644 index 000000000..cf3df2aa4 --- /dev/null +++ b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/app/PayAppController.java @@ -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 createApp(@Valid @RequestBody PayAppCreateReqVO createReqVO) { + return success(appService.createApp(createReqVO)); + } + + @PutMapping("/update") + @ApiOperation("更新支付应用信息") + @PreAuthorize("@ss.hasPermission('pay:app:update')") + public CommonResult updateApp(@Valid @RequestBody PayAppUpdateReqVO updateReqVO) { + appService.updateApp(updateReqVO); + return success(true); + } + + @PutMapping("/update-status") + @ApiOperation("更新支付应用状态") + @PreAuthorize("@ss.hasPermission('pay:app:update')") + public CommonResult 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 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 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> getAppList(@RequestParam("ids") Collection ids) { + List list = appService.getAppList(ids); + return success(PayAppConvert.INSTANCE.convertList(list)); + } + + @GetMapping("/page") + @ApiOperation("获得支付应用信息分页") + @PreAuthorize("@ss.hasPermission('pay:app:query')") + public CommonResult> getAppPage(@Valid PayAppPageReqVO pageVO) { + // 得到应用分页列表 + PageResult pageResult = appService.getAppPage(pageVO); + if (CollUtil.isEmpty(pageResult.getList())) { + return success(new PageResult<>(pageResult.getTotal())); + } + + // 得到所有的应用编号,查出所有的通道 + Collection payAppIds = CollectionUtils.convertList(pageResult.getList(), PayAppDO::getId); + List channels = channelService.getSimpleChannels(payAppIds); + + // 得到所有的商户信息 + Collection merchantIds = CollectionUtils.convertList(pageResult.getList(), PayAppDO::getMerchantId); + Map deptMap = merchantService.getMerchantMap(merchantIds); + + // 利用反射将通道数据复制到返回的数据结构中去 + List 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 list = appService.getAppList(exportReqVO); + // 导出 Excel + List datas = PayAppConvert.INSTANCE.convertList02(list); + ExcelUtils.write(response, "支付应用信息.xls", "数据", PayAppExcelVO.class, datas); + } + + + +} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/app/vo/PayAppBaseVO.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/app/vo/PayAppBaseVO.java new file mode 100644 index 000000000..6ffe565ec --- /dev/null +++ b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/app/vo/PayAppBaseVO.java @@ -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; + +} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/app/vo/PayAppCreateReqVO.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/app/vo/PayAppCreateReqVO.java new file mode 100644 index 000000000..3b0e69b99 --- /dev/null +++ b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/app/vo/PayAppCreateReqVO.java @@ -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 { + +} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/app/vo/PayAppExcelVO.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/app/vo/PayAppExcelVO.java new file mode 100644 index 000000000..f81b53bd0 --- /dev/null +++ b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/app/vo/PayAppExcelVO.java @@ -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; + +} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/app/vo/PayAppExportReqVO.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/app/vo/PayAppExportReqVO.java new file mode 100644 index 000000000..e2c68480d --- /dev/null +++ b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/app/vo/PayAppExportReqVO.java @@ -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; + +} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/app/vo/PayAppPageItemRespVO.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/app/vo/PayAppPageItemRespVO.java new file mode 100644 index 000000000..0261090e0 --- /dev/null +++ b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/app/vo/PayAppPageItemRespVO.java @@ -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(); + } +} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/app/vo/PayAppPageReqVO.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/app/vo/PayAppPageReqVO.java new file mode 100644 index 000000000..62156e993 --- /dev/null +++ b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/app/vo/PayAppPageReqVO.java @@ -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; + +} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/app/vo/PayAppRespVO.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/app/vo/PayAppRespVO.java new file mode 100644 index 000000000..565491f92 --- /dev/null +++ b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/app/vo/PayAppRespVO.java @@ -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; + +} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/app/vo/PayAppUpdateReqVO.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/app/vo/PayAppUpdateReqVO.java new file mode 100644 index 000000000..426366fc1 --- /dev/null +++ b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/app/vo/PayAppUpdateReqVO.java @@ -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; + +} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/app/vo/PayAppUpdateStatusReqVO.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/app/vo/PayAppUpdateStatusReqVO.java new file mode 100644 index 000000000..28a3218ae --- /dev/null +++ b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/app/vo/PayAppUpdateStatusReqVO.java @@ -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; + +} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/channel/PayChannelController.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/channel/PayChannelController.java new file mode 100644 index 000000000..b44dfa9a9 --- /dev/null +++ b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/channel/PayChannelController.java @@ -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 createChannel(@Valid @RequestBody PayChannelCreateReqVO createReqVO) { + return success(channelService.createChannel(createReqVO)); + } + + @PutMapping("/update") + @ApiOperation("更新支付渠道 ") + @PreAuthorize("@ss.hasPermission('pay:channel:update')") + public CommonResult 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 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 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> getChannelList(@RequestParam("ids") Collection ids) { + List list = channelService.getChannelList(ids); + return success(PayChannelConvert.INSTANCE.convertList(list)); + } + + @GetMapping("/page") + @ApiOperation("获得支付渠道分页") + @PreAuthorize("@ss.hasPermission('pay:channel:query')") + public CommonResult> getChannelPage(@Valid PayChannelPageReqVO pageVO) { + PageResult 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 list = channelService.getChannelList(exportReqVO); + // 导出 Excel + List 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 parsingPemFile(@RequestParam("file") MultipartFile file) { + return success(channelService.parsingPemFile(file)); + } + + @PostMapping("/create-wechat") + @ApiOperation("创建支付渠道 ") + @PreAuthorize("@ss.hasPermission('pay:channel:create')") + public CommonResult 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 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 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不可为空"); + } + } + +} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/channel/vo/PayChannelBaseVO.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/channel/vo/PayChannelBaseVO.java new file mode 100644 index 000000000..42a98b972 --- /dev/null +++ b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/channel/vo/PayChannelBaseVO.java @@ -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; + +} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/channel/vo/PayChannelCreateReqVO.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/channel/vo/PayChannelCreateReqVO.java new file mode 100644 index 000000000..f19b0384c --- /dev/null +++ b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/channel/vo/PayChannelCreateReqVO.java @@ -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 { + + + +} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/channel/vo/PayChannelExcelVO.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/channel/vo/PayChannelExcelVO.java new file mode 100644 index 000000000..a4618780a --- /dev/null +++ b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/channel/vo/PayChannelExcelVO.java @@ -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; + +} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/channel/vo/PayChannelExportReqVO.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/channel/vo/PayChannelExportReqVO.java new file mode 100644 index 000000000..29e3acdaf --- /dev/null +++ b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/channel/vo/PayChannelExportReqVO.java @@ -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; + +} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/channel/vo/PayChannelPageReqVO.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/channel/vo/PayChannelPageReqVO.java new file mode 100644 index 000000000..83851f944 --- /dev/null +++ b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/channel/vo/PayChannelPageReqVO.java @@ -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; + +} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/channel/vo/PayChannelRespVO.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/channel/vo/PayChannelRespVO.java new file mode 100644 index 000000000..b44625b24 --- /dev/null +++ b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/channel/vo/PayChannelRespVO.java @@ -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; + +} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/channel/vo/PayChannelUpdateReqVO.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/channel/vo/PayChannelUpdateReqVO.java new file mode 100644 index 000000000..658ed8ba3 --- /dev/null +++ b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/channel/vo/PayChannelUpdateReqVO.java @@ -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; + +} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/channel/vo/PayWeChatChannelRespVO.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/channel/vo/PayWeChatChannelRespVO.java new file mode 100644 index 000000000..eafa044fd --- /dev/null +++ b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/channel/vo/PayWeChatChannelRespVO.java @@ -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; + } + +} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/channel/vo/PayWechatChannelCreateReqVO.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/channel/vo/PayWechatChannelCreateReqVO.java new file mode 100644 index 000000000..36bfd579d --- /dev/null +++ b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/channel/vo/PayWechatChannelCreateReqVO.java @@ -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; + } + +} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/channel/vo/PayWechatChannelUpdateReqVO.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/channel/vo/PayWechatChannelUpdateReqVO.java new file mode 100644 index 000000000..60c814308 --- /dev/null +++ b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/channel/vo/PayWechatChannelUpdateReqVO.java @@ -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; + } +} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/merchant/PayMerchantController.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/merchant/PayMerchantController.java index 6ec9af43a..ceb9cb2c7 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/merchant/PayMerchantController.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/merchant/PayMerchantController.java @@ -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> getMerchantListByName(@RequestParam("name") String name) { + List 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) diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/merchant/vo/PayMerchantBaseVO.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/merchant/vo/PayMerchantBaseVO.java index 8bc863792..ed7b69a3f 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/merchant/vo/PayMerchantBaseVO.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/merchant/vo/PayMerchantBaseVO.java @@ -12,10 +12,6 @@ import javax.validation.constraints.NotNull; @Data public class PayMerchantBaseVO { - // TODO @aquan:no 应该不允许修改。啊哈哈,我的原型没画对 - @ApiModelProperty(value = "商户号") - private String no; - @ApiModelProperty(value = "商户全称", required = true) @NotNull(message = "商户全称不能为空") private String name; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/convert/app/PayAppConvert.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/convert/app/PayAppConvert.java new file mode 100644 index 000000000..15da37cbf --- /dev/null +++ b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/convert/app/PayAppConvert.java @@ -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 convertList(List list); + + PageResult convertPage(PageResult page); + + List convertList02(List list); + +} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/convert/channel/PayChannelConvert.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/convert/channel/PayChannelConvert.java new file mode 100644 index 000000000..05cb4d5e4 --- /dev/null +++ b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/convert/channel/PayChannelConvert.java @@ -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 convertList(List list); + + PageResult convertPage(PageResult page); + + List convertList02(List 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); +} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/dal/mysql/app/PayAppMapper.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/dal/mysql/app/PayAppMapper.java new file mode 100644 index 000000000..200ccf296 --- /dev/null +++ b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/dal/mysql/app/PayAppMapper.java @@ -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 { + + default PageResult selectPage(PayAppPageReqVO reqVO,Collection merchantIds) { + return selectPage(reqVO, new QueryWrapperX() + .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 selectList(PayAppExportReqVO reqVO) { + return selectList(new QueryWrapperX() + .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") ); + } + +} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/dal/mysql/channel/PayChannelMapper.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/dal/mysql/channel/PayChannelMapper.java new file mode 100644 index 000000000..2134f08d3 --- /dev/null +++ b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/dal/mysql/channel/PayChannelMapper.java @@ -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 { + + default PageResult selectPage(PayChannelPageReqVO reqVO) { + return selectPage(reqVO, new QueryWrapperX() + .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 selectList(PayChannelExportReqVO reqVO) { + return selectList(new QueryWrapperX() + .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") ); + } + +} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/service/app/PayAppService.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/service/app/PayAppService.java new file mode 100644 index 000000000..8baa6516d --- /dev/null +++ b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/service/app/PayAppService.java @@ -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 getAppList(Collection ids); + + /** + * 获得支付应用信息分页 + * + * @param pageReqVO 分页查询 + * @return 支付应用信息分页 + */ + PageResult getAppPage(PayAppPageReqVO pageReqVO); + + /** + * 获得支付应用信息列表, 用于 Excel 导出 + * + * @param exportReqVO 查询条件 + * @return 支付应用信息列表 + */ + List getAppList(PayAppExportReqVO exportReqVO); + + /** + * 修改应用信息状态 + * + * @param id 应用编号 + * @param status 状态{@link cn.iocoder.yudao.framework.common.enums.CommonStatusEnum} + */ + void updateAppStatus(Long id, Integer status); + + +} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/service/app/impl/PayAppServiceImpl.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/service/app/impl/PayAppServiceImpl.java new file mode 100644 index 000000000..499abe76e --- /dev/null +++ b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/service/app/impl/PayAppServiceImpl.java @@ -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 getAppList(Collection ids) { + return appMapper.selectBatchIds(ids); + } + + @Override + public PageResult getAppPage(PayAppPageReqVO pageReqVO) { + return appMapper.selectPage(pageReqVO,this.getMerchantCondition(pageReqVO.getMerchantName())); + } + + @Override + public List getAppList(PayAppExportReqVO exportReqVO) { + return appMapper.selectList(exportReqVO); + } + + /** + * 获取商户编号集合,根据商户名称模糊查询得到所有的商户编号集合 + * @param merchantName 商户名称 + * @return 商户编号集合 + */ + private Set 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); + } + } +} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/service/channel/PayChannelService.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/service/channel/PayChannelService.java new file mode 100644 index 000000000..420c23123 --- /dev/null +++ b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/service/channel/PayChannelService.java @@ -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 getChannelList(Collection ids); + + /** + * 获得支付渠道 + * 分页 + * + * @param pageReqVO 分页查询 + * @return 支付渠道 + * 分页 + */ + PageResult getChannelPage(PayChannelPageReqVO pageReqVO); + + /** + * 获得支付渠道 + * 列表, 用于 Excel 导出 + * + * @param exportReqVO 查询条件 + * @return 支付渠道 + * 列表 + */ + List getChannelList(PayChannelExportReqVO exportReqVO); + + /** + * 根据支付应用ID集合获取所有的支付渠道 + * + * @param payIds 支付应用编号集合 + * @return 支付渠道 + */ + List getSimpleChannels(Collection 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); +} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/service/channel/impl/PayChannelServiceImpl.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/service/channel/impl/PayChannelServiceImpl.java new file mode 100644 index 000000000..4412ccf90 --- /dev/null +++ b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/service/channel/impl/PayChannelServiceImpl.java @@ -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 getChannelList(Collection ids) { + return channelMapper.selectBatchIds(ids); + } + + @Override + public PageResult getChannelPage(PayChannelPageReqVO pageReqVO) { + return channelMapper.selectPage(pageReqVO); + } + + @Override + public List getChannelList(PayChannelExportReqVO exportReqVO) { + return channelMapper.selectList(exportReqVO); + } + + /** + * 根据支付应用ID集合获取所有的支付渠道 + * + * @param payIds 支付应用编号集合 + * @return 支付渠道 + */ + @Override + public List getSimpleChannels(Collection payIds) { + return channelMapper.selectList(new QueryWrapper().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().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().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); + } +} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/service/merchant/PayMerchantService.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/service/merchant/PayMerchantService.java index db7926c12..be0e66039 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/service/merchant/PayMerchantService.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/service/merchant/PayMerchantService.java @@ -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 getMerchantListByName(String merchantName); + + /** + * 根据商户名称模糊查询一定数量的商户集合 + * @param merchantName 商户名称 + * @return 商户集合 + */ + List getMerchantListByNameLimit(String merchantName); + + /** + * 获得指定编号的商户列表 + * + * @param merchantIds 商户编号数组 + * @return 商户列表 + */ + List getSimpleMerchants(Collection merchantIds); + + /** + * 获得指定编号的商户 Map + * + * @param merchantIds 商户编号数组 + * @return 商户 Map + */ + default Map getMerchantMap(Collection merchantIds){ + if (CollUtil.isEmpty(merchantIds)) { + return Collections.emptyMap(); + } + List list = getSimpleMerchants(merchantIds); + return CollectionUtils.convertMap(list, PayMerchantDO::getId); + } } diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/service/merchant/impl/PayMerchantServiceImpl.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/service/merchant/impl/PayMerchantServiceImpl.java index b329de2c5..556792d2f 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/service/merchant/impl/PayMerchantServiceImpl.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/service/merchant/impl/PayMerchantServiceImpl.java @@ -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 getMerchantListByName(String merchantName) { + return this.merchantMapper.selectList(new QueryWrapper() + .lambda().likeRight(PayMerchantDO::getName, merchantName)); + } + + /** + * 根据商户名称模糊查询一定数量的商户集合 + * + * @param merchantName 商户名称 + * @return 商户集合 + */ + @Override + public List getMerchantListByNameLimit(String merchantName) { + + LambdaQueryWrapper queryWrapper = new QueryWrapper().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 getSimpleMerchants(Collection merchantIds) { + return merchantMapper.selectBatchIds(merchantIds); + } + + /** + * 根据年月日时分秒毫秒生成商户号 + * @return 商户号 + */ + private String generateMerchantNo(){ + return "M" + DateUtil.format(LocalDateTime.now(),"yyyyMMddHHmmssSSS"); + } + } diff --git a/yudao-admin-server/src/main/resources/application-local.yaml b/yudao-admin-server/src/main/resources/application-local.yaml index 4f45d9476..60197c27c 100644 --- a/yudao-admin-server/src/main/resources/application-local.yaml +++ b/yudao-admin-server/src/main/resources/application-local.yaml @@ -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: diff --git a/yudao-admin-server/src/main/resources/application.yaml b/yudao-admin-server/src/main/resources/application.yaml index cad787dfe..26af6c0ed 100644 --- a/yudao-admin-server/src/main/resources/application.yaml +++ b/yudao-admin-server/src/main/resources/application.yaml @@ -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 diff --git a/yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/pay/app/service/PayAppServiceTest.java b/yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/pay/app/service/PayAppServiceTest.java new file mode 100644 index 000000000..8bea96b5f --- /dev/null +++ b/yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/pay/app/service/PayAppServiceTest.java @@ -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 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 list = appService.getAppList(reqVO); + // 断言 + assertEquals(1, list.size()); + assertPojoEquals(dbApp, list.get(0)); + } + +} diff --git a/yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/pay/channel/PayChannelServiceTest.java b/yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/pay/channel/PayChannelServiceTest.java new file mode 100644 index 000000000..5e1875f8d --- /dev/null +++ b/yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/pay/channel/PayChannelServiceTest.java @@ -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 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 list = channelService.getChannelList(reqVO); + // 断言 + assertEquals(1, list.size()); + assertPojoEquals(dbChannel, list.get(0)); + } + +} diff --git a/yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/pay/merchant/service/PayMerchantServiceTest.java b/yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/pay/merchant/service/PayMerchantServiceTest.java index f1f4626e1..f09f570d6 100644 --- a/yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/pay/merchant/service/PayMerchantServiceTest.java +++ b/yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/pay/merchant/service/PayMerchantServiceTest.java @@ -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 { diff --git a/yudao-admin-ui/src/api/pay/app.js b/yudao-admin-ui/src/api/pay/app.js new file mode 100644 index 000000000..788a959ee --- /dev/null +++ b/yudao-admin-ui/src/api/pay/app.js @@ -0,0 +1,67 @@ +import request from '@/utils/request' + +// 创建支付应用信息 +export function createApp(data) { + return request({ + url: '/pay/app/create', + method: 'post', + data: data + }) +} + +// 更新支付应用信息 +export function updateApp(data) { + return request({ + url: '/pay/app/update', + method: 'put', + data: data + }) +} + +// 支付应用信息状态修改 +export function changeAppStatus(id, status) { + const data = { + id, + status + } + return request({ + url: '/pay/app/update-status', + method: 'put', + data: data + }) +} + +// 删除支付应用信息 +export function deleteApp(id) { + return request({ + url: '/pay/app/delete?id=' + id, + method: 'delete' + }) +} + +// 获得支付应用信息 +export function getApp(id) { + return request({ + url: '/pay/app/get?id=' + id, + method: 'get' + }) +} + +// 获得支付应用信息分页 +export function getAppPage(query) { + return request({ + url: '/pay/app/page', + method: 'get', + params: query + }) +} + +// 导出支付应用信息 Excel +export function exportAppExcel(query) { + return request({ + url: '/pay/app/export-excel', + method: 'get', + params: query, + responseType: 'blob' + }) +} diff --git a/yudao-admin-ui/src/api/pay/channel.js b/yudao-admin-ui/src/api/pay/channel.js new file mode 100644 index 000000000..2a2accbd4 --- /dev/null +++ b/yudao-admin-ui/src/api/pay/channel.js @@ -0,0 +1,88 @@ +import request from '@/utils/request' + +// 创建支付渠道 +export function createChannel(data) { + return request({ + url: '/pay/channel/create', + method: 'post', + data: data + }) +} + + +// 更新支付渠道 +export function updateChannel(data) { + return request({ + url: '/pay/channel/update', + method: 'put', + data: data + }) +} + +// 删除支付渠道 +export function deleteChannel(id) { + return request({ + url: '/pay/channel/delete?id=' + id, + method: 'delete' + }) +} + +// 获得支付渠道 +export function getChannel(id) { + return request({ + url: '/pay/channel/get?id=' + id, + method: 'get' + }) +} + + + +// 获得支付渠道分页 +export function getChannelPage(query) { + return request({ + url: '/pay/channel/page', + method: 'get', + params: query + }) +} + +// 导出支付渠道Excel +export function exportChannelExcel(query) { + return request({ + url: '/pay/channel/export-excel', + method: 'get', + params: query, + responseType: 'blob' + }) +} + +// 创建微信支付渠道 +export function createWechatChannel(data) { + return request({ + url: '/pay/channel/create-wechat', + method: 'post', + data: data + }) +} + +// 获得支付渠道 +export function getWechatChannel(merchantId,appId,code) { + return request({ + url: '/pay/channel/get-wechat', + params:{ + merchantId:merchantId, + appId:appId, + code:code + }, + method: 'get' + }) +} + +// 更新支付渠道 +export function updateWechatChannel(data) { + return request({ + url: '/pay/channel/update-wechat', + method: 'put', + data: data + }) +} diff --git a/yudao-admin-ui/src/api/pay/merchant.js b/yudao-admin-ui/src/api/pay/merchant.js index 5dc6e96ee..1c6d7e20a 100644 --- a/yudao-admin-ui/src/api/pay/merchant.js +++ b/yudao-admin-ui/src/api/pay/merchant.js @@ -46,6 +46,16 @@ export function getMerchant(id) { method: 'get' }) } +// 根据商户名称搜索商户列表 +export function getMerchantListByName(name) { + return request({ + url: '/pay/merchant/list-name', + params:{ + name:name + }, + method: 'get' + }) +} // 获得支付商户信息分页 export function getMerchantPage(query) { diff --git a/yudao-admin-ui/src/assets/icons/svg/Mockitt-win32-x64-zh-1.1.7.exe b/yudao-admin-ui/src/assets/icons/svg/Mockitt-win32-x64-zh-1.1.7.exe new file mode 100644 index 000000000..0f2d4a27d Binary files /dev/null and b/yudao-admin-ui/src/assets/icons/svg/Mockitt-win32-x64-zh-1.1.7.exe differ diff --git a/yudao-admin-ui/src/assets/icons/svg/config.svg b/yudao-admin-ui/src/assets/icons/svg/config.svg new file mode 100644 index 000000000..79db5fb6a --- /dev/null +++ b/yudao-admin-ui/src/assets/icons/svg/config.svg @@ -0,0 +1,2 @@ + \ No newline at end of file diff --git a/yudao-admin-ui/src/assets/icons/svg/percentSign.svg b/yudao-admin-ui/src/assets/icons/svg/percentSign.svg new file mode 100644 index 000000000..bedbce63d --- /dev/null +++ b/yudao-admin-ui/src/assets/icons/svg/percentSign.svg @@ -0,0 +1,2 @@ + \ No newline at end of file diff --git a/yudao-admin-ui/src/utils/constants.js b/yudao-admin-ui/src/utils/constants.js index d0251ae68..f4cd50a2c 100644 --- a/yudao-admin-ui/src/utils/constants.js +++ b/yudao-admin-ui/src/utils/constants.js @@ -16,7 +16,7 @@ export const SysCommonStatusEnum = { * 菜单的类型枚举 */ export const SysMenuTypeEnum = { - DIR : 1, // 目录 + DIR: 1, // 目录 MENU: 2, // 菜单 BUTTON: 3 // 按钮 } @@ -90,3 +90,34 @@ export const SysUserSocialTypeEnum = { img: "https://cdn.jsdelivr.net/gh/justauth/justauth-oauth-logo@1.11/wechat_enterprise.png", } } + +export const PayChannelEnum = { + WX_PUB: { + "code": "wx_pub", + "name": "微信 JSAPI 支付", + }, + WX_LITE: { + "code": "wx_lite", + "name": "微信小程序支付" + }, + WX_APP: { + "code": "wx_app", + "name": "微信 APP 支付" + }, + ALIPAY_PC: { + "code": "alipay_pc", + "name": "支付宝 PC 网站支付" + }, + ALIPAY_WAP: { + "code": "alipay_wap", + "name": "支付宝 WAP 网站支付" + }, + ALIPAY_APP: { + "code": "alipay_app", + "name": "支付宝 APP 支付" + }, + ALIPAY_QR: { + "code": "alipay_qr", + "name": "支付宝扫码支付" + }, +} diff --git a/yudao-admin-ui/src/utils/dict.js b/yudao-admin-ui/src/utils/dict.js index 7c17cceb8..f084b2e62 100644 --- a/yudao-admin-ui/src/utils/dict.js +++ b/yudao-admin-ui/src/utils/dict.js @@ -32,7 +32,14 @@ export const DICT_TYPE = { TOOL_CODEGEN_TEMPLATE_TYPE: 'tool_codegen_template_type', // 商户状态 - PAY_MERCHANT_STATUS: 'pay_merchant_status' + PAY_MERCHANT_STATUS: 'pay_merchant_status', + // 应用状态 + PAY_APP_STATUS: 'pay_app_status', + // 渠道状态 + PAY_CHANNEL_STATUS: 'pay_channel_status', + // 微信渠道版本 + PAY_CHANNEL_WECHAT_VERSION:'pay_channel_wechat_version', + } /** diff --git a/yudao-admin-ui/src/views/pay/app/components/wechatJsApiForm.vue b/yudao-admin-ui/src/views/pay/app/components/wechatJsApiForm.vue new file mode 100644 index 000000000..01a984c2e --- /dev/null +++ b/yudao-admin-ui/src/views/pay/app/components/wechatJsApiForm.vue @@ -0,0 +1,261 @@ + + + diff --git a/yudao-admin-ui/src/views/pay/app/index.vue b/yudao-admin-ui/src/views/pay/app/index.vue new file mode 100644 index 000000000..e24ff4cd7 --- /dev/null +++ b/yudao-admin-ui/src/views/pay/app/index.vue @@ -0,0 +1,441 @@ + + + diff --git a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/dal/dataobject/merchant/PayChannelDO.java b/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/dal/dataobject/merchant/PayChannelDO.java index 2101e6634..074585e5d 100644 --- a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/dal/dataobject/merchant/PayChannelDO.java +++ b/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/dal/dataobject/merchant/PayChannelDO.java @@ -47,6 +47,11 @@ public class PayChannelDO extends BaseDO { */ private Double feeRate; + /** + * 备注 + */ + private String remark; + /** * 商户编号 * diff --git a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/dal/dataobject/merchant/PayMerchantDO.java b/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/dal/dataobject/merchant/PayMerchantDO.java index 3c32cf86d..a0c72b9ec 100644 --- a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/dal/dataobject/merchant/PayMerchantDO.java +++ b/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/dal/dataobject/merchant/PayMerchantDO.java @@ -33,7 +33,6 @@ public class PayMerchantDO extends BaseDO { * 例如说,M233666999 * 只有新增时插入,不允许修改 */ - @TableField(fill = FieldFill.INSERT) // TODO @aquan:Service 逻辑里设置,所以不用这个注解哈 private String no; /** * 商户全称 diff --git a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/enums/PayErrorCodeCoreConstants.java b/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/enums/PayErrorCodeCoreConstants.java index a4c88d8c0..a7ed739e3 100644 --- a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/enums/PayErrorCodeCoreConstants.java +++ b/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/enums/PayErrorCodeCoreConstants.java @@ -32,4 +32,18 @@ public interface PayErrorCodeCoreConstants { * ========== 支付商户信息 1-007-004-000 ========== */ ErrorCode MERCHANT_NOT_EXISTS = new ErrorCode(1007004000, "支付商户信息不存在"); + + + /** + * ========== 支付应用信息 1-007-005-000 ========== + */ + ErrorCode APP_NOT_EXISTS = new ErrorCode(1007005000, "支付应用信息不存在"); + + + /** + * ========== 支付渠道 1-007-006-000 ========== + */ + ErrorCode CHANNEL_NOT_EXISTS = new ErrorCode(1007006000, "支付渠道不存在"); + ErrorCode CHANNEL_KEY_READ_ERROR = new ErrorCode(1007006002, "支付渠道秘钥文件读取失败"); + ErrorCode EXIST_SAME_CHANNEL_ERROR = new ErrorCode(1007006003, "已存在相同的渠道"); } diff --git a/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/PayClientFactoryImpl.java b/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/PayClientFactoryImpl.java index 16cc49ed2..7c1c3efb2 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/PayClientFactoryImpl.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/PayClientFactoryImpl.java @@ -58,8 +58,11 @@ public class PayClientFactoryImpl implements PayClientFactory { PayChannelEnum channelEnum = PayChannelEnum.getByCode(channelCode); Assert.notNull(channelEnum, String.format("支付渠道(%s) 为空", channelEnum)); // 创建客户端 + // TODO @芋艿 WX_LITE WX_APP 如果不添加在 项目启动的时候去初始化会报错无法启动。所以我手动加了两个,具体需要你来配 switch (channelEnum) { case WX_PUB: return (AbstractPayClient) new WXPubPayClient(channelId, (WXPayClientConfig) config); + case WX_LITE: return (AbstractPayClient) new WXPubPayClient(channelId, (WXPayClientConfig) config); + case WX_APP: return (AbstractPayClient) new WXPubPayClient(channelId, (WXPayClientConfig) config); case ALIPAY_WAP: return (AbstractPayClient) new AlipayWapPayClient(channelId, (AlipayPayClientConfig) config); case ALIPAY_QR: return (AbstractPayClient) new AlipayQrPayClient(channelId, (AlipayPayClientConfig) config); } diff --git a/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/enums/PayChannelEnum.java b/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/enums/PayChannelEnum.java index ed1389e0e..a6734d961 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/enums/PayChannelEnum.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/enums/PayChannelEnum.java @@ -15,7 +15,8 @@ import lombok.Getter; public enum PayChannelEnum { WX_PUB("wx_pub", "微信 JSAPI 支付"), // 公众号的网页 - WX_LITE("wx_lit","微信小程序支付"), + // TODO @芋艿 这个地方你写的是 wx_lit 是不是少写了一个e? 还是我这里多加了一个e + WX_LITE("wx_lite","微信小程序支付"), WX_APP("wx_app", "微信 App 支付"), ALIPAY_PC("alipay_pc", "支付宝 PC 网站支付"),