完成支付模块支付应用信息和微信类型的支付渠道配置。
This commit is contained in:
parent
6265e4a736
commit
e46a27b937
|
@ -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'
|
||||
);
|
|
@ -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');
|
|
@ -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`,
|
||||
|
|
|
@ -0,0 +1,175 @@
|
|||
package cn.iocoder.yudao.adminserver.modules.pay.controller.app;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.iocoder.yudao.adminserver.modules.pay.controller.app.vo.*;
|
||||
import cn.iocoder.yudao.adminserver.modules.pay.convert.app.PayAppConvert;
|
||||
import cn.iocoder.yudao.adminserver.modules.pay.service.app.PayAppService;
|
||||
import cn.iocoder.yudao.adminserver.modules.pay.service.channel.PayChannelService;
|
||||
import cn.iocoder.yudao.adminserver.modules.pay.service.merchant.PayMerchantService;
|
||||
import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayAppDO;
|
||||
import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayChannelDO;
|
||||
import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayMerchantDO;
|
||||
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
|
||||
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
|
||||
import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiImplicitParam;
|
||||
import io.swagger.annotations.ApiImplicitParams;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.validation.Valid;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
||||
import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT;
|
||||
|
||||
/**
|
||||
* 支付应用信息 controller 组件
|
||||
*
|
||||
* @author aquan
|
||||
*/
|
||||
@Slf4j
|
||||
@Api(tags = "支付应用信息")
|
||||
@RestController
|
||||
@RequestMapping("/pay/app")
|
||||
@Validated
|
||||
public class PayAppController {
|
||||
|
||||
@Resource
|
||||
private PayAppService appService;
|
||||
|
||||
@Resource
|
||||
private PayChannelService channelService;
|
||||
|
||||
|
||||
@Resource
|
||||
private PayMerchantService merchantService;
|
||||
|
||||
@PostMapping("/create")
|
||||
@ApiOperation("创建支付应用信息")
|
||||
@PreAuthorize("@ss.hasPermission('pay:app:create')")
|
||||
public CommonResult<Long> createApp(@Valid @RequestBody PayAppCreateReqVO createReqVO) {
|
||||
return success(appService.createApp(createReqVO));
|
||||
}
|
||||
|
||||
@PutMapping("/update")
|
||||
@ApiOperation("更新支付应用信息")
|
||||
@PreAuthorize("@ss.hasPermission('pay:app:update')")
|
||||
public CommonResult<Boolean> updateApp(@Valid @RequestBody PayAppUpdateReqVO updateReqVO) {
|
||||
appService.updateApp(updateReqVO);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@PutMapping("/update-status")
|
||||
@ApiOperation("更新支付应用状态")
|
||||
@PreAuthorize("@ss.hasPermission('pay:app:update')")
|
||||
public CommonResult<Boolean> updateAppStatus(@Valid @RequestBody PayAppUpdateStatusReqVO updateReqVO) {
|
||||
appService.updateAppStatus(updateReqVO.getId(), updateReqVO.getStatus());
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@DeleteMapping("/delete")
|
||||
@ApiOperation("删除支付应用信息")
|
||||
@ApiImplicitParam(name = "id", value = "编号", required = true)
|
||||
@PreAuthorize("@ss.hasPermission('pay:app:delete')")
|
||||
public CommonResult<Boolean> deleteApp(@RequestParam("id") Long id) {
|
||||
appService.deleteApp(id);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@GetMapping("/get")
|
||||
@ApiOperation("获得支付应用信息")
|
||||
@ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class)
|
||||
@PreAuthorize("@ss.hasPermission('pay:app:query')")
|
||||
public CommonResult<PayAppRespVO> getApp(@RequestParam("id") Long id) {
|
||||
PayAppDO app = appService.getApp(id);
|
||||
return success(PayAppConvert.INSTANCE.convert(app));
|
||||
}
|
||||
|
||||
@GetMapping("/list")
|
||||
@ApiOperation("获得支付应用信息列表")
|
||||
@ApiImplicitParam(name = "ids", value = "编号列表", required = true, example = "1024,2048", dataTypeClass = List.class)
|
||||
@PreAuthorize("@ss.hasPermission('pay:app:query')")
|
||||
public CommonResult<List<PayAppRespVO>> getAppList(@RequestParam("ids") Collection<Long> ids) {
|
||||
List<PayAppDO> list = appService.getAppList(ids);
|
||||
return success(PayAppConvert.INSTANCE.convertList(list));
|
||||
}
|
||||
|
||||
@GetMapping("/page")
|
||||
@ApiOperation("获得支付应用信息分页")
|
||||
@PreAuthorize("@ss.hasPermission('pay:app:query')")
|
||||
public CommonResult<PageResult<PayAppPageItemRespVO>> getAppPage(@Valid PayAppPageReqVO pageVO) {
|
||||
// 得到应用分页列表
|
||||
PageResult<PayAppDO> pageResult = appService.getAppPage(pageVO);
|
||||
if (CollUtil.isEmpty(pageResult.getList())) {
|
||||
return success(new PageResult<>(pageResult.getTotal()));
|
||||
}
|
||||
|
||||
// 得到所有的应用编号,查出所有的通道
|
||||
Collection<Long> payAppIds = CollectionUtils.convertList(pageResult.getList(), PayAppDO::getId);
|
||||
List<PayChannelDO> channels = channelService.getSimpleChannels(payAppIds);
|
||||
|
||||
// 得到所有的商户信息
|
||||
Collection<Long> merchantIds = CollectionUtils.convertList(pageResult.getList(), PayAppDO::getMerchantId);
|
||||
Map<Long, PayMerchantDO> deptMap = merchantService.getMerchantMap(merchantIds);
|
||||
|
||||
// 利用反射将通道数据复制到返回的数据结构中去
|
||||
List<PayAppPageItemRespVO> appList = new ArrayList<>(pageResult.getList().size());
|
||||
pageResult.getList().forEach(app -> {
|
||||
// 写入应用信息的数据
|
||||
PayAppPageItemRespVO respVO = PayAppConvert.INSTANCE.pageConvert(app);
|
||||
// 写入商户的数据
|
||||
respVO.setPayMerchant(PayAppConvert.INSTANCE.convert(deptMap.get(app.getMerchantId())));
|
||||
// 写入支付渠道信息的数据
|
||||
PayAppPageItemRespVO.PayChannel payChannel = new PayAppPageItemRespVO.PayChannel();
|
||||
channels.forEach(c -> {
|
||||
if (c.getAppId().equals(app.getId())) {
|
||||
// 获取 set 方法
|
||||
String methodName = StrUtil.toCamelCase("set_" + c.getCode());
|
||||
try {
|
||||
// 根据 set 方法将值写入
|
||||
payChannel.getClass().getMethod(methodName, Integer.class)
|
||||
.invoke(payChannel, CommonStatusEnum.ENABLE.getStatus());
|
||||
} catch (IllegalAccessException | NoSuchMethodException | InvocationTargetException e) {
|
||||
log.error("[getAppPage]调用方法[{}]设置参数[{}]异常", c.getCode(), methodName);
|
||||
}
|
||||
}
|
||||
});
|
||||
respVO.setPayChannel(payChannel);
|
||||
appList.add(respVO);
|
||||
});
|
||||
|
||||
return success(new PageResult<>(appList, pageResult.getTotal()));
|
||||
}
|
||||
|
||||
@GetMapping("/export-excel")
|
||||
@ApiOperation("导出支付应用信息 Excel")
|
||||
@PreAuthorize("@ss.hasPermission('pay:app:export')")
|
||||
@OperateLog(type = EXPORT)
|
||||
public void exportAppExcel(@Valid PayAppExportReqVO exportReqVO,
|
||||
HttpServletResponse response) throws IOException {
|
||||
List<PayAppDO> list = appService.getAppList(exportReqVO);
|
||||
// 导出 Excel
|
||||
List<PayAppExcelVO> datas = PayAppConvert.INSTANCE.convertList02(list);
|
||||
ExcelUtils.write(response, "支付应用信息.xls", "数据", PayAppExcelVO.class, datas);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
|
@ -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;
|
||||
|
||||
}
|
|
@ -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 {
|
||||
|
||||
}
|
|
@ -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;
|
||||
|
||||
}
|
|
@ -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;
|
||||
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
|
||||
}
|
|
@ -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;
|
||||
|
||||
}
|
|
@ -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;
|
||||
|
||||
}
|
|
@ -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;
|
||||
|
||||
}
|
|
@ -0,0 +1,190 @@
|
|||
package cn.iocoder.yudao.adminserver.modules.pay.controller.channel;
|
||||
|
||||
import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayChannelDO;
|
||||
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
|
||||
import cn.iocoder.yudao.framework.pay.core.client.impl.wx.WXPayClientConfig;
|
||||
import cn.iocoder.yudao.framework.pay.core.client.impl.wx.WXPubPayClient;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
|
||||
import io.swagger.annotations.*;
|
||||
|
||||
import javax.validation.*;
|
||||
import javax.servlet.http.*;
|
||||
import java.util.*;
|
||||
import java.io.IOException;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
||||
|
||||
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
|
||||
|
||||
import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
|
||||
|
||||
import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.*;
|
||||
|
||||
import cn.iocoder.yudao.adminserver.modules.pay.controller.channel.vo.*;
|
||||
import cn.iocoder.yudao.adminserver.modules.pay.convert.channel.PayChannelConvert;
|
||||
import cn.iocoder.yudao.adminserver.modules.pay.service.channel.PayChannelService;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
@Api(tags = "支付渠道")
|
||||
@RestController
|
||||
@RequestMapping("/pay/channel")
|
||||
@Validated
|
||||
public class PayChannelController {
|
||||
|
||||
@Resource
|
||||
private PayChannelService channelService;
|
||||
|
||||
// todo 芋艿 这几个生成的方法是没用到的 您看要不删除了把? -----start
|
||||
@PostMapping("/create")
|
||||
@ApiOperation("创建支付渠道 ")
|
||||
@PreAuthorize("@ss.hasPermission('pay:channel:create')")
|
||||
public CommonResult<Long> createChannel(@Valid @RequestBody PayChannelCreateReqVO createReqVO) {
|
||||
return success(channelService.createChannel(createReqVO));
|
||||
}
|
||||
|
||||
@PutMapping("/update")
|
||||
@ApiOperation("更新支付渠道 ")
|
||||
@PreAuthorize("@ss.hasPermission('pay:channel:update')")
|
||||
public CommonResult<Boolean> updateChannel(@Valid @RequestBody PayChannelUpdateReqVO updateReqVO) {
|
||||
channelService.updateChannel(updateReqVO);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@DeleteMapping("/delete")
|
||||
@ApiOperation("删除支付渠道 ")
|
||||
@ApiImplicitParam(name = "id", value = "编号", required = true)
|
||||
@PreAuthorize("@ss.hasPermission('pay:channel:delete')")
|
||||
public CommonResult<Boolean> deleteChannel(@RequestParam("id") Long id) {
|
||||
channelService.deleteChannel(id);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@GetMapping("/get")
|
||||
@ApiOperation("获得支付渠道 ")
|
||||
@ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class)
|
||||
@PreAuthorize("@ss.hasPermission('pay:channel:query')")
|
||||
public CommonResult<PayChannelRespVO> getChannel(@RequestParam("id") Long id) {
|
||||
PayChannelDO channel = channelService.getChannel(id);
|
||||
return success(PayChannelConvert.INSTANCE.convert(channel));
|
||||
}
|
||||
|
||||
@GetMapping("/list")
|
||||
@ApiOperation("获得支付渠道列表")
|
||||
@ApiImplicitParam(name = "ids", value = "编号列表",
|
||||
required = true, example = "1024,2048", dataTypeClass = List.class)
|
||||
@PreAuthorize("@ss.hasPermission('pay:channel:query')")
|
||||
public CommonResult<List<PayChannelRespVO>> getChannelList(@RequestParam("ids") Collection<Long> ids) {
|
||||
List<PayChannelDO> list = channelService.getChannelList(ids);
|
||||
return success(PayChannelConvert.INSTANCE.convertList(list));
|
||||
}
|
||||
|
||||
@GetMapping("/page")
|
||||
@ApiOperation("获得支付渠道分页")
|
||||
@PreAuthorize("@ss.hasPermission('pay:channel:query')")
|
||||
public CommonResult<PageResult<PayChannelRespVO>> getChannelPage(@Valid PayChannelPageReqVO pageVO) {
|
||||
PageResult<PayChannelDO> pageResult = channelService.getChannelPage(pageVO);
|
||||
return success(PayChannelConvert.INSTANCE.convertPage(pageResult));
|
||||
}
|
||||
|
||||
@GetMapping("/export-excel")
|
||||
@ApiOperation("导出支付渠道Excel")
|
||||
@PreAuthorize("@ss.hasPermission('pay:channel:export')")
|
||||
@OperateLog(type = EXPORT)
|
||||
public void exportChannelExcel(@Valid PayChannelExportReqVO exportReqVO,
|
||||
HttpServletResponse response) throws IOException {
|
||||
List<PayChannelDO> list = channelService.getChannelList(exportReqVO);
|
||||
// 导出 Excel
|
||||
List<PayChannelExcelVO> datas = PayChannelConvert.INSTANCE.convertList02(list);
|
||||
ExcelUtils.write(response, "支付渠道.xls", "数据", PayChannelExcelVO.class, datas);
|
||||
}
|
||||
|
||||
// todo 芋艿 这几个生成的方法是没用到的 您看要不删除了把? -----end
|
||||
|
||||
@PostMapping("/parsing-pem")
|
||||
@ApiOperation("解析pem证书转换为字符串")
|
||||
@PreAuthorize("@ss.hasPermission('pay:channel:parsing')")
|
||||
@ApiImplicitParam(name = "file", value = "pem文件", required = true, dataTypeClass = MultipartFile.class)
|
||||
public CommonResult<String> parsingPemFile(@RequestParam("file") MultipartFile file) {
|
||||
return success(channelService.parsingPemFile(file));
|
||||
}
|
||||
|
||||
@PostMapping("/create-wechat")
|
||||
@ApiOperation("创建支付渠道 ")
|
||||
@PreAuthorize("@ss.hasPermission('pay:channel:create')")
|
||||
public CommonResult<Long> createWechatChannel(@Valid @RequestBody PayWechatChannelCreateReqVO reqVO) {
|
||||
// 针对于 V2 或者 V3 版本的参数校验
|
||||
this.paramAdvanceCheck(reqVO.getWeChatConfig().getApiVersion(),reqVO.getWeChatConfig().getMchKey(),
|
||||
reqVO.getWeChatConfig().getPrivateKeyContent(),reqVO.getWeChatConfig().getPrivateCertContent());
|
||||
|
||||
return success(channelService.createWechatChannel(reqVO));
|
||||
}
|
||||
|
||||
@GetMapping("/get-wechat")
|
||||
@ApiOperation("根据条件查询微信支付渠道")
|
||||
@ApiImplicitParams({
|
||||
@ApiImplicitParam(name = "merchantId", value = "商户编号",
|
||||
required = true, example = "1", dataTypeClass = Long.class),
|
||||
@ApiImplicitParam(name = "appId", value = "应用编号",
|
||||
required = true, example = "1", dataTypeClass = Long.class),
|
||||
@ApiImplicitParam(name = "code", value = "支付渠道编码",
|
||||
required = true, example = "wx_pub", dataTypeClass = String.class)
|
||||
})
|
||||
@PreAuthorize("@ss.hasPermission('pay:channel:query')")
|
||||
public CommonResult<PayWeChatChannelRespVO> getWeChatChannel(
|
||||
@RequestParam Long merchantId, @RequestParam Long appId, @RequestParam String code) {
|
||||
|
||||
// 獲取渠道
|
||||
PayChannelDO channel = channelService.getChannelByConditions(merchantId, appId, code);
|
||||
if (channel == null) {
|
||||
return success(new PayWeChatChannelRespVO());
|
||||
}
|
||||
|
||||
// 拼凑数据
|
||||
PayWeChatChannelRespVO respVo = PayChannelConvert.INSTANCE.convert2(channel);
|
||||
WXPayClientConfig config = (WXPayClientConfig) channel.getConfig();
|
||||
respVo.setWeChatConfig(PayChannelConvert.INSTANCE.configConvert(config));
|
||||
return success(respVo);
|
||||
}
|
||||
|
||||
@PutMapping("/update-wechat")
|
||||
@ApiOperation("更新微信支付渠道 ")
|
||||
@PreAuthorize("@ss.hasPermission('pay:channel:update')")
|
||||
public CommonResult<Boolean> updateWechatChannel(@Valid @RequestBody PayWechatChannelUpdateReqVO updateReqVO) {
|
||||
|
||||
// 针对于 V2 或者 V3 版本的参数校验
|
||||
this.paramAdvanceCheck(updateReqVO.getWeChatConfig().getApiVersion(),updateReqVO.getWeChatConfig().getMchKey(),
|
||||
updateReqVO.getWeChatConfig().getPrivateKeyContent(),updateReqVO.getWeChatConfig().getPrivateCertContent());
|
||||
|
||||
channelService.updateWechatChannel(updateReqVO);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* 预检测微信秘钥参数
|
||||
* @param version 版本
|
||||
* @param mchKey v2版本秘钥
|
||||
* @param privateKeyContent v3版本apiclient_key
|
||||
* @param privateCertContent v3版本中apiclient_cert
|
||||
*/
|
||||
private void paramAdvanceCheck(String version, String mchKey, String privateKeyContent, String privateCertContent) {
|
||||
// 针对于 V2 或者 V3 版本的参数校验
|
||||
if (version.equals(WXPayClientConfig.API_VERSION_V2)) {
|
||||
Assert.notNull(mchKey, "v2版本中商户密钥不可为空");
|
||||
}
|
||||
if (version.equals(WXPayClientConfig.API_VERSION_V3)) {
|
||||
Assert.notNull(privateKeyContent, "v3版本apiclient_key.pem不可为空");
|
||||
Assert.notNull(privateCertContent, "v3版本中apiclient_cert.pem不可为空");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
|
||||
}
|
|
@ -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 {
|
||||
|
||||
|
||||
|
||||
}
|
|
@ -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;
|
||||
|
||||
}
|
|
@ -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;
|
||||
|
||||
}
|
|
@ -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;
|
||||
|
||||
}
|
|
@ -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;
|
||||
|
||||
}
|
|
@ -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;
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -3,7 +3,6 @@ package cn.iocoder.yudao.adminserver.modules.pay.controller.merchant;
|
|||
import cn.iocoder.yudao.adminserver.modules.pay.controller.merchant.vo.*;
|
||||
import cn.iocoder.yudao.adminserver.modules.pay.convert.merchant.PayMerchantConvert;
|
||||
import cn.iocoder.yudao.adminserver.modules.pay.service.merchant.PayMerchantService;
|
||||
import cn.iocoder.yudao.adminserver.modules.system.controller.user.vo.user.SysUserUpdateStatusReqVO;
|
||||
import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayMerchantDO;
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
|
@ -76,6 +75,15 @@ public class PayMerchantController {
|
|||
return success(PayMerchantConvert.INSTANCE.convert(merchant));
|
||||
}
|
||||
|
||||
@GetMapping("/list-name")
|
||||
@ApiOperation("根据商户名称获得支付商户信息列表")
|
||||
@ApiImplicitParam(name = "name", value = "商户名称", required = true, example = "芋道", dataTypeClass = Long.class)
|
||||
@PreAuthorize("@ss.hasPermission('pay:merchant:query')")
|
||||
public CommonResult<List<PayMerchantRespVO>> getMerchantListByName(@RequestParam("name") String name) {
|
||||
List<PayMerchantDO> merchantListDO = merchantService.getMerchantListByNameLimit(name);
|
||||
return success(PayMerchantConvert.INSTANCE.convertList(merchantListDO));
|
||||
}
|
||||
|
||||
@GetMapping("/list")
|
||||
@ApiOperation("获得支付商户信息列表")
|
||||
@ApiImplicitParam(name = "ids", value = "编号列表", required = true, example = "1024,2048", dataTypeClass = List.class)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
package cn.iocoder.yudao.adminserver.modules.pay.convert.app;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import cn.iocoder.yudao.adminserver.modules.system.controller.user.vo.user.SysUserPageItemRespVO;
|
||||
import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.dept.SysDeptDO;
|
||||
import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayAppDO;
|
||||
import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayMerchantDO;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
import cn.iocoder.yudao.adminserver.modules.pay.controller.app.vo.*;
|
||||
|
||||
/**
|
||||
* 支付应用信息 Convert
|
||||
*
|
||||
* @author 芋艿
|
||||
*/
|
||||
@Mapper
|
||||
public interface PayAppConvert {
|
||||
|
||||
PayAppConvert INSTANCE = Mappers.getMapper(PayAppConvert.class);
|
||||
|
||||
PayAppPageItemRespVO pageConvert (PayAppDO bean);
|
||||
|
||||
PayAppPageItemRespVO.PayMerchant convert(PayMerchantDO bean);
|
||||
|
||||
PayAppDO convert(PayAppCreateReqVO bean);
|
||||
|
||||
PayAppDO convert(PayAppUpdateReqVO bean);
|
||||
|
||||
PayAppRespVO convert(PayAppDO bean);
|
||||
|
||||
List<PayAppRespVO> convertList(List<PayAppDO> list);
|
||||
|
||||
PageResult<PayAppRespVO> convertPage(PageResult<PayAppDO> page);
|
||||
|
||||
List<PayAppExcelVO> convertList02(List<PayAppDO> list);
|
||||
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
package cn.iocoder.yudao.adminserver.modules.pay.convert.channel;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayChannelDO;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
|
||||
import cn.iocoder.yudao.framework.pay.core.client.impl.wx.WXPayClientConfig;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.Mapping;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
import cn.iocoder.yudao.adminserver.modules.pay.controller.channel.vo.*;
|
||||
|
||||
/**
|
||||
* 支付渠道
|
||||
Convert
|
||||
*
|
||||
* @author 芋艿
|
||||
*/
|
||||
@Mapper
|
||||
public interface PayChannelConvert {
|
||||
|
||||
PayChannelConvert INSTANCE = Mappers.getMapper(PayChannelConvert.class);
|
||||
|
||||
@Mapping(target = "config",ignore = true)
|
||||
PayChannelDO convert(PayWechatChannelCreateReqVO bean);
|
||||
|
||||
@Mapping(target = "config",ignore = true)
|
||||
PayChannelDO convert(PayWechatChannelUpdateReqVO bean);
|
||||
|
||||
PayChannelDO convert(PayChannelCreateReqVO bean);
|
||||
|
||||
PayChannelDO convert(PayChannelUpdateReqVO bean);
|
||||
|
||||
PayChannelRespVO convert(PayChannelDO bean);
|
||||
|
||||
List<PayChannelRespVO> convertList(List<PayChannelDO> list);
|
||||
|
||||
PageResult<PayChannelRespVO> convertPage(PageResult<PayChannelDO> page);
|
||||
|
||||
List<PayChannelExcelVO> convertList02(List<PayChannelDO> list);
|
||||
|
||||
WXPayClientConfig configConvert(PayWechatChannelCreateReqVO.WeChatConfig bean);
|
||||
|
||||
WXPayClientConfig configConvert(PayWechatChannelUpdateReqVO.WeChatConfig bean);
|
||||
|
||||
@Mapping(target = "weChatConfig",ignore = true)
|
||||
PayWeChatChannelRespVO convert2(PayChannelDO bean);
|
||||
|
||||
PayWeChatChannelRespVO.WeChatConfig configConvert(WXPayClientConfig bean);
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
package cn.iocoder.yudao.adminserver.modules.pay.dal.mysql.app;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayAppDO;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.query.QueryWrapperX;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import cn.iocoder.yudao.adminserver.modules.pay.controller.app.vo.*;
|
||||
|
||||
/**
|
||||
* 支付应用信息 Mapper
|
||||
*
|
||||
* @author 芋艿
|
||||
*/
|
||||
@Mapper
|
||||
public interface PayAppMapper extends BaseMapperX<PayAppDO> {
|
||||
|
||||
default PageResult<PayAppDO> selectPage(PayAppPageReqVO reqVO,Collection<Long> merchantIds) {
|
||||
return selectPage(reqVO, new QueryWrapperX<PayAppDO>()
|
||||
.likeIfPresent("name", reqVO.getName())
|
||||
.eqIfPresent("status", reqVO.getStatus())
|
||||
.eqIfPresent("remark", reqVO.getRemark())
|
||||
.eqIfPresent("pay_notify_url", reqVO.getPayNotifyUrl())
|
||||
.eqIfPresent("refund_notify_url", reqVO.getRefundNotifyUrl())
|
||||
.inIfPresent("merchant_id", merchantIds)
|
||||
.betweenIfPresent("create_time", reqVO.getBeginCreateTime(), reqVO.getEndCreateTime())
|
||||
.orderByDesc("id"));
|
||||
}
|
||||
|
||||
default List<PayAppDO> selectList(PayAppExportReqVO reqVO) {
|
||||
return selectList(new QueryWrapperX<PayAppDO>()
|
||||
.likeIfPresent("name", reqVO.getName())
|
||||
.eqIfPresent("status", reqVO.getStatus())
|
||||
.eqIfPresent("remark", reqVO.getRemark())
|
||||
.eqIfPresent("pay_notify_url", reqVO.getPayNotifyUrl())
|
||||
.eqIfPresent("refund_notify_url", reqVO.getRefundNotifyUrl())
|
||||
.eqIfPresent("merchant_id", reqVO.getMerchantId())
|
||||
.betweenIfPresent("create_time", reqVO.getBeginCreateTime(), reqVO.getEndCreateTime())
|
||||
.orderByDesc("id") );
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
package cn.iocoder.yudao.adminserver.modules.pay.dal.mysql.channel;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayChannelDO;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.query.QueryWrapperX;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import cn.iocoder.yudao.adminserver.modules.pay.controller.channel.vo.*;
|
||||
|
||||
/**
|
||||
* 支付渠道
|
||||
Mapper
|
||||
*
|
||||
* @author 芋艿
|
||||
*/
|
||||
@Mapper
|
||||
public interface PayChannelMapper extends BaseMapperX<PayChannelDO> {
|
||||
|
||||
default PageResult<PayChannelDO> selectPage(PayChannelPageReqVO reqVO) {
|
||||
return selectPage(reqVO, new QueryWrapperX<PayChannelDO>()
|
||||
.eqIfPresent("code", reqVO.getCode())
|
||||
.eqIfPresent("status", reqVO.getStatus())
|
||||
.eqIfPresent("remark", reqVO.getRemark())
|
||||
.eqIfPresent("fee_rate", reqVO.getFeeRate())
|
||||
.eqIfPresent("merchant_id", reqVO.getMerchantId())
|
||||
.eqIfPresent("app_id", reqVO.getAppId())
|
||||
.eqIfPresent("config", reqVO.getConfig())
|
||||
.betweenIfPresent("create_time", reqVO.getBeginCreateTime(), reqVO.getEndCreateTime())
|
||||
.orderByDesc("id") );
|
||||
}
|
||||
|
||||
default List<PayChannelDO> selectList(PayChannelExportReqVO reqVO) {
|
||||
return selectList(new QueryWrapperX<PayChannelDO>()
|
||||
.eqIfPresent("code", reqVO.getCode())
|
||||
.eqIfPresent("status", reqVO.getStatus())
|
||||
.eqIfPresent("remark", reqVO.getRemark())
|
||||
.eqIfPresent("fee_rate", reqVO.getFeeRate())
|
||||
.eqIfPresent("merchant_id", reqVO.getMerchantId())
|
||||
.eqIfPresent("app_id", reqVO.getAppId())
|
||||
.eqIfPresent("config", reqVO.getConfig())
|
||||
.betweenIfPresent("create_time", reqVO.getBeginCreateTime(), reqVO.getEndCreateTime())
|
||||
.orderByDesc("id") );
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,81 @@
|
|||
package cn.iocoder.yudao.adminserver.modules.pay.service.app;
|
||||
|
||||
import java.util.*;
|
||||
import javax.validation.*;
|
||||
|
||||
import cn.iocoder.yudao.adminserver.modules.pay.controller.app.vo.*;
|
||||
import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayAppDO;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
/**
|
||||
* 支付应用信息 Service 接口
|
||||
*
|
||||
* @author 芋艿
|
||||
*/
|
||||
public interface PayAppService {
|
||||
|
||||
/**
|
||||
* 创建支付应用信息
|
||||
*
|
||||
* @param createReqVO 创建信息
|
||||
* @return 编号
|
||||
*/
|
||||
Long createApp(@Valid PayAppCreateReqVO createReqVO);
|
||||
|
||||
/**
|
||||
* 更新支付应用信息
|
||||
*
|
||||
* @param updateReqVO 更新信息
|
||||
*/
|
||||
void updateApp(@Valid PayAppUpdateReqVO updateReqVO);
|
||||
|
||||
/**
|
||||
* 删除支付应用信息
|
||||
*
|
||||
* @param id 编号
|
||||
*/
|
||||
void deleteApp(Long id);
|
||||
|
||||
/**
|
||||
* 获得支付应用信息
|
||||
*
|
||||
* @param id 编号
|
||||
* @return 支付应用信息
|
||||
*/
|
||||
PayAppDO getApp(Long id);
|
||||
|
||||
/**
|
||||
* 获得支付应用信息列表
|
||||
*
|
||||
* @param ids 编号
|
||||
* @return 支付应用信息列表
|
||||
*/
|
||||
List<PayAppDO> getAppList(Collection<Long> ids);
|
||||
|
||||
/**
|
||||
* 获得支付应用信息分页
|
||||
*
|
||||
* @param pageReqVO 分页查询
|
||||
* @return 支付应用信息分页
|
||||
*/
|
||||
PageResult<PayAppDO> getAppPage(PayAppPageReqVO pageReqVO);
|
||||
|
||||
/**
|
||||
* 获得支付应用信息列表, 用于 Excel 导出
|
||||
*
|
||||
* @param exportReqVO 查询条件
|
||||
* @return 支付应用信息列表
|
||||
*/
|
||||
List<PayAppDO> getAppList(PayAppExportReqVO exportReqVO);
|
||||
|
||||
/**
|
||||
* 修改应用信息状态
|
||||
*
|
||||
* @param id 应用编号
|
||||
* @param status 状态{@link cn.iocoder.yudao.framework.common.enums.CommonStatusEnum}
|
||||
*/
|
||||
void updateAppStatus(Long id, Integer status);
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,140 @@
|
|||
package cn.iocoder.yudao.adminserver.modules.pay.service.app.impl;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.iocoder.yudao.adminserver.modules.pay.service.merchant.PayMerchantService;
|
||||
import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayAppDO;
|
||||
import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayMerchantDO;
|
||||
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
||||
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import org.springframework.stereotype.Service;
|
||||
import javax.annotation.Resource;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
import java.util.*;
|
||||
import cn.iocoder.yudao.adminserver.modules.pay.controller.app.vo.*;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
|
||||
import cn.iocoder.yudao.adminserver.modules.pay.convert.app.PayAppConvert;
|
||||
import cn.iocoder.yudao.adminserver.modules.pay.dal.mysql.app.PayAppMapper;
|
||||
import cn.iocoder.yudao.adminserver.modules.pay.service.app.PayAppService;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||
import static cn.iocoder.yudao.coreservice.modules.pay.enums.PayErrorCodeCoreConstants.*;
|
||||
|
||||
/**
|
||||
* 支付应用信息 Service 实现类
|
||||
*
|
||||
* @author aquan
|
||||
*/
|
||||
@Service
|
||||
@Validated
|
||||
public class PayAppServiceImpl implements PayAppService {
|
||||
|
||||
@Resource
|
||||
private PayAppMapper appMapper;
|
||||
|
||||
/**
|
||||
* 商户 service 组件
|
||||
*/
|
||||
@Resource
|
||||
private PayMerchantService merchantService;
|
||||
|
||||
@Override
|
||||
public Long createApp(PayAppCreateReqVO createReqVO) {
|
||||
// 插入
|
||||
PayAppDO app = PayAppConvert.INSTANCE.convert(createReqVO);
|
||||
appMapper.insert(app);
|
||||
// 返回
|
||||
return app.getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateApp(PayAppUpdateReqVO updateReqVO) {
|
||||
// 校验存在
|
||||
this.validateAppExists(updateReqVO.getId());
|
||||
// 更新
|
||||
PayAppDO updateObj = PayAppConvert.INSTANCE.convert(updateReqVO);
|
||||
appMapper.updateById(updateObj);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteApp(Long id) {
|
||||
// 校验存在
|
||||
this.validateAppExists(id);
|
||||
// 删除
|
||||
appMapper.deleteById(id);
|
||||
}
|
||||
|
||||
private void validateAppExists(Long id) {
|
||||
if (appMapper.selectById(id) == null) {
|
||||
throw exception(APP_NOT_EXISTS);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public PayAppDO getApp(Long id) {
|
||||
return appMapper.selectById(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<PayAppDO> getAppList(Collection<Long> ids) {
|
||||
return appMapper.selectBatchIds(ids);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageResult<PayAppDO> getAppPage(PayAppPageReqVO pageReqVO) {
|
||||
return appMapper.selectPage(pageReqVO,this.getMerchantCondition(pageReqVO.getMerchantName()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<PayAppDO> getAppList(PayAppExportReqVO exportReqVO) {
|
||||
return appMapper.selectList(exportReqVO);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取商户编号集合,根据商户名称模糊查询得到所有的商户编号集合
|
||||
* @param merchantName 商户名称
|
||||
* @return 商户编号集合
|
||||
*/
|
||||
private Set<Long> getMerchantCondition(String merchantName) {
|
||||
if (StrUtil.isBlank(merchantName)) {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
return CollectionUtils.convertSet(merchantService.getMerchantListByName(merchantName), PayMerchantDO::getId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改应用信息状态
|
||||
*
|
||||
* @param id 应用编号
|
||||
* @param status 状态{@link CommonStatusEnum}
|
||||
*/
|
||||
@Override
|
||||
public void updateAppStatus(Long id, Integer status) {
|
||||
// 校验商户存在
|
||||
this.checkAppExists(id);
|
||||
// 更新状态
|
||||
PayAppDO app = new PayAppDO();
|
||||
app.setId(id);
|
||||
app.setStatus(status);
|
||||
appMapper.updateById(app);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 检查商户是否存在
|
||||
* @param id 商户编号
|
||||
*/
|
||||
@VisibleForTesting
|
||||
public void checkAppExists(Long id) {
|
||||
|
||||
if (id == null) {
|
||||
return;
|
||||
}
|
||||
PayAppDO payApp = appMapper.selectById(id);
|
||||
if (payApp == null) {
|
||||
throw exception(APP_NOT_EXISTS);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,130 @@
|
|||
package cn.iocoder.yudao.adminserver.modules.pay.service.channel;
|
||||
|
||||
import java.util.*;
|
||||
import javax.validation.*;
|
||||
|
||||
import cn.iocoder.yudao.adminserver.modules.pay.controller.channel.vo.*;
|
||||
import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayChannelDO;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
/**
|
||||
* 支付渠道
|
||||
* Service 接口
|
||||
*
|
||||
* @author 芋艿
|
||||
*/
|
||||
public interface PayChannelService {
|
||||
|
||||
|
||||
/**
|
||||
* 创建支付渠道
|
||||
*
|
||||
* @param createReqVO 创建信息
|
||||
* @return 编号
|
||||
*/
|
||||
Long createChannel(@Valid PayChannelCreateReqVO createReqVO);
|
||||
|
||||
/**
|
||||
* 更新支付渠道
|
||||
*
|
||||
* @param updateReqVO 更新信息
|
||||
*/
|
||||
void updateChannel(@Valid PayChannelUpdateReqVO updateReqVO);
|
||||
|
||||
/**
|
||||
* 删除支付渠道
|
||||
*
|
||||
* @param id 编号
|
||||
*/
|
||||
void deleteChannel(Long id);
|
||||
|
||||
/**
|
||||
* 获得支付渠道
|
||||
*
|
||||
* @param id 编号
|
||||
* @return 支付渠道
|
||||
*/
|
||||
PayChannelDO getChannel(Long id);
|
||||
|
||||
/**
|
||||
* 获得支付渠道
|
||||
* 列表
|
||||
*
|
||||
* @param ids 编号
|
||||
* @return 支付渠道
|
||||
* 列表
|
||||
*/
|
||||
List<PayChannelDO> getChannelList(Collection<Long> ids);
|
||||
|
||||
/**
|
||||
* 获得支付渠道
|
||||
* 分页
|
||||
*
|
||||
* @param pageReqVO 分页查询
|
||||
* @return 支付渠道
|
||||
* 分页
|
||||
*/
|
||||
PageResult<PayChannelDO> getChannelPage(PayChannelPageReqVO pageReqVO);
|
||||
|
||||
/**
|
||||
* 获得支付渠道
|
||||
* 列表, 用于 Excel 导出
|
||||
*
|
||||
* @param exportReqVO 查询条件
|
||||
* @return 支付渠道
|
||||
* 列表
|
||||
*/
|
||||
List<PayChannelDO> getChannelList(PayChannelExportReqVO exportReqVO);
|
||||
|
||||
/**
|
||||
* 根据支付应用ID集合获取所有的支付渠道
|
||||
*
|
||||
* @param payIds 支付应用编号集合
|
||||
* @return 支付渠道
|
||||
*/
|
||||
List<PayChannelDO> getSimpleChannels(Collection<Long> payIds);
|
||||
|
||||
/**
|
||||
* 解析pem文件获取公钥私钥字符串
|
||||
*
|
||||
* @param file pem公私钥文件
|
||||
* @return 解析后的字符串
|
||||
*/
|
||||
String parsingPemFile(MultipartFile file);
|
||||
|
||||
/**
|
||||
* 创建微信的渠道配置
|
||||
*
|
||||
* @param reqVO 创建信息
|
||||
* @return 创建结果
|
||||
*/
|
||||
Long createWechatChannel(PayWechatChannelCreateReqVO reqVO);
|
||||
|
||||
/**
|
||||
* 根据条件获取通道数量
|
||||
*
|
||||
* @param merchantId 商户编号
|
||||
* @param appid 应用编号
|
||||
* @param code 通道编码
|
||||
* @return 数量
|
||||
*/
|
||||
Integer getChannelCountByConditions(Long merchantId, Long appid, String code);
|
||||
|
||||
/**
|
||||
* 根据条件获取通道
|
||||
*
|
||||
* @param merchantId 商户编号
|
||||
* @param appid 应用编号
|
||||
* @param code 通道编码
|
||||
* @return 数量
|
||||
*/
|
||||
PayChannelDO getChannelByConditions(Long merchantId, Long appid, String code);
|
||||
|
||||
/**
|
||||
* 更新微信支付渠道
|
||||
*
|
||||
* @param updateReqVO 更新信息
|
||||
*/
|
||||
void updateWechatChannel(PayWechatChannelUpdateReqVO updateReqVO);
|
||||
}
|
|
@ -0,0 +1,196 @@
|
|||
package cn.iocoder.yudao.adminserver.modules.pay.service.channel.impl;
|
||||
|
||||
import cn.hutool.core.io.IoUtil;
|
||||
import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayChannelDO;
|
||||
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
|
||||
import cn.iocoder.yudao.framework.pay.core.client.impl.wx.WXPayClientConfig;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import com.fasterxml.jackson.databind.json.JsonMapper;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
|
||||
import cn.iocoder.yudao.adminserver.modules.pay.controller.channel.vo.*;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
|
||||
import cn.iocoder.yudao.adminserver.modules.pay.convert.channel.PayChannelConvert;
|
||||
import cn.iocoder.yudao.adminserver.modules.pay.dal.mysql.channel.PayChannelMapper;
|
||||
import cn.iocoder.yudao.adminserver.modules.pay.service.channel.PayChannelService;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||
import static cn.iocoder.yudao.coreservice.modules.pay.enums.PayErrorCodeCoreConstants.*;
|
||||
|
||||
/**
|
||||
* 支付渠道
|
||||
* Service 实现类
|
||||
*
|
||||
* @author 芋艿
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
@Validated
|
||||
public class PayChannelServiceImpl implements PayChannelService {
|
||||
|
||||
@Resource
|
||||
private PayChannelMapper channelMapper;
|
||||
|
||||
@Override
|
||||
public Long createChannel(PayChannelCreateReqVO createReqVO) {
|
||||
// 插入
|
||||
PayChannelDO channel = PayChannelConvert.INSTANCE.convert(createReqVO);
|
||||
channelMapper.insert(channel);
|
||||
// 返回
|
||||
return channel.getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateChannel(PayChannelUpdateReqVO updateReqVO) {
|
||||
// 校验存在
|
||||
this.validateChannelExists(updateReqVO.getId());
|
||||
// 更新
|
||||
PayChannelDO updateObj = PayChannelConvert.INSTANCE.convert(updateReqVO);
|
||||
channelMapper.updateById(updateObj);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteChannel(Long id) {
|
||||
// 校验存在
|
||||
this.validateChannelExists(id);
|
||||
// 删除
|
||||
channelMapper.deleteById(id);
|
||||
}
|
||||
|
||||
private void validateChannelExists(Long id) {
|
||||
if (channelMapper.selectById(id) == null) {
|
||||
throw exception(CHANNEL_NOT_EXISTS);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public PayChannelDO getChannel(Long id) {
|
||||
return channelMapper.selectById(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<PayChannelDO> getChannelList(Collection<Long> ids) {
|
||||
return channelMapper.selectBatchIds(ids);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageResult<PayChannelDO> getChannelPage(PayChannelPageReqVO pageReqVO) {
|
||||
return channelMapper.selectPage(pageReqVO);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<PayChannelDO> getChannelList(PayChannelExportReqVO exportReqVO) {
|
||||
return channelMapper.selectList(exportReqVO);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据支付应用ID集合获取所有的支付渠道
|
||||
*
|
||||
* @param payIds 支付应用编号集合
|
||||
* @return 支付渠道
|
||||
*/
|
||||
@Override
|
||||
public List<PayChannelDO> getSimpleChannels(Collection<Long> payIds) {
|
||||
return channelMapper.selectList(new QueryWrapper<PayChannelDO>().lambda().in(PayChannelDO::getAppId, payIds));
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析pem文件获取公钥私钥字符串
|
||||
*
|
||||
* @param file pem公私钥文件
|
||||
* @return 解析后的字符串
|
||||
*/
|
||||
@Override
|
||||
public String parsingPemFile(MultipartFile file) {
|
||||
try {
|
||||
return IoUtil.readUtf8(file.getInputStream());
|
||||
} catch (IOException e) {
|
||||
log.error("[parsingPemToString]读取pem[{}]文件错误", file.getOriginalFilename());
|
||||
throw exception(CHANNEL_KEY_READ_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建微信的渠道配置
|
||||
*
|
||||
* @param reqVO 创建信息
|
||||
* @return 创建结果
|
||||
*/
|
||||
@Override
|
||||
public Long createWechatChannel(PayWechatChannelCreateReqVO reqVO) {
|
||||
|
||||
// 判断是否有重复的有责无法新增
|
||||
Integer channelCount = this.getChannelCountByConditions(reqVO.getMerchantId(), reqVO.getAppId(), reqVO.getCode());
|
||||
if (channelCount > 0) {
|
||||
throw exception(EXIST_SAME_CHANNEL_ERROR);
|
||||
}
|
||||
|
||||
PayChannelDO channel = PayChannelConvert.INSTANCE.convert(reqVO);
|
||||
WXPayClientConfig config = PayChannelConvert.INSTANCE.configConvert(reqVO.getWeChatConfig());
|
||||
channel.setConfig(config);
|
||||
channelMapper.insert(channel);
|
||||
return channel.getId();
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据条件获取通道数量
|
||||
*
|
||||
* @param merchantId 商户编号
|
||||
* @param appid 应用编号
|
||||
* @param code 通道编码
|
||||
* @return 数量
|
||||
*/
|
||||
@Override
|
||||
public Integer getChannelCountByConditions(Long merchantId, Long appid, String code) {
|
||||
return this.channelMapper.selectCount(new QueryWrapper<PayChannelDO>().lambda()
|
||||
.eq(PayChannelDO::getMerchantId, merchantId)
|
||||
.eq(PayChannelDO::getAppId, appid)
|
||||
.eq(PayChannelDO::getCode, code)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据条件获取通道
|
||||
*
|
||||
* @param merchantId 商户编号
|
||||
* @param appid 应用编号
|
||||
* @param code 通道编码
|
||||
* @return 数量
|
||||
*/
|
||||
@Override
|
||||
public PayChannelDO getChannelByConditions(Long merchantId, Long appid, String code) {
|
||||
return this.channelMapper.selectOne((new QueryWrapper<PayChannelDO>().lambda()
|
||||
.eq(PayChannelDO::getMerchantId, merchantId)
|
||||
.eq(PayChannelDO::getAppId, appid)
|
||||
.eq(PayChannelDO::getCode, code)
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新微信支付渠道
|
||||
*
|
||||
* @param updateReqVO 更新信息
|
||||
*/
|
||||
@Override
|
||||
public void updateWechatChannel(PayWechatChannelUpdateReqVO updateReqVO) {
|
||||
// 校验存在
|
||||
this.validateChannelExists(updateReqVO.getId());
|
||||
PayChannelDO channel = PayChannelConvert.INSTANCE.convert(updateReqVO);
|
||||
WXPayClientConfig config = PayChannelConvert.INSTANCE.configConvert(updateReqVO.getWeChatConfig());
|
||||
channel.setConfig(config);
|
||||
this.channelMapper.updateById(channel);
|
||||
}
|
||||
}
|
|
@ -2,9 +2,13 @@ package cn.iocoder.yudao.adminserver.modules.pay.service.merchant;
|
|||
|
||||
import java.util.*;
|
||||
import javax.validation.*;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.iocoder.yudao.adminserver.modules.pay.controller.merchant.vo.*;
|
||||
import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.dept.SysDeptDO;
|
||||
import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayMerchantDO;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
|
||||
|
||||
/**
|
||||
* 支付商户信息 Service 接口
|
||||
|
@ -69,9 +73,46 @@ public interface PayMerchantService {
|
|||
|
||||
/**
|
||||
* 修改商户状态
|
||||
* @param id 商户编号
|
||||
*
|
||||
* @param id 商户编号
|
||||
* @param status 状态
|
||||
*/
|
||||
void updateMerchantStatus(Long id, Integer status);
|
||||
|
||||
/**
|
||||
* 根据商户名称模糊查询商户集合
|
||||
*
|
||||
* @param merchantName 商户名称
|
||||
* @return 商户集合
|
||||
*/
|
||||
List<PayMerchantDO> getMerchantListByName(String merchantName);
|
||||
|
||||
/**
|
||||
* 根据商户名称模糊查询一定数量的商户集合
|
||||
* @param merchantName 商户名称
|
||||
* @return 商户集合
|
||||
*/
|
||||
List<PayMerchantDO> getMerchantListByNameLimit(String merchantName);
|
||||
|
||||
/**
|
||||
* 获得指定编号的商户列表
|
||||
*
|
||||
* @param merchantIds 商户编号数组
|
||||
* @return 商户列表
|
||||
*/
|
||||
List<PayMerchantDO> getSimpleMerchants(Collection<Long> merchantIds);
|
||||
|
||||
/**
|
||||
* 获得指定编号的商户 Map
|
||||
*
|
||||
* @param merchantIds 商户编号数组
|
||||
* @return 商户 Map
|
||||
*/
|
||||
default Map<Long, PayMerchantDO> getMerchantMap(Collection<Long> merchantIds){
|
||||
if (CollUtil.isEmpty(merchantIds)) {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
List<PayMerchantDO> list = getSimpleMerchants(merchantIds);
|
||||
return CollectionUtils.convertMap(list, PayMerchantDO::getId);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,6 +10,8 @@ import cn.iocoder.yudao.adminserver.modules.pay.dal.mysql.merchant.PayMerchantMa
|
|||
import cn.iocoder.yudao.adminserver.modules.pay.service.merchant.PayMerchantService;
|
||||
import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayMerchantDO;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
@ -24,7 +26,7 @@ import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionU
|
|||
/**
|
||||
* 支付商户信息 Service 实现类
|
||||
*
|
||||
* @author 芋艿
|
||||
* @author aquan
|
||||
*/
|
||||
@Service
|
||||
@Validated
|
||||
|
@ -37,10 +39,7 @@ public class PayMerchantServiceImpl implements PayMerchantService {
|
|||
public Long createMerchant(PayMerchantCreateReqVO createReqVO) {
|
||||
// 插入
|
||||
PayMerchantDO merchant = PayMerchantConvert.INSTANCE.convert(createReqVO);
|
||||
// 根据 年月日时分秒毫秒 生成时间戳
|
||||
// TODO @aquan:生成 no 可以单独一个小方法
|
||||
String merchantNo = "M" + DateUtil.format(LocalDateTime.now(),"yyyyMMddHHmmssSSS");
|
||||
merchant.setNo(merchantNo);
|
||||
merchant.setNo(this.generateMerchantNo());
|
||||
merchantMapper.insert(merchant);
|
||||
// 返回
|
||||
return merchant.getId();
|
||||
|
@ -106,6 +105,35 @@ public class PayMerchantServiceImpl implements PayMerchantService {
|
|||
merchantMapper.updateById(merchant);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据商户名称模糊查询商户集合
|
||||
*
|
||||
* @param merchantName 商户名称
|
||||
* @return 商户集合
|
||||
*/
|
||||
@Override
|
||||
public List<PayMerchantDO> getMerchantListByName(String merchantName) {
|
||||
return this.merchantMapper.selectList(new QueryWrapper<PayMerchantDO>()
|
||||
.lambda().likeRight(PayMerchantDO::getName, merchantName));
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据商户名称模糊查询一定数量的商户集合
|
||||
*
|
||||
* @param merchantName 商户名称
|
||||
* @return 商户集合
|
||||
*/
|
||||
@Override
|
||||
public List<PayMerchantDO> getMerchantListByNameLimit(String merchantName) {
|
||||
|
||||
LambdaQueryWrapper<PayMerchantDO> queryWrapper = new QueryWrapper<PayMerchantDO>().lambda()
|
||||
.select(PayMerchantDO::getId, PayMerchantDO::getName)
|
||||
.likeRight(PayMerchantDO::getName, merchantName)
|
||||
.last("limit 200");
|
||||
|
||||
return this.merchantMapper.selectList(queryWrapper);
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查商户是否存在
|
||||
* @param id 商户编号
|
||||
|
@ -121,5 +149,24 @@ public class PayMerchantServiceImpl implements PayMerchantService {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得指定编号的商户列表
|
||||
*
|
||||
* @param merchantIds 商户编号数组
|
||||
* @return 商户列表
|
||||
*/
|
||||
@Override
|
||||
public List<PayMerchantDO> getSimpleMerchants(Collection<Long> merchantIds) {
|
||||
return merchantMapper.selectBatchIds(merchantIds);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据年月日时分秒毫秒生成商户号
|
||||
* @return 商户号
|
||||
*/
|
||||
private String generateMerchantNo(){
|
||||
return "M" + DateUtil.format(LocalDateTime.now(),"yyyyMMddHHmmssSSS");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -0,0 +1,196 @@
|
|||
package cn.iocoder.yudao.adminserver.modules.pay.app.service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
import cn.iocoder.yudao.adminserver.BaseDbUnitTest;
|
||||
import cn.iocoder.yudao.adminserver.modules.pay.controller.app.vo.PayAppCreateReqVO;
|
||||
import cn.iocoder.yudao.adminserver.modules.pay.controller.app.vo.PayAppExportReqVO;
|
||||
import cn.iocoder.yudao.adminserver.modules.pay.controller.app.vo.PayAppPageReqVO;
|
||||
import cn.iocoder.yudao.adminserver.modules.pay.controller.app.vo.PayAppUpdateReqVO;
|
||||
import cn.iocoder.yudao.adminserver.modules.pay.dal.mysql.app.PayAppMapper;
|
||||
import cn.iocoder.yudao.adminserver.modules.pay.service.app.impl.PayAppServiceImpl;
|
||||
import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayAppDO;
|
||||
import cn.iocoder.yudao.framework.common.util.object.ObjectUtils;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import java.util.*;
|
||||
|
||||
import static cn.iocoder.yudao.coreservice.modules.pay.enums.PayErrorCodeCoreConstants.*;
|
||||
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals;
|
||||
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException;
|
||||
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.buildTime;
|
||||
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
/**
|
||||
* {@link PayAppServiceImpl} 的单元测试类
|
||||
*
|
||||
* @author 芋艿
|
||||
*/
|
||||
@Import(PayAppServiceImpl.class)
|
||||
public class PayAppServiceTest extends BaseDbUnitTest {
|
||||
|
||||
@Resource
|
||||
private PayAppServiceImpl appService;
|
||||
|
||||
@Resource
|
||||
private PayAppMapper appMapper;
|
||||
|
||||
@Test
|
||||
public void testCreateApp_success() {
|
||||
// 准备参数
|
||||
PayAppCreateReqVO reqVO = randomPojo(PayAppCreateReqVO.class);
|
||||
|
||||
// 调用
|
||||
Long appId = appService.createApp(reqVO);
|
||||
// 断言
|
||||
assertNotNull(appId);
|
||||
// 校验记录的属性是否正确
|
||||
PayAppDO app = appMapper.selectById(appId);
|
||||
assertPojoEquals(reqVO, app);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateApp_success() {
|
||||
// mock 数据
|
||||
PayAppDO dbApp = randomPojo(PayAppDO.class);
|
||||
appMapper.insert(dbApp);// @Sql: 先插入出一条存在的数据
|
||||
// 准备参数
|
||||
PayAppUpdateReqVO reqVO = randomPojo(PayAppUpdateReqVO.class, o -> {
|
||||
o.setId(dbApp.getId()); // 设置更新的 ID
|
||||
});
|
||||
|
||||
// 调用
|
||||
appService.updateApp(reqVO);
|
||||
// 校验是否更新正确
|
||||
PayAppDO app = appMapper.selectById(reqVO.getId()); // 获取最新的
|
||||
assertPojoEquals(reqVO, app);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateApp_notExists() {
|
||||
// 准备参数
|
||||
PayAppUpdateReqVO reqVO = randomPojo(PayAppUpdateReqVO.class);
|
||||
|
||||
// 调用, 并断言异常
|
||||
assertServiceException(() -> appService.updateApp(reqVO), APP_NOT_EXISTS);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeleteApp_success() {
|
||||
// mock 数据
|
||||
PayAppDO dbApp = randomPojo(PayAppDO.class);
|
||||
appMapper.insert(dbApp);// @Sql: 先插入出一条存在的数据
|
||||
// 准备参数
|
||||
Long id = dbApp.getId();
|
||||
|
||||
// 调用
|
||||
appService.deleteApp(id);
|
||||
// 校验数据不存在了
|
||||
assertNull(appMapper.selectById(id));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeleteApp_notExists() {
|
||||
// 准备参数
|
||||
Long id = randomLongId();
|
||||
|
||||
// 调用, 并断言异常
|
||||
assertServiceException(() -> appService.deleteApp(id), APP_NOT_EXISTS);
|
||||
}
|
||||
|
||||
@Test // TODO 请修改 null 为需要的值
|
||||
public void testGetAppPage() {
|
||||
// mock 数据
|
||||
PayAppDO dbApp = randomPojo(PayAppDO.class, o -> { // 等会查询到
|
||||
o.setName(null);
|
||||
o.setStatus(null);
|
||||
o.setRemark(null);
|
||||
o.setPayNotifyUrl(null);
|
||||
o.setRefundNotifyUrl(null);
|
||||
o.setMerchantId(null);
|
||||
o.setCreateTime(null);
|
||||
});
|
||||
appMapper.insert(dbApp);
|
||||
// 测试 name 不匹配
|
||||
appMapper.insert(ObjectUtils.clone(dbApp, o -> o.setName(null)));
|
||||
// 测试 status 不匹配
|
||||
appMapper.insert(ObjectUtils.clone(dbApp, o -> o.setStatus(null)));
|
||||
// 测试 remark 不匹配
|
||||
appMapper.insert(ObjectUtils.clone(dbApp, o -> o.setRemark(null)));
|
||||
// 测试 payNotifyUrl 不匹配
|
||||
appMapper.insert(ObjectUtils.clone(dbApp, o -> o.setPayNotifyUrl(null)));
|
||||
// 测试 refundNotifyUrl 不匹配
|
||||
appMapper.insert(ObjectUtils.clone(dbApp, o -> o.setRefundNotifyUrl(null)));
|
||||
// 测试 merchantId 不匹配
|
||||
appMapper.insert(ObjectUtils.clone(dbApp, o -> o.setMerchantId(null)));
|
||||
// 测试 createTime 不匹配
|
||||
appMapper.insert(ObjectUtils.clone(dbApp, o -> o.setCreateTime(null)));
|
||||
// 准备参数
|
||||
PayAppPageReqVO reqVO = new PayAppPageReqVO();
|
||||
reqVO.setName(null);
|
||||
reqVO.setStatus(null);
|
||||
reqVO.setRemark(null);
|
||||
reqVO.setPayNotifyUrl(null);
|
||||
reqVO.setRefundNotifyUrl(null);
|
||||
reqVO.setBeginCreateTime(null);
|
||||
reqVO.setEndCreateTime(null);
|
||||
|
||||
// 调用
|
||||
PageResult<PayAppDO> pageResult = appService.getAppPage(reqVO);
|
||||
// 断言
|
||||
assertEquals(1, pageResult.getTotal());
|
||||
assertEquals(1, pageResult.getList().size());
|
||||
assertPojoEquals(dbApp, pageResult.getList().get(0));
|
||||
}
|
||||
|
||||
@Test // TODO 请修改 null 为需要的值
|
||||
public void testGetAppList() {
|
||||
// mock 数据
|
||||
PayAppDO dbApp = randomPojo(PayAppDO.class, o -> { // 等会查询到
|
||||
o.setName(null);
|
||||
o.setStatus(null);
|
||||
o.setRemark(null);
|
||||
o.setPayNotifyUrl(null);
|
||||
o.setRefundNotifyUrl(null);
|
||||
o.setMerchantId(null);
|
||||
o.setCreateTime(null);
|
||||
});
|
||||
appMapper.insert(dbApp);
|
||||
// 测试 name 不匹配
|
||||
appMapper.insert(ObjectUtils.clone(dbApp, o -> o.setName(null)));
|
||||
// 测试 status 不匹配
|
||||
appMapper.insert(ObjectUtils.clone(dbApp, o -> o.setStatus(null)));
|
||||
// 测试 remark 不匹配
|
||||
appMapper.insert(ObjectUtils.clone(dbApp, o -> o.setRemark(null)));
|
||||
// 测试 payNotifyUrl 不匹配
|
||||
appMapper.insert(ObjectUtils.clone(dbApp, o -> o.setPayNotifyUrl(null)));
|
||||
// 测试 refundNotifyUrl 不匹配
|
||||
appMapper.insert(ObjectUtils.clone(dbApp, o -> o.setRefundNotifyUrl(null)));
|
||||
// 测试 merchantId 不匹配
|
||||
appMapper.insert(ObjectUtils.clone(dbApp, o -> o.setMerchantId(null)));
|
||||
// 测试 createTime 不匹配
|
||||
appMapper.insert(ObjectUtils.clone(dbApp, o -> o.setCreateTime(null)));
|
||||
// 准备参数
|
||||
PayAppExportReqVO reqVO = new PayAppExportReqVO();
|
||||
reqVO.setName(null);
|
||||
reqVO.setStatus(null);
|
||||
reqVO.setRemark(null);
|
||||
reqVO.setPayNotifyUrl(null);
|
||||
reqVO.setRefundNotifyUrl(null);
|
||||
reqVO.setMerchantId(null);
|
||||
reqVO.setBeginCreateTime(null);
|
||||
reqVO.setEndCreateTime(null);
|
||||
|
||||
// 调用
|
||||
List<PayAppDO> list = appService.getAppList(reqVO);
|
||||
// 断言
|
||||
assertEquals(1, list.size());
|
||||
assertPojoEquals(dbApp, list.get(0));
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,204 @@
|
|||
package cn.iocoder.yudao.adminserver.modules.pay.channel;
|
||||
|
||||
import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayChannelDO;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
import cn.iocoder.yudao.adminserver.BaseDbUnitTest;
|
||||
import cn.iocoder.yudao.adminserver.modules.pay.service.channel.impl.PayChannelServiceImpl;
|
||||
import cn.iocoder.yudao.adminserver.modules.pay.controller.channel.vo.*;
|
||||
import cn.iocoder.yudao.adminserver.modules.pay.dal.mysql.channel.PayChannelMapper;
|
||||
import cn.iocoder.yudao.framework.common.util.object.ObjectUtils;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import java.util.*;
|
||||
|
||||
import static cn.iocoder.yudao.coreservice.modules.pay.enums.PayErrorCodeCoreConstants.*;
|
||||
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals;
|
||||
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException;
|
||||
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.buildTime;
|
||||
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
/**
|
||||
* {@link PayChannelServiceImpl} 的单元测试类
|
||||
*
|
||||
* @author 芋艿
|
||||
*/
|
||||
@Import(PayChannelServiceImpl.class)
|
||||
public class PayChannelServiceTest extends BaseDbUnitTest {
|
||||
|
||||
@Resource
|
||||
private PayChannelServiceImpl channelService;
|
||||
|
||||
@Resource
|
||||
private PayChannelMapper channelMapper;
|
||||
|
||||
@Test
|
||||
public void testCreateChannel_success() {
|
||||
// 准备参数
|
||||
PayChannelCreateReqVO reqVO = randomPojo(PayChannelCreateReqVO.class);
|
||||
|
||||
// 调用
|
||||
Long channelId = channelService.createChannel(reqVO);
|
||||
// 断言
|
||||
assertNotNull(channelId);
|
||||
// 校验记录的属性是否正确
|
||||
PayChannelDO channel = channelMapper.selectById(channelId);
|
||||
assertPojoEquals(reqVO, channel);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateChannel_success() {
|
||||
// mock 数据
|
||||
PayChannelDO dbChannel = randomPojo(PayChannelDO.class);
|
||||
channelMapper.insert(dbChannel);// @Sql: 先插入出一条存在的数据
|
||||
// 准备参数
|
||||
PayChannelUpdateReqVO reqVO = randomPojo(PayChannelUpdateReqVO.class, o -> {
|
||||
o.setId(dbChannel.getId()); // 设置更新的 ID
|
||||
});
|
||||
|
||||
// 调用
|
||||
channelService.updateChannel(reqVO);
|
||||
// 校验是否更新正确
|
||||
PayChannelDO channel = channelMapper.selectById(reqVO.getId()); // 获取最新的
|
||||
assertPojoEquals(reqVO, channel);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateChannel_notExists() {
|
||||
// 准备参数
|
||||
PayChannelUpdateReqVO reqVO = randomPojo(PayChannelUpdateReqVO.class);
|
||||
|
||||
// 调用, 并断言异常
|
||||
assertServiceException(() -> channelService.updateChannel(reqVO), CHANNEL_NOT_EXISTS);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeleteChannel_success() {
|
||||
// mock 数据
|
||||
PayChannelDO dbChannel = randomPojo(PayChannelDO.class);
|
||||
channelMapper.insert(dbChannel);// @Sql: 先插入出一条存在的数据
|
||||
// 准备参数
|
||||
Long id = dbChannel.getId();
|
||||
|
||||
// 调用
|
||||
channelService.deleteChannel(id);
|
||||
// 校验数据不存在了
|
||||
assertNull(channelMapper.selectById(id));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeleteChannel_notExists() {
|
||||
// 准备参数
|
||||
Long id = randomLongId();
|
||||
|
||||
// 调用, 并断言异常
|
||||
assertServiceException(() -> channelService.deleteChannel(id), CHANNEL_NOT_EXISTS);
|
||||
}
|
||||
|
||||
@Test // TODO 请修改 null 为需要的值
|
||||
public void testGetChannelPage() {
|
||||
// mock 数据
|
||||
PayChannelDO dbChannel = randomPojo(PayChannelDO.class, o -> { // 等会查询到
|
||||
o.setCode(null);
|
||||
o.setStatus(null);
|
||||
o.setRemark(null);
|
||||
o.setFeeRate(null);
|
||||
o.setMerchantId(null);
|
||||
o.setAppId(null);
|
||||
o.setConfig(null);
|
||||
o.setCreateTime(null);
|
||||
});
|
||||
channelMapper.insert(dbChannel);
|
||||
// 测试 code 不匹配
|
||||
channelMapper.insert(ObjectUtils.clone(dbChannel, o -> o.setCode(null)));
|
||||
// 测试 status 不匹配
|
||||
channelMapper.insert(ObjectUtils.clone(dbChannel, o -> o.setStatus(null)));
|
||||
// 测试 remark 不匹配
|
||||
channelMapper.insert(ObjectUtils.clone(dbChannel, o -> o.setRemark(null)));
|
||||
// 测试 feeRate 不匹配
|
||||
channelMapper.insert(ObjectUtils.clone(dbChannel, o -> o.setFeeRate(null)));
|
||||
// 测试 merchantId 不匹配
|
||||
channelMapper.insert(ObjectUtils.clone(dbChannel, o -> o.setMerchantId(null)));
|
||||
// 测试 appId 不匹配
|
||||
channelMapper.insert(ObjectUtils.clone(dbChannel, o -> o.setAppId(null)));
|
||||
// 测试 config 不匹配
|
||||
channelMapper.insert(ObjectUtils.clone(dbChannel, o -> o.setConfig(null)));
|
||||
// 测试 createTime 不匹配
|
||||
channelMapper.insert(ObjectUtils.clone(dbChannel, o -> o.setCreateTime(null)));
|
||||
// 准备参数
|
||||
PayChannelPageReqVO reqVO = new PayChannelPageReqVO();
|
||||
reqVO.setCode(null);
|
||||
reqVO.setStatus(null);
|
||||
reqVO.setRemark(null);
|
||||
reqVO.setFeeRate(null);
|
||||
reqVO.setMerchantId(null);
|
||||
reqVO.setAppId(null);
|
||||
reqVO.setConfig(null);
|
||||
reqVO.setBeginCreateTime(null);
|
||||
reqVO.setEndCreateTime(null);
|
||||
|
||||
// 调用
|
||||
PageResult<PayChannelDO> pageResult = channelService.getChannelPage(reqVO);
|
||||
// 断言
|
||||
assertEquals(1, pageResult.getTotal());
|
||||
assertEquals(1, pageResult.getList().size());
|
||||
assertPojoEquals(dbChannel, pageResult.getList().get(0));
|
||||
}
|
||||
|
||||
@Test // TODO 请修改 null 为需要的值
|
||||
public void testGetChannelList() {
|
||||
// mock 数据
|
||||
PayChannelDO dbChannel = randomPojo(PayChannelDO.class, o -> { // 等会查询到
|
||||
o.setCode(null);
|
||||
o.setStatus(null);
|
||||
o.setRemark(null);
|
||||
o.setFeeRate(null);
|
||||
o.setMerchantId(null);
|
||||
o.setAppId(null);
|
||||
o.setConfig(null);
|
||||
o.setCreateTime(null);
|
||||
});
|
||||
channelMapper.insert(dbChannel);
|
||||
// 测试 code 不匹配
|
||||
channelMapper.insert(ObjectUtils.clone(dbChannel, o -> o.setCode(null)));
|
||||
// 测试 status 不匹配
|
||||
channelMapper.insert(ObjectUtils.clone(dbChannel, o -> o.setStatus(null)));
|
||||
// 测试 remark 不匹配
|
||||
channelMapper.insert(ObjectUtils.clone(dbChannel, o -> o.setRemark(null)));
|
||||
// 测试 feeRate 不匹配
|
||||
channelMapper.insert(ObjectUtils.clone(dbChannel, o -> o.setFeeRate(null)));
|
||||
// 测试 merchantId 不匹配
|
||||
channelMapper.insert(ObjectUtils.clone(dbChannel, o -> o.setMerchantId(null)));
|
||||
// 测试 appId 不匹配
|
||||
channelMapper.insert(ObjectUtils.clone(dbChannel, o -> o.setAppId(null)));
|
||||
// 测试 config 不匹配
|
||||
channelMapper.insert(ObjectUtils.clone(dbChannel, o -> o.setConfig(null)));
|
||||
// 测试 createTime 不匹配
|
||||
channelMapper.insert(ObjectUtils.clone(dbChannel, o -> o.setCreateTime(null)));
|
||||
// 准备参数
|
||||
PayChannelExportReqVO reqVO = new PayChannelExportReqVO();
|
||||
reqVO.setCode(null);
|
||||
reqVO.setStatus(null);
|
||||
reqVO.setRemark(null);
|
||||
reqVO.setFeeRate(null);
|
||||
reqVO.setMerchantId(null);
|
||||
reqVO.setAppId(null);
|
||||
reqVO.setConfig(null);
|
||||
reqVO.setBeginCreateTime(null);
|
||||
reqVO.setEndCreateTime(null);
|
||||
|
||||
// 调用
|
||||
List<PayChannelDO> list = channelService.getChannelList(reqVO);
|
||||
// 断言
|
||||
assertEquals(1, list.size());
|
||||
assertPojoEquals(dbChannel, list.get(0));
|
||||
}
|
||||
|
||||
}
|
|
@ -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 {
|
||||
|
|
|
@ -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'
|
||||
})
|
||||
}
|
|
@ -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
|
||||
})
|
||||
}
|
|
@ -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) {
|
||||
|
|
Binary file not shown.
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 8.4 KiB |
|
@ -0,0 +1,2 @@
|
|||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1636341153732" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2282" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css">@font-face { font-family: element-icons; src: url("chrome-extension://moombeodfomdpjnpocobemoiaemednkg/fonts/element-icons.woff") format("woff"), url("chrome-extension://moombeodfomdpjnpocobemoiaemednkg/fonts/element-icons.ttf ") format("truetype"); }
|
||||
</style></defs><path d="M294.912 874.666667a21.333333 21.333333 0 0 1-17.194667-33.962667l469.333334-640a21.333333 21.333333 0 0 1 34.432 25.258667l-469.333334 640a21.248 21.248 0 0 1-17.237333 8.704zM358.912 533.333333a161.28 161.28 0 0 1-149.333333-170.666666 161.28 161.28 0 0 1 149.333333-170.666667 161.28 161.28 0 0 1 149.333333 170.666667 161.28 161.28 0 0 1-149.333333 170.666666z m0-298.666666a118.912 118.912 0 0 0-106.666667 128 118.912 118.912 0 0 0 106.666667 128 118.912 118.912 0 0 0 106.666667-128 118.912 118.912 0 0 0-106.666667-128zM700.245333 874.666667a161.28 161.28 0 0 1-149.333333-170.666667 161.28 161.28 0 0 1 149.333333-170.666667 161.28 161.28 0 0 1 149.333334 170.666667 161.28 161.28 0 0 1-149.333334 170.666667z m0-298.666667a118.912 118.912 0 0 0-106.666666 128 118.912 118.912 0 0 0 106.666666 128 118.912 118.912 0 0 0 106.666667-128 118.912 118.912 0 0 0-106.666667-128z" fill="#757575" p-id="2283"></path></svg>
|
After Width: | Height: | Size: 1.5 KiB |
|
@ -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": "支付宝扫码支付"
|
||||
},
|
||||
}
|
||||
|
|
|
@ -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',
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -0,0 +1,261 @@
|
|||
<template>
|
||||
<div>
|
||||
<el-dialog :visible.sync="transferParam.open" @close="close" append-to-body>
|
||||
<el-form ref="wechatJsApiForm" :model="form" :rules="rules" size="medium" label-width="100px"
|
||||
v-loading="transferParam.loading">
|
||||
<el-form-item label-width="180px" label="渠道费率" prop="feeRate">
|
||||
<el-input v-model="form.feeRate" placeholder="请输入渠道费率" clearable :style="{width: '100%'}">
|
||||
<template slot="append">%</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label-width="180px" label="公众号APPID" prop="weChatConfig.appId">
|
||||
<el-input v-model="form.weChatConfig.appId" placeholder="请输入公众号APPID" clearable :style="{width: '100%'}">
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label-width="180px" label="商户号" prop="weChatConfig.mchId">
|
||||
<el-input v-model="form.weChatConfig.mchId" :style="{width: '100%'}"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label-width="180px" label="渠道状态" prop="status">
|
||||
<el-radio-group v-model="form.status" size="medium">
|
||||
<el-radio v-for="dict in statusDictDatas" :key="parseInt(dict.value)" :label="parseInt(dict.value)">
|
||||
{{ dict.label }}
|
||||
</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label-width="180px" label="API 版本" prop="weChatConfig.apiVersion">
|
||||
<el-radio-group v-model="form.weChatConfig.apiVersion" size="medium">
|
||||
<el-radio v-for="dict in versionDictDatas" :key="dict.value" :label="dict.value">
|
||||
{{ dict.label }}
|
||||
</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label-width="180px" label="商户秘钥" prop="weChatConfig.mchKey"
|
||||
v-if="form.weChatConfig.apiVersion === 'v2'">
|
||||
<el-input v-model="form.weChatConfig.mchKey" placeholder="请输入商户秘钥" clearable
|
||||
:style="{width: '100%'}"></el-input>
|
||||
</el-form-item>
|
||||
<div v-if="form.weChatConfig.apiVersion === 'v3'">
|
||||
<el-form-item label-width="180px" label="apiclient_key.perm证书" prop="weChatConfig.privateKeyContent">
|
||||
<el-input v-model="form.weChatConfig.privateKeyContent" type="textarea"
|
||||
placeholder="请上传apiclient_key.perm证书"
|
||||
readonly :autosize="{minRows: 8, maxRows: 8}" :style="{width: '100%'}"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label-width="180px" label="" prop="privateKeyContentFile">
|
||||
<el-upload ref="privateKeyContentFile"
|
||||
:limit="1"
|
||||
:accept="fileAccept"
|
||||
:headers="header"
|
||||
:action="pemUploadAction"
|
||||
:before-upload="pemFileBeforeUpload"
|
||||
:on-success="privateKeyUploadSuccess"
|
||||
>
|
||||
<el-button size="small" type="primary" icon="el-icon-upload">点击上传</el-button>
|
||||
</el-upload>
|
||||
</el-form-item>
|
||||
<el-form-item label-width="180px" label="apiclient_cert.perm证书" prop="weChatConfig.privateCertContent">
|
||||
<el-input v-model="form.weChatConfig.privateCertContent" type="textarea"
|
||||
placeholder="请上传apiclient_cert.perm证书"
|
||||
readonly :autosize="{minRows: 8, maxRows: 8}" :style="{width: '100%'}"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label-width="180px" label="" prop="privateCertContentFile">
|
||||
<el-upload ref="privateCertContentFile"
|
||||
:limit="1"
|
||||
:accept="fileAccept"
|
||||
:headers="header"
|
||||
:action="pemUploadAction"
|
||||
:before-upload="pemFileBeforeUpload"
|
||||
:on-success="privateCertUploadSuccess"
|
||||
>
|
||||
<el-button size="small" type="primary" icon="el-icon-upload">点击上传</el-button>
|
||||
</el-upload>
|
||||
</el-form-item>
|
||||
</div>
|
||||
<el-form-item label-width="180px" label="备注" prop="remark">
|
||||
<el-input v-model="form.remark" :style="{width: '100%'}"></el-input>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button @click="close">取消</el-button>
|
||||
<el-button type="primary" @click="handleConfirm">确定</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import {DICT_TYPE, getDictDatas} from "@/utils/dict";
|
||||
import {createWechatChannel, getWechatChannel, updateWechatChannel} from "@/api/pay/channel";
|
||||
|
||||
export default {
|
||||
name: "wechatJsApiForm",
|
||||
components: {},
|
||||
props: {
|
||||
// 传输的参数
|
||||
transferParam: {
|
||||
// 加载动画
|
||||
"loading": false,
|
||||
// 是否修改
|
||||
"edit": false,
|
||||
// 是否显示
|
||||
"open": false,
|
||||
// 应用ID
|
||||
"appId": null,
|
||||
// 渠道编码
|
||||
"payCode": null,
|
||||
// 商户对象
|
||||
"payMerchant": {
|
||||
// 编号
|
||||
"id": null,
|
||||
// 名称
|
||||
"name": null
|
||||
},
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
form: {
|
||||
code: undefined,
|
||||
status: undefined,
|
||||
remark: undefined,
|
||||
feeRate: undefined,
|
||||
appId: undefined,
|
||||
merchantId: undefined,
|
||||
weChatConfig: {
|
||||
appId: undefined,
|
||||
mchId: undefined,
|
||||
apiVersion: undefined,
|
||||
mchKey: undefined,
|
||||
privateKeyContent: undefined,
|
||||
privateCertContent: undefined,
|
||||
}
|
||||
},
|
||||
rules: {
|
||||
feeRate: [{
|
||||
required: true,
|
||||
message: '请输入渠道费率',
|
||||
trigger: 'blur'
|
||||
}],
|
||||
'weChatConfig.mchId': [{
|
||||
required: true,
|
||||
message: '请传入商户号',
|
||||
trigger: 'blur'
|
||||
}],
|
||||
'weChatConfig.appId': [{
|
||||
required: true,
|
||||
message: '请输入公众号APPID',
|
||||
trigger: 'blur'
|
||||
}],
|
||||
status: [{
|
||||
required: true,
|
||||
message: '渠道状态不能为空',
|
||||
trigger: 'change'
|
||||
}],
|
||||
'weChatConfig.apiVersion': [{
|
||||
required: true,
|
||||
message: 'API版本不能为空',
|
||||
trigger: 'change'
|
||||
}],
|
||||
'weChatConfig.mchKey': [{
|
||||
required: true,
|
||||
message: '请输入商户秘钥',
|
||||
trigger: 'blur'
|
||||
}],
|
||||
'weChatConfig.privateKeyContent': [{
|
||||
required: true,
|
||||
message: '请上传apiclient_key.perm证书',
|
||||
trigger: 'blur'
|
||||
}],
|
||||
'weChatConfig.privateCertContent': [{
|
||||
required: true,
|
||||
message: '请上传apiclient_cert.perm证书',
|
||||
trigger: 'blur'
|
||||
}],
|
||||
},
|
||||
// 文件上传的header
|
||||
header: {
|
||||
"Authorization": null
|
||||
},
|
||||
pemUploadAction: 'http://127.0.0.1:48080/api/pay/channel/parsing-pem',
|
||||
fileAccept: ".pem",
|
||||
// 渠道状态 数据字典
|
||||
statusDictDatas: getDictDatas(DICT_TYPE.PAY_CHANNEL_STATUS),
|
||||
versionDictDatas: getDictDatas(DICT_TYPE.PAY_CHANNEL_WECHAT_VERSION),
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
transferParam: {
|
||||
deep: true, // 深度监听
|
||||
handler(newVal) {
|
||||
this.form.code = newVal.payCode;
|
||||
this.form.appId = newVal.appId;
|
||||
this.form.merchantId = newVal.payMerchant.id;
|
||||
// 只有在初次进来为编辑 并且为加载中的时候才回去请求数据
|
||||
if (newVal.edit === true && newVal.loading) {
|
||||
this.init();
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.header.Authorization = "Bearer " + this.$store.getters.token;
|
||||
},
|
||||
methods: {
|
||||
init() {
|
||||
getWechatChannel(this.transferParam.payMerchant.id, this.transferParam.appId, this.transferParam.payCode)
|
||||
.then(response => {
|
||||
this.form = response.data;
|
||||
this.transferParam.loading = false;
|
||||
})
|
||||
},
|
||||
close() {
|
||||
this.transferParam.open = false;
|
||||
this.$refs['wechatJsApiForm'].resetFields();
|
||||
},
|
||||
handleConfirm() {
|
||||
this.$refs['wechatJsApiForm'].validate(valid => {
|
||||
if (!valid) {
|
||||
return
|
||||
}
|
||||
if (this.transferParam.edit) {
|
||||
updateWechatChannel(this.form).then(response => {
|
||||
if (response.code === 0 ) {
|
||||
this.msgSuccess("修改成功");
|
||||
this.close();
|
||||
}
|
||||
|
||||
})
|
||||
} else {
|
||||
createWechatChannel(this.form).then(response => {
|
||||
if (response.code === 0) {
|
||||
this.msgSuccess("新增成功");
|
||||
this.$parent.refreshTable();
|
||||
this.close();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
pemFileBeforeUpload(file) {
|
||||
let format = '.' + file.name.split(".")[1];
|
||||
if (format !== this.fileAccept) {
|
||||
this.$message.error('请上传指定格式"' + this.fileAccept + '"文件');
|
||||
return false;
|
||||
}
|
||||
let isRightSize = file.size / 1024 / 1024 < 2
|
||||
if (!isRightSize) {
|
||||
this.$message.error('文件大小超过 2MB')
|
||||
}
|
||||
return isRightSize
|
||||
},
|
||||
privateKeyUploadSuccess(response) {
|
||||
this.form.weChatConfig.privateKeyContent = response.data;
|
||||
},
|
||||
privateCertUploadSuccess(response) {
|
||||
this.form.weChatConfig.privateCertContent = response.data;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
<style scoped>
|
||||
|
||||
</style>
|
|
@ -0,0 +1,441 @@
|
|||
<template>
|
||||
<div class="app-container">
|
||||
|
||||
<!-- 搜索工作栏 -->
|
||||
<el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
|
||||
<el-form-item label="应用名" prop="name">
|
||||
<el-input v-model="queryParams.name" placeholder="请输入应用名" clearable size="small"
|
||||
@keyup.enter.native="handleQuery"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="商户名称" prop="merchantName">
|
||||
<el-input v-model="queryParams.merchantName" placeholder="请输入商户名称" clearable size="small"
|
||||
@keyup.enter.native="handleQuery"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="开启状态" prop="status">
|
||||
<el-select v-model="queryParams.status" placeholder="请选择开启状态" clearable size="small">
|
||||
<el-option v-for="dict in statusDictDatas" :key="parseInt(dict.value)" :label="dict.label"
|
||||
:value="parseInt(dict.value)"/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
|
||||
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<!-- 操作工具栏 -->
|
||||
<el-row :gutter="10" class="mb8">
|
||||
<el-col :span="1.5">
|
||||
<el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd"
|
||||
v-hasPermi="['pay:app:create']">新增
|
||||
</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button type="warning" plain icon="el-icon-download" size="mini" @click="handleExport"
|
||||
v-hasPermi="['pay:app:export']">导出
|
||||
</el-button>
|
||||
</el-col>
|
||||
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
|
||||
</el-row>
|
||||
|
||||
<!-- 列表 -->
|
||||
<el-table v-loading="loading" :data="list">
|
||||
<el-table-column label="应用编号" align="center" prop="id"/>
|
||||
<el-table-column label="应用名" align="center" prop="name"/>
|
||||
<el-table-column label="开启状态" align="center" prop="status">
|
||||
<template slot-scope="scope">
|
||||
<el-switch v-model="scope.row.status" :active-value="0" :inactive-value="1"
|
||||
@change="handleStatusChange(scope.row)"/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="商户名称" align="center" prop="payMerchant.name"/>
|
||||
<el-table-column label="创建时间" align="center" prop="createTime" width="180">
|
||||
<template slot-scope="scope">
|
||||
<span>{{ parseTime(scope.row.createTime) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="支付宝配置" align="center">
|
||||
<el-table-column :label="payChannelEnum.ALIPAY_APP.name" align="center">
|
||||
<template slot-scope="scope">
|
||||
<el-button type="success" icon="el-icon-check" circle
|
||||
v-if="scope.row.payChannel.alipayApp === sysCommonStatusEnum.ENABLE"></el-button>
|
||||
<el-button type="danger" icon="el-icon-close" circle
|
||||
v-if="scope.row.payChannel.alipayApp === sysCommonStatusEnum.DISABLE"></el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column :label="payChannelEnum.ALIPAY_PC.name" align="center">
|
||||
<template slot-scope="scope">
|
||||
<el-button type="success" icon="el-icon-check" circle
|
||||
v-if="scope.row.payChannel.alipayPc === sysCommonStatusEnum.ENABLE"></el-button>
|
||||
<el-button type="danger" icon="el-icon-close" circle
|
||||
v-if="scope.row.payChannel.alipayPc === sysCommonStatusEnum.DISABLE"></el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column :label="payChannelEnum.ALIPAY_WAP.name" align="center">
|
||||
<template slot-scope="scope">
|
||||
<el-button type="success" icon="el-icon-check" circle
|
||||
v-if="scope.row.payChannel.alipayWap === sysCommonStatusEnum.ENABLE"></el-button>
|
||||
<el-button type="danger" icon="el-icon-close" circle
|
||||
v-if="scope.row.payChannel.alipayWap === sysCommonStatusEnum.DISABLE"></el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column :label="payChannelEnum.ALIPAY_QR.name" align="center">
|
||||
<template slot-scope="scope">
|
||||
<el-button type="success" icon="el-icon-check" circle
|
||||
v-if="scope.row.payChannel.alipayQr === sysCommonStatusEnum.ENABLE"></el-button>
|
||||
<el-button type="danger" icon="el-icon-close" circle
|
||||
v-if="scope.row.payChannel.alipayQr === sysCommonStatusEnum.DISABLE"></el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table-column>
|
||||
<el-table-column label="微信配置" align="center">
|
||||
<el-table-column :label="payChannelEnum.WX_LITE.name" align="center">
|
||||
<template slot-scope="scope">
|
||||
<el-button type="success" icon="el-icon-check" circle
|
||||
@click="handleUpdateChannel(scope.row,payChannelEnum.WX_LITE.code)"
|
||||
v-if="scope.row.payChannel.wxLite === sysCommonStatusEnum.ENABLE"></el-button>
|
||||
<el-button type="danger" icon="el-icon-close" circle
|
||||
@click="handleCreateChannel(scope.row,payChannelEnum.WX_LITE.code)"
|
||||
v-if="scope.row.payChannel.wxLite === sysCommonStatusEnum.DISABLE"></el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column :label="payChannelEnum.WX_PUB.name" align="center">
|
||||
<template slot-scope="scope">
|
||||
<el-button
|
||||
type="success" icon="el-icon-check" circle
|
||||
@click="handleUpdateChannel(scope.row,payChannelEnum.WX_PUB.code)"
|
||||
v-if="scope.row.payChannel.wxPub === sysCommonStatusEnum.ENABLE">
|
||||
</el-button>
|
||||
<el-button type="danger" icon="el-icon-close" circle
|
||||
@click="handleCreateChannel(scope.row,payChannelEnum.WX_PUB.code)"
|
||||
v-if="scope.row.payChannel.wxPub === sysCommonStatusEnum.DISABLE"></el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column :label="payChannelEnum.WX_APP.name" align="center">
|
||||
<template slot-scope="scope">
|
||||
<el-button type="success" icon="el-icon-check" circle
|
||||
@click="handleUpdateChannel(scope.row,payChannelEnum.WX_APP.code)"
|
||||
v-if="scope.row.payChannel.wxApp === sysCommonStatusEnum.ENABLE"></el-button>
|
||||
<el-button type="danger" icon="el-icon-close" circle
|
||||
@click="handleCreateChannel(scope.row,payChannelEnum.WX_APP.code)"
|
||||
v-if="scope.row.payChannel.wxApp === sysCommonStatusEnum.DISABLE"></el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
|
||||
<template slot-scope="scope">
|
||||
<el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)"
|
||||
v-hasPermi="['pay:app:update']">修改
|
||||
</el-button>
|
||||
<el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)"
|
||||
v-hasPermi="['pay:app:delete']">删除
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<!-- 分页组件 -->
|
||||
<pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize"
|
||||
@pagination="getList"/>
|
||||
|
||||
<!-- 对话框(添加 / 修改) -->
|
||||
<el-dialog :title="title" :visible.sync="open" width="800px" append-to-body>
|
||||
<el-form ref="form" :model="form" :rules="rules" label-width="160px">
|
||||
<el-form-item label="应用名" prop="name">
|
||||
<el-input v-model="form.name" placeholder="请输入应用名"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="所属商户" prop="merchantId">
|
||||
<el-select
|
||||
v-model="form.merchantId"
|
||||
filterable
|
||||
remote
|
||||
reserve-keyword
|
||||
placeholder="请选择所属商户"
|
||||
:remote-method="handleGetMerchantListByName"
|
||||
:loading="loading">
|
||||
<el-option
|
||||
v-for="item in merchantList"
|
||||
:key="item.id"
|
||||
:label="item.name"
|
||||
:value="item.id">
|
||||
</el-option>
|
||||
</el-select>
|
||||
<!-- <el-input v-model="form.merchantId" placeholder="请输入商户编号"/>-->
|
||||
</el-form-item>
|
||||
<el-form-item label="开启状态" prop="status">
|
||||
<el-radio-group v-model="form.status">
|
||||
<el-radio v-for="dict in statusDictDatas" :key="parseInt(dict.value)" :label="parseInt(dict.value)">
|
||||
{{ dict.label }}
|
||||
</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="支付结果的回调地址" prop="payNotifyUrl">
|
||||
<el-input v-model="form.payNotifyUrl" placeholder="请输入支付结果的回调地址"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="退款结果的回调地址" prop="refundNotifyUrl">
|
||||
<el-input v-model="form.refundNotifyUrl" placeholder="请输入退款结果的回调地址"/>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="备注" prop="remark">
|
||||
<el-input v-model="form.remark" placeholder="请输入备注"/>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button type="primary" @click="submitForm">确 定</el-button>
|
||||
<el-button @click="cancel">取 消</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
|
||||
<wechat-js-api-form :transferParam="wechatChannelParam"></wechat-js-api-form>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {createApp, updateApp, changeAppStatus, deleteApp, getApp, getAppPage, exportAppExcel} from "@/api/pay/app";
|
||||
import {DICT_TYPE, getDictDatas} from "@/utils/dict";
|
||||
import {PayChannelEnum, SysCommonStatusEnum} from "@/utils/constants";
|
||||
import {getMerchantListByName} from "@/api/pay/merchant";
|
||||
import wechatJsApiForm from "@/views/pay/app/components/wechatJsApiForm";
|
||||
|
||||
export default {
|
||||
name: "App",
|
||||
components: {
|
||||
"wechatJsApiForm": wechatJsApiForm
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
// 遮罩层
|
||||
loading: true,
|
||||
// 显示搜索条件
|
||||
showSearch: true,
|
||||
// 总条数
|
||||
total: 0,
|
||||
// 支付应用信息列表
|
||||
list: [],
|
||||
// 弹出层标题
|
||||
title: "",
|
||||
// 是否显示弹出层
|
||||
open: false,
|
||||
dateRangeCreateTime: [],
|
||||
// 查询参数
|
||||
queryParams: {
|
||||
pageNo: 1,
|
||||
pageSize: 10,
|
||||
name: null,
|
||||
status: null,
|
||||
remark: null,
|
||||
payNotifyUrl: null,
|
||||
refundNotifyUrl: null,
|
||||
merchantName: null,
|
||||
},
|
||||
// 表单参数
|
||||
form: {},
|
||||
// 表单校验
|
||||
rules: {
|
||||
name: [{required: true, message: "应用名不能为空", trigger: "blur"}],
|
||||
status: [{required: true, message: "开启状态不能为空", trigger: "blur"}],
|
||||
payNotifyUrl: [{required: true, message: "支付结果的回调地址不能为空", trigger: "blur"}],
|
||||
refundNotifyUrl: [{required: true, message: "退款结果的回调地址不能为空", trigger: "blur"}],
|
||||
merchantId: [{required: true, message: "商户编号不能为空", trigger: "blur"}],
|
||||
},
|
||||
// 数据字典
|
||||
statusDictDatas: getDictDatas(DICT_TYPE.PAY_APP_STATUS),
|
||||
sysCommonStatusEnum: SysCommonStatusEnum,
|
||||
// 支付渠道枚举
|
||||
payChannelEnum: PayChannelEnum,
|
||||
// 商户列表
|
||||
merchantList: [],
|
||||
// 是否显示支付窗口
|
||||
payOpen: false,
|
||||
// 微信组件传参参数
|
||||
wechatChannelParam: {
|
||||
// 是否修改
|
||||
"edit":false,
|
||||
// 是否显示
|
||||
"open":false,
|
||||
// 应用ID
|
||||
"appId": null,
|
||||
// 渠道编码
|
||||
"payCode": null,
|
||||
// 商户对象
|
||||
"payMerchant": {
|
||||
// 编号
|
||||
"id": null,
|
||||
// 名称
|
||||
"name": null
|
||||
},
|
||||
}
|
||||
};
|
||||
},
|
||||
created() {
|
||||
this.getList();
|
||||
},
|
||||
methods: {
|
||||
/** 查询列表 */
|
||||
getList() {
|
||||
this.loading = true;
|
||||
// 处理查询参数
|
||||
let params = {...this.queryParams};
|
||||
this.addBeginAndEndTime(params, this.dateRangeCreateTime, 'createTime');
|
||||
// 执行查询
|
||||
getAppPage(params).then(response => {
|
||||
console.log(response.data);
|
||||
this.list = response.data.list;
|
||||
this.total = response.data.total;
|
||||
this.loading = false;
|
||||
});
|
||||
},
|
||||
/** 取消按钮 */
|
||||
cancel() {
|
||||
this.open = false;
|
||||
this.reset();
|
||||
},
|
||||
/** 表单重置 */
|
||||
reset() {
|
||||
this.form = {
|
||||
id: undefined,
|
||||
name: undefined,
|
||||
status: undefined,
|
||||
remark: undefined,
|
||||
payNotifyUrl: undefined,
|
||||
refundNotifyUrl: undefined,
|
||||
merchantId: undefined,
|
||||
};
|
||||
this.resetForm("form");
|
||||
},
|
||||
/** 搜索按钮操作 */
|
||||
handleQuery() {
|
||||
this.queryParams.pageNo = 1;
|
||||
this.getList();
|
||||
},
|
||||
/** 重置按钮操作 */
|
||||
resetQuery() {
|
||||
this.dateRangeCreateTime = [];
|
||||
this.resetForm("queryForm");
|
||||
this.handleQuery();
|
||||
},
|
||||
/** 新增按钮操作 */
|
||||
handleAdd() {
|
||||
this.reset();
|
||||
this.open = true;
|
||||
this.title = "添加支付应用信息";
|
||||
},
|
||||
/** 修改按钮操作 */
|
||||
handleUpdate(row) {
|
||||
this.reset();
|
||||
const id = row.id;
|
||||
getApp(id).then(response => {
|
||||
this.form = response.data;
|
||||
this.open = true;
|
||||
this.title = "修改支付应用信息";
|
||||
});
|
||||
},
|
||||
// 用户状态修改
|
||||
handleStatusChange(row) {
|
||||
let text = row.status === SysCommonStatusEnum.ENABLE ? "启用" : "停用";
|
||||
this.$confirm('确认要"' + text + '""' + row.name + '"应用吗?', "警告", {
|
||||
confirmButtonText: "确定",
|
||||
cancelButtonText: "取消",
|
||||
type: "warning"
|
||||
}).then(function () {
|
||||
return changeAppStatus(row.id, row.status);
|
||||
}).then(() => {
|
||||
this.msgSuccess(text + "成功");
|
||||
}).catch(function () {
|
||||
row.status = row.status === SysCommonStatusEnum.ENABLE ? SysCommonStatusEnum.DISABLE
|
||||
: SysCommonStatusEnum.ENABLE;
|
||||
});
|
||||
},
|
||||
/** 提交按钮 */
|
||||
submitForm() {
|
||||
this.$refs["form"].validate(valid => {
|
||||
if (!valid) {
|
||||
return;
|
||||
}
|
||||
// 修改的提交
|
||||
if (this.form.id != null) {
|
||||
updateApp(this.form).then(response => {
|
||||
this.msgSuccess("修改成功");
|
||||
this.open = false;
|
||||
this.getList();
|
||||
});
|
||||
return;
|
||||
}
|
||||
// 添加的提交
|
||||
createApp(this.form).then(response => {
|
||||
this.msgSuccess("新增成功");
|
||||
this.open = false;
|
||||
this.getList();
|
||||
});
|
||||
});
|
||||
},
|
||||
/** 删除按钮操作 */
|
||||
handleDelete(row) {
|
||||
const id = row.id;
|
||||
this.$confirm('是否确认删除支付应用信息编号为"' + id + '"的数据项?', "警告", {
|
||||
confirmButtonText: "确定",
|
||||
cancelButtonText: "取消",
|
||||
type: "warning"
|
||||
}).then(function () {
|
||||
return deleteApp(id);
|
||||
}).then(() => {
|
||||
this.getList();
|
||||
this.msgSuccess("删除成功");
|
||||
})
|
||||
},
|
||||
/** 导出按钮操作 */
|
||||
handleExport() {
|
||||
// 处理查询参数
|
||||
let params = {...this.queryParams};
|
||||
params.pageNo = undefined;
|
||||
params.pageSize = undefined;
|
||||
this.addBeginAndEndTime(params, this.dateRangeCreateTime, 'createTime');
|
||||
// 执行导出
|
||||
this.$confirm('是否确认导出所有支付应用信息数据项?', "警告", {
|
||||
confirmButtonText: "确定",
|
||||
cancelButtonText: "取消",
|
||||
type: "warning"
|
||||
}).then(function () {
|
||||
return exportAppExcel(params);
|
||||
}).then(response => {
|
||||
this.downloadExcel(response, '支付应用信息.xls');
|
||||
})
|
||||
},
|
||||
/**
|
||||
* 根据商户名称模糊匹配商户信息
|
||||
* @param name 商户名称
|
||||
*/
|
||||
handleGetMerchantListByName(name) {
|
||||
getMerchantListByName(name).then(response => {
|
||||
console.log(response)
|
||||
this.merchantList = response.data;
|
||||
});
|
||||
},
|
||||
/**
|
||||
* 修改支付渠道信息
|
||||
*/
|
||||
handleUpdateChannel(row, payCode) {
|
||||
this.wechatChannelParam.edit = true;
|
||||
this.wechatChannelParam.loading = true;
|
||||
this.wechatChannelParam.appId = row.id;
|
||||
this.wechatChannelParam.payCode = payCode;
|
||||
this.wechatChannelParam.payMerchant = row.payMerchant;
|
||||
this.wechatChannelParam.open = true;
|
||||
},
|
||||
/**
|
||||
* 新增支付渠道信息
|
||||
*/
|
||||
handleCreateChannel(row, payCode) {
|
||||
this.wechatChannelParam.edit = false;
|
||||
this.wechatChannelParam.loading = false;
|
||||
this.wechatChannelParam.appId = row.id;
|
||||
this.wechatChannelParam.payCode = payCode;
|
||||
this.wechatChannelParam.payMerchant = row.payMerchant;
|
||||
this.wechatChannelParam.open = true;
|
||||
},
|
||||
refreshTable(){
|
||||
this.getList();
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
|
@ -47,6 +47,11 @@ public class PayChannelDO extends BaseDO {
|
|||
*/
|
||||
private Double feeRate;
|
||||
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
private String remark;
|
||||
|
||||
/**
|
||||
* 商户编号
|
||||
*
|
||||
|
|
|
@ -33,7 +33,6 @@ public class PayMerchantDO extends BaseDO {
|
|||
* 例如说,M233666999
|
||||
* 只有新增时插入,不允许修改
|
||||
*/
|
||||
@TableField(fill = FieldFill.INSERT) // TODO @aquan:Service 逻辑里设置,所以不用这个注解哈
|
||||
private String no;
|
||||
/**
|
||||
* 商户全称
|
||||
|
|
|
@ -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, "已存在相同的渠道");
|
||||
}
|
||||
|
|
|
@ -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<Config>) new WXPubPayClient(channelId, (WXPayClientConfig) config);
|
||||
case WX_LITE: return (AbstractPayClient<Config>) new WXPubPayClient(channelId, (WXPayClientConfig) config);
|
||||
case WX_APP: return (AbstractPayClient<Config>) new WXPubPayClient(channelId, (WXPayClientConfig) config);
|
||||
case ALIPAY_WAP: return (AbstractPayClient<Config>) new AlipayWapPayClient(channelId, (AlipayPayClientConfig) config);
|
||||
case ALIPAY_QR: return (AbstractPayClient<Config>) new AlipayQrPayClient(channelId, (AlipayPayClientConfig) config);
|
||||
}
|
||||
|
|
|
@ -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 网站支付"),
|
||||
|
|
Loading…
Reference in New Issue