!66 新增支付管理的管理后台:商户信息、应用信息、支付订单、退款订单等功能

Merge pull request !66 from 芋道源码/pay_extension
This commit is contained in:
芋道源码 2022-01-22 20:31:25 +00:00 committed by Gitee
commit 4be5b73dbc
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
160 changed files with 10738 additions and 262 deletions

1
.gitignore vendored
View File

@ -42,3 +42,4 @@ nbdist/
!*/build/*.java !*/build/*.java
!*/build/*.html !*/build/*.html
!*/build/*.xml !*/build/*.xml

8
sql/change_db.sql Normal file
View File

@ -0,0 +1,8 @@
ALTER TABLE `ruoyi-vue-pro`.`pay_order_extension`
CHANGE COLUMN `channel_notify_data` `channel_notify_data` VARCHAR(2048) CHARACTER SET 'utf8mb4' NULL DEFAULT NULL COMMENT '支付渠道异步通知的内容' ;
ALTER TABLE `ruoyi-vue-pro`.`pay_refund`
CHANGE COLUMN `req_no` `req_no` VARCHAR(64) NULL COMMENT '退款单请求号' ;
ALTER TABLE `ruoyi-vue-pro`.`pay_refund`
DROP COLUMN `req_no`;

View File

@ -0,0 +1,163 @@
package cn.iocoder.yudao.adminserver.modules.pay.controller.app;
import cn.hutool.core.collection.CollUtil;
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.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 cn.iocoder.yudao.framework.pay.core.enums.PayChannelEnum;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
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 javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.IOException;
import java.util.*;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT;
@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.getChannelListByAppIds(payAppIds);
// TODO @aquan可以基于 appId 简历一个 multiMap这样下面直接 get 到之后CollUtil buildSet 即可
Iterator<PayChannelDO> iterator = channels.iterator();
// 得到所有的商户信息
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())));
// 写入支付渠道信息的数据
Set<String> channelCodes = new HashSet<>(PayChannelEnum.values().length);
while (iterator.hasNext()) {
PayChannelDO channelDO = iterator.next();
if (channelDO.getAppId().equals(app.getId())) {
channelCodes.add(channelDO.getCode());
iterator.remove();
}
}
respVO.setChannelCodes(channelCodes);
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);
}
@GetMapping("/list-merchant-id")
@ApiOperation("根据商户 ID 查询支付应用信息")
@ApiImplicitParam(name = "merchantId", value = "商户ID", required = true, example = "1", dataTypeClass = Long.class)
@PreAuthorize("@ss.hasPermission('pay:merchant:query')")
public CommonResult<List<PayAppRespVO>> getMerchantListByName(@RequestParam String merchantId) {
List<PayAppDO> appListDO = appService.getListByMerchantId(merchantId);
return success(PayAppConvert.INSTANCE.convertList(appListDO));
}
}

View File

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

View File

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

View File

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

View File

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

View File

@ -0,0 +1,50 @@
package cn.iocoder.yudao.adminserver.modules.pay.controller.app.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import java.util.Date;
import java.util.Set;
/**
* 支付应用信息分页查询 Response VO
*
* @author aquan
*/
@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;
}
@ApiModelProperty(value = "渠道编码集合", required = true, example = "alipay_pc,alipay_wap...")
private Set<String> channelCodes;
}

View File

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

View File

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

View File

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

View File

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

View File

@ -0,0 +1,129 @@
package cn.iocoder.yudao.adminserver.modules.pay.controller.channel;
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 cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayChannelDO;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
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 org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.IOException;
import java.util.Collection;
import java.util.List;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT;
/**
* 支付渠道 controller 组件
* @author aquan
*/
@Api(tags = "支付渠道")
@RestController
@RequestMapping("/pay/channel")
@Validated
public class PayChannelController {
@Resource
private PayChannelService channelService;
@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);
}
@GetMapping("/get-channel")
@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<PayChannelRespVO> getChannel(
@RequestParam Long merchantId, @RequestParam Long appId, @RequestParam String code) {
// 獲取渠道
PayChannelDO channel = channelService.getChannelByConditions(merchantId, appId, code);
if (channel == null) {
return success(new PayChannelRespVO());
}
// 拼凑数据
PayChannelRespVO respVo = PayChannelConvert.INSTANCE.convert(channel);
return success(respVo);
}
}

View File

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

View File

@ -0,0 +1,21 @@
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.constraints.NotBlank;
@ApiModel("支付渠道 创建 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class PayChannelCreateReqVO extends PayChannelBaseVO {
@ApiModelProperty(value = "通道配置的 json 字符串")
@NotBlank(message = "通道配置不能为空")
private String config;
}

View File

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

View File

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

View File

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

View File

@ -0,0 +1,21 @@
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;
@ApiModelProperty(value = "配置", required = true)
private String config;
}

View File

@ -0,0 +1,21 @@
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;
@ApiModelProperty(value = "通道配置的json字符串")
@NotBlank(message = "通道配置不能为空")
private String config;
}

View File

@ -0,0 +1,116 @@
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.coreservice.modules.pay.dal.dataobject.merchant.PayMerchantDO;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
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.ApiOperation;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.IOException;
import java.util.Collection;
import java.util.List;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT;
@Api(tags = "支付商户信息")
@RestController
@RequestMapping("/pay/merchant")
@Validated
public class PayMerchantController {
@Resource
private PayMerchantService merchantService;
@PostMapping("/create")
@ApiOperation("创建支付商户信息")
@PreAuthorize("@ss.hasPermission('pay:merchant:create')")
public CommonResult<Long> createMerchant(@Valid @RequestBody PayMerchantCreateReqVO createReqVO) {
return success(merchantService.createMerchant(createReqVO));
}
@PutMapping("/update")
@ApiOperation("更新支付商户信息")
@PreAuthorize("@ss.hasPermission('pay:merchant:update')")
public CommonResult<Boolean> updateMerchant(@Valid @RequestBody PayMerchantUpdateReqVO updateReqVO) {
merchantService.updateMerchant(updateReqVO);
return success(true);
}
@PutMapping("/update-status")
@ApiOperation("修改支付商户状态")
@PreAuthorize("@ss.hasPermission('pay:merchant:update')")
public CommonResult<Boolean> updateMerchantStatus(@Valid @RequestBody PayMerchantUpdateStatusReqVO reqVO) {
merchantService.updateMerchantStatus(reqVO.getId(), reqVO.getStatus());
return success(true);
}
@DeleteMapping("/delete")
@ApiOperation("删除支付商户信息")
@ApiImplicitParam(name = "id", value = "编号", required = true)
@PreAuthorize("@ss.hasPermission('pay:merchant:delete')")
public CommonResult<Boolean> deleteMerchant(@RequestParam("id") Long id) {
merchantService.deleteMerchant(id);
return success(true);
}
@GetMapping("/get")
@ApiOperation("获得支付商户信息")
@ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class)
@PreAuthorize("@ss.hasPermission('pay:merchant:query')")
public CommonResult<PayMerchantRespVO> getMerchant(@RequestParam("id") Long id) {
PayMerchantDO merchant = merchantService.getMerchant(id);
return success(PayMerchantConvert.INSTANCE.convert(merchant));
}
@GetMapping("/list-by-name")
@ApiOperation("根据商户名称获得支付商户信息列表")
@ApiImplicitParam(name = "name", value = "商户名称", example = "芋道", dataTypeClass = Long.class)
@PreAuthorize("@ss.hasPermission('pay:merchant:query')")
public CommonResult<List<PayMerchantRespVO>> getMerchantListByName(@RequestParam(required = false) String name) {
List<PayMerchantDO> merchantListDO = merchantService.getMerchantListByName(name);
return success(PayMerchantConvert.INSTANCE.convertList(merchantListDO));
}
@GetMapping("/list")
@ApiOperation("获得支付商户信息列表")
@ApiImplicitParam(name = "ids", value = "编号列表", required = true, example = "1024,2048", dataTypeClass = List.class)
@PreAuthorize("@ss.hasPermission('pay:merchant:query')")
public CommonResult<List<PayMerchantRespVO>> getMerchantList(@RequestParam("ids") Collection<Long> ids) {
List<PayMerchantDO> list = merchantService.getMerchantList(ids);
return success(PayMerchantConvert.INSTANCE.convertList(list));
}
@GetMapping("/page")
@ApiOperation("获得支付商户信息分页")
@PreAuthorize("@ss.hasPermission('pay:merchant:query')")
public CommonResult<PageResult<PayMerchantRespVO>> getMerchantPage(@Valid PayMerchantPageReqVO pageVO) {
PageResult<PayMerchantDO> pageResult = merchantService.getMerchantPage(pageVO);
return success(PayMerchantConvert.INSTANCE.convertPage(pageResult));
}
@GetMapping("/export-excel")
@ApiOperation("导出支付商户信息 Excel")
@PreAuthorize("@ss.hasPermission('pay:merchant:export')")
@OperateLog(type = EXPORT)
public void exportMerchantExcel(@Valid PayMerchantExportReqVO exportReqVO,
HttpServletResponse response) throws IOException {
List<PayMerchantDO> list = merchantService.getMerchantList(exportReqVO);
// 导出 Excel
List<PayMerchantExcelVO> datas = PayMerchantConvert.INSTANCE.convertList02(list);
ExcelUtils.write(response, "支付商户信息.xls", "数据", PayMerchantExcelVO.class, datas);
}
}

View File

@ -0,0 +1,30 @@
package cn.iocoder.yudao.adminserver.modules.pay.controller.merchant.vo;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotNull;
/**
* 支付商户信息 Base VO提供给添加修改详细的子 VO 使用
* 如果子 VO 存在差异的字段请不要添加到这里影响 Swagger 文档生成
*/
@Data
public class PayMerchantBaseVO {
@ApiModelProperty(value = "商户全称", required = true)
@NotNull(message = "商户全称不能为空")
private String name;
@ApiModelProperty(value = "商户简称", required = true)
@NotNull(message = "商户简称不能为空")
private String shortName;
@ApiModelProperty(value = "开启状态", required = true)
@NotNull(message = "开启状态不能为空")
private Integer status;
@ApiModelProperty(value = "备注")
private String remark;
}

View File

@ -0,0 +1,14 @@
package cn.iocoder.yudao.adminserver.modules.pay.controller.merchant.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 PayMerchantCreateReqVO extends PayMerchantBaseVO {
}

View File

@ -0,0 +1,40 @@
package cn.iocoder.yudao.adminserver.modules.pay.controller.merchant.vo;
import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
import com.alibaba.excel.annotation.ExcelProperty;
import lombok.Data;
import java.util.Date;
/**
* 支付商户信息 Excel VO
*
* @author 芋艿
*/
@Data
public class PayMerchantExcelVO {
@ExcelProperty("商户编号")
private Long id;
@ExcelProperty("商户号")
private String no;
@ExcelProperty("商户全称")
private String name;
@ExcelProperty("商户简称")
private String shortName;
@ExcelProperty(value = "开启状态",converter = DictConvert.class)
@DictFormat("sys_common_status")
private Integer status;
@ExcelProperty("备注")
private String remark;
@ExcelProperty("创建时间")
private Date createTime;
}

View File

@ -0,0 +1,38 @@
package cn.iocoder.yudao.adminserver.modules.pay.controller.merchant.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 = "参数和 PayMerchantPageReqVO 是一致的")
@Data
public class PayMerchantExportReqVO {
@ApiModelProperty(value = "商户号")
private String no;
@ApiModelProperty(value = "商户全称")
private String name;
@ApiModelProperty(value = "商户简称")
private String shortName;
@ApiModelProperty(value = "开启状态")
private Integer status;
@ApiModelProperty(value = "备注")
private String remark;
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
@ApiModelProperty(value = "开始创建时间")
private Date beginCreateTime;
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
@ApiModelProperty(value = "结束创建时间")
private Date endCreateTime;
}

View File

@ -0,0 +1,40 @@
package cn.iocoder.yudao.adminserver.modules.pay.controller.merchant.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 PayMerchantPageReqVO extends PageParam {
@ApiModelProperty(value = "商户号")
private String no;
@ApiModelProperty(value = "商户全称")
private String name;
@ApiModelProperty(value = "商户简称")
private String shortName;
@ApiModelProperty(value = "开启状态")
private Integer status;
@ApiModelProperty(value = "备注")
private String remark;
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
@ApiModelProperty(value = "开始创建时间")
private Date beginCreateTime;
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
@ApiModelProperty(value = "结束创建时间")
private Date endCreateTime;
}

View File

@ -0,0 +1,30 @@
package cn.iocoder.yudao.adminserver.modules.pay.controller.merchant.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import java.util.Date;
@ApiModel("支付商户信息 Response VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class PayMerchantRespVO extends PayMerchantBaseVO {
@ApiModelProperty(value = "商户编号", required = true)
private Long id;
@ApiModelProperty(value = "创建时间", required = true)
private Date createTime;
/**
* 商户号
* 例如说M233666999
* 只有新增时插入不允许修改
*/
private String no;
}

View File

@ -0,0 +1,18 @@
package cn.iocoder.yudao.adminserver.modules.pay.controller.merchant.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 PayMerchantUpdateReqVO extends PayMerchantBaseVO {
@ApiModelProperty(value = "商户编号", required = true)
@NotNull(message = "商户编号不能为空")
private Long id;
}

View File

@ -0,0 +1,21 @@
package cn.iocoder.yudao.adminserver.modules.pay.controller.merchant.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 PayMerchantUpdateStatusReqVO {
@ApiModelProperty(value = "商户编号", required = true, example = "1024")
@NotNull(message = "商户编号不能为空")
private Long id;
@ApiModelProperty(value = "状态", required = true, example = "1", notes = "见 SysCommonStatusEnum 枚举")
@NotNull(message = "状态不能为空")
private Integer status;
}

View File

@ -0,0 +1,177 @@
package cn.iocoder.yudao.adminserver.modules.pay.controller.order;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.iocoder.yudao.adminserver.modules.pay.controller.order.vo.order.*;
import cn.iocoder.yudao.adminserver.modules.pay.convert.order.PayOrderConvert;
import cn.iocoder.yudao.adminserver.modules.pay.service.app.PayAppService;
import cn.iocoder.yudao.adminserver.modules.pay.service.merchant.PayMerchantService;
import cn.iocoder.yudao.adminserver.modules.pay.service.order.PayOrderExtensionService;
import cn.iocoder.yudao.adminserver.modules.pay.service.order.PayOrderService;
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.coreservice.modules.pay.dal.dataobject.order.PayOrderDO;
import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.order.PayOrderExtensionDO;
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 cn.iocoder.yudao.framework.pay.core.enums.PayChannelEnum;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.IOException;
import java.util.ArrayList;
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
*/
@Api(tags = "支付订单")
@RestController
@RequestMapping("/pay/order")
@Validated
public class PayOrderController {
/**
* 订单 service 组件
*/
@Resource
private PayOrderService orderService;
/**
* 订单扩展 service 组件
*/
@Resource
private PayOrderExtensionService orderExtensionService;
/**
* 商户 service 组件
*/
@Resource
private PayMerchantService merchantService;
/**
* 应用 service 组件
*/
@Resource
private PayAppService appService;
@GetMapping("/get")
@ApiOperation("获得支付订单")
@ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class)
@PreAuthorize("@ss.hasPermission('pay:order:query')")
public CommonResult<PayOrderDetailsRespVO> getOrder(@RequestParam("id") Long id) {
PayOrderDO order = orderService.getOrder(id);
if (ObjectUtil.isNull(order)) {
return success(new PayOrderDetailsRespVO());
}
PayMerchantDO merchantDO = merchantService.getMerchant(order.getMerchantId());
PayAppDO appDO = appService.getApp(order.getAppId());
PayChannelEnum channelEnum = PayChannelEnum.getByCode(order.getChannelCode());
PayOrderDetailsRespVO respVO = PayOrderConvert.INSTANCE.orderDetailConvert(order);
respVO.setMerchantName(ObjectUtil.isNotNull(merchantDO) ? merchantDO.getName() : "未知商户");
respVO.setAppName(ObjectUtil.isNotNull(appDO) ? appDO.getName() : "未知应用");
respVO.setChannelCodeName(ObjectUtil.isNotNull(channelEnum) ? channelEnum.getName() : "未知渠道");
PayOrderExtensionDO extensionDO = orderExtensionService.getOrderExtension(order.getSuccessExtensionId());
if (ObjectUtil.isNotNull(extensionDO)) {
respVO.setPayOrderExtension(PayOrderConvert.INSTANCE.orderDetailExtensionConvert(extensionDO));
}
return success(respVO);
}
@GetMapping("/page")
@ApiOperation("获得支付订单分页")
@PreAuthorize("@ss.hasPermission('pay:order:query')")
public CommonResult<PageResult<PayOrderPageItemRespVO>> getOrderPage(@Valid PayOrderPageReqVO pageVO) {
PageResult<PayOrderDO> pageResult = orderService.getOrderPage(pageVO);
if (CollectionUtil.isEmpty(pageResult.getList())) {
return success(new PageResult<>(pageResult.getTotal()));
}
// 处理商户ID数据
Map<Long, PayMerchantDO> merchantMap = merchantService.getMerchantMap(
CollectionUtils.convertList(pageResult.getList(), PayOrderDO::getMerchantId));
// 处理应用ID数据
Map<Long, PayAppDO> appMap = appService.getAppMap(
CollectionUtils.convertList(pageResult.getList(), PayOrderDO::getAppId));
List<PayOrderPageItemRespVO> pageList = new ArrayList<>(pageResult.getList().size());
pageResult.getList().forEach(c -> {
PayMerchantDO merchantDO = merchantMap.get(c.getMerchantId());
PayAppDO appDO = appMap.get(c.getAppId());
PayChannelEnum channelEnum = PayChannelEnum.getByCode(c.getChannelCode());
PayOrderPageItemRespVO orderItem = PayOrderConvert.INSTANCE.pageConvertItemPage(c);
orderItem.setMerchantName(ObjectUtil.isNotNull(merchantDO) ? merchantDO.getName() : "未知商户");
orderItem.setAppName(ObjectUtil.isNotNull(appDO) ? appDO.getName() : "未知应用");
orderItem.setChannelCodeName(ObjectUtil.isNotNull(channelEnum) ? channelEnum.getName() : "未知渠道");
pageList.add(orderItem);
});
return success(new PageResult<>(pageList, pageResult.getTotal()));
}
@GetMapping("/export-excel")
@ApiOperation("导出支付订单Excel")
@PreAuthorize("@ss.hasPermission('pay:order:export')")
@OperateLog(type = EXPORT)
public void exportOrderExcel(@Valid PayOrderExportReqVO exportReqVO,
HttpServletResponse response) throws IOException {
List<PayOrderDO> list = orderService.getOrderList(exportReqVO);
if (CollectionUtil.isEmpty(list)) {
ExcelUtils.write(response, "支付订单.xls", "数据",
PayOrderExcelVO.class, new ArrayList<>());
}
// 处理商户ID数据
Map<Long, PayMerchantDO> merchantMap = merchantService.getMerchantMap(
CollectionUtils.convertList(list, PayOrderDO::getMerchantId));
// 处理应用ID数据
Map<Long, PayAppDO> appMap = appService.getAppMap(
CollectionUtils.convertList(list, PayOrderDO::getAppId));
// 处理扩展订单数据
Map<Long, PayOrderExtensionDO> orderExtensionMap = orderExtensionService
.getOrderExtensionMap(CollectionUtils.convertList(list, PayOrderDO::getSuccessExtensionId));
List<PayOrderExcelVO> excelDatum = new ArrayList<>(list.size());
list.forEach(c -> {
PayMerchantDO merchantDO = merchantMap.get(c.getMerchantId());
PayAppDO appDO = appMap.get(c.getAppId());
PayChannelEnum channelEnum = PayChannelEnum.getByCode(c.getChannelCode());
PayOrderExtensionDO orderExtensionDO = orderExtensionMap.get(c.getSuccessExtensionId());
PayOrderExcelVO excelItem = PayOrderConvert.INSTANCE.excelConvert(c);
excelItem.setMerchantName(ObjectUtil.isNotNull(merchantDO) ? merchantDO.getName() : "未知商户");
excelItem.setAppName(ObjectUtil.isNotNull(appDO) ? appDO.getName() : "未知应用");
excelItem.setChannelCodeName(ObjectUtil.isNotNull(channelEnum) ? channelEnum.getName() : "未知渠道");
excelItem.setNo(ObjectUtil.isNotNull(orderExtensionDO) ? orderExtensionDO.getNo() : "");
excelDatum.add(excelItem);
});
// 导出 Excel
ExcelUtils.write(response, "支付订单.xls", "数据", PayOrderExcelVO.class, excelDatum);
}
}

View File

@ -0,0 +1,174 @@
package cn.iocoder.yudao.adminserver.modules.pay.controller.order;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.iocoder.yudao.adminserver.modules.pay.controller.order.vo.refund.vo.*;
import cn.iocoder.yudao.adminserver.modules.pay.convert.refund.PayRefundConvert;
import cn.iocoder.yudao.adminserver.modules.pay.service.app.PayAppService;
import cn.iocoder.yudao.adminserver.modules.pay.service.merchant.PayMerchantService;
import cn.iocoder.yudao.adminserver.modules.pay.service.order.PayOrderService;
import cn.iocoder.yudao.adminserver.modules.pay.service.order.PayRefundService;
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.coreservice.modules.pay.dal.dataobject.order.PayOrderDO;
import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.order.PayRefundDO;
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 cn.iocoder.yudao.framework.pay.core.enums.PayChannelEnum;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.IOException;
import java.util.ArrayList;
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
*/
@Api(tags = "退款订单")
@RestController
@RequestMapping("/pay/refund")
@Validated
public class PayRefundController {
@Resource
private PayRefundService refundService;
/**
* 商户 service 组件
*/
@Resource
private PayMerchantService merchantService;
/**
* 应用 service 组件
*/
@Resource
private PayAppService appService;
/**
* 订单 service 组件
*/
@Resource
private PayOrderService orderService;
@GetMapping("/get")
@ApiOperation("获得退款订单")
@ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class)
@PreAuthorize("@ss.hasPermission('pay:refund:query')")
public CommonResult<PayRefundDetailsRespVO> getRefund(@RequestParam("id") Long id) {
PayRefundDO refund = refundService.getRefund(id);
if (ObjectUtil.isNull(refund)) {
return success(new PayRefundDetailsRespVO());
}
PayMerchantDO merchantDO = merchantService.getMerchant(refund.getMerchantId());
PayAppDO appDO = appService.getApp(refund.getAppId());
PayChannelEnum channelEnum = PayChannelEnum.getByCode(refund.getChannelCode());
PayOrderDO orderDO = orderService.getOrder(refund.getOrderId());
PayRefundDetailsRespVO refundDetail = PayRefundConvert.INSTANCE.refundDetailConvert(refund);
refundDetail.setMerchantName(ObjectUtil.isNotNull(merchantDO) ? merchantDO.getName() : "未知商户");
refundDetail.setAppName(ObjectUtil.isNotNull(appDO) ? appDO.getName() : "未知应用");
refundDetail.setChannelCodeName(ObjectUtil.isNotNull(channelEnum) ? channelEnum.getName() : "未知渠道");
refundDetail.setSubject(orderDO.getSubject());
return success(refundDetail);
}
@GetMapping("/page")
@ApiOperation("获得退款订单分页")
@PreAuthorize("@ss.hasPermission('pay:refund:query')")
public CommonResult<PageResult<PayRefundPageItemRespVO>> getRefundPage(@Valid PayRefundPageReqVO pageVO) {
PageResult<PayRefundDO> pageResult = refundService.getRefundPage(pageVO);
if (CollectionUtil.isEmpty(pageResult.getList())) {
return success(new PageResult<>(pageResult.getTotal()));
}
// 处理商户ID数据
Map<Long, PayMerchantDO> merchantMap = merchantService.getMerchantMap(
CollectionUtils.convertList(pageResult.getList(), PayRefundDO::getMerchantId));
// 处理应用ID数据
Map<Long, PayAppDO> appMap = appService.getAppMap(
CollectionUtils.convertList(pageResult.getList(), PayRefundDO::getAppId));
List<PayRefundPageItemRespVO> list = new ArrayList<>(pageResult.getList().size());
pageResult.getList().forEach(c -> {
PayMerchantDO merchantDO = merchantMap.get(c.getMerchantId());
PayAppDO appDO = appMap.get(c.getAppId());
PayChannelEnum channelEnum = PayChannelEnum.getByCode(c.getChannelCode());
PayRefundPageItemRespVO item = PayRefundConvert.INSTANCE.pageItemConvert(c);
item.setMerchantName(ObjectUtil.isNotNull(merchantDO) ? merchantDO.getName() : "未知商户");
item.setAppName(ObjectUtil.isNotNull(appDO) ? appDO.getName() : "未知应用");
item.setChannelCodeName(ObjectUtil.isNotNull(channelEnum) ? channelEnum.getName() : "未知渠道");
list.add(item);
});
return success(new PageResult<>(list, pageResult.getTotal()));
}
@GetMapping("/export-excel")
@ApiOperation("导出退款订单 Excel")
@PreAuthorize("@ss.hasPermission('pay:refund:export')")
@OperateLog(type = EXPORT)
public void exportRefundExcel(@Valid PayRefundExportReqVO exportReqVO,
HttpServletResponse response) throws IOException {
List<PayRefundDO> list = refundService.getRefundList(exportReqVO);
if (CollectionUtil.isEmpty(list)) {
ExcelUtils.write(response, "退款订单.xls", "数据",
PayRefundExcelVO.class, new ArrayList<>());
}
// 处理商户ID数据
Map<Long, PayMerchantDO> merchantMap = merchantService.getMerchantMap(
CollectionUtils.convertList(list, PayRefundDO::getMerchantId));
// 处理应用ID数据
Map<Long, PayAppDO> appMap = appService.getAppMap(
CollectionUtils.convertList(list, PayRefundDO::getAppId));
List<PayRefundExcelVO> excelDatum = new ArrayList<>(list.size());
// 处理商品名称数据
Map<Long, PayOrderDO> orderMap = orderService.getOrderSubjectMap(
CollectionUtils.convertList(list, PayRefundDO::getOrderId));
list.forEach(c -> {
PayMerchantDO merchantDO = merchantMap.get(c.getMerchantId());
PayAppDO appDO = appMap.get(c.getAppId());
PayChannelEnum channelEnum = PayChannelEnum.getByCode(c.getChannelCode());
PayRefundExcelVO excelItem = PayRefundConvert.INSTANCE.excelConvert(c);
excelItem.setMerchantName(ObjectUtil.isNotNull(merchantDO) ? merchantDO.getName() : "未知商户");
excelItem.setAppName(ObjectUtil.isNotNull(appDO) ? appDO.getName() : "未知应用");
excelItem.setChannelCodeName(ObjectUtil.isNotNull(channelEnum) ? channelEnum.getName() : "未知渠道");
excelItem.setSubject(orderMap.get(c.getOrderId()).getSubject());
excelDatum.add(excelItem);
});
// 导出 Excel
ExcelUtils.write(response, "退款订单.xls", "数据", PayRefundExcelVO.class, excelDatum);
}
}

View File

@ -0,0 +1,108 @@
package cn.iocoder.yudao.adminserver.modules.pay.controller.order.vo.order;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import javax.validation.constraints.NotNull;
import java.util.Date;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
/**
* 支付订单
* Base VO提供给添加修改详细的子 VO 使用
* 如果子 VO 存在差异的字段请不要添加到这里影响 Swagger 文档生成
*
* @author aquan
*/
@Data
public class PayOrderBaseVO {
@ApiModelProperty(value = "商户编号", required = true)
@NotNull(message = "商户编号不能为空")
private Long merchantId;
@ApiModelProperty(value = "应用编号", required = true)
@NotNull(message = "应用编号不能为空")
private Long appId;
@ApiModelProperty(value = "渠道编号")
private Long channelId;
@ApiModelProperty(value = "渠道编码")
private String channelCode;
@ApiModelProperty(value = "商户订单编号", required = true)
@NotNull(message = "商户订单编号不能为空")
private String merchantOrderId;
@ApiModelProperty(value = "商品标题", required = true)
@NotNull(message = "商品标题不能为空")
private String subject;
@ApiModelProperty(value = "商品描述", required = true)
@NotNull(message = "商品描述不能为空")
private String body;
@ApiModelProperty(value = "异步通知地址", required = true)
@NotNull(message = "异步通知地址不能为空")
private String notifyUrl;
@ApiModelProperty(value = "通知商户支付结果的回调状态", required = true)
@NotNull(message = "通知商户支付结果的回调状态不能为空")
private Integer notifyStatus;
@ApiModelProperty(value = "支付金额,单位:分", required = true)
@NotNull(message = "支付金额,单位:分不能为空")
private Long amount;
@ApiModelProperty(value = "渠道手续费,单位:百分比")
private Double channelFeeRate;
@ApiModelProperty(value = "渠道手续金额,单位:分")
private Long channelFeeAmount;
@ApiModelProperty(value = "支付状态", required = true)
@NotNull(message = "支付状态不能为空")
private Integer status;
@ApiModelProperty(value = "用户 IP", required = true)
@NotNull(message = "用户 IP不能为空")
private String userIp;
@ApiModelProperty(value = "订单失效时间", required = true)
@NotNull(message = "订单失效时间不能为空")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private Date expireTime;
@ApiModelProperty(value = "订单支付成功时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private Date successTime;
@ApiModelProperty(value = "订单支付通知时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private Date notifyTime;
@ApiModelProperty(value = "支付成功的订单拓展单编号")
private Long successExtensionId;
@ApiModelProperty(value = "退款状态", required = true)
@NotNull(message = "退款状态不能为空")
private Integer refundStatus;
@ApiModelProperty(value = "退款次数", required = true)
@NotNull(message = "退款次数不能为空")
private Integer refundTimes;
@ApiModelProperty(value = "退款总金额,单位:分", required = true)
@NotNull(message = "退款总金额,单位:分不能为空")
private Long refundAmount;
@ApiModelProperty(value = "渠道用户编号")
private String channelUserId;
@ApiModelProperty(value = "渠道订单号")
private String channelOrderNo;
}

View File

@ -0,0 +1,53 @@
package cn.iocoder.yudao.adminserver.modules.pay.controller.order.vo.order;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import java.util.Date;
/**
* 支付订单详细信息由支付订单和支付订单扩展信息组成
*
* @author aquan
*/
@ApiModel("支付订单详细信息 Response VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class PayOrderDetailsRespVO extends PayOrderBaseVO {
@ApiModelProperty(value = "支付订单编号")
private Long id;
@ApiModelProperty(value = "商户名称")
private String merchantName;
@ApiModelProperty(value = "应用名称")
private String appName;
@ApiModelProperty(value = "渠道编号名称")
private String channelCodeName;
@ApiModelProperty(value = "创建时间")
private Date createTime;
/**
* 支付订单扩展
*/
private PayOrderExtension payOrderExtension;
@Data
@ApiModel("支付订单扩展")
public static class PayOrderExtension {
@ApiModelProperty(value = "支付订单号")
private String no;
@ApiModelProperty(value = "支付异步通知的内容")
private String channelNotifyData;
}
}

View File

@ -0,0 +1,91 @@
package cn.iocoder.yudao.adminserver.modules.pay.controller.order.vo.order;
import cn.iocoder.yudao.adminserver.modules.system.enums.SysDictTypeConstants;
import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
import com.alibaba.excel.annotation.ExcelProperty;
import lombok.Data;
import java.util.Date;
/**
* 支付订单Excel VO
*
* @author aquan
*/
@Data
public class PayOrderExcelVO {
@ExcelProperty("支付订单编号")
private Long id;
@ExcelProperty(value = "商户名称")
private String merchantName;
@ExcelProperty(value = "应用名称")
private String appName;
@ExcelProperty("商品标题")
private String subject;
@ExcelProperty("商户订单编号")
private String merchantOrderId;
@ExcelProperty("渠道订单号")
private String channelOrderNo;
@ExcelProperty(value = "支付订单号")
private String no;
@ExcelProperty("支付金额,单位:元")
private String amount;
@ExcelProperty("渠道手续金额,单位:元")
private String channelFeeAmount;
@ExcelProperty("渠道手续费,单位:百分比")
private String channelFeeRate;
@DictFormat(SysDictTypeConstants.PAY_ORDER_STATUS)
@ExcelProperty(value = "支付状态", converter = DictConvert.class)
private Integer status;
@DictFormat(SysDictTypeConstants.PAY_ORDER_NOTIFY_STATUS)
@ExcelProperty(value = "通知商户支付结果的回调状态", converter = DictConvert.class)
private Integer notifyStatus;
@ExcelProperty("异步通知地址")
private String notifyUrl;
@ExcelProperty("创建时间")
private Date createTime;
@ExcelProperty("订单支付成功时间")
private Date successTime;
@ExcelProperty("订单失效时间")
private Date expireTime;
@ExcelProperty("订单支付通知时间")
private Date notifyTime;
@ExcelProperty(value = "渠道编号名称")
private String channelCodeName;
@ExcelProperty("用户 IP")
private String userIp;
@DictFormat(SysDictTypeConstants.PAY_ORDER_REFUND_STATUS)
@ExcelProperty(value = "退款状态", converter = DictConvert.class)
private Integer refundStatus;
@ExcelProperty("退款次数")
private Integer refundTimes;
@ExcelProperty("退款总金额,单位:元")
private String refundAmount;
@ExcelProperty("商品描述")
private String body;
}

View File

@ -0,0 +1,112 @@
package cn.iocoder.yudao.adminserver.modules.pay.controller.order.vo.order;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import java.util.Date;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
/**
* 支付订单 Excel 导出 Request VO
* @author aquan
*/
@ApiModel(value = "支付订单 Excel 导出 Request VO", description = "参数和 PayOrderPageReqVO 是一致的")
@Data
public class PayOrderExportReqVO {
@ApiModelProperty(value = "商户编号")
private Long merchantId;
@ApiModelProperty(value = "应用编号")
private Long appId;
@ApiModelProperty(value = "渠道编号")
private Long channelId;
@ApiModelProperty(value = "渠道编码")
private String channelCode;
@ApiModelProperty(value = "商户订单编号")
private String merchantOrderId;
@ApiModelProperty(value = "商品标题")
private String subject;
@ApiModelProperty(value = "商品描述")
private String body;
@ApiModelProperty(value = "异步通知地址")
private String notifyUrl;
@ApiModelProperty(value = "通知商户支付结果的回调状态")
private Integer notifyStatus;
@ApiModelProperty(value = "支付金额,单位:分")
private Long amount;
@ApiModelProperty(value = "渠道手续费,单位:百分比")
private Double channelFeeRate;
@ApiModelProperty(value = "渠道手续金额,单位:分")
private Long channelFeeAmount;
@ApiModelProperty(value = "支付状态")
private Integer status;
@ApiModelProperty(value = "用户 IP")
private String userIp;
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
@ApiModelProperty(value = "开始订单失效时间")
private Date beginExpireTime;
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
@ApiModelProperty(value = "结束订单失效时间")
private Date endExpireTime;
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
@ApiModelProperty(value = "开始订单支付成功时间")
private Date beginSuccessTime;
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
@ApiModelProperty(value = "结束订单支付成功时间")
private Date endSuccessTime;
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
@ApiModelProperty(value = "开始订单支付通知时间")
private Date beginNotifyTime;
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
@ApiModelProperty(value = "结束订单支付通知时间")
private Date endNotifyTime;
@ApiModelProperty(value = "支付成功的订单拓展单编号")
private Long successExtensionId;
@ApiModelProperty(value = "退款状态")
private Integer refundStatus;
@ApiModelProperty(value = "退款次数")
private Integer refundTimes;
@ApiModelProperty(value = "退款总金额,单位:分")
private Long refundAmount;
@ApiModelProperty(value = "渠道用户编号")
private String channelUserId;
@ApiModelProperty(value = "渠道订单号")
private String channelOrderNo;
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
@ApiModelProperty(value = "开始创建时间")
private Date beginCreateTime;
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
@ApiModelProperty(value = "结束创建时间")
private Date endCreateTime;
}

View File

@ -0,0 +1,41 @@
package cn.iocoder.yudao.adminserver.modules.pay.controller.order.vo.order;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import java.util.Date;
/**
* 支付订单分页 Request VO
*
* @author aquan
*/
@ApiModel("支付订单分页 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class PayOrderPageItemRespVO extends PayOrderBaseVO {
@ApiModelProperty(value = "支付订单编号", required = true)
private Long id;
@ApiModelProperty(value = "创建时间", required = true)
private Date createTime;
@ApiModelProperty(value = "商户名称")
private String merchantName;
@ApiModelProperty(value = "应用名称")
private String appName;
@ApiModelProperty(value = "渠道名称")
private String channelCodeName;
@ApiModelProperty(value = "支付订单号")
private String no;
}

View File

@ -0,0 +1,118 @@
package cn.iocoder.yudao.adminserver.modules.pay.controller.order.vo.order;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import org.springframework.format.annotation.DateTimeFormat;
import java.util.Date;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
/**
* 支付订单分页 Request VO
*
* @author aquan
*/
@ApiModel("支付订单分页 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class PayOrderPageReqVO extends PageParam {
@ApiModelProperty(value = "商户编号")
private Long merchantId;
@ApiModelProperty(value = "应用编号")
private Long appId;
@ApiModelProperty(value = "渠道编号")
private Long channelId;
@ApiModelProperty(value = "渠道编码")
private String channelCode;
@ApiModelProperty(value = "商户订单编号")
private String merchantOrderId;
@ApiModelProperty(value = "商品标题")
private String subject;
@ApiModelProperty(value = "商品描述")
private String body;
@ApiModelProperty(value = "异步通知地址")
private String notifyUrl;
@ApiModelProperty(value = "通知商户支付结果的回调状态")
private Integer notifyStatus;
@ApiModelProperty(value = "支付金额,单位:分")
private Long amount;
@ApiModelProperty(value = "渠道手续费,单位:百分比")
private Double channelFeeRate;
@ApiModelProperty(value = "渠道手续金额,单位:分")
private Long channelFeeAmount;
@ApiModelProperty(value = "支付状态")
private Integer status;
@ApiModelProperty(value = "用户 IP")
private String userIp;
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
@ApiModelProperty(value = "开始订单失效时间")
private Date beginExpireTime;
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
@ApiModelProperty(value = "结束订单失效时间")
private Date endExpireTime;
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
@ApiModelProperty(value = "开始订单支付成功时间")
private Date beginSuccessTime;
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
@ApiModelProperty(value = "结束订单支付成功时间")
private Date endSuccessTime;
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
@ApiModelProperty(value = "开始订单支付通知时间")
private Date beginNotifyTime;
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
@ApiModelProperty(value = "结束订单支付通知时间")
private Date endNotifyTime;
@ApiModelProperty(value = "支付成功的订单拓展单编号")
private Long successExtensionId;
@ApiModelProperty(value = "退款状态")
private Integer refundStatus;
@ApiModelProperty(value = "退款次数")
private Integer refundTimes;
@ApiModelProperty(value = "退款总金额,单位:分")
private Long refundAmount;
@ApiModelProperty(value = "渠道用户编号")
private String channelUserId;
@ApiModelProperty(value = "渠道订单号")
private String channelOrderNo;
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
@ApiModelProperty(value = "开始创建时间")
private Date beginCreateTime;
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
@ApiModelProperty(value = "结束创建时间")
private Date endCreateTime;
}

View File

@ -0,0 +1,28 @@
package cn.iocoder.yudao.adminserver.modules.pay.controller.order.vo.order;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import java.util.Date;
/**
* 支付订单 Response VO
*
* @author aquan
*/
@ApiModel("支付订单 Response VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class PayOrderRespVO extends PayOrderBaseVO {
@ApiModelProperty(value = "支付订单编号", required = true)
private Long id;
@ApiModelProperty(value = "创建时间", required = true)
private Date createTime;
}

View File

@ -0,0 +1,110 @@
package cn.iocoder.yudao.adminserver.modules.pay.controller.order.vo.refund.vo;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import javax.validation.constraints.NotNull;
import java.util.Date;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
/**
* 退款订单 Base VO提供给添加修改详细的子 VO 使用
* 如果子 VO 存在差异的字段请不要添加到这里影响 Swagger 文档生成
*/
@Data
public class PayRefundBaseVO {
@ApiModelProperty(value = "商户编号", required = true)
@NotNull(message = "商户编号不能为空")
private Long merchantId;
@ApiModelProperty(value = "应用编号", required = true)
@NotNull(message = "应用编号不能为空")
private Long appId;
@ApiModelProperty(value = "渠道编号", required = true)
@NotNull(message = "渠道编号不能为空")
private Long channelId;
@ApiModelProperty(value = "渠道编码", required = true)
@NotNull(message = "渠道编码不能为空")
private String channelCode;
@ApiModelProperty(value = "支付订单编号 pay_order 表id", required = true)
@NotNull(message = "支付订单编号 pay_order 表id不能为空")
private Long orderId;
@ApiModelProperty(value = "交易订单号 pay_extension 表no 字段", required = true)
@NotNull(message = "交易订单号 pay_extension 表no 字段不能为空")
private String tradeNo;
@ApiModelProperty(value = "商户订单编号(商户系统生成)", required = true)
@NotNull(message = "商户订单编号(商户系统生成)不能为空")
private String merchantOrderId;
@ApiModelProperty(value = "商户退款订单号(商户系统生成)", required = true)
@NotNull(message = "商户退款订单号(商户系统生成)不能为空")
private String merchantRefundNo;
@ApiModelProperty(value = "异步通知商户地址", required = true)
@NotNull(message = "异步通知商户地址不能为空")
private String notifyUrl;
@ApiModelProperty(value = "通知商户退款结果的回调状态", required = true)
@NotNull(message = "通知商户退款结果的回调状态不能为空")
private Integer notifyStatus;
@ApiModelProperty(value = "退款状态", required = true)
@NotNull(message = "退款状态不能为空")
private Integer status;
@ApiModelProperty(value = "退款类型(部分退款,全部退款)", required = true)
@NotNull(message = "退款类型(部分退款,全部退款)不能为空")
private Integer type;
@ApiModelProperty(value = "支付金额,单位分", required = true)
@NotNull(message = "支付金额,单位分不能为空")
private Long payAmount;
@ApiModelProperty(value = "退款金额,单位分", required = true)
@NotNull(message = "退款金额,单位分不能为空")
private Long refundAmount;
@ApiModelProperty(value = "退款原因", required = true)
@NotNull(message = "退款原因不能为空")
private String reason;
@ApiModelProperty(value = "用户 IP")
private String userIp;
@ApiModelProperty(value = "渠道订单号pay_order 中的channel_order_no 对应", required = true)
@NotNull(message = "渠道订单号pay_order 中的channel_order_no 对应不能为空")
private String channelOrderNo;
@ApiModelProperty(value = "渠道退款单号,渠道返回")
private String channelRefundNo;
@ApiModelProperty(value = "渠道调用报错时,错误码")
private String channelErrorCode;
@ApiModelProperty(value = "渠道调用报错时,错误信息")
private String channelErrorMsg;
@ApiModelProperty(value = "支付渠道的额外参数")
private String channelExtras;
@ApiModelProperty(value = "退款失效时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private Date expireTime;
@ApiModelProperty(value = "退款成功时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private Date successTime;
@ApiModelProperty(value = "退款通知时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private Date notifyTime;
}

View File

@ -0,0 +1,12 @@
package cn.iocoder.yudao.adminserver.modules.pay.controller.order.vo.refund.vo;
import lombok.*;
import io.swagger.annotations.*;
@ApiModel("退款订单创建 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class PayRefundCreateReqVO extends PayRefundBaseVO {
}

View File

@ -0,0 +1,44 @@
package cn.iocoder.yudao.adminserver.modules.pay.controller.order.vo.refund.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import javax.validation.constraints.NotNull;
import java.util.Date;
/**
* 退款订单详情 Response VO
*
* @author aquan
*/
@ApiModel("退款订单详情 Response VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class PayRefundDetailsRespVO extends PayRefundBaseVO {
@ApiModelProperty(value = "支付退款编号", required = true)
private Long id;
@ApiModelProperty(value = "商户名称")
private String merchantName;
@ApiModelProperty(value = "应用名称")
private String appName;
@ApiModelProperty(value = "渠道编号名称")
private String channelCodeName;
@NotNull(message = "商品标题不能为空")
private String subject;
@ApiModelProperty(value = "创建时间")
private Date createTime;
@ApiModelProperty(value = "更新时间")
private Date updateTime;
}

View File

@ -0,0 +1,88 @@
package cn.iocoder.yudao.adminserver.modules.pay.controller.order.vo.refund.vo;
import cn.iocoder.yudao.adminserver.modules.system.enums.SysDictTypeConstants;
import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
import com.alibaba.excel.annotation.ExcelProperty;
import lombok.Data;
import java.util.Date;
/**
* 退款订单 Excel VO
*
* @author aquan
*/
@Data
public class PayRefundExcelVO {
@ExcelProperty("支付退款编号")
private Long id;
@ExcelProperty("商品名称")
private String subject;
@ExcelProperty(value = "商户名称")
private String merchantName;
@ExcelProperty(value = "应用名称")
private String appName;
@ExcelProperty(value = "渠道编号名称")
private String channelCodeName;
@ExcelProperty("交易订单号")
private String tradeNo;
@ExcelProperty("商户订单编号")
private String merchantOrderId;
@ExcelProperty("商户退款订单号")
private String merchantRefundNo;
@ExcelProperty("异步通知商户地址")
private String notifyUrl;
@DictFormat(SysDictTypeConstants.PAY_ORDER_NOTIFY_STATUS)
@ExcelProperty(value = "商户退款结果回调状态", converter = DictConvert.class)
private Integer notifyStatus;
@DictFormat(SysDictTypeConstants.PAY_REFUND_ORDER_STATUS)
@ExcelProperty(value = "退款状态", converter = DictConvert.class)
private Integer status;
@DictFormat(SysDictTypeConstants.PAY_REFUND_ORDER_TYPE)
@ExcelProperty(value = "退款类型", converter = DictConvert.class)
private Integer type;
@ExcelProperty("支付金额,单位:元")
private String payAmount;
@ExcelProperty("退款金额,单位:元")
private String refundAmount;
@ExcelProperty("退款原因")
private String reason;
@ExcelProperty("用户付款 IP")
private String userIp;
@ExcelProperty("渠道订单号")
private String channelOrderNo;
@ExcelProperty("渠道退款单号")
private String channelRefundNo;
@ExcelProperty("创建时间")
private Date createTime;
@ExcelProperty("退款成功时间")
private Date successTime;
@ExcelProperty("退款通知时间")
private Date notifyTime;
@ExcelProperty("退款失效时间")
private Date expireTime;
}

View File

@ -0,0 +1,111 @@
package cn.iocoder.yudao.adminserver.modules.pay.controller.order.vo.refund.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import java.util.Date;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@ApiModel(value = "退款订单 Excel 导出 Request VO", description = "参数和 PayRefundPageReqVO 是一致的")
@Data
public class PayRefundExportReqVO {
@ApiModelProperty(value = "商户编号")
private Long merchantId;
@ApiModelProperty(value = "应用编号")
private Long appId;
@ApiModelProperty(value = "渠道编号")
private Long channelId;
@ApiModelProperty(value = "渠道编码")
private String channelCode;
@ApiModelProperty(value = "支付订单编号 pay_order 表id")
private Long orderId;
@ApiModelProperty(value = "交易订单号 pay_extension 表no 字段")
private String tradeNo;
@ApiModelProperty(value = "商户订单编号(商户系统生成)")
private String merchantOrderId;
@ApiModelProperty(value = "商户退款订单号(商户系统生成)")
private String merchantRefundNo;
@ApiModelProperty(value = "异步通知商户地址")
private String notifyUrl;
@ApiModelProperty(value = "通知商户退款结果的回调状态")
private Integer notifyStatus;
@ApiModelProperty(value = "退款状态")
private Integer status;
@ApiModelProperty(value = "退款类型(部分退款,全部退款)")
private Integer type;
@ApiModelProperty(value = "支付金额,单位分")
private Long payAmount;
@ApiModelProperty(value = "退款金额,单位分")
private Long refundAmount;
@ApiModelProperty(value = "退款原因")
private String reason;
@ApiModelProperty(value = "用户 IP")
private String userIp;
@ApiModelProperty(value = "渠道订单号pay_order 中的channel_order_no 对应")
private String channelOrderNo;
@ApiModelProperty(value = "渠道退款单号,渠道返回")
private String channelRefundNo;
@ApiModelProperty(value = "渠道调用报错时,错误码")
private String channelErrorCode;
@ApiModelProperty(value = "渠道调用报错时,错误信息")
private String channelErrorMsg;
@ApiModelProperty(value = "支付渠道的额外参数")
private String channelExtras;
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
@ApiModelProperty(value = "开始退款失效时间")
private Date beginExpireTime;
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
@ApiModelProperty(value = "结束退款失效时间")
private Date endExpireTime;
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
@ApiModelProperty(value = "开始退款成功时间")
private Date beginSuccessTime;
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
@ApiModelProperty(value = "结束退款成功时间")
private Date endSuccessTime;
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
@ApiModelProperty(value = "开始退款通知时间")
private Date beginNotifyTime;
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
@ApiModelProperty(value = "结束退款通知时间")
private Date endNotifyTime;
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
@ApiModelProperty(value = "开始创建时间")
private Date beginCreateTime;
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
@ApiModelProperty(value = "结束创建时间")
private Date endCreateTime;
}

View File

@ -0,0 +1,36 @@
package cn.iocoder.yudao.adminserver.modules.pay.controller.order.vo.refund.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import java.util.Date;
/**
* 退款订单分页查询 Response VO
* @author aquan
*/
@ApiModel("退款订单分页查询 Response VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class PayRefundPageItemRespVO extends PayRefundBaseVO {
@ApiModelProperty(value = "支付订单编号", required = true)
private Long id;
@ApiModelProperty(value = "商户名称")
private String merchantName;
@ApiModelProperty(value = "应用名称")
private String appName;
@ApiModelProperty(value = "渠道名称")
private String channelCodeName;
@ApiModelProperty(value = "创建时间", required = true)
private Date createTime;
}

View File

@ -0,0 +1,116 @@
package cn.iocoder.yudao.adminserver.modules.pay.controller.order.vo.refund.vo;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import org.springframework.format.annotation.DateTimeFormat;
import java.util.Date;
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 PayRefundPageReqVO extends PageParam {
@ApiModelProperty(value = "商户编号")
private Long merchantId;
@ApiModelProperty(value = "应用编号")
private Long appId;
@ApiModelProperty(value = "渠道编号")
private Long channelId;
@ApiModelProperty(value = "渠道编码")
private String channelCode;
@ApiModelProperty(value = "支付订单编号 pay_order 表id")
private Long orderId;
@ApiModelProperty(value = "交易订单号 pay_extension 表no 字段")
private String tradeNo;
@ApiModelProperty(value = "商户订单编号(商户系统生成)")
private String merchantOrderId;
@ApiModelProperty(value = "商户退款订单号(商户系统生成)")
private String merchantRefundNo;
@ApiModelProperty(value = "异步通知商户地址")
private String notifyUrl;
@ApiModelProperty(value = "通知商户退款结果的回调状态")
private Integer notifyStatus;
@ApiModelProperty(value = "退款状态")
private Integer status;
@ApiModelProperty(value = "退款类型(部分退款,全部退款)")
private Integer type;
@ApiModelProperty(value = "支付金额,单位分")
private Long payAmount;
@ApiModelProperty(value = "退款金额,单位分")
private Long refundAmount;
@ApiModelProperty(value = "退款原因")
private String reason;
@ApiModelProperty(value = "用户 IP")
private String userIp;
@ApiModelProperty(value = "渠道订单号pay_order 中的channel_order_no 对应")
private String channelOrderNo;
@ApiModelProperty(value = "渠道退款单号,渠道返回")
private String channelRefundNo;
@ApiModelProperty(value = "渠道调用报错时,错误码")
private String channelErrorCode;
@ApiModelProperty(value = "渠道调用报错时,错误信息")
private String channelErrorMsg;
@ApiModelProperty(value = "支付渠道的额外参数")
private String channelExtras;
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
@ApiModelProperty(value = "开始退款失效时间")
private Date beginExpireTime;
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
@ApiModelProperty(value = "结束退款失效时间")
private Date endExpireTime;
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
@ApiModelProperty(value = "开始退款成功时间")
private Date beginSuccessTime;
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
@ApiModelProperty(value = "结束退款成功时间")
private Date endSuccessTime;
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
@ApiModelProperty(value = "开始退款通知时间")
private Date beginNotifyTime;
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
@ApiModelProperty(value = "结束退款通知时间")
private Date endNotifyTime;
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
@ApiModelProperty(value = "开始创建时间")
private Date beginCreateTime;
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
@ApiModelProperty(value = "结束创建时间")
private Date endCreateTime;
}

View File

@ -0,0 +1,23 @@
package cn.iocoder.yudao.adminserver.modules.pay.controller.order.vo.refund.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import java.util.Date;
@ApiModel("退款订单 Response VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class PayRefundRespVO extends PayRefundBaseVO {
@ApiModelProperty(value = "支付退款编号", required = true)
private Long id;
@ApiModelProperty(value = "创建时间", required = true)
private Date createTime;
}

View File

@ -0,0 +1,17 @@
package cn.iocoder.yudao.adminserver.modules.pay.controller.order.vo.refund.vo;
import lombok.*;
import io.swagger.annotations.*;
import javax.validation.constraints.*;
@ApiModel("退款订单更新 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class PayRefundUpdateReqVO extends PayRefundBaseVO {
@ApiModelProperty(value = "支付退款编号", required = true)
@NotNull(message = "支付退款编号不能为空")
private Long id;
}

View File

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

View File

@ -0,0 +1,42 @@
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(PayChannelCreateReqVO bean);
@Mapping(target = "config",ignore = true)
PayChannelDO convert(PayChannelUpdateReqVO bean);
@Mapping(target = "config",expression = "java(cn.iocoder.yudao.framework.common.util.json.JsonUtils.toJsonString(bean.getConfig()))")
PayChannelRespVO convert(PayChannelDO bean);
List<PayChannelRespVO> convertList(List<PayChannelDO> list);
PageResult<PayChannelRespVO> convertPage(PageResult<PayChannelDO> page);
List<PayChannelExcelVO> convertList02(List<PayChannelDO> list);
}

View File

@ -0,0 +1,34 @@
package cn.iocoder.yudao.adminserver.modules.pay.convert.merchant;
import java.util.*;
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.merchant.vo.*;
/**
* 支付商户信息 Convert
*
* @author 芋艿
*/
@Mapper
public interface PayMerchantConvert {
PayMerchantConvert INSTANCE = Mappers.getMapper(PayMerchantConvert.class);
PayMerchantDO convert(PayMerchantCreateReqVO bean);
PayMerchantDO convert(PayMerchantUpdateReqVO bean);
PayMerchantRespVO convert(PayMerchantDO bean);
List<PayMerchantRespVO> convertList(List<PayMerchantDO> list);
PageResult<PayMerchantRespVO> convertPage(PageResult<PayMerchantDO> page);
List<PayMerchantExcelVO> convertList02(List<PayMerchantDO> list);
}

View File

@ -0,0 +1,104 @@
package cn.iocoder.yudao.adminserver.modules.pay.convert.order;
import cn.iocoder.yudao.adminserver.modules.pay.controller.order.vo.order.PayOrderDetailsRespVO;
import cn.iocoder.yudao.adminserver.modules.pay.controller.order.vo.order.PayOrderExcelVO;
import cn.iocoder.yudao.adminserver.modules.pay.controller.order.vo.order.PayOrderPageItemRespVO;
import cn.iocoder.yudao.adminserver.modules.pay.controller.order.vo.order.PayOrderRespVO;
import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.order.PayOrderDO;
import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.order.PayOrderExtensionDO;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.List;
/**
* 支付订单 Convert
*
* @author aquan
*/
@Mapper
public interface PayOrderConvert {
PayOrderConvert INSTANCE = Mappers.getMapper(PayOrderConvert.class);
PayOrderRespVO convert(PayOrderDO bean);
/**
* 订单DO 转换为 详细订单 RespVO
*
* @param bean 订单DO
* @return 详细订单 RespVO
*/
PayOrderDetailsRespVO orderDetailConvert(PayOrderDO bean);
/**
* 订单扩展DO 转换为 详细订单扩展 RespVO
*
* @param bean 订单扩展DO
* @return 详细订单扩展 RespVO
*/
PayOrderDetailsRespVO.PayOrderExtension orderDetailExtensionConvert(PayOrderExtensionDO bean);
List<PayOrderRespVO> convertList(List<PayOrderDO> list);
PageResult<PayOrderRespVO> convertPage(PageResult<PayOrderDO> page);
List<PayOrderExcelVO> convertList02(List<PayOrderDO> list);
/**
* 订单DO转自定义分页对象
*
* @param bean 订单DO
* @return 分页对象
*/
PayOrderPageItemRespVO pageConvertItemPage(PayOrderDO bean);
/**
* 订单DO 订单导出excel VO
*
* @param bean 订单 DO
* @return 订单导出excel VO
*/
default PayOrderExcelVO excelConvert(PayOrderDO bean) {
if (bean == null) {
return null;
}
PayOrderExcelVO payOrderExcelVO = new PayOrderExcelVO();
payOrderExcelVO.setId(bean.getId());
payOrderExcelVO.setSubject(bean.getSubject());
payOrderExcelVO.setMerchantOrderId(bean.getMerchantOrderId());
payOrderExcelVO.setChannelOrderNo(bean.getChannelOrderNo());
payOrderExcelVO.setStatus(bean.getStatus());
payOrderExcelVO.setNotifyStatus(bean.getNotifyStatus());
payOrderExcelVO.setNotifyUrl(bean.getNotifyUrl());
payOrderExcelVO.setCreateTime(bean.getCreateTime());
payOrderExcelVO.setSuccessTime(bean.getSuccessTime());
payOrderExcelVO.setExpireTime(bean.getExpireTime());
payOrderExcelVO.setNotifyTime(bean.getNotifyTime());
payOrderExcelVO.setUserIp(bean.getUserIp());
payOrderExcelVO.setRefundStatus(bean.getRefundStatus());
payOrderExcelVO.setRefundTimes(bean.getRefundTimes());
payOrderExcelVO.setBody(bean.getBody());
BigDecimal multiple = new BigDecimal(100);
payOrderExcelVO.setAmount(BigDecimal.valueOf(bean.getAmount())
.divide(multiple, 2, RoundingMode.HALF_UP).toString());
payOrderExcelVO.setChannelFeeAmount(BigDecimal.valueOf(bean.getChannelFeeAmount())
.divide(multiple, 2, RoundingMode.HALF_UP).toString());
payOrderExcelVO.setChannelFeeRate(java.math.BigDecimal.valueOf(bean.getChannelFeeRate())
.multiply(multiple).toString());
payOrderExcelVO.setRefundAmount(BigDecimal.valueOf(bean.getRefundAmount())
.divide(multiple, 2, RoundingMode.HALF_UP).toString());
return payOrderExcelVO;
}
}

View File

@ -0,0 +1,90 @@
package cn.iocoder.yudao.adminserver.modules.pay.convert.refund;
import cn.iocoder.yudao.adminserver.modules.pay.controller.order.vo.refund.vo.*;
import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.order.PayRefundDO;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.List;
/**
* 退款订单 Convert
*
* @author aquan
*/
@Mapper
public interface PayRefundConvert {
PayRefundConvert INSTANCE = Mappers.getMapper(PayRefundConvert.class);
PayRefundDO convert(PayRefundCreateReqVO bean);
PayRefundDO convert(PayRefundUpdateReqVO bean);
PayRefundRespVO convert(PayRefundDO bean);
/**
* 退款订单 DO 退款详情订单 VO
*
* @param bean 退款订单 DO
* @return 退款详情订单 VO
*/
PayRefundDetailsRespVO refundDetailConvert(PayRefundDO bean);
/**
* 退款订单DO 分页退款条目VO
*
* @param bean 退款订单DO
* @return 分页退款条目VO
*/
PayRefundPageItemRespVO pageItemConvert(PayRefundDO bean);
List<PayRefundRespVO> convertList(List<PayRefundDO> list);
PageResult<PayRefundRespVO> convertPage(PageResult<PayRefundDO> page);
List<PayRefundExcelVO> convertList02(List<PayRefundDO> list);
/**
* 退款订单DO 导出excel VO
*
* @param bean 退款订单DO
* @return 导出 excel VO
*/
default PayRefundExcelVO excelConvert(PayRefundDO bean) {
if (bean == null) {
return null;
}
PayRefundExcelVO payRefundExcelVO = new PayRefundExcelVO();
payRefundExcelVO.setId(bean.getId());
payRefundExcelVO.setTradeNo(bean.getTradeNo());
payRefundExcelVO.setMerchantOrderId(bean.getMerchantOrderId());
payRefundExcelVO.setMerchantRefundNo(bean.getMerchantRefundNo());
payRefundExcelVO.setNotifyUrl(bean.getNotifyUrl());
payRefundExcelVO.setNotifyStatus(bean.getNotifyStatus());
payRefundExcelVO.setStatus(bean.getStatus());
payRefundExcelVO.setType(bean.getType());
payRefundExcelVO.setReason(bean.getReason());
payRefundExcelVO.setUserIp(bean.getUserIp());
payRefundExcelVO.setChannelOrderNo(bean.getChannelOrderNo());
payRefundExcelVO.setChannelRefundNo(bean.getChannelRefundNo());
payRefundExcelVO.setExpireTime(bean.getExpireTime());
payRefundExcelVO.setSuccessTime(bean.getSuccessTime());
payRefundExcelVO.setNotifyTime(bean.getNotifyTime());
payRefundExcelVO.setCreateTime(bean.getCreateTime());
BigDecimal multiple = new BigDecimal(100);
payRefundExcelVO.setPayAmount(BigDecimal.valueOf(bean.getPayAmount())
.divide(multiple, 2, RoundingMode.HALF_UP).toString());
payRefundExcelVO.setRefundAmount(BigDecimal.valueOf(bean.getRefundAmount())
.divide(multiple, 2, RoundingMode.HALF_UP).toString());
return payRefundExcelVO;
}
}

View File

@ -0,0 +1,83 @@
package cn.iocoder.yudao.adminserver.modules.pay.dal.mysql.app;
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.coreservice.modules.pay.dal.dataobject.merchant.PayAppDO;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.framework.mybatis.core.query.QueryWrapperX;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import org.apache.ibatis.annotations.Mapper;
import java.util.Collection;
import java.util.List;
/**
* 支付应用信息 Mapper
*
* @author aquan
*/
@Mapper
public interface PayAppMapper extends BaseMapperX<PayAppDO> {
/**
* 分页查询
*
* @param reqVO 支付应用信息分页查询条件
* @param merchantIds 商户 ID 集合
* @return 支付应用信息
*/
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"));
}
/**
* 列表查询
*
* @param reqVO 支付应用信息 Excel 导出查询条件
* @param merchantIds 商户 ID 集合
* @return 支付应用信息
*/
default List<PayAppDO> selectList(PayAppExportReqVO reqVO, Collection<Long> merchantIds) {
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())
.inIfPresent("merchant_id", merchantIds)
.betweenIfPresent("create_time", reqVO.getBeginCreateTime(), reqVO.getEndCreateTime())
.orderByDesc("id"));
}
/**
* 根据 商户 ID 查询支付应用信息
*
* @param merchantId 商户 ID
* @return 支付应用信息列表
*/
default List<PayAppDO> getListByMerchantId(String merchantId) {
return selectList(new LambdaQueryWrapper<PayAppDO>()
.select(PayAppDO::getId, PayAppDO::getName)
.eq(PayAppDO::getMerchantId, merchantId));
}
/**
* 根据商户号统计存在的支付应用数量
*
* @param merchantId 商户 ID
* @return 支付应用数量
*/
default Long selectCount(Long merchantId) {
return selectCount(new LambdaQueryWrapper<PayAppDO>().eq(PayAppDO::getMerchantId, merchantId));
}
}

View File

@ -0,0 +1,91 @@
package cn.iocoder.yudao.adminserver.modules.pay.dal.mysql.channel;
import cn.iocoder.yudao.adminserver.modules.pay.controller.channel.vo.PayChannelExportReqVO;
import cn.iocoder.yudao.adminserver.modules.pay.controller.channel.vo.PayChannelPageReqVO;
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.mapper.BaseMapperX;
import cn.iocoder.yudao.framework.mybatis.core.query.QueryWrapperX;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.apache.ibatis.annotations.Mapper;
import java.util.Collection;
import java.util.List;
/**
* 支付渠道
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") );
}
/**
* 根据条件获取通道数量
*
* @param merchantId 商户编号
* @param appid 应用编号
* @param code 通道编码
* @return 数量
*/
default Integer selectCount(Long merchantId, Long appid, String code) {
return this.selectCount(new QueryWrapper<PayChannelDO>().lambda()
.eq(PayChannelDO::getMerchantId, merchantId)
.eq(PayChannelDO::getAppId, appid)
.eq(PayChannelDO::getCode, code)).intValue();
}
/**
* 根据条件获取通道
*
* @param merchantId 商户编号
* @param appid 应用编号
* @param code 通道编码
* @return 数量
*/
default PayChannelDO selectOne(Long merchantId, Long appid, String code) {
return this.selectOne((new QueryWrapper<PayChannelDO>().lambda()
.eq(PayChannelDO::getMerchantId, merchantId)
.eq(PayChannelDO::getAppId, appid)
.eq(PayChannelDO::getCode, code)
));
}
/**
* 根据支付应用ID集合获得支付渠道列表
*
* @param appIds 应用编号集合
* @return 支付渠道列表
*/
default List<PayChannelDO> getChannelListByAppIds(Collection<Long> appIds){
return this.selectList(new QueryWrapper<PayChannelDO>().lambda()
.in(PayChannelDO::getAppId, appIds));
}
}

View File

@ -0,0 +1,53 @@
package cn.iocoder.yudao.adminserver.modules.pay.dal.mysql.merchant;
import cn.iocoder.yudao.adminserver.modules.pay.controller.merchant.vo.PayMerchantExportReqVO;
import cn.iocoder.yudao.adminserver.modules.pay.controller.merchant.vo.PayMerchantPageReqVO;
import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayMerchantDO;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.framework.mybatis.core.query.QueryWrapperX;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
/**
* 支付商户信息 Mapper
*
* @author 芋艿
*/
@Mapper
public interface PayMerchantMapper extends BaseMapperX<PayMerchantDO> {
default PageResult<PayMerchantDO> selectPage(PayMerchantPageReqVO reqVO) {
return selectPage(reqVO, new QueryWrapperX<PayMerchantDO>()
.likeIfPresent("no", reqVO.getNo())
.likeIfPresent("name", reqVO.getName())
.likeIfPresent("short_name", reqVO.getShortName())
.eqIfPresent("status", reqVO.getStatus())
.eqIfPresent("remark", reqVO.getRemark())
.betweenIfPresent("create_time", reqVO.getBeginCreateTime(), reqVO.getEndCreateTime())
.orderByDesc("id"));
}
default List<PayMerchantDO> selectList(PayMerchantExportReqVO reqVO) {
return selectList(new QueryWrapperX<PayMerchantDO>()
.likeIfPresent("no", reqVO.getNo())
.likeIfPresent("name", reqVO.getName())
.likeIfPresent("short_name", reqVO.getShortName())
.eqIfPresent("status", reqVO.getStatus())
.eqIfPresent("remark", reqVO.getRemark())
.betweenIfPresent("create_time", reqVO.getBeginCreateTime(), reqVO.getEndCreateTime())
.orderByDesc("id"));
}
/**
* 根据商户名称模糊查询商户集合
*
* @param merchantName 商户名称
* @return 商户集合
*/
default List<PayMerchantDO> getMerchantListByName(String merchantName) {
return this.selectList(new QueryWrapperX<PayMerchantDO>()
.likeIfPresent("name", merchantName));
}
}

View File

@ -0,0 +1,16 @@
package cn.iocoder.yudao.adminserver.modules.pay.dal.mysql.order;
import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.order.PayOrderExtensionDO;
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import org.apache.ibatis.annotations.Mapper;
/**
* 支付订单 Mapper
*
* @author aquan
*/
@Mapper
public interface PayOrderExtensionMapper extends BaseMapperX<PayOrderExtensionDO> {
}

View File

@ -0,0 +1,79 @@
package cn.iocoder.yudao.adminserver.modules.pay.dal.mysql.order;
import cn.iocoder.yudao.adminserver.modules.pay.controller.order.vo.order.PayOrderExportReqVO;
import cn.iocoder.yudao.adminserver.modules.pay.controller.order.vo.order.PayOrderPageReqVO;
import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.order.PayOrderDO;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.framework.mybatis.core.query.QueryWrapperX;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import org.apache.ibatis.annotations.Mapper;
import java.util.Collection;
import java.util.List;
/**
* 支付订单 Mapper 组件
*
* @author aquan
*/
@Mapper
public interface PayOrderMapper extends BaseMapperX<PayOrderDO> {
default PageResult<PayOrderDO> selectPage(PayOrderPageReqVO reqVO) {
return selectPage(reqVO, new QueryWrapperX<PayOrderDO>()
.eqIfPresent("merchant_id", reqVO.getMerchantId())
.eqIfPresent("app_id", reqVO.getAppId())
.eqIfPresent("channel_id", reqVO.getChannelId())
.eqIfPresent("channel_code", reqVO.getChannelCode())
.likeIfPresent("merchant_order_id", reqVO.getMerchantOrderId())
.eqIfPresent("notify_status", reqVO.getNotifyStatus())
.eqIfPresent("status", reqVO.getStatus())
.eqIfPresent("refund_status", reqVO.getRefundStatus())
.likeIfPresent("channel_order_no", reqVO.getChannelOrderNo())
.betweenIfPresent("create_time", reqVO.getBeginCreateTime(), reqVO.getEndCreateTime())
.orderByDesc("id"));
}
default List<PayOrderDO> selectList(PayOrderExportReqVO reqVO) {
return selectList(new QueryWrapperX<PayOrderDO>()
.eqIfPresent("merchant_id", reqVO.getMerchantId())
.eqIfPresent("app_id", reqVO.getAppId())
.eqIfPresent("channel_id", reqVO.getChannelId())
.eqIfPresent("channel_code", reqVO.getChannelCode())
.likeIfPresent("merchant_order_id", reqVO.getMerchantOrderId())
.eqIfPresent("notify_status", reqVO.getNotifyStatus())
.eqIfPresent("status", reqVO.getStatus())
.eqIfPresent("refund_status", reqVO.getRefundStatus())
.likeIfPresent("channel_order_no", reqVO.getChannelOrderNo())
.betweenIfPresent("create_time", reqVO.getBeginCreateTime(), reqVO.getEndCreateTime())
.orderByDesc("id"));
}
/**
* 根据订单 ID 集合查询订单商品名称
*
* @param idList 订单 ID 集合
* @return 只包含商品名称和标题的订单集合对象
*/
default List<PayOrderDO> findByIdListQueryOrderSubject(Collection<Long> idList) {
return selectList(new LambdaQueryWrapper<PayOrderDO>()
.select(PayOrderDO::getId, PayOrderDO::getSubject)
.in(PayOrderDO::getId, idList));
}
/**
* 查询符合的订单数量
*
* @param appId 应用编号
* @param status 订单状态
* @return 条数
*/
default Long selectCount(Long appId, Integer status) {
return selectCount(new LambdaQueryWrapper<PayOrderDO>()
.eq(PayOrderDO::getAppId, appId)
.in(PayOrderDO::getStatus, status));
}
}

View File

@ -0,0 +1,61 @@
package cn.iocoder.yudao.adminserver.modules.pay.dal.mysql.order;
import cn.iocoder.yudao.adminserver.modules.pay.controller.order.vo.refund.vo.PayRefundExportReqVO;
import cn.iocoder.yudao.adminserver.modules.pay.controller.order.vo.refund.vo.PayRefundPageReqVO;
import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.order.PayRefundDO;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.framework.mybatis.core.query.QueryWrapperX;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
/**
* 退款订单 Mapper
*
* @author aquan
*/
@Mapper
public interface PayRefundMapper extends BaseMapperX<PayRefundDO> {
default PageResult<PayRefundDO> selectPage(PayRefundPageReqVO reqVO) {
return selectPage(reqVO, new QueryWrapperX<PayRefundDO>()
.eqIfPresent("merchant_id", reqVO.getMerchantId())
.eqIfPresent("app_id", reqVO.getAppId())
.eqIfPresent("channel_code", reqVO.getChannelCode())
.likeIfPresent("merchant_refund_no", reqVO.getMerchantRefundNo())
.eqIfPresent("type", reqVO.getType())
.eqIfPresent("status", reqVO.getStatus())
.eqIfPresent("notify_status", reqVO.getNotifyStatus())
.betweenIfPresent("create_time", reqVO.getBeginCreateTime(), reqVO.getEndCreateTime())
.orderByDesc("id"));
}
default List<PayRefundDO> selectList(PayRefundExportReqVO reqVO) {
return selectList(new QueryWrapperX<PayRefundDO>()
.eqIfPresent("merchant_id", reqVO.getMerchantId())
.eqIfPresent("app_id", reqVO.getAppId())
.eqIfPresent("channel_code", reqVO.getChannelCode())
.likeIfPresent("merchant_refund_no", reqVO.getMerchantRefundNo())
.eqIfPresent("type", reqVO.getType())
.eqIfPresent("status", reqVO.getStatus())
.eqIfPresent("notify_status", reqVO.getNotifyStatus())
.betweenIfPresent("create_time", reqVO.getBeginCreateTime(), reqVO.getEndCreateTime())
.orderByDesc("id"));
}
/**
* 查询符合的订单数量
*
* @param appId 应用编号
* @param status 订单状态
* @return 条数
*/
default Long selectCount(Long appId, Integer status) {
return selectCount(new LambdaQueryWrapper<PayRefundDO>()
.eq(PayRefundDO::getAppId, appId)
.eq(PayRefundDO::getStatus, status));
}
}

View File

@ -0,0 +1 @@
package cn.iocoder.yudao.adminserver.modules.pay.enums;

View File

@ -0,0 +1,103 @@
package cn.iocoder.yudao.adminserver.modules.pay.service.app;
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.coreservice.modules.pay.dal.dataobject.merchant.PayAppDO;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
import javax.validation.Valid;
import java.util.Collection;
import java.util.List;
import java.util.Map;
/**
* 支付应用信息 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);
/**
* 根据商户 ID 获得支付应用信息列表,
*
* @param merchantId 商户 ID
* @return 支付应用信息列表
*/
List<PayAppDO> getListByMerchantId(String merchantId);
/**
* 获得指定编号的商户 Map
*
* @param appIdList 应用编号集合
* @return 商户 Map
*/
default Map<Long, PayAppDO> getAppMap(Collection<Long> appIdList) {
List<PayAppDO> list = this.getAppList(appIdList);
return CollectionUtils.convertMap(list, PayAppDO::getId);
}
}

View File

@ -0,0 +1,189 @@
package cn.iocoder.yudao.adminserver.modules.pay.service.app.impl;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
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.convert.app.PayAppConvert;
import cn.iocoder.yudao.adminserver.modules.pay.dal.mysql.app.PayAppMapper;
import cn.iocoder.yudao.adminserver.modules.pay.dal.mysql.merchant.PayMerchantMapper;
import cn.iocoder.yudao.adminserver.modules.pay.dal.mysql.order.PayOrderMapper;
import cn.iocoder.yudao.adminserver.modules.pay.dal.mysql.order.PayRefundMapper;
import cn.iocoder.yudao.adminserver.modules.pay.service.app.PayAppService;
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.coreservice.modules.pay.enums.order.PayOrderStatusEnum;
import cn.iocoder.yudao.coreservice.modules.pay.enums.order.PayRefundStatusEnum;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import com.google.common.annotations.VisibleForTesting;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;
import javax.annotation.Resource;
import java.util.*;
import static cn.iocoder.yudao.coreservice.modules.pay.enums.PayErrorCodeCoreConstants.*;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
/**
* 支付应用信息 Service 实现类
*
* @author aquan
*/
@Service
@Validated
public class PayAppServiceImpl implements PayAppService {
@Resource
private PayAppMapper appMapper;
@Resource
private PayMerchantMapper merchantMapper;
@Resource
private PayOrderMapper orderMapper;
@Resource
private PayRefundMapper refundMapper;
@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);
this.validateOrderTransactionExist(id);
// 删除
appMapper.deleteById(id);
}
private void validateAppExists(Long id) {
if (appMapper.selectById(id) == null) {
throw exception(PAY_APP_NOT_FOUND);
}
}
@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) {
Set<Long> merchantIdList = this.getMerchantCondition(pageReqVO.getMerchantName());
if (StrUtil.isNotBlank(pageReqVO.getMerchantName()) && CollectionUtil.isEmpty(merchantIdList)) {
return new PageResult<>();
}
return appMapper.selectPage(pageReqVO, merchantIdList);
}
@Override
public List<PayAppDO> getAppList(PayAppExportReqVO exportReqVO) {
Set<Long> merchantIdList = this.getMerchantCondition(exportReqVO.getMerchantName());
if (StrUtil.isNotBlank(exportReqVO.getMerchantName()) && CollectionUtil.isEmpty(merchantIdList)) {
return new ArrayList<>();
}
return appMapper.selectList(exportReqVO, merchantIdList);
}
/**
* 获取商户编号集合根据商户名称模糊查询得到所有的商户编号集合
*
* @param merchantName 商户名称
* @return 商户编号集合
*/
private Set<Long> getMerchantCondition(String merchantName) {
if (StrUtil.isBlank(merchantName)) {
return Collections.emptySet();
}
return convertSet(merchantMapper.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);
}
/**
* 根据商户 ID 获得支付应用信息列表,
*
* @param merchantId 商户 ID
* @return 支付应用信息列表
*/
@Override
public List<PayAppDO> getListByMerchantId(String merchantId) {
return appMapper.getListByMerchantId(merchantId);
}
/**
* 检查商户是否存在
*
* @param id 商户编号
*/
@VisibleForTesting
public void checkAppExists(Long id) {
if (id == null) {
return;
}
PayAppDO payApp = appMapper.selectById(id);
if (payApp == null) {
throw exception(PAY_APP_NOT_FOUND);
}
}
/**
* 验证是否存在交易中或者退款中等处理中状态的订单
*
* @param appId 应用 ID
*/
private void validateOrderTransactionExist(Long appId) {
// 查看交易订单
if (orderMapper.selectCount(appId, PayOrderStatusEnum.WAITING.getStatus()) > 0) {
throw exception(PAY_APP_EXIST_TRANSACTION_ORDER_CANT_DELETE);
}
// 查看退款订单
if (refundMapper.selectCount(appId, PayRefundStatusEnum.CREATE.getStatus()) > 0) {
throw exception(PAY_APP_EXIST_TRANSACTION_ORDER_CANT_DELETE);
}
}
}

View File

@ -0,0 +1,107 @@
package cn.iocoder.yudao.adminserver.modules.pay.service.channel;
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;
import javax.validation.Valid;
import java.util.Collection;
import java.util.List;
/**
* 支付渠道 Service 接口
*
* @author aquan
*/
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 appIds 应用编号集合
* @return 支付渠道列表
*/
List<PayChannelDO> getChannelListByAppIds(Collection<Long> appIds);
/**
* 根据条件获取通道数量
*
* @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);
}

View File

@ -0,0 +1,161 @@
package cn.iocoder.yudao.adminserver.modules.pay.service.channel.impl;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONUtil;
import cn.iocoder.yudao.adminserver.modules.pay.controller.channel.vo.PayChannelCreateReqVO;
import cn.iocoder.yudao.adminserver.modules.pay.controller.channel.vo.PayChannelExportReqVO;
import cn.iocoder.yudao.adminserver.modules.pay.controller.channel.vo.PayChannelPageReqVO;
import cn.iocoder.yudao.adminserver.modules.pay.controller.channel.vo.PayChannelUpdateReqVO;
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 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.PayClientConfig;
import cn.iocoder.yudao.framework.pay.core.enums.PayChannelEnum;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;
import javax.annotation.Resource;
import javax.validation.Validator;
import java.util.Collection;
import java.util.List;
import static cn.iocoder.yudao.coreservice.modules.pay.enums.PayErrorCodeCoreConstants.CHANNEL_EXIST_SAME_CHANNEL_ERROR;
import static cn.iocoder.yudao.coreservice.modules.pay.enums.PayErrorCodeCoreConstants.CHANNEL_NOT_EXISTS;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
/**
* 支付渠道 Service 实现类
*
* @author aquan
*/
@Service
@Slf4j
@Validated
public class PayChannelServiceImpl implements PayChannelService {
@Resource
private PayChannelMapper channelMapper;
@Resource
private Validator validator;
@Override
public Long createChannel(PayChannelCreateReqVO reqVO) {
// 断言是否有重复的
PayChannelDO channelDO = this.getChannelByConditions(reqVO.getMerchantId(), reqVO.getAppId(), reqVO.getCode());
if (ObjectUtil.isNotNull(channelDO)) {
throw exception(CHANNEL_EXIST_SAME_CHANNEL_ERROR);
}
// 新增渠道
PayChannelDO channel = PayChannelConvert.INSTANCE.convert(reqVO);
settingConfigAndCheckParam(channel, reqVO.getConfig());
channelMapper.insert(channel);
return channel.getId();
}
@Override
public void updateChannel(PayChannelUpdateReqVO updateReqVO) {
// 校验存在
this.validateChannelExists(updateReqVO.getId());
// 更新
PayChannelDO channel = PayChannelConvert.INSTANCE.convert(updateReqVO);
settingConfigAndCheckParam(channel, updateReqVO.getConfig());
channelMapper.updateById(channel);
}
@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 appIds 应用编号集合
* @return 支付渠道列表
*/
@Override
public List<PayChannelDO> getChannelListByAppIds(Collection<Long> appIds) {
return channelMapper.getChannelListByAppIds(appIds);
}
/**
* 根据条件获取通道数量
*
* @param merchantId 商户编号
* @param appid 应用编号
* @param code 通道编码
* @return 数量
*/
@Override
public Integer getChannelCountByConditions(Long merchantId, Long appid, String code) {
return this.channelMapper.selectCount(merchantId, appid, code);
}
/**
* 根据条件获取通道
*
* @param merchantId 商户编号
* @param appid 应用编号
* @param code 通道编码
* @return 数量
*/
@Override
public PayChannelDO getChannelByConditions(Long merchantId, Long appid, String code) {
return this.channelMapper.selectOne(merchantId, appid, code);
}
/**
* 设置渠道配置以及参数校验
*
* @param channel 渠道
* @param configStr 配置
*/
private void settingConfigAndCheckParam(PayChannelDO channel, String configStr) {
// 得到这个渠道是微信的还是支付宝的
Class<? extends PayClientConfig> payClass = PayChannelEnum.getByCode(channel.getCode()).getConfigClass();
if (ObjectUtil.isNull(payClass)) {
throw exception(CHANNEL_NOT_EXISTS);
}
PayClientConfig config = JSONUtil.toBean(configStr, payClass);
// 验证参数
config.validate(validator);
channel.setConfig(config);
}
}

View File

@ -0,0 +1,104 @@
package cn.iocoder.yudao.adminserver.modules.pay.service.merchant;
import cn.iocoder.yudao.adminserver.modules.pay.controller.merchant.vo.PayMerchantCreateReqVO;
import cn.iocoder.yudao.adminserver.modules.pay.controller.merchant.vo.PayMerchantExportReqVO;
import cn.iocoder.yudao.adminserver.modules.pay.controller.merchant.vo.PayMerchantPageReqVO;
import cn.iocoder.yudao.adminserver.modules.pay.controller.merchant.vo.PayMerchantUpdateReqVO;
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;
import javax.validation.Valid;
import java.util.Collection;
import java.util.List;
import java.util.Map;
/**
* 支付商户信息 Service 接口
*
* @author aquan
*/
public interface PayMerchantService {
/**
* 创建支付商户信息
*
* @param createReqVO 创建信息
* @return 编号
*/
Long createMerchant(@Valid PayMerchantCreateReqVO createReqVO);
/**
* 更新支付商户信息
*
* @param updateReqVO 更新信息
*/
void updateMerchant(@Valid PayMerchantUpdateReqVO updateReqVO);
/**
* 删除支付商户信息
*
* @param id 编号
*/
void deleteMerchant(Long id);
/**
* 获得支付商户信息
*
* @param id 编号
* @return 支付商户信息
*/
PayMerchantDO getMerchant(Long id);
/**
* 获得支付商户信息列表
*
* @param ids 编号
* @return 支付商户信息列表
*/
List<PayMerchantDO> getMerchantList(Collection<Long> ids);
/**
* 获得支付商户信息分页
*
* @param pageReqVO 分页查询
* @return 支付商户信息分页
*/
PageResult<PayMerchantDO> getMerchantPage(PayMerchantPageReqVO pageReqVO);
/**
* 获得支付商户信息列表, 用于 Excel 导出
*
* @param exportReqVO 查询条件
* @return 支付商户信息列表
*/
List<PayMerchantDO> getMerchantList(PayMerchantExportReqVO exportReqVO);
/**
* 修改商户状态
*
* @param id 商户编号
* @param status 状态
*/
void updateMerchantStatus(Long id, Integer status);
/**
* 根据商户名称模糊查询商户集合
*
* @param merchantName 商户名称
* @return 商户集合
*/
List<PayMerchantDO> getMerchantListByName(String merchantName);
/**
* 获得指定编号的商户 Map
*
* @param merchantIds 商户编号数组
* @return 商户 Map
*/
default Map<Long, PayMerchantDO> getMerchantMap(Collection<Long> merchantIds) {
List<PayMerchantDO> list = this.getMerchantList(merchantIds);
return CollectionUtils.convertMap(list, PayMerchantDO::getId);
}
}

View File

@ -0,0 +1,150 @@
package cn.iocoder.yudao.adminserver.modules.pay.service.merchant.impl;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.iocoder.yudao.adminserver.modules.pay.controller.merchant.vo.PayMerchantCreateReqVO;
import cn.iocoder.yudao.adminserver.modules.pay.controller.merchant.vo.PayMerchantExportReqVO;
import cn.iocoder.yudao.adminserver.modules.pay.controller.merchant.vo.PayMerchantPageReqVO;
import cn.iocoder.yudao.adminserver.modules.pay.controller.merchant.vo.PayMerchantUpdateReqVO;
import cn.iocoder.yudao.adminserver.modules.pay.convert.merchant.PayMerchantConvert;
import cn.iocoder.yudao.adminserver.modules.pay.dal.mysql.app.PayAppMapper;
import cn.iocoder.yudao.adminserver.modules.pay.dal.mysql.merchant.PayMerchantMapper;
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.google.common.annotations.VisibleForTesting;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;
import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.Collection;
import java.util.List;
import static cn.iocoder.yudao.coreservice.modules.pay.enums.PayErrorCodeCoreConstants.PAY_MERCHANT_EXIST_APP_CANT_DELETE;
import static cn.iocoder.yudao.coreservice.modules.pay.enums.PayErrorCodeCoreConstants.PAY_MERCHANT_NOT_EXISTS;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
/**
* 支付商户信息 Service 实现类
*
* @author aquan
*/
@Service
@Validated
public class PayMerchantServiceImpl implements PayMerchantService {
@Resource
private PayMerchantMapper merchantMapper;
@Resource
private PayAppMapper appMapper;
@Override
public Long createMerchant(PayMerchantCreateReqVO createReqVO) {
// 插入
PayMerchantDO merchant = PayMerchantConvert.INSTANCE.convert(createReqVO);
merchant.setNo(this.generateMerchantNo());
merchantMapper.insert(merchant);
// 返回
return merchant.getId();
}
@Override
public void updateMerchant(PayMerchantUpdateReqVO updateReqVO) {
// 校验存在
this.validateMerchantExists(updateReqVO.getId());
// 更新
PayMerchantDO updateObj = PayMerchantConvert.INSTANCE.convert(updateReqVO);
merchantMapper.updateById(updateObj);
}
@Override
public void deleteMerchant(Long id) {
// 校验
this.validateMerchantExists(id);
this.validateAppExists(id);
// 删除
merchantMapper.deleteById(id);
}
@Override
public PayMerchantDO getMerchant(Long id) {
return merchantMapper.selectById(id);
}
@Override
public List<PayMerchantDO> getMerchantList(Collection<Long> ids) {
return merchantMapper.selectBatchIds(ids);
}
@Override
public PageResult<PayMerchantDO> getMerchantPage(PayMerchantPageReqVO pageReqVO) {
return merchantMapper.selectPage(pageReqVO);
}
@Override
public List<PayMerchantDO> getMerchantList(PayMerchantExportReqVO exportReqVO) {
return merchantMapper.selectList(exportReqVO);
}
@Override
public void updateMerchantStatus(Long id, Integer status) {
// 校验商户存在
this.checkMerchantExists(id);
// 更新状态
PayMerchantDO merchant = new PayMerchantDO();
merchant.setId(id);
merchant.setStatus(status);
merchantMapper.updateById(merchant);
}
@Override
public List<PayMerchantDO> getMerchantListByName(String merchantName) {
return this.merchantMapper.getMerchantListByName(merchantName);
}
@VisibleForTesting
public void checkMerchantExists(Long id) {
if (id == null) {
return;
}
PayMerchantDO merchant = merchantMapper.selectById(id);
if (merchant == null) {
throw exception(PAY_MERCHANT_NOT_EXISTS);
}
}
/**
* 校验商户是否存在
*
* @param id 商户 ID
*/
private void validateMerchantExists(Long id) {
if (ObjectUtil.isNull(merchantMapper.selectById(id))) {
throw exception(PAY_MERCHANT_NOT_EXISTS);
}
}
/**
* 校验商户是否还存在支付应用
*
* @param id 商户ID
*/
private void validateAppExists(Long id) {
if (appMapper.selectCount(id) > 0) {
throw exception(PAY_MERCHANT_EXIST_APP_CANT_DELETE);
}
}
// TODO @芋艿后续增加下合适的算法
/**
* 根据年月日时分秒毫秒生成商户号
*
* @return 商户号
*/
private String generateMerchantNo() {
return "M" + DateUtil.format(LocalDateTime.now(), "yyyyMMddHHmmssSSS");
}
}

View File

@ -0,0 +1,48 @@
package cn.iocoder.yudao.adminserver.modules.pay.service.order;
import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.order.PayOrderExtensionDO;
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
import java.util.Collection;
import java.util.List;
import java.util.Map;
/**
* 支付订单 Service 接口
*
* @author aquan
*/
public interface PayOrderExtensionService {
/**
* 获得支付订单
*
* @param id 编号
* @return 支付订单
*/
PayOrderExtensionDO getOrderExtension(Long id);
/**
* 获得支付订单
* 列表
*
* @param ids 编号
* @return 支付订单
* 列表
*/
List<PayOrderExtensionDO> getOrderExtensionList(Collection<Long> ids);
/**
* 根据订单成功的 扩展订单ID 查询所有的扩展订单转 map 返回
*
* @param successExtensionIdList 订单 ID 集合
* @return 订单扩展 map 集合
*/
default Map<Long, PayOrderExtensionDO> getOrderExtensionMap(Collection<Long> successExtensionIdList) {
List<PayOrderExtensionDO> list = this.getOrderExtensionList(successExtensionIdList);
return CollectionUtils.convertMap(list, PayOrderExtensionDO::getId);
}
}

View File

@ -0,0 +1,67 @@
package cn.iocoder.yudao.adminserver.modules.pay.service.order;
import cn.iocoder.yudao.adminserver.modules.pay.controller.order.vo.order.PayOrderExportReqVO;
import cn.iocoder.yudao.adminserver.modules.pay.controller.order.vo.order.PayOrderPageReqVO;
import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.order.PayOrderDO;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
import java.util.Collection;
import java.util.List;
import java.util.Map;
/**
* 支付订单 Service 接口
*
* @author aquan
*/
public interface PayOrderService {
/**
* 获得支付订单
*
* @param id 编号
* @return 支付订单
*/
PayOrderDO getOrder(Long id);
/**
* 获得支付订单
* 分页
*
* @param pageReqVO 分页查询
* @return 支付订单
* 分页
*/
PageResult<PayOrderDO> getOrderPage(PayOrderPageReqVO pageReqVO);
/**
* 获得支付订单
* 列表, 用于 Excel 导出
*
* @param exportReqVO 查询条件
* @return 支付订单
* 列表
*/
List<PayOrderDO> getOrderList(PayOrderExportReqVO exportReqVO);
/**
* 根据 ID 集合获取只包含商品名称的订单集合
*
* @param idList 订单 ID 集合
* @return 只包含商品名称的订单集合
*/
List<PayOrderDO> getOrderSubjectList(Collection<Long> idList);
/**
* 根据订单 ID 集合获取订单商品名称Map集合
*
* @param idList 订单 ID 集合
* @return 订单商品 map 集合
*/
default Map<Long, PayOrderDO> getOrderSubjectMap(Collection<Long> idList) {
List<PayOrderDO> list = getOrderSubjectList(idList);
return CollectionUtils.convertMap(list, PayOrderDO::getId);
}
}

View File

@ -0,0 +1,41 @@
package cn.iocoder.yudao.adminserver.modules.pay.service.order;
import cn.iocoder.yudao.adminserver.modules.pay.controller.order.vo.refund.vo.PayRefundExportReqVO;
import cn.iocoder.yudao.adminserver.modules.pay.controller.order.vo.refund.vo.PayRefundPageReqVO;
import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.order.PayRefundDO;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import java.util.List;
/**
* 退款订单 Service 接口
*
* @author aquan
*/
public interface PayRefundService {
/**
* 获得退款订单
*
* @param id 编号
* @return 退款订单
*/
PayRefundDO getRefund(Long id);
/**
* 获得退款订单分页
*
* @param pageReqVO 分页查询
* @return 退款订单分页
*/
PageResult<PayRefundDO> getRefundPage(PayRefundPageReqVO pageReqVO);
/**
* 获得退款订单列表, 用于 Excel 导出
*
* @param exportReqVO 查询条件
* @return 退款订单列表
*/
List<PayRefundDO> getRefundList(PayRefundExportReqVO exportReqVO);
}

View File

@ -0,0 +1,35 @@
package cn.iocoder.yudao.adminserver.modules.pay.service.order.impl;
import cn.iocoder.yudao.adminserver.modules.pay.dal.mysql.order.PayOrderExtensionMapper;
import cn.iocoder.yudao.adminserver.modules.pay.service.order.PayOrderExtensionService;
import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.order.PayOrderExtensionDO;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;
import javax.annotation.Resource;
import java.util.Collection;
import java.util.List;
/**
* 支付订单 Service 实现类
*
* @author aquan
*/
@Service
@Validated
public class PayOrderExtensionServiceImpl implements PayOrderExtensionService {
@Resource
private PayOrderExtensionMapper orderExtensionMapper;
@Override
public PayOrderExtensionDO getOrderExtension(Long id) {
return orderExtensionMapper.selectById(id);
}
@Override
public List<PayOrderExtensionDO> getOrderExtensionList(Collection<Long> ids) {
return orderExtensionMapper.selectBatchIds(ids);
}
}

View File

@ -0,0 +1,54 @@
package cn.iocoder.yudao.adminserver.modules.pay.service.order.impl;
import cn.iocoder.yudao.adminserver.modules.pay.controller.order.vo.order.PayOrderExportReqVO;
import cn.iocoder.yudao.adminserver.modules.pay.controller.order.vo.order.PayOrderPageReqVO;
import cn.iocoder.yudao.adminserver.modules.pay.dal.mysql.order.PayOrderMapper;
import cn.iocoder.yudao.adminserver.modules.pay.service.order.PayOrderService;
import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.order.PayOrderDO;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;
import javax.annotation.Resource;
import java.util.Collection;
import java.util.List;
/**
* 支付订单 Service 实现类
*
* @author aquan
*/
@Service
@Validated
public class PayOrderServiceImpl implements PayOrderService {
@Resource
private PayOrderMapper orderMapper;
@Override
public PayOrderDO getOrder(Long id) {
return orderMapper.selectById(id);
}
@Override
public PageResult<PayOrderDO> getOrderPage(PayOrderPageReqVO pageReqVO) {
return orderMapper.selectPage(pageReqVO);
}
@Override
public List<PayOrderDO> getOrderList(PayOrderExportReqVO exportReqVO) {
return orderMapper.selectList(exportReqVO);
}
/**
* 根据 ID 集合获取只包含商品名称的订单集合
*
* @param idList 订单 ID 集合
* @return 只包含商品名称的订单集合
*/
@Override
public List<PayOrderDO> getOrderSubjectList(Collection<Long> idList) {
return orderMapper.findByIdListQueryOrderSubject(idList);
}
}

View File

@ -0,0 +1,42 @@
package cn.iocoder.yudao.adminserver.modules.pay.service.order.impl;
import cn.iocoder.yudao.adminserver.modules.pay.controller.order.vo.refund.vo.PayRefundExportReqVO;
import cn.iocoder.yudao.adminserver.modules.pay.controller.order.vo.refund.vo.PayRefundPageReqVO;
import cn.iocoder.yudao.adminserver.modules.pay.dal.mysql.order.PayRefundMapper;
import cn.iocoder.yudao.adminserver.modules.pay.service.order.PayRefundService;
import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.order.PayRefundDO;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;
import javax.annotation.Resource;
import java.util.List;
/**
* 退款订单 Service 实现类
*
* @author aquan
*/
@Service
@Validated
public class PayRefundServiceImpl implements PayRefundService {
@Resource
private PayRefundMapper refundMapper;
@Override
public PayRefundDO getRefund(Long id) {
return refundMapper.selectById(id);
}
@Override
public PageResult<PayRefundDO> getRefundPage(PayRefundPageReqVO pageReqVO) {
return refundMapper.selectPage(pageReqVO);
}
@Override
public List<PayRefundDO> getRefundList(PayRefundExportReqVO exportReqVO) {
return refundMapper.selectList(exportReqVO);
}
}

View File

@ -22,6 +22,31 @@ public interface SysDictTypeConstants {
String SMS_SEND_STATUS = "sys_sms_send_status"; // 短信发送状态 String SMS_SEND_STATUS = "sys_sms_send_status"; // 短信发送状态
String SMS_RECEIVE_STATUS = "sys_sms_receive_status"; // 短信接收状态 String SMS_RECEIVE_STATUS = "sys_sms_receive_status"; // 短信接收状态
/**
* 支付-订单-订单状态
*/
String PAY_ORDER_STATUS = "pay_order_status";
/**
* 支付-订单-订单回调商户状态
*/
String PAY_ORDER_NOTIFY_STATUS = "pay_order_notify_status";
/**
* 支付-订单-订单退款状态
*/
String PAY_ORDER_REFUND_STATUS = "pay_order_refund_status";
/**
* 支付-退款订单-退款状态
*/
String PAY_REFUND_ORDER_STATUS = "pay_refund_order_status";
/**
* 支付-退款订单-退款类别
*/
String PAY_REFUND_ORDER_TYPE = "pay_refund_order_type";
String BPM_TASK_ASSIGN_RULE_TYPE = "bpm_task_assign_rule_type"; // 任务分配规则类型 String BPM_TASK_ASSIGN_RULE_TYPE = "bpm_task_assign_rule_type"; // 任务分配规则类型
String BPM_TASK_ASSIGN_SCRIPT = "bpm_task_assign_script"; // 任务分配自定义脚本 String BPM_TASK_ASSIGN_SCRIPT = "bpm_task_assign_script"; // 任务分配自定义脚本

View File

@ -183,6 +183,7 @@ yudao:
- ${management.endpoints.web.base-path}/** # 不处理 Actuator 的请求 - ${management.endpoints.web.base-path}/** # 不处理 Actuator 的请求
pay: pay:
pay-notify-url: http://niubi.natapp1.cc/api/pay/order/notify pay-notify-url: http://niubi.natapp1.cc/api/pay/order/notify
pay-return-url: http://niubi.natapp1.cc/api/pay/order/return
refund-notify-url: http://niubi.natapp1.cc/api/pay/refund/notify refund-notify-url: http://niubi.natapp1.cc/api/pay/refund/notify
demo: false # 关闭演示模式 demo: false # 关闭演示模式

View File

@ -31,7 +31,7 @@ import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
class BpmUserTaskActivitiBehaviorTest extends BaseMockitoUnitTest { public class BpmUserTaskActivitiBehaviorTest extends BaseMockitoUnitTest {
@InjectMocks @InjectMocks
private BpmUserTaskActivitiBehavior behavior; private BpmUserTaskActivitiBehavior behavior;

View File

@ -0,0 +1,245 @@
package cn.iocoder.yudao.adminserver.modules.pay.service.app;
import cn.hutool.core.util.RandomUtil;
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.dal.mysql.merchant.PayMerchantMapper;
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.coreservice.modules.pay.dal.dataobject.merchant.PayMerchantDO;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.context.annotation.Import;
import javax.annotation.Resource;
import java.util.Collections;
import java.util.List;
import static cn.iocoder.yudao.coreservice.modules.pay.enums.PayErrorCodeCoreConstants.PAY_APP_NOT_FOUND;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.buildTime;
import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId;
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.test.core.util.RandomUtils.randomLongId;
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;
import static org.junit.jupiter.api.Assertions.*;
/**
* {@link PayAppServiceImpl} 的单元测试类
*
* @author 芋艿
*/
@Import(PayAppServiceImpl.class)
public class PayAppServiceTest extends BaseDbUnitTest {
@Resource
private PayAppServiceImpl appService;
@Resource
private PayAppMapper appMapper;
@MockBean(name = "payMerchantMapper")
private PayMerchantMapper payMerchantMapper;
@Test
public void testCreateApp_success() {
// 准备参数
PayAppCreateReqVO reqVO = randomPojo(PayAppCreateReqVO.class, o ->
o.setStatus((RandomUtil.randomEle(CommonStatusEnum.values()).getStatus())));
// 调用
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, o ->
o.setStatus(CommonStatusEnum.DISABLE.getStatus()));
appMapper.insert(dbApp);// @Sql: 先插入出一条存在的数据
// 准备参数
PayAppUpdateReqVO reqVO = randomPojo(PayAppUpdateReqVO.class, o -> {
o.setStatus(CommonStatusEnum.ENABLE.getStatus());
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, o ->
o.setStatus((RandomUtil.randomEle(CommonStatusEnum.values()).getStatus())));
// 调用, 并断言异常
assertServiceException(() -> appService.updateApp(reqVO), PAY_APP_NOT_FOUND);
}
@Test
public void testDeleteApp_success() {
// mock 数据
PayAppDO dbApp = randomPojo(PayAppDO.class, o ->
o.setStatus((RandomUtil.randomEle(CommonStatusEnum.values()).getStatus())));
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), PAY_APP_NOT_FOUND);
}
@Test
public void testGetAppPage() {
Long merchantId = 1L;
Long mismatchMerchantId = 2L;
// mock 数据
PayAppDO dbApp = randomPojo(PayAppDO.class, o -> { // 等会查询到
o.setName("灿灿姐的杂货铺");
o.setStatus(CommonStatusEnum.ENABLE.getStatus());
o.setRemark("敏敏姐的小卖铺");
o.setPayNotifyUrl("https://www.hc.com");
o.setRefundNotifyUrl("https://www.xm.com");
o.setMerchantId(merchantId);
o.setCreateTime(buildTime(2021,11,20));
});
// mock 数据
PayMerchantDO dbMerchant = randomPojo(PayMerchantDO.class, o -> { // 等会查询到
o.setId(merchantId);
o.setNo("M1008611");
o.setName("灿哥的杂货铺");
o.setShortName("灿灿子");
o.setStatus(CommonStatusEnum.ENABLE.getStatus());
o.setRemark("灿哥的杂货铺");
o.setCreateTime(buildTime(2021,11,3));
});
Mockito.when(payMerchantMapper.getMerchantListByName(dbMerchant.getName()))
.thenReturn(Collections.singletonList(dbMerchant));
appMapper.insert(dbApp);
// 测试 name 不匹配
appMapper.insert(cloneIgnoreId(dbApp, o -> o.setName("敏敏姐的杂货铺")));
// 测试 status 不匹配
appMapper.insert(cloneIgnoreId(dbApp, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus())));
// 测试 remark 不匹配
appMapper.insert(cloneIgnoreId(dbApp, o -> o.setRemark("灿灿姐的小卖部")));
// 测试 payNotifyUrl 不匹配
appMapper.insert(cloneIgnoreId(dbApp, o -> o.setPayNotifyUrl("xm.com")));
// 测试 refundNotifyUrl 不匹配
appMapper.insert(cloneIgnoreId(dbApp, o -> o.setRefundNotifyUrl("hc.com")));
// 测试 merchantId 不匹配
appMapper.insert(cloneIgnoreId(dbApp, o -> o.setMerchantId(mismatchMerchantId)));
// 测试 createTime 不匹配
appMapper.insert(cloneIgnoreId(dbApp, o -> o.setCreateTime(buildTime(2021,12,21))));
// 准备参数
PayAppPageReqVO reqVO = new PayAppPageReqVO();
reqVO.setName("灿灿姐的杂货铺");
reqVO.setStatus(CommonStatusEnum.ENABLE.getStatus());
reqVO.setRemark("敏敏姐的小卖铺");
reqVO.setPayNotifyUrl("https://www.hc.com");
reqVO.setRefundNotifyUrl("https://www.xm.com");
reqVO.setMerchantName(dbMerchant.getName());
reqVO.setBeginCreateTime(buildTime(2021,11,19));
reqVO.setEndCreateTime(buildTime(2021,11,21));
// 调用
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() {
Long merchantId = 1L;
Long mismatchMerchantId = 2L;
// mock 数据
PayAppDO dbApp = randomPojo(PayAppDO.class, o -> { // 等会查询到
o.setName("灿灿姐的杂货铺");
o.setStatus(CommonStatusEnum.ENABLE.getStatus());
o.setRemark("敏敏姐的小卖铺");
o.setPayNotifyUrl("https://www.hc.com");
o.setRefundNotifyUrl("https://www.xm.com");
o.setMerchantId(merchantId);
o.setCreateTime(buildTime(2021,11,20));
});
// mock 数据
PayMerchantDO dbMerchant = randomPojo(PayMerchantDO.class, o -> { // 等会查询到
o.setId(merchantId);
o.setNo("M1008611");
o.setName("灿哥的杂货铺");
o.setShortName("灿灿子");
o.setStatus(CommonStatusEnum.ENABLE.getStatus());
o.setRemark("灿哥的杂货铺");
o.setCreateTime(buildTime(2021,11,3));
});
Mockito.when(payMerchantMapper.getMerchantListByName(dbMerchant.getName()))
.thenReturn(Collections.singletonList(dbMerchant));
appMapper.insert(dbApp);
// 测试 name 不匹配
appMapper.insert(cloneIgnoreId(dbApp, o -> o.setName("敏敏姐的杂货铺")));
// 测试 status 不匹配
appMapper.insert(cloneIgnoreId(dbApp, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus())));
// 测试 remark 不匹配
appMapper.insert(cloneIgnoreId(dbApp, o -> o.setRemark("灿灿姐的小卖部")));
// 测试 payNotifyUrl 不匹配
appMapper.insert(cloneIgnoreId(dbApp, o -> o.setPayNotifyUrl("xm.com")));
// 测试 refundNotifyUrl 不匹配
appMapper.insert(cloneIgnoreId(dbApp, o -> o.setRefundNotifyUrl("hc.com")));
// 测试 merchantId 不匹配
appMapper.insert(cloneIgnoreId(dbApp, o -> o.setMerchantId(mismatchMerchantId)));
// 测试 createTime 不匹配
appMapper.insert(cloneIgnoreId(dbApp, o -> o.setCreateTime(buildTime(2021,12,21))));
// 准备参数
PayAppExportReqVO reqVO = new PayAppExportReqVO();
reqVO.setName("灿灿姐的杂货铺");
reqVO.setStatus(CommonStatusEnum.ENABLE.getStatus());
reqVO.setRemark("敏敏姐的小卖铺");
reqVO.setPayNotifyUrl("https://www.hc.com");
reqVO.setRefundNotifyUrl("https://www.xm.com");
reqVO.setMerchantName(dbMerchant.getName());
reqVO.setBeginCreateTime(buildTime(2021,11,19));
reqVO.setEndCreateTime(buildTime(2021,11,21));
// 调用
List<PayAppDO> list = appService.getAppList(reqVO);
// 断言
assertEquals(1, list.size());
assertPojoEquals(dbApp, list.get(0));
}
}

View File

@ -0,0 +1,20 @@
package cn.iocoder.yudao.adminserver.modules.pay.service.channel;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.validation.Validation;
import javax.validation.Validator;
/**
* 用于初始化 validator Bean 对象
* @author aquan
*/
@Configuration
public class PayChannelConfig {
@Bean
public Validator validator(){
return Validation.buildDefaultValidatorFactory().getValidator();
}
}

View File

@ -0,0 +1,404 @@
package cn.iocoder.yudao.adminserver.modules.pay.service.channel;
import cn.iocoder.yudao.adminserver.BaseDbUnitTest;
import cn.iocoder.yudao.adminserver.modules.pay.controller.channel.vo.PayChannelCreateReqVO;
import cn.iocoder.yudao.adminserver.modules.pay.controller.channel.vo.PayChannelExportReqVO;
import cn.iocoder.yudao.adminserver.modules.pay.controller.channel.vo.PayChannelPageReqVO;
import cn.iocoder.yudao.adminserver.modules.pay.controller.channel.vo.PayChannelUpdateReqVO;
import cn.iocoder.yudao.adminserver.modules.pay.dal.mysql.channel.PayChannelMapper;
import cn.iocoder.yudao.adminserver.modules.pay.service.channel.impl.PayChannelServiceImpl;
import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayChannelDO;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.pay.core.client.impl.alipay.AlipayPayClientConfig;
import cn.iocoder.yudao.framework.pay.core.client.impl.wx.WXPayClientConfig;
import cn.iocoder.yudao.framework.pay.core.enums.PayChannelEnum;
import com.alibaba.fastjson.JSON;
import org.junit.jupiter.api.Test;
import org.springframework.context.annotation.Import;
import javax.annotation.Resource;
import java.util.List;
import static cn.iocoder.yudao.coreservice.modules.pay.enums.PayErrorCodeCoreConstants.CHANNEL_NOT_EXISTS;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.buildTime;
import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId;
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.test.core.util.RandomUtils.randomLongId;
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;
import static org.junit.jupiter.api.Assertions.*;
/**
* {@link PayChannelServiceImpl} 的单元测试类
*
* @author 芋艿
*/
@Import({
PayChannelServiceImpl.class,
PayChannelConfig.class
})
public class PayChannelServiceTest extends BaseDbUnitTest {
@Resource
private PayChannelServiceImpl channelService;
@Resource
private PayChannelMapper channelMapper;
@Test
public void testCreateWechatVersion2Channel_success() {
// 准备参数
WXPayClientConfig v2Config = getV2Config();
PayChannelCreateReqVO reqVO = randomPojo(PayChannelCreateReqVO.class, o -> {
o.setCode(PayChannelEnum.WX_PUB.getCode());
o.setStatus(CommonStatusEnum.ENABLE.getStatus());
o.setConfig(JSON.toJSONString(v2Config));
});
// 调用
Long channelId = channelService.createChannel(reqVO);
// 断言
assertNotNull(channelId);
// 校验记录的属性是否正确
PayChannelDO channel = channelMapper.selectById(channelId);
assertPojoEquals(reqVO, channel, "config");
// 关于config 对象应该拿出来重新对比
assertPojoEquals(v2Config, channel.getConfig());
}
@Test
public void testCreateWechatVersion3Channel_success() {
// 准备参数
WXPayClientConfig v3Config = getV3Config();
PayChannelCreateReqVO reqVO = randomPojo(PayChannelCreateReqVO.class, o -> {
o.setCode(PayChannelEnum.WX_PUB.getCode());
o.setStatus(CommonStatusEnum.ENABLE.getStatus());
o.setConfig(JSON.toJSONString(v3Config));
});
// 调用
Long channelId = channelService.createChannel(reqVO);
// 断言
assertNotNull(channelId);
// 校验记录的属性是否正确
PayChannelDO channel = channelMapper.selectById(channelId);
assertPojoEquals(reqVO, channel, "config");
// 关于config 对象应该拿出来重新对比
assertPojoEquals(v3Config, channel.getConfig());
}
@Test
public void testCreateAliPayPublicKeyChannel_success() {
// 准备参数
AlipayPayClientConfig payClientConfig = getPublicKeyConfig();
PayChannelCreateReqVO reqVO = randomPojo(PayChannelCreateReqVO.class, o -> {
o.setCode(PayChannelEnum.ALIPAY_APP.getCode());
o.setStatus(CommonStatusEnum.ENABLE.getStatus());
o.setConfig(JSON.toJSONString(payClientConfig));
});
// 调用
Long channelId = channelService.createChannel(reqVO);
// 断言
assertNotNull(channelId);
// 校验记录的属性是否正确
PayChannelDO channel = channelMapper.selectById(channelId);
assertPojoEquals(reqVO, channel, "config");
// 关于config 对象应该拿出来重新对比
assertPojoEquals(payClientConfig, channel.getConfig());
}
@Test
public void testCreateAliPayCertificateChannel_success() {
// 准备参数
AlipayPayClientConfig payClientConfig = getCertificateConfig();
PayChannelCreateReqVO reqVO = randomPojo(PayChannelCreateReqVO.class, o -> {
o.setCode(PayChannelEnum.ALIPAY_APP.getCode());
o.setStatus(CommonStatusEnum.ENABLE.getStatus());
o.setConfig(JSON.toJSONString(payClientConfig));
});
// 调用
Long channelId = channelService.createChannel(reqVO);
// 断言
assertNotNull(channelId);
// 校验记录的属性是否正确
PayChannelDO channel = channelMapper.selectById(channelId);
assertPojoEquals(reqVO, channel, "config");
// 关于config 对象应该拿出来重新对比
assertPojoEquals(payClientConfig, channel.getConfig());
}
@Test
public void testUpdateChannel_success() {
// mock 数据
AlipayPayClientConfig payClientConfig = getCertificateConfig();
PayChannelDO dbChannel = randomPojo(PayChannelDO.class, o -> {
o.setCode(PayChannelEnum.ALIPAY_APP.getCode());
o.setStatus(CommonStatusEnum.ENABLE.getStatus());
o.setConfig(payClientConfig);
});
channelMapper.insert(dbChannel);// @Sql: 先插入出一条存在的数据
// 准备参数
AlipayPayClientConfig payClientPublicKeyConfig = getPublicKeyConfig();
PayChannelUpdateReqVO reqVO = randomPojo(PayChannelUpdateReqVO.class, o -> {
o.setCode(dbChannel.getCode());
o.setStatus(dbChannel.getStatus());
o.setConfig(JSON.toJSONString(payClientPublicKeyConfig));
o.setId(dbChannel.getId()); // 设置更新的 ID
});
// 调用
channelService.updateChannel(reqVO);
// 校验是否更新正确
PayChannelDO channel = channelMapper.selectById(reqVO.getId()); // 获取最新的
assertPojoEquals(reqVO, channel, "config");
assertPojoEquals(payClientPublicKeyConfig, channel.getConfig());
}
@Test
public void testUpdateChannel_notExists() {
// 准备参数
AlipayPayClientConfig payClientPublicKeyConfig = getPublicKeyConfig();
PayChannelUpdateReqVO reqVO = randomPojo(PayChannelUpdateReqVO.class, o -> {
o.setCode(PayChannelEnum.ALIPAY_APP.getCode());
o.setStatus(CommonStatusEnum.ENABLE.getStatus());
o.setConfig(JSON.toJSONString(payClientPublicKeyConfig));
});
// 调用, 并断言异常
assertServiceException(() -> channelService.updateChannel(reqVO), CHANNEL_NOT_EXISTS);
}
@Test
public void testDeleteChannel_success() {
// mock 数据
AlipayPayClientConfig payClientConfig = getCertificateConfig();
PayChannelDO dbChannel = randomPojo(PayChannelDO.class, o -> {
o.setCode(PayChannelEnum.ALIPAY_APP.getCode());
o.setStatus(CommonStatusEnum.ENABLE.getStatus());
o.setConfig(payClientConfig);
});
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 数据
AlipayPayClientConfig payClientConfig = getCertificateConfig();
PayChannelDO dbChannel = randomPojo(PayChannelDO.class, o -> { // 等会查询到
o.setCode(PayChannelEnum.ALIPAY_APP.getCode());
o.setStatus(CommonStatusEnum.ENABLE.getStatus());
o.setRemark("灿灿子的支付渠道");
o.setFeeRate(0.03);
o.setMerchantId(1L);
o.setAppId(1L);
o.setConfig(payClientConfig);
o.setCreateTime(buildTime(2021,11,20));
});
channelMapper.insert(dbChannel);
// 执行拷贝的时候会出现异常所以在插入后要重置为null 后续在写入新的
dbChannel.setConfig(null);
// 测试 code 不匹配
channelMapper.insert(cloneIgnoreId(dbChannel, o -> {
o.setConfig(payClientConfig);
o.setCode(PayChannelEnum.WX_PUB.getCode());
}));
// 测试 status 不匹配
channelMapper.insert(cloneIgnoreId(dbChannel, o -> {
o.setConfig(payClientConfig);
o.setStatus(CommonStatusEnum.DISABLE.getStatus());
}));
// 测试 remark 不匹配
channelMapper.insert(cloneIgnoreId(dbChannel, o ->{
o.setConfig(payClientConfig);
o.setRemark("敏敏子的渠道");
}));
// 测试 feeRate 不匹配
channelMapper.insert(cloneIgnoreId(dbChannel, o -> {
o.setConfig(payClientConfig);
o.setFeeRate(1.23);
}));
// 测试 merchantId 不匹配
channelMapper.insert(cloneIgnoreId(dbChannel, o -> {
o.setConfig(payClientConfig);
o.setMerchantId(2L);
}));
// 测试 appId 不匹配
channelMapper.insert(cloneIgnoreId(dbChannel, o -> {
o.setConfig(payClientConfig);
o.setAppId(2L);
}));
// 测试 createTime 不匹配
channelMapper.insert(cloneIgnoreId(dbChannel, o -> {
o.setConfig(payClientConfig);
o.setCreateTime(buildTime(2021, 10, 20));
}));
// 准备参数
PayChannelPageReqVO reqVO = new PayChannelPageReqVO();
reqVO.setCode(PayChannelEnum.ALIPAY_APP.getCode());
reqVO.setStatus(CommonStatusEnum.ENABLE.getStatus());
reqVO.setRemark("灿灿子的支付渠道");
reqVO.setFeeRate(0.03);
reqVO.setMerchantId(1L);
reqVO.setAppId(1L);
reqVO.setConfig(JSON.toJSONString(payClientConfig));
reqVO.setBeginCreateTime(buildTime(2021,11,19));
reqVO.setEndCreateTime(buildTime(2021,11,21));
// 调用
PageResult<PayChannelDO> pageResult = channelService.getChannelPage(reqVO);
// 断言
assertEquals(1, pageResult.getTotal());
assertEquals(1, pageResult.getList().size());
assertPojoEquals(dbChannel, pageResult.getList().get(0), "config");
assertPojoEquals(payClientConfig, pageResult.getList().get(0).getConfig());
}
@Test
public void testGetChannelList() {
// mock 数据
AlipayPayClientConfig payClientConfig = getCertificateConfig();
PayChannelDO dbChannel = randomPojo(PayChannelDO.class, o -> { // 等会查询到
o.setCode(PayChannelEnum.ALIPAY_APP.getCode());
o.setStatus(CommonStatusEnum.ENABLE.getStatus());
o.setRemark("灿灿子的支付渠道");
o.setFeeRate(0.03);
o.setMerchantId(1L);
o.setAppId(1L);
o.setConfig(payClientConfig);
o.setCreateTime(buildTime(2021,11,20));
});
channelMapper.insert(dbChannel);
// 执行拷贝的时候会出现异常所以在插入后要重置为null 后续在写入新的
dbChannel.setConfig(null);
// 测试 code 不匹配
channelMapper.insert(cloneIgnoreId(dbChannel, o -> {
o.setConfig(payClientConfig);
o.setCode(PayChannelEnum.WX_PUB.getCode());
}));
// 测试 status 不匹配
channelMapper.insert(cloneIgnoreId(dbChannel, o -> {
o.setConfig(payClientConfig);
o.setStatus(CommonStatusEnum.DISABLE.getStatus());
}));
// 测试 remark 不匹配
channelMapper.insert(cloneIgnoreId(dbChannel, o ->{
o.setConfig(payClientConfig);
o.setRemark("敏敏子的渠道");
}));
// 测试 feeRate 不匹配
channelMapper.insert(cloneIgnoreId(dbChannel, o -> {
o.setConfig(payClientConfig);
o.setFeeRate(1.23);
}));
// 测试 merchantId 不匹配
channelMapper.insert(cloneIgnoreId(dbChannel, o -> {
o.setConfig(payClientConfig);
o.setMerchantId(2L);
}));
// 测试 appId 不匹配
channelMapper.insert(cloneIgnoreId(dbChannel, o -> {
o.setConfig(payClientConfig);
o.setAppId(2L);
}));
// 测试 createTime 不匹配
channelMapper.insert(cloneIgnoreId(dbChannel, o -> {
o.setConfig(payClientConfig);
o.setCreateTime(buildTime(2021, 10, 20));
}));
// 准备参数
PayChannelExportReqVO reqVO = new PayChannelExportReqVO();
reqVO.setCode(PayChannelEnum.ALIPAY_APP.getCode());
reqVO.setStatus(CommonStatusEnum.ENABLE.getStatus());
reqVO.setRemark("灿灿子的支付渠道");
reqVO.setFeeRate(0.03);
reqVO.setMerchantId(1L);
reqVO.setAppId(1L);
reqVO.setConfig(JSON.toJSONString(payClientConfig));
reqVO.setBeginCreateTime(buildTime(2021,11,19));
reqVO.setEndCreateTime(buildTime(2021,11,21));
// 调用
List<PayChannelDO> list = channelService.getChannelList(reqVO);
// 断言
assertEquals(1, list.size());
assertPojoEquals(dbChannel, list.get(0), "config");
assertPojoEquals(payClientConfig, list.get(0).getConfig());
}
public WXPayClientConfig getV2Config() {
return new WXPayClientConfig()
.setAppId("APP00001")
.setMchId("MCH00001")
.setApiVersion(WXPayClientConfig.API_VERSION_V2)
.setMchKey("dsa1d5s6a1d6sa16d1sa56d15a61das6")
.setApiV3Key("")
.setPrivateCertContent("")
.setPrivateKeyContent("");
}
public WXPayClientConfig getV3Config() {
return new WXPayClientConfig()
.setAppId("APP00001")
.setMchId("MCH00001")
.setApiVersion(WXPayClientConfig.API_VERSION_V3)
.setMchKey("")
.setApiV3Key("sdadasdsadadsa")
.setPrivateKeyContent("dsa445das415d15asd16ad156as")
.setPrivateCertContent("dsadasd45asd4s5a");
}
public AlipayPayClientConfig getPublicKeyConfig() {
return new AlipayPayClientConfig()
.setServerUrl(AlipayPayClientConfig.SERVER_URL_PROD)
.setAppId("APP00001")
.setSignType(AlipayPayClientConfig.SIGN_TYPE_DEFAULT)
.setMode(AlipayPayClientConfig.MODE_PUBLIC_KEY)
.setPrivateKey("13131321312")
.setAlipayPublicKey("13321321321")
.setAppCertContent("")
.setAlipayPublicCertContent("")
.setRootCertContent("");
}
public AlipayPayClientConfig getCertificateConfig() {
return new AlipayPayClientConfig()
.setServerUrl(AlipayPayClientConfig.SERVER_URL_PROD)
.setAppId("APP00001")
.setSignType(AlipayPayClientConfig.SIGN_TYPE_DEFAULT)
.setMode(AlipayPayClientConfig.MODE_CERTIFICATE)
.setPrivateKey("")
.setAlipayPublicKey("")
.setAppCertContent("13321321321sda")
.setAlipayPublicCertContent("13321321321aqeqw")
.setRootCertContent("13321321321dsad");
}
}

View File

@ -0,0 +1,193 @@
package cn.iocoder.yudao.adminserver.modules.pay.service.merchant;
import cn.hutool.core.util.RandomUtil;
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;
import cn.iocoder.yudao.adminserver.modules.pay.controller.merchant.vo.PayMerchantPageReqVO;
import cn.iocoder.yudao.adminserver.modules.pay.controller.merchant.vo.PayMerchantUpdateReqVO;
import cn.iocoder.yudao.adminserver.modules.pay.dal.mysql.merchant.PayMerchantMapper;
import cn.iocoder.yudao.adminserver.modules.pay.service.merchant.impl.PayMerchantServiceImpl;
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.PageResult;
import org.junit.jupiter.api.Test;
import org.springframework.context.annotation.Import;
import javax.annotation.Resource;
import java.util.List;
import static cn.iocoder.yudao.coreservice.modules.pay.enums.PayErrorCodeCoreConstants.PAY_MERCHANT_NOT_EXISTS;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.buildTime;
import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId;
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.test.core.util.RandomUtils.randomLongId;
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;
import static org.junit.jupiter.api.Assertions.*;
/**
* {@link PayMerchantServiceImpl} 的单元测试类
*
* @author aquan
*/
@Import(PayMerchantServiceImpl.class)
public class PayMerchantServiceTest extends BaseDbUnitTest {
@Resource
private PayMerchantServiceImpl merchantService;
@Resource
private PayMerchantMapper merchantMapper;
@Test
public void testCreateMerchant_success() {
// 准备参数
PayMerchantCreateReqVO reqVO = randomPojo(PayMerchantCreateReqVO.class,o ->
o.setStatus(RandomUtil.randomEle(CommonStatusEnum.values()).getStatus()));
// 调用
Long merchantId = merchantService.createMerchant(reqVO);
// 断言
assertNotNull(merchantId);
// 校验记录的属性是否正确
PayMerchantDO merchant = merchantMapper.selectById(merchantId);
assertPojoEquals(reqVO, merchant);
}
@Test
public void testUpdateMerchant_success() {
// mock 数据
PayMerchantDO dbMerchant = randomPojo(PayMerchantDO.class, o ->
o.setStatus(CommonStatusEnum.ENABLE.getStatus()));
merchantMapper.insert(dbMerchant);// @Sql: 先插入出一条存在的数据
// 准备参数
PayMerchantUpdateReqVO reqVO = randomPojo(PayMerchantUpdateReqVO.class, o -> {
o.setId(dbMerchant.getId()); // 设置更新的 ID
o.setStatus(CommonStatusEnum.DISABLE.getStatus());
});
// 调用
merchantService.updateMerchant(reqVO);
// 校验是否更新正确
PayMerchantDO merchant = merchantMapper.selectById(reqVO.getId()); // 获取最新的
assertPojoEquals(reqVO, merchant);
}
@Test
public void testUpdateMerchant_notExists() {
// 准备参数
PayMerchantUpdateReqVO reqVO = randomPojo(PayMerchantUpdateReqVO.class);
// 调用, 并断言异常
assertServiceException(() -> merchantService.updateMerchant(reqVO), PAY_MERCHANT_NOT_EXISTS);
}
@Test
public void testDeleteMerchant_success() {
// mock 数据
PayMerchantDO dbMerchant = randomPojo(PayMerchantDO.class,
o-> o.setStatus(CommonStatusEnum.ENABLE.getStatus()));
merchantMapper.insert(dbMerchant);// @Sql: 先插入出一条存在的数据
// 准备参数
Long id = dbMerchant.getId();
// 调用
merchantService.deleteMerchant(id);
// 校验数据不存在了
assertNull(merchantMapper.selectById(id));
}
@Test
public void testDeleteMerchant_notExists() {
// 准备参数
Long id = randomLongId();
// 调用, 并断言异常
assertServiceException(() -> merchantService.deleteMerchant(id), PAY_MERCHANT_NOT_EXISTS);
}
@Test
public void testGetMerchantPage() {
// mock 数据
PayMerchantDO dbMerchant = randomPojo(PayMerchantDO.class, o -> { // 等会查询到
o.setNo("M1008611");
o.setName("灿哥的杂货铺");
o.setShortName("灿灿子");
o.setStatus(CommonStatusEnum.ENABLE.getStatus());
o.setRemark("灿哥的杂货铺");
o.setCreateTime(buildTime(2021,11,3));
});
merchantMapper.insert(dbMerchant);
// 测试 no 不匹配
merchantMapper.insert(cloneIgnoreId(dbMerchant, o -> o.setNo("M200000")));
// 测试 name 不匹配
merchantMapper.insert(cloneIgnoreId(dbMerchant, o -> o.setName("斌哥的杂货铺")));
// 测试 shortName 不匹配
merchantMapper.insert(cloneIgnoreId(dbMerchant, o -> o.setShortName("斌斌子")));
// 测试 status 不匹配
merchantMapper.insert(cloneIgnoreId(dbMerchant, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus())));
// 测试 remark 不匹配
merchantMapper.insert(cloneIgnoreId(dbMerchant, o -> o.setRemark("斌哥的杂货铺")));
// 测试 createTime 不匹配
merchantMapper.insert(cloneIgnoreId(dbMerchant, o -> o.setCreateTime(buildTime(2022,12,4))));
// 准备参数
PayMerchantPageReqVO reqVO = new PayMerchantPageReqVO();
reqVO.setNo("M1008611");
reqVO.setName("灿哥的杂货铺");
reqVO.setShortName("灿灿子");
reqVO.setStatus(CommonStatusEnum.ENABLE.getStatus());
reqVO.setRemark("灿哥的杂货铺");
reqVO.setBeginCreateTime(buildTime(2021,11,2));
reqVO.setEndCreateTime(buildTime(2021,11,4));
// 调用
PageResult<PayMerchantDO> pageResult = merchantService.getMerchantPage(reqVO);
// 断言
assertEquals(1, pageResult.getTotal());
assertEquals(1, pageResult.getList().size());
assertPojoEquals(dbMerchant, pageResult.getList().get(0));
}
@Test
public void testGetMerchantList() {
// mock 数据
PayMerchantDO dbMerchant = randomPojo(PayMerchantDO.class, o -> { // 等会查询到
o.setNo("M1008611");
o.setName("灿哥的杂货铺");
o.setShortName("灿灿子");
o.setStatus(CommonStatusEnum.ENABLE.getStatus());
o.setRemark("灿哥的杂货铺");
o.setCreateTime(buildTime(2021,11,3));
});
merchantMapper.insert(dbMerchant);
// 测试 no 不匹配
merchantMapper.insert(cloneIgnoreId(dbMerchant, o -> o.setNo("M200000")));
// 测试 name 不匹配
merchantMapper.insert(cloneIgnoreId(dbMerchant, o -> o.setName("斌哥的杂货铺")));
// 测试 shortName 不匹配
merchantMapper.insert(cloneIgnoreId(dbMerchant, o -> o.setShortName("斌斌子")));
// 测试 status 不匹配
merchantMapper.insert(cloneIgnoreId(dbMerchant, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus())));
// 测试 remark 不匹配
merchantMapper.insert(cloneIgnoreId(dbMerchant, o -> o.setRemark("斌哥的杂货铺")));
// 测试 createTime 不匹配
merchantMapper.insert(cloneIgnoreId(dbMerchant, o -> o.setCreateTime(buildTime(2022,12,4))));
// 准备参数
PayMerchantExportReqVO reqVO = new PayMerchantExportReqVO();
reqVO.setNo("M1008611");
reqVO.setName("灿哥的杂货铺");
reqVO.setShortName("灿灿子");
reqVO.setStatus(CommonStatusEnum.ENABLE.getStatus());
reqVO.setRemark("灿哥的杂货铺");
reqVO.setBeginCreateTime(buildTime(2021,11,2));
reqVO.setEndCreateTime(buildTime(2021,11,4));
// 调用
List<PayMerchantDO> list = merchantService.getMerchantList(reqVO);
// 断言
assertEquals(1, list.size());
assertPojoEquals(dbMerchant, list.get(0));
}
}

View File

@ -0,0 +1,196 @@
package cn.iocoder.yudao.adminserver.modules.pay.service.order;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.RandomUtil;
import cn.iocoder.yudao.adminserver.BaseDbUnitTest;
import cn.iocoder.yudao.adminserver.modules.pay.controller.order.vo.order.PayOrderExportReqVO;
import cn.iocoder.yudao.adminserver.modules.pay.controller.order.vo.order.PayOrderPageReqVO;
import cn.iocoder.yudao.adminserver.modules.pay.dal.mysql.order.PayOrderMapper;
import cn.iocoder.yudao.adminserver.modules.pay.service.order.impl.PayOrderServiceImpl;
import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.order.PayOrderDO;
import cn.iocoder.yudao.coreservice.modules.pay.enums.order.PayOrderNotifyStatusEnum;
import cn.iocoder.yudao.coreservice.modules.pay.enums.order.PayOrderStatusEnum;
import cn.iocoder.yudao.coreservice.modules.pay.enums.order.PayRefundTypeEnum;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.date.DateUtils;
import cn.iocoder.yudao.framework.pay.core.enums.PayChannelEnum;
import org.junit.jupiter.api.Test;
import org.springframework.context.annotation.Import;
import javax.annotation.Resource;
import java.util.Date;
import java.util.List;
import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId;
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals;
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;
import static org.junit.jupiter.api.Assertions.assertEquals;
/**
* {@link PayOrderServiceImpl} 的单元测试类
*
* @author 芋艿
*/
@Import(PayOrderServiceImpl.class)
public class PayOrderServiceTest extends BaseDbUnitTest {
@Resource
private PayOrderServiceImpl orderService;
@Resource
private PayOrderMapper orderMapper;
public String generateNo() {
return DateUtil.format(new Date(), "yyyyMMddHHmmss") + RandomUtil.randomInt(100000, 999999);
}
@Test
public void testGetOrderPage() {
String merchantOrderId = generateNo();
String channelOrderId = generateNo();
// mock 数据
PayOrderDO dbOrder = randomPojo(PayOrderDO.class, o -> { // 等会查询到
o.setMerchantId(1L);
o.setAppId(1L);
o.setChannelId(1L);
o.setChannelCode(PayChannelEnum.WX_PUB.getCode());
o.setMerchantOrderId(merchantOrderId);
o.setSubject("灿灿子的炸弹猫");
o.setBody("斌斌子送给灿灿子的炸弹猫");
o.setNotifyUrl("https://hc.com/lbh");
o.setNotifyStatus(PayOrderNotifyStatusEnum.SUCCESS.getStatus());
o.setAmount(10000L);
o.setChannelFeeRate(0.01);
o.setChannelFeeAmount(1L);
o.setStatus(PayOrderStatusEnum.SUCCESS.getStatus());
o.setUserIp("127.0.0.1");
o.setCreateTime(DateUtils.buildTime(2018, 1, 1, 10, 1, 0));
o.setExpireTime(DateUtils.buildTime(2018, 1, 1, 10, 30, 0));
o.setSuccessTime(DateUtils.buildTime(2018, 1, 1, 10, 10, 2));
o.setNotifyTime(DateUtils.buildTime(2018, 1, 1, 10, 10, 15));
o.setSuccessExtensionId(1L);
o.setRefundStatus(PayRefundTypeEnum.NO.getStatus());
o.setRefundTimes(0);
o.setRefundAmount(0L);
o.setChannelUserId("1008611");
o.setChannelOrderNo(channelOrderId);
o.setUpdateTime(DateUtils.buildTime(2018, 1, 1, 10, 10, 15));
});
orderMapper.insert(dbOrder);
// 测试 merchantId 不匹配
orderMapper.insert(cloneIgnoreId(dbOrder, o -> o.setMerchantId(2L)));
// 测试 appId 不匹配
orderMapper.insert(cloneIgnoreId(dbOrder, o -> o.setAppId(2L)));
// 测试 channelId 不匹配
orderMapper.insert(cloneIgnoreId(dbOrder, o -> o.setChannelId(2L)));
// 测试 channelCode 不匹配
orderMapper.insert(cloneIgnoreId(dbOrder, o -> o.setChannelCode(PayChannelEnum.ALIPAY_APP.getCode())));
// 测试 merchantOrderId 不匹配
orderMapper.insert(cloneIgnoreId(dbOrder, o -> o.setMerchantOrderId(generateNo())));
// 测试 notifyStatus 不匹配
orderMapper.insert(cloneIgnoreId(dbOrder, o -> o.setNotifyStatus(PayOrderNotifyStatusEnum.FAILURE.getStatus())));
// 测试 status 不匹配
orderMapper.insert(cloneIgnoreId(dbOrder, o -> o.setStatus(PayOrderStatusEnum.CLOSED.getStatus())));
// 测试 refundStatus 不匹配
orderMapper.insert(cloneIgnoreId(dbOrder, o -> o.setRefundStatus(PayRefundTypeEnum.ALL.getStatus())));
// 测试 createTime 不匹配
orderMapper.insert(cloneIgnoreId(dbOrder, o -> o.setCreateTime(DateUtils.buildTime(2019, 1, 1, 10, 10,
1))));
// 准备参数
PayOrderPageReqVO reqVO = new PayOrderPageReqVO();
reqVO.setMerchantId(1L);
reqVO.setAppId(1L);
reqVO.setChannelId(1L);
reqVO.setChannelCode(PayChannelEnum.WX_PUB.getCode());
reqVO.setMerchantOrderId(merchantOrderId);
reqVO.setNotifyStatus(PayOrderNotifyStatusEnum.SUCCESS.getStatus());
reqVO.setStatus(PayOrderStatusEnum.SUCCESS.getStatus());
reqVO.setRefundStatus(PayRefundTypeEnum.NO.getStatus());
reqVO.setBeginCreateTime(DateUtils.buildTime(2018, 1, 1, 10, 1, 0));
reqVO.setEndCreateTime(DateUtils.buildTime(2018, 1, 1, 10, 1, 0));
// 调用
PageResult<PayOrderDO> pageResult = orderService.getOrderPage(reqVO);
// 断言
assertEquals(1, pageResult.getTotal());
assertEquals(1, pageResult.getList().size());
assertPojoEquals(dbOrder, pageResult.getList().get(0));
// assertEquals(0, dbOrder.getUpdateTime().compareTo(pageResult.getList().get(0).getUpdateTime()));
}
@Test
public void testGetOrderList() {
// mock 数据
String merchantOrderId = generateNo();
String channelOrderId = generateNo();
PayOrderDO dbOrder = randomPojo(PayOrderDO.class, o -> { // 等会查询到
o.setMerchantId(1L);
o.setAppId(1L);
o.setChannelId(1L);
o.setChannelCode(PayChannelEnum.WX_PUB.getCode());
o.setMerchantOrderId(merchantOrderId);
o.setSubject("灿灿子的炸弹猫");
o.setBody("斌斌子送给灿灿子的炸弹猫");
o.setNotifyUrl("https://hc.com/lbh");
o.setNotifyStatus(PayOrderNotifyStatusEnum.SUCCESS.getStatus());
o.setAmount(10000L);
o.setChannelFeeRate(0.01);
o.setChannelFeeAmount(1L);
o.setStatus(PayOrderStatusEnum.SUCCESS.getStatus());
o.setUserIp("127.0.0.1");
o.setCreateTime(DateUtils.buildTime(2018, 1, 1, 10, 1, 0));
o.setExpireTime(DateUtils.buildTime(2018, 1, 1, 10, 30, 0));
o.setSuccessTime(DateUtils.buildTime(2018, 1, 1, 10, 10, 2));
o.setNotifyTime(DateUtils.buildTime(2018, 1, 1, 10, 10, 15));
o.setSuccessExtensionId(1L);
o.setRefundStatus(PayRefundTypeEnum.NO.getStatus());
o.setRefundTimes(0);
o.setRefundAmount(0L);
o.setChannelUserId("1008611");
o.setChannelOrderNo(channelOrderId);
o.setUpdateTime(DateUtils.buildTime(2018, 1, 1, 10, 10, 15));
});
orderMapper.insert(dbOrder);
// 测试 merchantId 不匹配
orderMapper.insert(cloneIgnoreId(dbOrder, o -> o.setMerchantId(2L)));
// 测试 appId 不匹配
orderMapper.insert(cloneIgnoreId(dbOrder, o -> o.setAppId(2L)));
// 测试 channelId 不匹配
orderMapper.insert(cloneIgnoreId(dbOrder, o -> o.setChannelId(2L)));
// 测试 channelCode 不匹配
orderMapper.insert(cloneIgnoreId(dbOrder, o -> o.setChannelCode(PayChannelEnum.ALIPAY_APP.getCode())));
// 测试 merchantOrderId 不匹配
orderMapper.insert(cloneIgnoreId(dbOrder, o -> o.setMerchantOrderId(generateNo())));
// 测试 notifyStatus 不匹配
orderMapper.insert(cloneIgnoreId(dbOrder, o -> o.setNotifyStatus(PayOrderNotifyStatusEnum.FAILURE.getStatus())));
// 测试 status 不匹配
orderMapper.insert(cloneIgnoreId(dbOrder, o -> o.setStatus(PayOrderStatusEnum.CLOSED.getStatus())));
// 测试 refundStatus 不匹配
orderMapper.insert(cloneIgnoreId(dbOrder, o -> o.setRefundStatus(PayRefundTypeEnum.ALL.getStatus())));
// 测试 createTime 不匹配
orderMapper.insert(cloneIgnoreId(dbOrder, o -> o.setCreateTime(DateUtils.buildTime(2019, 1, 1, 10, 10,
1))));
// 准备参数
PayOrderExportReqVO reqVO = new PayOrderExportReqVO();
reqVO.setMerchantId(1L);
reqVO.setAppId(1L);
reqVO.setChannelId(1L);
reqVO.setChannelCode(PayChannelEnum.WX_PUB.getCode());
reqVO.setMerchantOrderId(merchantOrderId);
reqVO.setNotifyStatus(PayOrderNotifyStatusEnum.SUCCESS.getStatus());
reqVO.setStatus(PayOrderStatusEnum.SUCCESS.getStatus());
reqVO.setRefundStatus(PayRefundTypeEnum.NO.getStatus());
reqVO.setBeginCreateTime(DateUtils.buildTime(2018, 1, 1, 10, 1, 0));
reqVO.setEndCreateTime(DateUtils.buildTime(2018, 1, 1, 10, 1, 0));
// 调用
List<PayOrderDO> list = orderService.getOrderList(reqVO);
// 断言
assertEquals(1, list.size());
assertPojoEquals(dbOrder, list.get(0));
}
}

View File

@ -0,0 +1,183 @@
package cn.iocoder.yudao.adminserver.modules.pay.service.refund;
import cn.iocoder.yudao.adminserver.BaseDbUnitTest;
import cn.iocoder.yudao.adminserver.modules.pay.controller.order.vo.refund.vo.PayRefundExportReqVO;
import cn.iocoder.yudao.adminserver.modules.pay.controller.order.vo.refund.vo.PayRefundPageReqVO;
import cn.iocoder.yudao.adminserver.modules.pay.dal.mysql.order.PayRefundMapper;
import cn.iocoder.yudao.adminserver.modules.pay.service.order.impl.PayRefundServiceImpl;
import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.order.PayRefundDO;
import cn.iocoder.yudao.coreservice.modules.pay.enums.order.PayOrderNotifyStatusEnum;
import cn.iocoder.yudao.coreservice.modules.pay.enums.order.PayRefundStatusEnum;
import cn.iocoder.yudao.coreservice.modules.pay.enums.order.PayRefundTypeEnum;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.date.DateUtils;
import cn.iocoder.yudao.framework.pay.core.enums.PayChannelEnum;
import org.junit.jupiter.api.Test;
import org.springframework.context.annotation.Import;
import javax.annotation.Resource;
import java.util.List;
import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId;
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals;
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;
import static org.junit.jupiter.api.Assertions.assertEquals;
/**
* {@link PayRefundServiceImpl} 的单元测试类
*
* @author aquan
*/
@Import(PayRefundServiceImpl.class)
public class PayRefundServiceTest extends BaseDbUnitTest {
@Resource
private PayRefundServiceImpl refundService;
@Resource
private PayRefundMapper refundMapper;
@Test
public void testGetRefundPage() {
// mock 数据
PayRefundDO dbRefund = randomPojo(PayRefundDO.class, o -> { // 等会查询到
o.setMerchantId(1L);
o.setAppId(1L);
o.setChannelId(1L);
o.setChannelCode(PayChannelEnum.WX_PUB.getCode());
o.setOrderId(1L);
o.setTradeNo("OT0000001");
o.setMerchantOrderId("MOT0000001");
o.setMerchantRefundNo("MRF0000001");
o.setNotifyUrl("https://www.cancanzi.com");
o.setNotifyStatus(PayOrderNotifyStatusEnum.SUCCESS.getStatus());
o.setStatus(PayRefundStatusEnum.SUCCESS.getStatus());
o.setType(PayRefundTypeEnum.SOME.getStatus());
o.setPayAmount(100L);
o.setRefundAmount(500L);
o.setReason("就是想退款了,你有意见吗");
o.setUserIp("127.0.0.1");
o.setChannelOrderNo("CH0000001");
o.setChannelRefundNo("CHR0000001");
o.setChannelErrorCode("");
o.setChannelErrorMsg("");
o.setChannelExtras("");
o.setExpireTime(DateUtils.buildTime(2021, 1, 1, 10, 10, 30));
o.setSuccessTime(DateUtils.buildTime(2021, 1, 1, 10, 10, 15));
o.setNotifyTime(DateUtils.buildTime(2021, 1, 1, 10, 10, 20));
o.setCreateTime(DateUtils.buildTime(2021, 1, 1, 10, 10, 10));
o.setUpdateTime(DateUtils.buildTime(2021, 1, 1, 10, 10, 35));
});
refundMapper.insert(dbRefund);
// 测试 merchantId 不匹配
refundMapper.insert(cloneIgnoreId(dbRefund, o -> o.setMerchantId(2L)));
// 测试 appId 不匹配
refundMapper.insert(cloneIgnoreId(dbRefund, o -> o.setAppId(2L)));
// 测试 channelCode 不匹配
refundMapper.insert(cloneIgnoreId(dbRefund, o -> o.setChannelCode(PayChannelEnum.ALIPAY_APP.getCode())));
// 测试 merchantRefundNo 不匹配
refundMapper.insert(cloneIgnoreId(dbRefund, o -> o.setMerchantRefundNo("MRF1111112")));
// 测试 notifyStatus 不匹配
refundMapper.insert(
cloneIgnoreId(dbRefund, o -> o.setNotifyStatus(PayOrderNotifyStatusEnum.FAILURE.getStatus())));
// 测试 status 不匹配
refundMapper.insert(cloneIgnoreId(dbRefund, o -> o.setStatus(PayRefundStatusEnum.CLOSE.getStatus())));
// 测试 type 不匹配
refundMapper.insert(cloneIgnoreId(dbRefund, o -> o.setType(PayRefundTypeEnum.ALL.getStatus())));
// 测试 createTime 不匹配
refundMapper.insert(cloneIgnoreId(dbRefund, o ->
o.setCreateTime(DateUtils.buildTime(2022, 1, 1, 10, 10, 10))));
// 准备参数
PayRefundPageReqVO reqVO = new PayRefundPageReqVO();
reqVO.setMerchantId(1L);
reqVO.setAppId(1L);
reqVO.setChannelCode(PayChannelEnum.WX_PUB.getCode());
reqVO.setMerchantRefundNo("MRF0000001");
reqVO.setNotifyStatus(PayOrderNotifyStatusEnum.SUCCESS.getStatus());
reqVO.setStatus(PayRefundStatusEnum.SUCCESS.getStatus());
reqVO.setType(PayRefundTypeEnum.SOME.getStatus());
reqVO.setBeginCreateTime(DateUtils.buildTime(2021, 1, 1, 10, 10, 10));
reqVO.setEndCreateTime(DateUtils.buildTime(2021, 1, 1, 10, 10, 12));
// 调用
PageResult<PayRefundDO> pageResult = refundService.getRefundPage(reqVO);
// 断言
assertEquals(1, pageResult.getTotal());
assertEquals(1, pageResult.getList().size());
assertPojoEquals(dbRefund, pageResult.getList().get(0));
}
@Test
public void testGetRefundList() {
// mock 数据
PayRefundDO dbRefund = randomPojo(PayRefundDO.class, o -> { // 等会查询到
o.setMerchantId(1L);
o.setAppId(1L);
o.setChannelId(1L);
o.setChannelCode(PayChannelEnum.WX_PUB.getCode());
o.setOrderId(1L);
o.setTradeNo("OT0000001");
o.setMerchantOrderId("MOT0000001");
o.setMerchantRefundNo("MRF0000001");
o.setNotifyUrl("https://www.cancanzi.com");
o.setNotifyStatus(PayOrderNotifyStatusEnum.SUCCESS.getStatus());
o.setStatus(PayRefundStatusEnum.SUCCESS.getStatus());
o.setType(PayRefundTypeEnum.SOME.getStatus());
o.setPayAmount(100L);
o.setRefundAmount(500L);
o.setReason("就是想退款了,你有意见吗");
o.setUserIp("127.0.0.1");
o.setChannelOrderNo("CH0000001");
o.setChannelRefundNo("CHR0000001");
o.setChannelErrorCode("");
o.setChannelErrorMsg("");
o.setChannelExtras("");
o.setExpireTime(DateUtils.buildTime(2021, 1, 1, 10, 10, 30));
o.setSuccessTime(DateUtils.buildTime(2021, 1, 1, 10, 10, 15));
o.setNotifyTime(DateUtils.buildTime(2021, 1, 1, 10, 10, 20));
o.setCreateTime(DateUtils.buildTime(2021, 1, 1, 10, 10, 10));
o.setUpdateTime(DateUtils.buildTime(2021, 1, 1, 10, 10, 35));
});
refundMapper.insert(dbRefund);
// 测试 merchantId 不匹配
refundMapper.insert(cloneIgnoreId(dbRefund, o -> o.setMerchantId(2L)));
// 测试 appId 不匹配
refundMapper.insert(cloneIgnoreId(dbRefund, o -> o.setAppId(2L)));
// 测试 channelCode 不匹配
refundMapper.insert(cloneIgnoreId(dbRefund, o -> o.setChannelCode(PayChannelEnum.ALIPAY_APP.getCode())));
// 测试 merchantRefundNo 不匹配
refundMapper.insert(cloneIgnoreId(dbRefund, o -> o.setMerchantRefundNo("MRF1111112")));
// 测试 notifyStatus 不匹配
refundMapper.insert(
cloneIgnoreId(dbRefund, o -> o.setNotifyStatus(PayOrderNotifyStatusEnum.FAILURE.getStatus())));
// 测试 status 不匹配
refundMapper.insert(cloneIgnoreId(dbRefund, o -> o.setStatus(PayRefundStatusEnum.CLOSE.getStatus())));
// 测试 type 不匹配
refundMapper.insert(cloneIgnoreId(dbRefund, o -> o.setType(PayRefundTypeEnum.ALL.getStatus())));
// 测试 createTime 不匹配
refundMapper.insert(cloneIgnoreId(dbRefund, o ->
o.setCreateTime(DateUtils.buildTime(2022, 1, 1, 10, 10, 10))));
// 准备参数
PayRefundExportReqVO reqVO = new PayRefundExportReqVO();
reqVO.setMerchantId(1L);
reqVO.setAppId(1L);
reqVO.setChannelCode(PayChannelEnum.WX_PUB.getCode());
reqVO.setMerchantRefundNo("MRF0000001");
reqVO.setNotifyStatus(PayOrderNotifyStatusEnum.SUCCESS.getStatus());
reqVO.setStatus(PayRefundStatusEnum.SUCCESS.getStatus());
reqVO.setType(PayRefundTypeEnum.SOME.getStatus());
reqVO.setBeginCreateTime(DateUtils.buildTime(2021, 1, 1, 10, 10, 10));
reqVO.setEndCreateTime(DateUtils.buildTime(2021, 1, 1, 10, 10, 12));
// 调用
List<PayRefundDO> list = refundService.getRefundList(reqVO);
// 断言
assertEquals(1, list.size());
assertPojoEquals(dbRefund, list.get(0));
}
}

View File

@ -26,5 +26,12 @@ DELETE FROM "sys_error_code";
DELETE FROM "sys_social_user"; DELETE FROM "sys_social_user";
DELETE FROM "sys_tenant"; DELETE FROM "sys_tenant";
-- pay 开头的 DB
DELETE FROM pay_merchant;
DELETE FROM pay_app;
DELETE FROM pay_channel;
DELETE FROM pay_order;
DELETE FROM pay_refund;
-- bpm 开头的 DB -- bpm 开头的 DB
DELETE FROM "bpm_form"; DELETE FROM "bpm_form";

View File

@ -474,6 +474,131 @@ CREATE TABLE IF NOT EXISTS "sys_tenant" (
) COMMENT '租户'; ) COMMENT '租户';
CREATE TABLE IF NOT EXISTS "pay_merchant"
(
"id" number NOT NULL GENERATED BY DEFAULT AS IDENTITY,
"no" varchar(32) NOT NULL,
"name" varchar(64) NOT NULL,
"short_name" varchar(64) NOT NULL,
"status" tinyint NOT NULL,
"remark" varchar(255) DEFAULT NULL,
"creator" varchar(64) DEFAULT '',
"create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updater" varchar(64) DEFAULT '',
"update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
"deleted" bit(1) NOT NULL DEFAULT FALSE,
PRIMARY KEY ("id")
) COMMENT '支付商户信息';
CREATE TABLE IF NOT EXISTS "pay_app"
(
"id" number NOT NULL GENERATED BY DEFAULT AS IDENTITY,
"name" varchar(64) NOT NULL,
"status" tinyint NOT NULL,
"remark" varchar(255) DEFAULT NULL,
`pay_notify_url` varchar(1024) NOT NULL,
`refund_notify_url` varchar(1024) NOT NULL,
`merchant_id` bigint(20) NOT NULL,
"creator" varchar(64) DEFAULT '',
"create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updater" varchar(64) DEFAULT '',
"update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
"deleted" bit(1) NOT NULL DEFAULT FALSE,
PRIMARY KEY ("id")
) COMMENT = '支付应用信息';
CREATE TABLE IF NOT EXISTS "pay_channel"
(
"id" number NOT NULL GENERATED BY DEFAULT AS IDENTITY,
"code" varchar(32) NOT NULL,
"status" tinyint(4) NOT NULL,
"remark" varchar(255) DEFAULT NULL,
"fee_rate" double NOT NULL DEFAULT 0,
"merchant_id" bigint(20) NOT NULL,
"app_id" bigint(20) NOT NULL,
"config" varchar(10240) NOT NULL,
"creator" varchar(64) NULL DEFAULT '',
"create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updater" varchar(64) NULL DEFAULT '',
"update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
"deleted" bit(1) NOT NULL DEFAULT FALSE,
PRIMARY KEY ("id")
) COMMENT = '支付渠道';
CREATE TABLE IF NOT EXISTS `pay_order`
(
"id" number NOT NULL GENERATED BY DEFAULT AS IDENTITY,
`merchant_id` bigint(20) NOT NULL,
`app_id` bigint(20) NOT NULL,
`channel_id` bigint(20) DEFAULT NULL,
`channel_code` varchar(32) DEFAULT NULL,
`merchant_order_id` varchar(64) NOT NULL,
`subject` varchar(32) NOT NULL,
`body` varchar(128) NOT NULL,
`notify_url` varchar(1024) NOT NULL,
`notify_status` tinyint(4) NOT NULL,
`amount` bigint(20) NOT NULL,
`channel_fee_rate` double DEFAULT 0,
`channel_fee_amount` bigint(20) DEFAULT 0,
`status` tinyint(4) NOT NULL,
`user_ip` varchar(50) NOT NULL,
`expire_time` datetime(0) NOT NULL DEFAULT CURRENT_TIMESTAMP,
`success_time` datetime(0) DEFAULT CURRENT_TIMESTAMP,
`notify_time` datetime(0) DEFAULT CURRENT_TIMESTAMP,
`success_extension_id` bigint(20) DEFAULT NULL COMMENT '支付成功的订单拓展单编号',
`refund_status` tinyint(4) NOT NULL,
`refund_times` tinyint(4) NOT NULL,
`refund_amount` bigint(20) NOT NULL,
`channel_user_id` varchar(255) DEFAULT NULL,
`channel_order_no` varchar(64) DEFAULT NULL,
`creator` varchar(64) DEFAULT '',
`create_time` datetime(0) NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updater` varchar(64) DEFAULT '',
`update_time` datetime(0) NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`deleted` bit(1) NOT NULL DEFAULT FALSE,
PRIMARY KEY ("id")
) COMMENT = '支付订单';
CREATE TABLE IF NOT EXISTS `pay_refund`
(
"id" number NOT NULL GENERATED BY DEFAULT AS IDENTITY,
`req_no` varchar(64) NOT NULL,
`merchant_id` bigint(20) NOT NULL,
`app_id` bigint(20) NOT NULL,
`channel_id` bigint(20) NOT NULL,
`channel_code` varchar(32) NOT NULL,
`order_id` bigint(20) NOT NULL,
`trade_no` varchar(64) NOT NULL,
`merchant_order_id` varchar(64) NOT NULL,
`merchant_refund_no` varchar(64) NOT NULL,
`notify_url` varchar(1024) NOT NULL,
`notify_status` tinyint(4) NOT NULL,
`status` tinyint(4) NOT NULL,
`type` tinyint(4) NOT NULL,
`pay_amount` bigint(20) NOT NULL,
`refund_amount` bigint(20) NOT NULL,
`reason` varchar(256) NOT NULL,
`user_ip` varchar(50) NULL DEFAULT NULL,
`channel_order_no` varchar(64) NOT NULL,
`channel_refund_no` varchar(64) NULL DEFAULT NULL,
`channel_error_code` varchar(128) NULL DEFAULT NULL,
`channel_error_msg` varchar(256) NULL DEFAULT NULL,
`channel_extras` varchar(1024) NULL DEFAULT NULL,
`expire_time` datetime(0) NULL DEFAULT NULL,
`success_time` datetime(0) NULL DEFAULT NULL,
`notify_time` datetime(0) NULL DEFAULT NULL,
`creator` varchar(64) NULL DEFAULT '',
`create_time` datetime(0) NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updater` varchar(64) NULL DEFAULT '',
`update_time` datetime(0) NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`deleted` bit(1) NOT NULL DEFAULT FALSE,
PRIMARY KEY ("id")
) COMMENT = '退款订单';
CREATE TABLE IF NOT EXISTS "bpm_form" ( CREATE TABLE IF NOT EXISTS "bpm_form" (
"id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY,
"name" varchar(63) NOT NULL, "name" varchar(63) NOT NULL,

View File

@ -42,7 +42,7 @@
"clipboard": "2.0.6", "clipboard": "2.0.6",
"core-js": "3.19.1", "core-js": "3.19.1",
"echarts": "4.9.0", "echarts": "4.9.0",
"element-ui": "2.15.0", "element-ui": "^2.15.6",
"file-saver": "2.0.4", "file-saver": "2.0.4",
"fuse.js": "6.4.3", "fuse.js": "6.4.3",
"highlight.js": "9.18.5", "highlight.js": "9.18.5",

View File

@ -0,0 +1,78 @@
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'
})
}
// 根据商ID称搜索应用列表
export function getAppListByMerchantId(merchantId) {
return request({
url: '/pay/app/list-merchant-id',
params:{
merchantId:merchantId
},
method: 'get'
})
}

View File

@ -0,0 +1,71 @@
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 getChannel(merchantId,appId,code) {
return request({
url: '/pay/channel/get-channel',
params:{
merchantId:merchantId,
appId:appId,
code:code
},
method: 'get'
})
}

View File

@ -0,0 +1,77 @@
import request from '@/utils/request'
// 创建支付商户信息
export function createMerchant(data) {
return request({
url: '/pay/merchant/create',
method: 'post',
data: data
})
}
// 更新支付商户信息
export function updateMerchant(data) {
return request({
url: '/pay/merchant/update',
method: 'put',
data: data
})
}
// 支付商户状态修改
export function changeMerchantStatus(id, status) {
const data = {
id,
status
}
return request({
url: '/pay/merchant/update-status',
method: 'put',
data: data
})
}
// 删除支付商户信息
export function deleteMerchant(id) {
return request({
url: '/pay/merchant/delete?id=' + id,
method: 'delete'
})
}
// 获得支付商户信息
export function getMerchant(id) {
return request({
url: '/pay/merchant/get?id=' + id,
method: 'get'
})
}
// 根据商户名称搜索商户列表
export function getMerchantListByName(name) {
return request({
url: '/pay/merchant/list-by-name',
params:{
name:name
},
method: 'get'
})
}
// 获得支付商户信息分页
export function getMerchantPage(query) {
return request({
url: '/pay/merchant/page',
method: 'get',
params: query
})
}
// 导出支付商户信息 Excel
export function exportMerchantExcel(query) {
return request({
url: '/pay/merchant/export-excel',
method: 'get',
params: query,
responseType: 'blob'
})
}

View File

@ -0,0 +1,54 @@
import request from '@/utils/request'
// 创建支付订单
export function createOrder(data) {
return request({
url: '/pay/order/create',
method: 'post',
data: data
})
}
// 更新支付订单
export function updateOrder(data) {
return request({
url: '/pay/order/update',
method: 'put',
data: data
})
}
// 删除支付订单
export function deleteOrder(id) {
return request({
url: '/pay/order/delete?id=' + id,
method: 'delete'
})
}
// 获得支付订单
export function getOrder(id) {
return request({
url: '/pay/order/get?id=' + id,
method: 'get'
})
}
// 获得支付订单分页
export function getOrderPage(query) {
return request({
url: '/pay/order/page',
method: 'get',
params: query
})
}
// 导出支付订单 Excel
export function exportOrderExcel(query) {
return request({
url: '/pay/order/export-excel',
method: 'get',
params: query,
responseType: 'blob'
})
}

View File

@ -0,0 +1,54 @@
import request from '@/utils/request'
// 创建退款订单
export function createRefund(data) {
return request({
url: '/pay/refund/create',
method: 'post',
data: data
})
}
// 更新退款订单
export function updateRefund(data) {
return request({
url: '/pay/refund/update',
method: 'put',
data: data
})
}
// 删除退款订单
export function deleteRefund(id) {
return request({
url: '/pay/refund/delete?id=' + id,
method: 'delete'
})
}
// 获得退款订单
export function getRefund(id) {
return request({
url: '/pay/refund/get?id=' + id,
method: 'get'
})
}
// 获得退款订单分页
export function getRefundPage(query) {
return request({
url: '/pay/refund/page',
method: 'get',
params: query
})
}
// 导出退款订单 Excel
export function exportRefundExcel(query) {
return request({
url: '/pay/refund/export-excel',
method: 'get',
params: query,
responseType: 'blob'
})
}

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 8.4 KiB

View File

@ -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="1635907181185" class="icon" viewBox="0 0 1184 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3259" xmlns:xlink="http://www.w3.org/1999/xlink" width="231.25" 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="M1005.633722 616.006249c-5.311502-0.479955-10.431022-1.27988-15.518545-2.143799-1.087898-0.127988-2.271787-0.287973-3.359685-0.479955-2.399775-0.415961-4.671562-1.055901-7.007343-1.631847-9.951067-2.143799-19.678155-4.831547-28.989282-8.351217l0 133.235509-731.355435 0 0-133.235509c-9.375121 3.551667-19.006218 6.303409-29.053276 8.511202-2.335781 0.415961-4.607568 1.055901-6.943349 1.535856-1.087898 0.191982-2.175796 0.31997-3.359685 0.511952-5.11952 0.767928-10.271037 1.535856-15.518545 2.079805-5.983439 0.479955-12.094866 0.863919-18.270287 0.863919-12.47883 0-24.701684-1.215886-36.540574-3.327688l0 357.310502c0 29.309252 24.573696 53.11502 54.874855 53.11502l841.073149 0c30.237165 0 54.810861-23.773771 54.810861-53.11502l0-357.342499c-11.83889 2.143799-24.061744 3.327688-36.540574 3.327688-6.07943 0-12.254851-0.351967-18.23829-0.863919z" p-id="3260"></path><path d="M182.83086 109.749711l804.500578 0c30.301159 0 54.874855-24.573696 54.874855-54.874855s-24.573696-54.874855-54.874855-54.874855l-804.500578 0c-30.301159 0-54.874855 24.573696-54.874855 54.874855 0.031997 30.301159 24.605693 54.874855 54.874855 54.874855z" p-id="3261"></path><path d="M1067.387932 164.592569l-964.549573 0-102.838359 256.007999c0 80.728432 65.529857 146.258288 146.258288 146.258288s146.258288-65.529857 146.258288-146.258288c0 80.728432 65.529857 146.258288 146.258288 146.258288s146.258288-65.529857 146.258288-146.258288c0 80.728432 65.529857 146.258288 146.258288 146.258288s146.258288-65.529857 146.258288-146.258288c0 80.728432 65.529857 146.258288 146.258288 146.258288s146.258288-65.529857 146.258288-146.258288l-102.806362-256.007999z" p-id="3262"></path></svg>

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

@ -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="1638429990011" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1233" 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="M459.954135 607.201246l233.733369 0c14.352893 0 25.941835-11.088546 25.941835-24.798802 0-13.623275-11.587919-24.710798-25.941835-24.710798l-233.733369 0c-14.352893 0-25.986861 11.087523-25.986861 24.710798C433.967274 596.1127 445.601242 607.201246 459.954135 607.201246zM382.017088 824.38673l287.564391-0.272199 0-0.633427c9.370415-1.494027 16.660448-9.233292 16.660448-19.053961 0-9.773598-7.290033-17.693987-16.660448-19.23304l0-0.633427L369.500007 784.560676c-27.275203 0-51.949162-38.46915-51.949162-65.214281l0-415.585113c0.181125-1.041726 0.633427-1.992377 0.633427-3.123131 0-10.997472-8.985652-20.00359-20.032242-20.00359-11.023054 0-20.010753 9.007141-20.010753 20.00359l0 418.708244C278.1423 773.383102 327.080895 824.38673 382.017088 824.38673zM693.687504 89.925079c-3.235694 0-311.669392-0.814552-311.669392-0.814552-51.2922 0-96.314603 39.10053-102.108562 88.294952-0.181125 1.085728-0.656963 2.036379-0.656963 3.168156 0 0.091074 0.023536 0.135076 0.023536 0.181125 0 0.046049-0.023536 0.090051-0.023536 0.181125l0.067538 0c0.181125 10.860349 9.031701 19.685341 19.942191 19.685341 10.933003 0 19.762089-8.824993 19.964704-19.685341l0.226151 0c6.043646-24.664749 27.027563-52.04433 50.04786-52.04433l284.755416 0c-0.406253 60.461023 0 118.435413 0 118.435413 0 54.531987 35.991726 91.642187 91.358731 91.642187 0 0 40.133046 0 90.428545 0l0 380.37724c0.338714 44.261063-33.70259 65.757656-62.180178 65.214281l0 0.272199c-10.229992 0.723477-18.425651 9.188266-18.425651 19.594267 0 10.454096 8.195659 18.736736 18.425651 19.417235l0 0.271176c0.248663 0 0.49835-0.091074 0.74599-0.091074 0.184195 0 0.340761 0.091074 0.522909 0.091074 0.971118 0 1.811252-0.407276 2.739391-0.544399 52.287877-3.755534 97.580432-52.314483 97.580432-104.22476L875.452267 299.777551 693.687504 89.925079zM745.615177 299.777551c-27.684526 0-51.927673-51.411927-51.927673-78.69941 0 0 0-27.606755 0-78.656431l0-0.045025 129.839137 157.400866L745.615177 299.777551zM459.954135 483.471246l233.733369 0c14.352893 0 25.941835-11.041474 25.941835-24.708751 0-13.667278-11.587919-24.7548-25.941835-24.7548l-233.733369 0c-14.352893 0-25.986861 11.087523-25.986861 24.7548C433.967274 472.430796 445.601242 483.471246 459.954135 483.471246zM716.709847 841.356216c-8.53335 0-15.32708 6.246261-17.113773 14.256702l-0.475837-0.045025c-21.73093 44.171012-40.426735 34.032094-62.294788 34.032094L252.179998 889.599987c-27.27725 0-64.466244-38.512129-64.466244-65.213257L187.713754 322.314847c0-24.800849 29.857005-58.606793 55.954383-63.403029l0-0.543376c10.571776-0.543376 19.082614-9.142218 19.082614-19.86749 0-10.68127-8.510838-19.279089-19.082614-19.777439l0-0.226151c-0.181125 0.044002-0.339738 0.091074-0.51984 0.091074-0.158612 0-0.272199-0.091074-0.429789-0.091074-1.245364 0-2.353604 0.497327-3.553942 0.724501-50.703799 5.203512-90.860381 52.134381-90.860381 103.092983l0 502.07086c0 54.034661 48.938596 105.038288 103.875812 105.038288l389.558343 0c47.104831 0 78.254272-17.198707 90.542132-61.683874 1.358951-2.533706 2.330068-5.250584 2.330068-8.326643C734.611565 849.546759 726.601124 841.356216 716.709847 841.356216z" p-id="1234"></path></svg>

After

Width:  |  Height:  |  Size: 3.7 KiB

View File

@ -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="1635906769564" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2420" 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="M512 0C230.4 0 0 230.4 0 512s230.4 512 512 512 512-230.4 512-512S793.6 0 512 0z m0 921.6c-225.28 0-409.6-184.32-409.6-409.6s184.32-409.6 409.6-409.6 409.6 184.32 409.6 409.6-184.32 409.6-409.6 409.6z" p-id="2421"></path><path d="M665.6 537.6h-102.4v-51.2h102.4c25.6 0 51.2-25.6 51.2-51.2s-25.6-51.2-51.2-51.2h-30.72l20.48-20.48c20.48-20.48 20.48-51.2 0-71.68s-51.2-20.48-71.68 0L512 363.52 440.32 296.96c-20.48-20.48-51.2-20.48-71.68 0s-20.48 51.2 0 71.68l20.48 20.48H358.4c-25.6 0-51.2 25.6-51.2 51.2s25.6 51.2 51.2 51.2h102.4v51.2H358.4c-25.6 0-51.2 25.6-51.2 51.2s25.6 51.2 51.2 51.2h102.4v56.32c0 25.6 20.48 46.08 46.08 46.08h10.24c25.6 0 46.08-20.48 46.08-46.08v-56.32h102.4c25.6 0 51.2-25.6 51.2-51.2s-25.6-56.32-51.2-56.32z" p-id="2422"></path></svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

@ -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

View File

@ -90,3 +90,138 @@ export const SysUserSocialTypeEnum = {
img: "https://cdn.jsdelivr.net/gh/justauth/justauth-oauth-logo@1.11/wechat_enterprise.png", 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": "支付宝扫码支付"
},
}
/**
* 支付类型枚举
*/
export const PayType = {
WECHAT: "WECHAT",
ALIPAY: "ALIPAY"
}
/**
* 支付订单状态枚举
*/
export const payOrderStatusEnum = {
WAITING: {
status: 0,
name: '未支付'
},
SUCCESS: {
status: 10,
name: '已支付'
},
CLOSED: {
status: 20,
name: '未支付'
}
}
/**
* 支付订单回调状态枚举
*/
export const payOrderNotifyStatusEnum = {
NO: {
status: 0,
name: '未通知'
},
SUCCESS: {
status: 10,
name: '通知成功'
},
FAILURE: {
status: 20,
name: '通知失败'
}
}
/**
* 支付订单退款状态枚举
*/
export const payOrderRefundStatusEnum = {
NO: {
status: 0,
name: '未退款'
},
SOME: {
status: 10,
name: '部分退款'
},
ALL: {
status: 20,
name: '全部退款'
}
}
/**
* 支付退款订单状态枚举
*/
export const payRefundStatusEnum = {
CREATE:{
status:0,
name: '退款订单生成'
},
SUCCESS:{
status:1,
name: '退款成功'
},
FAILURE:{
status:2,
name: '退款失败'
},
PROCESSING_NOTIFY:{
status:3,
name: '退款中,渠道通知结果'
},
PROCESSING_QUERY:{
status:4,
name: '退款中,系统查询结果'
},
UNKNOWN_RETRY:{
status:5,
name: '状态未知,请重试'
},
UNKNOWN_QUERY:{
status:6,
name: '状态未知,系统查询结果'
},
CLOSE:{
status:99,
name: '退款关闭'
}
}

View File

@ -41,8 +41,29 @@ export const DICT_TYPE = {
BPM_PROCESS_INSTANCE_STATUS: 'bpm_process_instance_status', BPM_PROCESS_INSTANCE_STATUS: 'bpm_process_instance_status',
BPM_PROCESS_INSTANCE_RESULT: 'bpm_process_instance_result', BPM_PROCESS_INSTANCE_RESULT: 'bpm_process_instance_result',
BPM_TASK_ASSIGN_SCRIPT: 'bpm_task_assign_script', BPM_TASK_ASSIGN_SCRIPT: 'bpm_task_assign_script',
OA_LEAVE_STATUS: 'flow_status', // todo 芋艿:可以删除 BPM_OA_LEAVE_TYPE: 'bpm_oa_leave_type',
BPM_OA_LEAVE_TYPE: 'bpm_oa_leave_type'
// pay
// 微信渠道版本
PAY_CHANNEL_WECHAT_VERSION:'pay_channel_wechat_version',
// 支付渠道支付宝算法类型
PAY_CHANNEL_ALIPAY_SIGN_TYPE:'pay_channel_alipay_sign_type',
// 支付宝公钥类型
PAY_CHANNEL_ALIPAY_MODE:'pay_channel_alipay_mode',
// 支付宝网关地址
PAY_CHANNEL_ALIPAY_SERVER_TYPE:'pay_channel_alipay_server_type',
// 支付渠道编码类型
PAY_CHANNEL_CODE_TYPE: 'pay_channel_code_type',
// 商户支付订单回调状态
PAY_ORDER_NOTIFY_STATUS: 'pay_order_notify_status',
// 商户支付订单状态
PAY_ORDER_STATUS: 'pay_order_status',
// 商户支付订单退款状态
PAY_ORDER_REFUND_STATUS: 'pay_order_refund_status',
// 退款订单状态
PAY_REFUND_ORDER_STATUS: 'pay_refund_order_status',
// 退款订单类别
PAY_REFUND_ORDER_TYPE: 'pay_refund_order_type',
} }
/** /**

View File

@ -37,7 +37,9 @@ export function parseTime(time, pattern) {
const time_str = format.replace(/{(y|m|d|h|i|s|a)+}/g, (result, key) => { const time_str = format.replace(/{(y|m|d|h|i|s|a)+}/g, (result, key) => {
let value = formatObj[key] let value = formatObj[key]
// Note: getDay() returns 0 on Sunday // Note: getDay() returns 0 on Sunday
if (key === 'a') { return ['日', '一', '二', '三', '四', '五', '六'][value] } if (key === 'a') {
return ['日', '一', '二', '三', '四', '五', '六'][value]
}
if (result.length > 0 && value < 10) { if (result.length > 0 && value < 10) {
value = '0' + value value = '0' + value
} }
@ -98,7 +100,7 @@ export function addBeginAndEndTime(params, dateRange, propName) {
return params; return params;
} }
// 回显数据字典 // 回显数据字典 原若依所保留,请使用 dict.js 中的新方法
export function selectDictLabel(datas, value) { export function selectDictLabel(datas, value) {
var actions = []; var actions = [];
Object.keys(datas).some((key) => { Object.keys(datas).some((key) => {
@ -188,7 +190,9 @@ export function handleTree(data, id, parentId, children, rootId) {
id = id || 'id' id = id || 'id'
parentId = parentId || 'parentId' parentId = parentId || 'parentId'
children = children || 'children' children = children || 'children'
rootId = rootId || Math.min.apply(Math, data.map(item => { return item[parentId] })) || 0 rootId = rootId || Math.min.apply(Math, data.map(item => {
return item[parentId]
})) || 0
//对源数据深度克隆 //对源数据深度克隆
const cloneData = JSON.parse(JSON.stringify(data)) const cloneData = JSON.parse(JSON.stringify(data))
//循环所有项 //循环所有项
@ -203,3 +207,22 @@ export function handleTree(data, id, parentId, children, rootId) {
}); });
return treeData !== '' ? treeData : data; return treeData !== '' ? treeData : data;
} }
/**
* 获取当前时间
* @param timeStr 时分秒 字符串 格式为 xx:xx:xx
*/
export function getNowDateTime(timeStr) {
let now = new Date();
let year = now.getFullYear(); //得到年份
let month = (now.getMonth() + 1).toString().padStart(2, "0"); //得到月份
let day = now.getDate().toString().padStart(2, "0"); //得到日期
if (timeStr != null) {
return `${year}-${month}-${day} ${timeStr}`;
}
let hours = now.getHours().toString().padStart(2, "0") // 得到小时;
let minutes = now.getMinutes().toString().padStart(2, "0") // 得到分钟;
let seconds = now.getSeconds().toString().padStart(2, "0") // 得到秒;
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
}

View File

@ -0,0 +1,358 @@
<template>
<div>
<el-dialog :visible.sync="transferParam.aliPayOpen" :title="title" @closed="close" append-to-body width="800px">
<el-form ref="aliPayForm" :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="aliPayConfig.appId">
<el-input v-model="form.aliPayConfig.appId" placeholder="请输入开放平台APPID" clearable :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="网关地址" prop="aliPayConfig.serverUrl">
<el-radio-group v-model="form.aliPayConfig.serverUrl" size="medium">
<el-radio v-for="dict in aliPayServerDatas" :key="dict.value" :label="dict.value">
{{ dict.label }}
</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label-width="180px" label="算法类型" prop="aliPayConfig.signType">
<el-radio-group v-model="form.aliPayConfig.signType" size="medium">
<el-radio v-for="dict in aliPaySignTypeDatas" :key="dict.value" :label="dict.value">
{{ dict.label }}
</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label-width="180px" label="公钥类型" prop="aliPayConfig.mode">
<el-radio-group v-model="form.aliPayConfig.mode" size="medium">
<el-radio v-for="dict in aliPayModeDatas" :key="parseInt(dict.value)" :label="parseInt(dict.value)">
{{ dict.label }}
</el-radio>
</el-radio-group>
</el-form-item>
<div v-if="form.aliPayConfig.mode === 1">
<el-form-item label-width="180px" label="商户私钥" prop="aliPayConfig.privateKey">
<el-input type="textarea" :autosize="{minRows: 8, maxRows: 8}" v-model="form.aliPayConfig.privateKey"
placeholder="请输入商户私钥" clearable :style="{width: '100%'}">
</el-input>
</el-form-item>
<el-form-item label-width="180px" label="支付宝公钥字符串" prop="aliPayConfig.alipayPublicKey">
<el-input
type="textarea"
:autosize="{minRows: 8, maxRows: 8}"
v-model="form.aliPayConfig.alipayPublicKey"
placeholder="请输入支付宝公钥字符串" clearable
:style="{width: '100%'}">
</el-input>
</el-form-item>
</div>
<div v-if="form.aliPayConfig.mode === 2">
<el-form-item label-width="180px" label="商户公钥应用证书" prop="aliPayConfig.appCertContent">
<el-input v-model="form.aliPayConfig.appCertContent" type="textarea"
placeholder="请上传商户公钥应用证书"
readonly :autosize="{minRows: 8, maxRows: 8}" :style="{width: '100%'}"></el-input>
</el-form-item>
<el-form-item label-width="180px" label="">
<el-upload
action=""
ref="privateKeyContentFile"
:limit="1"
:accept="fileAccept"
:http-request="appCertUpload"
:before-upload="fileBeforeUpload">
<el-button size="small" type="primary" icon="el-icon-upload">点击上传</el-button>
</el-upload>
</el-form-item>
<el-form-item label-width="180px" label="支付宝公钥证书" prop="aliPayConfig.alipayPublicCertContent">
<el-input v-model="form.aliPayConfig.alipayPublicCertContent" type="textarea"
placeholder="请上传支付宝公钥证书"
readonly :autosize="{minRows: 8, maxRows: 8}" :style="{width: '100%'}"></el-input>
</el-form-item>
<el-form-item label-width="180px" label="">
<el-upload
ref="privateCertContentFile"
action=""
:limit="1"
:accept="fileAccept"
:before-upload="fileBeforeUpload"
:http-request="alipayPublicCertUpload">
<el-button size="small" type="primary" icon="el-icon-upload">点击上传</el-button>
</el-upload>
</el-form-item>
<el-form-item label-width="180px" label="根证书" prop="aliPayConfig.rootCertContent">
<el-input
v-model="form.aliPayConfig.rootCertContent"
type="textarea"
placeholder="请上传根证书"
readonly :autosize="{minRows: 8, maxRows: 8}"
:style="{width: '100%'}">
</el-input>
</el-form-item>
<el-form-item label-width="180px" label="">
<el-upload
ref="privateCertContentFile"
:limit="1"
:accept="fileAccept"
action=""
:before-upload="fileBeforeUpload"
:http-request="rootCertUpload">
<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 {createChannel, getChannel, updateChannel} from "@/api/pay/channel";
const defaultForm = {
code: '',
status: null,
remark: '',
feeRate: null,
appId: '',
merchantId: null,
aliPayConfig: {
appId: '',
serverUrl: null,
signType: '',
mode: null,
privateKey: '',
alipayPublicKey: '',
appCertContent: '',
alipayPublicCertContent: '',
rootCertContent: ''
}
};
export default {
name: "aliPayChannelForm",
components: {},
props: {
//
transferParam: {
//
"loading": false,
//
"edit": false,
//
"aliPayOpen": false,
// ID
"appId": null,
//
"payCode": null,
//
"payMerchant": {
//
"id": null,
//
"name": null
},
}
},
data() {
return {
title:'',
form: JSON.parse(JSON.stringify(defaultForm)),
rules: {
feeRate: [{
required: true,
message: '请输入渠道费率',
trigger: 'blur'
}],
'aliPayConfig.appId': [{
required: true,
message: '请输入开放平台上创建的应用的 ID',
trigger: 'blur'
}],
status: [{
required: true,
message: '渠道状态不能为空',
trigger: 'blur'
}],
'aliPayConfig.serverUrl': [{
required: true,
message: '请传入网关地址',
trigger: 'blur'
}],
'aliPayConfig.signType': [{
required: true,
message: '请传入签名算法类型',
trigger: 'blur'
}],
'aliPayConfig.mode': [{
required: true,
message: '公钥类型不能为空',
trigger: 'blur'
}],
'aliPayConfig.privateKey': [{
required: true,
message: '请输入商户私钥',
trigger: 'blur'
}],
'aliPayConfig.alipayPublicKey': [{
required: true,
message: '请输入支付宝公钥字符串',
trigger: 'blur'
}],
'aliPayConfig.appCertContent': [{
required: true,
message: '请上传商户公钥应用证书',
trigger: 'blur'
}],
'aliPayConfig.alipayPublicCertContent': [{
required: true,
message: '请上传支付宝公钥证书',
trigger: 'blur'
}],
'aliPayConfig.rootCertContent': [{
required: true,
message: '请上传指定根证书',
trigger: 'blur'
}],
},
fileAccept: ".crt",
//
statusDictDatas: getDictDatas(DICT_TYPE.SYS_COMMON_STATUS),
//
aliPaySignTypeDatas: getDictDatas(DICT_TYPE.PAY_CHANNEL_ALIPAY_SIGN_TYPE),
//
aliPayModeDatas: getDictDatas(DICT_TYPE.PAY_CHANNEL_ALIPAY_MODE),
//
aliPayServerDatas: getDictDatas(DICT_TYPE.PAY_CHANNEL_ALIPAY_SERVER_TYPE),
}
},
watch: {
transferParam: {
deep: true, //
handler(newVal) {
if (newVal.aliPayOpen) {
this.form.code = newVal.payCode;
this.form.appId = newVal.appId;
this.form.merchantId = newVal.payMerchant.id;
//
if (newVal.edit === true && newVal.loading) {
this.title = "编辑支付渠道";
this.init();
} else {
this.title = "创建支付渠道";
}
}
}
}
},
methods: {
init() {
getChannel(this.transferParam.payMerchant.id, this.transferParam.appId, this.transferParam.payCode)
.then(response => {
this.form.id = response.data.id;
this.form.feeRate = response.data.feeRate;
this.form.status = response.data.status;
this.form.remark = response.data.remark;
let config = JSON.parse(response.data.config);
this.form.aliPayConfig.appId = config.appId;
this.form.aliPayConfig.serverUrl = config.serverUrl;
this.form.aliPayConfig.signType = config.signType;
this.form.aliPayConfig.mode = config.mode;
this.form.aliPayConfig.privateKey = config.privateKey;
this.form.aliPayConfig.alipayPublicKey = config.alipayPublicKey;
this.form.aliPayConfig.appCertContent = config.appCertContent;
this.form.aliPayConfig.alipayPublicCertContent = config.alipayPublicCertContent;
this.form.aliPayConfig.rootCertContent = config.rootCertContent;
this.transferParam.loading = false;
})
},
close() {
this.transferParam.aliPayOpen = false;
this.form = JSON.parse(JSON.stringify(defaultForm));
},
handleConfirm() {
this.$refs['aliPayForm'].validate(valid => {
if (!valid) {
return
}
let data = this.form;
data.config = JSON.stringify(this.form.aliPayConfig);
if (this.transferParam.edit) {
updateChannel(data).then(response => {
if (response.code === 0) {
this.msgSuccess("修改成功");
this.close();
}
})
} else {
createChannel(data).then(response => {
if (response.code === 0) {
this.msgSuccess("新增成功");
this.$parent.refreshTable();
this.close();
}
});
}
});
},
fileBeforeUpload(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
},
appCertUpload(event) {
const readFile = new FileReader()
readFile.onload = (e) => {
this.form.aliPayConfig.appCertContent = e.target.result
}
readFile.readAsText(event.file);
},
alipayPublicCertUpload(event) {
const readFile = new FileReader()
readFile.onload = (e) => {
this.form.aliPayConfig.alipayPublicCertContent = e.target.result
}
readFile.readAsText(event.file);
},
rootCertUpload(event) {
const readFile = new FileReader()
readFile.onload = (e) => {
this.form.aliPayConfig.rootCertContent = e.target.result
}
readFile.readAsText(event.file);
},
}
}
</script>
<style scoped>
</style>

View File

@ -0,0 +1,299 @@
<template>
<div>
<el-dialog :visible.sync="transferParam.wechatOpen" :title="title" @close="close" append-to-body width="800px">
<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%'}" type="textarea" :autosize="{minRows: 8, maxRows: 8}"></el-input>
</el-form-item>
<div v-if="form.weChatConfig.apiVersion === 'v3'">
<el-form-item label-width="180px" label="API V3秘钥" prop="weChatConfig.apiV3Key">
<el-input v-model="form.weChatConfig.apiV3Key" placeholder="请输入API V3秘钥" clearable
:style="{width: '100%'}" type="textarea" :autosize="{minRows: 8, maxRows: 8}"></el-input>
</el-form-item>
<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=""
:before-upload="pemFileBeforeUpload"
:http-request="privateKeyUpload"
>
<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=""
:before-upload="pemFileBeforeUpload"
:http-request="privateCertUpload"
>
<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 {createChannel, getChannel, updateChannel} from "@/api/pay/channel";
const defaultForm = {
code: '',
status: null,
remark: '',
feeRate: null,
appId: '',
merchantId: null,
weChatConfig: {
appId: '',
mchId: '',
apiVersion: '',
mchKey: '',
privateKeyContent: '',
privateCertContent: '',
apiV3Key:'',
}
}
export default {
name: "wechatChannelForm",
components: {},
props: {
//
transferParam: {
//
"loading": false,
//
"edit": false,
//
"wechatOpen": false,
// ID
"appId": null,
//
"payCode": null,
//
"payMerchant": {
//
"id": null,
//
"name": null
},
}
},
data() {
return {
title:'',
form: JSON.parse(JSON.stringify(defaultForm)),
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: 'blur'
}],
'weChatConfig.apiVersion': [{
required: true,
message: 'API版本不能为空',
trigger: 'blur'
}],
'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'
}],
'weChatConfig.apiV3Key': [{
required: true,
message: '请上传apiV3秘钥值',
trigger: 'blur'
}],
},
// header
header: {
"Authorization": null
},
fileAccept: ".pem",
//
statusDictDatas: getDictDatas(DICT_TYPE.SYS_COMMON_STATUS),
versionDictDatas: getDictDatas(DICT_TYPE.PAY_CHANNEL_WECHAT_VERSION),
}
},
watch: {
transferParam: {
deep: true, //
handler(newVal) {
if (newVal.wechatOpen) {
this.form.code = newVal.payCode;
this.form.appId = newVal.appId;
this.form.merchantId = newVal.payMerchant.id;
//
if (newVal.edit && newVal.loading) {
this.title = "编辑支付渠道";
this.init();
} else {
this.title = "创建支付渠道";
}
}
}
}
},
methods: {
init() {
getChannel(this.transferParam.payMerchant.id, this.transferParam.appId, this.transferParam.payCode)
.then(response => {
this.form.id = response.data.id;
this.form.feeRate = response.data.feeRate;
this.form.appId = response.data.appId;
this.form.status = response.data.status;
this.form.remark = response.data.remark;
let config = JSON.parse(response.data.config);
this.form.weChatConfig.appId = config.appId;
this.form.weChatConfig.apiVersion = config.apiVersion;
this.form.weChatConfig.mchId = config.mchId;
this.form.weChatConfig.mchKey = config.mchKey;
this.form.weChatConfig.privateKeyContent = config.privateKeyContent;
this.form.weChatConfig.privateCertContent = config.privateCertContent;
this.form.weChatConfig.apiV3Key = config.apiV3Key;
this.transferParam.loading = false;
})
},
close() {
this.transferParam.wechatOpen = false;
this.form = JSON.parse(JSON.stringify(defaultForm));
},
handleConfirm() {
this.$refs['wechatJsApiForm'].validate(valid => {
if (!valid) {
return
}
let data = this.form;
data.config = JSON.stringify(this.form.weChatConfig);
if (this.transferParam.edit) {
updateChannel(data).then(response => {
if (response.code === 0) {
this.msgSuccess("修改成功");
this.close();
}
})
} else {
createChannel(data).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
},
privateKeyUpload(event) {
const readFile = new FileReader()
readFile.onload = (e) => {
this.form.weChatConfig.privateKeyContent = e.target.result
}
readFile.readAsText(event.file);
},
privateCertUpload(event) {
const readFile = new FileReader()
readFile.onload = (e) => {
this.form.weChatConfig.privateCertContent = e.target.result
}
readFile.readAsText(event.file);
}
}
}
</script>
<style scoped>
</style>

View File

@ -0,0 +1,492 @@
<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="judgeChannelExist(scope.row.channelCodes,payChannelEnum.ALIPAY_APP.code)"
@click="handleUpdateChannel(scope.row,payChannelEnum.ALIPAY_APP.code,payType.ALIPAY)">
</el-button>
<el-button v-else
type="danger" icon="el-icon-close" circle
@click="handleCreateChannel(scope.row,payChannelEnum.ALIPAY_APP.code,payType.ALIPAY)">
</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="judgeChannelExist(scope.row.channelCodes,payChannelEnum.ALIPAY_PC.code)"
@click="handleUpdateChannel(scope.row,payChannelEnum.ALIPAY_APP.code,payType.ALIPAY)">
</el-button>
<el-button v-else
type="danger" icon="el-icon-close" circle
@click="handleCreateChannel(scope.row,payChannelEnum.ALIPAY_PC.code,payType.ALIPAY)">
</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="judgeChannelExist(scope.row.channelCodes,payChannelEnum.ALIPAY_WAP.code)"
@click="handleUpdateChannel(scope.row,payChannelEnum.ALIPAY_APP.code,payType.ALIPAY)">
</el-button>
<el-button v-else
type="danger" icon="el-icon-close" circle
@click="handleCreateChannel(scope.row,payChannelEnum.ALIPAY_WAP.code,payType.ALIPAY)">
</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="judgeChannelExist(scope.row.channelCodes,payChannelEnum.ALIPAY_QR.code)"
@click="handleUpdateChannel(scope.row,payChannelEnum.ALIPAY_APP.code,payType.ALIPAY)">
</el-button>
<el-button v-else
type="danger" icon="el-icon-close" circle
@click="handleCreateChannel(scope.row,payChannelEnum.ALIPAY_QR.code,payType.ALIPAY)">
</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
v-if="judgeChannelExist(scope.row.channelCodes,payChannelEnum.WX_LITE.code)"
@click="handleUpdateChannel(scope.row,payChannelEnum.ALIPAY_APP.code,payType.WECHAT)">
</el-button>
<el-button v-else
type="danger" icon="el-icon-close" circle
@click="handleCreateChannel(scope.row,payChannelEnum.WX_LITE.code,payType.WECHAT)">
</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
v-if="judgeChannelExist(scope.row.channelCodes,payChannelEnum.WX_PUB.code)"
@click="handleUpdateChannel(scope.row,payChannelEnum.ALIPAY_APP.code,payType.WECHAT)">
</el-button>
<el-button v-else
type="danger" icon="el-icon-close" circle
@click="handleCreateChannel(scope.row,payChannelEnum.WX_PUB.code,payType.WECHAT)">
</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
v-if="judgeChannelExist(scope.row.channelCodes,payChannelEnum.WX_APP.code)"
@click="handleUpdateChannel(scope.row,payChannelEnum.ALIPAY_APP.code,payType.WECHAT)">
</el-button>
<el-button v-else
type="danger" icon="el-icon-close" circle
@click="handleCreateChannel(scope.row,payChannelEnum.WX_APP.code,payType.WECHAT)">
</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-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-channel-form :transferParam="channelParam"></wechat-channel-form>
<ali-pay-channel-form :transferParam="channelParam"></ali-pay-channel-form>
</div>
</template>
<script>
import {createApp, updateApp, changeAppStatus, deleteApp, getApp, getAppPage, exportAppExcel} from "@/api/pay/app";
import {DICT_TYPE, getDictDatas} from "@/utils/dict";
import {PayType, PayChannelEnum, SysCommonStatusEnum} from "@/utils/constants";
import {getMerchantListByName} from "@/api/pay/merchant";
import wechatChannelForm from "@/views/pay/app/components/wechatChannelForm";
import aliPayChannelForm from "@/views/pay/app/components/aliPayChannelForm";
export default {
name: "App",
components: {
"wechatChannelForm": wechatChannelForm,
"aliPayChannelForm": aliPayChannelForm
},
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.SYS_COMMON_STATUS),
sysCommonStatusEnum: SysCommonStatusEnum,
//
payChannelEnum: PayChannelEnum,
//
payType: PayType,
//
merchantList: [],
//
payOpen: false,
//
channelParam: {
//
"edit": false,
//
"wechatOpen": false,
//
"aliPayOpen": false,
// ID
"appId": null,
//
"payCode": null,
//
"payMerchant": {
//
"id": null,
//
"name": null
},
}
};
},
created() {
this.getList();
this.handleGetMerchantListByName(null);
},
methods: {
/** 查询列表 */
getList() {
this.loading = true;
//
let params = {...this.queryParams};
this.addBeginAndEndTime(params, this.dateRangeCreateTime, 'createTime');
//
getAppPage(params).then(response => {
this.list = response.data.list;
console.log(this.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("删除成功");
}).catch(() => {
this.$message({
type: 'info',
message: '已取消删除'
});
});
},
/** 导出按钮操作 */
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 => {
this.merchantList = response.data;
});
},
/**
* 修改支付渠道信息
*/
handleUpdateChannel(row, payCode, type) {
this.settingChannelParam(row, payCode, type)
this.channelParam.edit = true;
this.channelParam.loading = true;
},
/**
* 新增支付渠道信息
*/
handleCreateChannel(row, payCode, type) {
this.settingChannelParam(row, payCode, type)
this.channelParam.edit = false;
this.channelParam.loading = false;
},
/**
* 设置支付渠道信息
*/
settingChannelParam(row, payCode, type) {
if (type === PayType.WECHAT) {
this.channelParam.wechatOpen = true;
this.channelParam.aliPayOpen = false;
}
if (type === PayType.ALIPAY) {
this.channelParam.aliPayOpen = true;
this.channelParam.wechatOpen = false;
}
this.channelParam.edit = false;
this.channelParam.loading = false;
this.channelParam.appId = row.id;
this.channelParam.payCode = payCode;
this.channelParam.payMerchant = row.payMerchant;
},
/**
* 根据渠道编码判断渠道列表中是否存在
* @param channels 渠道列表
* @param channelCode 渠道编码
*/
judgeChannelExist(channels, channelCode) {
return channels.indexOf(channelCode) !== -1;
},
refreshTable() {
this.getList();
}
}
};
</script>

View File

@ -0,0 +1,296 @@
<template>
<div class="app-container">
<!-- 搜索工作栏 -->
<el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
<el-form-item label="商户号" prop="no">
<el-input v-model="queryParams.no" placeholder="请输入商户号" clearable size="small" @keyup.enter.native="handleQuery"/>
</el-form-item>
<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="shortName">
<el-input v-model="queryParams.shortName" 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 label="备注" prop="remark">
<el-input v-model="queryParams.remark" placeholder="请输入备注" clearable size="small" @keyup.enter.native="handleQuery"/>
</el-form-item>
<el-form-item label="创建时间">
<el-date-picker v-model="dateRangeCreateTime" size="small" style="width: 240px" value-format="yyyy-MM-dd"
type="daterange" range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期" />
</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:merchant: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:merchant: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="no" />
<el-table-column label="商户全称" align="center" prop="name" />
<el-table-column label="商户简称" align="center" prop="shortName" />
<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="remark" />
<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" 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:merchant:update']">修改</el-button>
<el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)"
v-hasPermi="['pay:merchant: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="500px" append-to-body>
<el-form ref="form" :model="form" :rules="rules" label-width="80px">
<!-- <el-form-item label="商户号" prop="no">-->
<!-- <el-input v-model="form.no" placeholder="请输入商户号" />-->
<!-- </el-form-item>-->
<el-form-item label="商户全称" prop="name">
<el-input v-model="form.name" placeholder="请输入商户全称" />
</el-form-item>
<el-form-item label="商户简称" prop="shortName">
<el-input v-model="form.shortName" 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="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>
</div>
</template>
<script>
import {
createMerchant,
updateMerchant,
changeMerchantStatus,
deleteMerchant,
getMerchant,
getMerchantPage,
exportMerchantExcel
} from "@/api/pay/merchant";
import {DICT_TYPE, getDictDatas} from "@/utils/dict";
import {SysCommonStatusEnum} from "@/utils/constants";
export default {
name: "Merchant",
components: {
},
data() {
return {
//
loading: true,
//
showSearch: true,
//
total: 0,
//
list: [],
//
title: "",
//
open: false,
dateRangeCreateTime: [],
//
queryParams: {
pageNo: 1,
pageSize: 10,
no: null,
name: null,
shortName: null,
status: null,
remark: null,
},
//
form: {},
//
rules: {
no: [{ required: true, message: "商户号不能为空", trigger: "blur" }],
name: [{ required: true, message: "商户全称不能为空", trigger: "blur" }],
shortName: [{ required: true, message: "商户简称不能为空", trigger: "blur" }],
status: [{ required: true, message: "开启状态不能为空", trigger: "blur" }],
},
//
statusDictDatas: getDictDatas(DICT_TYPE.SYS_COMMON_STATUS)
};
},
created() {
this.getList();
},
methods: {
/** 查询列表 */
getList() {
this.loading = true;
//
let params = {...this.queryParams};
this.addBeginAndEndTime(params, this.dateRangeCreateTime, 'createTime');
//
getMerchantPage(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,
no: undefined,
name: undefined,
shortName: undefined,
status: undefined,
remark: 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;
getMerchant(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 changeMerchantStatus(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) {
updateMerchant(this.form).then(response => {
this.msgSuccess("修改成功");
this.open = false;
this.getList();
});
return;
}
//
createMerchant(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 deleteMerchant(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 exportMerchantExcel(params);
}).then(response => {
this.downloadExcel(response, '支付商户信息.xls');
})
}
}
};
</script>

Some files were not shown because too many files have changed in this diff Show More